@lmzhen/dsh-evolution-merge-ui 0.32.6 → 0.34.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 +328 -177
- package/lib/types/client/MergeStore.d.ts +1 -0
- package/lib/types/client/Panel.d.ts +5 -2
- package/lib/types/client/api.d.ts +9 -1
- package/lib/types/client/platform-modal.d.ts +15 -0
- package/lib/types/client/session.d.ts +2 -0
- package/lib/types/client/sorting.d.ts +4 -4
- package/package.json +2 -2
package/lib/client.js
CHANGED
|
@@ -163,34 +163,51 @@ window.__ModuleLoader__.load({
|
|
|
163
163
|
...EMPTY,
|
|
164
164
|
reason: "seat-missing"
|
|
165
165
|
};
|
|
166
|
+
let lastReady;
|
|
167
|
+
let generation = 0;
|
|
166
168
|
const listeners = /* @__PURE__ */ new Set();
|
|
167
|
-
let
|
|
168
|
-
let listening = false;
|
|
169
|
+
let remoteOff;
|
|
169
170
|
const notify = () => {
|
|
170
171
|
for (const listener of listeners) listener();
|
|
171
172
|
};
|
|
172
|
-
const
|
|
173
|
-
|
|
173
|
+
const absorb = (next) => {
|
|
174
|
+
if (next.status === "ready") {
|
|
175
|
+
lastReady = next;
|
|
176
|
+
snapshot = next;
|
|
177
|
+
} else if (lastReady !== void 0) snapshot = {
|
|
178
|
+
...lastReady,
|
|
179
|
+
stale: true,
|
|
180
|
+
reason: next.reason ?? "readback-failed"
|
|
181
|
+
};
|
|
182
|
+
else snapshot = next;
|
|
174
183
|
notify();
|
|
175
184
|
};
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
185
|
+
const refresh = async () => {
|
|
186
|
+
const ticket = ++generation;
|
|
187
|
+
const next = await describe(namespace);
|
|
188
|
+
if (ticket !== generation) return;
|
|
189
|
+
absorb(next);
|
|
190
|
+
};
|
|
191
|
+
const remote = () => ctx.get?.("remote");
|
|
192
|
+
const stopRemote = () => {
|
|
193
|
+
remoteOff?.();
|
|
194
|
+
remoteOff = void 0;
|
|
195
|
+
};
|
|
196
|
+
const startRemote = () => {
|
|
197
|
+
if (remoteOff !== void 0) return;
|
|
198
|
+
remoteOff = remote()?.$on?.("settings/document-updated", (changed) => {
|
|
199
|
+
if (changed === namespace) refresh();
|
|
200
|
+
});
|
|
186
201
|
};
|
|
187
202
|
const form = {
|
|
188
203
|
getSnapshot: () => snapshot,
|
|
189
204
|
subscribe: (listener) => {
|
|
190
205
|
listeners.add(listener);
|
|
191
|
-
|
|
206
|
+
startRemote();
|
|
207
|
+
refresh();
|
|
192
208
|
return () => {
|
|
193
209
|
listeners.delete(listener);
|
|
210
|
+
if (listeners.size === 0) stopRemote();
|
|
194
211
|
};
|
|
195
212
|
},
|
|
196
213
|
set: async (field, value) => await form.mutate([{
|
|
@@ -204,35 +221,39 @@ window.__ModuleLoader__.load({
|
|
|
204
221
|
}]),
|
|
205
222
|
mutate: async (ops, expectedRevision) => {
|
|
206
223
|
const outcome = await write(namespace, ops, expectedRevision ?? snapshot.revision);
|
|
207
|
-
if (outcome.snapshot !== void 0)
|
|
208
|
-
|
|
209
|
-
notify();
|
|
210
|
-
} else await refresh();
|
|
224
|
+
if (outcome.snapshot !== void 0) absorb(outcome.snapshot);
|
|
225
|
+
else await refresh();
|
|
211
226
|
return outcome.ok;
|
|
227
|
+
},
|
|
228
|
+
refresh,
|
|
229
|
+
dispose: () => {
|
|
230
|
+
stopRemote();
|
|
231
|
+
listeners.clear();
|
|
212
232
|
}
|
|
213
233
|
};
|
|
214
234
|
return form;
|
|
215
235
|
}
|
|
216
236
|
/**
|
|
217
|
-
* Build one
|
|
218
|
-
*
|
|
219
|
-
*
|
|
237
|
+
* Build one seat per client registration; every form's remote listener is released by
|
|
238
|
+
* the caller's effect. No module-level WeakMap: a replaced registration must not share
|
|
239
|
+
* a dead seat with the previous one.
|
|
220
240
|
*/
|
|
221
|
-
const seats = /* @__PURE__ */ new WeakMap();
|
|
222
241
|
function createSettingsSeat(ctx) {
|
|
223
|
-
const cached = seats.get(ctx);
|
|
224
|
-
if (cached !== void 0) return cached;
|
|
225
242
|
const forms = /* @__PURE__ */ new Map();
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
form
|
|
230
|
-
|
|
243
|
+
return {
|
|
244
|
+
get(namespace) {
|
|
245
|
+
let form = forms.get(namespace);
|
|
246
|
+
if (form === void 0) {
|
|
247
|
+
form = createForm(namespace, ctx);
|
|
248
|
+
forms.set(namespace, form);
|
|
249
|
+
}
|
|
250
|
+
return form;
|
|
251
|
+
},
|
|
252
|
+
dispose: () => {
|
|
253
|
+
for (const form of forms.values()) form.dispose?.();
|
|
254
|
+
forms.clear();
|
|
231
255
|
}
|
|
232
|
-
|
|
233
|
-
} };
|
|
234
|
-
seats.set(ctx, seat);
|
|
235
|
-
return seat;
|
|
256
|
+
};
|
|
236
257
|
}
|
|
237
258
|
//#endregion
|
|
238
259
|
//#region ../evolution-client-kit/src/workspace.ts
|
|
@@ -491,7 +512,8 @@ window.__ModuleLoader__.load({
|
|
|
491
512
|
startCommands: facts.startCommands,
|
|
492
513
|
notes: [...facts.notes],
|
|
493
514
|
degraded: facts.degraded,
|
|
494
|
-
...facts.active === null
|
|
515
|
+
...facts.active === null ? {} : { activeRun: toRun(facts.active) },
|
|
516
|
+
...facts.last === null ? {} : { lastRun: toRun(facts.last) },
|
|
495
517
|
approval: {
|
|
496
518
|
mergeApproval: facts.approval.mergeApproval,
|
|
497
519
|
...platformWrite === void 0 ? {} : { platformWrite }
|
|
@@ -518,9 +540,14 @@ window.__ModuleLoader__.load({
|
|
|
518
540
|
};
|
|
519
541
|
}
|
|
520
542
|
async function body(name, side, rowId) {
|
|
521
|
-
const
|
|
543
|
+
const query = new URLSearchParams({
|
|
544
|
+
name,
|
|
545
|
+
side
|
|
546
|
+
});
|
|
547
|
+
if (rowId !== void 0) query.set("id", rowId);
|
|
548
|
+
const answer = await requestWire(HOST_ROUTES.body + "?" + query.toString());
|
|
522
549
|
if (!answer.ok) {
|
|
523
|
-
if (answer.failure.kind === "problem" && answer.failure.code === "bad-query" && (answer.failure.message ?? "").includes("
|
|
550
|
+
if (answer.failure.kind === "problem" && answer.failure.code === "bad-query" && (answer.failure.message ?? "").includes("ambiguous")) return {
|
|
524
551
|
ok: false,
|
|
525
552
|
failure: {
|
|
526
553
|
...answer.failure,
|
|
@@ -541,6 +568,56 @@ window.__ModuleLoader__.load({
|
|
|
541
568
|
}
|
|
542
569
|
};
|
|
543
570
|
}
|
|
571
|
+
async function decide(rowId, verb, sessionId) {
|
|
572
|
+
const path = HOST_ROUTES.body.replace(/body$/, "decision");
|
|
573
|
+
let response;
|
|
574
|
+
try {
|
|
575
|
+
response = await fetch(path, {
|
|
576
|
+
method: "POST",
|
|
577
|
+
headers: {
|
|
578
|
+
accept: "application/json",
|
|
579
|
+
"content-type": "application/json"
|
|
580
|
+
},
|
|
581
|
+
body: JSON.stringify({
|
|
582
|
+
rowId,
|
|
583
|
+
verb,
|
|
584
|
+
sessionId
|
|
585
|
+
})
|
|
586
|
+
});
|
|
587
|
+
} catch {
|
|
588
|
+
return {
|
|
589
|
+
ok: false,
|
|
590
|
+
failure: problem("server", 0)
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
let body;
|
|
594
|
+
try {
|
|
595
|
+
body = await response.json();
|
|
596
|
+
} catch {
|
|
597
|
+
return {
|
|
598
|
+
ok: false,
|
|
599
|
+
failure: problem("server", response.status)
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
if (typeof body !== "object" || body === null) return {
|
|
603
|
+
ok: false,
|
|
604
|
+
failure: problem("server", response.status)
|
|
605
|
+
};
|
|
606
|
+
const record = body;
|
|
607
|
+
if (record.wireVersion !== 1 || typeof record.ok !== "boolean" || typeof record.message !== "string") return {
|
|
608
|
+
ok: false,
|
|
609
|
+
failure: problem("wire-version", response.status)
|
|
610
|
+
};
|
|
611
|
+
return {
|
|
612
|
+
ok: true,
|
|
613
|
+
payload: {
|
|
614
|
+
ok: record.ok,
|
|
615
|
+
message: record.message,
|
|
616
|
+
...typeof record.code === "string" ? { code: record.code } : {},
|
|
617
|
+
...typeof record.runId === "string" ? { runId: record.runId } : {}
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
}
|
|
544
621
|
async function history() {
|
|
545
622
|
const answer = await requestWire(HOST_ROUTES.history);
|
|
546
623
|
return answer.ok ? {
|
|
@@ -634,6 +711,8 @@ window.__ModuleLoader__.load({
|
|
|
634
711
|
"skipKind.forced": "强制",
|
|
635
712
|
"action.approve": "复制批准",
|
|
636
713
|
"action.reject": "复制拒绝",
|
|
714
|
+
"decision.approve": "批准",
|
|
715
|
+
"decision.reject": "拒绝",
|
|
637
716
|
"action.retry-candidates": "复制重试候选",
|
|
638
717
|
"action.retry-resume": "重试续跑",
|
|
639
718
|
"action.discard": "复制丢弃",
|
|
@@ -686,6 +765,7 @@ window.__ModuleLoader__.load({
|
|
|
686
765
|
"stage.state.absent": "无暂存",
|
|
687
766
|
"origin.system": "系统",
|
|
688
767
|
"row.id": "编号",
|
|
768
|
+
"row.details": "详情",
|
|
689
769
|
"row.requestedTarget": "请求目标",
|
|
690
770
|
"row.stage": "合并暂存",
|
|
691
771
|
"row.summaryA": "摘要 A",
|
|
@@ -707,7 +787,6 @@ window.__ModuleLoader__.load({
|
|
|
707
787
|
"history.reason.archived": "已归档",
|
|
708
788
|
"history.reason.unknown": "原因未提供",
|
|
709
789
|
"history.lastVersion": "最后版本",
|
|
710
|
-
"history.archivedAt": "归档时间",
|
|
711
790
|
"body.truncated": "正文过长,已截断。",
|
|
712
791
|
"body.empty": "正文为空。",
|
|
713
792
|
"body.totalBytes": "总字节",
|
|
@@ -834,6 +913,8 @@ window.__ModuleLoader__.load({
|
|
|
834
913
|
"skipKind.forced": "forced",
|
|
835
914
|
"action.approve": "Copy approve",
|
|
836
915
|
"action.reject": "Copy reject",
|
|
916
|
+
"decision.approve": "Approve",
|
|
917
|
+
"decision.reject": "Reject",
|
|
837
918
|
"action.retry-candidates": "Copy retry candidates",
|
|
838
919
|
"action.retry-resume": "Retry resume",
|
|
839
920
|
"action.discard": "Copy discard",
|
|
@@ -886,6 +967,7 @@ window.__ModuleLoader__.load({
|
|
|
886
967
|
"stage.state.absent": "Not staged",
|
|
887
968
|
"origin.system": "System",
|
|
888
969
|
"row.id": "ID",
|
|
970
|
+
"row.details": "Details",
|
|
889
971
|
"row.requestedTarget": "Requested target",
|
|
890
972
|
"row.stage": "Merge staging",
|
|
891
973
|
"row.summaryA": "Summary A",
|
|
@@ -907,7 +989,6 @@ window.__ModuleLoader__.load({
|
|
|
907
989
|
"history.reason.archived": "archived",
|
|
908
990
|
"history.reason.unknown": "reason not provided",
|
|
909
991
|
"history.lastVersion": "Last version",
|
|
910
|
-
"history.archivedAt": "Archived at",
|
|
911
992
|
"body.truncated": "Body is truncated.",
|
|
912
993
|
"body.empty": "Body is empty.",
|
|
913
994
|
"body.totalBytes": "Total bytes",
|
|
@@ -966,14 +1047,14 @@ window.__ModuleLoader__.load({
|
|
|
966
1047
|
"settings.saved": "已保存",
|
|
967
1048
|
"settings.saveFailed": "保存失败",
|
|
968
1049
|
"settings.openPlatform": "打开平台设置",
|
|
969
|
-
"settings.openPlatformPath": "设置 → 内置插件 →
|
|
1050
|
+
"settings.openPlatformPath": "设置 → 内置插件 → 自进化 → 技能自动合并",
|
|
970
1051
|
"settings.live": "可直接在此保存;platformWrite 能力来自宿主。"
|
|
971
1052
|
});
|
|
972
1053
|
Object.assign(en, {
|
|
973
1054
|
"settings.saved": "Saved",
|
|
974
1055
|
"settings.saveFailed": "Save failed",
|
|
975
1056
|
"settings.openPlatform": "Open platform settings",
|
|
976
|
-
"settings.openPlatformPath": "Settings → Built-in plugins →
|
|
1057
|
+
"settings.openPlatformPath": "Settings → Built-in plugins → Evolution → Skill auto-merge",
|
|
977
1058
|
"settings.live": "Save directly here; platformWrite capability comes from the host."
|
|
978
1059
|
});
|
|
979
1060
|
Object.assign(zh, { "settings.platformWriteLinkHint": "此开关属于平台设置,这里只读;请到平台设置修改。" });
|
|
@@ -1015,6 +1096,13 @@ window.__ModuleLoader__.load({
|
|
|
1015
1096
|
".evolution-merge-panel [data-role=\"failure\"] [data-tone=\"fail\"] { color:var(--dsw-alias-state-error-primary); }",
|
|
1016
1097
|
".evolution-merge-panel [data-role=\"fallback\"] { display:flex; gap:var(--evo-space-6); flex-wrap:wrap; }",
|
|
1017
1098
|
".evolution-merge-panel [data-role=\"overlay\"] { position:fixed; z-index:60; top:8vh; left:50%; transform:translateX(-50%); width:min(820px, calc(100vw - 64px)); max-height:78vh; overflow:auto; 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); box-shadow:0 0 var(--evo-space-8) var(--dsw-alias-border-l2); }",
|
|
1099
|
+
".evo-merge-modal { width:min(820px, calc(100vw - 48px)); max-width:calc(100vw - 48px); max-height:min(78vh, 720px); }",
|
|
1100
|
+
".evo-merge-modal [data-role=\"overlay\"][data-platform-modal] { position:static; z-index:auto; top:auto; left:auto; transform:none; width:auto; box-sizing:border-box; max-height:none; overflow:auto; padding:var(--evo-space-20); border:0; border-radius:0; background:transparent; box-shadow:none; gap:var(--evo-space-8); }",
|
|
1101
|
+
".evo-merge-modal [data-role=\"overlay-head\"] { display:flex; align-items:center; justify-content:space-between; gap:var(--evo-space-8); }",
|
|
1102
|
+
".evo-merge-modal [data-role=\"overlay-title\"] { margin:0; font-size:var(--evo-type-lg); }",
|
|
1103
|
+
".evo-merge-modal [data-role=\"body-text\"] { margin:0; max-height:52vh; overflow:auto; white-space:pre-wrap; }",
|
|
1104
|
+
".evo-merge-modal [data-role=\"history-list\"] { margin:0; padding-left:var(--evo-space-20); }",
|
|
1105
|
+
".evo-merge-modal [data-role=\"history-item\"] { padding:var(--evo-space-4) 0; }",
|
|
1018
1106
|
".evolution-merge-panel [data-role=\"overlay-head\"] { display:flex; align-items:center; justify-content:space-between; gap:var(--evo-space-8); }",
|
|
1019
1107
|
".evolution-merge-panel [data-role=\"overlay-title\"] { margin:0; font-size:var(--evo-type-lg); }",
|
|
1020
1108
|
".evolution-merge-panel [data-role=\"rows\"] { display:flex; flex-direction:column; gap:var(--evo-space-6); }",
|
|
@@ -1055,6 +1143,25 @@ window.__ModuleLoader__.load({
|
|
|
1055
1143
|
".evolution-merge-panel [data-role=\"refresh\"] { align-self:flex-start; }"
|
|
1056
1144
|
].join("\n");
|
|
1057
1145
|
//#endregion
|
|
1146
|
+
//#region src/client/platform-modal.ts
|
|
1147
|
+
const PLATFORM_UI_MODULE$1 = "@deepseek-ai/dsh-client-ui-primitives";
|
|
1148
|
+
let cached;
|
|
1149
|
+
/** The platform Modal, or undefined in a non-browser/SSR render or a deployment without the row. */
|
|
1150
|
+
function platformModal() {
|
|
1151
|
+
if (cached !== void 0) return cached ?? void 0;
|
|
1152
|
+
if (typeof window === "undefined") {
|
|
1153
|
+
cached = null;
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
try {
|
|
1157
|
+
const row = require(PLATFORM_UI_MODULE$1);
|
|
1158
|
+
cached = typeof row.Modal === "function" ? row.Modal : null;
|
|
1159
|
+
} catch {
|
|
1160
|
+
cached = null;
|
|
1161
|
+
}
|
|
1162
|
+
return cached ?? void 0;
|
|
1163
|
+
}
|
|
1164
|
+
//#endregion
|
|
1058
1165
|
//#region src/client/platform-menu.ts
|
|
1059
1166
|
/**
|
|
1060
1167
|
* The one seam onto the platform's menu material and rows.
|
|
@@ -1116,9 +1223,9 @@ window.__ModuleLoader__.load({
|
|
|
1116
1223
|
const value = workspaceId?.trim() ?? "";
|
|
1117
1224
|
return value === "" ? "local" : value;
|
|
1118
1225
|
}
|
|
1119
|
-
/** Stable localStorage key for one workspace and
|
|
1120
|
-
function rowOrderKey(workspaceId, queue) {
|
|
1121
|
-
return "dsh-evolution-merge.row-order.v1:" + encodeURIComponent(resolveWorkspaceId(workspaceId)) + ":" + queue;
|
|
1226
|
+
/** Stable localStorage key for one workspace, queue and expired filter. */
|
|
1227
|
+
function rowOrderKey(workspaceId, queue, expiredOnly = false) {
|
|
1228
|
+
return "dsh-evolution-merge.row-order.v1:" + encodeURIComponent(resolveWorkspaceId(workspaceId)) + ":" + queue + (expiredOnly ? ":expired" : ":live");
|
|
1122
1229
|
}
|
|
1123
1230
|
function defaultStorage() {
|
|
1124
1231
|
try {
|
|
@@ -1147,18 +1254,18 @@ window.__ModuleLoader__.load({
|
|
|
1147
1254
|
/** One tab's persisted order; failures degrade to an empty (wire) order. */
|
|
1148
1255
|
function createRowOrderStore(storage = defaultStorage()) {
|
|
1149
1256
|
return {
|
|
1150
|
-
read(workspaceId, queue) {
|
|
1257
|
+
read(workspaceId, queue, expiredOnly = false) {
|
|
1151
1258
|
if (storage === void 0) return [];
|
|
1152
1259
|
try {
|
|
1153
|
-
return normalize(storage.getItem(rowOrderKey(workspaceId, queue)));
|
|
1260
|
+
return normalize(storage.getItem(rowOrderKey(workspaceId, queue, expiredOnly)));
|
|
1154
1261
|
} catch {
|
|
1155
1262
|
return [];
|
|
1156
1263
|
}
|
|
1157
1264
|
},
|
|
1158
|
-
write(workspaceId, queue, ids) {
|
|
1265
|
+
write(workspaceId, queue, ids, expiredOnly = false) {
|
|
1159
1266
|
if (storage === void 0) return;
|
|
1160
1267
|
try {
|
|
1161
|
-
storage.setItem(rowOrderKey(workspaceId, queue), JSON.stringify(ids));
|
|
1268
|
+
storage.setItem(rowOrderKey(workspaceId, queue, expiredOnly), JSON.stringify(ids));
|
|
1162
1269
|
} catch {}
|
|
1163
1270
|
}
|
|
1164
1271
|
};
|
|
@@ -1214,13 +1321,6 @@ window.__ModuleLoader__.load({
|
|
|
1214
1321
|
//#endregion
|
|
1215
1322
|
//#region src/client/Panel.ts
|
|
1216
1323
|
/** Batch 4 merge panel: keyed read store, four tabs, local overlays, localized errors. */
|
|
1217
|
-
async function saveSetting(form, field, value) {
|
|
1218
|
-
try {
|
|
1219
|
-
return await form.set(field, value);
|
|
1220
|
-
} catch {
|
|
1221
|
-
return false;
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1224
1324
|
const QUEUES = [
|
|
1225
1325
|
"verify",
|
|
1226
1326
|
"pending",
|
|
@@ -1320,8 +1420,12 @@ window.__ModuleLoader__.load({
|
|
|
1320
1420
|
}, t("stage.state." + stage.state) + expiry);
|
|
1321
1421
|
}
|
|
1322
1422
|
function runNode(view, t, copy) {
|
|
1323
|
-
const
|
|
1324
|
-
|
|
1423
|
+
const active = view.activeRun;
|
|
1424
|
+
const last = view.lastRun;
|
|
1425
|
+
if (active === void 0 && last === void 0) return null;
|
|
1426
|
+
return (0, react.createElement)("div", { "data-role": "run-strips" }, active === void 0 ? null : runStrip(active, t, copy, "active"), last === void 0 ? null : runStrip(last, t, copy, "last"));
|
|
1427
|
+
}
|
|
1428
|
+
function runStrip(run, t, copy, role) {
|
|
1325
1429
|
const report = run.actions.find((action) => action.id === "report");
|
|
1326
1430
|
const reportEnabled = report?.enabled === true;
|
|
1327
1431
|
const internals = [
|
|
@@ -1359,6 +1463,7 @@ window.__ModuleLoader__.load({
|
|
|
1359
1463
|
];
|
|
1360
1464
|
return (0, react.createElement)("div", {
|
|
1361
1465
|
"data-role": "run-strip",
|
|
1466
|
+
"data-run-role": role,
|
|
1362
1467
|
"data-run-state": run.state
|
|
1363
1468
|
}, (0, react.createElement)("span", { "data-role": "run-state" }, t("run.state") + " " + t("run." + run.state)), run.progress === null || run.progress === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-progress" }, t("run.progress") + " " + String(run.progress.done) + "/" + String(run.progress.total)), (0, react.createElement)("button", {
|
|
1364
1469
|
type: "button",
|
|
@@ -1392,78 +1497,18 @@ window.__ModuleLoader__.load({
|
|
|
1392
1497
|
"data-value": missing ? "missing" : disabled ? "unavailable" : value === true ? "on" : "off"
|
|
1393
1498
|
}, text), note === void 0 ? null : (0, react.createElement)("span", { "data-role": "settings-note" }, note), link === true ? (0, react.createElement)("span", { "data-role": "settings-link" }, t("settings.openPlatformPath")) : null);
|
|
1394
1499
|
}
|
|
1395
|
-
function
|
|
1396
|
-
const subscribe = (0, react.useCallback)((listener) => form.subscribe(listener), [form]);
|
|
1397
|
-
const readSnapshot = (0, react.useCallback)(() => form["getSnapshot"](), [form]);
|
|
1398
|
-
const snapshot = (0, react.useSyncExternalStore)(subscribe, readSnapshot, readSnapshot);
|
|
1399
|
-
const fieldPresent = snapshot.status !== "ready" || snapshot.value === void 0 || Object.prototype.hasOwnProperty.call(snapshot.value, field);
|
|
1400
|
-
const [busy, setBusy] = (0, react.useState)(false);
|
|
1401
|
-
const [saved, setSaved] = (0, react.useState)(void 0);
|
|
1402
|
-
const value = snapshot.status === "ready" && typeof snapshot.value?.[field] === "boolean" ? snapshot.value[field] : fallback;
|
|
1403
|
-
const disabled = !capability || busy || snapshot.status !== "ready" || !snapshot.writable;
|
|
1404
|
-
const toggle = async () => {
|
|
1405
|
-
if (disabled) return;
|
|
1406
|
-
setBusy(true);
|
|
1407
|
-
setSaved(void 0);
|
|
1408
|
-
const ok = await saveSetting(form, field, !value);
|
|
1409
|
-
setBusy(false);
|
|
1410
|
-
setSaved(ok ? "saved" : "failed");
|
|
1411
|
-
};
|
|
1412
|
-
if (!fieldPresent) return (0, react.createElement)(ReadOnlySetting, {
|
|
1413
|
-
section: "platform-write",
|
|
1414
|
-
label,
|
|
1415
|
-
value: fallback,
|
|
1416
|
-
disabled: !capability,
|
|
1417
|
-
missing: false,
|
|
1418
|
-
note: t("settings.platformWriteLinkHint"),
|
|
1419
|
-
link: true,
|
|
1420
|
-
t
|
|
1421
|
-
});
|
|
1422
|
-
return (0, react.createElement)("div", {
|
|
1423
|
-
"data-role": "settings-section",
|
|
1424
|
-
"data-section": field === "mergeApproval" ? "merge-approval" : "platform-write",
|
|
1425
|
-
...disabled ? { "data-disabled": "true" } : {}
|
|
1426
|
-
}, (0, react.createElement)("label", {
|
|
1427
|
-
"data-role": "settings-label",
|
|
1428
|
-
htmlFor: "merge-setting-" + field
|
|
1429
|
-
}, label), (0, react.createElement)("input", {
|
|
1430
|
-
id: "merge-setting-" + field,
|
|
1431
|
-
"aria-label": label,
|
|
1432
|
-
type: "checkbox",
|
|
1433
|
-
role: "switch",
|
|
1434
|
-
"data-role": "settings-toggle",
|
|
1435
|
-
"data-field": field,
|
|
1436
|
-
"data-value": value ? "on" : "off",
|
|
1437
|
-
checked: value,
|
|
1438
|
-
disabled,
|
|
1439
|
-
onChange: () => {
|
|
1440
|
-
toggle();
|
|
1441
|
-
}
|
|
1442
|
-
}), (0, react.createElement)("span", { "data-role": "settings-value" }, value ? t("settings.on") : t("settings.off")), ...saved === void 0 ? [] : [(0, react.createElement)("span", {
|
|
1443
|
-
"data-role": "settings-save-state",
|
|
1444
|
-
"data-save": saved
|
|
1445
|
-
}, t(saved === "saved" ? "settings.saved" : "settings.saveFailed"))]);
|
|
1446
|
-
}
|
|
1447
|
-
function SettingsCard({ view, settings, t }) {
|
|
1500
|
+
function SettingsCard({ view, t }) {
|
|
1448
1501
|
const platform = view.approval.platformWrite;
|
|
1449
|
-
const platformCapability = platform?.capability
|
|
1502
|
+
const platformCapability = platform?.capability === true;
|
|
1450
1503
|
const platformFallback = platform?.enabled ?? false;
|
|
1451
|
-
const mergeCapability = settings?.merge !== void 0;
|
|
1452
1504
|
const mergeFallback = view.approval.mergeApproval;
|
|
1453
|
-
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")),
|
|
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, {
|
|
1454
1506
|
section: "merge-approval",
|
|
1455
1507
|
label: t("settings.mergeApproval"),
|
|
1456
1508
|
value: mergeFallback,
|
|
1457
1509
|
disabled: false,
|
|
1458
1510
|
missing: false,
|
|
1459
1511
|
t
|
|
1460
|
-
}) : (0, react.createElement)(EditableSetting, {
|
|
1461
|
-
form: settings.merge,
|
|
1462
|
-
field: "mergeApproval",
|
|
1463
|
-
label: t("settings.mergeApproval"),
|
|
1464
|
-
fallback: mergeFallback,
|
|
1465
|
-
capability: mergeCapability,
|
|
1466
|
-
t
|
|
1467
1512
|
}), (0, react.createElement)(ReadOnlySetting, {
|
|
1468
1513
|
section: "platform-write",
|
|
1469
1514
|
label: t("settings.platformWrite"),
|
|
@@ -1471,35 +1516,53 @@ window.__ModuleLoader__.load({
|
|
|
1471
1516
|
disabled: platformCapability === false,
|
|
1472
1517
|
missing: platform === void 0,
|
|
1473
1518
|
note: t("settings.platformWriteLinkHint"),
|
|
1474
|
-
link: true,
|
|
1475
1519
|
t
|
|
1476
|
-
}), (0, react.createElement)("p", { "data-role": "settings-readonly" },
|
|
1520
|
+
}), (0, react.createElement)("p", { "data-role": "settings-readonly" }, t("settings.readonly")));
|
|
1477
1521
|
}
|
|
1478
|
-
function rowNode(row, t, copy, sort, openBody) {
|
|
1479
|
-
const
|
|
1522
|
+
function rowNode(row, t, copy, sort, openBody, onDecide, busy) {
|
|
1523
|
+
const first = [
|
|
1480
1524
|
row.target === void 0 ? void 0 : t("row.target") + " " + row.target,
|
|
1525
|
+
row.failure === void 0 ? void 0 : t("row.failure") + " " + row.failure.code + (row.failure.retryable ? "" : " · " + t("row.noRetry")),
|
|
1526
|
+
row.expired === void 0 ? void 0 : t("row.expired") + " " + t("expired." + row.expired),
|
|
1527
|
+
row.reasonCode === void 0 && row.reason === void 0 ? void 0 : t("row.reason") + " " + reasonText(t, row.reasonCode, row.reason ?? "")
|
|
1528
|
+
].filter((value) => value !== void 0).join(" · ");
|
|
1529
|
+
const details = [
|
|
1530
|
+
t("row.id") + " " + row.id,
|
|
1481
1531
|
row.targetActual === void 0 ? void 0 : t("row.actualTarget") + " " + row.targetActual,
|
|
1482
1532
|
row.verifySubState === void 0 ? void 0 : t("row.verify") + " " + t("verify." + row.verifySubState),
|
|
1483
1533
|
row.origin === void 0 ? void 0 : t("row.origin") + " " + t("origin." + row.origin),
|
|
1484
1534
|
row.attempts === void 0 ? void 0 : t("row.attempts") + " " + String(row.attempts),
|
|
1485
|
-
row.confidence === void 0 ? void 0 : t("row.confidence") + " " + row.confidence.toFixed(2)
|
|
1486
|
-
row.failure === void 0 ? void 0 : t("row.failure") + " " + row.failure.code + (row.failure.retryable ? "" : " · " + t("row.noRetry")),
|
|
1487
|
-
row.expired === void 0 ? void 0 : t("row.expired") + " " + t("expired." + row.expired),
|
|
1488
|
-
row.reasonCode === void 0 && row.reason === void 0 ? void 0 : t("row.reason") + " " + reasonText(t, row.reasonCode, row.reason ?? "")
|
|
1535
|
+
row.confidence === void 0 ? void 0 : t("row.confidence") + " " + row.confidence.toFixed(2)
|
|
1489
1536
|
].filter((value) => value !== void 0).join(" · ");
|
|
1490
|
-
const actions = row.actions.
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1537
|
+
const actions = row.actions.flatMap((action) => {
|
|
1538
|
+
const decision = (action.id === "approve" || action.id === "reject") && onDecide !== void 0;
|
|
1539
|
+
const primary = (0, react.createElement)("button", {
|
|
1540
|
+
key: action.id,
|
|
1541
|
+
type: "button",
|
|
1542
|
+
"data-role": decision ? "row-decision" : "row-action",
|
|
1543
|
+
"data-action": action.id,
|
|
1544
|
+
...action.disabledReason === void 0 ? {} : { "data-disabled-reason": action.disabledReason },
|
|
1545
|
+
title: action.command,
|
|
1546
|
+
disabled: !action.enabled || busy,
|
|
1547
|
+
onClick: () => {
|
|
1548
|
+
if (!action.enabled || busy) return;
|
|
1549
|
+
if (decision) onDecide(row.id, action.id);
|
|
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);
|
|
1563
|
+
}
|
|
1564
|
+
}, t("row.copy"))];
|
|
1565
|
+
});
|
|
1503
1566
|
return (0, react.createElement)("div", {
|
|
1504
1567
|
key: row.id,
|
|
1505
1568
|
"data-role": "row",
|
|
@@ -1539,10 +1602,16 @@ window.__ModuleLoader__.load({
|
|
|
1539
1602
|
event.preventDefault();
|
|
1540
1603
|
sort.menu(row.id, event.clientX, event.clientY);
|
|
1541
1604
|
}
|
|
1542
|
-
}, (0, react.createElement)("div", null, (0, react.createElement)("div", { "data-role": "row-label" }, row.label), (0, react.createElement)("div", {
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1605
|
+
}, (0, react.createElement)("div", null, (0, react.createElement)("div", { "data-role": "row-label" }, row.label), (0, react.createElement)("div", { "data-role": "row-meta" }, t("state." + row.state) + (row.stage === null ? "" : " · " + t("stage." + row.stage))), stageNode(row, t), summaryNode(row, t), first === "" ? null : (0, react.createElement)("div", { "data-role": "row-facts" }, first), (0, react.createElement)("details", { "data-role": "row-details" }, (0, react.createElement)("summary", null, t("row.details")), (0, react.createElement)("p", null, details))), (0, react.createElement)("div", null, (0, react.createElement)("div", { "data-role": "row-meta" }, new Date(row.updatedAt).toLocaleString()), (0, react.createElement)("div", { "data-role": "row-actions" }, (0, react.createElement)("button", {
|
|
1606
|
+
type: "button",
|
|
1607
|
+
"data-role": "row-sort",
|
|
1608
|
+
"aria-haspopup": "menu",
|
|
1609
|
+
title: t("sort.menu"),
|
|
1610
|
+
onClick: (event) => {
|
|
1611
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
1612
|
+
sort.menu(row.id, rect.left, rect.bottom);
|
|
1613
|
+
}
|
|
1614
|
+
}, t("sort.menu")), (() => {
|
|
1546
1615
|
const bodyA = row.bodies?.find((body) => body.name === row.a);
|
|
1547
1616
|
const bodyB = row.bodies?.find((body) => body.name === row.b);
|
|
1548
1617
|
return [bodyA === void 0 ? null : (0, react.createElement)("button", {
|
|
@@ -1554,7 +1623,7 @@ window.__ModuleLoader__.load({
|
|
|
1554
1623
|
onClick: () => {
|
|
1555
1624
|
openBody(bodyA.name, bodyA.side, bodyA.rowId);
|
|
1556
1625
|
}
|
|
1557
|
-
}, "A"), bodyB === void 0 ? null : (0, react.createElement)("button", {
|
|
1626
|
+
}, "A · " + bodyA.name), bodyB === void 0 ? null : (0, react.createElement)("button", {
|
|
1558
1627
|
key: "b",
|
|
1559
1628
|
type: "button",
|
|
1560
1629
|
"data-role": "body-b",
|
|
@@ -1563,7 +1632,7 @@ window.__ModuleLoader__.load({
|
|
|
1563
1632
|
onClick: () => {
|
|
1564
1633
|
openBody(bodyB.name, bodyB.side, bodyB.rowId);
|
|
1565
1634
|
}
|
|
1566
|
-
}, "B")];
|
|
1635
|
+
}, "B · " + bodyB.name)];
|
|
1567
1636
|
})(), actions)));
|
|
1568
1637
|
}
|
|
1569
1638
|
const overlayKey = (event, onClose) => {
|
|
@@ -1586,39 +1655,55 @@ window.__ModuleLoader__.load({
|
|
|
1586
1655
|
}
|
|
1587
1656
|
};
|
|
1588
1657
|
function bodyNode(overlay, t, onClose) {
|
|
1589
|
-
|
|
1658
|
+
const Modal = platformModal();
|
|
1659
|
+
const title = t("overlay.body") + " · " + overlay.name;
|
|
1660
|
+
const inner = (0, react.createElement)("section", {
|
|
1590
1661
|
"data-role": "overlay",
|
|
1591
1662
|
"data-overlay": "body",
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1663
|
+
"aria-label": title,
|
|
1664
|
+
...Modal === void 0 ? {
|
|
1665
|
+
role: "dialog",
|
|
1666
|
+
"aria-modal": "true",
|
|
1667
|
+
onKeyDown: (event) => {
|
|
1668
|
+
overlayKey(event, onClose);
|
|
1669
|
+
}
|
|
1670
|
+
} : { "data-platform-modal": "true" }
|
|
1671
|
+
}, (0, react.createElement)("div", { "data-role": "overlay-head" }, (0, react.createElement)("h3", { "data-role": "overlay-title" }, title), (0, react.createElement)("button", {
|
|
1599
1672
|
type: "button",
|
|
1600
1673
|
"data-role": "overlay-close",
|
|
1601
|
-
autoFocus: true,
|
|
1674
|
+
...Modal === void 0 ? { autoFocus: true } : { "data-modal-autofocus": "true" },
|
|
1602
1675
|
onClick: onClose
|
|
1603
1676
|
}, t("close"))), (0, react.createElement)("p", { "data-role": "overlay-meta" }, t("body." + overlay.side) + " · " + (overlay.status === "ready" ? t("body.totalBytes") + " " + String(overlay.body?.totalBytes ?? 0) : "")), 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" && overlay.body !== void 0 ? (0, react.createElement)("div", null, overlay.body.truncated ? (0, react.createElement)("p", { "data-role": "body-truncated" }, t("body.truncated")) : null, overlay.body.text === "" ? (0, react.createElement)("p", { "data-role": "body-empty" }, t("body.empty")) : (0, react.createElement)("pre", { "data-role": "body-text" }, overlay.body.text)) : null);
|
|
1677
|
+
return Modal === void 0 ? inner : (0, react.createElement)(Modal, {
|
|
1678
|
+
open: true,
|
|
1679
|
+
onClose,
|
|
1680
|
+
title,
|
|
1681
|
+
closeLabel: t("close"),
|
|
1682
|
+
headless: true,
|
|
1683
|
+
className: "evo-merge-modal"
|
|
1684
|
+
}, inner);
|
|
1604
1685
|
}
|
|
1605
1686
|
function historyNode(overlay, t, onClose) {
|
|
1606
|
-
|
|
1687
|
+
const Modal = platformModal();
|
|
1688
|
+
const title = t("history");
|
|
1689
|
+
const inner = (0, react.createElement)("section", {
|
|
1607
1690
|
"data-role": "overlay",
|
|
1608
1691
|
"data-overlay": "history",
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
event.
|
|
1615
|
-
|
|
1692
|
+
"aria-label": title,
|
|
1693
|
+
...Modal === void 0 ? {
|
|
1694
|
+
role: "dialog",
|
|
1695
|
+
"aria-modal": "true",
|
|
1696
|
+
onKeyDown: (event) => {
|
|
1697
|
+
if (event.key === "Escape") {
|
|
1698
|
+
event.preventDefault();
|
|
1699
|
+
onClose();
|
|
1700
|
+
}
|
|
1616
1701
|
}
|
|
1617
|
-
}
|
|
1618
|
-
}, (0, react.createElement)("div", { "data-role": "overlay-head" }, (0, react.createElement)("h3", { "data-role": "overlay-title" },
|
|
1702
|
+
} : { "data-platform-modal": "true" }
|
|
1703
|
+
}, (0, react.createElement)("div", { "data-role": "overlay-head" }, (0, react.createElement)("h3", { "data-role": "overlay-title" }, title), (0, react.createElement)("button", {
|
|
1619
1704
|
type: "button",
|
|
1620
1705
|
"data-role": "overlay-close",
|
|
1621
|
-
autoFocus: true,
|
|
1706
|
+
...Modal === void 0 ? { autoFocus: true } : { "data-modal-autofocus": "true" },
|
|
1622
1707
|
onClick: onClose
|
|
1623
1708
|
}, 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" ? overlay.items === void 0 || overlay.items.length === 0 ? (0, react.createElement)("p", { "data-role": "history-empty" }, t("history.empty")) : (0, react.createElement)("ul", { "data-role": "history-list" }, overlay.items.map((item) => (0, react.createElement)("li", {
|
|
1624
1709
|
key: item.name + ":" + item.archivedAt,
|
|
@@ -1628,6 +1713,14 @@ window.__ModuleLoader__.load({
|
|
|
1628
1713
|
const reason = reasonText(t, item.reasonCode, item.reason);
|
|
1629
1714
|
return kind === reason ? kind : kind + " · " + reason;
|
|
1630
1715
|
})() + " · v" + String(item.lastVersion) + " · " + t("history.archivedAt", { date: new Date(item.archivedAt).toLocaleString() })))) : null);
|
|
1716
|
+
return Modal === void 0 ? inner : (0, react.createElement)(Modal, {
|
|
1717
|
+
open: true,
|
|
1718
|
+
onClose,
|
|
1719
|
+
title,
|
|
1720
|
+
closeLabel: t("close"),
|
|
1721
|
+
headless: true,
|
|
1722
|
+
className: "evo-merge-modal"
|
|
1723
|
+
}, inner);
|
|
1631
1724
|
}
|
|
1632
1725
|
function MergePanel(face) {
|
|
1633
1726
|
const { store, t } = face;
|
|
@@ -1635,6 +1728,8 @@ window.__ModuleLoader__.load({
|
|
|
1635
1728
|
const [copyState, setCopyState] = (0, react.useState)({ kind: "idle" });
|
|
1636
1729
|
const [orders, setOrders] = (0, react.useState)({});
|
|
1637
1730
|
const [dragId, setDragId] = (0, react.useState)(void 0);
|
|
1731
|
+
const [deciding, setDeciding] = (0, react.useState)(void 0);
|
|
1732
|
+
const [decisionNotice, setDecisionNotice] = (0, react.useState)(void 0);
|
|
1638
1733
|
const [menu, setMenu] = (0, react.useState)(void 0);
|
|
1639
1734
|
const returnFocus = (0, react.useRef)(null);
|
|
1640
1735
|
const captureFocus = () => {
|
|
@@ -1656,6 +1751,27 @@ window.__ModuleLoader__.load({
|
|
|
1656
1751
|
};
|
|
1657
1752
|
const workspaceId = resolveWorkspaceId(face.workspaceId);
|
|
1658
1753
|
const orderStore = (0, react.useMemo)(() => createRowOrderStore(), []);
|
|
1754
|
+
const decideRow = (rowId, verb) => {
|
|
1755
|
+
if (face.decide === void 0) return;
|
|
1756
|
+
setDeciding(rowId);
|
|
1757
|
+
(async () => {
|
|
1758
|
+
try {
|
|
1759
|
+
setDecisionNotice({
|
|
1760
|
+
rowId,
|
|
1761
|
+
...await face.decide(rowId, verb)
|
|
1762
|
+
});
|
|
1763
|
+
store.refresh();
|
|
1764
|
+
} catch (error) {
|
|
1765
|
+
setDecisionNotice({
|
|
1766
|
+
rowId,
|
|
1767
|
+
ok: false,
|
|
1768
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1769
|
+
});
|
|
1770
|
+
} finally {
|
|
1771
|
+
setDeciding(void 0);
|
|
1772
|
+
}
|
|
1773
|
+
})();
|
|
1774
|
+
};
|
|
1659
1775
|
const copy = (command) => {
|
|
1660
1776
|
(async () => {
|
|
1661
1777
|
try {
|
|
@@ -1705,15 +1821,15 @@ window.__ModuleLoader__.load({
|
|
|
1705
1821
|
const viewFailure = snapshot.viewState === "error" ? snapshot.viewFailure : void 0;
|
|
1706
1822
|
const queue = snapshot.current;
|
|
1707
1823
|
const uiState = blocked !== void 0 ? "blocked" : viewFailure !== void 0 ? "error" : snapshot.viewState === "loading" ? "loading" : queue.status === "error" ? "error" : queue.status === "loading" ? "loading" : queue.status === "empty" ? "empty" : "ready";
|
|
1708
|
-
const orderKey = rowOrderKey(workspaceId, snapshot.queue);
|
|
1709
|
-
const visibleOrder = orders[orderKey] ?? orderStore.read(workspaceId, snapshot.queue);
|
|
1824
|
+
const orderKey = rowOrderKey(workspaceId, snapshot.queue, snapshot.expiredOnly);
|
|
1825
|
+
const visibleOrder = orders[orderKey] ?? orderStore.read(workspaceId, snapshot.queue, snapshot.expiredOnly);
|
|
1710
1826
|
const visibleRows = orderRows(queue.rows, visibleOrder);
|
|
1711
1827
|
const saveOrder = (ids) => {
|
|
1712
1828
|
setOrders((previous) => ({
|
|
1713
1829
|
...previous,
|
|
1714
1830
|
[orderKey]: ids
|
|
1715
1831
|
}));
|
|
1716
|
-
orderStore.write(workspaceId, snapshot.queue, ids);
|
|
1832
|
+
orderStore.write(workspaceId, snapshot.queue, ids, snapshot.expiredOnly);
|
|
1717
1833
|
};
|
|
1718
1834
|
const sortHandlers = {
|
|
1719
1835
|
start: (id) => {
|
|
@@ -1785,13 +1901,18 @@ window.__ModuleLoader__.load({
|
|
|
1785
1901
|
store.toggleExpired();
|
|
1786
1902
|
}
|
|
1787
1903
|
}, t("tab.expired") + " " + String(view.expired)) : null;
|
|
1904
|
+
const notice = decisionNotice === void 0 ? null : (0, react.createElement)("p", {
|
|
1905
|
+
"data-role": "decision-notice",
|
|
1906
|
+
"data-ok": decisionNotice.ok ? "true" : "false"
|
|
1907
|
+
}, decisionNotice.message);
|
|
1788
1908
|
const list = uiState === "ready" && queue.status === "ready" ? (0, react.createElement)("div", {
|
|
1789
1909
|
"data-role": "rows",
|
|
1790
1910
|
id: "merge-rows",
|
|
1791
1911
|
role: "tabpanel"
|
|
1792
|
-
}, visibleRows.map((row) => rowNode(row, t, copy, sortHandlers, openBody))) : null;
|
|
1912
|
+
}, visibleRows.map((row) => rowNode(row, t, copy, sortHandlers, openBody, face.decide === void 0 ? void 0 : decideRow, deciding === row.id))) : null;
|
|
1793
1913
|
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;
|
|
1794
|
-
const
|
|
1914
|
+
const staleViewFailure = snapshot.viewState === "ready" ? snapshot.viewFailure : void 0;
|
|
1915
|
+
const activeFailure = viewFailure !== void 0 ? viewFailure : staleViewFailure !== void 0 ? staleViewFailure : queue.status === "error" ? queue.failure : void 0;
|
|
1795
1916
|
const overlay = snapshot.overlay;
|
|
1796
1917
|
const menuStyle = menu === void 0 ? void 0 : {
|
|
1797
1918
|
position: "fixed",
|
|
@@ -1868,7 +1989,6 @@ window.__ModuleLoader__.load({
|
|
|
1868
1989
|
}
|
|
1869
1990
|
}, t("start.pair"))), view.degraded ? (0, react.createElement)("p", { "data-role": "degraded" }, t("degraded") + " " + view.notes.join(",")) : null, (0, react.createElement)(SettingsCard, {
|
|
1870
1991
|
view,
|
|
1871
|
-
settings: face.settings,
|
|
1872
1992
|
t
|
|
1873
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", {
|
|
1874
1994
|
"data-role": "note",
|
|
@@ -1879,7 +1999,7 @@ window.__ModuleLoader__.load({
|
|
|
1879
1999
|
}, t("copied") + " " + (copyState.text ?? "")) : (0, react.createElement)("p", {
|
|
1880
2000
|
"data-role": "copy-failed",
|
|
1881
2001
|
role: "alert"
|
|
1882
|
-
}, t("copyFailed")), list, empty, queue.nextCursor === void 0 || uiState !== "ready" ? null : (0, react.createElement)("button", {
|
|
2002
|
+
}, t("copyFailed")), notice, list, empty, queue.nextCursor === void 0 || uiState !== "ready" ? null : (0, react.createElement)("button", {
|
|
1883
2003
|
type: "button",
|
|
1884
2004
|
"data-role": "load-more",
|
|
1885
2005
|
disabled: queue.status === "loading",
|
|
@@ -1957,6 +2077,7 @@ window.__ModuleLoader__.load({
|
|
|
1957
2077
|
overlayToken = 0;
|
|
1958
2078
|
snapshot;
|
|
1959
2079
|
started = false;
|
|
2080
|
+
loadedView = false;
|
|
1960
2081
|
disposed = false;
|
|
1961
2082
|
constructor(source, initial = {}) {
|
|
1962
2083
|
this.source = source;
|
|
@@ -2030,14 +2151,16 @@ window.__ModuleLoader__.load({
|
|
|
2030
2151
|
});
|
|
2031
2152
|
return;
|
|
2032
2153
|
}
|
|
2154
|
+
const keeping = this.loadedView;
|
|
2033
2155
|
this.set({
|
|
2034
2156
|
...this.snapshot,
|
|
2035
|
-
viewState: "error",
|
|
2157
|
+
viewState: keeping ? "ready" : "error",
|
|
2036
2158
|
viewFailure: outcome.failure,
|
|
2037
2159
|
viewRefreshing: false
|
|
2038
2160
|
});
|
|
2039
2161
|
return;
|
|
2040
2162
|
}
|
|
2163
|
+
this.loadedView = true;
|
|
2041
2164
|
const wasBlocked = this.snapshot.viewState === "blocked";
|
|
2042
2165
|
this.set({
|
|
2043
2166
|
...this.snapshot,
|
|
@@ -2261,8 +2384,19 @@ window.__ModuleLoader__.load({
|
|
|
2261
2384
|
}
|
|
2262
2385
|
};
|
|
2263
2386
|
//#endregion
|
|
2387
|
+
//#region src/client/session.ts
|
|
2388
|
+
function currentSessionId(ctx) {
|
|
2389
|
+
const byId = ctx.sessions?.list?.getSnapshot?.().byId;
|
|
2390
|
+
if (byId === void 0) return void 0;
|
|
2391
|
+
return Object.values(byId).find((session) => (session.retainedBy?.mainView ?? 0) > 0)?.id;
|
|
2392
|
+
}
|
|
2393
|
+
//#endregion
|
|
2264
2394
|
//#region src/client/index.ts
|
|
2265
|
-
const inject = [
|
|
2395
|
+
const inject = [
|
|
2396
|
+
"slots",
|
|
2397
|
+
"sessions",
|
|
2398
|
+
"locale"
|
|
2399
|
+
];
|
|
2266
2400
|
/** The view component receives the workbench's activeView marker alongside its face. */
|
|
2267
2401
|
function MergeView(props) {
|
|
2268
2402
|
return props.activeView === "merge" ? MergePanel(props) : null;
|
|
@@ -2272,6 +2406,10 @@ window.__ModuleLoader__.load({
|
|
|
2272
2406
|
* @param ctx - the client context.
|
|
2273
2407
|
*/
|
|
2274
2408
|
function apply(ctx) {
|
|
2409
|
+
const seat = createSettingsSeat(ctx);
|
|
2410
|
+
ctx.effect(() => () => {
|
|
2411
|
+
seat.dispose?.();
|
|
2412
|
+
}, "evolution-merge-ui: settings seat");
|
|
2275
2413
|
registerWorkbenchView(ctx, {
|
|
2276
2414
|
id: PANEL_ID,
|
|
2277
2415
|
order: 45,
|
|
@@ -2292,7 +2430,6 @@ window.__ModuleLoader__.load({
|
|
|
2292
2430
|
body,
|
|
2293
2431
|
history
|
|
2294
2432
|
};
|
|
2295
|
-
const seat = createSettingsSeat(ctx);
|
|
2296
2433
|
const workspaceId = panelWorkspaceId(ctx);
|
|
2297
2434
|
return {
|
|
2298
2435
|
store: new MergeStore(source),
|
|
@@ -2302,6 +2439,20 @@ window.__ModuleLoader__.load({
|
|
|
2302
2439
|
...seat.get("evolution-merge") === void 0 ? {} : { merge: seat.get("evolution-merge") },
|
|
2303
2440
|
...seat.get("evolution-approval") === void 0 ? {} : { platform: seat.get("evolution-approval") }
|
|
2304
2441
|
},
|
|
2442
|
+
decide: async (rowId, verb) => {
|
|
2443
|
+
const sessionId = currentSessionId(ctx);
|
|
2444
|
+
if (sessionId === void 0) return {
|
|
2445
|
+
ok: false,
|
|
2446
|
+
message: "没有当前会话;请打开会话后重试"
|
|
2447
|
+
};
|
|
2448
|
+
const result = await decide(rowId, verb, sessionId);
|
|
2449
|
+
if (result.ok) return result.payload;
|
|
2450
|
+
const failure = result.failure;
|
|
2451
|
+
return {
|
|
2452
|
+
ok: false,
|
|
2453
|
+
message: "message" in failure && typeof failure.message === "string" ? failure.message : "审批请求失败"
|
|
2454
|
+
};
|
|
2455
|
+
},
|
|
2305
2456
|
...workspaceId === void 0 ? {} : { workspaceId }
|
|
2306
2457
|
};
|
|
2307
2458
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Batch 4 merge panel: keyed read store, four tabs, local overlays, localized errors. */
|
|
2
2
|
import { type ReactNode } from 'react';
|
|
3
3
|
import type { MergeStore } from './MergeStore.ts';
|
|
4
|
-
import type {
|
|
4
|
+
import type { SettingsFace } from '@lmzhen/dsh-evolution-client-kit';
|
|
5
5
|
export type Translate = (key: string, values?: Readonly<Record<string, string | number>>) => string;
|
|
6
6
|
export interface MergeFace {
|
|
7
7
|
store: MergeStore;
|
|
@@ -9,7 +9,10 @@ export interface MergeFace {
|
|
|
9
9
|
doctorCommand?: string;
|
|
10
10
|
settings?: SettingsFace;
|
|
11
11
|
workspaceId?: string;
|
|
12
|
+
decide?: (rowId: string, verb: 'approve' | 'reject') => Promise<{
|
|
13
|
+
ok: boolean;
|
|
14
|
+
message: string;
|
|
15
|
+
}>;
|
|
12
16
|
}
|
|
13
|
-
export declare function saveSetting(form: ConfigFormLike, field: string, value: boolean): Promise<boolean>;
|
|
14
17
|
export declare function MergePanel(face: MergeFace): ReactNode;
|
|
15
18
|
//# sourceMappingURL=Panel.d.ts.map
|
|
@@ -65,7 +65,8 @@ export interface MergeViewPayload {
|
|
|
65
65
|
};
|
|
66
66
|
notes: string[];
|
|
67
67
|
degraded: boolean;
|
|
68
|
-
|
|
68
|
+
activeRun?: MergeRunView;
|
|
69
|
+
lastRun?: MergeRunView;
|
|
69
70
|
approval: MergeApproval;
|
|
70
71
|
}
|
|
71
72
|
export interface RowActionView {
|
|
@@ -177,6 +178,13 @@ export declare const isBlocked: (failure: MergeFailure) => failure is MergeBlock
|
|
|
177
178
|
export declare function view(): Promise<MergeOutcome<MergeViewPayload>>;
|
|
178
179
|
export declare function rows(queue: MergeQueue, cursor?: string, expiredOnly?: boolean): Promise<MergeOutcome<QueuePage>>;
|
|
179
180
|
export declare function body(name: string, side: 'live' | 'archive', rowId?: string): Promise<MergeOutcome<MergeBody>>;
|
|
181
|
+
export interface MergeDecisionOutcome {
|
|
182
|
+
readonly ok: boolean;
|
|
183
|
+
readonly message: string;
|
|
184
|
+
readonly code?: string;
|
|
185
|
+
readonly runId?: string;
|
|
186
|
+
}
|
|
187
|
+
export declare function decide(rowId: string, verb: 'approve' | 'reject', sessionId: string): Promise<MergeOutcome<MergeDecisionOutcome>>;
|
|
180
188
|
export declare function history(): Promise<MergeOutcome<{
|
|
181
189
|
items: MergeHistoryItem[];
|
|
182
190
|
}>>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Platform Modal reached through the rc.3 client module table. */
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
export interface PlatformModalProps {
|
|
4
|
+
readonly open: boolean;
|
|
5
|
+
readonly onClose: () => void;
|
|
6
|
+
readonly title: string;
|
|
7
|
+
readonly closeLabel: string;
|
|
8
|
+
readonly children?: ReactNode;
|
|
9
|
+
readonly headless?: boolean;
|
|
10
|
+
readonly className?: string;
|
|
11
|
+
}
|
|
12
|
+
export type PlatformModalComponent = (props: PlatformModalProps) => ReactNode;
|
|
13
|
+
/** The platform Modal, or undefined in a non-browser/SSR render or a deployment without the row. */
|
|
14
|
+
export declare function platformModal(): PlatformModalComponent | undefined;
|
|
15
|
+
//# sourceMappingURL=platform-modal.d.ts.map
|
|
@@ -7,12 +7,12 @@ export interface StorageLike {
|
|
|
7
7
|
export type RowOrderEdge = 'top' | 'bottom';
|
|
8
8
|
/** Workspace scope for one tab. A missing panel workspace is the local scope. */
|
|
9
9
|
export declare function resolveWorkspaceId(workspaceId: string | null | undefined): string;
|
|
10
|
-
/** Stable localStorage key for one workspace and
|
|
11
|
-
export declare function rowOrderKey(workspaceId: string | null | undefined, queue: MergeQueue): string;
|
|
10
|
+
/** Stable localStorage key for one workspace, queue and expired filter. */
|
|
11
|
+
export declare function rowOrderKey(workspaceId: string | null | undefined, queue: MergeQueue, expiredOnly?: boolean): string;
|
|
12
12
|
/** One tab's persisted order; failures degrade to an empty (wire) order. */
|
|
13
13
|
export declare function createRowOrderStore(storage?: StorageLike | undefined): {
|
|
14
|
-
read(workspaceId: string | null | undefined, queue: MergeQueue): readonly string[];
|
|
15
|
-
write(workspaceId: string | null | undefined, queue: MergeQueue, ids: readonly string[]): void;
|
|
14
|
+
read(workspaceId: string | null | undefined, queue: MergeQueue, expiredOnly?: boolean): readonly string[];
|
|
15
|
+
write(workspaceId: string | null | undefined, queue: MergeQueue, ids: readonly string[], expiredOnly?: boolean): void;
|
|
16
16
|
};
|
|
17
17
|
/** Apply persisted ids first, then append unknown rows in their wire order. */
|
|
18
18
|
export declare function orderRows<T extends {
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
]
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"version": "0.
|
|
14
|
+
"version": "0.34.0",
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"react-dom": "^18.2.0"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@lmzhen/dsh-evolution-client-kit": "^0.
|
|
54
|
+
"@lmzhen/dsh-evolution-client-kit": "^0.34.0"
|
|
55
55
|
},
|
|
56
56
|
"engines": {
|
|
57
57
|
"dsh": ">=0.2.1-rc.2 <0.2.2-0"
|