m's Q1+Q3 picks (2026-05-26): five canonical view_types
(card/list/calendar/kanban/timeline). Slice B introduces the parameter and
the first non-default rendering: card view on /tree shows the filtered set
as a flat tile grid alongside the existing tree forest.
New web/view_type.go owns the enum, per-route allowed set, parser, and
the chip-strip builder. Per the design note, view_type is RENDER state,
not filter state — kept off TreeFilter so the same filter can render as
card or list.
PageViewTypes("/") = {default: list, allowed: [list, card]}.
Dashboard / calendar / timeline are LOCKED to their native shape in
slice B; switching templates on /dashboard for card vs list is mostly
already done via fuller's 5h tabbed-tiles surface and stays as-is for
now (the chip strip surfaces card as the only allowed value there).
Kanban + cross-page list/card swaps land in slice C onwards.
Render:
- handleTree parses `?view_type=` with the per-route catalog, builds
flatMatchedItems for the card consumer alongside the existing forest.
- tree_section.tmpl gains a view-type chip strip (locked entries shown
greyed-out with title tooltip) + branches into either `tree-card` or
the forest based on .ViewType.
- New templates/tree_card.tmpl renders a flat grid of tiles for the
matched set; per-item field set mirrors the list rendering.
- Hidden `view_type` input added to the search form so chip clicks
preserve the view choice.
Tests:
- view_type_test.go: parser fallback, per-route catalog, chip strip
active/locked flags, filter preservation in chip URLs.
- server_test.go: end-to-end dispatch — GET /?view_type=card renders
tree-card-grid, GET / renders forest, unknown values fall back to
list. Chip strip present on both views.
30 lines
1.2 KiB
Cheetah
30 lines
1.2 KiB
Cheetah
{{/*
|
|
Phase 5i Slice B — card view for /tree. Renders the filtered item set as a
|
|
flat tile grid (no forest, no ancestor-keep). One tile per matched item,
|
|
ordered by primary path. Reuses the per-item field set the list view emits;
|
|
the visual difference is layout, not data shape.
|
|
*/}}
|
|
{{define "tree-card"}}
|
|
<div class="tree-card-grid">
|
|
{{range .CardItems}}
|
|
<article class="tree-card">
|
|
<header class="tree-card-head">
|
|
<a class="tree-card-title" href="/i/{{.PrimaryPath}}">{{.Title}}</a>
|
|
<span class="tree-card-slug muted">{{.PrimaryPath}}</span>
|
|
</header>
|
|
<p class="tree-card-meta">
|
|
{{range .Management}}<span class="mgmt mgmt-{{.}}">{{.}}</span>{{end}}
|
|
{{range .Tags}}<span class="tag">{{.}}</span>{{end}}
|
|
{{if .Pinned}}<span class="pinned" title="Pinned">★</span>{{end}}
|
|
{{if eq .Status "done"}}<span class="status status-done">done</span>{{end}}
|
|
{{if .Archived}}<span class="status status-archived">archived</span>{{end}}
|
|
</p>
|
|
</article>
|
|
{{else}}
|
|
<div class="tree-card-empty">
|
|
<em>No items match. Try fewer filters or <a href="/">clear all</a>.</em>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|