Files
steve e973b2ce20 feat: add project export and import functionality
- Implemented `pcli project export` command to export project hierarchy as JSON.
- Added `pcli project import` command to import project data from JSON.
- Created user client to fetch user details for comment attribution.
- Introduced new data structures for export and import processes.
- Ensured name-based references in exports and handled conflicts during imports.
- Added versioning and progress reporting for import operations.
- Updated documentation and specifications for new features.
2026-03-04 19:53:55 +00:00

260 lines
7.8 KiB
Go

package model
import (
"encoding/json"
"fmt"
)
type Project struct {
ID string `json:"id"`
OwnerProjectManagerID *string `json:"ownerProjectManagerId"`
BackgroundImageID *string `json:"backgroundImageId"`
Name string `json:"name"`
Description *string `json:"description"`
BackgroundType *string `json:"backgroundType"`
BackgroundGradient *string `json:"backgroundGradient"`
IsHidden bool `json:"isHidden"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
}
type Board struct {
ID string `json:"id"`
ProjectID string `json:"projectId"`
Position float64 `json:"position"`
Name string `json:"name"`
DefaultView string `json:"defaultView"`
DefaultCardType string `json:"defaultCardType"`
LimitCardTypesToDefaultOne bool `json:"limitCardTypesToDefaultOne"`
AlwaysDisplayCardCreator bool `json:"alwaysDisplayCardCreator"`
ExpandTaskListsByDefault bool `json:"expandTaskListsByDefault"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
Lists []List `json:"lists,omitempty"`
Cards []Card `json:"cards,omitempty"`
Labels []Label `json:"labels,omitempty"`
CardLabels []CardLabel `json:"cardLabels,omitempty"`
CardMemberships []CardMembership `json:"cardMemberships,omitempty"`
}
type List struct {
ID string `json:"id"`
BoardID string `json:"boardId"`
Type string `json:"type"`
Position *float64 `json:"position"`
Name *string `json:"name"`
Color *string `json:"color"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
}
type Stopwatch struct {
StartedAt string `json:"startedAt"`
Total float64 `json:"total"`
}
type Card struct {
ID string `json:"id"`
BoardID string `json:"boardId"`
ListID string `json:"listId"`
CreatorUserID *string `json:"creatorUserId"`
PrevListID *string `json:"prevListId"`
CoverAttachmentID *string `json:"coverAttachmentId"`
Type string `json:"type"`
Position *float64 `json:"position"`
Name string `json:"name"`
Description *string `json:"description"`
DueDate *string `json:"dueDate"`
IsDueCompleted *bool `json:"isDueCompleted"`
Stopwatch *Stopwatch `json:"stopwatch"`
CommentsTotal int `json:"commentsTotal"`
IsClosed bool `json:"isClosed"`
ListChangedAt *string `json:"listChangedAt"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
}
type CardDetail struct {
Card
TaskLists []TaskList `json:"taskLists,omitempty"`
Tasks []Task `json:"tasks,omitempty"`
}
type CardWithList struct {
Card
ListName string `json:"listName"`
Labels []string `json:"labels"`
}
type Comment struct {
ID string `json:"id"`
CardID string `json:"cardId"`
UserID *string `json:"userId"`
Text string `json:"text"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
}
type TaskList struct {
ID string `json:"id"`
CardID string `json:"cardId"`
Position float64 `json:"position"`
Name string `json:"name"`
ShowOnFrontOfCard bool `json:"showOnFrontOfCard"`
HideCompletedTasks bool `json:"hideCompletedTasks"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
}
type Task struct {
ID string `json:"id"`
TaskListID string `json:"taskListId"`
LinkedCardID *string `json:"linkedCardId"`
AssigneeUserID *string `json:"assigneeUserId"`
Position float64 `json:"position"`
Name string `json:"name"`
IsCompleted bool `json:"isCompleted"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
}
type Label struct {
ID string `json:"id"`
BoardID string `json:"boardId"`
Position float64 `json:"position"`
Name *string `json:"name"`
Color string `json:"color"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
}
type Action struct {
ID string `json:"id"`
BoardID *string `json:"boardId"`
CardID string `json:"cardId"`
UserID *string `json:"userId"`
Type string `json:"type"`
Data json.RawMessage `json:"data"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
}
type CardLabel struct {
ID string `json:"id"`
CardID string `json:"cardId"`
LabelID string `json:"labelId"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
}
type CardMembership struct {
ID string `json:"id"`
CardID string `json:"cardId"`
UserID string `json:"userId"`
CreatedAt *string `json:"createdAt"`
UpdatedAt *string `json:"updatedAt"`
}
type Envelope struct {
Data any `json:"data"`
Error *string `json:"error"`
}
type StatusSummary struct {
TotalBoards int `json:"totalBoards"`
Boards []BoardSummary `json:"boards"`
}
type BoardSummary struct {
ID string `json:"id"`
Name string `json:"name"`
Lists []ListSummary `json:"lists"`
}
type ListSummary struct {
ID string `json:"id"`
Name string `json:"name"`
OpenCards int `json:"openCards"`
ClosedCards int `json:"closedCards"`
}
type User struct {
ID string `json:"id"`
Name string `json:"name"`
Username *string `json:"username"`
Email string `json:"email"`
}
// Export types - portable structs without Planka IDs
type ExportEnvelope struct {
Version int `json:"version"`
ExportedAt string `json:"exportedAt"`
Project ExportProject `json:"project"`
}
type ExportProject struct {
Name string `json:"name"`
Description *string `json:"description,omitempty"`
Boards []ExportBoard `json:"boards"`
}
type ExportBoard struct {
Name string `json:"name"`
Position float64 `json:"position"`
Lists []ExportList `json:"lists"`
Labels []ExportLabel `json:"labels"`
Cards []ExportCard `json:"cards"`
}
type ExportList struct {
Name string `json:"name"`
Position float64 `json:"position"`
Type string `json:"type"`
Color *string `json:"color,omitempty"`
}
type ExportLabel struct {
Name *string `json:"name,omitempty"`
Position float64 `json:"position"`
Color string `json:"color"`
}
type ExportCard struct {
Name string `json:"name"`
Position *float64 `json:"position,omitempty"`
ListName string `json:"listName"`
LabelNames []string `json:"labelNames,omitempty"`
Description *string `json:"description,omitempty"`
DueDate *string `json:"dueDate,omitempty"`
IsClosed bool `json:"isClosed,omitempty"`
Type string `json:"type"`
TaskLists []ExportTaskList `json:"taskLists,omitempty"`
Comments []ExportComment `json:"comments,omitempty"`
}
type ExportTaskList struct {
Name string `json:"name"`
Position float64 `json:"position"`
Tasks []ExportTask `json:"tasks"`
}
type ExportTask struct {
Name string `json:"name"`
Position float64 `json:"position"`
IsCompleted bool `json:"isCompleted"`
}
type ExportComment struct {
Text string `json:"text"`
}
type APIError struct {
StatusCode int
Message string
}
func (e *APIError) Error() string {
return fmt.Sprintf("API error (status %d): %s", e.StatusCode, e.Message)
}