Commit graph

3 commits

Author SHA1 Message Date
0ad47561ed feat(server): redirect rows-dir URLs to canonical .table.html
When an HTML GET hits a directory that's the rows-dir of a registered
table — i.e. parent declares `tables: { <name>: ... }` with a valid
spec, OR the default-MDL fallback applies at archive/<party>/mdl/ —
ServeDirectory now 302s to <parent>/<name>.table.html so users land
on the table view instead of a bare browse listing of the row-yaml
files. JSON GETs on the same URL fall through unchanged so the table
client can still enumerate row files.

Detection reuses RecognizeTableRequest: synthesize the equivalent
.table.html URL from the directory request and let the existing
recognizer apply its operator-vs-default-vs-missing-spec rules. No
duplicated validation.

Updates main_test.go's TestDispatchSlashRouting to expect the new
behavior on archive/<party>/mdl/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:43:08 -05:00
821ed3ee19 feat(handler): mdl/ → table-app default with embedded fallback spec
Three pieces wire the per-party Master Deliverables List as the default
view at archive/<party>/mdl/:

1. **Dispatcher redirect.** GET (and HEAD) on
   <project>/archive/<party>/mdl/ (case-fold on archive and mdl) now
   302 → <project>/archive/<party>/mdl.table.html. Non-archive paths
   and deeper mdl/ paths fall through unchanged.

2. **Default-spec fallback in RecognizeTableRequest.** When a request
   matches archive/<party>/mdl.table.html and no operator-supplied
   tables: { mdl: ... } declaration covers it, the handler returns a
   recognised request anyway. Operator declarations still win — and a
   typo'd declaration pointing at a missing file yields 404 (not a
   silent fallback).

3. **Static-file fallback for the spec yaml.** GET archive/<party>/
   mdl.table.yaml and archive/<party>/mdl.form.yaml return embedded
   default bytes (default-mdl.{table,form}.yaml in the handler package)
   when no operator file exists at that path. Operator files always
   win because the dispatcher's os.Stat finds them before reaching the
   IsDefaultMdlSpec branch.

The defaults use ZDDC vocabulary: tracking, title, discipline, type,
plannedRevision, plannedDate, status (DFT/IFR/IFA/IFC/AFC/AB), owner,
notes. Operators override per-party by writing
archive/<party>/{mdl.table.yaml,mdl.form.yaml} and a tables: { mdl: ... }
entry in the party's .zddc.

Tests:
- 4 dispatcher redirect cases (success, case-fold mdl, case-fold archive,
  deeper-path skip, non-archive skip)
- 6 tablehandler cases (default fires at archive/<party>/, operator
  override wins, scope check, embedded yaml served, operator yaml wins,
  scope check on yaml fallback)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 09:26:53 -05:00
9ca36f25d8 feat(tables): new sortable/filterable grid tool for directories of YAML files
Tables is the eighth HTML tool: a read-only tabular view over a
directory of YAML files declared via `tables:` in `.zddc`. Anchor use
case is the Master Deliverables List, where each row is one
`<tracking>.yaml` under `Archive/<Party>/MDL/`. Rows click through to
the existing form renderer for editing.

Schema (zddc/internal/zddc/file.go)
  - New `Tables map[string]string` on ZddcFile. Map key becomes the URL
    stem (`tables[MDL]` → `<dir>/MDL.table.html`); the value is a path
    relative to the .zddc pointing at a `*.table.yaml` spec describing
    columns + the rows directory. No upward cascade in v1 — each
    directory hosting a table declares it directly.

Server handler (zddc/internal/handler/tablehandler.go)
  - `RecognizeTableRequest` matches GET `/<dir>/<name>.table.html`
    against the cascade's `tables:` declarations. Dispatch routes
    table requests before the form-system intercept.
  - `ServeTable` ACL-gates with `policy.ActionRead` and serves the
    embedded `tables.html` template; client walks the directory itself
    via the listing JSON or FS Access API.
  - tables.html embedded via //go:embed — same pattern as form.html.

Frontend (tables/)
  - Vanilla JS: app/context/util/filters/sort/render/main modules.
  - Reads spec + row YAML files via window.zddc.source (HTTP polyfill
    or local FS handle); js-yaml 4.1.0 vendored in shared/vendor for
    client-side parsing.
  - Sample fixtures under tables/sample/ for local testing.

Build + CI
  - Lockstep build registers tables alongside the other 7 tools (HTML
    output, embed mirror, versions.txt, release-output, tags).
  - Playwright project added; `npx playwright test --project=tables`
    is part of `npm test`.

Drive-by: rename mdedit Playwright selectors `#select-directory` →
`#addDirectoryBtn` to fix three pre-existing failing tests.

Drive-by: ignore locally-built `zddc/zddc-server` binary so it doesn't
get accidentally staged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 20:32:01 -05:00