Commit Graph

5 Commits

Author SHA1 Message Date
Benjamin Admin bf5ea860cc Phase 7: pinning, plan versions, solver budget + UX polish
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 37s
CI / test-go-edu-search (push) Successful in 29s
CI / test-python-klausur (push) Failing after 3m56s
CI / test-python-agent-core (push) Successful in 19s
CI / test-nodejs-website (push) Successful in 23s
Backend (school-service):
  - tt_solution gains parent_solution_id (self-FK, ON DELETE SET NULL)
    and seconds_limit columns via ALTER TABLE IF NOT EXISTS.
  - CreateTimetableSolutionRequest accepts optional parent_solution_id
    and seconds_limit (5-600s) with binding validation.
  - CreateSolution checks parent ownership before INSERT so users can't
    fork another tenant's plan.
  - New PUT /timetable/lessons/:id/pin endpoint; ownership enforced via
    the lesson's solution.created_by_user_id JOIN.

Solver:
  - Lesson.pinned now carries @PlanningPin so Timefold leaves locked
    cells untouched during the search.
  - build_problem() takes optional parent_solution_id; if set, copies
    pinned (class_id, subject_id, day, period, room) tuples onto fresh
    Lesson objects via greedy first-fit matching. Surplus pinned rows
    from curriculum changes are silently dropped.
  - _build_factory(seconds) replaces the module-level factory so each
    job honours its tt_solution.seconds_limit override.
  - persist_solution writes lesson.pinned back so subsequent re-solves
    inherit it.

Frontend (studio-v2):
  - SolutionList grows three knobs in the create-form: Basieren auf
    (parent dropdown, only completed solutions, disabled when none),
    Sekunden-Limit (5-600), and the existing Name.
  - PlanView cells get a pin/unpin button with optimistic update and
    rollback on error. Pinned cells gain an amber ring.
  - types.ts + api.ts mirror the new fields; lessonsApi.pin(id, bool).
  - HelpPanel: collapsible 6-step Bedienungsanleitung explaining the
    setup-to-plan workflow. Anchored at the top of /stundenplan above
    the dev token banner.
  - page.tsx switches to the same gradient + animated-blob background
    used on /korrektur so /stundenplan stops looking like a slate-900
    test page.
  - JWT dev banner gets a step-by-step explanation of how to grab the
    token from DevTools and a non-blocking success indicator (no more
    alert()).

Tests:
  - school-service: 6 new validator cases for parent_solution_id +
    seconds_limit boundaries. 73 subtests total, all green.
  - studio-v2: mockSchoolApi adds PUT /lessons/:id/pin route. 5 new
    Playwright tests across two suites (parent-selector visibility +
    options, seconds-limit input, pin button render, pin-icon flip).
    Existing tests adjusted to the new help panel + JWT banner wording.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 08:19:39 +02:00
Benjamin Admin 612ecec6d9 Phase 6: Plan-Ansicht — solution list + weekly grid view
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 27s
CI / test-go-edu-search (push) Successful in 29s
CI / test-python-klausur (push) Failing after 3m18s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 23s
Frontend additions in studio-v2:
  - types.ts adds TimetableSolution, TimetableLesson, SolutionStatus,
    CreateTimetableSolution mirroring the Go models.
  - lib/stundenplan/api.ts adds solutionsApi with list/get/create/remove/
    lessons. Solve trigger is POST /timetable/solutions — school-service
    forwards to the solver-service over the Docker network.
  - _components/plan/SolutionList: table of past solves with status
    badges, hard/soft score, Anzeigen + Loeschen buttons, and a
    'Neuen Plan generieren' trigger. Auto-polls every 4 s while any
    solution is pending/running, clears the interval otherwise.
  - _components/plan/PlanView: Mo–Fr × period weekly grid. Three
    perspectives (Klasse / Lehrer / Raum) toggleable via test-id'd
    buttons; selector below lists every unique resource with at least
    one lesson. Cells colour-coded by tt_subject.color.
  - _components/plan/PlanHub orchestrates list + view; default tab in
    page.tsx switches from 'klassen' to 'plan'.

Tests:
  - mockSchoolApi helper extracted to e2e/_helpers.ts so the spec file
    stays under 500 LOC. Helper now also mocks /solutions GET/POST/DELETE
    and /solutions/:id/lessons; solutions kept in a closure so POST
    appears in the next GET.
  - 8 new tests across two suites: SolutionList empty state, list
    render, completed-vs-failed Anzeigen visibility, solve trigger;
    PlanView placeholder when no selection, grid render, perspective
    switching.
  - Existing Klassen CRUD tests now click the Klassen tab first
    (Plan is the new default landing tab).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 01:03:55 +02:00
