Files
fabdash/README.md
2026-03-05 12:13:22 -06:00

455 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FabDash
**Fabrication Dashboard** — A sleek, modern project management & scheduling application.
![Version](https://img.shields.io/badge/version-1.0.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)
- [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 24 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.*