feat(tables): row context-menu opens the form, not raw YAML

Replace "Edit YAML" with "Edit row" — navigates to row.url, which
is already the schema-driven form-mode editor URL. The form handler
unwraps virtual-view URLs server-side so SSR and rollup rows route
to their per-party canonical paths automatically; no client-side
URL rewriting needed.

This fills the gap where row-click only opens the form for
complex-type cells (objects, arrays) — for plain scalars it enters
inline edit mode. Right-click → Edit row is now the discoverable
way to reach the full form for any row.

Raw YAML editing remains available via the browse tool directly
(navigate to the file's parent folder and click it in the tree).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-05-19 08:43:45 -05:00
parent 1721b4b1db
commit f9ba493145
2 changed files with 17 additions and 71 deletions

View file

@ -150,49 +150,22 @@
return { status: 'ok', deleted: okCount, failed: failCount };
}
// Map a row's yamlUrl to the browse-tool deep-link that opens the
// file in the YAML editor (preview-yaml.js). Three URL shapes:
//
// /<project>/archive/<party>/<...>/<file>.yaml
// → /<project>/archive/<party>/<...>/?file=<file>.yaml
// (already canonical — just split into dir + file)
//
// /<project>/ssr/<party>.yaml (virtual SSR row)
// → /<project>/archive/<party>/?file=ssr.yaml
//
// /<project>/(mdl|rsk)/<party>__<file>.yaml (virtual rollup row)
// → /<project>/archive/<party>/(mdl|rsk)/?file=<file>.yaml
//
// Returns null when no editable URL is reachable (unsaved row, or
// a yamlUrl shape we don't recognize).
function browseEditUrl(row) {
if (!row || !row.yamlUrl) return null;
const url = row.yamlUrl;
let m = url.match(/^(\/[^/]+)\/ssr\/([^/]+)\.yaml$/);
if (m) return m[1] + '/archive/' + m[2] + '/?file=ssr.yaml';
m = url.match(/^(\/[^/]+)\/(mdl|rsk)\/([^/]+)__(.+)\.yaml$/);
if (m) return m[1] + '/archive/' + m[3] + '/' + m[2] + '/?file=' + m[4] + '.yaml';
const slash = url.lastIndexOf('/');
if (slash < 0) return null;
return url.slice(0, slash + 1) + '?file=' + url.slice(slash + 1);
}
function buildRowMenu(ctx) {
const rangeRows = ctx.rangeRowIds || [];
const inRange = rangeRows.length > 1 && rangeRows.indexOf(ctx.rowId) !== -1;
const targets = inRange ? rangeRows : [ctx.rowId];
const items = [];
// Edit YAML — opens the row's backing .yaml file in the browse
// tool's YAML editor. Disabled on multi-row range and unsaved
// draft rows (no file on disk yet).
// Edit row — opens the schema-driven form-mode editor for
// this row. row.url is already the <id>.yaml.html form URL
// (the form handler unwraps virtual-view URLs server-side, so
// SSR + rollup rows route to their per-party canonical paths
// automatically). Disabled on multi-row range and unsaved
// draft rows (no backing file yet).
const singleRow = targets.length === 1 ? ctx.row : null;
const editUrl = singleRow && !singleRow.isNew ? browseEditUrl(singleRow) : null;
const editUrl = singleRow && !singleRow.isNew && singleRow.url ? singleRow.url : null;
items.push({
label: 'Edit YAML',
label: 'Edit row',
icon: '✎',
disabled: !editUrl,
action: function () {

View file

@ -1515,7 +1515,7 @@ body.is-elevated::after {
</svg>
<div class="header-title-group">
<span class="app-header__title" id="table-title">ZDDC Table</span>
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-alpha · 2026-05-19 13:37:29 · 1604b62-dirty</span></span>
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-alpha · 2026-05-19 13:42:33 · 1721b4b-dirty</span></span>
</div>
</div>
<div class="header-right">
@ -5817,49 +5817,22 @@ body.is-elevated::after {
return { status: 'ok', deleted: okCount, failed: failCount };
}
// Map a row's yamlUrl to the browse-tool deep-link that opens the
// file in the YAML editor (preview-yaml.js). Three URL shapes:
//
// /<project>/archive/<party>/<...>/<file>.yaml
// → /<project>/archive/<party>/<...>/?file=<file>.yaml
// (already canonical — just split into dir + file)
//
// /<project>/ssr/<party>.yaml (virtual SSR row)
// → /<project>/archive/<party>/?file=ssr.yaml
//
// /<project>/(mdl|rsk)/<party>__<file>.yaml (virtual rollup row)
// → /<project>/archive/<party>/(mdl|rsk)/?file=<file>.yaml
//
// Returns null when no editable URL is reachable (unsaved row, or
// a yamlUrl shape we don't recognize).
function browseEditUrl(row) {
if (!row || !row.yamlUrl) return null;
const url = row.yamlUrl;
let m = url.match(/^(\/[^/]+)\/ssr\/([^/]+)\.yaml$/);
if (m) return m[1] + '/archive/' + m[2] + '/?file=ssr.yaml';
m = url.match(/^(\/[^/]+)\/(mdl|rsk)\/([^/]+)__(.+)\.yaml$/);
if (m) return m[1] + '/archive/' + m[3] + '/' + m[2] + '/?file=' + m[4] + '.yaml';
const slash = url.lastIndexOf('/');
if (slash < 0) return null;
return url.slice(0, slash + 1) + '?file=' + url.slice(slash + 1);
}
function buildRowMenu(ctx) {
const rangeRows = ctx.rangeRowIds || [];
const inRange = rangeRows.length > 1 && rangeRows.indexOf(ctx.rowId) !== -1;
const targets = inRange ? rangeRows : [ctx.rowId];
const items = [];
// Edit YAML — opens the row's backing .yaml file in the browse
// tool's YAML editor. Disabled on multi-row range and unsaved
// draft rows (no file on disk yet).
// Edit row — opens the schema-driven form-mode editor for
// this row. row.url is already the <id>.yaml.html form URL
// (the form handler unwraps virtual-view URLs server-side, so
// SSR + rollup rows route to their per-party canonical paths
// automatically). Disabled on multi-row range and unsaved
// draft rows (no backing file yet).
const singleRow = targets.length === 1 ? ctx.row : null;
const editUrl = singleRow && !singleRow.isNew ? browseEditUrl(singleRow) : null;
const editUrl = singleRow && !singleRow.isNew && singleRow.url ? singleRow.url : null;
items.push({
label: 'Edit YAML',
label: 'Edit row',
icon: '✎',
disabled: !editUrl,
action: function () {