diff --git a/README.md b/README.md index 4f98d90..134e361 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,11 @@ - [Project Structure](#project-structure) - [Features](#features) - [Interaction Reference](#interaction-reference) +- [Keyboard Shortcuts](#keyboard-shortcuts) - [API Reference](#api-reference) - [Component Architecture](#component-architecture) - [Unraid Installation](#unraid-installation) +- [Adding Your Logo](#adding-your-logo) - [Updating FabDash on Unraid](#updating-fabdash-on-unraid) - [Local Development](#local-development) - [Environment Variables](#environment-variables) @@ -29,7 +31,7 @@ ## Overview -FabDash is a self-hosted, full-stack project management dashboard built for fabrication teams. It features a large interactive calendar, multi-deliverable project tracking, drag-and-drop scheduling, a per-project timeline Focus View, and a rich right-click context menu system. All wrapped in a dark/gold UI and deployed as a single Docker container with no external dependencies. +FabDash is a self-hosted, full-stack project management dashboard built for fabrication teams. It features a large interactive calendar, multi-deliverable project tracking, drag-and-drop scheduling, a per-project Focus View timeline, workload heatmap, agenda panel, right-click context menus, keyboard shortcuts, and a collapsible branded sidebar — all wrapped in a dark/gold UI and deployed as a single Docker container with no external dependencies. --- @@ -42,17 +44,20 @@ FabDash is a self-hosted, full-stack project management dashboard built for fabr | React | ^18.3.1 | UI framework | | Vite | ^5.4.11 | Build tool and dev server | | Tailwind CSS | ^3.4.15 | Utility-first styling | -| @fullcalendar/core | 6.1.15 | FullCalendar core (pinned) | +| @fullcalendar/core | 6.1.15 | FullCalendar core (pinned — version must match all FC packages) | | @fullcalendar/react | 6.1.15 | Calendar component | | @fullcalendar/daygrid | 6.1.15 | Month/week grid view | | @fullcalendar/timegrid | 6.1.15 | Time-slot view | -| @fullcalendar/interaction | 6.1.15 | Drag-and-drop, click events | -| react-chrono | 2.6.0 | Focus View timeline (pinned — last React 18 compatible) | +| @fullcalendar/interaction | 6.1.15 | Drag-and-drop, click, select events | +| react-chrono | 2.6.0 | Focus View timeline (pinned — v2.7+ requires React 19) | | Zustand | ^4.5.5 | Global state management | | Axios | ^1.7.9 | HTTP client | -| date-fns | ^3.6.0 | Date formatting | +| date-fns | ^3.6.0 | Date formatting and calculations | -> **Note:** All FullCalendar packages are pinned to exactly `6.1.15` to prevent version mismatch errors during Docker builds. `react-chrono` is pinned to `2.6.0` — versions ≥ 2.7.0 require React 19. +> **Dependency notes:** +> - All FullCalendar packages are pinned to exactly `6.1.15` (no `^`) to prevent version mismatch build errors +> - `react-chrono` is pinned to `2.6.0` — versions ≥ 2.7.0 require React 19 which breaks the build +> - `npm install --legacy-peer-deps` is used in the Dockerfile and local dev to handle peer dependency conflicts ### Backend @@ -67,8 +72,8 @@ FabDash is a self-hosted, full-stack project management dashboard built for fabr ### Database - **SQLite** — Zero-config, file-based persistence at `/app/data/fabdash.db` -- Mounted as a named Docker volume so data survives all container restarts and rebuilds -- **Inline migrations** — New columns are applied automatically on startup via `_run_migrations()` in `app/__init__.py`; no manual migration commands required +- Mounted as a Docker volume so data survives all container restarts and image rebuilds +- **Inline migrations** — New columns are applied automatically on startup via `_run_migrations()` in `app/__init__.py`; no `flask db upgrade` commands needed --- @@ -76,7 +81,7 @@ FabDash is a self-hosted, full-stack project management dashboard built for fabr ``` fabdash/ -├── Dockerfile +├── Dockerfile # Multi-stage: Node (React build) → Python (Flask) ├── docker-compose.yml ├── .env.example ├── .gitignore @@ -87,53 +92,61 @@ fabdash/ │ ├── config.py │ ├── requirements.txt │ └── app/ -│ ├── __init__.py # App factory + inline migrations +│ ├── __init__.py # App factory + inline schema migrations │ ├── extensions.py -│ ├── models.py # Project + Deliverable models +│ ├── models.py # Project + Deliverable ORM models │ └── routes/ │ ├── __init__.py -│ ├── projects.py +│ ├── projects.py # CRUD + drive_url support │ └── deliverables.py │ └── frontend/ - ├── package.json - ├── vite.config.js # optimizeDeps for FullCalendar + ├── package.json # react-chrono@2.6.0, @fullcalendar/* pinned to 6.1.15 + ├── vite.config.js # optimizeDeps for FullCalendar, /api proxy ├── tailwind.config.js ├── postcss.config.js ├── index.html + └── public/ + └── logo.png # ← Drop your square logo here └── src/ ├── main.jsx - ├── App.jsx + ├── App.jsx # Sidebar layout, keyboard shortcuts, toast container ├── api/ │ ├── projects.js │ └── deliverables.js ├── components/ │ ├── Calendar/ - │ │ └── MainCalendar.jsx # dblclick + right-click on events + │ │ ├── MainCalendar.jsx # Events, drag-drop, tooltip, select, heatmap toggle + │ │ ├── EventTooltip.jsx # Hover preview card + │ │ ├── AgendaPanel.jsx # Upcoming deliverables (next 60 days) + │ │ └── WorkloadHeatmap.jsx # 20-week density heatmap + stat cards │ ├── Projects/ - │ │ ├── ProjectList.jsx - │ │ ├── ProjectCard.jsx # dblclick + right-click, Drive link - │ │ └── ProjectModal.jsx # Drive URL input field + │ │ ├── ProjectList.jsx # Logo header, tab toggle, empty state + │ │ ├── ProjectCard.jsx # Drive link, dblclick, right-click + │ │ └── ProjectModal.jsx # Drive URL field │ ├── Deliverables/ │ │ └── DeliverableModal.jsx │ ├── FocusView/ │ │ ├── FocusDrawer.jsx - │ │ ├── FocusTimeline.jsx # Click any card to activate - │ │ └── DeliverableCard.jsx # dblclick + right-click, status menu + │ │ ├── FocusTimeline.jsx # px padding fix for scale-105 clip + │ │ └── DeliverableCard.jsx # Click=select, dblclick=edit, right-click=menu │ └── UI/ │ ├── Button.jsx │ ├── Badge.jsx - │ ├── Modal.jsx + │ ├── Modal.jsx # Animated enter transition │ ├── Drawer.jsx - │ └── ContextMenu.jsx # Floating right-click menu + │ ├── ContextMenu.jsx # Floating right-click menu + │ └── Toast.jsx # 30-second undo toast with countdown ring ├── store/ │ ├── useProjectStore.js - │ └── useFocusStore.js # setActiveDeliverable action + │ ├── useFocusStore.js # setActiveDeliverable action + │ ├── useUIStore.js # sidebarOpen, sidebarTab, showHeatmap + │ └── useToastStore.js # Toast queue management ├── utils/ │ ├── dateHelpers.js │ └── statusHelpers.js └── styles/ - └── globals.css + └── globals.css # FullCalendar dark theme, slide-up animation ``` --- @@ -142,67 +155,86 @@ fabdash/ ### Calendar -- **Large full-width calendar** — Month, Week, and Day views via FullCalendar -- **Drag-and-drop rescheduling** — Move any deliverable to a new date; backend patches immediately +- **Full-width calendar** — Month, Week, and Day views via FullCalendar +- **Week numbers** — ISO week numbers displayed in gold on the left edge +- **Drag-and-drop rescheduling** — Move any deliverable to a new date; backend patches immediately with a 30-second undo toast +- **Date range drag-select** — Click and drag across multiple days to open Add Deliverable modal pre-filled with the start date - **Click empty date cell** — Opens Add Deliverable modal pre-filled with that date +- **Hover tooltip** — Shows project name, deliverable title, due date, and status badge without clicking - **Single-click event** — Opens Deliverable Focus View - **Double-click event** — Opens Edit Deliverable modal directly - **Right-click event** — Context menu (Edit, Focus View, Open Drive, Delete) +### Workload Heatmap + +Toggle between the calendar and heatmap with the **⬡ Heatmap** button in the top-right of the main area. + +- **20-week grid** — Mon–Sun rows, week columns, centered 10 weeks before and after today +- **Color intensity** — Cells shade from dark (no deliverables) to full gold (3+ deliverables) +- **Today ring** — Current day highlighted with a white ring +- **Hover tooltip** — Shows date + all deliverable titles and project names for that day (up to 5, with overflow count) +- **Click cell** — Opens Focus View for the first deliverable on that day +- **Stat cards** — Total / Upcoming / In Progress / Completed / Overdue counts across all projects + +### Sidebar + +- **Collapsible** — Click the `◀` tab or press `B` to collapse. The toggle becomes a branded square tile showing your logo +- **Projects tab** — Project cards with deliverable rows; empty state SVG illustration with keyboard hint +- **Upcoming tab** — Agenda panel showing all deliverables due in the next 60 days, grouped by date with sticky headers; Today highlighted in gold +- **Keyboard shortcut legend** — Pinned at the bottom of the sidebar + ### Projects -- **Multi-deliverable projects** — Add unlimited deliverables per project, each with its own title, due date, and status -- **Inline creation** — Add all deliverables while creating the project in a single form submission -- **Color coding** — 12-swatch palette + custom hex input; color appears on calendar events and sidebar cards -- **Google Drive link** — Optional Drive folder URL stored per project; appears as a button on the project card and in context menus -- **Double-click project header** — Opens Edit Project modal instantly +- **Multi-deliverable projects** — Unlimited deliverables per project, each with its own title, due date, and status +- **Inline creation** — Add all deliverables in a single form while creating the project +- **Color coding** — 12-swatch palette + custom hex input +- **Google Drive link** — Optional Drive folder URL stored per project; shows as a Drive button on the card and appears in context menus +- **Double-click project header** — Opens Edit Project modal - **Right-click project header** — Context menu (Edit, Open Drive, Delete) ### Deliverables - **Status tracking** — Upcoming / In Progress / Completed / Overdue -- **Auto-overdue detection** — Any deliverable whose due date has passed is automatically returned as `overdue` by the API unless it is marked `completed`. Logic is computed at read time — no cron job needed +- **Auto-overdue** — Any deliverable whose due date has passed is returned as `overdue` by the API unless marked `completed`. Computed at read time — no cron job required - **Double-click sidebar row** — Opens Edit Deliverable modal - **Right-click sidebar row** — Context menu (Edit, Focus View, Delete) ### Deliverable Focus View -- **Slide-up drawer** — Triggered by clicking any calendar event or sidebar deliverable -- **Horizontal timeline** — All deliverables for the project rendered in date order -- **Active card highlighting** — Clicked deliverable glows in gold with a "Selected" badge -- **Click any card** — Switches the active/selected card without closing the drawer +- **Slide-up drawer** — Opens from bottom of screen when clicking any calendar event or sidebar row +- **Horizontal timeline** — All deliverables for the project rendered in chronological order +- **Active card** — Highlighted in gold with a "Selected" badge floating above; properly padded so scale-105 transform never clips against scroll container edges +- **Click any card** — Switches the active/selected card - **Double-click any card** — Opens Edit Deliverable modal -- **Right-click any card** — Context menu with quick status change (all 4 statuses), Edit, and Delete +- **Right-click any card** — Context menu with quick status change (all 4 statuses inline), Edit, and Delete ### Right-Click Context Menu -A custom floating `ContextMenu` component appears at the cursor position and auto-adjusts to stay within the viewport. It closes on outside click or `Escape`. Available everywhere: +Custom floating `ContextMenu` component auto-adjusts to stay within the viewport. Closes on outside click or `Escape`. | Trigger | Menu Items | |---|---| -| Calendar event | Edit Deliverable, Open Focus View, Open Drive*, Delete | +| Calendar event | Edit Deliverable, Open Focus View, Open Drive Folder*, Delete | | Sidebar project header | Edit Project, Open Drive*, Delete Project | | Sidebar deliverable row | Edit Deliverable, Open Focus View, Delete | -| Focus View card | Edit Deliverable, Mark Upcoming/In Progress/Completed/Overdue, Delete | +| Focus View card | Edit Deliverable, Mark Upcoming / In Progress / Completed / Overdue, Delete | -*Only shown when a Drive URL is set on the project. +*Only shown when a Google Drive URL is set on the project. -### Theme & Design System +### Undo Toast -```js -// tailwind.config.js — custom tokens -colors: { - gold: '#C9A84C', // Primary accent - 'gold-light': '#E8C96A', - 'gold-muted': '#8A6E2F', - surface: '#111111', // Page background - 'surface-raised': '#1A1A1A', // Sidebar, drawer - 'surface-elevated': '#242424', // Cards - 'surface-border': '#2E2E2E', // Borders - 'text-primary': '#F5F5F5', - 'text-muted': '#888888', -} -``` +After a drag-and-drop rescheduling, a toast appears at the bottom of the screen with: +- The new date +- An **Undo** button that patches back to the original date +- A circular SVG countdown ring showing seconds remaining (30s default) +- Auto-dismisses when the timer expires + +### Animations & Polish + +- **Modal enter** — Backdrop fades in, dialog scales up from 95% with a translateY, using `requestAnimationFrame` for reliable transitions +- **Sidebar slide** — `transition-[width] duration-300` for smooth collapse/expand +- **Toast slide-up** — `@keyframes slide-up` animation in `globals.css` +- **Heatmap cells** — `hover:scale-125` on each cell for tactile feedback --- @@ -211,11 +243,27 @@ colors: { | Location | Single Click | Double Click | Right Click | |---|---|---|---| | Calendar event | Open Focus View | Edit Deliverable modal | Context menu | -| Calendar empty cell | Add Deliverable (pre-filled date) | — | — | +| Calendar empty cell | Add Deliverable (date pre-filled) | — | — | +| Calendar date range drag | Add Deliverable (start date pre-filled) | — | — | | Sidebar project header | — | Edit Project modal | Context menu | | Sidebar deliverable row | Open Focus View | Edit Deliverable modal | Context menu | | Focus View card | Select / activate | Edit Deliverable modal | Context menu | -| Focus View active card Edit button | Edit Deliverable modal | — | — | +| Heatmap cell (with deliverables) | Open Focus View for first deliverable | — | — | + +--- + +## Keyboard Shortcuts + +| Key | Action | +|---|---| +| `N` | Open New Project modal | +| `B` | Toggle sidebar open / collapsed | +| `←` | Calendar — previous month/week/day | +| `→` | Calendar — next month/week/day | +| `T` | Calendar — jump to today | +| `Esc` | Close any open modal or drawer | + +Shortcuts are blocked when focus is inside an input, textarea, or select field. --- @@ -240,19 +288,19 @@ colors: { | `PATCH` | `/api/deliverables/:id` | Update title, due_date, or status | | `DELETE` | `/api/deliverables/:id` | Delete deliverable | -**Example — Create Project:** +**Example — Create Project with Drive link:** ```json POST /api/projects { - "name": "CODA", - "color": "#4A90D9", + "name": "Tucson", + "color": "#E67E22", "description": "ADA Call Column and Shelter Equipment Box", "drive_url": "https://drive.google.com/drive/folders/your-folder-id", "deliverables": [ { "title": "Cut Extrusion to Length", "due_date": "2026-03-05", "status": "in_progress" }, { "title": "Cut Faceplates and Top Plates", "due_date": "2026-03-06", "status": "upcoming" }, - { "title": "Fabricate Shelter Assembly Box", "due_date": "2026-03-11", "status": "upcoming" } + { "title": "Fabricate Shelter Assembly Box", "due_date": "2026-03-10", "status": "upcoming" } ] } ``` @@ -263,24 +311,39 @@ POST /api/projects ``` App -├── Sidebar -│ ├── ProjectList -│ │ └── ProjectCard (× N) ← dblclick + right-click -│ │ ├── DeliverableRow (× N) ← dblclick + right-click -│ │ ├── DeliverableModal (local) -│ │ └── ContextMenu (local) -│ └── Button ["+ Project"] +├──