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.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
# project-import Spec
|
||||
|
||||
## Purpose
|
||||
|
||||
Enable users to import a Planka project hierarchy from a JSON export file, creating all resources (boards, lists, cards, labels, tasks, comments) on the target Planka instance with fresh IDs while preserving structure and ordering.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Import project hierarchy from JSON
|
||||
The system SHALL read a JSON export file and create all resources (project, boards, lists, labels, cards, card-labels, task lists, tasks, comments) on the target Planka instance with fresh IDs.
|
||||
|
||||
#### Scenario: Import from stdin
|
||||
- **WHEN** user runs `pcli project import < backup.json`
|
||||
- **THEN** the system reads the JSON from stdin and creates all resources
|
||||
|
||||
#### Scenario: Import from file flag
|
||||
- **WHEN** user runs `pcli project import --file backup.json`
|
||||
- **THEN** the system reads the JSON from the specified file and creates all resources
|
||||
|
||||
#### Scenario: No input provided
|
||||
- **WHEN** user runs `pcli project import` with no stdin and no --file flag
|
||||
- **THEN** the system exits with an error indicating input is required
|
||||
|
||||
### Requirement: Import creates project if not exists
|
||||
The system SHALL look up the project by name. If no project with that name exists, the system SHALL create it. If the project already exists, the system SHALL use the existing project.
|
||||
|
||||
#### Scenario: Project does not exist
|
||||
- **WHEN** importing a project named "proj1" and no project with that name exists
|
||||
- **THEN** the system creates a new project named "proj1"
|
||||
|
||||
#### Scenario: Project already exists
|
||||
- **WHEN** importing a project named "proj1" and a project with that name already exists
|
||||
- **THEN** the system uses the existing project (does not create a duplicate)
|
||||
|
||||
### Requirement: Import fails if board name conflicts
|
||||
Before creating any resources, the system SHALL check that none of the boards in the export file have names that conflict with existing boards in the target project. If any board name already exists under the target project, the system SHALL exit with an error naming the conflicting board(s) and create nothing.
|
||||
|
||||
#### Scenario: No board conflict
|
||||
- **WHEN** importing boards "board1" and "board2" into project "proj1" which has no boards
|
||||
- **THEN** the import proceeds and creates both boards
|
||||
|
||||
#### Scenario: Board name conflict
|
||||
- **WHEN** importing board "board1" into project "proj1" which already has a board named "board1"
|
||||
- **THEN** the system exits with an error: board "board1" already exists in project "proj1"
|
||||
- **THEN** no resources are created
|
||||
|
||||
#### Scenario: Partial conflict
|
||||
- **WHEN** importing boards "board1" and "board2" into project "proj1" which already has "board2"
|
||||
- **THEN** the system exits with an error about "board2" conflicting
|
||||
- **THEN** no resources are created (not even "board1")
|
||||
|
||||
### Requirement: Import creates resources in dependency order
|
||||
The system SHALL create resources top-down: board → lists → labels → cards → card-label associations → task lists → tasks → comments. Name-to-ID maps SHALL be maintained at each level to resolve references for child resources.
|
||||
|
||||
#### Scenario: Card references resolved on import
|
||||
- **WHEN** a card in the export has `"listName": "In Progress"` and `"labelNames": ["Bug"]`
|
||||
- **THEN** the system creates the card in the list named "In Progress" and associates it with the label named "Bug" using the IDs generated during import
|
||||
|
||||
### Requirement: Import preserves ordering
|
||||
The system SHALL use position values from the export to maintain the original display ordering of boards, lists, labels, and cards.
|
||||
|
||||
#### Scenario: List positions preserved
|
||||
- **WHEN** the export contains lists with positions 1, 2, 3
|
||||
- **THEN** the imported lists are created with those same position values
|
||||
|
||||
### Requirement: Import validates export version
|
||||
The system SHALL check the `version` field of the export JSON. If the version is not supported (currently only version `1`), the system SHALL exit with an error.
|
||||
|
||||
#### Scenario: Supported version
|
||||
- **WHEN** the export file has `"version": 1`
|
||||
- **THEN** the import proceeds normally
|
||||
|
||||
#### Scenario: Unsupported version
|
||||
- **WHEN** the export file has `"version": 99`
|
||||
- **THEN** the system exits with an error indicating the version is not supported
|
||||
|
||||
### Requirement: Import reports progress
|
||||
The system SHALL output progress information to stderr as it creates resources, including the count of each resource type created.
|
||||
|
||||
#### Scenario: Progress reporting
|
||||
- **WHEN** an import completes successfully
|
||||
- **THEN** stderr shows a summary: boards created, lists created, cards created, etc.
|
||||
|
||||
### Requirement: Import handles missing list reference
|
||||
If a card references a `listName` that does not exist in the board's lists, the system SHALL exit with an error identifying the card and the missing list name.
|
||||
|
||||
#### Scenario: Invalid list reference
|
||||
- **WHEN** a card references `"listName": "Nonexistent"` and no list with that name exists in the board
|
||||
- **THEN** the system exits with an error: card "<name>" references unknown list "Nonexistent"
|
||||
Reference in New Issue
Block a user