Files
TKB_plan/web/docs/plans/2026-03-27-file-manager.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.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 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:

{
  "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