|
@@ -269,130 +269,27 @@ with a `BOOTSTRAP_ADMIN` audit row.
|
|
|
`active_days`; `max_working_days` in the body is rejected. Migration
|
|
`active_days`; `max_working_days` in the body is rejected. Migration
|
|
|
002 backfills legacy rows (half-days round up, clamped to 0..5).
|
|
002 backfills legacy rows (half-days round up, clamped to 0..5).
|
|
|
+14 tests, 88 total (was 74).
|
|
+14 tests, 88 total (was 74).
|
|
|
|
|
+- [x] **Phase 13 — Focus filter + Reset in the task list** (`b027c5d`):
|
|
|
|
|
+ new `[data-focus-select]` in the task-list toolbar picks one sprint
|
|
|
|
|
+ worker; `applyFilters()` grows a fourth AND predicate hiding rows
|
|
|
|
|
+ whose `[data-assign][data-sw-id="{focus}"]` is not > 0, and a new
|
|
|
|
|
+ `applyFocusColumnVisibility()` tags every sw column that is
|
|
|
|
|
+ all-zero across the remaining visible rows with `.focus-auto-hidden`
|
|
|
|
|
+ (a one-line utility added to `assets/css/input.css` — does NOT
|
|
|
|
|
+ touch `hiddenCols`, so clearing focus restores the user's manual
|
|
|
|
|
+ Columns picks). `[data-reset-filters]` wipes search, prio,
|
|
|
|
|
+ ownerFilterSet, focusWorker, and hiddenCols in one click and
|
|
|
|
|
+ re-hides itself. All state lives in `localStorage`
|
|
|
|
|
+ (`sp:{sprintId}:focusWorker` joins the existing namespace). Pure
|
|
|
|
|
+ client-side; no schema, route, or audit changes. Tests unchanged
|
|
|
|
|
+ at 88 (the phase is 100% JS over existing HTML, same pattern as
|
|
|
|
|
+ Phase 10).
|
|
|
|
|
|
|
|
### Upcoming
|
|
### Upcoming
|
|
|
|
|
|
|
|
-- [ ] **Phase 13 — "Focus" filter in the task list**
|
|
|
|
|
-
|
|
|
|
|
- **Problem.** With more than a handful of workers on a sprint, the
|
|
|
|
|
- task list is wide and noisy for someone who only cares about what
|
|
|
|
|
- *they* (or one specific teammate) are on the hook for. Today you
|
|
|
|
|
- can filter by owner, but "owner" is not the same as "has time
|
|
|
|
|
- assigned" — a task owned by Alice can still have Bob doing 3 days
|
|
|
|
|
- of the work. Scanning a 12-worker grid for Bob's non-zero cells is
|
|
|
|
|
- exactly what the computer should do.
|
|
|
|
|
-
|
|
|
|
|
- **Goal.** Add a **Focus** control to the task-list toolbar. Pick
|
|
|
|
|
- one sprint worker; the list then shows only tasks where that
|
|
|
|
|
- worker's assignment is > 0, and any worker column that is zero for
|
|
|
|
|
- every remaining visible task collapses away. A **Reset filters**
|
|
|
|
|
- button next to it clears the search, priority filter, owner
|
|
|
|
|
- multi-select, focus worker, and any manually-hidden columns in one
|
|
|
|
|
- click. All state is purely client-side — no API changes.
|
|
|
|
|
-
|
|
|
|
|
- **Scope (plan).**
|
|
|
|
|
-
|
|
|
|
|
- 1. **Toolbar (`views/sprints/show.php`).**
|
|
|
|
|
- - Between the existing `[data-owner-filter-root]` and
|
|
|
|
|
- `[data-columns-root]`, insert a `[data-focus-filter-root]`
|
|
|
|
|
- block: a `<select data-focus-select>` with `<option value="">
|
|
|
|
|
- All workers</option>` + one `<option value="{sw_id}">{name}
|
|
|
|
|
- </option>` per sprint worker. Styled to match the other
|
|
|
|
|
- toolbar controls.
|
|
|
|
|
- - At the far left of the toolbar row, add a
|
|
|
|
|
- `<button data-reset-filters>` (subtle, border-only, "Reset"
|
|
|
|
|
- label). Visible only when any filter is active (managed by
|
|
|
|
|
- the same logic that computes filter state below).
|
|
|
|
|
- - No schema or controller changes — this is pure view + JS.
|
|
|
|
|
-
|
|
|
|
|
- 2. **JS filter state (`public/assets/js/sprint-planner.js`).**
|
|
|
|
|
- - New localStorage key: `sp:{sprintId}:focusWorker`, string
|
|
|
|
|
- value (sw_id or "").
|
|
|
|
|
- - Hydrate on boot, reflect into `<select data-focus-select>`.
|
|
|
|
|
- - On `change`: persist, then call `applyFilters()`.
|
|
|
|
|
- - `applyFilters()` grows a fourth AND clause: if focus is set
|
|
|
|
|
- and the row's `[data-assign][data-sw-id="{focus}"]` input has
|
|
|
|
|
- value ≤ 0, hide the row. Use the same zero-tolerance the
|
|
|
|
|
- capacity math uses (`Number(v) > 0`, not `!== 0`, so 0.0 is
|
|
|
|
|
- treated as empty).
|
|
|
|
|
-
|
|
|
|
|
- 3. **Derived column auto-hide (new function,
|
|
|
|
|
- `applyFocusColumnVisibility()`).**
|
|
|
|
|
- - Called at the end of `applyFilters()` when focus is active.
|
|
|
|
|
- - For each sprint worker's column `sw-{id}`:
|
|
|
|
|
- - If any visible task row has `[data-assign][data-sw-id="{id}"]`
|
|
|
|
|
- > 0 → keep the column as-is (respect the user's manual
|
|
|
|
|
- visibility from the Columns dropdown).
|
|
|
|
|
- - Otherwise → add a transient CSS class `focus-auto-hidden`
|
|
|
|
|
- to every `[data-col="sw-{id}"]` cell/header (don't touch
|
|
|
|
|
- the user's `hiddenCols` set, so turning focus off restores
|
|
|
|
|
- their pick).
|
|
|
|
|
- - When focus is cleared, strip every `.focus-auto-hidden` and
|
|
|
|
|
- let `applyColumnVisibility()` re-run.
|
|
|
|
|
- - Define `.focus-auto-hidden { display: none; }` in
|
|
|
|
|
- `assets/css/input.css` (one line; Tailwind's `@layer
|
|
|
|
|
- utilities` section, or inline in the view — former keeps the
|
|
|
|
|
- vendored CSS path consistent).
|
|
|
|
|
-
|
|
|
|
|
- 4. **Reset button.**
|
|
|
|
|
- - On click: clear `[data-task-search]`, reset
|
|
|
|
|
- `[data-prio-filter]` to `""`, empty `ownerFilterSet` (and
|
|
|
|
|
- persist), clear `focusWorker` (and persist), and empty
|
|
|
|
|
- `hiddenCols` (and persist), then call the existing update
|
|
|
|
|
- functions (`updateOwnerFilterUi`, `applyColumnVisibility`,
|
|
|
|
|
- `applyFilters`). One code path, no reloads.
|
|
|
|
|
- - Visibility rule: show the button when any of
|
|
|
|
|
- `{search, prio, ownerFilterSet.size, focusWorker,
|
|
|
|
|
- hiddenCols.size}` is non-empty. Re-evaluate after every
|
|
|
|
|
- filter change.
|
|
|
|
|
-
|
|
|
|
|
- 5. **Edge cases / behaviour.**
|
|
|
|
|
- - **Focus + owner + search all active** → AND. The existing
|
|
|
|
|
- `applyFilters` ordering is fine; focus is just another
|
|
|
|
|
- predicate per row.
|
|
|
|
|
- - **Focused worker has no assigned tasks** → row list is empty,
|
|
|
|
|
- every sw column is all-zero, so every sw column collapses.
|
|
|
|
|
- The existing `[data-task-empty-filter]` banner covers the
|
|
|
|
|
- empty-rows case — test that it shows, not the "No tasks yet"
|
|
|
|
|
- banner.
|
|
|
|
|
- - **New task created while focus is on** → `buildTaskRow` adds
|
|
|
|
|
- a row with zero assignments, so the focus filter will hide
|
|
|
|
|
- it immediately. Acceptable (user can clear focus to see it),
|
|
|
|
|
- but a small UX surprise — call it out in the commit message.
|
|
|
|
|
- - **Worker removed from sprint** → the reorder-then-reload
|
|
|
|
|
- (§10) already covers this; focus just reads from the refreshed
|
|
|
|
|
- DOM.
|
|
|
|
|
- - **Archived sprints** → read-only, but the focus/reset
|
|
|
|
|
- controls are pure UI, so they still work for viewers.
|
|
|
|
|
-
|
|
|
|
|
- 6. **Tests.** No new PHPUnit — this phase is 100% client-side JS
|
|
|
|
|
- over existing HTML. Manual acceptance:
|
|
|
|
|
- (a) pick a worker with assignments → only their tasks show
|
|
|
|
|
- and only columns with non-zero cells for those tasks
|
|
|
|
|
- remain;
|
|
|
|
|
- (b) pick a worker with no assignments → empty-filter banner,
|
|
|
|
|
- all sw columns collapsed;
|
|
|
|
|
- (c) stack with search + prio + owner filters → all four AND;
|
|
|
|
|
- (d) hit Reset → everything clears, Reset button vanishes.
|
|
|
|
|
- Add these to [ACCEPTANCE.md](ACCEPTANCE.md) in the same commit
|
|
|
|
|
- so the §10 manual walkthrough stays truthful.
|
|
|
|
|
-
|
|
|
|
|
- **Out of scope.**
|
|
|
|
|
- - Server-side enforcement of the filter. The API does not gate
|
|
|
|
|
- which tasks a user can see — sprint membership already grants
|
|
|
|
|
- read access to the whole sprint, and focus is a personal lens
|
|
|
|
|
- over that.
|
|
|
|
|
- - Multi-worker focus. Sticking to one worker at a time keeps the
|
|
|
|
|
- UI + column-collapse rule simple. Multi-focus would muddy "what
|
|
|
|
|
- counts as a relevant column" and nobody has asked for it.
|
|
|
|
|
- - Persisting the Reset click as an audit event. Pure UI state, no
|
|
|
|
|
- data mutation, no audit row.
|
|
|
|
|
-
|
|
|
|
|
- **Spec alignment.**
|
|
|
|
|
- - §3 / §4 / §5: unchanged — no schema or domain changes.
|
|
|
|
|
- - §6 Routes: unchanged — no new endpoints.
|
|
|
|
|
- - §7 Audit: unchanged — no mutations.
|
|
|
|
|
- - §11: phpunit count stays 88 (no new tests).
|
|
|
|
|
|
|
+Nothing scheduled. Residual follow-ups are in §10; the main outstanding
|
|
|
|
|
+item is a human-run walkthrough of [ACCEPTANCE.md](ACCEPTANCE.md)
|
|
|
|
|
+(now covering Phases 1–13) in a running container.
|
|
|
|
|
|
|
|
## 10. Residual known gaps / deferred items
|
|
## 10. Residual known gaps / deferred items
|
|
|
|
|
|
|
@@ -449,14 +346,14 @@ vendor/bin/phpunit
|
|
|
Tell Claude:
|
|
Tell Claude:
|
|
|
|
|
|
|
|
> Working on `/Users/achiappa/Development/claude_code_private/sprint_planer_web`.
|
|
> Working on `/Users/achiappa/Development/claude_code_private/sprint_planer_web`.
|
|
|
-> Read `HANDOFF.md`, the git log, and `ACCEPTANCE.md`. Phases 1–12 are
|
|
|
|
|
-> shipped (see §9); Phase 13 ("Focus" filter + reset in the task list)
|
|
|
|
|
-> is planned but not implemented — the scope is in §9 under Upcoming.
|
|
|
|
|
-> Other outstanding items are in §10 (mostly a manual acceptance
|
|
|
|
|
-> walkthrough in the running container). If I ask you to work Phase 13,
|
|
|
|
|
-> follow the maintenance rule in §14 — commit code, then commit a
|
|
|
|
|
-> HANDOFF.md update separately that moves the entry from Upcoming →
|
|
|
|
|
-> Shipped with its SHA.
|
|
|
|
|
|
|
+> Read `HANDOFF.md`, the git log, and `ACCEPTANCE.md`. Phases 1–13 are
|
|
|
|
|
+> shipped (see §9) and §9 Upcoming is empty — no scheduled work.
|
|
|
|
|
+> Outstanding items are in §10 (mostly a human-run acceptance
|
|
|
|
|
+> walkthrough in the running container). If you plan to take on a new
|
|
|
|
|
+> phase, append its plan to §9 Upcoming first; when it ships, follow
|
|
|
|
|
+> the maintenance rule in §14 — commit code, then commit a HANDOFF.md
|
|
|
|
|
+> update separately that moves the entry from Upcoming → Shipped with
|
|
|
|
|
+> its SHA.
|
|
|
|
|
|
|
|
Claude should verify what's described here against actual repo state
|
|
Claude should verify what's described here against actual repo state
|
|
|
before acting — nothing here is load-bearing once it grows stale.
|
|
before acting — nothing here is load-bearing once it grows stale.
|
|
@@ -464,6 +361,8 @@ before acting — nothing here is load-bearing once it grows stale.
|
|
|
## 13. Git history (as of this handoff)
|
|
## 13. Git history (as of this handoff)
|
|
|
|
|
|
|
|
```
|
|
```
|
|
|
|
|
+b027c5d Phase 13: Focus filter + Reset in the task list
|
|
|
|
|
+815e232 HANDOFF.md: note 5-dot Arbeitstage indicator follow-up
|
|
|
1aca417 Sprint view Arbeitstage: 5-dot weekday indicator instead of a number
|
|
1aca417 Sprint view Arbeitstage: 5-dot weekday indicator instead of a number
|
|
|
59eb1d7 HANDOFF.md: mark Phase 12 shipped
|
|
59eb1d7 HANDOFF.md: mark Phase 12 shipped
|
|
|
a634582 Phase 12: per-week weekday selection (Mo–Fr) drives Arbeitstage
|
|
a634582 Phase 12: per-week weekday selection (Mo–Fr) drives Arbeitstage
|