Files
TKB_plan/CLAUDE.md
Docker Config Backup b4158d687f feat: TKB shift scheduler — personnel shift planning web app
Full rewrite of METRO HMG for TKB tunnel department:
- People-based grid (18 TKB + 5 IT), year-long calendar
- Color-coded shift values (4/6/8/12/A/B/D/N/U/O)
- Drag-and-drop cells, multi-cell selection (click/ctrl/shift/drag)
- Right-click context menu with color palette
- Tunnel closure + Metro + D8 info rows (toggleable)
- Czech holidays highlighted with names
- PDF export (2-page A4 landscape, DejaVu font for Czech chars)
- Improvement proposals system
- Sticky headers (vertical + horizontal scroll)
- Cell value filter toggles in legend

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 09:48:38 +02:00

5.1 KiB
Raw Blame History

TKB HMG — Tunnel Maintenance Schedule Manager

This is a spinoff of the METRO HMG project (Prague metro station maintenance scheduling). Adapted for Prague car tunnels (TKB) maintenance department.

Origin

Copied from /home/klas/Prace/METRO/web/ — a fully working schedule management web app.

Architecture

Tech Stack

  • Frontend: React 19 + TypeScript + Vite + Tailwind CSS
  • Backend: Express (Node.js), file-based JSON storage
  • Excel: openpyxl (Python, server-side export/import), xlsx (client-side import)
  • Port: 3080 (change in web/server.js)

Key Files

web/
├── server.js                 # Express API server (ES modules)
├── export_excel.py           # Python: JSON → Excel using template
├── import_excel.py           # Python: Excel → JSON
├── deploy.sh                 # Deploy script (rsync to remote)
├── watch-deploy.js           # Auto-deploy on file changes
├── public/
│   └── template.xlsx         # Excel template for export formatting
├── src/
│   ├── App.tsx               # Main app: login → file manager → editor
│   ├── FileManager.tsx       # File list, upload, compare, delete
│   ├── ScheduleTable.tsx     # Main schedule grid (largest component)
│   ├── useScheduleState.ts   # State management: stations, obstacles, comments
│   ├── useDragBlock.ts       # Drag-and-drop logic for blocks and s/v cells
│   ├── blockParser.ts        # Parse k+14+Z indivisible blocks
│   ├── constraints.ts        # Validation: max k/night, max 5 evaluations
│   ├── ContextMenu.tsx       # Right-click menu (obstacles, comments, s/v)
│   ├── Toolbar.tsx           # Filter toggles, save, undo, compare banner
│   ├── Login.tsx             # Simple client-side auth
│   ├── excelIO.ts            # Client-side Excel import (xlsx library)
│   ├── types.ts              # All TypeScript interfaces
│   └── data.json             # Default/fallback schedule data
└── schedules/                # Server-stored JSON schedule files

API Endpoints (server.js)

  • GET /api/files — List all schedule files (metadata only)
  • GET /api/files/:id — Load single file with full data
  • POST /api/files — Create new file { name, data }
  • PUT /api/files/:id — Update file { name?, data }
  • DELETE /api/files/:id — Delete file
  • POST /api/files/import-excel — Upload .xlsx, parse to JSON, create file
  • GET /api/files/:id/export-excel — Download as Excel using template
  • GET /api/files/diff/:id1/:id2 — Cell-by-cell diff between two files

Data Model

ScheduleData {
  dayIndex: DayInfo[]           // Array of day metadata (idx, day, month, year, week, weekend)
  stations: Station[]           // 27 stations, each with data: Record<string, CellValue>
  obstacles?: Obstacle[]        // Per-cell blocking issues (hatched red overlay)
  dayComments?: DayComment[]    // DEN row comments (hatched blue column overlay)
  cellComments?: CellComment[]  // Per-cell comments (blue triangle indicator)
}

Cell values: s (physical servers), v (virtual servers), k (on-site work), 14 (evaluation days), Z (processing)

Key Concepts

  • dayIndex.idx values are NOT array indices — they're offsets from the Excel column mapping (col = idx + 7)
  • Indivisible block: k + 14×"14" + 5×"Z" = 20 cells that move as one unit
  • s and v cells are independent, can be dragged separately, can have multiple per station
  • Holidays are hardcoded in useScheduleState.ts as HOLIDAYS Map
  • Constraints: max 1 k/night, max 5 stations in "14"+"Z" simultaneously
  • Ghost blocks: comparison overlay shows old positions as dashed semi-transparent blocks

Running

cd web
npm install
npx vite build
node server.js          # Production: serves dist/ on port 3080
# OR
npm run dev             # Dev: Vite HMR on port 5173, proxies /api to 3080

Auth

  • Username: metro, Password: colsys (client-side only, in Login.tsx)
  • Change these for TKB deployment

Deploying to Remote

./deploy.sh             # Builds, rsyncs to remote, restarts pm2

Edit deploy.sh to set the remote host. Uses pm2 for process management.

Excel Template

  • public/template.xlsx — the original Excel schedule format
  • Export writes data into this template, preserving formatting
  • Replace with TKB's own template

What to Customize for TKB

  1. Station list — Change station codes/names in data.json and STATION_ROWS in export_excel.py and server.js
  2. Excel template — Replace public/template.xlsx with TKB's schedule format
  3. Holidays — Update HOLIDAYS Map in useScheduleState.ts
  4. Constraints — Adjust rules in constraints.ts (may differ for tunnels)
  5. Phase labels — Update PHASE_LABELS in Toolbar.tsx and getCellColor in ScheduleTable.tsx
  6. Login credentials — Change in Login.tsx
  7. App title — Change in index.html and header in App.tsx
  8. Port — Change PORT in server.js
  9. Deploy target — Update REMOTE in deploy.sh