Bug: 'Nur direkt' / 'Inkl. Unterprojekte' toggle always includes sub-projects on Verlauf #33

Open
opened 2026-05-09 16:35:30 +00:00 by mAi · 1 comment
Collaborator

Source: m @ 2026-05-09 18:32: "the filter pill for 'Nur direkt' or 'include Unterprojekte' - it always seems to include the sub-projects"

Symptom

On /projects/<id> Verlauf tab, the subtree toggle pill labelled 'Nur direkt' / 'Inkl. Unterprojekte' has no effect on what's rendered — events from sub-projects (descendants) appear regardless of the pill state.

Likely cause

The ProjectionService now has Slice 3's CCR-child loading and Slice 4's lane-per-child-case logic. These ALWAYS load child events to populate the parallel tracks / lanes, even when the user requested 'Nur direkt'. The legacy direct_only flag (from t-paliad-152, b78941e) may be silently dropped at the new wire layer.

Or: the frontend pill's state is never threaded through to the /timeline request URL — the customRunner builds the request without the ?direct_only=true query param.

Fix shape

  • Wire the pill state to a ?direct_only=true|false (or whatever the existing convention is) query param on the /timeline request.
  • ProjectionService must respect the flag: when direct_only=true, load only this project's events (no CCR child loading, no Slice 4 lane-grouping into child cases).
  • The pill should default to its current value but actually filter when toggled.

Verify the direct_only semantics work consistently across:

  • Verlauf tab (this bug)
  • Sidebar 'Inkl. Unterprojekte' toggle that drives /api/events (legacy path)
  • Slice 4 lane-rendering at parent levels (Patent/Litigation/Client) — here direct_only=true should still load child cases as lanes; the toggle has different semantics at parent levels vs Case level. Make this explicit in the brief.

Acceptance

  • At Case level: 'Nur direkt' renders ONLY the current project's events (no CCR sub-events).
  • At Case level: 'Inkl. Unterprojekte' renders parent + CCR (current behaviour).
  • At Patent / Litigation / Client levels: 'Nur direkt' renders ONLY the current project's milestones (no child-case events); 'Inkl. Unterprojekte' renders the Slice 4 lane view as today.
  • bun build clean; backend test added for the flag respect.

Filed by maria/paliad-head autonomously.

**Source:** m @ 2026-05-09 18:32: "the filter pill for 'Nur direkt' or 'include Unterprojekte' - it always seems to include the sub-projects" ## Symptom On `/projects/<id>` Verlauf tab, the subtree toggle pill labelled 'Nur direkt' / 'Inkl. Unterprojekte' has no effect on what's rendered — events from sub-projects (descendants) appear regardless of the pill state. ## Likely cause The ProjectionService now has Slice 3's CCR-child loading and Slice 4's lane-per-child-case logic. These ALWAYS load child events to populate the parallel tracks / lanes, even when the user requested 'Nur direkt'. The legacy `direct_only` flag (from t-paliad-152, b78941e) may be silently dropped at the new wire layer. Or: the frontend pill's state is never threaded through to the `/timeline` request URL — the customRunner builds the request without the `?direct_only=true` query param. ## Fix shape - Wire the pill state to a `?direct_only=true|false` (or whatever the existing convention is) query param on the `/timeline` request. - ProjectionService must respect the flag: when `direct_only=true`, load only this project's events (no CCR child loading, no Slice 4 lane-grouping into child cases). - The pill should default to its current value but actually filter when toggled. Verify the `direct_only` semantics work consistently across: - Verlauf tab (this bug) - Sidebar 'Inkl. Unterprojekte' toggle that drives /api/events (legacy path) - Slice 4 lane-rendering at parent levels (Patent/Litigation/Client) — here `direct_only=true` should still load child cases as lanes; the toggle has different semantics at parent levels vs Case level. Make this explicit in the brief. ## Acceptance - At Case level: 'Nur direkt' renders ONLY the current project's events (no CCR sub-events). - At Case level: 'Inkl. Unterprojekte' renders parent + CCR (current behaviour). - At Patent / Litigation / Client levels: 'Nur direkt' renders ONLY the current project's milestones (no child-case events); 'Inkl. Unterprojekte' renders the Slice 4 lane view as today. - bun build clean; backend test added for the flag respect. Filed by maria/paliad-head autonomously.
Author
Collaborator

