docs(20-02): complete tablo detail templ components plan summary
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a60de1fc7a
commit
b05f280089
1 changed files with 131 additions and 0 deletions
131
.planning/phases/20-tablo-detail-kanban-restyle/20-02-SUMMARY.md
Normal file
131
.planning/phases/20-tablo-detail-kanban-restyle/20-02-SUMMARY.md
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
---
|
||||
phase: 20-tablo-detail-kanban-restyle
|
||||
plan: "02"
|
||||
subsystem: go-backend/views+handlers
|
||||
tags: [tablo-detail, kanban, templ, htmx, sortable]
|
||||
dependency_graph:
|
||||
requires:
|
||||
- 20-01 (TabloDetailViewModel, GetTabloDetailPage handler, GET /tablos/{tabloID} route)
|
||||
provides:
|
||||
- TabloDetailPage (real templ component, replaces Plan 01 stub)
|
||||
- TabloDetailHeader (header with avatar, title, metadata row)
|
||||
- TabloDetailTabBar (HTMX tab navigation with hx-get + hx-push-url)
|
||||
- TabloDetailKanbanBoard (4-column flex container)
|
||||
- TabloDetailKanbanColumn (column with header, task list, hidden reorder form)
|
||||
- TabloDetailTaskCard (task card with drag handle + delete button)
|
||||
- TabloDetailEtapesSection (etapes list below kanban)
|
||||
- TabloDetailSortableScript (Sortable.js DOMContentLoaded + htmx:afterSettle init)
|
||||
- GetTabloDetailTab handler (GET /tablos/{tabloID}/{tab})
|
||||
- GET /tablos/{tabloID}/{tab} route
|
||||
affects:
|
||||
- go-backend/router.go
|
||||
tech_stack:
|
||||
added: []
|
||||
patterns:
|
||||
- templ component hierarchy (8 sub-components under TabloDetailPage)
|
||||
- Hidden reorder form per column (id="reorder-form-{status}") for Sortable.js onEnd
|
||||
- HTMX tab navigation (hx-get + hx-push-url="true")
|
||||
- Tab handler pattern (tasks tab returns partial; other tabs return "coming soon" fragment)
|
||||
key_files:
|
||||
created:
|
||||
- go-backend/internal/web/views/tablo_detail.templ
|
||||
- go-backend/internal/web/views/tablo_detail_templ.go
|
||||
- go-backend/internal/web/handlers/tablo_detail_tab.go
|
||||
modified:
|
||||
- go-backend/internal/web/views/tablo_detail_view.go
|
||||
- go-backend/router.go
|
||||
decisions:
|
||||
- Tab links use hx-get + hx-push-url="true" targeting #tab-content per UI-SPEC locked interaction contract; plain href anchors explicitly forbidden
|
||||
- TabloDetailKanbanBoard is a standalone component; TasksKanbanLayout from tasks.templ is not reused (separate surface per RESEARCH anti-patterns)
|
||||
- TabloDetailSortableScript uses templ.Raw to emit raw script block; guard el._sortable prevents double-init after HTMX swap
|
||||
- GetTabloDetailTab returns kanban board fragment only for tasks tab; other tabs return hardcoded "coming soon" text (tab slug never interpolated into HTML - T-20-07 mitigation)
|
||||
- strconv.Itoa used for integer-to-string conversion in templ (not fmt.Sprintf)
|
||||
metrics:
|
||||
duration: "~15min"
|
||||
completed_date: "2026-05-18"
|
||||
tasks_completed: 2
|
||||
files_created: 3
|
||||
files_modified: 2
|
||||
---
|
||||
|
||||
# Phase 20 Plan 02: TabloDetailPage Templ Component + Tab Handler Summary
|
||||
|
||||
Full HTML surface for the tablo detail page: templ components for header, HTMX tab bar, kanban board (4 columns each with hidden reorder form), task cards with drag handles, etapes section, and Sortable.js init script. Stub replaced with real templ component; tab route registered.
|
||||
|
||||
## What Was Built
|
||||
|
||||
**views/tablo_detail.templ**
|
||||
- `TabloDetailPage(vm TabloDetailViewModel)` — outer wrapper calling all sub-components
|
||||
- `TabloDetailHeader(vm TabloDetailViewModel)` — header with colored avatar, h1 title, metadata row (owner, due date, status badge, progress bar)
|
||||
- `TabloDetailTabBar(tabloID string)` — 5-tab nav (Vue d'ensemble, Tâches, Fichiers, Discussion, Événements) using hx-get + hx-target="#tab-content" + hx-push-url="true"; Tâches always active
|
||||
- `TabloDetailKanbanBoard(columns, tabloID)` — flex container iterating over 4 columns
|
||||
- `TabloDetailKanbanColumn(col, tabloID)` — column with header (title, count, "+ Ajouter"), task list (.task-list.sortable-column), hidden reorder form id="reorder-form-{col.ID}", create zone
|
||||
- `TabloDetailTaskCard(task, tabloID)` — article.task-card with .task-drag-handle, .task-card-title, ui.IconButton delete with hx-delete
|
||||
- `TabloDetailEtapesSection(etapes)` — section.tablo-etapes-section with h2 "Étapes" and ul of li.tablo-etape-row items
|
||||
- `TabloDetailSortableScript(tabloID)` — raw script block with initTabloDetailSortable() registered on DOMContentLoaded + htmx:afterSettle
|
||||
|
||||
**views/tablo_detail_view.go**
|
||||
- Stub `TabloDetailPage` function (templ.ComponentFunc) removed
|
||||
- `context`, `io`, `templ` imports removed (no longer needed in .go file)
|
||||
- All struct types and `NewTabloDetailViewModel` / `computeTabloProgress` functions retained
|
||||
|
||||
**handlers/tablo_detail_tab.go**
|
||||
- `GetTabloDetailTab()` handler for GET /tablos/{tabloID}/{tab}
|
||||
- Auth check → UUID parse → tab slug switch
|
||||
- tasks tab: fetches tablo + tasks → builds vm → renders TabloDetailKanbanBoard fragment
|
||||
- Other tabs: returns hardcoded `<div class="tab-coming-soon">...</div>`
|
||||
|
||||
**router.go**
|
||||
- `mux.Get("/tablos/{tabloID}/{tab}", authHandler.GetTabloDetailTab())` registered after /tablos/{tabloID}
|
||||
|
||||
## Security (Threat Model)
|
||||
|
||||
| Threat | Mitigation | Status |
|
||||
|--------|------------|--------|
|
||||
| T-20-04: task.Title injected into HTML | templ auto-escapes all { expr } interpolations | Mitigated |
|
||||
| T-20-05: data-status from user input | data-status comes from hardcoded column IDs only | Mitigated |
|
||||
| T-20-07: {tab} slug reflected into HTML | Tab slug used only as switch key; "coming soon" text hardcoded | Mitigated |
|
||||
|
||||
## Test Coverage
|
||||
|
||||
All pre-existing handler tests pass with the real templ component:
|
||||
- `TestGetTabloDetailPage_Returns200` — authenticated + owned tablo → 200 + tablo name in body
|
||||
- `TestGetTabloDetailPage_Returns404` — unknown tablo → 404
|
||||
- `TestGetTabloDetailPage_Returns400` — invalid UUID → 400
|
||||
- `TestGetTabloDetailPage_Unauthenticated` — no cookie → 302 /login
|
||||
- `TestTabloDetailKanbanColumns` — body contains todo/in_progress/in_review/done data-status values
|
||||
- `TestGetTabloDetailPage_ContainsSortableScript` — body contains "initTabloDetailSortable"
|
||||
|
||||
Full view model tests also pass (TestComputeTabloProgress_*, TestNewTabloDetailViewModel_*).
|
||||
|
||||
## Commits
|
||||
|
||||
| Hash | Type | Description |
|
||||
|------|------|-------------|
|
||||
| 4ae19fa | feat | TabloDetailPage templ component + GetTabloDetailTab handler |
|
||||
| a60de1f | feat | Replace TabloDetailPage stub with templ component + register tab route |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed exactly as written.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None. The TabloDetailPage stub from Plan 01 has been replaced. The "coming soon" tab content in GetTabloDetailTab is intentional scaffolding for Phase 21+ (overview, files, discussion, events), not an unresolved stub.
|
||||
|
||||
## Self-Check
|
||||
|
||||
Files created:
|
||||
- go-backend/internal/web/views/tablo_detail.templ — FOUND
|
||||
- go-backend/internal/web/views/tablo_detail_templ.go — FOUND
|
||||
- go-backend/internal/web/handlers/tablo_detail_tab.go — FOUND
|
||||
|
||||
Commits:
|
||||
- 4ae19fa — FOUND
|
||||
- a60de1f — FOUND
|
||||
|
||||
just generate — PASSES (tablo_detail_templ.go generated)
|
||||
go build ./... — PASSES
|
||||
go test ./... -count=1 — ALL PASS (13 packages)
|
||||
|
||||
## Self-Check: PASSED
|
||||
Loading…
Reference in a new issue