Per the reference doc at zddc.varasys.io/reference.html#tracking-numbers,
a tracking number is composed of: originator, [phase], project,
[area], discipline, type, sequence, [suffix]. The default Master
Deliverables List now surfaces every component as its own column,
plus the standard MDL metadata (title, plannedRevision,
plannedDate, status, owner). Columns appear in the canonical
filename order so the table reads left-to-right like the tracking
number itself.
Optional components ([phase], [area], [suffix]) render in the
table even when blank — keeps the layout consistent across rows.
Projects on a schema that doesn't use them hide the columns by
overriding (see customization).
Form schema (default-mdl.form.yaml):
- One JSON Schema property per tracking-number component, plus
the deliverable metadata. originator / project / discipline /
type / sequence are required; phase / area / suffix are
optional. The schema is intentionally permissive — free-text
strings on every component, no enums or regex constraints.
Projects pick their own conventions for originator codes,
discipline vocabularies, etc.; a default that imposed a
fixed set would just get in the way.
- Phase 2's editable-cell widget factory derives the right
per-cell editor from this schema: text inputs for the
components, the existing select for `status` (which keeps
its enum), date input for `plannedDate`, textarea for
`notes`.
Customization (the "way for end users to customize"):
- Drop your own table.yaml and / or form.yaml into the rows
directory (archive/<party>/mdl/, or any directory hosting a
table). Operator-supplied files override the embedded defaults
ATOMICALLY — there's no field-level merge, the operator file
wins entirely. This matches every other "spec on disk wins"
convention in zddc-server.
- Hide a column: omit it from the columns: list.
- Rename a column header: change `title:`.
- Add a column: append a {field, title} entry AND add a
matching property in form.yaml's schema.properties.
- Tighten constraints: use `enum:`, `pattern:`, `minLength:`
etc. on form.yaml properties.
- Pre-filter rows on load: defaults.filter[<field>].
The whole rows-directory is self-contained — copying mdl/ to a
new project takes the spec, the form, and every row YAML
together.
Documentation:
- AGENTS.md "Tables system" gains a paragraph on the default-MDL
column set + the customization mechanism + a pointer to the
embedded source files.
- tables/template.html help panel rewrites the body to cover:
* What the directory IS (spec + form + row YAMLs together).
* Editable-cell keyboard shortcuts (the Phase 1-5 sequence
we just shipped — arrows, Tab, Enter, F2, Delete, Ctrl+D /
R / C / V / Z, Shift+arrow / Shift+click for ranges).
* The auto-save model + per-row state swatch colors.
* The customization model with a worked file-tree example.
Replaces the obsolete pre-Phase-1 wording that referenced
`*.table.yaml` parent files and click-to-navigate-row UX.
Tests: no schema test changes — the default YAMLs are loaded
through the same RecognizeTableRequest / RecognizeFormRequest
paths that already cover the fallback. Full Playwright + Go
suites green (44 + 13).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
188 lines
8.8 KiB
HTML
188 lines
8.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>ZDDC Table</title>
|
|
<link rel="icon" type="image/svg+xml" href="{{FAVICON}}">
|
|
<style>
|
|
{{CSS_PLACEHOLDER}}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header class="app-header">
|
|
<div class="header-left">
|
|
<svg class="app-header__logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" aria-hidden="true">
|
|
<rect width="64" height="64" rx="12" fill="#1e3a5f"/>
|
|
<g fill="#fff">
|
|
<rect x="14" y="18" width="36" height="7"/>
|
|
<polygon points="43,25 50,25 21,43 14,43"/>
|
|
<rect x="14" y="43" width="36" height="7"/>
|
|
</g>
|
|
</svg>
|
|
<div class="header-title-group">
|
|
<span class="app-header__title" id="table-title">ZDDC Table</span>
|
|
<span class="build-timestamp">{{BUILD_LABEL}}</span>
|
|
</div>
|
|
</div>
|
|
<div class="header-right">
|
|
<button id="theme-btn" class="btn btn-secondary" title="Theme: auto (follows OS)" aria-label="Theme: auto (follows OS)">◐</button>
|
|
<button id="help-btn" class="btn btn-secondary" title="Help" aria-label="Help">?</button>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Table mode: shown for /<dir>/table.html requests. -->
|
|
<main id="table-mode" class="table-main" hidden>
|
|
<div id="table-description" class="table-description" hidden></div>
|
|
<div id="table-status" class="table-status" hidden></div>
|
|
<div class="table-toolbar" id="table-toolbar">
|
|
<div class="table-toolbar__left">
|
|
<span id="table-rowcount" class="table-rowcount" aria-live="polite"></span>
|
|
<button type="button" id="table-clear-filters" class="btn btn-secondary btn-sm" hidden>Clear filters</button>
|
|
</div>
|
|
<div class="table-toolbar__right">
|
|
<a id="table-add-row" class="btn btn-primary btn-sm" hidden>+ Add row</a>
|
|
</div>
|
|
</div>
|
|
<div class="table-scroll">
|
|
<table id="table-root" class="zddc-table" aria-describedby="table-description">
|
|
<thead></thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
<div id="table-empty" class="table-empty" hidden>No rows match the current filters.</div>
|
|
</main>
|
|
|
|
<!-- Form mode: shown for /<dir>/form.html and /<dir>/<id>.yaml.html
|
|
requests. Same bundle ships both modes so a row's "+ Add row"
|
|
and click-to-edit reuse the table tool's spec, validator, and
|
|
file-IO instead of duplicating them in a separate form HTML. -->
|
|
<main id="form-mode" class="form-main" hidden>
|
|
<div id="form-status" class="form-status" hidden></div>
|
|
<form id="form-root" class="form-root" novalidate></form>
|
|
<div class="form-actions">
|
|
<button type="button" id="submit-btn" class="btn btn-primary">Submit</button>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Help Panel -->
|
|
<aside id="help-panel" class="help-panel" hidden aria-labelledby="help-panel-title">
|
|
<div class="help-panel__header">
|
|
<h2 id="help-panel-title" class="help-panel__title">Help — ZDDC Table</h2>
|
|
<button type="button" class="help-panel__close" id="help-panel-close" aria-label="Close">×</button>
|
|
</div>
|
|
<div class="help-panel__body">
|
|
<h3>What is this table?</h3>
|
|
<p>The directory you opened — say <code>archive/Acme/mdl/</code> —
|
|
<em>is</em> the table. <code>table.yaml</code> describes the
|
|
columns; <code>form.yaml</code> describes the row-edit form
|
|
schema; every other <code>.yaml</code> file in the directory
|
|
is one row. Copying the directory anywhere takes the whole
|
|
table (spec + form + every row) with it.</p>
|
|
|
|
<h3>Editing cells</h3>
|
|
<p>Click a cell to select it. Then:</p>
|
|
<dl>
|
|
<dt><kbd>↑</kbd> / <kbd>↓</kbd> / <kbd>←</kbd> / <kbd>→</kbd></dt>
|
|
<dd>Move selection. Hold <kbd>Shift</kbd> to extend a range.</dd>
|
|
<dt><kbd>Tab</kbd> / <kbd>Shift+Tab</kbd></dt>
|
|
<dd>Move right / left, wrap to next / previous row.</dd>
|
|
<dt><kbd>Enter</kbd> / <kbd>F2</kbd> / double-click / typing</dt>
|
|
<dd>Enter edit mode. Typing replaces the cell value; the
|
|
others keep it.</dd>
|
|
<dt><kbd>Enter</kbd> in edit mode</dt>
|
|
<dd>Commit and move down.</dd>
|
|
<dt><kbd>Tab</kbd> in edit mode</dt>
|
|
<dd>Commit and move right.</dd>
|
|
<dt><kbd>Esc</kbd></dt>
|
|
<dd>Cancel the edit; restore the prior value.</dd>
|
|
<dt><kbd>Delete</kbd> / <kbd>Backspace</kbd></dt>
|
|
<dd>Clear every cell in the current selection.</dd>
|
|
<dt><kbd>Ctrl+D</kbd> / <kbd>Ctrl+R</kbd></dt>
|
|
<dd>Fill the top row down / left column right through the
|
|
selected range.</dd>
|
|
<dt><kbd>Ctrl+C</kbd> / <kbd>Ctrl+V</kbd></dt>
|
|
<dd>Copy / paste — interoperates with Excel and Google
|
|
Sheets via tab-separated values.</dd>
|
|
<dt><kbd>Ctrl+Z</kbd></dt>
|
|
<dd>Undo the last edit (one history per session).</dd>
|
|
</dl>
|
|
<p>Edits save automatically when you move to a different row.
|
|
A small left-edge swatch on the row indicates state:
|
|
<strong>blue</strong> = unsaved, <strong>amber</strong> = the
|
|
server flagged a validation error, <strong>orange</strong> =
|
|
someone else changed this row since you loaded it (you'll
|
|
get a prompt with <em>Use mine</em> / <em>Reload</em>).</p>
|
|
|
|
<h3>Sorting</h3>
|
|
<p>Click a column header to sort by that column. Click again to
|
|
toggle direction. <kbd>Shift</kbd>-click another header to
|
|
add a secondary sort key.</p>
|
|
|
|
<h3>Filtering</h3>
|
|
<p>Type in the box under a column header to filter rows whose
|
|
value contains your text (case-insensitive). Same filter UI
|
|
for every column.</p>
|
|
|
|
<h3>Customizing the columns</h3>
|
|
<p>The default Master Deliverables List has columns for every
|
|
component of a tracking number
|
|
(<code>originator</code>, <code>phase</code>,
|
|
<code>project</code>, <code>area</code>,
|
|
<code>discipline</code>, <code>type</code>,
|
|
<code>sequence</code>, <code>suffix</code>) plus deliverable
|
|
metadata. To customize, drop your own
|
|
<code>table.yaml</code> (and matching
|
|
<code>form.yaml</code>) into this directory:</p>
|
|
<pre><code>archive/<party>/mdl/
|
|
table.yaml ← columns + sort/filter defaults
|
|
form.yaml ← per-row schema (JSON Schema)
|
|
<id>.yaml ... ← rows</code></pre>
|
|
<p>Operator-supplied files override the embedded defaults.
|
|
Hide a column by omitting it from <code>columns:</code>;
|
|
add a column by appending one (and adding the matching
|
|
property in <code>form.yaml</code>'s
|
|
<code>schema.properties</code>). The same pattern works
|
|
for any directory — <code><dir>/table.html</code>
|
|
is automatically a table whenever
|
|
<code><dir>/table.yaml</code> exists.</p>
|
|
|
|
<h3>Permissions</h3>
|
|
<p>Whether a row is editable depends on the cascading
|
|
<code>.zddc</code> permissions for the directory. Rows
|
|
in <code>Issued</code> or <code>Received</code> archives
|
|
are read-only by design (WORM).</p>
|
|
|
|
<h3>Header buttons</h3>
|
|
<dl>
|
|
<dt>◐ Theme</dt>
|
|
<dd>Cycle auto / light / dark.</dd>
|
|
<dt>? Help</dt>
|
|
<dd>This panel. Press <kbd>Esc</kbd> to close.</dd>
|
|
</dl>
|
|
</div>
|
|
</aside>
|
|
|
|
<!--
|
|
Server injects the table context here on render. Shape:
|
|
{
|
|
"title": "Optional page title override",
|
|
"description": "Optional description shown above the table",
|
|
"columns": [{field, title, width?, format?, filter?, sort?, enum?}],
|
|
"rows": [{url, data, editable}],
|
|
"defaults": {sort?: [{field, dir}], filter?: {field: value}}
|
|
}
|
|
-->
|
|
<script id="table-context" type="application/json">{}</script>
|
|
|
|
<!--
|
|
Form mode context — server injects this for /<dir>/form.html and
|
|
/<dir>/<id>.yaml.html. Empty in table-mode renders.
|
|
-->
|
|
<script id="form-context" type="application/json">{}</script>
|
|
|
|
<script>
|
|
{{JS_PLACEHOLDER}}
|
|
</script>
|
|
</body>
|
|
</html>
|