feat(tables): Edit YAML row-context menu item
Opens the row's backing .yaml in the browse tool's YAML editor (preview-yaml.js — CodeMirror with syntax highlight, lint, Ctrl+S save). Disabled on multi-row range and unsaved draft rows. Three URL shapes resolve correctly: per-party row → <dir>/?file=<file>.yaml SSR virtual → /<project>/archive/<party>/?file=ssr.yaml rollup virtual → /<project>/archive/<party>/<slot>/?file=<file>.yaml Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f3d334a221
commit
1604b62477
2 changed files with 121 additions and 25 deletions
|
|
@ -150,13 +150,60 @@
|
|||
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).
|
||||
const singleRow = targets.length === 1 ? ctx.row : null;
|
||||
const editUrl = singleRow && !singleRow.isNew ? browseEditUrl(singleRow) : null;
|
||||
items.push({
|
||||
label: 'Edit YAML',
|
||||
icon: '✎',
|
||||
disabled: !editUrl,
|
||||
action: function () {
|
||||
if (editUrl) window.location.href = editUrl;
|
||||
}
|
||||
});
|
||||
|
||||
items.push({ separator: true });
|
||||
|
||||
const label = targets.length > 1 ? 'Delete ' + targets.length + ' rows' : 'Delete row';
|
||||
return [
|
||||
{
|
||||
items.push({
|
||||
label: label,
|
||||
icon: '🗑',
|
||||
danger: true,
|
||||
|
|
@ -165,8 +212,9 @@
|
|||
if (targets.length > 1) deleteRows(targets);
|
||||
else deleteRow(targets[0]);
|
||||
}
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function onRowContext(ev) {
|
||||
|
|
|
|||
|
|
@ -1511,7 +1511,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:13:20 · cef7188-dirty</span></span>
|
||||
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-alpha · 2026-05-19 13:30:29 · f3d334a-dirty</span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
|
|
@ -5749,13 +5749,60 @@ 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).
|
||||
const singleRow = targets.length === 1 ? ctx.row : null;
|
||||
const editUrl = singleRow && !singleRow.isNew ? browseEditUrl(singleRow) : null;
|
||||
items.push({
|
||||
label: 'Edit YAML',
|
||||
icon: '✎',
|
||||
disabled: !editUrl,
|
||||
action: function () {
|
||||
if (editUrl) window.location.href = editUrl;
|
||||
}
|
||||
});
|
||||
|
||||
items.push({ separator: true });
|
||||
|
||||
const label = targets.length > 1 ? 'Delete ' + targets.length + ' rows' : 'Delete row';
|
||||
return [
|
||||
{
|
||||
items.push({
|
||||
label: label,
|
||||
icon: '🗑',
|
||||
danger: true,
|
||||
|
|
@ -5764,8 +5811,9 @@ body.is-elevated::after {
|
|||
if (targets.length > 1) deleteRows(targets);
|
||||
else deleteRow(targets[0]);
|
||||
}
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function onRowContext(ev) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue