docs: add zotero collection import design
This commit is contained in:
commit
0c0c773e61
@ -0,0 +1,336 @@
|
||||
# Zotero Collection Import Design
|
||||
|
||||
## Overview
|
||||
|
||||
This design upgrades the current left-panel import area from two temporary flows:
|
||||
|
||||
- import current selection from a bridge snapshot
|
||||
- text-search fallback import
|
||||
|
||||
into one unified Zotero collection importer.
|
||||
|
||||
The new importer must visualize the user's current Zotero collection hierarchy, let the user browse collections, display the literature under the selected collection, remember cross-collection checkbox state, and batch-import selected items into the current project.
|
||||
|
||||
This work is intentionally scoped to the import surface only. The project card panel and writing panel remain in place.
|
||||
|
||||
## Goals
|
||||
|
||||
- Replace the current left-panel import widgets with one unified `Import From Zotero` section
|
||||
- Visualize Zotero collections as a tree in the left panel
|
||||
- When a collection is selected, show the literature under that collection and all descendant collections
|
||||
- Support checkbox-based multi-selection across collection switches
|
||||
- Remember previous selection state while the page remains open
|
||||
- Support bulk actions:
|
||||
- select all items from the current collection plus descendants
|
||||
- clear all selected items
|
||||
- import selected items into the current project
|
||||
- Preserve the existing project panel, card panel, and writing panel structure
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Full drag-and-drop tree editing
|
||||
- Editing Zotero collections
|
||||
- Multi-pane import wizard
|
||||
- Persisting import selections across browser restarts or across different users
|
||||
- Replacing the bridge-based current-selection import flow at the API level
|
||||
|
||||
The bridge-based import endpoint may remain available, but it is no longer the main UI path.
|
||||
|
||||
## Product Scope
|
||||
|
||||
The importer is a left-panel replacement only.
|
||||
|
||||
### Unchanged Areas
|
||||
|
||||
- project creation
|
||||
- project list
|
||||
- project card list
|
||||
- card detail viewer
|
||||
- writing recommendation form
|
||||
- writing plan form
|
||||
|
||||
### Replaced Area
|
||||
|
||||
The current pair of sections:
|
||||
|
||||
- `导入当前选中`
|
||||
- `后备导入`
|
||||
|
||||
will be removed and replaced with:
|
||||
|
||||
- `从 Zotero 导入`
|
||||
|
||||
## User Flow
|
||||
|
||||
1. The user selects a project
|
||||
2. The user browses the Zotero collection tree
|
||||
3. The user clicks one collection
|
||||
4. The UI loads all literature from that collection and all descendants
|
||||
5. The user checks items to import
|
||||
6. The user may switch to a different collection and continue selecting
|
||||
7. Previously selected items remain selected
|
||||
8. The user clicks `导入所选到当前项目`
|
||||
9. The backend imports all selected items into the current project
|
||||
10. The card panel refreshes with the newly imported cards
|
||||
|
||||
## Layout
|
||||
|
||||
The page stays three-column.
|
||||
|
||||
### Left Panel
|
||||
|
||||
The left panel contains:
|
||||
|
||||
1. `创建项目`
|
||||
2. `项目列表`
|
||||
3. `从 Zotero 导入`
|
||||
|
||||
### Import Section Structure
|
||||
|
||||
The import section has three internal regions:
|
||||
|
||||
1. collection tree
|
||||
2. collection item list
|
||||
3. sticky action bar
|
||||
|
||||
#### Collection Tree
|
||||
|
||||
- tree view with expand/collapse state
|
||||
- current collection highlighted
|
||||
- each node shows:
|
||||
- collection name
|
||||
- descendant-aware item count
|
||||
|
||||
#### Collection Item List
|
||||
|
||||
- shows items from the current collection and all descendant collections
|
||||
- each row contains:
|
||||
- checkbox
|
||||
- title
|
||||
- year
|
||||
- item type
|
||||
- compact metadata
|
||||
- rows already selected in other collections remain checked when shown again
|
||||
|
||||
#### Sticky Action Bar
|
||||
|
||||
- selected count
|
||||
- `全选当前目录及子目录`
|
||||
- `清空选择`
|
||||
- `导入所选到当前项目`
|
||||
|
||||
The action bar remains visible while scrolling within the import section.
|
||||
|
||||
## Interaction Semantics
|
||||
|
||||
### Collection Selection
|
||||
|
||||
Clicking a collection:
|
||||
|
||||
- sets it as the active collection
|
||||
- loads all items under that collection plus descendants
|
||||
- does not clear already selected items
|
||||
|
||||
### Checkbox State
|
||||
|
||||
Selection is tracked by `item_key`, not by visible row index.
|
||||
|
||||
This means:
|
||||
|
||||
- switching collections does not lose selection
|
||||
- re-entering a collection restores prior checkbox state
|
||||
- the selected count reflects the union of all selected items across the session
|
||||
|
||||
### Select-All Behavior
|
||||
|
||||
`全选当前目录及子目录` means:
|
||||
|
||||
- take the currently displayed item set
|
||||
- merge all of those item keys into the global selected set
|
||||
- keep existing selections from other collections intact
|
||||
|
||||
### Clear Behavior
|
||||
|
||||
`清空选择` means:
|
||||
|
||||
- clear the full selected item set
|
||||
- uncheck all visible rows
|
||||
- reset the selected count to zero
|
||||
|
||||
### Import Behavior
|
||||
|
||||
`导入所选到当前项目` means:
|
||||
|
||||
- require a currently selected project
|
||||
- submit the full selected item key set to the backend
|
||||
- keep the active collection and tree expansion state
|
||||
- clear the selected item set on success
|
||||
- refresh the project card list
|
||||
|
||||
## Frontend State Model
|
||||
|
||||
The page should maintain these state keys:
|
||||
|
||||
- `selectedCollectionKey`
|
||||
- `expandedCollectionKeys`
|
||||
- `selectedItemKeys`
|
||||
- `visibleCollectionItems`
|
||||
|
||||
### State Rules
|
||||
|
||||
- `selectedCollectionKey` changes when the user clicks a tree node
|
||||
- `expandedCollectionKeys` changes when nodes are opened or closed
|
||||
- `selectedItemKeys` persists across collection switches during the current browser session
|
||||
- `visibleCollectionItems` updates whenever the active collection changes
|
||||
|
||||
`selectedItemKeys` is the source of truth for checkbox rendering and batch import.
|
||||
|
||||
## Backend API Additions
|
||||
|
||||
Three API capabilities are required.
|
||||
|
||||
### 1. Collection Tree
|
||||
|
||||
`GET /api/zotero/collections/tree`
|
||||
|
||||
Returns the current Zotero collection hierarchy.
|
||||
|
||||
Each node must include:
|
||||
|
||||
- `collection_key`
|
||||
- `name`
|
||||
- `parent_key`
|
||||
- `children`
|
||||
- `direct_item_count`
|
||||
- `descendant_item_count`
|
||||
|
||||
### 2. Collection Items
|
||||
|
||||
`GET /api/zotero/collections/{collection_key}/items?include_descendants=true`
|
||||
|
||||
Returns all regular Zotero items under the selected collection. In V1 of this feature, the UI will always request `include_descendants=true`.
|
||||
|
||||
Each returned item must include:
|
||||
|
||||
- `item_key`
|
||||
- `title`
|
||||
- `year`
|
||||
- `item_type`
|
||||
- `abstract`
|
||||
- `collection_paths`
|
||||
|
||||
### 3. Batch Import
|
||||
|
||||
`POST /api/projects/{project_id}/imports/item-keys`
|
||||
|
||||
This endpoint already exists and should remain the import execution path for the new UI.
|
||||
|
||||
Input:
|
||||
|
||||
```json
|
||||
{
|
||||
"item_keys": ["ABCD1234", "EFGH5678"]
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
- `project_id`
|
||||
- `imported_item_keys`
|
||||
- `project_view`
|
||||
|
||||
## Reader Responsibilities
|
||||
|
||||
The Zotero reader must support collection-tree import without depending on bridge snapshots.
|
||||
|
||||
Required reader capabilities:
|
||||
|
||||
- build normalized collection tree data
|
||||
- compute direct item counts per collection
|
||||
- compute descendant-aware item counts per collection
|
||||
- list all regular items under a collection with optional descendant inclusion
|
||||
|
||||
The reader should continue to ignore attachment, note, and annotation rows as import roots.
|
||||
|
||||
## Error Handling
|
||||
|
||||
### No Project Selected
|
||||
|
||||
- disable import submission or return a clear UI error
|
||||
- do not clear selected checkboxes
|
||||
|
||||
### Collection Tree Load Failure
|
||||
|
||||
- show error state in the import section
|
||||
- do not affect cards or writing sections
|
||||
|
||||
### Empty Collection
|
||||
|
||||
- show an empty-state list
|
||||
- keep tree navigation usable
|
||||
|
||||
### Partial Import Failure
|
||||
|
||||
- report imported item keys and failed item keys separately if the backend can distinguish them
|
||||
- do not silently report full success if part of the request failed
|
||||
|
||||
### Missing Local Zotero Data
|
||||
|
||||
- show import section unavailable
|
||||
- preserve the rest of the application
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Reader Tests
|
||||
|
||||
- build collection tree from fixture Zotero data
|
||||
- compute descendant-aware item counts
|
||||
- list collection items with descendant inclusion
|
||||
|
||||
### API Tests
|
||||
|
||||
- `GET /api/zotero/collections/tree`
|
||||
- `GET /api/zotero/collections/{collection_key}/items?include_descendants=true`
|
||||
- `POST /api/projects/{project_id}/imports/item-keys`
|
||||
|
||||
### UI Tests
|
||||
|
||||
The index template must include:
|
||||
|
||||
- collection tree container
|
||||
- collection item list container
|
||||
- selected count area
|
||||
- select-all button
|
||||
- clear-selection button
|
||||
- import-selected button
|
||||
|
||||
## Constraints And Tradeoffs
|
||||
|
||||
### Why Tree + Side List Instead Of Tree-Mixed Items
|
||||
|
||||
The user explicitly chose:
|
||||
|
||||
- collection tree on one side
|
||||
- item list shown after selecting a collection
|
||||
|
||||
This keeps scanning manageable for large libraries and avoids turning the tree itself into an overloaded mixed node structure.
|
||||
|
||||
### Why Session-Scoped Selection Memory
|
||||
|
||||
The user explicitly asked to remember previous selection state, but not to store durable drafts of import batches. Session-scoped state is enough for the workflow and avoids backend persistence complexity.
|
||||
|
||||
### Why Keep Cards And Writing Panels Unchanged
|
||||
|
||||
The import feature is a left-panel responsibility. Expanding it into a page-level mode would create unnecessary layout churn and broaden the implementation risk.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
This feature is complete when:
|
||||
|
||||
- the old `导入当前选中` and `后备导入` UI sections are gone
|
||||
- the left panel shows a collection tree and descendant-aware collection item list
|
||||
- selecting items survives collection switches during the session
|
||||
- the user can select all items from a collection plus descendants
|
||||
- the user can clear all current selections
|
||||
- the user can batch-import the selected items into the active project
|
||||
- the project card area refreshes after a successful import
|
||||
Loading…
Reference in New Issue
Block a user