@lmzhen/dsh-evolution-merge-ui 0.34.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +615 -289
- package/lib/types/client/MergeRow.d.ts +34 -0
- package/lib/types/client/MergeRunStrip.d.ts +16 -0
- package/lib/types/client/MergeSettings.d.ts +15 -0
- package/lib/types/client/MergeStore.d.ts +13 -0
- package/lib/types/client/Panel.d.ts +1 -1
- package/lib/types/client/api.d.ts +1 -1
- package/lib/types/client/merge-presentation.d.ts +20 -0
- package/package.json +2 -2
- package/lib/types/client/platform-menu.d.ts +0 -52
package/lib/client.js
CHANGED
|
@@ -272,6 +272,144 @@ window.__ModuleLoader__.load({
|
|
|
272
272
|
} catch {}
|
|
273
273
|
}
|
|
274
274
|
//#endregion
|
|
275
|
+
//#region ../evolution-client-kit/src/format.ts
|
|
276
|
+
/**
|
|
277
|
+
* Format an ISO string, epoch milliseconds, or null as local wall time.
|
|
278
|
+
* Invalid values return null; callers decide how to say "unknown".
|
|
279
|
+
* @param value - ISO string, epoch ms, or null.
|
|
280
|
+
* @param options - seconds on/off; defaults to on.
|
|
281
|
+
* @returns the formatted local time, or null when the value is absent/invalid.
|
|
282
|
+
*/
|
|
283
|
+
function formatLocalDateTime(value, options = {}) {
|
|
284
|
+
if (value === null || value === void 0) return null;
|
|
285
|
+
const ms = typeof value === "number" ? value : Date.parse(value);
|
|
286
|
+
if (!Number.isFinite(ms)) return null;
|
|
287
|
+
const date = new Date(ms);
|
|
288
|
+
if (Number.isNaN(date.getTime())) return null;
|
|
289
|
+
const pad = (part) => String(part).padStart(2, "0");
|
|
290
|
+
const head = String(date.getFullYear()) + "-" + pad(date.getMonth() + 1) + "-" + pad(date.getDate()) + " " + pad(date.getHours()) + ":" + pad(date.getMinutes());
|
|
291
|
+
return options.seconds === false ? head : head + ":" + pad(date.getSeconds());
|
|
292
|
+
}
|
|
293
|
+
//#endregion
|
|
294
|
+
//#region ../evolution-client-kit/src/notice.ts
|
|
295
|
+
/** One inline state notice: semantic tone plus text, no surface-specific styling. */
|
|
296
|
+
//#endregion
|
|
297
|
+
//#region ../evolution-client-kit/src/presentation/decision-frame.ts
|
|
298
|
+
/** One decision card: title, facts, at most one primary, secondary actions and details. */
|
|
299
|
+
function actionButton(action, role) {
|
|
300
|
+
return (0, react.createElement)("button", {
|
|
301
|
+
key: action.id,
|
|
302
|
+
type: "button",
|
|
303
|
+
"data-role": role === "primary" ? "decision-primary" : "decision-secondary",
|
|
304
|
+
"data-action": action.id,
|
|
305
|
+
"aria-busy": action.busy === true ? "true" : void 0,
|
|
306
|
+
...action.attributes ?? {},
|
|
307
|
+
disabled: action.disabled === true || action.busy === true,
|
|
308
|
+
title: action.title ?? action.label,
|
|
309
|
+
onClick: () => {
|
|
310
|
+
if (action.disabled !== true && action.busy !== true) action.onSelect();
|
|
311
|
+
}
|
|
312
|
+
}, action.label);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Render the one-card decision surface. The model has a singular primary on purpose.
|
|
316
|
+
* @param props - decision model and optional surface class.
|
|
317
|
+
* @returns the decision frame.
|
|
318
|
+
*/
|
|
319
|
+
function DecisionFrame({ decision, className }) {
|
|
320
|
+
const secondary = decision.secondary ?? [];
|
|
321
|
+
return (0, react.createElement)("section", {
|
|
322
|
+
"data-role": "decision-frame",
|
|
323
|
+
...className === void 0 ? {} : { className }
|
|
324
|
+
}, (0, react.createElement)("h2", { "data-role": "decision-title" }, decision.title), decision.summary === void 0 || decision.summary === "" ? null : (0, react.createElement)("p", { "data-role": "decision-summary" }, decision.summary), decision.facts.length === 0 ? null : (0, react.createElement)("dl", { "data-role": "decision-facts" }, decision.facts.map((fact) => (0, react.createElement)("div", {
|
|
325
|
+
key: fact.label,
|
|
326
|
+
"data-role": "decision-fact"
|
|
327
|
+
}, (0, react.createElement)("dt", null, fact.label), (0, react.createElement)("dd", null, fact.value)))), decision.details === void 0 ? null : (0, react.createElement)("div", { "data-role": "decision-details" }, decision.details), decision.primary === void 0 && secondary.length === 0 ? null : (0, react.createElement)("div", { "data-role": "decision-actions" }, decision.primary === void 0 ? null : actionButton(decision.primary, "primary"), secondary.map((action) => actionButton(action, "secondary"))));
|
|
328
|
+
}
|
|
329
|
+
//#endregion
|
|
330
|
+
//#region ../evolution-client-kit/src/presentation/task-banner.ts
|
|
331
|
+
/** A read-only task hint; it deliberately has no primary action. */
|
|
332
|
+
/**
|
|
333
|
+
* Render a task count plus one sentence. The absence of an action prop is the contract.
|
|
334
|
+
* @param props - count, sentence and optional surface class.
|
|
335
|
+
* @returns the banner.
|
|
336
|
+
*/
|
|
337
|
+
function TaskBanner({ count, text, className }) {
|
|
338
|
+
return (0, react.createElement)("div", {
|
|
339
|
+
"data-role": "task-banner",
|
|
340
|
+
"data-count": String(count),
|
|
341
|
+
role: "status",
|
|
342
|
+
...className === void 0 ? {} : { className }
|
|
343
|
+
}, (0, react.createElement)("strong", { "data-role": "task-banner-count" }, String(count)), (0, react.createElement)("span", { "data-role": "task-banner-text" }, text));
|
|
344
|
+
}
|
|
345
|
+
//#endregion
|
|
346
|
+
//#region ../evolution-client-kit/src/presentation/chips.ts
|
|
347
|
+
/** Read-only status chips and toggleable filter chips. */
|
|
348
|
+
//#endregion
|
|
349
|
+
//#region ../evolution-client-kit/src/presentation/empty-state.ts
|
|
350
|
+
/** A compact completed/empty state with at most one primary next step. */
|
|
351
|
+
//#endregion
|
|
352
|
+
//#region ../evolution-client-kit/src/presentation/disclosure-group.ts
|
|
353
|
+
/** A native details group for normal/secondary facts. */
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region ../evolution-client-kit/src/presentation/time-text.ts
|
|
356
|
+
/** The one local-time presentation used by reading surfaces. */
|
|
357
|
+
//#endregion
|
|
358
|
+
//#region ../evolution-client-kit/src/presentation/action-menu.ts
|
|
359
|
+
/**
|
|
360
|
+
* The one seam onto the platform's menu material, plus a small fallback for deployments
|
|
361
|
+
* without the primitive row. No page owns a second menu implementation.
|
|
362
|
+
*/
|
|
363
|
+
const PLATFORM_UI_MODULE$1 = "@deepseek-ai/dsh-client-ui-primitives";
|
|
364
|
+
/**
|
|
365
|
+
* Render the platform menu directly. Kept exported for callers that already own the primitive row.
|
|
366
|
+
* @param primitives - platform MenuSurface/MenuItemButton pair.
|
|
367
|
+
* @param actions - rows in display order.
|
|
368
|
+
* @param label - accessible menu name.
|
|
369
|
+
* @param style - fixed position computed from the pointer.
|
|
370
|
+
* @param className - optional surface class.
|
|
371
|
+
* @returns the menu element.
|
|
372
|
+
*/
|
|
373
|
+
function renderPlatformMenu(primitives, actions, label, style, className) {
|
|
374
|
+
return (0, react.createElement)(primitives.MenuSurface, {
|
|
375
|
+
"data-role": "action-menu",
|
|
376
|
+
"data-platform": "true",
|
|
377
|
+
role: "menu",
|
|
378
|
+
"aria-label": label,
|
|
379
|
+
...className === void 0 ? {} : { className },
|
|
380
|
+
style
|
|
381
|
+
}, actions.map((action) => (0, react.createElement)(primitives.MenuItemButton, {
|
|
382
|
+
key: action.id,
|
|
383
|
+
children: action.label,
|
|
384
|
+
...action.separatorBefore === true ? { separatorBefore: true } : {},
|
|
385
|
+
...action.disabled === true ? { disabled: true } : {},
|
|
386
|
+
...action.danger === true ? { danger: true } : {},
|
|
387
|
+
onSelect: action.onSelect
|
|
388
|
+
})));
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Accept only the two component functions; a namespace row without them is not a menu.
|
|
392
|
+
* @param row - the module row's exports.
|
|
393
|
+
* @returns the two components, or undefined.
|
|
394
|
+
*/
|
|
395
|
+
function menuPrimitivesFrom(row) {
|
|
396
|
+
const surface = row.MenuSurface;
|
|
397
|
+
const item = row.MenuItemButton;
|
|
398
|
+
if (typeof surface !== "function" || typeof item !== "function") return void 0;
|
|
399
|
+
return {
|
|
400
|
+
MenuSurface: surface,
|
|
401
|
+
MenuItemButton: item
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
/** The module-table row, when this deployment carries it. */
|
|
405
|
+
const PLATFORM_MENU = (() => {
|
|
406
|
+
try {
|
|
407
|
+
return menuPrimitivesFrom(require(PLATFORM_UI_MODULE$1));
|
|
408
|
+
} catch {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
})();
|
|
412
|
+
//#endregion
|
|
275
413
|
//#region src/client/api.ts
|
|
276
414
|
/** Read-only merge wire client. Classifies every failure and never writes. */
|
|
277
415
|
const HOST_ROUTES = ROUTES.merge;
|
|
@@ -628,7 +766,7 @@ window.__ModuleLoader__.load({
|
|
|
628
766
|
reason: item.reason,
|
|
629
767
|
...item.reasonCode === void 0 ? {} : { reasonCode: item.reasonCode },
|
|
630
768
|
lastVersion: item.lastVersion,
|
|
631
|
-
archivedAt: new Date(item.archivedAt).toISOString(),
|
|
769
|
+
archivedAt: item.archivedAt === null ? null : new Date(item.archivedAt).toISOString(),
|
|
632
770
|
...item.sourceRunId === void 0 ? {} : { sourceRunId: item.sourceRunId }
|
|
633
771
|
})) }
|
|
634
772
|
} : answer;
|
|
@@ -641,15 +779,18 @@ window.__ModuleLoader__.load({
|
|
|
641
779
|
const NS = "evolution-merge";
|
|
642
780
|
const zh = {
|
|
643
781
|
"entry.label": "技能合并",
|
|
644
|
-
"title": "
|
|
782
|
+
"title": "合并建议",
|
|
783
|
+
"task.pending": "条合并建议待处理",
|
|
645
784
|
"start.scan": "复制扫描命令",
|
|
646
785
|
"start.pair": "复制配对命令模板",
|
|
647
786
|
"degraded": "读模型降级:",
|
|
648
787
|
"copied": "已复制:",
|
|
649
788
|
"copyFailed": "复制失败:浏览器没有接受剪贴板写入。",
|
|
789
|
+
"copyRetry": "重试复制",
|
|
650
790
|
"row.noSummary": "无摘要",
|
|
791
|
+
"row.summaryBoth": "双方摘要",
|
|
651
792
|
"overlay.body": "正文",
|
|
652
|
-
"hint": "
|
|
793
|
+
"hint": "先处理需要判断的合并,其他信息按需展开。",
|
|
653
794
|
"history": "历史",
|
|
654
795
|
"close": "关闭",
|
|
655
796
|
"tab.verify": "待判断",
|
|
@@ -691,6 +832,9 @@ window.__ModuleLoader__.load({
|
|
|
691
832
|
"row.failure": "失败",
|
|
692
833
|
"row.noRetry": "不可重试",
|
|
693
834
|
"row.copy": "复制命令",
|
|
835
|
+
"row.more": "更多命令",
|
|
836
|
+
"row.viewBoth": "查看双方",
|
|
837
|
+
"overlay.pair": "查看双方",
|
|
694
838
|
"tab.expired": "已过期",
|
|
695
839
|
"row.targetCreated": "新建",
|
|
696
840
|
"row.verify": "判定状态",
|
|
@@ -730,6 +874,7 @@ window.__ModuleLoader__.load({
|
|
|
730
874
|
"disabled.unavailable": "暂不可用",
|
|
731
875
|
"history.empty": "没有历史。",
|
|
732
876
|
"history.archivedAt": "归档于 {date}",
|
|
877
|
+
"history.archivedAtUnknown": "归档时间未知",
|
|
733
878
|
"failureServer": "读取失败",
|
|
734
879
|
"failureUnauthorized": "未登录",
|
|
735
880
|
"failureForbidden": "无权访问",
|
|
@@ -808,6 +953,9 @@ window.__ModuleLoader__.load({
|
|
|
808
953
|
"settings.capabilityDisabled": "当前部署不可用",
|
|
809
954
|
"settings.readonly": "只读显示;修改请到平台设置页。",
|
|
810
955
|
"run.title": "运行",
|
|
956
|
+
"run.progressUnknown": "进度未知",
|
|
957
|
+
"run.current": "当前运行",
|
|
958
|
+
"run.last": "上次完成",
|
|
811
959
|
"run.id": "运行编号",
|
|
812
960
|
"run.state": "状态",
|
|
813
961
|
"run.stage": "阶段",
|
|
@@ -843,15 +991,18 @@ window.__ModuleLoader__.load({
|
|
|
843
991
|
});
|
|
844
992
|
const en = {
|
|
845
993
|
"entry.label": "Skill merge",
|
|
846
|
-
"title": "
|
|
994
|
+
"title": "Merge suggestions",
|
|
995
|
+
"task.pending": "merge suggestions need attention",
|
|
847
996
|
"start.scan": "Copy scan command",
|
|
848
997
|
"start.pair": "Copy pair command template",
|
|
849
998
|
"degraded": "Degraded read model:",
|
|
850
999
|
"copied": "Copied:",
|
|
851
1000
|
"copyFailed": "Copy failed: the browser did not accept the clipboard write.",
|
|
1001
|
+
"copyRetry": "Retry copy",
|
|
852
1002
|
"row.noSummary": "No summary",
|
|
1003
|
+
"row.summaryBoth": "Shared summary",
|
|
853
1004
|
"overlay.body": "Body",
|
|
854
|
-
"hint": "
|
|
1005
|
+
"hint": "Resolve the merges that need a decision first; everything else stays folded.",
|
|
855
1006
|
"history": "History",
|
|
856
1007
|
"close": "Close",
|
|
857
1008
|
"tab.verify": "To judge",
|
|
@@ -893,6 +1044,9 @@ window.__ModuleLoader__.load({
|
|
|
893
1044
|
"row.failure": "Failure",
|
|
894
1045
|
"row.noRetry": "not retryable",
|
|
895
1046
|
"row.copy": "Copy command",
|
|
1047
|
+
"row.more": "More commands",
|
|
1048
|
+
"row.viewBoth": "View both",
|
|
1049
|
+
"overlay.pair": "View both",
|
|
896
1050
|
"tab.expired": "Expired",
|
|
897
1051
|
"row.targetCreated": "created",
|
|
898
1052
|
"row.verify": "Verify state",
|
|
@@ -932,6 +1086,7 @@ window.__ModuleLoader__.load({
|
|
|
932
1086
|
"disabled.unavailable": "unavailable",
|
|
933
1087
|
"history.empty": "No history.",
|
|
934
1088
|
"history.archivedAt": "Archived {date}",
|
|
1089
|
+
"history.archivedAtUnknown": "Archive time unknown",
|
|
935
1090
|
"failureServer": "Read failed",
|
|
936
1091
|
"failureUnauthorized": "Not signed in",
|
|
937
1092
|
"failureForbidden": "Forbidden",
|
|
@@ -1010,6 +1165,9 @@ window.__ModuleLoader__.load({
|
|
|
1010
1165
|
"settings.capabilityDisabled": "Not available in this deployment",
|
|
1011
1166
|
"settings.readonly": "Read-only here; edit in platform settings.",
|
|
1012
1167
|
"run.title": "Run",
|
|
1168
|
+
"run.progressUnknown": "progress unknown",
|
|
1169
|
+
"run.current": "Current run",
|
|
1170
|
+
"run.last": "Last completed",
|
|
1013
1171
|
"run.id": "Run ID",
|
|
1014
1172
|
"run.state": "State",
|
|
1015
1173
|
"run.stage": "Stage",
|
|
@@ -1091,7 +1249,32 @@ window.__ModuleLoader__.load({
|
|
|
1091
1249
|
".evolution-merge-panel [data-role=\"title\"] { margin:0; font-size:var(--evo-type-lg); font-weight:600; }",
|
|
1092
1250
|
".evolution-merge-panel [data-role=\"start\"] { display:flex; gap:var(--evo-space-6); flex-wrap:wrap; }",
|
|
1093
1251
|
".evolution-merge-panel [data-role=\"degraded\"] { margin:0; color:var(--dsw-alias-state-warn-primary); font-size:var(--evo-type-xs); }",
|
|
1094
|
-
".evolution-merge-panel [data-role=\"
|
|
1252
|
+
".evolution-merge-panel [data-role=\"task-banner\"] { display:flex; align-items:baseline; gap:var(--evo-space-6); padding:var(--evo-space-10) var(--evo-space-12); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); background:var(--dsw-alias-bg-layer-1); color:var(--dsw-alias-label-primary); }",
|
|
1253
|
+
".evolution-merge-panel [data-role=\"task-banner-count\"] { font-size:var(--evo-type-lg); font-variant-numeric:tabular-nums; }",
|
|
1254
|
+
".evolution-merge-panel [data-role=\"task-banner-text\"] { color:var(--dsw-alias-label-secondary); font-size:var(--evo-type-sm); }",
|
|
1255
|
+
".evolution-merge-panel .merge-decision { display:flex; flex-direction:column; gap:var(--evo-space-8); padding:var(--evo-space-12); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); background:var(--dsw-alias-bg-layer-1); }",
|
|
1256
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-title\"] { margin:0; font-size:var(--evo-type-sm); font-weight:600; }",
|
|
1257
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-summary\"] { margin:0; color:var(--dsw-alias-label-secondary); font-size:var(--evo-type-xs); }",
|
|
1258
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-facts\"] { display:grid; grid-template-columns:max-content minmax(0,1fr); gap:var(--evo-space-4) var(--evo-space-12); margin:0; font-size:var(--evo-type-xs); }",
|
|
1259
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-fact\"] { display:contents; }",
|
|
1260
|
+
".evolution-merge-panel .merge-decision dt { color:var(--dsw-alias-label-tertiary); }",
|
|
1261
|
+
".evolution-merge-panel .merge-decision dd { margin:0; min-width:0; overflow-wrap:anywhere; }",
|
|
1262
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-actions\"] { display:flex; flex-wrap:wrap; align-items:center; gap:var(--evo-space-8); padding-top:var(--evo-space-8); }",
|
|
1263
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-primary\"], .evolution-merge-panel .merge-decision [data-role=\"decision-secondary\"], .evolution-merge-panel .merge-decision [data-role=\"view-both\"] { padding:var(--evo-space-6) var(--evo-space-12); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); background:var(--dsw-alias-bg-layer-1); color:var(--dsw-alias-label-primary); font-size:var(--evo-type-sm); cursor:pointer; }",
|
|
1264
|
+
".evolution-merge-panel [data-role=\"pair-grid\"] { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--evo-space-12); }",
|
|
1265
|
+
".evolution-merge-panel [data-role=\"body-a\"], .evolution-merge-panel [data-role=\"body-b\"] { min-width:0; }",
|
|
1266
|
+
".evolution-merge-panel [data-role=\"body-a\"] pre, .evolution-merge-panel [data-role=\"body-b\"] pre { max-height:min(52vh,560px); overflow:auto; white-space:pre-wrap; }",
|
|
1267
|
+
"@media (max-width:900px){.evolution-merge-panel [data-role=\"pair-grid\"]{grid-template-columns:minmax(0,1fr)}}",
|
|
1268
|
+
".evo-merge-modal [data-role=\"pair-grid\"]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--evo-space-12)}",
|
|
1269
|
+
".evo-merge-modal [data-role=\"body-a\"],.evo-merge-modal [data-role=\"body-b\"]{min-width:0}",
|
|
1270
|
+
".evo-merge-modal [data-role=\"body-a\"] pre,.evo-merge-modal [data-role=\"body-b\"] pre{max-height:min(52vh,560px);overflow:auto;white-space:pre-wrap}",
|
|
1271
|
+
"@media (max-width:900px){.evo-merge-modal [data-role=\"pair-grid\"]{grid-template-columns:minmax(0,1fr)}}",
|
|
1272
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-primary\"] { background:var(--dsw-alias-label-primary); border-color:transparent; color:var(--dsw-alias-label-primary-foreground); }",
|
|
1273
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-primary\"]:disabled, .evolution-merge-panel .merge-decision [data-role=\"decision-secondary\"]:disabled, .evolution-merge-panel .merge-decision [data-role=\"view-both\"]:disabled { color:var(--dsw-alias-label-dimmed); cursor:default; }",
|
|
1274
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-details\"] { display:flex; flex-direction:column; gap:var(--evo-space-4); }",
|
|
1275
|
+
".evolution-merge-panel [data-role=\"row-actions\"] { display:flex; align-items:center; justify-content:flex-end; gap:var(--evo-space-8); }",
|
|
1276
|
+
".evolution-merge-panel [data-role=\"expired-toggle\"] { display:inline-flex; align-items:center; gap:var(--evo-space-4); border:var(--evo-hairline-width) solid var(--dsw-alias-border-secondary); border-radius:var(--evo-radius-control); background:transparent; color:var(--dsw-alias-label-secondary); font:inherit; font-size:var(--evo-type-xs); padding:var(--evo-space-4) var(--evo-space-8); cursor:pointer; }",
|
|
1277
|
+
".evolution-merge-panel [data-role=\"expired-toggle\"][data-active=\"true\"] { color:var(--dsw-alias-state-warn-primary); border-color:var(--dsw-alias-state-warn-primary); background:transparent; }",
|
|
1095
1278
|
".evolution-merge-panel [data-role=\"failure\"] { display:flex; flex-direction:column; gap:var(--evo-space-6); }",
|
|
1096
1279
|
".evolution-merge-panel [data-role=\"failure\"] [data-tone=\"fail\"] { color:var(--dsw-alias-state-error-primary); }",
|
|
1097
1280
|
".evolution-merge-panel [data-role=\"fallback\"] { display:flex; gap:var(--evo-space-6); flex-wrap:wrap; }",
|
|
@@ -1106,7 +1289,7 @@ window.__ModuleLoader__.load({
|
|
|
1106
1289
|
".evolution-merge-panel [data-role=\"overlay-head\"] { display:flex; align-items:center; justify-content:space-between; gap:var(--evo-space-8); }",
|
|
1107
1290
|
".evolution-merge-panel [data-role=\"overlay-title\"] { margin:0; font-size:var(--evo-type-lg); }",
|
|
1108
1291
|
".evolution-merge-panel [data-role=\"rows\"] { display:flex; flex-direction:column; gap:var(--evo-space-6); }",
|
|
1109
|
-
".evolution-merge-panel [data-role=\"row\"] { display:
|
|
1292
|
+
".evolution-merge-panel [data-role=\"row\"] { display:flex; flex-direction:column; gap:var(--evo-space-6); padding:var(--evo-space-8); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); cursor:grab; }",
|
|
1110
1293
|
".evolution-merge-panel [data-role=\"row\"]:active { cursor:grabbing; }",
|
|
1111
1294
|
".evolution-merge-panel [data-role=\"row-label\"] { font-weight:600; }",
|
|
1112
1295
|
".evolution-merge-panel [data-role=\"row-meta\"] { color:var(--dsw-alias-label-tertiary); font-size:var(--evo-type-xs); }",
|
|
@@ -1120,7 +1303,9 @@ window.__ModuleLoader__.load({
|
|
|
1120
1303
|
".evolution-merge-panel [data-role=\"settings-card\"] { display:flex; flex-direction:column; gap:var(--evo-space-6); padding:var(--evo-space-10); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); background:var(--dsw-alias-bg-layer-1); }",
|
|
1121
1304
|
".evolution-merge-panel [data-role=\"settings-title\"] { margin:0; font-size:var(--evo-type-sm); }",
|
|
1122
1305
|
".evolution-merge-panel [data-role=\"settings-hint\"], .evolution-merge-panel [data-role=\"settings-readonly\"] { margin:0; color:var(--dsw-alias-label-tertiary); font-size:var(--evo-type-xs); }",
|
|
1123
|
-
".evolution-merge-panel [data-role=\"settings-
|
|
1306
|
+
".evolution-merge-panel [data-role=\"settings-chips\"] { display:flex; flex-wrap:wrap; gap:var(--evo-space-6); }",
|
|
1307
|
+
".evolution-merge-panel [data-role=\"settings-section\"] { display:inline-flex; align-items:center; gap:var(--evo-space-6); padding:var(--evo-space-2) var(--evo-space-8); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); font-size:var(--evo-type-xs); }",
|
|
1308
|
+
".evolution-merge-panel [data-role=\"settings-label\"] { color:var(--dsw-alias-label-secondary); }",
|
|
1124
1309
|
".evolution-merge-panel [data-role=\"settings-section\"][data-disabled=\"true\"] { color:var(--dsw-alias-label-tertiary); }",
|
|
1125
1310
|
".evolution-merge-panel [data-role=\"settings-toggle\"] { margin:0; }",
|
|
1126
1311
|
".evolution-merge-panel [data-role=\"settings-value\"] { font-weight:600; min-width:2.5em; text-align:right; }",
|
|
@@ -1144,7 +1329,7 @@ window.__ModuleLoader__.load({
|
|
|
1144
1329
|
].join("\n");
|
|
1145
1330
|
//#endregion
|
|
1146
1331
|
//#region src/client/platform-modal.ts
|
|
1147
|
-
const PLATFORM_UI_MODULE
|
|
1332
|
+
const PLATFORM_UI_MODULE = "@deepseek-ai/dsh-client-ui-primitives";
|
|
1148
1333
|
let cached;
|
|
1149
1334
|
/** The platform Modal, or undefined in a non-browser/SSR render or a deployment without the row. */
|
|
1150
1335
|
function platformModal() {
|
|
@@ -1154,7 +1339,7 @@ window.__ModuleLoader__.load({
|
|
|
1154
1339
|
return;
|
|
1155
1340
|
}
|
|
1156
1341
|
try {
|
|
1157
|
-
const row = require(PLATFORM_UI_MODULE
|
|
1342
|
+
const row = require(PLATFORM_UI_MODULE);
|
|
1158
1343
|
cached = typeof row.Modal === "function" ? row.Modal : null;
|
|
1159
1344
|
} catch {
|
|
1160
1345
|
cached = null;
|
|
@@ -1162,61 +1347,6 @@ window.__ModuleLoader__.load({
|
|
|
1162
1347
|
return cached ?? void 0;
|
|
1163
1348
|
}
|
|
1164
1349
|
//#endregion
|
|
1165
|
-
//#region src/client/platform-menu.ts
|
|
1166
|
-
/**
|
|
1167
|
-
* The one seam onto the platform's menu material and rows.
|
|
1168
|
-
*
|
|
1169
|
-
* The family bundle keeps `@deepseek-ai/*` external, so the platform components are reached through
|
|
1170
|
-
* the loader-provided `require` (the same door the Markdown seam uses). A deployment without the
|
|
1171
|
-
* row gets the panel's own menu fallback; the platform path is not a hard dependency.
|
|
1172
|
-
* @module dsh-evolution-merge-ui/client
|
|
1173
|
-
*/
|
|
1174
|
-
const PLATFORM_UI_MODULE = "@deepseek-ai/dsh-client-ui-primitives";
|
|
1175
|
-
/**
|
|
1176
|
-
* Render the coordinate menu through the platform primitives.
|
|
1177
|
-
* @param primitives - the platform MenuSurface/MenuItemButton pair.
|
|
1178
|
-
* @param actions - rows in display order.
|
|
1179
|
-
* @param label - accessible menu name.
|
|
1180
|
-
* @param style - fixed position computed from the pointer.
|
|
1181
|
-
* @returns the menu element.
|
|
1182
|
-
*/
|
|
1183
|
-
function renderPlatformMenu(primitives, actions, label, style) {
|
|
1184
|
-
return (0, react.createElement)(primitives.MenuSurface, {
|
|
1185
|
-
"data-role": "sort-menu",
|
|
1186
|
-
"data-platform": "true",
|
|
1187
|
-
role: "menu",
|
|
1188
|
-
"aria-label": label,
|
|
1189
|
-
style
|
|
1190
|
-
}, actions.map((action) => (0, react.createElement)(primitives.MenuItemButton, {
|
|
1191
|
-
key: action.id,
|
|
1192
|
-
children: action.label,
|
|
1193
|
-
...action.separatorBefore === true ? { separatorBefore: true } : {},
|
|
1194
|
-
onSelect: action.onSelect
|
|
1195
|
-
})));
|
|
1196
|
-
}
|
|
1197
|
-
/**
|
|
1198
|
-
* Accept only the two component functions; a namespace row without them is not a menu.
|
|
1199
|
-
* @param row - the module row's exports.
|
|
1200
|
-
* @returns the two components, or undefined.
|
|
1201
|
-
*/
|
|
1202
|
-
function menuPrimitivesFrom(row) {
|
|
1203
|
-
const surface = row.MenuSurface;
|
|
1204
|
-
const item = row.MenuItemButton;
|
|
1205
|
-
if (typeof surface !== "function" || typeof item !== "function") return void 0;
|
|
1206
|
-
return {
|
|
1207
|
-
MenuSurface: surface,
|
|
1208
|
-
MenuItemButton: item
|
|
1209
|
-
};
|
|
1210
|
-
}
|
|
1211
|
-
/** The module-table row, when this deployment carries it. */
|
|
1212
|
-
const PLATFORM_MENU = (() => {
|
|
1213
|
-
try {
|
|
1214
|
-
return menuPrimitivesFrom(require(PLATFORM_UI_MODULE));
|
|
1215
|
-
} catch {
|
|
1216
|
-
return;
|
|
1217
|
-
}
|
|
1218
|
-
})();
|
|
1219
|
-
//#endregion
|
|
1220
1350
|
//#region src/client/sorting.ts
|
|
1221
1351
|
/** Workspace scope for one tab. A missing panel workspace is the local scope. */
|
|
1222
1352
|
function resolveWorkspaceId(workspaceId) {
|
|
@@ -1305,121 +1435,14 @@ window.__ModuleLoader__.load({
|
|
|
1305
1435
|
return edge === "top" ? [id, ...rest] : [...rest, id];
|
|
1306
1436
|
}
|
|
1307
1437
|
//#endregion
|
|
1308
|
-
//#region src/client/
|
|
1309
|
-
/**
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
"/evolution merge candidates",
|
|
1317
|
-
"/evolution merge status",
|
|
1318
|
-
"/evolution merge report",
|
|
1319
|
-
"/evolution doctor"
|
|
1320
|
-
];
|
|
1321
|
-
//#endregion
|
|
1322
|
-
//#region src/client/Panel.ts
|
|
1323
|
-
/** Batch 4 merge panel: keyed read store, four tabs, local overlays, localized errors. */
|
|
1324
|
-
const QUEUES = [
|
|
1325
|
-
"verify",
|
|
1326
|
-
"pending",
|
|
1327
|
-
"fuse",
|
|
1328
|
-
"skipped"
|
|
1329
|
-
];
|
|
1330
|
-
const DOCTOR_COMMAND = "/evolution doctor";
|
|
1331
|
-
function problemKey(problem) {
|
|
1332
|
-
switch (problem.code) {
|
|
1333
|
-
case "unauthenticated": return "failureUnauthorized";
|
|
1334
|
-
case "forbidden": return "failureForbidden";
|
|
1335
|
-
case "unmounted": return "failureUnmounted";
|
|
1336
|
-
case "capability": return "failureCapability";
|
|
1337
|
-
case "body-ambiguous": return "failureBodyAmbiguous";
|
|
1338
|
-
case "wire-version": return "failureWireVersion";
|
|
1339
|
-
case "body-missing": return "failureBodyMissing";
|
|
1340
|
-
case "bad-query": return "failureBadQuery";
|
|
1341
|
-
case "refused": return "failureRefused";
|
|
1342
|
-
case "server": return "failureServer";
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
function reasonText(t, reasonCode, fallback) {
|
|
1346
|
-
if (reasonCode === void 0) return fallback;
|
|
1347
|
-
const key = "history.reason." + reasonCode;
|
|
1348
|
-
const text = t(key);
|
|
1349
|
-
return text === key ? fallback : text;
|
|
1350
|
-
}
|
|
1351
|
-
function blockedReasonKey(failure) {
|
|
1352
|
-
const code = failure.readiness.code ?? failure.code;
|
|
1353
|
-
if (code.endsWith("needs-repair")) return "blocked.reason.needs-repair";
|
|
1354
|
-
if (code.endsWith("forward-only")) return "blocked.reason.forward-only";
|
|
1355
|
-
if (code.endsWith("migration-blocked")) return "blocked.reason.migration-blocked";
|
|
1356
|
-
return "blocked.reason.unknown";
|
|
1357
|
-
}
|
|
1358
|
-
function failureNode(t, failure, fallback, copy) {
|
|
1359
|
-
if (isBlocked(failure)) {
|
|
1360
|
-
const raw = failure.readiness.message;
|
|
1361
|
-
return (0, react.createElement)("div", {
|
|
1362
|
-
"data-role": "blocked",
|
|
1363
|
-
role: "alert",
|
|
1364
|
-
"data-block-code": failure.code,
|
|
1365
|
-
"data-readiness-code": failure.readiness.code ?? ""
|
|
1366
|
-
}, (0, react.createElement)("h3", { "data-role": "blocked-title" }, t("blocked.title")), (0, react.createElement)("p", {
|
|
1367
|
-
"data-role": "blocked-reason",
|
|
1368
|
-
title: raw ?? t(blockedReasonKey(failure))
|
|
1369
|
-
}, t(blockedReasonKey(failure))), (0, react.createElement)("p", { "data-role": "blocked-hint" }, t("blocked.hint")), raw === void 0 ? null : (0, react.createElement)("details", { "data-role": "blocked-detail" }, (0, react.createElement)("summary", null, t("blocked.detail")), (0, react.createElement)("p", { "data-role": "blocked-raw" }, raw)), (0, react.createElement)("div", { "data-role": "blocked-actions" }, (0, react.createElement)("button", {
|
|
1370
|
-
type: "button",
|
|
1371
|
-
"data-role": "doctor",
|
|
1372
|
-
onClick: () => {
|
|
1373
|
-
copy(DOCTOR_COMMAND);
|
|
1374
|
-
}
|
|
1375
|
-
}, t("blocked.doctor")), (0, react.createElement)("button", {
|
|
1376
|
-
type: "button",
|
|
1377
|
-
"data-role": "refresh",
|
|
1378
|
-
onClick: () => {
|
|
1379
|
-
window.dispatchEvent(new Event("evolution-merge:refresh"));
|
|
1380
|
-
}
|
|
1381
|
-
}, t("refresh"))));
|
|
1382
|
-
}
|
|
1383
|
-
const capability = failure.code === "capability";
|
|
1384
|
-
return (0, react.createElement)("div", {
|
|
1385
|
-
"data-role": capability ? "capability-failure" : "failure",
|
|
1386
|
-
"data-error-code": failure.code,
|
|
1387
|
-
"data-status": String(failure.status)
|
|
1388
|
-
}, (0, react.createElement)("p", {
|
|
1389
|
-
"data-role": "failure-title",
|
|
1390
|
-
title: failure.message
|
|
1391
|
-
}, t(problemKey(failure))), capability ? (0, react.createElement)("p", { "data-role": "capability-hint" }, t("failureCapabilityHint")) : null, failure.message === void 0 ? null : (0, react.createElement)("details", { "data-role": "failure-detail" }, (0, react.createElement)("summary", null, t("failureDetails")), (0, react.createElement)("p", { "data-role": "failure-raw" }, failure.message)), fallback.length === 0 ? null : (0, react.createElement)("div", { "data-role": "fallback" }, fallback.map((command) => (0, react.createElement)("button", {
|
|
1392
|
-
key: command,
|
|
1393
|
-
type: "button",
|
|
1394
|
-
"data-role": "fallback-command",
|
|
1395
|
-
onClick: () => {
|
|
1396
|
-
copy(command);
|
|
1397
|
-
}
|
|
1398
|
-
}, command))));
|
|
1399
|
-
}
|
|
1400
|
-
function summaryNode(row, t) {
|
|
1401
|
-
if (row.state !== "pending" || row.summary === void 0) return null;
|
|
1402
|
-
return (0, react.createElement)("div", { "data-role": "pending-summary" }, [
|
|
1403
|
-
["row.summaryA", row.summary.a],
|
|
1404
|
-
["row.summaryB", row.summary.b],
|
|
1405
|
-
["row.rationale", row.summary.rationale]
|
|
1406
|
-
].map(([label, value]) => (0, react.createElement)("div", {
|
|
1407
|
-
key: label,
|
|
1408
|
-
"data-role": "pending-summary-slot"
|
|
1409
|
-
}, (0, react.createElement)("span", { "data-role": "pending-summary-label" }, t(label)), (0, react.createElement)("span", { "data-role": "pending-summary-value" }, value === null || value === "" ? t("row.noSummary") : value))));
|
|
1410
|
-
}
|
|
1411
|
-
function stageNode(row, t) {
|
|
1412
|
-
const stage = row.stageView;
|
|
1413
|
-
if (stage === void 0) return null;
|
|
1414
|
-
const tone = stage.state === "lost" ? "fail" : stage.state === "expired" || stage.state === "reserved" ? "warn" : "neutral";
|
|
1415
|
-
const expiry = stage.expiresAt === void 0 ? "" : " · " + t("row.expires") + " " + new Date(stage.expiresAt).toLocaleString();
|
|
1416
|
-
return (0, react.createElement)("span", {
|
|
1417
|
-
"data-role": "stage-badge",
|
|
1418
|
-
"data-stage": stage.state,
|
|
1419
|
-
"data-tone": tone
|
|
1420
|
-
}, t("stage.state." + stage.state) + expiry);
|
|
1421
|
-
}
|
|
1422
|
-
function runNode(view, t, copy) {
|
|
1438
|
+
//#region src/client/MergeRunStrip.ts
|
|
1439
|
+
/** The merge run strips: active/last identity, state, progress, report and details. */
|
|
1440
|
+
/**
|
|
1441
|
+
* Render active and last runs as two independently labelled strips.
|
|
1442
|
+
* @param props - view, translator and command copier.
|
|
1443
|
+
* @returns the strips, or null when neither run exists.
|
|
1444
|
+
*/
|
|
1445
|
+
function MergeRunStrips({ view, t, copy }) {
|
|
1423
1446
|
const active = view.activeRun;
|
|
1424
1447
|
const last = view.lastRun;
|
|
1425
1448
|
if (active === void 0 && last === void 0) return null;
|
|
@@ -1441,7 +1464,7 @@ window.__ModuleLoader__.load({
|
|
|
1441
1464
|
run.endedAt === void 0 ? null : (0, react.createElement)("span", {
|
|
1442
1465
|
key: "ended",
|
|
1443
1466
|
"data-role": "run-ended"
|
|
1444
|
-
}, t("run.endedAt") + " " +
|
|
1467
|
+
}, t("run.endedAt") + " " + (formatLocalDateTime(run.endedAt) ?? "")),
|
|
1445
1468
|
run.failure === void 0 ? null : (0, react.createElement)("span", {
|
|
1446
1469
|
key: "failure",
|
|
1447
1470
|
"data-role": "run-failure",
|
|
@@ -1465,7 +1488,10 @@ window.__ModuleLoader__.load({
|
|
|
1465
1488
|
"data-role": "run-strip",
|
|
1466
1489
|
"data-run-role": role,
|
|
1467
1490
|
"data-run-state": run.state
|
|
1468
|
-
}, (0, react.createElement)("span", { "data-role": "run-
|
|
1491
|
+
}, (0, react.createElement)("span", { "data-role": "run-identity" }, t(role === "active" ? "run.current" : "run.last")), (0, react.createElement)("span", { "data-role": "run-state" }, t("run.state") + " " + t("run." + run.state)), run.progress === null || run.progress === void 0 ? run.state === "succeeded" ? (0, react.createElement)("span", {
|
|
1492
|
+
"data-role": "run-progress",
|
|
1493
|
+
"data-progress": "unknown"
|
|
1494
|
+
}, t("run.progressUnknown")) : null : (0, react.createElement)("span", { "data-role": "run-progress" }, t("run.progress") + " " + String(run.progress.done) + "/" + String(run.progress.total)), (0, react.createElement)("button", {
|
|
1469
1495
|
type: "button",
|
|
1470
1496
|
"data-role": "run-report",
|
|
1471
1497
|
"data-action": "report",
|
|
@@ -1486,46 +1512,64 @@ window.__ModuleLoader__.load({
|
|
|
1486
1512
|
}
|
|
1487
1513
|
}, t("action." + action.id))), (0, react.createElement)("details", { "data-role": "run-details" }, (0, react.createElement)("summary", null, t("run.details")), ...internals));
|
|
1488
1514
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1515
|
+
//#endregion
|
|
1516
|
+
//#region src/client/merge-presentation.ts
|
|
1517
|
+
/**
|
|
1518
|
+
* Compare the two source summaries after trimming. Equal non-empty text is one fact;
|
|
1519
|
+
* missing text stays missing rather than being invented.
|
|
1520
|
+
* @param a - source A summary, or null.
|
|
1521
|
+
* @param b - source B summary, or null.
|
|
1522
|
+
* @returns the presentation form.
|
|
1523
|
+
*/
|
|
1524
|
+
function summarizePair(a, b) {
|
|
1525
|
+
const left = a?.trim() ?? "";
|
|
1526
|
+
const right = b?.trim() ?? "";
|
|
1527
|
+
if (left === "" && right === "") return { kind: "missing" };
|
|
1528
|
+
if (left !== "" && left === right) return {
|
|
1529
|
+
kind: "same",
|
|
1530
|
+
text: left
|
|
1531
|
+
};
|
|
1532
|
+
return {
|
|
1533
|
+
kind: "different",
|
|
1534
|
+
a: left === "" ? null : left,
|
|
1535
|
+
b: right === "" ? null : right
|
|
1536
|
+
};
|
|
1499
1537
|
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
return (0, react.createElement)("div", { "data-role": "settings-card" }, (0, react.createElement)("h3", { "data-role": "settings-title" }, t("settings.title")), (0, react.createElement)("p", { "data-role": "settings-hint" }, t("settings.hint")), (0, react.createElement)("p", { "data-role": "settings-path" }, t("settings.openPlatformPath")), (0, react.createElement)(ReadOnlySetting, {
|
|
1506
|
-
section: "merge-approval",
|
|
1507
|
-
label: t("settings.mergeApproval"),
|
|
1508
|
-
value: mergeFallback,
|
|
1509
|
-
disabled: false,
|
|
1510
|
-
missing: false,
|
|
1511
|
-
t
|
|
1512
|
-
}), (0, react.createElement)(ReadOnlySetting, {
|
|
1513
|
-
section: "platform-write",
|
|
1514
|
-
label: t("settings.platformWrite"),
|
|
1515
|
-
value: platformFallback,
|
|
1516
|
-
disabled: platformCapability === false,
|
|
1517
|
-
missing: platform === void 0,
|
|
1518
|
-
note: t("settings.platformWriteLinkHint"),
|
|
1519
|
-
t
|
|
1520
|
-
}), (0, react.createElement)("p", { "data-role": "settings-readonly" }, t("settings.readonly")));
|
|
1538
|
+
//#endregion
|
|
1539
|
+
//#region src/client/MergeRow.ts
|
|
1540
|
+
/** One merge row: summary, stage, facts, one primary decision and the copy/sort drawer. */
|
|
1541
|
+
function reasonText$1(t, reasonCode, fallback) {
|
|
1542
|
+
return reasonCode === void 0 ? fallback : t("history.reason." + reasonCode);
|
|
1521
1543
|
}
|
|
1522
|
-
function
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1544
|
+
function summaryNode(row, t) {
|
|
1545
|
+
if (row.state !== "pending" || row.summary === void 0) return null;
|
|
1546
|
+
const pair = summarizePair(row.summary.a, row.summary.b);
|
|
1547
|
+
const slots = pair.kind === "same" ? [[t("row.summaryBoth"), pair.text]] : pair.kind === "missing" ? [[t("row.summaryBoth"), t("row.noSummary")]] : [[t("row.summaryA"), pair.a], [t("row.summaryB"), pair.b]];
|
|
1548
|
+
slots.push([t("row.rationale"), row.summary.rationale]);
|
|
1549
|
+
return (0, react.createElement)("div", { "data-role": "pending-summary" }, slots.map(([label, value]) => (0, react.createElement)("div", {
|
|
1550
|
+
key: label,
|
|
1551
|
+
"data-role": "pending-summary-slot"
|
|
1552
|
+
}, (0, react.createElement)("span", { "data-role": "pending-summary-label" }, label), (0, react.createElement)("span", { "data-role": "pending-summary-value" }, value === null || value === "" ? t("row.noSummary") : value))));
|
|
1553
|
+
}
|
|
1554
|
+
function stageNode(row, t) {
|
|
1555
|
+
const stage = row.stageView;
|
|
1556
|
+
if (stage === void 0) return null;
|
|
1557
|
+
const tone = stage.state === "lost" ? "fail" : stage.state === "expired" || stage.state === "reserved" ? "warn" : "neutral";
|
|
1558
|
+
const expiry = stage.expiresAt === void 0 ? "" : " · " + t("row.expires") + " " + new Date(stage.expiresAt).toLocaleString();
|
|
1559
|
+
return (0, react.createElement)("span", {
|
|
1560
|
+
"data-role": "stage-badge",
|
|
1561
|
+
"data-stage": stage.state,
|
|
1562
|
+
"data-tone": tone
|
|
1563
|
+
}, t("stage.state." + stage.state) + expiry);
|
|
1564
|
+
}
|
|
1565
|
+
/**
|
|
1566
|
+
* Render one row as a decision card. The approve action is the only primary; A/B, reject and
|
|
1567
|
+
* auxiliary sort/copy commands cannot borrow that weight.
|
|
1568
|
+
* @param props - row, translator, copier, sort hooks, body opener and decision callback.
|
|
1569
|
+
* @returns the row with drag/keyboard wiring and a separate more drawer.
|
|
1570
|
+
*/
|
|
1571
|
+
function MergeRow(props) {
|
|
1572
|
+
const { row, t, copy, sort, openBoth, onDecide, busy } = props;
|
|
1529
1573
|
const details = [
|
|
1530
1574
|
t("row.id") + " " + row.id,
|
|
1531
1575
|
row.targetActual === void 0 ? void 0 : t("row.actualTarget") + " " + row.targetActual,
|
|
@@ -1534,35 +1578,83 @@ window.__ModuleLoader__.load({
|
|
|
1534
1578
|
row.attempts === void 0 ? void 0 : t("row.attempts") + " " + String(row.attempts),
|
|
1535
1579
|
row.confidence === void 0 ? void 0 : t("row.confidence") + " " + row.confidence.toFixed(2)
|
|
1536
1580
|
].filter((value) => value !== void 0).join(" · ");
|
|
1537
|
-
const
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1581
|
+
const approve = row.actions.find((action) => action.id === "approve");
|
|
1582
|
+
const reject = row.actions.find((action) => action.id === "reject");
|
|
1583
|
+
const bodyA = row.bodies?.find((body) => body.name === row.a);
|
|
1584
|
+
const bodyB = row.bodies?.find((body) => body.name === row.b);
|
|
1585
|
+
const primary = approve === void 0 ? void 0 : {
|
|
1586
|
+
id: "approve",
|
|
1587
|
+
label: t("decision.approve"),
|
|
1588
|
+
disabled: !approve.enabled || busy || onDecide === void 0,
|
|
1589
|
+
...approve.disabledReason === void 0 ? {} : { attributes: { "data-disabled-reason": approve.disabledReason } },
|
|
1590
|
+
onSelect: () => {
|
|
1591
|
+
if (approve.enabled && !busy && onDecide !== void 0) onDecide(row.id, "approve");
|
|
1592
|
+
}
|
|
1593
|
+
};
|
|
1594
|
+
const secondary = [];
|
|
1595
|
+
if (approve !== void 0 && onDecide === void 0) secondary.push({
|
|
1596
|
+
id: "approve",
|
|
1597
|
+
label: t("action.approve"),
|
|
1598
|
+
disabled: !approve.enabled || busy,
|
|
1599
|
+
attributes: { "data-role": "row-action" },
|
|
1600
|
+
onSelect: () => {
|
|
1601
|
+
if (approve.enabled && !busy) copy(approve.command);
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1604
|
+
if (reject !== void 0) secondary.push({
|
|
1605
|
+
id: "reject",
|
|
1606
|
+
label: t("decision.reject"),
|
|
1607
|
+
disabled: !reject.enabled || busy || onDecide === void 0,
|
|
1608
|
+
...reject.disabledReason === void 0 ? {} : { attributes: { "data-disabled-reason": reject.disabledReason } },
|
|
1609
|
+
onSelect: () => {
|
|
1610
|
+
if (reject.enabled && !busy && onDecide !== void 0) onDecide(row.id, "reject");
|
|
1611
|
+
}
|
|
1612
|
+
});
|
|
1613
|
+
if (bodyA !== void 0 && bodyB !== void 0) secondary.push({
|
|
1614
|
+
id: "view-both",
|
|
1615
|
+
label: t("row.viewBoth"),
|
|
1616
|
+
attributes: { "data-role": "view-both" },
|
|
1617
|
+
onSelect: () => {
|
|
1618
|
+
openBoth({
|
|
1619
|
+
name: bodyA.name,
|
|
1620
|
+
side: bodyA.side
|
|
1621
|
+
}, {
|
|
1622
|
+
name: bodyB.name,
|
|
1623
|
+
side: bodyB.side
|
|
1624
|
+
}, bodyA.rowId);
|
|
1625
|
+
}
|
|
1626
|
+
});
|
|
1627
|
+
for (const action of row.actions) {
|
|
1628
|
+
if (action.id === "approve" || action.id === "reject" || action.id === "copy" || action.id === "discard") continue;
|
|
1629
|
+
secondary.push({
|
|
1630
|
+
id: action.id,
|
|
1631
|
+
label: t("action." + action.id),
|
|
1546
1632
|
disabled: !action.enabled || busy,
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
if (
|
|
1550
|
-
else copy(action.command);
|
|
1551
|
-
}
|
|
1552
|
-
}, decision ? t("decision." + action.id) : t("action." + action.id));
|
|
1553
|
-
if (!decision) return [primary];
|
|
1554
|
-
return [primary, (0, react.createElement)("button", {
|
|
1555
|
-
key: action.id + "-copy",
|
|
1556
|
-
type: "button",
|
|
1557
|
-
"data-role": "row-copy",
|
|
1558
|
-
"data-action": action.id + "-copy",
|
|
1559
|
-
title: action.command,
|
|
1560
|
-
disabled: busy,
|
|
1561
|
-
onClick: () => {
|
|
1562
|
-
if (!busy) copy(action.command);
|
|
1633
|
+
attributes: { "data-role": "row-action" },
|
|
1634
|
+
onSelect: () => {
|
|
1635
|
+
if (action.enabled && !busy) copy(action.command);
|
|
1563
1636
|
}
|
|
1564
|
-
}
|
|
1565
|
-
}
|
|
1637
|
+
});
|
|
1638
|
+
}
|
|
1639
|
+
const facts = [
|
|
1640
|
+
...row.target === void 0 ? [] : [{
|
|
1641
|
+
label: t("row.target"),
|
|
1642
|
+
value: row.target
|
|
1643
|
+
}],
|
|
1644
|
+
...row.failure === void 0 ? [] : [{
|
|
1645
|
+
label: t("row.failure"),
|
|
1646
|
+
value: row.failure.code + (row.failure.retryable ? "" : " · " + t("row.noRetry"))
|
|
1647
|
+
}],
|
|
1648
|
+
...row.expired === void 0 ? [] : [{
|
|
1649
|
+
label: t("row.expired"),
|
|
1650
|
+
value: t("expired." + row.expired)
|
|
1651
|
+
}],
|
|
1652
|
+
...row.reasonCode === void 0 && row.reason === void 0 ? [] : [{
|
|
1653
|
+
label: t("row.reason"),
|
|
1654
|
+
value: reasonText$1(t, row.reasonCode, row.reason ?? "")
|
|
1655
|
+
}]
|
|
1656
|
+
];
|
|
1657
|
+
const decisionDetails = (0, react.createElement)("div", null, stageNode(row, t), summaryNode(row, t), bodyA === void 0 || bodyB === void 0 ? null : (0, react.createElement)("div", { "data-role": "body-names" }, "A · " + bodyA.name + " · B · " + bodyB.name), (0, react.createElement)("details", { "data-role": "row-details" }, (0, react.createElement)("summary", null, t("row.details")), (0, react.createElement)("p", null, details)));
|
|
1566
1658
|
return (0, react.createElement)("div", {
|
|
1567
1659
|
key: row.id,
|
|
1568
1660
|
"data-role": "row",
|
|
@@ -1602,7 +1694,16 @@ window.__ModuleLoader__.load({
|
|
|
1602
1694
|
event.preventDefault();
|
|
1603
1695
|
sort.menu(row.id, event.clientX, event.clientY);
|
|
1604
1696
|
}
|
|
1605
|
-
}, (0, react.createElement)(
|
|
1697
|
+
}, (0, react.createElement)(DecisionFrame, {
|
|
1698
|
+
className: "merge-decision",
|
|
1699
|
+
decision: {
|
|
1700
|
+
title: row.label,
|
|
1701
|
+
facts,
|
|
1702
|
+
...primary === void 0 ? {} : { primary },
|
|
1703
|
+
...secondary.length === 0 ? {} : { secondary },
|
|
1704
|
+
details: decisionDetails
|
|
1705
|
+
}
|
|
1706
|
+
}), (0, react.createElement)("div", { "data-role": "row-actions" }, (0, react.createElement)("div", { "data-role": "row-meta" }, new Date(row.updatedAt).toLocaleString()), (0, react.createElement)("details", { "data-role": "row-more" }, (0, react.createElement)("summary", null, t("row.more")), (0, react.createElement)("button", {
|
|
1606
1707
|
type: "button",
|
|
1607
1708
|
"data-role": "row-sort",
|
|
1608
1709
|
"aria-haspopup": "menu",
|
|
@@ -1611,29 +1712,151 @@ window.__ModuleLoader__.load({
|
|
|
1611
1712
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
1612
1713
|
sort.menu(row.id, rect.left, rect.bottom);
|
|
1613
1714
|
}
|
|
1614
|
-
}, t("sort.menu")), (() => {
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1715
|
+
}, t("sort.menu")), ...row.actions.map((action) => (0, react.createElement)("button", {
|
|
1716
|
+
key: "copy-" + action.id,
|
|
1717
|
+
type: "button",
|
|
1718
|
+
"data-role": "row-copy",
|
|
1719
|
+
"data-action": action.id + "-copy",
|
|
1720
|
+
title: action.command,
|
|
1721
|
+
disabled: busy,
|
|
1722
|
+
onClick: () => {
|
|
1723
|
+
if (!busy) copy(action.command);
|
|
1724
|
+
}
|
|
1725
|
+
}, t("row.copy") + " " + t("action." + action.id))))));
|
|
1726
|
+
}
|
|
1727
|
+
//#endregion
|
|
1728
|
+
//#region src/client/MergeSettings.ts
|
|
1729
|
+
/** The merge settings summary: two read-only state chips and one settings path. */
|
|
1730
|
+
function SettingChip({ section, label, value, disabled, missing, t }) {
|
|
1731
|
+
const text = missing ? t("settings.capabilityMissing") : disabled ? t("settings.capabilityDisabled") : value === true ? t("settings.on") : t("settings.off");
|
|
1732
|
+
const state = missing ? "missing" : disabled ? "unavailable" : value === true ? "on" : "off";
|
|
1733
|
+
return (0, react.createElement)("span", {
|
|
1734
|
+
"data-role": "settings-section",
|
|
1735
|
+
"data-section": section,
|
|
1736
|
+
"data-disabled": missing || disabled ? "true" : "false",
|
|
1737
|
+
"data-state": state
|
|
1738
|
+
}, (0, react.createElement)("span", { "data-role": "settings-label" }, label), (0, react.createElement)("span", {
|
|
1739
|
+
"data-role": "settings-value",
|
|
1740
|
+
"data-value": state
|
|
1741
|
+
}, text));
|
|
1742
|
+
}
|
|
1743
|
+
/**
|
|
1744
|
+
* Render the read-only approval state without the old large settings card.
|
|
1745
|
+
* @param props - the merge view and translator.
|
|
1746
|
+
* @returns two chips and the one current settings path.
|
|
1747
|
+
*/
|
|
1748
|
+
function MergeSettings({ view, t }) {
|
|
1749
|
+
const platform = view.approval.platformWrite;
|
|
1750
|
+
const platformCapability = platform?.capability === true;
|
|
1751
|
+
const platformFallback = platform?.enabled ?? false;
|
|
1752
|
+
return (0, react.createElement)("div", { "data-role": "settings-card" }, (0, react.createElement)("h3", { "data-role": "settings-title" }, t("settings.title")), (0, react.createElement)("p", { "data-role": "settings-path" }, t("settings.openPlatformPath")), (0, react.createElement)("div", { "data-role": "settings-chips" }, (0, react.createElement)(SettingChip, {
|
|
1753
|
+
section: "merge-approval",
|
|
1754
|
+
label: t("settings.mergeApproval"),
|
|
1755
|
+
value: view.approval.mergeApproval,
|
|
1756
|
+
disabled: false,
|
|
1757
|
+
missing: false,
|
|
1758
|
+
t
|
|
1759
|
+
}), (0, react.createElement)(SettingChip, {
|
|
1760
|
+
section: "platform-write",
|
|
1761
|
+
label: t("settings.platformWrite"),
|
|
1762
|
+
value: platformFallback,
|
|
1763
|
+
disabled: platformCapability === false,
|
|
1764
|
+
missing: platform === void 0,
|
|
1765
|
+
t
|
|
1766
|
+
})));
|
|
1767
|
+
}
|
|
1768
|
+
//#endregion
|
|
1769
|
+
//#region src/client/fallbacks.ts
|
|
1770
|
+
/** Static command-face fallback for a Facts read failure; the API fallback is unavailable then. */
|
|
1771
|
+
const FALLBACK_COMMANDS = [
|
|
1772
|
+
"/evolution merge scan",
|
|
1773
|
+
"/evolution merge pair <a> <b>",
|
|
1774
|
+
"/evolution merge pending",
|
|
1775
|
+
"/evolution merge pending --expired",
|
|
1776
|
+
"/evolution merge skipped",
|
|
1777
|
+
"/evolution merge candidates",
|
|
1778
|
+
"/evolution merge status",
|
|
1779
|
+
"/evolution merge report",
|
|
1780
|
+
"/evolution doctor"
|
|
1781
|
+
];
|
|
1782
|
+
//#endregion
|
|
1783
|
+
//#region src/client/Panel.ts
|
|
1784
|
+
/** Batch 4 merge panel: keyed read store, four tabs, local overlays, localized errors. */
|
|
1785
|
+
const QUEUES = [
|
|
1786
|
+
"verify",
|
|
1787
|
+
"pending",
|
|
1788
|
+
"fuse",
|
|
1789
|
+
"skipped"
|
|
1790
|
+
];
|
|
1791
|
+
const DOCTOR_COMMAND = "/evolution doctor";
|
|
1792
|
+
function problemKey(problem) {
|
|
1793
|
+
switch (problem.code) {
|
|
1794
|
+
case "unauthenticated": return "failureUnauthorized";
|
|
1795
|
+
case "forbidden": return "failureForbidden";
|
|
1796
|
+
case "unmounted": return "failureUnmounted";
|
|
1797
|
+
case "capability": return "failureCapability";
|
|
1798
|
+
case "body-ambiguous": return "failureBodyAmbiguous";
|
|
1799
|
+
case "wire-version": return "failureWireVersion";
|
|
1800
|
+
case "body-missing": return "failureBodyMissing";
|
|
1801
|
+
case "bad-query": return "failureBadQuery";
|
|
1802
|
+
case "refused": return "failureRefused";
|
|
1803
|
+
case "server": return "failureServer";
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
function reasonText(t, reasonCode, fallback) {
|
|
1807
|
+
if (reasonCode === void 0) return fallback;
|
|
1808
|
+
const key = "history.reason." + reasonCode;
|
|
1809
|
+
const text = t(key);
|
|
1810
|
+
return text === key ? fallback : text;
|
|
1811
|
+
}
|
|
1812
|
+
function blockedReasonKey(failure) {
|
|
1813
|
+
const code = failure.readiness.code ?? failure.code;
|
|
1814
|
+
if (code.endsWith("needs-repair")) return "blocked.reason.needs-repair";
|
|
1815
|
+
if (code.endsWith("forward-only")) return "blocked.reason.forward-only";
|
|
1816
|
+
if (code.endsWith("migration-blocked")) return "blocked.reason.migration-blocked";
|
|
1817
|
+
return "blocked.reason.unknown";
|
|
1818
|
+
}
|
|
1819
|
+
function failureNode(t, failure, fallback, copy) {
|
|
1820
|
+
if (isBlocked(failure)) {
|
|
1821
|
+
const raw = failure.readiness.message;
|
|
1822
|
+
return (0, react.createElement)("div", {
|
|
1823
|
+
"data-role": "blocked",
|
|
1824
|
+
role: "alert",
|
|
1825
|
+
"data-block-code": failure.code,
|
|
1826
|
+
"data-readiness-code": failure.readiness.code ?? ""
|
|
1827
|
+
}, (0, react.createElement)("h3", { "data-role": "blocked-title" }, t("blocked.title")), (0, react.createElement)("p", {
|
|
1828
|
+
"data-role": "blocked-reason",
|
|
1829
|
+
title: raw ?? t(blockedReasonKey(failure))
|
|
1830
|
+
}, t(blockedReasonKey(failure))), (0, react.createElement)("p", { "data-role": "blocked-hint" }, t("blocked.hint")), raw === void 0 ? null : (0, react.createElement)("details", { "data-role": "blocked-detail" }, (0, react.createElement)("summary", null, t("blocked.detail")), (0, react.createElement)("p", { "data-role": "blocked-raw" }, raw)), (0, react.createElement)("div", { "data-role": "blocked-actions" }, (0, react.createElement)("button", {
|
|
1619
1831
|
type: "button",
|
|
1620
|
-
"data-role": "
|
|
1621
|
-
"aria-label": t("body." + bodyA.side) + " " + bodyA.name,
|
|
1622
|
-
title: t("body." + bodyA.side) + " " + bodyA.name,
|
|
1832
|
+
"data-role": "doctor",
|
|
1623
1833
|
onClick: () => {
|
|
1624
|
-
|
|
1834
|
+
copy(DOCTOR_COMMAND);
|
|
1625
1835
|
}
|
|
1626
|
-
}, "
|
|
1627
|
-
key: "b",
|
|
1836
|
+
}, t("blocked.doctor")), (0, react.createElement)("button", {
|
|
1628
1837
|
type: "button",
|
|
1629
|
-
"data-role": "
|
|
1630
|
-
"aria-label": t("body." + bodyB.side) + " " + bodyB.name,
|
|
1631
|
-
title: t("body." + bodyB.side) + " " + bodyB.name,
|
|
1838
|
+
"data-role": "refresh",
|
|
1632
1839
|
onClick: () => {
|
|
1633
|
-
|
|
1840
|
+
window.dispatchEvent(new Event("evolution-merge:refresh"));
|
|
1634
1841
|
}
|
|
1635
|
-
}, "
|
|
1636
|
-
}
|
|
1842
|
+
}, t("refresh"))));
|
|
1843
|
+
}
|
|
1844
|
+
const capability = failure.code === "capability";
|
|
1845
|
+
return (0, react.createElement)("div", {
|
|
1846
|
+
"data-role": capability ? "capability-failure" : "failure",
|
|
1847
|
+
"data-error-code": failure.code,
|
|
1848
|
+
"data-status": String(failure.status)
|
|
1849
|
+
}, (0, react.createElement)("p", {
|
|
1850
|
+
"data-role": "failure-title",
|
|
1851
|
+
title: failure.message
|
|
1852
|
+
}, t(problemKey(failure))), capability ? (0, react.createElement)("p", { "data-role": "capability-hint" }, t("failureCapabilityHint")) : null, failure.message === void 0 ? null : (0, react.createElement)("details", { "data-role": "failure-detail" }, (0, react.createElement)("summary", null, t("failureDetails")), (0, react.createElement)("p", { "data-role": "failure-raw" }, failure.message)), fallback.length === 0 ? null : (0, react.createElement)("div", { "data-role": "fallback" }, fallback.map((command) => (0, react.createElement)("button", {
|
|
1853
|
+
key: command,
|
|
1854
|
+
type: "button",
|
|
1855
|
+
"data-role": "fallback-command",
|
|
1856
|
+
onClick: () => {
|
|
1857
|
+
copy(command);
|
|
1858
|
+
}
|
|
1859
|
+
}, command))));
|
|
1637
1860
|
}
|
|
1638
1861
|
const overlayKey = (event, onClose) => {
|
|
1639
1862
|
if (event.key === "Escape") {
|
|
@@ -1683,6 +1906,39 @@ window.__ModuleLoader__.load({
|
|
|
1683
1906
|
className: "evo-merge-modal"
|
|
1684
1907
|
}, inner);
|
|
1685
1908
|
}
|
|
1909
|
+
function pairNode(overlay, t, onClose) {
|
|
1910
|
+
const Modal = platformModal();
|
|
1911
|
+
const title = t("overlay.pair");
|
|
1912
|
+
const block = (target, body) => (0, react.createElement)("section", {
|
|
1913
|
+
"data-role": target === overlay.a ? "body-a" : "body-b",
|
|
1914
|
+
"data-side": target.side
|
|
1915
|
+
}, (0, react.createElement)("h4", { "data-role": "pair-name" }, target.name + " · " + t("body." + target.side)), body === void 0 ? null : body.truncated ? (0, react.createElement)("p", { "data-role": "body-truncated" }, t("body.truncated")) : null, body === void 0 ? null : body.text === "" ? (0, react.createElement)("p", { "data-role": "body-empty" }, t("body.empty")) : (0, react.createElement)("pre", { "data-role": "body-text" }, body.text));
|
|
1916
|
+
const inner = (0, react.createElement)("section", {
|
|
1917
|
+
"data-role": "overlay",
|
|
1918
|
+
"data-overlay": "pair",
|
|
1919
|
+
"aria-label": title,
|
|
1920
|
+
...Modal === void 0 ? {
|
|
1921
|
+
role: "dialog",
|
|
1922
|
+
"aria-modal": "true",
|
|
1923
|
+
onKeyDown: (event) => {
|
|
1924
|
+
overlayKey(event, onClose);
|
|
1925
|
+
}
|
|
1926
|
+
} : { "data-platform-modal": "true" }
|
|
1927
|
+
}, (0, react.createElement)("div", { "data-role": "overlay-head" }, (0, react.createElement)("h3", { "data-role": "overlay-title" }, title), (0, react.createElement)("button", {
|
|
1928
|
+
type: "button",
|
|
1929
|
+
"data-role": "overlay-close",
|
|
1930
|
+
...Modal === void 0 ? { autoFocus: true } : { "data-modal-autofocus": "true" },
|
|
1931
|
+
onClick: onClose
|
|
1932
|
+
}, t("close"))), overlay.status === "loading" ? (0, react.createElement)("p", { "data-role": "overlay-loading" }, t("loading")) : null, overlay.status === "error" && overlay.failure !== void 0 ? failureNode(t, overlay.failure, [], () => {}) : null, overlay.status === "ready" ? (0, react.createElement)("div", { "data-role": "pair-grid" }, block(overlay.a, overlay.aBody), block(overlay.b, overlay.bBody)) : null);
|
|
1933
|
+
return Modal === void 0 ? inner : (0, react.createElement)(Modal, {
|
|
1934
|
+
open: true,
|
|
1935
|
+
onClose,
|
|
1936
|
+
title,
|
|
1937
|
+
closeLabel: t("close"),
|
|
1938
|
+
headless: true,
|
|
1939
|
+
className: "evo-merge-modal"
|
|
1940
|
+
}, inner);
|
|
1941
|
+
}
|
|
1686
1942
|
function historyNode(overlay, t, onClose) {
|
|
1687
1943
|
const Modal = platformModal();
|
|
1688
1944
|
const title = t("history");
|
|
@@ -1712,7 +1968,7 @@ window.__ModuleLoader__.load({
|
|
|
1712
1968
|
const kind = t("history.kind." + item.kind);
|
|
1713
1969
|
const reason = reasonText(t, item.reasonCode, item.reason);
|
|
1714
1970
|
return kind === reason ? kind : kind + " · " + reason;
|
|
1715
|
-
})() + " · v" + String(item.lastVersion) + " · " + t("history.archivedAt", { date:
|
|
1971
|
+
})() + " · v" + String(item.lastVersion) + " · " + (item.archivedAt === null ? t("history.archivedAtUnknown") : t("history.archivedAt", { date: formatLocalDateTime(item.archivedAt) ?? t("history.archivedAtUnknown") }))))) : null);
|
|
1716
1972
|
return Modal === void 0 ? inner : (0, react.createElement)(Modal, {
|
|
1717
1973
|
open: true,
|
|
1718
1974
|
onClose,
|
|
@@ -1735,9 +1991,9 @@ window.__ModuleLoader__.load({
|
|
|
1735
1991
|
const captureFocus = () => {
|
|
1736
1992
|
returnFocus.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
1737
1993
|
};
|
|
1738
|
-
const
|
|
1994
|
+
const openBoth = (a, b, rowId) => {
|
|
1739
1995
|
captureFocus();
|
|
1740
|
-
store.
|
|
1996
|
+
store.openPair(a, b, rowId);
|
|
1741
1997
|
};
|
|
1742
1998
|
const openHistory = () => {
|
|
1743
1999
|
captureFocus();
|
|
@@ -1905,11 +2161,23 @@ window.__ModuleLoader__.load({
|
|
|
1905
2161
|
"data-role": "decision-notice",
|
|
1906
2162
|
"data-ok": decisionNotice.ok ? "true" : "false"
|
|
1907
2163
|
}, decisionNotice.message);
|
|
2164
|
+
const taskBanner = view.counts.pending > 0 ? (0, react.createElement)(TaskBanner, {
|
|
2165
|
+
count: view.counts.pending,
|
|
2166
|
+
text: t("task.pending")
|
|
2167
|
+
}) : null;
|
|
1908
2168
|
const list = uiState === "ready" && queue.status === "ready" ? (0, react.createElement)("div", {
|
|
1909
2169
|
"data-role": "rows",
|
|
1910
2170
|
id: "merge-rows",
|
|
1911
2171
|
role: "tabpanel"
|
|
1912
|
-
}, visibleRows.map((row) =>
|
|
2172
|
+
}, visibleRows.map((row) => (0, react.createElement)(MergeRow, {
|
|
2173
|
+
row,
|
|
2174
|
+
t,
|
|
2175
|
+
copy,
|
|
2176
|
+
sort: sortHandlers,
|
|
2177
|
+
openBoth,
|
|
2178
|
+
onDecide: face.decide === void 0 ? void 0 : decideRow,
|
|
2179
|
+
busy: deciding === row.id
|
|
2180
|
+
}))) : null;
|
|
1913
2181
|
const empty = uiState === "empty" ? (0, react.createElement)("div", null, (0, react.createElement)("p", { "data-role": "note" }, t("empty." + snapshot.queue)), (0, react.createElement)("p", { "data-role": "empty-scope" }, t("empty.scope"))) : null;
|
|
1914
2182
|
const staleViewFailure = snapshot.viewState === "ready" ? snapshot.viewFailure : void 0;
|
|
1915
2183
|
const activeFailure = viewFailure !== void 0 ? viewFailure : staleViewFailure !== void 0 ? staleViewFailure : queue.status === "error" ? queue.failure : void 0;
|
|
@@ -1975,38 +2243,48 @@ window.__ModuleLoader__.load({
|
|
|
1975
2243
|
return (0, react.createElement)("section", {
|
|
1976
2244
|
className: CSS_TAG_ID,
|
|
1977
2245
|
"data-state": uiState
|
|
1978
|
-
}, (0, react.createElement)("h2", { "data-role": "title" }, t("title")), (0, react.createElement)("p", { "data-role": "hint" }, t("hint")), blocked !== void 0 ? failureNode(t, blocked, fallback, copy) : (0, react.createElement)("div", { "data-role": "content" }, (0, react.createElement)("
|
|
1979
|
-
type: "button",
|
|
1980
|
-
"data-role": "start-scan",
|
|
1981
|
-
onClick: () => {
|
|
1982
|
-
copy(view.startCommands.scan);
|
|
1983
|
-
}
|
|
1984
|
-
}, t("start.scan")), (0, react.createElement)("button", {
|
|
1985
|
-
type: "button",
|
|
1986
|
-
"data-role": "start-pair",
|
|
1987
|
-
onClick: () => {
|
|
1988
|
-
copy(view.startCommands.pair);
|
|
1989
|
-
}
|
|
1990
|
-
}, t("start.pair"))), view.degraded ? (0, react.createElement)("p", { "data-role": "degraded" }, t("degraded") + " " + view.notes.join(",")) : null, (0, react.createElement)(SettingsCard, {
|
|
1991
|
-
view,
|
|
1992
|
-
t
|
|
1993
|
-
}), runNode(view, t, copy), tabs, expiredToggle, snapshot.viewState === "loading" || queue.status === "loading" ? (0, react.createElement)("p", { "data-role": "note" }, t("loading")) : queue.refreshing === true ? (0, react.createElement)("p", {
|
|
2246
|
+
}, (0, react.createElement)("h2", { "data-role": "title" }, t("title")), (0, react.createElement)("p", { "data-role": "hint" }, t("hint")), blocked !== void 0 ? failureNode(t, blocked, fallback, copy) : (0, react.createElement)("div", { "data-role": "content" }, taskBanner, snapshot.viewState === "loading" || queue.status === "loading" ? (0, react.createElement)("p", { "data-role": "note" }, t("loading")) : queue.refreshing === true ? (0, react.createElement)("p", {
|
|
1994
2247
|
"data-role": "note",
|
|
1995
2248
|
role: "status"
|
|
1996
2249
|
}, t("refreshing")) : null, activeFailure === void 0 ? null : failureNode(t, activeFailure, fallback, copy), copyState.kind === "idle" ? null : copyState.kind === "copied" ? (0, react.createElement)("p", {
|
|
1997
2250
|
"data-role": "copied",
|
|
1998
2251
|
role: "status"
|
|
1999
|
-
}, t("copied") + " " + (copyState.text ?? "")) : (0, react.createElement)("
|
|
2252
|
+
}, t("copied") + " " + (copyState.text ?? "")) : (0, react.createElement)("div", {
|
|
2000
2253
|
"data-role": "copy-failed",
|
|
2001
2254
|
role: "alert"
|
|
2002
|
-
}, t("copyFailed")),
|
|
2255
|
+
}, (0, react.createElement)("p", null, t("copyFailed")), copyState.text === void 0 ? null : (0, react.createElement)("code", { "data-role": "copy-failed-command" }, copyState.text), (0, react.createElement)("button", {
|
|
2256
|
+
type: "button",
|
|
2257
|
+
"data-role": "copy-retry",
|
|
2258
|
+
onClick: () => {
|
|
2259
|
+
if (copyState.text !== void 0) copy(copyState.text);
|
|
2260
|
+
}
|
|
2261
|
+
}, t("copyRetry"))), notice, list, tabs, expiredToggle, empty, queue.nextCursor === void 0 || uiState !== "ready" ? null : (0, react.createElement)("button", {
|
|
2003
2262
|
type: "button",
|
|
2004
2263
|
"data-role": "load-more",
|
|
2005
2264
|
disabled: queue.status === "loading",
|
|
2006
2265
|
onClick: () => {
|
|
2007
2266
|
store.loadMore();
|
|
2008
2267
|
}
|
|
2009
|
-
}, t("loadMore")), (0, react.createElement)(
|
|
2268
|
+
}, t("loadMore")), (0, react.createElement)(MergeSettings, {
|
|
2269
|
+
view,
|
|
2270
|
+
t
|
|
2271
|
+
}), (0, react.createElement)(MergeRunStrips, {
|
|
2272
|
+
view,
|
|
2273
|
+
t,
|
|
2274
|
+
copy
|
|
2275
|
+
}), view.degraded ? (0, react.createElement)("p", { "data-role": "degraded" }, t("degraded") + " " + view.notes.join(",")) : null, (0, react.createElement)("div", { "data-role": "start" }, (0, react.createElement)("button", {
|
|
2276
|
+
type: "button",
|
|
2277
|
+
"data-role": "start-scan",
|
|
2278
|
+
onClick: () => {
|
|
2279
|
+
copy(view.startCommands.scan);
|
|
2280
|
+
}
|
|
2281
|
+
}, t("start.scan")), (0, react.createElement)("button", {
|
|
2282
|
+
type: "button",
|
|
2283
|
+
"data-role": "start-pair",
|
|
2284
|
+
onClick: () => {
|
|
2285
|
+
copy(view.startCommands.pair);
|
|
2286
|
+
}
|
|
2287
|
+
}, t("start.pair"))), (0, react.createElement)("button", {
|
|
2010
2288
|
type: "button",
|
|
2011
2289
|
"data-role": "history",
|
|
2012
2290
|
onClick: () => {
|
|
@@ -2018,7 +2296,7 @@ window.__ModuleLoader__.load({
|
|
|
2018
2296
|
onClick: () => {
|
|
2019
2297
|
copy(doctorCommand);
|
|
2020
2298
|
}
|
|
2021
|
-
}, t("doctor.open")), overlay === void 0 ? null : overlay.kind === "body" ? bodyNode(overlay, t, closeOverlay) : historyNode(overlay, t, closeOverlay), (0, react.createElement)("button", {
|
|
2299
|
+
}, t("doctor.open")), overlay === void 0 ? null : overlay.kind === "body" ? bodyNode(overlay, t, closeOverlay) : overlay.kind === "pair" ? pairNode(overlay, t, closeOverlay) : historyNode(overlay, t, closeOverlay), (0, react.createElement)("button", {
|
|
2022
2300
|
type: "button",
|
|
2023
2301
|
"data-role": "refresh",
|
|
2024
2302
|
onClick: () => {
|
|
@@ -2331,6 +2609,54 @@ window.__ModuleLoader__.load({
|
|
|
2331
2609
|
}
|
|
2332
2610
|
});
|
|
2333
2611
|
}
|
|
2612
|
+
async openPair(a, b, rowId) {
|
|
2613
|
+
const token = ++this.overlayToken;
|
|
2614
|
+
this.set({
|
|
2615
|
+
...this.snapshot,
|
|
2616
|
+
overlay: {
|
|
2617
|
+
kind: "pair",
|
|
2618
|
+
a,
|
|
2619
|
+
b,
|
|
2620
|
+
status: "loading"
|
|
2621
|
+
}
|
|
2622
|
+
});
|
|
2623
|
+
const [left, right] = await Promise.all([this.source.body(a.name, a.side, rowId), this.source.body(b.name, b.side, rowId)]);
|
|
2624
|
+
if (this.disposed || token !== this.overlayToken) return;
|
|
2625
|
+
if (!left.ok || !right.ok) {
|
|
2626
|
+
const failure = !left.ok ? left.failure : !right.ok ? right.failure : void 0;
|
|
2627
|
+
if (failure?.kind === "blocked") {
|
|
2628
|
+
this.set({
|
|
2629
|
+
...this.snapshot,
|
|
2630
|
+
viewState: "blocked",
|
|
2631
|
+
viewFailure: failure,
|
|
2632
|
+
overlay: void 0
|
|
2633
|
+
});
|
|
2634
|
+
return;
|
|
2635
|
+
}
|
|
2636
|
+
this.set({
|
|
2637
|
+
...this.snapshot,
|
|
2638
|
+
overlay: {
|
|
2639
|
+
kind: "pair",
|
|
2640
|
+
a,
|
|
2641
|
+
b,
|
|
2642
|
+
status: "error",
|
|
2643
|
+
...failure === void 0 ? {} : { failure }
|
|
2644
|
+
}
|
|
2645
|
+
});
|
|
2646
|
+
return;
|
|
2647
|
+
}
|
|
2648
|
+
this.set({
|
|
2649
|
+
...this.snapshot,
|
|
2650
|
+
overlay: {
|
|
2651
|
+
kind: "pair",
|
|
2652
|
+
a,
|
|
2653
|
+
b,
|
|
2654
|
+
status: "ready",
|
|
2655
|
+
aBody: left.payload,
|
|
2656
|
+
bBody: right.payload
|
|
2657
|
+
}
|
|
2658
|
+
});
|
|
2659
|
+
}
|
|
2334
2660
|
async openHistory() {
|
|
2335
2661
|
const token = ++this.overlayToken;
|
|
2336
2662
|
this.set({
|