455 lines
13 KiB
Markdown
455 lines
13 KiB
Markdown
# FabDash
|
||
|
||
**Fabrication Dashboard** — A sleek, modern project management & scheduling application.
|
||
|
||

|
||

|
||

|
||

|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
- [Overview](#overview)
|
||
- [Tech Stack](#tech-stack)
|
||
- [Project Structure](#project-structure)
|
||
- [Features](#features)
|
||
- [API Reference](#api-reference)
|
||
- [Docker Deployment](#docker-deployment)
|
||
- [Unraid Installation](#unraid-installation)
|
||
- [Local Development](#local-development)
|
||
- [Environment Variables](#environment-variables)
|
||
- [Database Schema](#database-schema)
|
||
- [Roadmap](#roadmap)
|
||
|
||
---
|
||
|
||
## Overview
|
||
|
||
FabDash is a self-hosted project management dashboard built for fabrication teams. It features a large interactive calendar, multi-deliverable project tracking, drag-and-drop scheduling, and a per-project timeline Focus View. All wrapped in a dark/gold UI and deployed as a single Docker container.
|
||
|
||
---
|
||
|
||
## Tech Stack
|
||
|
||
| Layer | Technology |
|
||
|---|---|
|
||
| Frontend | React 18, Vite, Tailwind CSS |
|
||
| Calendar | FullCalendar v6 (daygrid, timegrid, interaction) |
|
||
| Focus View | Custom horizontal timeline with react-chrono |
|
||
| State | Zustand |
|
||
| HTTP | Axios |
|
||
| Backend | Flask 3, Flask-SQLAlchemy, Flask-Migrate, Flask-CORS |
|
||
| Database | SQLite (persisted via Docker volume) |
|
||
| Server | Gunicorn (production) |
|
||
|
||
---
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
fabdash/
|
||
├── Dockerfile
|
||
├── docker-compose.yml
|
||
├── .env.example
|
||
├── .gitignore
|
||
├── README.md
|
||
│
|
||
├── backend/
|
||
│ ├── run.py
|
||
│ ├── config.py
|
||
│ ├── requirements.txt
|
||
│ └── app/
|
||
│ ├── __init__.py
|
||
│ ├── extensions.py
|
||
│ ├── models.py
|
||
│ └── routes/
|
||
│ ├── __init__.py
|
||
│ ├── projects.py
|
||
│ └── deliverables.py
|
||
│
|
||
└── frontend/
|
||
├── package.json
|
||
├── vite.config.js
|
||
├── tailwind.config.js
|
||
├── postcss.config.js
|
||
├── index.html
|
||
└── src/
|
||
├── main.jsx
|
||
├── App.jsx
|
||
├── api/
|
||
│ ├── projects.js
|
||
│ └── deliverables.js
|
||
├── components/
|
||
│ ├── Calendar/
|
||
│ │ └── MainCalendar.jsx
|
||
│ ├── Projects/
|
||
│ │ ├── ProjectList.jsx
|
||
│ │ ├── ProjectCard.jsx
|
||
│ │ └── ProjectModal.jsx
|
||
│ ├── Deliverables/
|
||
│ │ └── DeliverableModal.jsx
|
||
│ ├── FocusView/
|
||
│ │ ├── FocusDrawer.jsx
|
||
│ │ ├── FocusTimeline.jsx
|
||
│ │ └── DeliverableCard.jsx
|
||
│ └── UI/
|
||
│ ├── Button.jsx
|
||
│ ├── Badge.jsx
|
||
│ ├── Modal.jsx
|
||
│ └── Drawer.jsx
|
||
├── store/
|
||
│ ├── useProjectStore.js
|
||
│ └── useFocusStore.js
|
||
├── utils/
|
||
│ ├── dateHelpers.js
|
||
│ └── statusHelpers.js
|
||
└── styles/
|
||
└── globals.css
|
||
```
|
||
|
||
---
|
||
|
||
## Features
|
||
|
||
- **Large calendar view** — Month, Week, and Day modes via FullCalendar
|
||
- **Drag-and-drop** — Move deliverables to new dates; backend updates instantly
|
||
- **Multi-deliverable projects** — Add unlimited deliverables per project, each with its own due date and status
|
||
- **Color-coded projects** — 12-swatch palette + custom hex; colors appear on calendar events and sidebar cards
|
||
- **Deliverable Focus View** — Click any calendar event to open a slide-up drawer showing the full project timeline, with the selected deliverable highlighted in gold
|
||
- **Status tracking** — Upcoming / In Progress / Completed / Overdue badges per deliverable
|
||
- **Dark/gold theme** — Dark surfaces with gold as the primary accent throughout
|
||
- **Full persistence** — SQLite database via Flask-SQLAlchemy, mounted as a Docker volume
|
||
|
||
---
|
||
|
||
## API Reference
|
||
|
||
### Projects
|
||
|
||
| Method | Endpoint | Description |
|
||
|---|---|---|
|
||
| `GET` | `/api/projects` | List all projects with nested deliverables |
|
||
| `POST` | `/api/projects` | Create project (with optional deliverables inline) |
|
||
| `GET` | `/api/projects/:id` | Get single project |
|
||
| `PATCH` | `/api/projects/:id` | Update name, color, or description |
|
||
| `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 |
|
||
|
||
---
|
||
|
||
## Docker Deployment
|
||
|
||
FabDash uses a **multi-stage Docker build**:
|
||
|
||
1. Stage 1 compiles the React/Vite frontend into static files
|
||
2. Stage 2 copies those files into Flask's `static/` folder
|
||
3. Gunicorn serves the Flask API at `/api/*` and the React SPA at `/*`
|
||
|
||
No Nginx, no separate containers, no reverse proxy required.
|
||
|
||
```bash
|
||
git clone https://github.com/yourname/fabdash.git
|
||
cd fabdash
|
||
cp .env.example .env
|
||
# Edit .env and set a strong SECRET_KEY
|
||
docker compose up -d --build
|
||
# App available at http://your-host:8080
|
||
```
|
||
|
||
---
|
||
|
||
## Unraid Installation
|
||
|
||
FabDash is designed to run cleanly on Unraid via a Docker Compose build from source.
|
||
Two methods are provided below — **Terminal (recommended)** and **Unraid Docker GUI**.
|
||
|
||
---
|
||
|
||
### Method 1 — Terminal via SSH (Recommended)
|
||
|
||
This method builds the image directly on your Unraid server and uses `docker compose` to manage the container.
|
||
|
||
#### Step 1 — Enable SSH on Unraid
|
||
|
||
Go to **Settings → Management Access → SSH** and ensure SSH is enabled.
|
||
|
||
#### Step 2 — SSH into your Unraid server
|
||
|
||
```bash
|
||
ssh root@YOUR_UNRAID_IP
|
||
```
|
||
|
||
#### Step 3 — Clone the repository
|
||
|
||
```bash
|
||
cd /mnt/user/appdata
|
||
git clone https://github.com/yourname/fabdash.git
|
||
cd fabdash
|
||
```
|
||
|
||
#### Step 4 — Create your environment file
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
nano .env
|
||
```
|
||
|
||
Set a strong `SECRET_KEY`:
|
||
|
||
```env
|
||
SECRET_KEY=your-strong-random-secret-key-here
|
||
FLASK_ENV=production
|
||
DATABASE_URL=sqlite:////app/data/fabdash.db
|
||
```
|
||
|
||
Press `Ctrl+X`, then `Y` to save.
|
||
|
||
#### Step 5 — Build and start the container
|
||
|
||
```bash
|
||
docker compose up -d --build
|
||
```
|
||
|
||
The build will take 2–4 minutes the first time (downloading Node and Python layers, compiling the React app).
|
||
|
||
#### Step 6 — Access FabDash
|
||
|
||
Open your browser and navigate to:
|
||
|
||
```
|
||
http://YOUR_UNRAID_IP:8080
|
||
```
|
||
|
||
#### Useful Commands
|
||
|
||
```bash
|
||
# View live logs
|
||
docker compose logs -f fabdash
|
||
|
||
# Stop the container
|
||
docker compose down
|
||
|
||
# Rebuild after a git pull (update)
|
||
git pull
|
||
docker compose up -d --build
|
||
|
||
# Open a shell inside the container
|
||
docker exec -it fabdash bash
|
||
|
||
# Run database migrations (after schema changes)
|
||
docker exec -it fabdash flask db upgrade
|
||
```
|
||
|
||
---
|
||
|
||
### Method 2 — Unraid Docker GUI (Manual Container)
|
||
|
||
Use this method if you have already built and pushed the FabDash image to a registry (Docker Hub or GHCR). If you are running from source, use Method 1.
|
||
|
||
#### Step 1 — Push image to a registry (on your dev machine)
|
||
|
||
```bash
|
||
docker build -t yourdockerhubuser/fabdash:latest .
|
||
docker push yourdockerhubuser/fabdash:latest
|
||
```
|
||
|
||
#### Step 2 — Add container via Unraid Docker tab
|
||
|
||
1. In Unraid, go to the **Docker** tab
|
||
2. Click **Add Container**
|
||
3. Switch to **Advanced View** (toggle top-right)
|
||
|
||
Fill in the fields:
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| **Name** | `fabdash` |
|
||
| **Repository** | `yourdockerhubuser/fabdash:latest` |
|
||
| **Network Type** | Bridge |
|
||
| **Port** | Host: `8080` → Container: `8080` (TCP) |
|
||
| **Path** | Host: `/mnt/user/appdata/fabdash/data` → Container: `/app/data` |
|
||
|
||
#### Step 3 — Add Environment Variables
|
||
|
||
Click **Add another Path, Port, Variable...** and add:
|
||
|
||
| Key | Value |
|
||
|---|---|
|
||
| `SECRET_KEY` | `your-strong-random-key` |
|
||
| `FLASK_ENV` | `production` |
|
||
| `DATABASE_URL` | `sqlite:////app/data/fabdash.db` |
|
||
|
||
#### Step 4 — Apply
|
||
|
||
Click **Apply**. Unraid will pull the image and start the container. Access at:
|
||
|
||
```
|
||
http://YOUR_UNRAID_IP:8080
|
||
```
|
||
|
||
#### Updating the Container (GUI method)
|
||
|
||
1. SSH into Unraid
|
||
2. Run: `docker pull yourdockerhubuser/fabdash:latest`
|
||
3. In the Docker tab, click the FabDash container icon → **Update**
|
||
|
||
---
|
||
|
||
### Data Persistence on Unraid
|
||
|
||
Your SQLite database is stored at:
|
||
|
||
```
|
||
/mnt/user/appdata/fabdash/data/fabdash.db
|
||
```
|
||
|
||
This path survives container restarts, image rebuilds, and Unraid reboots. Back it up with Unraid's **Appdata Backup** plugin or manually:
|
||
|
||
```bash
|
||
cp /mnt/user/appdata/fabdash/data/fabdash.db /mnt/user/backups/fabdash-$(date +%Y%m%d).db
|
||
```
|
||
|
||
---
|
||
|
||
## Local Development
|
||
|
||
Run backend and frontend separately to get Vite hot-module reloading:
|
||
|
||
**Terminal 1 — Flask:**
|
||
|
||
```bash
|
||
cd backend
|
||
python -m venv venv
|
||
source venv/bin/activate # Windows: venv\Scripts\activate
|
||
pip install -r requirements.txt
|
||
export FLASK_ENV=development
|
||
flask run --port 5000
|
||
```
|
||
|
||
**Terminal 2 — React:**
|
||
|
||
```bash
|
||
cd frontend
|
||
npm install
|
||
npm run dev # http://localhost:5173
|
||
```
|
||
|
||
Vite proxies `/api/*` calls to Flask on port 5000 automatically via `vite.config.js`.
|
||
|
||
---
|
||
|
||
## Environment Variables
|
||
|
||
| Variable | Default | Description |
|
||
|---|---|---|
|
||
| `SECRET_KEY` | *(required)* | Flask session secret — use a long random string |
|
||
| `FLASK_ENV` | `production` | Set to `development` for debug mode |
|
||
| `DATABASE_URL` | `sqlite:////app/data/fabdash.db` | Full SQLite path (4 slashes = absolute path) |
|
||
|
||
---
|
||
|
||
## Database Schema
|
||
|
||
```sql
|
||
CREATE TABLE projects (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
name TEXT NOT NULL,
|
||
color TEXT NOT NULL DEFAULT '#C9A84C',
|
||
description TEXT,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
CREATE TABLE deliverables (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||
title TEXT NOT NULL,
|
||
due_date DATE NOT NULL,
|
||
status TEXT NOT NULL DEFAULT 'upcoming'
|
||
CHECK(status IN ('upcoming','in_progress','completed','overdue')),
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
CREATE INDEX idx_deliverables_project ON deliverables(project_id);
|
||
CREATE INDEX idx_deliverables_due_date ON deliverables(due_date);
|
||
```
|
||
|
||
---
|
||
|
||
## Roadmap
|
||
|
||
### v1.0 — Core Release *(current)*
|
||
|
||
- [x] Dark/gold Tailwind design system
|
||
- [x] FullCalendar with Month / Week / Day views
|
||
- [x] Drag-and-drop deliverable rescheduling
|
||
- [x] Multi-deliverable project creation with inline rows
|
||
- [x] Add / Edit / Delete for projects and deliverables
|
||
- [x] Deliverable Focus View (slide-up drawer + horizontal timeline)
|
||
- [x] Active deliverable gold highlight in Focus View
|
||
- [x] Status badges (Upcoming / In Progress / Completed / Overdue)
|
||
- [x] Flask REST API + SQLite persistence
|
||
- [x] Cascade delete (project → deliverables)
|
||
- [x] Single Docker container deployment
|
||
- [x] Unraid installation guide (Terminal + GUI)
|
||
|
||
### v1.1 — Polish & UX
|
||
|
||
- [ ] Keyboard shortcuts (`N` = new project, `Esc` = close, arrow keys = calendar nav)
|
||
- [ ] 30-second undo toast for drag-and-drop moves
|
||
- [ ] Animated modal/drawer enter and exit transitions
|
||
- [ ] Hover tooltip on calendar events (preview without opening Focus View)
|
||
- [ ] Responsive layout with collapsible sidebar
|
||
- [ ] Empty state illustrations
|
||
|
||
### v1.2 — Calendar Enhancements
|
||
|
||
- [ ] Agenda sidebar showing all upcoming deliverables across projects
|
||
- [ ] Click empty date → pre-filled Add Deliverable modal with project selector
|
||
- [ ] Date range selection for bulk deliverable creation
|
||
- [ ] "Today" jump button
|
||
- [ ] Week numbers in calendar header
|
||
|
||
### v2.0 — Auth & Multi-user
|
||
|
||
- [ ] User login (Flask-Login + JWT)
|
||
- [ ] Multi-user support with project ownership
|
||
- [ ] Role-based access per project (Owner / Editor / Viewer)
|
||
- [ ] Activity log per project
|
||
- [ ] Comment threads on deliverables
|
||
|
||
### v2.1 — Notifications & Integrations
|
||
|
||
- [ ] In-app notification center for approaching due dates
|
||
- [ ] Email reminders at configurable intervals (Flask-Mail)
|
||
- [ ] iCal / Google Calendar export per project
|
||
- [ ] Slack webhook for deliverable status changes
|
||
- [ ] CSV import/export for bulk setup
|
||
|
||
### v2.2 — Advanced Views
|
||
|
||
- [ ] Gantt view alternate layout
|
||
- [ ] Kanban board (columns by status)
|
||
- [ ] Cross-project timeline view
|
||
- [ ] Workload heatmap showing deliverable density per day
|
||
- [ ] Archived projects with searchable history
|
||
|
||
### v3.0 — Intelligence Layer
|
||
|
||
- [ ] AI scheduling suggestions based on project cadence
|
||
- [ ] Conflict detection — flag overloaded days
|
||
- [ ] Natural language input ("Add final draft due next Friday to CODA")
|
||
|
||
---
|
||
|
||
*Built with intention. No subscriptions. No bloat. Just your fabrication workflow.*
|