Files
resolutionflow/WORKSPACE-REMOVAL-PLAN.md
chihlasm fa709faa60 feat: UI design system - sidebar layout, workspace system, and shell redesign (#77)
* feat: add workspace system and sidebar layout (UI design system Phase A+B)

Backend: Workspace model, migration (036), schemas, CRUD API endpoints.
Adds workspace_id to trees and categories, seeds 4 default workspaces
per account, auto-assigns existing trees by tree_type.

Frontend: Complete AppLayout rewrite from top-nav to CSS Grid shell
with persistent sidebar + topbar. New components: WorkspaceSwitcher,
NavItem, CategoryList, TagCloud, TopBar, Sidebar. Dashboard components:
QuickStats, FiltersBar, SectionGroup, TreeListItem, SessionsPanel.
WorkspaceStore with localStorage persistence.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add command palette search, dashboard rewrite, and shell height fixes (Phase C)

- Add ⌘K command palette with debounced search across flows and sessions
- Rewrite QuickStartPage as dashboard with stats, filters, sessions panel
- Fix h-[calc(100vh-4rem)] → h-full across all pages for CSS Grid shell
- Add active session count badge to sidebar Sessions nav item

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add sidebar collapse, category/tag filtering, and workspace CRUD (Phase D)

- Sidebar collapse/expand toggle with icon-only rail mode (persisted)
- Sidebar category/tag clicks navigate to /trees with URL params
- TreeLibraryPage syncs filters from URL search params bidirectionally
- Workspace create modal with icon picker and auto-slug generation
- TopBar logo adapts to collapsed sidebar state

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add Quick Launch modal with actions and recent flows

- Zap button opens Quick Launch with create/navigate shortcuts
- Shows recent flows for quick session start
- Keyboard navigation support (arrows + enter)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add activity notifications panel with session feed

- Bell icon shows dot indicator for recent activity
- Dropdown panel shows recent sessions with status icons
- Links to session detail and sessions list page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: remove workspace system, add pinned flows and label renames

Replace workspace system with pinned flows API (pin/unpin/list/reorder).
Rename user-facing labels: Tree→Flow, Procedure→Project. Add sidebar
nav sub-items for flow type filtering. Remove 11 workspace files,
add migrations 037-038, clean all workspace references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: collapsed sidebar layout scaling and toggle button size

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate auth pages to new design system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate TreeLibraryPage to new design system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate session pages to new design system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate TreeEditorPage to new design system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate TreeNavigationPage to new design system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate session sharing components to new design system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: remove workspace dropdown animation (dead code)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate common components to new design system

Migrate 15 components from monochrome glass-card design to purple gradient
accent design system tokens (bg-card, border-border, text-foreground,
bg-gradient-brand, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate procedural and step library components to new design system

Migrate 10 components from monochrome glass-card design to purple gradient
accent design system tokens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate admin pages and components to new design system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate remaining pages to new design system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate remaining components to new design system

Migrates 38 files: tree-editor forms, session modals, step library,
common components, library views, tree preview, and misc UI to use
design tokens (bg-card, border-border, text-foreground, bg-accent,
bg-gradient-brand) replacing old monochrome patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: keep brand text visible on sidebar collapse, hide sub-items until hover

- TopBar: always show "ResolutionFlow" text regardless of sidebar state
- NavItem: sub-items (Troubleshooting, Projects) hidden by default,
  revealed on hover or when a child route is active

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:45:19 -05:00

609 lines
23 KiB
Markdown

# Workspace Removal & Navigation Refactor — Implementation Plan
> **Purpose:** Combined implementation plan for removing the workspace system, renaming UI labels (Trees→Flows, Procedures→Projects), adding pinned flows, and restructuring sidebar navigation.
> **Source of Truth:** [UI-DESIGN-SYSTEM.md](UI-DESIGN-SYSTEM.md) v2
> **Date:** February 15, 2026
> **Tailwind Version:** v3 only — do not use v4 syntax or patterns (see `package.json` line 56)
---
## Why This Change
Workspaces added unnecessary cognitive overhead for the target MSP audience. UX research (Hick's Law, context-switching studies) shows that at the current product scale (10-15 beta testers, <50 flows per account), a workspace switcher creates friction without organizational benefit. The replacement is a flat navigation model with type sub-items and pinned favorites.
---
## Phase 1 — Backend: Add Pinned Flows (ship BEFORE removing workspaces)
> **Important sequencing:** Add the pinned flows feature first and verify it works. Then remove workspaces in Phase 2. This ensures the replacement feature is stable before tearing out the old one. If both are done in the same session, at minimum run the pinned flows tests before starting workspace removal.
### 1a. Add Pinned Flows Table
```bash
cd backend
alembic revision --autogenerate -m "add_user_pinned_trees"
```
```sql
CREATE TABLE user_pinned_trees (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
tree_id UUID NOT NULL REFERENCES trees(id) ON DELETE CASCADE,
display_order INTEGER NOT NULL DEFAULT 0,
pinned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_user_pinned_tree UNIQUE (user_id, tree_id)
);
CREATE INDEX idx_user_pinned_trees_user ON user_pinned_trees(user_id);
CREATE INDEX idx_user_pinned_trees_tree ON user_pinned_trees(tree_id);
```
### 1b. Pinned Flows API Contract
**Endpoints:**
| Method | Path | Description | Auth |
|--------|------|-------------|------|
| `GET` | `/api/v1/trees/pinned` | List user's pinned flows (ordered by display_order) | Required |
| `POST` | `/api/v1/trees/{id}/pin` | Pin a flow to sidebar | Required |
| `DELETE` | `/api/v1/trees/{id}/pin` | Unpin a flow from sidebar | Required |
| `PATCH` | `/api/v1/trees/pinned/reorder` | Update display_order for all pinned flows | Required |
**Constraints & Limits:**
- Max 15 pinned flows per user (return 409 if exceeded)
- `UNIQUE(user_id, tree_id)` — pinning an already-pinned flow returns 200 (idempotent), not an error
- Unpinning an already-unpinned flow returns 200 (idempotent)
- When a tree is deleted, cascade removes the pin automatically (FK ON DELETE CASCADE)
- Pins are per-user, not per-account — each user has their own pinned set
**Response Shapes:**
```typescript
// GET /api/v1/trees/pinned
interface PinnedFlowsResponse {
items: PinnedFlow[];
count: number;
}
interface PinnedFlow {
id: string; // pin record id
tree_id: string;
tree_name: string;
tree_type: 'troubleshooting' | 'procedural';
category_emoji?: string;
category_name?: string;
pinned_at: string; // ISO datetime
display_order: number;
}
// POST /api/v1/trees/{id}/pin → returns PinnedFlow
// DELETE /api/v1/trees/{id}/pin → returns { success: true }
// PATCH /api/v1/trees/pinned/reorder
// body: { order: [{ tree_id: string, display_order: number }] }
// returns: PinnedFlowsResponse
```
**Error Codes:**
- `404` — tree not found or user lacks access
- `409` — max pins reached (15)
- `200` — idempotent success (pin already exists / already unpinned)
### 1c. Add Pinned Flows Backend Files
```
CREATE: backend/app/models/user_pinned_tree.py
MODIFY: backend/app/models/__init__.py — add UserPinnedTree import
MODIFY: backend/app/api/endpoints/trees.py — add pin/unpin/list-pinned/reorder endpoints
MODIFY: backend/app/schemas/tree.py — add PinnedFlow schema, add is_pinned to TreeListItem
MODIFY: backend/app/api/router.py — register pin routes (nested under trees router)
```
**Verify pinned flows work before proceeding:**
```bash
cd backend
alembic upgrade head
pytest tests/ -k "pin" -v # Run pin-related tests
# Manual: POST a pin, GET pinned list, verify response shapes
```
---
## Phase 2 — Backend: Remove Workspace System
### 2a. New Forward Migration (DO NOT use downgrade path)
> **⚠️ Critical:** The existing `036_add_workspaces.py` downgrade function drops `tree_categories.color`, which we want to keep. Create a new forward migration instead.
```bash
cd backend
alembic revision --autogenerate -m "remove_workspace_system"
```
The migration must:
```python
def upgrade():
# 1. Drop workspace_id FK from trees (if column exists)
op.drop_constraint('trees_workspace_id_fkey', 'trees', type_='foreignkey')
op.drop_column('trees', 'workspace_id')
# 2. Drop workspace_id FK from tree_categories (if column exists)
op.drop_constraint('tree_categories_workspace_id_fkey', 'tree_categories', type_='foreignkey')
op.drop_column('tree_categories', 'workspace_id')
# 3. Drop workspaces table
op.drop_table('workspaces')
# DO NOT drop tree_categories.color — we still use it
def downgrade():
# Recreate workspaces table and FKs if needed (reverse of above)
pass
```
### 2b. Delete Workspace Backend Files
```
DELETE: backend/app/api/endpoints/workspaces.py
DELETE: backend/app/models/workspace.py
DELETE: backend/app/schemas/workspace.py (if exists)
```
### 2c. Clean Up Orphaned Workspace References
> **⚠️ Important:** Workspace references exist beyond the obvious files. Scrub these:
| File | What to Remove |
|------|---------------|
| `backend/app/api/router.py` | Remove workspace route registration |
| `backend/app/models/__init__.py` (line 23, 55) | Remove `Workspace` import and `__all__` entry |
| `backend/app/models/account.py` (line 18, 49) | Remove `workspaces` relationship on Account model |
| `backend/app/models/category.py` (line 40) | Remove `workspace_id` column if present |
| `backend/app/models/tree.py` | Remove `workspace_id` column and relationship if present |
**Verification:**
```bash
cd backend
grep -r "workspace" app/ --include="*.py" -l
# Should only return this plan file and alembic migration history — no active code
pytest --override-ini="addopts="
# All tests must pass
```
**Migration smoke test (run against BOTH clean and existing DB):**
```bash
# Test on existing DB with workspace data:
alembic upgrade head
# Verify no errors, workspace tables gone, tree_categories.color still exists
# Test on clean DB (full migration chain):
dropdb patherly_test && createdb patherly_test
DATABASE_URL=postgresql://...patherly_test alembic upgrade head
# Verify clean run through all migrations
```
---
## Phase 3 — Frontend: Remove Workspace System
### 3a. Move sidebarCollapsed State First
The `sidebarCollapsed` state currently lives in `workspaceStore.ts`. Move it before deleting:
```typescript
// frontend/src/store/userPreferencesStore.ts — ADD these:
sidebarCollapsed: boolean;
toggleSidebar: () => void;
// Implementation:
sidebarCollapsed: localStorage.getItem('sidebar-collapsed') === 'true',
toggleSidebar: () => {
const next = !get().sidebarCollapsed;
localStorage.setItem('sidebar-collapsed', String(next));
set({ sidebarCollapsed: next });
},
```
> Note: `userPreferencesStore` already uses Zustand persist — verify the localStorage key name doesn't conflict.
### 3b. Delete Workspace Frontend Files
```
DELETE: frontend/src/store/workspaceStore.ts
DELETE: frontend/src/components/workspace/WorkspaceSwitcher.tsx
DELETE: frontend/src/components/workspace/WorkspaceCreateModal.tsx
DELETE: frontend/src/constants/workspaceLabels.ts
DELETE: frontend/src/types/workspace.ts (or remove Workspace type if shared file)
DELETE: frontend/src/api/workspaces.ts
DELETE: docs/mockups/resolutionflow-workspaces-mockup.html
```
**Before deleting `workspace/` directory**, move these components:
```
MOVE: frontend/src/components/workspace/CategoryList.tsx → frontend/src/components/sidebar/CategoryList.tsx
MOVE: frontend/src/components/workspace/TagCloud.tsx → frontend/src/components/sidebar/TagCloud.tsx
```
### 3c. Update Shell Files That Import Workspace Store
> **⚠️ Important:** These files are marked "keep" in the design system doc but they currently import workspace code. Each needs internal refactoring:
| File | Lines to Change | Action |
|------|----------------|--------|
| `AppLayout.tsx` (line 6, 17) | `import { useWorkspaceStore }` | Replace with `import { useUserPreferencesStore }` — use `sidebarCollapsed` and `toggleSidebar` from there |
| `TopBar.tsx` (line 6, 20) | `import { useWorkspaceStore }` | Replace with `useUserPreferencesStore` for `sidebarCollapsed`. Remove `getActiveWorkspace()` and `labels` — use static labels or `getFlowLabels()` |
| `Sidebar.tsx` (line 4, 111+) | `WorkspaceSwitcher` import and render | Remove workspace switcher component. Add pinned flows section and nav sub-items (Phase 4) |
### 3d. Clean Up Orphaned Frontend References
> **⚠️ Important:** Additional workspace references exist beyond the obvious files:
| File | What to Change |
|------|---------------|
| `frontend/src/types/index.ts` (line 11, 14) | Remove `Workspace` type export |
| `frontend/src/components/layout/QuickLaunch.tsx` | Replace workspace-dependent labels with static "New Flow" / "New Project" |
| `frontend/src/components/layout/CommandPalette.tsx` | Replace workspace-dependent search placeholder and result labels |
**Verification:**
```bash
cd frontend
grep -r "workspace" src/ --include="*.ts" --include="*.tsx" -l
# Should return nothing except possibly test files or comments
grep -r "workspaceStore\|WorkspaceSwitcher\|workspacesApi\|workspaceLabels" src/ -l
# Must return nothing
npm run build
# Must compile clean with zero errors
```
---
## Phase 4 — Label Renames (Repo-Wide Audit)
### 4a. Create Flow Type Labels
```typescript
// frontend/src/constants/flowLabels.ts (NEW — replaces workspaceLabels.ts)
export interface FlowTypeLabels {
navLabel: string;
singular: string;
plural: string;
newButton: string;
searchPlaceholder: string;
icon: string;
}
export const FLOW_TYPE_LABELS: Record<string, FlowTypeLabels> = {
all: {
navLabel: 'All Flows',
singular: 'Flow',
plural: 'Flows',
newButton: '+ Create Flow',
searchPlaceholder: 'Search flows, sessions, tags…',
icon: '📦',
},
troubleshooting: {
navLabel: 'Troubleshooting',
singular: 'Flow',
plural: 'Flows',
newButton: '+ New Troubleshooting Flow',
searchPlaceholder: 'Search troubleshooting flows…',
icon: '🔧',
},
procedural: {
navLabel: 'Projects',
singular: 'Project',
plural: 'Projects',
newButton: '+ New Project',
searchPlaceholder: 'Search projects, runbooks…',
icon: '📋',
},
};
export function getFlowLabels(typeFilter?: string): FlowTypeLabels {
if (typeFilter && typeFilter in FLOW_TYPE_LABELS) {
return FLOW_TYPE_LABELS[typeFilter];
}
return FLOW_TYPE_LABELS.all;
}
```
### 4b. Label Audit — Files Requiring Changes
Every instance of old terminology must be found and replaced. This is a **repo-wide pass**, not a targeted find-replace.
**User-facing label changes:**
| Old Label | New Label | Notes |
|-----------|-----------|-------|
| "All Trees" | "All Flows" | Sidebar nav, page titles |
| "Tree Editor" | "Flow Editor" | Sidebar nav |
| "New Tree" | "Create Flow" | Buttons, menus |
| "All Procedures" | "Projects" | Sub-nav item |
| "New Procedure" | "New Project" | Buttons, menus |
| "Procedure" (singular) | "Project" | Throughout UI |
**Known files with old labels (non-exhaustive):**
| File | Old Text | New Text |
|------|----------|----------|
| `Sidebar.tsx` | "All Trees", "Tree Editor" | "All Flows", "Flow Editor" |
| `TreeLibraryPage.tsx` (line 279, 298) | "All Trees", "Tree" references | "All Flows", "Flow" |
| `QuickStartPage.tsx` (line 150) | Workspace/procedure labels | Flow/Project labels |
| `QuickLaunch.tsx` | "New Tree", "New Procedure" | "Create Flow", "New Project" |
| `CommandPalette.tsx` | Search labels | Flow-based labels |
| `TopBar.tsx` | Search placeholder | Use `getFlowLabels()` or static "Search flows, sessions, tags…" |
**Catch-all verification:**
```bash
cd frontend
# Find any remaining user-facing "Tree" or "Procedure" labels (excluding variable names and imports)
grep -rn '".*Tree.*"' src/ --include="*.tsx" --include="*.ts" | grep -v "import\|//\|interface\|type \|treesApi\|tree_type\|treeId\|TreeNav\|TreeGrid\|TreeList\|TreeTable"
grep -rn '".*Procedure.*"' src/ --include="*.tsx" --include="*.ts" | grep -v "import\|//\|type "
```
> **Important:** Only rename **user-facing strings** (UI text, placeholder text, toast messages, page titles). Do NOT rename: variable names (`treesApi`, `TreeListItem`), route paths (`/trees`), database columns (`tree_type`), or API endpoints (`/api/v1/trees`). Internal code can say "tree" — users never see it.
### 4c. Acceptance Criteria for Label Audit
- [ ] No user-visible text says "Tree" (except proper nouns or technical docs)
- [ ] No user-visible text says "Procedure" — all say "Project"
- [ ] Search bar placeholder says "Search flows, sessions, tags…"
- [ ] Page title on library page says "Flow Library"
- [ ] "+ Create Flow" button on library page (or "+ New Project" when filtered to projects)
- [ ] Sidebar nav says "All Flows", "Flow Editor"
- [ ] Empty states use "flow" / "project" language
- [ ] Toast messages use "flow" / "project" language
---
## Phase 5 — Sidebar: Nav Sub-Items & Pinned Flows UI
### 5a. Extend NavItem for Children
```tsx
// frontend/src/components/layout/NavItem.tsx — extend props
interface NavItemProps {
href: string;
icon: LucideIcon;
label: string;
badge?: number | 'dot';
isActive?: boolean;
children?: NavSubItem[]; // NEW
}
interface NavSubItem {
href: string;
label: string;
count?: number;
isActive?: boolean;
}
```
**Sub-item rendering:**
- Indented `pl-9` (past parent icon)
- No icon, just text + optional count badge
- Font: `text-[0.8125rem] text-muted-foreground`, active: `text-foreground`
- Active: `bg-[var(--sidebar-active)]` but without the left gradient bar (only parent gets that)
- Sub-items always visible (not collapsible) — there are only 2
### 5b. Sidebar Structure
```
── PINNED ─────────────────── (collapsible section)
📧 Email Delivery Issues (click → start session or go to flow)
🔒 AD Account Lockout
👤 New User Onboarding
───────────────────────────────
📊 Dashboard
📦 All Flows 47
🔧 Troubleshooting 29
📋 Projects 18
✏️ Flow Editor
⏱️ Sessions 4
📄 Exports
📚 Step Library •
───────────────────────────────
CATEGORIES
● Networking 12
● Active Directory 8
● Email 11
───────────────────────────────
POPULAR TAGS
[vpn] [dns] [exchange] [onboarding]
═══════════════════════════════
👥 Team
⚙️ Settings
```
**Behavior:**
- Clicking "All Flows" → `/trees` (no type filter)
- Clicking "Troubleshooting" → `/trees?type=troubleshooting`
- Clicking "Projects" → `/trees?type=procedural`
- When a sub-item is active, parent "All Flows" stays highlighted (dimmer state)
- Badge counts update based on actual tree counts by type
### 5c. Pinned Flows Section
```tsx
// frontend/src/components/sidebar/PinnedFlowsSection.tsx (NEW)
interface PinnedFlowsSectionProps {
flows: PinnedFlow[];
onFlowClick: (treeId: string) => void;
onUnpin: (treeId: string) => void;
}
```
**Behavior:**
- Each pinned item: emoji + name (truncated with ellipsis) + hover reveals quick-start button
- Right-click context menu: "Start Session", "Edit Flow", "Unpin from Sidebar"
- Empty state: "⭐ Pin your most-used flows here" in `text-xs text-muted-foreground`
- Section header has collapse chevron
- Max 15 items shown; section scrolls internally if needed
- Drag-to-reorder (calls `PATCH /api/v1/trees/pinned/reorder`)
### 5d. Pinned Flows Frontend Wiring
```
CREATE: frontend/src/api/pinnedFlows.ts — pinTree(id), unpinTree(id), listPinned(), reorderPinned(order)
CREATE: frontend/src/components/sidebar/PinnedFlowsSection.tsx
MODIFY: frontend/src/types/tree.ts (or index.ts) — add is_pinned?: boolean to TreeListItem, add PinnedFlow type
MODIFY: frontend/src/api/trees.ts — add is_pinned to list response handling
MODIFY: frontend/src/components/layout/Sidebar.tsx — import and render PinnedFlowsSection above nav
MODIFY: frontend/src/pages/TreeLibraryPage.tsx — add pin star to flow cards (visible on hover, filled if pinned)
MODIFY: flow card three-dot menu — add "Pin to Sidebar" / "Unpin from Sidebar" action
```
**Pin/unpin interaction:**
- Toast on pin: "📌 Pinned **{name}** to sidebar"
- Toast on unpin: "Unpinned **{name}**"
- Library flow cards show subtle star icon on hover; filled star if pinned
- Pin star click calls API, optimistically updates UI
---
## Phase 6 — Library Page Cleanup
### 6a. Remove Folder Sidebar Panel
> **⚠️ Important:** `TreeLibraryPage.tsx` has deep folder state dependencies (lines 9, 34, 261+). This is not a simple component removal.
**What to remove:**
- `FolderSidebar` component import and rendering (the persistent left panel)
- `FolderEditModal` import and state
- The CSS column that gives FolderSidebar its own grid track
- `mobileFolderOpen` state
**What to KEEP:**
- `selectedFolderId` state — keep for now, wire to a future "Filter by Folder" dropdown
- `folders` state and `foldersApi.list()` call — keep data available
- `FolderSidebar.tsx` and `FolderEditModal.tsx` files — do not delete, just stop rendering them
- All folder-related backend code (models, API, database tables) — untouched
**Replacement UX (deferred but noted):**
- Future: "Filter by Folder" dropdown in the filters bar, or "Move to Folder" in the three-dot menu
- For now: folder filtering is simply not visible in the UI. The data model and API remain intact.
**Layout change:**
- Library page becomes full-width within the main content area (no second sidebar column)
- Grid goes from `sidebar | folders | content``sidebar | content`
### 6b. Verification
```bash
cd frontend && npm run build
# Must compile clean
```
Manual checks:
- [ ] Library page is full-width (no left folder panel)
- [ ] No JavaScript errors in browser console related to folder state
- [ ] Category filtering from sidebar clicks still works
- [ ] Tag filtering from sidebar clicks still works
---
## Complete File Manifest
### Delete (11 files)
| File | Reason |
|------|--------|
| `frontend/src/store/workspaceStore.ts` | Replaced by userPreferencesStore (sidebarCollapsed) |
| `frontend/src/components/workspace/WorkspaceSwitcher.tsx` | Feature removed |
| `frontend/src/components/workspace/WorkspaceCreateModal.tsx` | Feature removed |
| `frontend/src/constants/workspaceLabels.ts` | Replaced by flowLabels.ts |
| `frontend/src/types/workspace.ts` | Type no longer needed |
| `frontend/src/api/workspaces.ts` | API removed |
| `backend/app/api/endpoints/workspaces.py` | API removed |
| `backend/app/models/workspace.py` | Model removed |
| `backend/app/schemas/workspace.py` | Schema removed (if exists) |
| `docs/mockups/resolutionflow-workspaces-mockup.html` | Outdated mockup |
### Move (2 files)
| From | To |
|------|----|
| `frontend/src/components/workspace/CategoryList.tsx` | `frontend/src/components/sidebar/CategoryList.tsx` |
| `frontend/src/components/workspace/TagCloud.tsx` | `frontend/src/components/sidebar/TagCloud.tsx` |
Then delete the empty `frontend/src/components/workspace/` directory.
### Create (6+ files)
| File | Purpose |
|------|---------|
| `backend/alembic/versions/0XX_remove_workspace_system.py` | Drop workspace tables/columns |
| `backend/alembic/versions/0XX_add_user_pinned_trees.py` | New pinned flows table |
| `backend/app/models/user_pinned_tree.py` | UserPinnedTree SQLAlchemy model |
| `frontend/src/constants/flowLabels.ts` | Flow type label constants |
| `frontend/src/api/pinnedFlows.ts` | Pin/unpin API client |
| `frontend/src/components/sidebar/PinnedFlowsSection.tsx` | Pinned flows sidebar component |
### Modify (14 files — key changes only)
| File | Changes |
|------|---------|
| `backend/app/api/router.py` | Remove workspace routes, add pin routes |
| `backend/app/models/__init__.py` | Remove Workspace import (line 23, 55), add UserPinnedTree |
| `backend/app/models/account.py` | Remove `workspaces` relationship (line 18, 49) |
| `backend/app/models/category.py` | Remove `workspace_id` column (line 40) if present |
| `backend/app/models/tree.py` | Remove `workspace_id` column/relationship if present |
| `backend/app/api/endpoints/trees.py` | Add pin/unpin/list-pinned/reorder endpoints |
| `backend/app/schemas/tree.py` | Add PinnedFlow schema, add `is_pinned` to tree list |
| `frontend/src/store/userPreferencesStore.ts` | Absorb `sidebarCollapsed` + `toggleSidebar` |
| `frontend/src/components/layout/AppLayout.tsx` | Replace workspaceStore with userPreferencesStore |
| `frontend/src/components/layout/TopBar.tsx` | Replace workspaceStore, static search labels |
| `frontend/src/components/layout/Sidebar.tsx` | Remove workspace switcher, add pinned section + nav sub-items |
| `frontend/src/components/layout/NavItem.tsx` | Add `children` sub-item support |
| `frontend/src/pages/TreeLibraryPage.tsx` | Remove FolderSidebar, update labels, add pin star |
| `frontend/src/components/layout/QuickLaunch.tsx` | Update action labels |
| `frontend/src/components/layout/CommandPalette.tsx` | Update search labels |
| `frontend/src/pages/QuickStartPage.tsx` | Update workspace/procedure labels (line 150) |
| `frontend/src/types/index.ts` | Remove Workspace export (line 11, 14), add PinnedFlow |
---
## Verification Checklist
### Automated
```bash
# Backend
cd backend
alembic upgrade head # Migration applies clean
pytest --override-ini="addopts=" # All tests pass
grep -r "workspace" app/ --include="*.py" -l # No active workspace refs
# Frontend
cd frontend
npm run build # Compiles clean, zero errors
grep -r "workspaceStore\|WorkspaceSwitcher\|workspacesApi\|workspaceLabels" src/ -l
# Returns nothing
```
### Manual UI Checks
- [ ] Sidebar shows "All Flows" with "Troubleshooting" and "Projects" sub-items — no workspace switcher
- [ ] Clicking "Troubleshooting" filters library to `?type=troubleshooting`
- [ ] Clicking "Projects" filters library to `?type=procedural`
- [ ] Clicking "All Flows" removes type filter
- [ ] Sub-item counts reflect actual flow counts per type
- [ ] Pin a flow from the library card three-dot menu → appears in sidebar "PINNED" section
- [ ] Unpin a flow → disappears from sidebar
- [ ] Pinned flow click navigates to that flow
- [ ] Library page is full-width (no folder sidebar panel)
- [ ] Search bar is centered in top bar
- [ ] Keyboard shortcut shows "Ctrl+K" on Windows, "⌘K" on Mac
- [ ] All user-visible labels say "Flow" / "Project", never "Tree" / "Procedure"
- [ ] Empty states use correct terminology
- [ ] Toast messages use correct terminology
- [ ] Command palette search works with new labels
- [ ] Quick Launch actions show correct labels