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>
5.2 KiB
File Manager + Diff Comparison Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Transform the app from single-schedule editor into a multi-file schedule manager with Excel import/export and visual diff comparison.
Architecture: Server stores multiple JSON schedule files in a schedules/ directory. Each file has metadata (name, created, modified). The UI gets a file list sidebar/header, open/save/save-as/delete operations, Excel import creates new files, Excel export from any file. Diff mode loads two files and renders an overlay showing changed cells.
Tech Stack: Express (file-based storage), React (existing), openpyxl (Excel), xlsx (client-side Excel read)
Task 1: Server — File Storage API
Files:
- Modify:
server.js
Step 1: Create schedules directory and migrate existing data
Add schedules/ directory. Each file is {id}.json with structure:
{
"id": "abc123",
"name": "HMG_Profylaxe_20260326_D6",
"createdAt": "2026-03-26T10:00:00Z",
"modifiedAt": "2026-03-27T14:00:00Z",
"data": { "dayIndex": [...], "stations": [...], "obstacles": [...], "dayComments": [...] }
}
Step 2: New API endpoints
Replace single GET/POST /api/schedule with:
GET /api/files— List all files (id, name, createdAt, modifiedAt — no data)GET /api/files/:id— Load single file with full dataPOST /api/files— Create new file (from JSON body or Excel import)PUT /api/files/:id— Update existing fileDELETE /api/files/:id— Delete filePOST /api/files/import-excel— Upload Excel, parse to JSON, create fileGET /api/files/:id/export-excel— Download file as Excel using templateGET /api/files/diff/:id1/:id2— Compute diff between two files, return changed cells
Keep old endpoints as aliases for backward compat (GET/POST /api/schedule → operates on a "current" file or the first file).
Step 3: Migration on first start
If saved_schedule.json exists but schedules/ is empty, migrate it as the first file.
Step 4: Diff computation
Diff endpoint compares two files cell by cell:
{
"added": [{"stationCode": "DE", "dayIdx": 100, "newValue": "k"}],
"removed": [{"stationCode": "DE", "dayIdx": 96, "oldValue": "k"}],
"changed": [{"stationCode": "HR", "dayIdx": 105, "oldValue": 14, "newValue": "Z"}]
}
Step 5: Commit
Task 2: UI — File List & Management
Files:
- Create:
src/FileManager.tsx - Modify:
src/App.tsx - Modify:
src/types.ts
Step 1: Add types
interface ScheduleFile {
id: string
name: string
createdAt: string
modifiedAt: string
}
interface ScheduleFileWithData extends ScheduleFile {
data: ScheduleData
}
Step 2: FileManager component
A top bar or panel showing:
- List of saved files (name, date modified)
- "Otevřít" (open) button per file
- "Smazat" (delete) button per file
- "Nahrát Excel" (upload Excel) button
- "Nový soubor" (new file) button
- Currently open file name shown prominently
- "Uložit" saves to current file
- "Uložit jako" (save as) creates new file
- Checkbox to select two files for comparison
Step 3: App.tsx changes
- Start with file list view (no schedule loaded)
- Opening a file loads data into the editor
- Save writes back to the same file ID
- "Save as" prompts for name, creates new file
- Back button returns to file list
Step 4: Commit
Task 3: Excel Import → New File
Files:
- Modify:
server.js(import endpoint) - Modify:
src/FileManager.tsx - Modify:
src/excelIO.ts
Step 1: Upload flow
FileManager has "Nahrát Excel" button → file picker → POST multipart to /api/files/import-excel → server parses with Python → creates new schedule file → returns file metadata → UI refreshes list.
Server-side parsing reuses the column mapping logic (col = idx + 7, rows 13-39 for stations). Also extract comments from DEN row.
Step 2: Commit
Task 4: Diff Comparison View
Files:
- Create:
src/DiffOverlay.tsx - Modify:
src/ScheduleTable.tsx - Modify:
src/App.tsx
Step 1: DiffOverlay component
When two files are selected for comparison, load both, compute diff, and render overlay on the table:
- Green background on cells that exist in current but not in comparison (added)
- Red background on cells that exist in comparison but not in current (removed)
- Yellow background on cells with different values (changed)
- Legend showing what colors mean
- Toggle to show/hide diff overlay
Step 2: Diff in ScheduleTable
Pass optional diffData prop to ScheduleTable. When present, each cell checks if it has a diff entry and renders the appropriate overlay color.
Step 3: Commit
Task 5: Excel Export per File
Files:
- Modify:
server.js - Modify:
export_excel.py
Step 1: Per-file export
GET /api/files/:id/export-excel loads the specific file's data and runs through the Python template exporter. File downloads with the schedule name in filename.
Step 2: Commit
Task 6: Deploy & Test
Step 1: Build and test locally Step 2: Deploy to copelk Step 3: Migrate existing data on copelk