zotero-kb/docs/superpowers/specs/2026-04-15-zotero-collection-import-design.md

12 KiB

Zotero Collection Import Design

Overview

This design replaces the current crowded import area with a lighter flow:

  • the main page keeps project, cards, and writing views visible
  • the import UI moves into a modal opened from a single 导入文献 button

The modal visualizes the user's current Zotero collection hierarchy, lets the user browse collections, displays the literature under the selected collection and all descendants, remembers cross-collection checkbox state for the current browser session, and batch-imports 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 an import modal
  • Visualize Zotero collections as a tree inside the modal
  • 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, even if the modal is closed and reopened
  • Support bulk actions:
    • select all items from the current collection plus descendants
    • clear all selected items
    • import selected items into the current project
  • Keep the item list compact by default:
    • show checkbox and title only
    • show abstract only after hover delay
  • Preserve the existing project panel, card panel, and writing panel structure

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

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 Import From Zotero modal

User Flow

  1. The user selects a project or leaves the page without selecting one yet
  2. The user clicks 导入文献
  3. The modal opens
  4. The user browses the Zotero collection tree
  5. The user clicks one collection
  6. The UI loads all literature from that collection and all descendants
  7. The user checks items to import
  8. The user may switch to a different collection and continue selecting
  9. Previously selected items remain selected
  10. The user clicks 导入所选到当前项目
  11. The backend imports all selected items into the current project
  12. The card panel refreshes with the newly imported cards
  13. The modal closes on success

Layout

The page stays three-column.

Main Page

The left panel contains:

  1. 创建项目
  2. 项目列表
  3. 导入文献

The collection tree and collection item list are no longer rendered inline on the main page.

Import Modal

The modal has three internal regions:

  1. modal header
  2. modal body
  3. sticky action bar

Modal Header

  • title
  • current project name or an explicit "未选择项目" state
  • selected count
  • close button

Modal Body

  • desktop: two-column layout
    • left: collection tree
    • right: collection item list
  • narrow screens: automatically stack into top and bottom sections

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, and abstract are not shown inline by default
  • 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 modal.

Interaction Semantics

Modal Open And Close

Clicking 导入文献 opens the modal.

The modal can be closed by:

  • clicking the close button
  • clicking the overlay
  • pressing Esc

Closing the modal does not clear:

  • selectedCollectionKey
  • expandedCollectionKeys
  • selectedItemKeys

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 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
  • 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 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:

  • isImportModalOpen
  • selectedCollectionKey
  • expandedCollectionKeys
  • selectedItemKeys
  • visibleCollectionItems
  • hoveredItemKey
  • hoverTimerId
  • previewItemKey

State Rules

  • isImportModalOpen changes when the user opens or closes the modal
  • selectedCollectionKey changes when the user clicks a tree node
  • expandedCollectionKeys changes when nodes are opened or closed
  • selectedItemKeys persists across collection switches and modal reopen during the current browser session
  • visibleCollectionItems updates whenever the active collection changes
  • hoveredItemKey, hoverTimerId, and previewItemKey control 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_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:

{
  "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

  • 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 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 main page must include:

  • import-modal trigger button

The modal must include:

  • collection tree container
  • collection item list container
  • selected count area
  • select-all button
  • clear-selection button
  • import-selected button

UI behavior must cover:

  • modal can open without a selected project
  • 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

Constraints And Tradeoffs

Why Modal Instead Of Left-Panel Inline Import

The inline importer works functionally but makes the main page too crowded. A modal keeps import as a focused subtask and preserves the readability of the project, cards, and writing columns.

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 Title-Only Rows By Default

The user explicitly wanted a lighter list. Showing only the title in the default list keeps density under control, while delayed preview preserves access to abstracts when needed.

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 modal with collection tree and descendant-aware item list
  • selecting items survives collection switches and modal reopen 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 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