Files
fabdash/README.md

487 lines
14 KiB
Markdown
Raw Normal View History

2026-03-05 11:53:28 -06:00
# FabDash
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
**Fabrication Dashboard** — A sleek, modern project management & scheduling application.
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
![Version](https://img.shields.io/badge/version-1.0.0-gold)
2026-03-05 11:53:28 -06:00
![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)
2026-03-05 11:59:14 -06:00
![Docker](https://img.shields.io/badge/deployment-Single%20Docker%20Container-blue)
2026-03-05 11:53:28 -06:00
---
## Table of Contents
- [Overview](#overview)
- [Tech Stack](#tech-stack)
- [Project Structure](#project-structure)
- [Features](#features)
- [API Reference](#api-reference)
2026-03-05 12:13:22 -06:00
- [Unraid Installation](#unraid-installation)
2026-03-05 12:20:22 -06:00
- [Updating FabDash on Unraid](#updating-fabdash-on-unraid)
2026-03-05 11:59:14 -06:00
- [Local Development](#local-development)
2026-03-05 11:53:28 -06:00
- [Environment Variables](#environment-variables)
- [Database Schema](#database-schema)
- [Roadmap](#roadmap)
2026-03-05 11:59:14 -06:00
2026-03-05 11:53:28 -06:00
---
## Overview
2026-03-05 12:20:22 -06:00
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.
2026-03-05 11:53:28 -06:00
---
## Tech Stack
2026-03-05 12:13:22 -06:00
| Layer | Technology |
|---|---|
| Frontend | React 18, Vite, Tailwind CSS |
| Calendar | FullCalendar v6 (daygrid, timegrid, interaction) |
2026-03-05 12:20:22 -06:00
| Focus View | Custom horizontal timeline (react-chrono) |
2026-03-05 12:13:22 -06:00
| State | Zustand |
| HTTP | Axios |
| Backend | Flask 3, Flask-SQLAlchemy, Flask-Migrate, Flask-CORS |
| Database | SQLite (persisted via Docker volume) |
| Server | Gunicorn (production) |
2026-03-05 11:53:28 -06:00
---
## Project Structure
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
fabdash/
2026-03-05 11:59:14 -06:00
├── Dockerfile
├── docker-compose.yml
2026-03-05 11:53:28 -06:00
├── .env.example
├── .gitignore
2026-03-05 11:59:14 -06:00
├── README.md
├── backend/
│ ├── run.py
│ ├── config.py
│ ├── requirements.txt
│ └── app/
│ ├── __init__.py
│ ├── extensions.py
│ ├── models.py
│ └── routes/
2026-03-05 12:13:22 -06:00
│ ├── __init__.py
2026-03-05 11:59:14 -06:00
│ ├── projects.py
│ └── deliverables.py
└── frontend/
├── package.json
├── vite.config.js
├── tailwind.config.js
2026-03-05 12:13:22 -06:00
├── postcss.config.js
2026-03-05 11:59:14 -06:00
├── index.html
└── src/
├── main.jsx
├── App.jsx
├── api/
│ ├── projects.js
│ └── deliverables.js
├── components/
│ ├── Calendar/
2026-03-05 12:13:22 -06:00
│ │ └── MainCalendar.jsx
2026-03-05 11:59:14 -06:00
│ ├── Projects/
│ │ ├── ProjectList.jsx
│ │ ├── ProjectCard.jsx
│ │ └── ProjectModal.jsx
│ ├── Deliverables/
2026-03-05 12:13:22 -06:00
│ │ └── DeliverableModal.jsx
2026-03-05 11:59:14 -06:00
│ ├── 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
```
2026-03-05 11:53:28 -06:00
---
2026-03-05 12:13:22 -06:00
## Features
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
- **Large calendar view** — Month, Week, and Day modes via FullCalendar
- **Drag-and-drop** — Move deliverables to new dates; backend updates instantly
2026-03-05 12:20:22 -06:00
- **Multi-deliverable projects** — Unlimited deliverables per project, each with its own due date and status
- **Color-coded projects** — 12-swatch palette + custom hex input
- **Deliverable Focus View** — Click any calendar event to open a slide-up drawer with the full project timeline; clicked deliverable highlighted in gold
- **Status tracking** — Upcoming / In Progress / Completed / Overdue badges
- **Dark/gold theme** — Dark surfaces throughout with gold as the primary accent
- **Full persistence** — SQLite via Flask-SQLAlchemy, mounted as a Docker volume
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
---
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
## API Reference
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
### Projects
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
| Method | Endpoint | Description |
|---|---|---|
| `GET` | `/api/projects` | List all projects with nested deliverables |
2026-03-05 12:20:22 -06:00
| `POST` | `/api/projects` | Create project (with optional inline deliverables) |
2026-03-05 12:13:22 -06:00
| `GET` | `/api/projects/:id` | Get single project |
| `PATCH` | `/api/projects/:id` | Update name, color, or description |
| `DELETE` | `/api/projects/:id` | Delete project + cascade deliverables |
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
### Deliverables
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
| 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 |
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
---
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
## Unraid Installation
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
FabDash is installed by cloning the repo and building the Docker image locally on your Unraid server via SSH, then registering and managing the container through the Unraid Docker GUI. This gives you full GUI control (start, stop, logs, edit) while keeping the image local.
2026-03-05 11:53:28 -06:00
---
2026-03-05 12:20:22 -06:00
### Step 1 — Enable SSH on Unraid
2026-03-05 12:13:22 -06:00
2026-03-05 12:20:22 -06:00
Go to **Settings → Management Access** and confirm SSH is enabled. Note your Unraid server's local IP address (visible on the Unraid dashboard header).
2026-03-05 12:13:22 -06:00
2026-03-05 12:20:22 -06:00
---
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
### Step 2 — SSH into Unraid and Clone the Repo
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
Open a terminal on your local machine and connect:
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
```bash
ssh root@YOUR_UNRAID_IP
2026-03-05 11:59:14 -06:00
```
2026-03-05 12:13:22 -06:00
2026-03-05 12:20:22 -06:00
Clone FabDash into your appdata share:
2026-03-05 12:13:22 -06:00
```bash
cd /mnt/user/appdata
git clone https://github.com/yourname/fabdash.git
cd fabdash
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
---
### Step 3 — Build the Docker Image Locally
This command builds the image on your Unraid server and tags it as `fabdash:latest`.
The first build takes 35 minutes (downloads Node + Python layers, compiles React).
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
```bash
2026-03-05 12:20:22 -06:00
docker build -t fabdash:latest .
2026-03-05 12:13:22 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
When complete, verify the image exists:
2026-03-05 11:59:14 -06:00
2026-03-05 12:20:22 -06:00
```bash
docker images | grep fabdash
# fabdash latest abc123def456 1 minute ago ...
2026-03-05 12:13:22 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
---
### Step 4 — Create the Data Directory
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
Create the persistent directory where SQLite will store your database:
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
```bash
2026-03-05 12:20:22 -06:00
mkdir -p /mnt/user/appdata/fabdash/data
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
---
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
### Step 5 — Add the Container via Unraid Docker GUI
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
1. In the Unraid web UI, go to the **Docker** tab
2. At the bottom, click **Add Container**
3. In the top-right of the form, toggle to **Advanced View**
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
Fill in the fields exactly as follows:
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
#### Basic Settings
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
| Field | Value |
|---|---|
| **Name** | `fabdash` |
| **Repository** | `fabdash:latest` |
| **Docker Hub URL** | *(leave blank — local image)* |
| **Network Type** | `Bridge` |
| **Console shell command** | `bash` |
| **Privileged** | `Off` |
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
#### Port Mapping
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
Click **Add another Path, Port, Variable, Label or Device** → select **Port**:
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
| Field | Value |
|---|---|
| **Name** | `Web UI` |
| **Container Port** | `8080` |
| **Host Port** | `8080` |
| **Connection Type** | `TCP` |
2026-03-05 12:13:22 -06:00
2026-03-05 12:20:22 -06:00
> Access FabDash at `http://YOUR_UNRAID_IP:8080` after starting the container.
> Change Host Port if `8080` is already in use on your server.
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
#### Volume / Path Mapping
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
Click **Add another Path, Port, Variable, Label or Device** → select **Path**:
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
| Field | Value |
|---|---|
| **Name** | `AppData` |
| **Container Path** | `/app/data` |
| **Host Path** | `/mnt/user/appdata/fabdash/data` |
| **Access Mode** | `Read/Write` |
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
> This is where `fabdash.db` will live. Data persists across all container restarts and rebuilds.
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
#### Environment Variables
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
Click **Add another Path, Port, Variable, Label or Device** → select **Variable** for each:
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
| Name | Key | Value |
|---|---|---|
| Secret Key | `SECRET_KEY` | `your-strong-random-secret-key-here` |
| Flask Environment | `FLASK_ENV` | `production` |
| Database URL | `DATABASE_URL` | `sqlite:////app/data/fabdash.db` |
> **SECRET_KEY** — Use a long random string. Generate one with:
> ```bash
> cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 48 | head -n 1
> ```
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
#### Extra Parameters (optional)
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
| Field | Value |
|---|---|
2026-03-05 12:20:22 -06:00
| **Extra Parameters** | `--restart unless-stopped` |
2026-03-05 11:59:14 -06:00
2026-03-05 12:20:22 -06:00
---
2026-03-05 11:59:14 -06:00
2026-03-05 12:20:22 -06:00
### Step 6 — Apply and Start
2026-03-05 11:59:14 -06:00
2026-03-05 12:20:22 -06:00
Click **Apply** at the bottom of the form. Unraid will register and start the container using your locally built image.
2026-03-05 11:59:14 -06:00
2026-03-05 12:20:22 -06:00
Navigate to the **Docker** tab — you should see `fabdash` running with a green indicator.
2026-03-05 11:59:14 -06:00
2026-03-05 12:20:22 -06:00
Open your browser:
2026-03-05 11:59:14 -06:00
```
2026-03-05 12:13:22 -06:00
http://YOUR_UNRAID_IP:8080
2026-03-05 11:59:14 -06:00
```
2026-03-05 12:20:22 -06:00
---
### Step 7 — Verify (Optional)
Check container logs from the Unraid Docker tab by clicking the `fabdash` container icon → **Logs**, or via SSH:
```bash
docker logs fabdash --tail 50
```
A healthy startup looks like:
```
[INFO] Starting gunicorn 23.0.0
[INFO] Listening at: http://0.0.0.0:8080
[INFO] Worker booting (pid: ...)
```
---
## Updating FabDash on Unraid
When a new version is pushed to GitHub, update FabDash in three steps:
### Step 1 — Pull the latest code and rebuild
SSH into Unraid:
```bash
ssh root@YOUR_UNRAID_IP
cd /mnt/user/appdata/fabdash
git pull
docker build -t fabdash:latest .
```
### Step 2 — Restart the container via Unraid GUI
1. Go to the **Docker** tab in Unraid
2. Click the `fabdash` container icon
3. Select **Restart**
The container will stop, reload with the newly built image, and come back up. Your database is untouched.
### Step 3 — Verify
2026-03-05 11:59:14 -06:00
2026-03-05 12:20:22 -06:00
```bash
docker logs fabdash --tail 20
```
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
---
2026-03-05 11:59:14 -06:00
2026-03-05 12:20:22 -06:00
## Data Backup
2026-03-05 11:59:14 -06:00
2026-03-05 12:20:22 -06:00
Your database lives at:
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
```
/mnt/user/appdata/fabdash/data/fabdash.db
2026-03-05 11:59:14 -06:00
```
2026-03-05 12:20:22 -06:00
**Manual backup:**
2026-03-05 11:59:14 -06:00
```bash
2026-03-05 12:20:22 -06:00
cp /mnt/user/appdata/fabdash/data/fabdash.db \
/mnt/user/backups/fabdash-$(date +%Y%m%d-%H%M).db
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
**Automated backup** — Use the **Appdata Backup/Restore** plugin from Unraid Community Applications to schedule regular backups of `/mnt/user/appdata/fabdash/`.
2026-03-05 11:53:28 -06:00
---
2026-03-05 11:59:14 -06:00
## Local Development
2026-03-05 12:20:22 -06:00
Run backend and frontend separately for Vite hot-module reloading:
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
**Terminal 1 — Flask:**
2026-03-05 11:59:14 -06:00
```bash
2026-03-05 11:53:28 -06:00
cd backend
2026-03-05 11:59:14 -06:00
python -m venv venv
2026-03-05 12:20:22 -06:00
source venv/bin/activate # Windows: venv\Scripts\activate
2026-03-05 11:59:14 -06:00
pip install -r requirements.txt
2026-03-05 12:13:22 -06:00
export FLASK_ENV=development
2026-03-05 11:53:28 -06:00
flask run --port 5000
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
**Terminal 2 — React:**
2026-03-05 11:59:14 -06:00
```bash
2026-03-05 11:53:28 -06:00
cd frontend
2026-03-05 11:59:14 -06:00
npm install
2026-03-05 12:20:22 -06:00
npm run dev # http://localhost:5173
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:20:22 -06:00
Vite proxies all `/api/*` calls to Flask on port 5000 automatically via `vite.config.js`. No CORS issues in dev.
2026-03-05 11:53:28 -06:00
---
## Environment Variables
2026-03-05 12:20:22 -06:00
| Variable | Required | Default | Description |
|---|---|---|---|
| `SECRET_KEY` | Yes | — | Flask session secret. Use a long random string |
| `FLASK_ENV` | No | `production` | Set to `development` for debug mode |
| `DATABASE_URL` | No | `sqlite:////app/data/fabdash.db` | SQLite path (4 slashes = absolute path) |
2026-03-05 11:53:28 -06:00
---
## Database Schema
2026-03-05 11:59:14 -06:00
```sql
2026-03-05 11:53:28 -06:00
CREATE TABLE projects (
2026-03-05 11:59:14 -06:00
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
color TEXT NOT NULL DEFAULT '#C9A84C',
2026-03-05 11:53:28 -06:00
description TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE deliverables (
2026-03-05 11:59:14 -06:00
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')),
2026-03-05 11:53:28 -06:00
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
2026-03-05 11:59:14 -06:00
CREATE INDEX idx_deliverables_project ON deliverables(project_id);
2026-03-05 11:53:28 -06:00
CREATE INDEX idx_deliverables_due_date ON deliverables(due_date);
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
---
## Roadmap
2026-03-05 12:13:22 -06:00
### v1.0 — Core Release *(current)*
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
- [x] Dark/gold Tailwind design system
- [x] FullCalendar with Month / Week / Day views
2026-03-05 11:53:28 -06:00
- [x] Drag-and-drop deliverable rescheduling
2026-03-05 12:13:22 -06:00
- [x] Multi-deliverable project creation with inline rows
2026-03-05 11:59:14 -06:00
- [x] Add / Edit / Delete for projects and deliverables
2026-03-05 12:20:22 -06:00
- [x] Deliverable Focus View — slide-up drawer with horizontal timeline
2026-03-05 12:13:22 -06:00
- [x] Active deliverable gold highlight in Focus View
2026-03-05 11:53:28 -06:00
- [x] Status badges (Upcoming / In Progress / Completed / Overdue)
2026-03-05 12:13:22 -06:00
- [x] Flask REST API + SQLite persistence
2026-03-05 11:53:28 -06:00
- [x] Cascade delete (project → deliverables)
2026-03-05 12:13:22 -06:00
- [x] Single Docker container deployment
2026-03-05 12:20:22 -06:00
- [x] Unraid installation — local build + Docker GUI management
2026-03-05 11:53:28 -06:00
### v1.1 — Polish & UX
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
- [ ] Keyboard shortcuts (`N` = new project, `Esc` = close, arrow keys = calendar nav)
- [ ] 30-second undo toast for drag-and-drop moves
2026-03-05 12:20:22 -06:00
- [ ] Animated modal/drawer transitions
2026-03-05 12:13:22 -06:00
- [ ] Hover tooltip on calendar events (preview without opening Focus View)
- [ ] Responsive layout with collapsible sidebar
- [ ] Empty state illustrations
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
### v1.2 — Calendar Enhancements
2026-03-05 11:59:14 -06:00
- [ ] Agenda sidebar showing all upcoming deliverables across projects
- [ ] Date range selection for bulk deliverable creation
2026-03-05 12:13:22 -06:00
- [ ] "Today" jump button
- [ ] Week numbers in calendar header
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
### v2.0 — Auth & Multi-user
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
- [ ] User login (Flask-Login + JWT)
- [ ] Multi-user support with project ownership
2026-03-05 11:59:14 -06:00
- [ ] Role-based access per project (Owner / Editor / Viewer)
2026-03-05 12:20:22 -06:00
- [ ] Activity log and comment threads per deliverable
2026-03-05 11:53:28 -06:00
### v2.1 — Notifications & Integrations
2026-03-05 11:59:14 -06:00
2026-03-05 11:53:28 -06:00
- [ ] In-app notification center for approaching due dates
2026-03-05 12:13:22 -06:00
- [ ] Email reminders at configurable intervals (Flask-Mail)
2026-03-05 12:20:22 -06:00
- [ ] iCal / Google Calendar export
2026-03-05 12:13:22 -06:00
- [ ] Slack webhook for deliverable status changes
2026-03-05 12:20:22 -06:00
- [ ] CSV import/export
2026-03-05 11:53:28 -06:00
### v2.2 — Advanced Views
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
- [ ] Gantt view alternate layout
- [ ] Kanban board (columns by status)
- [ ] Cross-project timeline view
2026-03-05 12:20:22 -06:00
- [ ] Workload heatmap
2026-03-05 11:53:28 -06:00
### v3.0 — Intelligence Layer
2026-03-05 11:59:14 -06:00
2026-03-05 12:20:22 -06:00
- [ ] AI scheduling suggestions
- [ ] Conflict detection for overloaded days
- [ ] Natural language deliverable input
2026-03-05 11:53:28 -06:00
---
*Built with intention. No subscriptions. No bloat. Just your fabrication workflow.*