# FABDASH **Fabrication Dashboard** — A sleek, modern project management & scheduling application built for fabrication workflows. Repo: https://github.com/jasonMPM/fabdash ![Version](https://img.shields.io/badge/version-1.1.0-gold) ![Stack](https://img.shields.io/badge/stack-React%20%2B%20Flask%20%2B%20SQLite-informational) ![Theme](https://img.shields.io/badge/theme-Dark%20%2F%20Gold-yellow) ![Docker](https://img.shields.io/badge/deployment-Single%20Docker%20Container-blue) --- ## Table of Contents - [Overview](#overview) - [Tech Stack](#tech-stack) - [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) - [Database Schema](#database-schema) - [Roadmap](#roadmap) --- ## 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 Focus View timeline, a redesigned workload heatmap with per-status color-coded grids, an 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. --- ## Tech Stack ### Frontend | Package | Version | Purpose | |---|---|---| | 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 — 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, 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 and calculations | > **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 | Package | Version | Purpose | |---|---|---| | Flask | 3.1.0 | REST API + static file serving | | Flask-SQLAlchemy | 3.1.1 | ORM for SQLite | | Flask-Migrate | 4.0.7 | Schema migration support | | Flask-CORS | 5.0.0 | Cross-origin support (dev) | | Gunicorn | 23.0.0 | Production WSGI server | ### Database - **SQLite** — Zero-config, file-based persistence at `/app/data/fabdash.db` - 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 --- ## Project Structure ``` fabdash/ ├── Dockerfile # Multi-stage: Node (React build) → Python (Flask) ├── docker-compose.yml ├── .env.example ├── .gitignore ├── README.md │ ├── backend/ │ ├── run.py │ ├── config.py │ ├── requirements.txt │ └── app/ │ ├── __init__.py # App factory + inline schema migrations │ ├── extensions.py │ ├── models.py # Project + Deliverable ORM models │ └── routes/ │ ├── __init__.py │ ├── projects.py # CRUD + drive_url support │ └── deliverables.py │ └── frontend/ ├── 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 └── landing.html # Self-contained marketing landing page └── src/ ├── main.jsx ├── App.jsx # Sidebar layout, keyboard shortcuts, toast container ├── api/ │ ├── projects.js │ └── deliverables.js ├── components/ │ ├── Calendar/ │ │ ├── MainCalendar.jsx # Events, drag-drop, tooltip, select, ResizeObserver reflow │ │ ├── EventTooltip.jsx # Hover preview card │ │ ├── AgendaPanel.jsx # Upcoming deliverables (next 60 days) │ │ └── WorkloadHeatmap.jsx # Per-status 4-column mini grids + combined All Tasks grid │ ├── Projects/ │ │ ├── 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 # px padding fix for scale-105 clip │ │ └── DeliverableCard.jsx # Click=select, dblclick=edit, right-click=menu │ └── UI/ │ ├── Button.jsx │ ├── Badge.jsx │ ├── Modal.jsx # Animated enter transition │ ├── Drawer.jsx │ ├── ContextMenu.jsx # Floating right-click menu │ └── Toast.jsx # 30-second undo toast with countdown ring ├── store/ │ ├── useProjectStore.js │ ├── useFocusStore.js # setActiveDeliverable action │ ├── useUIStore.js # sidebarOpen, sidebarTab, showHeatmap │ └── useToastStore.js # Toast queue management ├── utils/ │ ├── dateHelpers.js │ └── statusHelpers.js └── styles/ └── globals.css # FullCalendar dark theme, slide-up animation ``` --- ## Features ### Calendar - **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) - **Smooth sidebar reflow** — `ResizeObserver` calls `updateSize()` on every frame during the sidebar CSS transition so the calendar grid never clips or overflows ### Workload Heatmap Toggle between the calendar and heatmap with the **⬡ Heatmap** button in the top-right. When the heatmap is active, the button reads **← Calendar** to return. The heatmap has two visual sections: #### Per-Status Mini Grids (top row) A 4-column grid — one column per status — each with a stat card above its heatmap: | Status | Color | Stat card shows | |---|---|---| | Upcoming | Blue | Total upcoming deliverables | | In Progress | Amber | Total in-progress deliverables | | Completed | Green | Total completed deliverables | | Overdue | Red | Total overdue deliverables | - **20-week grid per status** — Mon–Sun rows, week columns, centered 10 weeks before and after today - **3-tier intensity** — Empty → 20% tint (1 item) → 55% tint (2 items) → full color + glow (3+ items) - **Today ring** — Current day highlighted with a white ring across all grids - **Hover tooltip** — Shows date, status label, and all matching deliverable titles/projects (up to 5, overflow count) - **Click cell** — Opens Focus View for the first deliverable of that status on that day #### Combined "All Tasks" Grid (bottom) A single large heatmap (40px cells) showing every deliverable across all statuses: - **Dominant-status coloring** — Each day cell is colored by its most urgent status using priority order: `overdue > in_progress > upcoming > completed`. Ties resolved by count, then priority - **Color legend** — Inline legend shows all 4 status colors with labels - **Hover tooltip** — Shows per-status breakdown counts for that day, plus all deliverable titles/project names - **Click cell** — Opens Focus View for the first deliverable on that day ### 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** — 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** — 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** — 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 inline), Edit, and Delete ### Right-Click Context Menu 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 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 | *Only shown when a Google Drive URL is set on the project. ### Undo Toast 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 ### Landing Page A self-contained marketing page served at `/landing.html`. Built as a standalone HTML file in `frontend/public/` — Vite copies it to `dist/` and Flask serves it without touching app routing. - **Parallax hero** — Animated dark/gold header with tagline - **Mock app preview** — Static UI mockup of the calendar view - **Workload heatmap demo** — Illustrated heatmap section showing the density grid concept - **Benefit cards** — Feature highlights with icons - **Focus View mockup** — Illustrated timeline drawer preview - **How-it-works steps** — 3-step numbered walkthrough - **Docker quick-start block** — Copy-paste install commands - **Footer** — GitHub repository link ### 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 - **Calendar reflow** — `ResizeObserver` drives `updateSize()` on every pixel change during the sidebar transition - **Toast slide-up** — `@keyframes slide-up` animation in `globals.css` - **Heatmap cells** — `hover:scale-125` on each cell for tactile feedback --- ## Interaction Reference | Location | Single Click | Double Click | Right Click | |---|---|---|---| | Calendar event | Open Focus View | Edit Deliverable modal | Context menu | | 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 | | 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. --- ## API Reference ### Projects | Method | Endpoint | Description | |---|---|---| | `GET` | `/api/projects` | List all projects with nested deliverables | | `POST` | `/api/projects` | Create project (with optional inline deliverables) | | `GET` | `/api/projects/:id` | Get single project | | `PATCH` | `/api/projects/:id` | Update name, color, description, or drive_url | | `DELETE` | `/api/projects/:id` | Delete project + cascade deliverables | ### Deliverables | Method | Endpoint | Description | |---|---|---| | `GET` | `/api/deliverables?project_id=:id` | List deliverables for a project | | `POST` | `/api/deliverables` | Create deliverable | | `PATCH` | `/api/deliverables/:id` | Update title, due_date, or status | | `DELETE` | `/api/deliverables/:id` | Delete deliverable | **Example — Create Project with Drive link:** ```json POST /api/projects { "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-10", "status": "upcoming" } ] } ``` --- ## Component Architecture ``` App ├──