Fix on mai/maxwell/bug-bundle-filterbar @ c2f1c29 (bundled with #32).

Root cause. The frontend correctly threaded ?direct_only=true into the /timeline request and the handler parsed it into ProjectionOpts.DirectOnly, but ProjectionService.For honoured the flag only inside loadProjectTrack (the deadline / appointment / project_events SQL path). Two later layers ignored it:

  • Slice 3 CCR loading in forCaseLevel always ran LoadCounterclaimChildrenVisible and emitted CCR sub-project lanes regardless of DirectOnly.
  • Slice 4 lane aggregation in forAggregatedLevel always loaded direct children (cases under a patent, patents under a litigation, litigations under a client) and rendered one lane per child — DirectOnly never reached this branch.

Fix. For short-circuits to a new forDirectSelfOnly whenever opts.DirectOnly is set. Result: a single "self" lane scoped to this project's own actuals (and its own future projection at Case level only). The level-policy kind/status filter still applies at higher levels, so a Patent-level direct view doesn't suddenly leak off_script custom milestones the aggregated default filters out.

Acceptance behaviour.

  • Case-level Nur direkt → CCR sub-project lane disappears, parent_context lane disappears (when viewing a CCR child).
  • Case-level Inkl. → unchanged (Slice 3 parallel-track render).
  • Patent / Litigation / Client Nur direkt → collapses to this project's own milestones in a single 'self' lane.
  • Patent / Litigation / Client Inkl. → unchanged (Slice 4 lane view).

Tests. Two new live-DB subtests in TestProjectionService_LevelAggregation_Live:

  • Patent-level: direct_only collapses to single 'self' lane — asserts only one lane (id=self, project_id=patent.ID), and that Case-A's deadline + bubbled milestone do NOT surface.
  • Case-level: direct_only drops CCR sub-project lane — seeds a CCR child + milestone, confirms the default subtree path includes the counterclaim:<id> lane and direct_only excludes it.

Commit: c2f1c29b10

Fix on `mai/maxwell/bug-bundle-filterbar` @ c2f1c29 (bundled with #32). **Root cause.** The frontend correctly threaded `?direct_only=true` into the `/timeline` request and the handler parsed it into `ProjectionOpts.DirectOnly`, but `ProjectionService.For` honoured the flag only inside `loadProjectTrack` (the deadline / appointment / project_events SQL path). Two later layers ignored it: - **Slice 3 CCR loading** in `forCaseLevel` always ran `LoadCounterclaimChildrenVisible` and emitted CCR sub-project lanes regardless of DirectOnly. - **Slice 4 lane aggregation** in `forAggregatedLevel` always loaded direct children (cases under a patent, patents under a litigation, litigations under a client) and rendered one lane per child — DirectOnly never reached this branch. **Fix.** `For` short-circuits to a new `forDirectSelfOnly` whenever `opts.DirectOnly` is set. Result: a single "self" lane scoped to this project's own actuals (and its own future projection at Case level only). The level-policy kind/status filter still applies at higher levels, so a Patent-level direct view doesn't suddenly leak `off_script` custom milestones the aggregated default filters out. **Acceptance behaviour.** - Case-level `Nur direkt` → CCR sub-project lane disappears, parent_context lane disappears (when viewing a CCR child). - Case-level `Inkl.` → unchanged (Slice 3 parallel-track render). - Patent / Litigation / Client `Nur direkt` → collapses to this project's own milestones in a single 'self' lane. - Patent / Litigation / Client `Inkl.` → unchanged (Slice 4 lane view). **Tests.** Two new live-DB subtests in `TestProjectionService_LevelAggregation_Live`: - `Patent-level: direct_only collapses to single 'self' lane` — asserts only one lane (id=`self`, project_id=patent.ID), and that Case-A's deadline + bubbled milestone do NOT surface. - `Case-level: direct_only drops CCR sub-project lane` — seeds a CCR child + milestone, confirms the default subtree path includes the `counterclaim:<id>` lane and direct_only excludes it. Commit: https://mgit.msbls.de/m/paliad/commit/c2f1c29b103d5afddde7b42896f0596012b37a9d
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/paliad#33
No description provided.