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>
172 lines
5.2 KiB
Markdown
172 lines
5.2 KiB
Markdown
# 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:
|
|
```json
|
|
{
|
|
"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 data
|
|
- `POST /api/files` — Create new file (from JSON body or Excel import)
|
|
- `PUT /api/files/:id` — Update existing file
|
|
- `DELETE /api/files/:id` — Delete file
|
|
- `POST /api/files/import-excel` — Upload Excel, parse to JSON, create file
|
|
- `GET /api/files/:id/export-excel` — Download file as Excel using template
|
|
- `GET /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:
|
|
```json
|
|
{
|
|
"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**
|
|
|
|
```typescript
|
|
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**
|