docs(16-03): complete kanban restyle + etape grouping plan summary
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e2ee4349f8
commit
3a5a26c5c8
1 changed files with 118 additions and 0 deletions
118
.planning/phases/16-tablo-detail/16-03-SUMMARY.md
Normal file
118
.planning/phases/16-tablo-detail/16-03-SUMMARY.md
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
---
|
||||||
|
phase: 16-tablo-detail
|
||||||
|
plan: "03"
|
||||||
|
subsystem: templates
|
||||||
|
tags: [htmx, templ, kanban, etape-grouping, design-tokens]
|
||||||
|
dependency_graph:
|
||||||
|
requires: [16-01, 16-02]
|
||||||
|
provides: [kanban-etape-grouping, tasks-section-layout, task-row-layout, etape-strip-removed]
|
||||||
|
affects: [16-04-files-templ]
|
||||||
|
tech_stack:
|
||||||
|
added: []
|
||||||
|
patterns: [groupTasksByEtape helper, EtapeGroup type, EtapeGroupHeader component, tasks-section kanban layout, task-row card pattern]
|
||||||
|
key_files:
|
||||||
|
created: []
|
||||||
|
modified:
|
||||||
|
- backend/templates/tasks.templ
|
||||||
|
- backend/templates/tablos.templ
|
||||||
|
- backend/internal/web/handlers_tasks.go
|
||||||
|
decisions:
|
||||||
|
- "EtapeGroup.EtapeColor always set to empty string — sqlc.Etape struct has no Color field in this schema (no etape color in DB migration)"
|
||||||
|
- "uuid.UUID(t.EtapeID.Bytes).String() used for pgtype.UUID → string conversion — matches existing taskEtapeIDString helper in tasks_forms.go"
|
||||||
|
- "tablos.templ KanbanBoard call updated in Task 2 (not Task 1) — build would fail if tasks.templ committed alone; treated as atomic with handlers_tasks.go updates"
|
||||||
|
metrics:
|
||||||
|
duration: ~20min
|
||||||
|
completed: 2026-05-16T22:30:00Z
|
||||||
|
tasks_completed: 2
|
||||||
|
files_modified: 3
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 16 Plan 03: Kanban Restyle + Etape Grouping Summary
|
||||||
|
|
||||||
|
**One-liner:** Added `groupTasksByEtape` helper and `EtapeGroupHeader` component to `tasks.templ`; restyled `KanbanColumn` to `tasks-section` layout, `TaskCard` to `task-row` layout, `AddTaskTrigger` to `tasks-add-button`; removed `@EtapeStrip` OOB calls from `TaskCardGone`/`TaskCardOOB`; updated all three `KanbanBoard` call sites to accept `etapes []sqlc.Etape` as 5th parameter.
|
||||||
|
|
||||||
|
## Tasks Completed
|
||||||
|
|
||||||
|
| Task | Name | Commit | Files |
|
||||||
|
|------|------|--------|-------|
|
||||||
|
| 1 | Add groupTasksByEtape helper, EtapeGroup type, EtapeGroupHeader component; update KanbanBoard/Column signatures and restyled column/card/trigger | 084fc0e | `backend/templates/tasks.templ` |
|
||||||
|
| 2 | Update all three KanbanBoard call sites (tablos.templ + handlers_tasks.go) and verify full test suite | e2ee434 | `backend/internal/web/handlers_tasks.go`, `backend/templates/tablos.templ` |
|
||||||
|
|
||||||
|
## What Was Built
|
||||||
|
|
||||||
|
**Task 1 — tasks.templ:**
|
||||||
|
|
||||||
|
- **EtapeGroup type:** Struct with `EtapeID string`, `EtapeTitle string`, `EtapeColor string`, `Tasks []sqlc.Task`. EtapeColor always empty (schema has no color field).
|
||||||
|
|
||||||
|
- **groupTasksByEtape helper:** Iterates tasks, uses `!t.EtapeID.Valid` to detect unassigned (pgtype.UUID nil check), converts valid UUIDs via `uuid.UUID(t.EtapeID.Bytes).String()` (same pattern as `taskEtapeIDString` in `tasks_forms.go`). Iterates etapes in declaration order, only adds groups with tasks. Appends unassigned group last only if any unassigned tasks exist.
|
||||||
|
|
||||||
|
- **EtapeGroupHeader component:** Renders `div class="etape-group-header"`. If `EtapeColor != ""` renders color dot span with inline style. Renders `span class="etape-group-label is-unassigned"` for unassigned group (`EtapeID == ""`), plain `etape-group-label` otherwise.
|
||||||
|
|
||||||
|
- **KanbanBoard signature:** Added `etapes []sqlc.Etape` as 5th parameter. Passes `etapes` through to each `@KanbanColumn(...)` call.
|
||||||
|
|
||||||
|
- **KanbanColumn restyled:** Outer `div class="kanban-column"` wraps `div class="tasks-section"`. Header: `div class="tasks-section-header"` with left side (h3 + badge) and right side (`div id="add-task-slot-{status}"` containing `@AddTaskTrigger`). Body: `div class="task-list sortable-column"` — empty state uses `p class="task-list-empty"`, else computes `groups := groupTasksByEtape(tasks, etapes)` and renders `@EtapeGroupHeader(group)` + task loop.
|
||||||
|
|
||||||
|
- **TaskCard restyled:** Inner div changed from `task-card bg-white rounded border...` to `task-row task-card`. Drag handle removed. HTMX edit attributes moved to the outer task-row div (making the whole row clickable). Children: `div class="task-check"` (round checkbox), `div class="task-body"` (task title p), `@ui.IconButton` with trash/danger/ghost for delete confirm.
|
||||||
|
|
||||||
|
- **AddTaskTrigger restyled:** Button class changed from `ui-button ui-button-soft ui-button-neutral ui-button-md w-full text-left text-sm mt-2` to `tasks-add-button`. All HTMX attributes preserved unchanged.
|
||||||
|
|
||||||
|
- **EtapeStrip OOB removal:** Deleted `@EtapeStrip(tabloID, etapes, counts, filter, csrfToken, true)` from both `TaskCardGone` and `TaskCardOOB`. Kept `etapes []sqlc.Etape` and `counts EtapeTaskCounts` params on both signatures (avoids handler signature changes that would break tests). Added `// TODO: remove etapes and counts params after Phase 16 cleanup` comments.
|
||||||
|
|
||||||
|
**Task 2 — call site updates:**
|
||||||
|
|
||||||
|
- `backend/templates/tablos.templ` `TasksTabFragment`: `@KanbanBoard(tablo.ID, csrfToken, tasks, filter)` → `@KanbanBoard(tablo.ID, csrfToken, tasks, filter, etapes)`. `etapes` is already a parameter of `TasksTabFragment`.
|
||||||
|
|
||||||
|
- `backend/internal/web/handlers_tasks.go` line 589 (single reorder path): `tasks, _, _, filter, ok` → `tasks, etapes, _, filter, ok`; KanbanBoard call updated to pass `etapes`.
|
||||||
|
|
||||||
|
- `backend/internal/web/handlers_tasks.go` line 639 (batch reorder path): same change.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
```
|
||||||
|
grep -c "groupTasksByEtape" tasks.templ → 3 (func decl + call inside KanbanColumn)
|
||||||
|
grep -c "EtapeGroupHeader" tasks.templ → 3 (templ decl + usage in KanbanColumn)
|
||||||
|
grep -c "kanban-column" tasks.templ → 1
|
||||||
|
grep -c "tasks-section" tasks.templ → 2 (tasks-section + tasks-section-header)
|
||||||
|
grep -c "task-row" tasks.templ → 1
|
||||||
|
grep -c "EtapeStrip" tasks.templ → 0
|
||||||
|
grep -c "KanbanBoard.*etapes" handlers_tasks.go → 2
|
||||||
|
grep -c "KanbanBoard.*etapes" tablos.templ → 1
|
||||||
|
go build ./backend/... → exit 0
|
||||||
|
go test ./backend/internal/web/... -count=1 → ok (all tests pass)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 1 - Bug] sqlc.Etape has no Color field**
|
||||||
|
- **Found during:** Task 1 — first build attempt
|
||||||
|
- **Issue:** Plan specified `etape.Color.Valid` and `etape.Color.String` field access on `sqlc.Etape`. The actual schema `type Etape struct` has no `Color` field — only `ID, TabloID, Title, Description, Position, CreatedAt, UpdatedAt`.
|
||||||
|
- **Fix:** Set `EtapeGroup.EtapeColor` to `""` unconditionally in `groupTasksByEtape`. `EtapeGroupHeader` will not render a color dot for any group (since `EtapeColor` is always empty). The `is-unassigned` label logic still works correctly.
|
||||||
|
- **Files modified:** `backend/templates/tasks.templ`
|
||||||
|
- **Commit:** 084fc0e
|
||||||
|
|
||||||
|
**2. [Rule 3 - Blocking] tablos.templ KanbanBoard call updated in Task 2 (not deferred)**
|
||||||
|
- **Found during:** Task 1 — `go build ./backend/...` fails after tasks_templ.go regeneration because `tablos_templ.go` still calls old 4-arg KanbanBoard
|
||||||
|
- **Issue:** Plan intended tablos.templ to be updated in Task 2, but the templ compiler regenerates `tablos_templ.go` from `tablos.templ` immediately, causing a compile-time argument count mismatch.
|
||||||
|
- **Fix:** Updated `@KanbanBoard(tablo.ID, csrfToken, tasks, filter)` → `@KanbanBoard(tablo.ID, csrfToken, tasks, filter, etapes)` in tablos.templ during the Task 1/Task 2 boundary (before the first commit), then committed tasks.templ alone and tablos.templ + handlers_tasks.go together. The work was still split into two commits as planned.
|
||||||
|
- **Files modified:** `backend/templates/tablos.templ`
|
||||||
|
- **Commit:** e2ee434
|
||||||
|
|
||||||
|
## Known Stubs
|
||||||
|
|
||||||
|
- **EtapeGroup color dot:** `EtapeColor` is always `""` because `sqlc.Etape` has no `Color` field. The `etape-group-color-dot` CSS and `EtapeGroupHeader` color dot rendering are wired but will never fire unless a `Color` field is added to the schema in a future phase.
|
||||||
|
|
||||||
|
## Threat Flags
|
||||||
|
|
||||||
|
No new trust boundaries introduced. All changes are HTML/CSS restructuring of existing authenticated routes. T-16-03-01 through T-16-03-04 dispositions unchanged (accept).
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
- `backend/templates/tasks.templ` — FOUND, contains `groupTasksByEtape`, `EtapeGroupHeader`, `kanban-column`, `tasks-section`, `task-row task-card`, `tasks-add-button`, zero `EtapeStrip`
|
||||||
|
- `backend/templates/tablos.templ` — FOUND, contains `KanbanBoard.*etapes`
|
||||||
|
- `backend/internal/web/handlers_tasks.go` — FOUND, contains 2x `KanbanBoard.*etapes`
|
||||||
|
- Commit 084fc0e — FOUND (Task 1)
|
||||||
|
- Commit e2ee434 — FOUND (Task 2)
|
||||||
|
- `go build ./backend/...` — exit 0
|
||||||
|
- `go test ./backend/internal/web/... -count=1` — PASSED (ok backend/internal/web + ok backend/internal/web/ui)
|
||||||
Loading…
Reference in a new issue