Skip to content

feat(web): folders + drag-drop + active-folder context + batch ops + …#113

Merged
chauncygu merged 1 commit into
mainfrom
fix/web-ui
May 10, 2026
Merged

feat(web): folders + drag-drop + active-folder context + batch ops + …#113
chauncygu merged 1 commit into
mainfrom
fix/web-ui

Conversation

@chauncygu
Copy link
Copy Markdown
Contributor

…resizable sidebar

ChatGPT-style session organization in the Chat UI, layered on top of the slash-fix work in the previous commit. Five independent UX features behind a single coordinated change so the schema migration only runs once.

Folders

  • New folders table (per-user, name unique). chat_sessions gains a nullable folder_id FK.
  • In-place migration in init_db(): PRAGMA table_info probes for the column on existing DBs and ALTER TABLE adds it. No Alembic, no manual upgrade steps.
  • Endpoints: GET/POST /api/folders, PATCH/DELETE /api/folders/{id}, PATCH /api/sessions/{id}/folder. Cross-user folders return 404 the same way single-session ownership checks do.
  • Deleting a folder reparents its sessions to Ungrouped (folder_id = NULL) rather than deleting them. Repo layer NULLs explicitly because SQLite PRAGMA foreign_keys is off in this engine.

Drag-drop + Move-to context menu

  • Sessions are HTML5-draggable; folder rows + Ungrouped header are drop targets with visual highlight.
  • Right-click on a session: flat Move-to list with every folder, plus (Ungrouped) when applicable, plus "+ New folder…" for create-and-move in one click.
  • Right-click on a folder: Rename / Delete, with a confirm() that says "sessions become Ungrouped — they are NOT deleted".

Active-folder context (ChatGPT-style)

  • Click a folder name (not the disclosure arrow) to enter that folder. Row gets accent highlight; topbar grows a "Chat · in " breadcrumb.
  • While a folder is active, + New and direct-typing auto-create both drop the new session into that folder. Switching to any session syncs the active context to that session's folder.
  • State persists across reloads via localStorage (cc-active-folder). Deleted folders auto-clear.

Batch operations

  • "Select" button enters multi-select mode (checkboxes, Select all respects the search filter). Footer action bar batch-deletes (single confirm + total-message count) or batch-exports as one combined Markdown (chats-N-sessions.md).
  • Endpoints: POST /api/sessions/batch_delete and batch_export.
  • Right-click is suppressed in select mode to avoid mode confusion.

Resizable sidebar

  • 4-px drag handle between sidebar and main pane (mouse + touch). Width clamped to 200–600 px and persisted to localStorage (cc-sidebar-w). Double-click resets to default. Hidden under @media (max-width: 768px) so the mobile drawer keeps its swipe behavior.

Tests

  • +10 in tests/test_web_api.py: folder CRUD, duplicate-409, move, delete-preserves-as-ungrouped, cross-user isolation, list-includes- folder_id, batch delete, batch delete cross-user, batch export, batch export empty 400.
  • File now at 31 tests, all passing. Zero regressions on the prior 21.

Docs

  • README news entry (today, latest), Web UI feature table, API ASCII diagram.
  • docs/news.md — same two May 10 entries (feature + earlier bug-fix).
  • docs/guides/web-ui.md — Layout, Persistence (5 tables), Session management table, new Folders & active-folder context section, HTTP API (Folders subsection, Sessions extras), Architecture notes (migration + delete_folder PRAGMA detail + two-step session placement), Tests 21 → 31.

…resizable sidebar

ChatGPT-style session organization in the Chat UI, layered on top of the
slash-fix work in the previous commit. Five independent UX features behind
a single coordinated change so the schema migration only runs once.

Folders
  - New `folders` table (per-user, name unique). chat_sessions gains a
    nullable `folder_id` FK.
  - In-place migration in init_db(): PRAGMA table_info probes for the
    column on existing DBs and ALTER TABLE adds it. No Alembic, no manual
    upgrade steps.
  - Endpoints: GET/POST /api/folders, PATCH/DELETE /api/folders/{id},
    PATCH /api/sessions/{id}/folder. Cross-user folders return 404 the
    same way single-session ownership checks do.
  - Deleting a folder reparents its sessions to Ungrouped (folder_id =
    NULL) rather than deleting them. Repo layer NULLs explicitly because
    SQLite PRAGMA foreign_keys is off in this engine.

Drag-drop + Move-to context menu
  - Sessions are HTML5-draggable; folder rows + Ungrouped header are
    drop targets with visual highlight.
  - Right-click on a session: flat Move-to list with every folder, plus
    (Ungrouped) when applicable, plus "+ New folder…" for create-and-move
    in one click.
  - Right-click on a folder: Rename / Delete, with a confirm() that says
    "sessions become Ungrouped — they are NOT deleted".

Active-folder context (ChatGPT-style)
  - Click a folder name (not the disclosure arrow) to enter that folder.
    Row gets accent highlight; topbar grows a "Chat · in <Folder>"
    breadcrumb.
  - While a folder is active, + New and direct-typing auto-create both
    drop the new session into that folder. Switching to any session
    syncs the active context to that session's folder.
  - State persists across reloads via localStorage (cc-active-folder).
    Deleted folders auto-clear.

Batch operations
  - "Select" button enters multi-select mode (checkboxes, Select all
    respects the search filter). Footer action bar batch-deletes (single
    confirm + total-message count) or batch-exports as one combined
    Markdown (chats-N-sessions.md).
  - Endpoints: POST /api/sessions/batch_delete and batch_export.
  - Right-click is suppressed in select mode to avoid mode confusion.

Resizable sidebar
  - 4-px drag handle between sidebar and main pane (mouse + touch).
    Width clamped to 200–600 px and persisted to localStorage
    (cc-sidebar-w). Double-click resets to default. Hidden under
    @media (max-width: 768px) so the mobile drawer keeps its swipe
    behavior.

Tests
  - +10 in tests/test_web_api.py: folder CRUD, duplicate-409, move,
    delete-preserves-as-ungrouped, cross-user isolation, list-includes-
    folder_id, batch delete, batch delete cross-user, batch export,
    batch export empty 400.
  - File now at 31 tests, all passing. Zero regressions on the prior 21.

Docs
  - README news entry (today, latest), Web UI feature table, API ASCII
    diagram.
  - docs/news.md — same two May 10 entries (feature + earlier bug-fix).
  - docs/guides/web-ui.md — Layout, Persistence (5 tables), Session
    management table, new Folders & active-folder context section, HTTP
    API (Folders subsection, Sessions extras), Architecture notes
    (migration + delete_folder PRAGMA detail + two-step session
    placement), Tests 21 → 31.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@chauncygu chauncygu merged commit 949bdef into main May 10, 2026
4 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant