13 KiB
Zotero Collection Import Design
Overview
This design revises the current import flow into a true full-screen modal experience:
- the main page keeps project, cards, and writing views visible until import starts
- clicking
导入文献opens a full-screen modal layer that visually occupies the whole viewport
The import modal visualizes the current Zotero collection hierarchy, lets the user browse collections, displays only the directly contained literature for the selected collection, remembers cross-collection checkbox state for the current browser session, and batch-imports the 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 import widgets with one
导入文献button that opens a full-screen modal - Visualize Zotero collections as a tree on the left side of the full-screen modal
- When a collection is selected, show only the items directly contained by that collection
- Support checkbox-based multi-selection across collection switches
- Remember previous selection state while the page remains open, even if the modal is closed and reopened
- Support top-bar actions:
- clear all selected items
- import selected items into the current project
- Keep the item list compact by default:
- show checkbox, title, and year only
- show abstract only after hover delay or explicit details trigger
- Preserve the existing project panel, card panel, and writing panel structure outside the modal
Non-Goals
- Full drag-and-drop tree editing
- Editing Zotero collections
- Multi-step import wizard
- Persisting import selections across browser restarts or across different users
- Replacing the bridge-based current-selection import flow at the API level
- Showing abstract text inline for every row by default
- Collection-level bulk selection such as “select all current collection and descendants”
The bridge-based import endpoint may remain available, but it is no longer the main UI path.
Product Scope
The importer is a modal-based subflow launched from the main page.
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:
- one
导入文献button on the main page - one full-screen
Import From Zoteromodal
User Flow
- The user selects a project or leaves the page without selecting one yet
- The user clicks
导入文献 - A full-screen modal opens
- The user browses the Zotero collection tree on the left
- The user clicks one collection
- The UI loads only the items directly contained by that collection
- The user checks individual items to import
- The user may switch to a different collection and continue selecting
- Previously selected items remain selected
- The user clicks
导入所选到当前项目 - The backend imports all selected items into the current project
- The card panel refreshes with the newly imported cards
- The modal closes on success
Layout
The page stays three-column until the import modal opens.
Main Page
The left panel contains:
创建项目项目列表导入文献
The collection tree and collection item list are not rendered inline on the main page.
Full-Screen Modal
The modal fills the viewport and has three internal regions:
- top toolbar
- modal body
- full-screen overlay/background layer
Top Toolbar
返回主页面- current project name or explicit
未选择项目 - selected count
清空选择导入所选
This toolbar remains visible while the collection tree and item list scroll.
Modal Body
- desktop: fixed two-column layout
- left: collection tree
- right: collection item list
- narrow screens: may stack or collapse the tree, but the desktop target is explicitly left-tree / right-list
Collection Tree
- tree view with expand/collapse state
- current collection highlighted
- each node shows:
- collection name
- item count for that collection
Collection Item List
- shows only items directly contained in the selected collection
- each row contains:
- checkbox
- title
- year
- abstract is not shown inline
- rows already selected in other collections remain checked when shown again
Interaction Semantics
Modal Open And Close
Clicking 导入文献 opens the full-screen modal.
The modal can be closed by:
- clicking the explicit return button
- clicking the overlay if that behavior is preserved
- pressing
Esc
Closing the modal does not clear:
selectedCollectionKeyexpandedCollectionKeysselectedItemKeys
Reopening the modal restores the previous browsing and selection state for the current page session.
Collection Selection
Clicking a collection:
- sets it as the active collection
- loads only items directly contained by that collection
- 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
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
- remain disabled when no project is selected
- 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
- close the modal on success
- refresh the project card list
Abstract Preview Behavior
The item list stays compact by default.
Desktop
- hovering the title area of an item row starts a 3 second timer
- if the pointer is still on the row after 3 seconds, an abstract preview popover appears
- if the abstract is empty, no popover appears
- moving the pointer away before 3 seconds cancels the timer
- moving the pointer away after the popover appears closes it
- only one preview popover may be open at a time
Mobile And Narrow-Screen Fallback
Hover is not reliable on touch devices, so the UI must degrade to an explicit preview trigger such as a small details button per row.
This fallback:
- opens the same abstract preview content
- does not rely on hover timing
- does not change batch-selection behavior
Preview Cancellation Rules
The preview timer or popover closes immediately when:
- the user leaves the row
- the user scrolls the item list
- the user changes collection
- the user clicks a checkbox
Frontend State Model
The page should maintain these state keys:
isImportModalOpenselectedCollectionKeyexpandedCollectionKeysselectedItemKeysvisibleCollectionItemsselectedItemMetahoveredItemKeyhoverTimerIdpreviewItemKey
State Rules
isImportModalOpenchanges when the user opens or closes the modalselectedCollectionKeychanges when the user clicks a tree nodeexpandedCollectionKeyschanges when nodes are opened or closedselectedItemKeyspersists across collection switches and modal reopen during the current browser sessionvisibleCollectionItemsupdates whenever the active collection changesselectedItemMetastores minimal metadata for already selected itemshoveredItemKey,hoverTimerId, andpreviewItemKeycontrol delayed abstract preview
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_keynameparent_keychildrendirect_item_countdescendant_item_count
2. Collection Items
GET /api/zotero/collections/{collection_key}/items?include_descendants=false
Returns only regular Zotero items directly contained by the selected collection.
Each returned item must include:
item_keytitleyearitem_typeabstractcollection_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:
{
"item_keys": ["ABCD1234", "EFGH5678"]
}
Output:
project_idimported_item_keysproject_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
- 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
- allow the modal to open and load Zotero data
- disable import submission with a clear UI message
- do not clear selected checkboxes
Collection Tree Load Failure
- show error state inside the modal
- 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
- disable or error the modal content clearly
- preserve the rest of the application
Testing Strategy
Reader Tests
- build collection tree from fixture Zotero data
- compute direct item counts
- list collection items without descendant inclusion
API Tests
GET /api/zotero/collections/treeGET /api/zotero/collections/{collection_key}/items?include_descendants=falsePOST /api/projects/{project_id}/imports/item-keys
UI Tests
The main page must include:
- import-modal trigger button
The modal must include:
- collection tree container
- collection item list container
- selected count area
- clear-selection button
- import-selected button
UI behavior must cover:
- full-screen modal opens from the trigger button
- import action is disabled when no project is selected
- closing and reopening the modal preserves selected items during the session
- import success closes the modal and refreshes cards
- abstract preview appears only after the hover delay on desktop
- item rows display title and year by default, not abstract text
Constraints And Tradeoffs
Why Full-Screen Modal Instead Of A Centered Dialog
The user explicitly wants the import experience to feel like a whole-page task, not a cramped dialog anchored inside the left side of the UI. A full-screen modal preserves modal semantics while matching that expectation visually.
Why Collection Tree + Direct Item List
The user explicitly chose:
- collection tree on the left
- item list on the right
- only direct items for the selected collection
This keeps the browsing model simple: collection chooses the scope, list chooses the individual papers.
Why No Collection-Level Bulk Select
The user explicitly wants to choose papers one by one, not by collection-level bulk action. The collection tree filters the list; it does not act as a selection shortcut.
Why Title + Year By Default
The user explicitly wanted a lighter list than the current dense layout. Showing title and year by default preserves scanning context while leaving abstracts to delayed preview.
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 subflow. Expanding it into a permanent page layout 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 main page shows a
导入文献button instead of an inline importer - clicking the button opens a full-screen modal with collection tree and direct-item list
- selecting items survives collection switches and modal reopen during the session
- the user can clear all current selections
- the user can batch-import the selected items into the active project
- the import button is disabled when no project is selected
- the project card area refreshes after a successful import
- abstract preview appears only through the delayed preview interaction, not inline by default
- the item list shows title and year by default, not descendant-wide result sets or collection-level bulk select actions