Restores the /views URL family in the paliad shape m asked for:
GET /views → MRU 302 or onboarding shell
GET /views/{slug} → render saved view as its own page
GET /views/new → editor blank
GET /views/{slug}/edit → editor existing
POST /views → create
POST /views/{slug} → update
POST /views/{slug}/delete → delete
POST /views/reorder → drag-reorder hook (used in slice G)
Render path:
- handleViewRender resolves the slug against user views (slice C adds
system views), touches last_used_at fire-and-forget so the next /views
landing 302s here, then dispatches the same view_type renderers the
tree page uses (list / card / kanban). filter_json is decoded into a
TreeFilter + view_type + group_by; URL chip params overlay the saved
filter so chips narrow the view further without losing the saved
baseline. calendar / timeline view_types fall back to list in slice B;
slice D wires their dedicated templates.
Editor path:
- handleViewEditor renders templates/view_editor.tmpl, a minimal form
for slice B (slice D adds the live chip strip, slug auto-derivation,
and the icon registry). Pre-fills every persisted field on edit.
Templates:
- views_landing.tmpl — index card list + "+ new view" link.
- view_render.tmpl — header (name + slug + edit/delete) + tree-section
partial. Bundled with tree_section / tree_card / tree_kanban /
project_chip so the rendered view shares the dispatch chain.
- view_editor.tmpl — form for create + edit.
Encoding:
- encodeFilterToJSON canonicalises (filter_query, view_type) into the
filter_json shape. view_type lives INSIDE the JSON per m's Q2 pick.
- decodeViewSpec is the inverse — slice C's system-view code reuses it
to convert SystemView definitions into the same shape.
- overlayURLOntoSavedFilter mirrors the 5i fix-shift pattern: URL chip
values selectively override the saved baseline (q / tag / mgmt /
status / has / show-archived / public / project / project_descendants).
Error mapping:
- writeViewError translates the typed store errors (ErrViewSlugFormat /
Reserved / Taken / NotFound) into 400 / 409 with human-readable
banners. handlers map ErrViewNotFound to 404 directly.
Tests (HTTP integration):
- TestViewsLandingOnboarding — empty store → shell with "+ New view".
- TestViewsLandingMRURedirects — touched view triggers 302 to it.
- TestViewRenderShowsSavedView — name + slug + view_type=card grid.
- TestViewRender404OnUnknownSlug — unknown slug 404s, no silent
fall-back to tree.
- TestViewCreateAndDelete — POST /views creates; reserved slug 400s;
POST /views/<slug>/delete removes the row.
- TestSavedViewFilterOverlay — ?tag=work narrows the saved view; URL
chip values overlay the persisted filter.
15 lines
477 B
Cheetah
15 lines
477 B
Cheetah
{{define "content"}}
|
|
<section class="view-header">
|
|
<h1>{{.View.Name}}</h1>
|
|
<p class="muted view-meta">
|
|
<code>/views/{{.View.Slug}}</code> ·
|
|
<a href="/views/{{.View.Slug}}/edit">edit</a> ·
|
|
<form method="post" action="/views/{{.View.Slug}}/delete" style="display:inline">
|
|
<button type="submit" class="link-button" onclick="return confirm('Delete view {{.View.Name}}?')">delete</button>
|
|
</form>
|
|
</p>
|
|
</section>
|
|
|
|
{{template "tree-section" .}}
|
|
{{end}}
|