Benjamin Admin c2c09e1cd9 Stundenplan Phase 3c: complete Stammdaten + RegelnHub with 4 editors
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 31s
CI / test-go-edu-search (push) Successful in 30s
CI / test-python-klausur (push) Failing after 3m31s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 22s
Frontend additions in studio-v2:
  - PeriodsManager renders the weekly grid as a Mo–So table with one
    row per period_index. New entries auto-increment period_index so
    the user can hit Anlegen repeatedly for a full day's slots.
  - CurriculumManager joins classes + subjects; new entries refuse to
    open when either prerequisite list is empty (banner instead).
  - AssignmentsManager joins teacher × class × subject with the same
    prerequisite-banner pattern.
  - regeln/RegelnHub: vertical sidebar grouping all 15 constraint
    types by parent entity (Lehrer/Fach/Klasse/Raum). Implemented
    editors are clickable, the other 11 are visibly disabled with
    a 'soon' tag.
  - Three new editors:
      TeacherUnavailableWindowEditor (time-window pattern),
      SubjectMaxConsecutiveEditor (number-input pattern),
      SubjectPreferredPeriodEditor (number range pattern).
  - page.tsx wires every tab to its manager; the not-implemented
    placeholder is gone (no more empty tabs).

Test coverage:
  - e2e/stundenplan.spec.ts rewritten: 23 tests across 7 suites,
    covering all 8 tabs, the new managers' prerequisite banners,
    sub-tab switching in the RegelnHub, and the disabled state of
    not-yet-implemented constraint rules. Each test mocks the
    backend via page.route() so the suite stays hermetic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 23:08:15 +02:00
Benjamin Admin 73636f76a2 Stundenplan Phase 3b: 3 more Stammdaten managers, first constraint editor, full test coverage
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 30s
CI / test-go-edu-search (push) Successful in 30s
CI / test-python-klausur (push) Failing after 3m6s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 21s
Frontend additions in studio-v2:
  - LehrerManager / FaecherManager / RaeumeManager — same CRUD pattern as
    Klassen, with entity-specific form fields and table columns.
  - regeln/TeacherUnavailableDayEditor — first constraint editor, joins
    against teachersApi to render a readable name in the dropdown and
    list. Falls back to a guidance banner when no teachers exist yet.
  - page.tsx wires up the new tabs; data-testid attributes added across
    managers so the Playwright suite can target them deterministically.

Tests:
  - school-service: timetable_constraints_more_test.go fills the
    remaining 9 constraint DTOs (TeacherMaxHoursDay/Week,
    TeacherExcludedSubject/Room, SubjectMinDayGap,
    SubjectContiguousWhenRepeated, SubjectDoubleLesson, ClassNoGaps,
    RoomRequiresType). 66 subtests total, all green.
  - studio-v2: e2e/stundenplan.spec.ts covers the page shell, tab
    navigation, Klassen CRUD with mocked backend, constraint editor's
    empty-teacher fallback, sidebar entry. All school-service calls
    intercepted via page.route() so the suite is hermetic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 22:44:39 +02:00
Benjamin Admin f21ecf293b Add Stundenplan frontend scaffolding in studio-v2
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 31s
CI / test-go-edu-search (push) Successful in 29s
CI / test-python-klausur (push) Failing after 2m36s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 22s
Phase 3 — initial UI for the timetable scheduler:
  - app/stundenplan/page.tsx with tab navigation (Klassen / Lehrer /
    Faecher / Raeume / Zeitraster / Stundentafel / Lehrauftraege /
    Regeln) and a dev-mode JWT entry to authenticate against
    school-service until full auth is wired up.
  - app/stundenplan/_components/KlassenManager.tsx as the working
    prototype for one entity (list / create / delete). Pattern can be
    copied for the other 6 stammdaten + 15 constraint editors.
  - lib/stundenplan/api.ts exposing typed clients for all 22 endpoints
    (7 stammdaten + 15 constraint tables). Constraints use a factory
    to keep the file tight.
  - app/api/school/[...path]/route.ts proxies the browser through
    Next.js to school-service so HTTPS studio-v2 can reach the plain
    HTTP backend.
  - Sidebar.tsx gains a Stundenplan entry with 26-language labels.
  - docker-compose.yml exposes SCHOOL_SERVICE_URL to studio-v2 and
    declares the school-service dependency.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 22:25:18 +02:00