@lmzhen/dsh-evolution-merge-ui 0.30.17 → 0.30.19
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 +1640 -354
- package/lib/types/client/MergeStore.d.ts +74 -0
- package/lib/types/client/Panel.d.ts +10 -14
- package/lib/types/client/api.d.ts +103 -19
- package/lib/types/client/fallbacks.d.ts +3 -0
- package/lib/types/client/index.d.ts +1 -4
- package/lib/types/client/routes.generated.d.ts +2 -0
- package/lib/types/client/seam.d.ts +20 -0
- package/lib/types/client/sorting.d.ts +25 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -5,14 +5,10 @@ window.__ModuleLoader__.load({
|
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let react = require("react");
|
|
8
|
-
//#
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* external), so the table is mirrored here mechanically; a rename in core regenerates all three
|
|
13
|
-
* client copies, and the generator's --check makes a stale copy red.
|
|
14
|
-
*/
|
|
15
|
-
const ROUTES = {
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/client/api.ts
|
|
10
|
+
/** Read-only merge wire client. Classifies every failure and never writes. */
|
|
11
|
+
const HOST_ROUTES = {
|
|
16
12
|
approval: {
|
|
17
13
|
pending: "/api/dsh-evolution/approval/pending",
|
|
18
14
|
preview: "/api/dsh-evolution/approval/preview",
|
|
@@ -31,56 +27,62 @@ window.__ModuleLoader__.load({
|
|
|
31
27
|
merge: {
|
|
32
28
|
view: "/api/dsh-evolution/merge/view",
|
|
33
29
|
rows: "/api/dsh-evolution/merge/rows",
|
|
30
|
+
run: "/api/dsh-evolution/merge/run",
|
|
31
|
+
runs: "/api/dsh-evolution/merge/runs",
|
|
34
32
|
body: "/api/dsh-evolution/merge/body",
|
|
35
33
|
history: "/api/dsh-evolution/merge/history"
|
|
36
34
|
},
|
|
37
35
|
diagnostics: { view: "/api/dsh-evolution/diagnostics" }
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
kind: "forbidden",
|
|
49
|
-
status: 403
|
|
36
|
+
}.merge;
|
|
37
|
+
const isBlocked = (failure) => failure.kind === "blocked";
|
|
38
|
+
const asReadiness = (value) => {
|
|
39
|
+
const raw = typeof value === "object" && value !== null ? value : {};
|
|
40
|
+
const steps = Array.isArray(raw.steps) ? raw.steps.filter((step) => typeof step === "string") : void 0;
|
|
41
|
+
return {
|
|
42
|
+
...typeof raw.ok === "boolean" ? { ok: raw.ok } : {},
|
|
43
|
+
...typeof raw.code === "string" ? { code: raw.code } : {},
|
|
44
|
+
...typeof raw.message === "string" ? { message: raw.message } : {},
|
|
45
|
+
...steps === void 0 ? {} : { steps }
|
|
50
46
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
};
|
|
48
|
+
const asPlatformWrite = (value) => {
|
|
49
|
+
if (typeof value === "boolean") return {
|
|
50
|
+
enabled: value,
|
|
51
|
+
capability: true
|
|
54
52
|
};
|
|
55
|
-
return
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
54
|
+
const raw = value;
|
|
55
|
+
const enabled = typeof raw.enabled === "boolean" ? raw.enabled : typeof raw.value === "boolean" ? raw.value : void 0;
|
|
56
|
+
const capability = typeof raw.capability === "boolean" ? raw.capability : typeof raw.available === "boolean" ? raw.available : true;
|
|
57
|
+
return enabled === void 0 ? void 0 : {
|
|
58
|
+
enabled,
|
|
59
|
+
capability
|
|
58
60
|
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
async function
|
|
61
|
+
};
|
|
62
|
+
const problem = (code, status, wireCode, message) => ({
|
|
63
|
+
kind: "problem",
|
|
64
|
+
code,
|
|
65
|
+
status,
|
|
66
|
+
...wireCode === void 0 ? {} : { wireCode },
|
|
67
|
+
...message === void 0 ? {} : { message }
|
|
68
|
+
});
|
|
69
|
+
async function requestWire(path) {
|
|
68
70
|
let response;
|
|
69
71
|
try {
|
|
70
|
-
response = await
|
|
71
|
-
} catch
|
|
72
|
+
response = await fetch(path, { headers: { accept: "application/json" } });
|
|
73
|
+
} catch {
|
|
72
74
|
return {
|
|
73
75
|
ok: false,
|
|
74
|
-
failure:
|
|
75
|
-
kind: "server",
|
|
76
|
-
status: 0,
|
|
77
|
-
detail: error instanceof Error ? error.message : String(error)
|
|
78
|
-
}
|
|
76
|
+
failure: problem("server", 0)
|
|
79
77
|
};
|
|
80
78
|
}
|
|
81
|
-
if (
|
|
79
|
+
if (response.status === 401) return {
|
|
80
|
+
ok: false,
|
|
81
|
+
failure: problem("unauthenticated", 401)
|
|
82
|
+
};
|
|
83
|
+
if (response.status === 403) return {
|
|
82
84
|
ok: false,
|
|
83
|
-
failure:
|
|
85
|
+
failure: problem("forbidden", 403)
|
|
84
86
|
};
|
|
85
87
|
let body;
|
|
86
88
|
try {
|
|
@@ -88,87 +90,250 @@ window.__ModuleLoader__.load({
|
|
|
88
90
|
} catch {
|
|
89
91
|
return {
|
|
90
92
|
ok: false,
|
|
91
|
-
failure:
|
|
92
|
-
kind: "server",
|
|
93
|
-
status: response.status
|
|
94
|
-
}
|
|
93
|
+
failure: problem("server", response.status)
|
|
95
94
|
};
|
|
96
95
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
const record = body;
|
|
97
|
+
const code = typeof record.code === "string" ? record.code : void 0;
|
|
98
|
+
const message = typeof record.message === "string" ? record.message : void 0;
|
|
99
|
+
if (code === "E-323" || message?.startsWith("E-323") === true) return {
|
|
100
|
+
ok: false,
|
|
101
|
+
failure: problem("capability", response.status, code, message)
|
|
102
|
+
};
|
|
103
|
+
if (response.status === 503 && code === "merge-state-blocked" && typeof record.readiness === "object" && record.readiness !== null) return {
|
|
104
|
+
ok: false,
|
|
105
|
+
failure: {
|
|
106
|
+
kind: "blocked",
|
|
107
|
+
code,
|
|
108
|
+
readiness: asReadiness(record.readiness)
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
if (response.status === 404) {
|
|
112
|
+
if (code === "E-325") return {
|
|
113
|
+
ok: false,
|
|
114
|
+
failure: problem("unmounted", 404, code, message)
|
|
102
115
|
};
|
|
103
|
-
|
|
104
|
-
const errorRecord = typeof nested === "object" && nested !== null ? nested : void 0;
|
|
105
|
-
const code = typeof record.code === "string" && record.code !== "" ? record.code : typeof errorRecord?.code === "string" ? errorRecord.code : void 0;
|
|
106
|
-
const message = typeof record.message === "string" && record.message !== "" ? record.message : typeof errorRecord?.message === "string" ? errorRecord.message : void 0;
|
|
107
|
-
if (record.ok === false && code !== void 0 && message !== void 0 && message !== "") return {
|
|
116
|
+
if (code === "merge-body-missing" || code === "merge-body-not-found") return {
|
|
108
117
|
ok: false,
|
|
109
|
-
failure:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
118
|
+
failure: problem("body-missing", 404, code, message)
|
|
119
|
+
};
|
|
120
|
+
return {
|
|
121
|
+
ok: false,
|
|
122
|
+
failure: problem("unmounted", 404, code, message)
|
|
114
123
|
};
|
|
115
124
|
}
|
|
116
|
-
return {
|
|
125
|
+
if (response.status === 400 && code === "merge-bad-query") return {
|
|
117
126
|
ok: false,
|
|
118
|
-
failure:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
failure: problem("bad-query", 400, code, message)
|
|
128
|
+
};
|
|
129
|
+
if (!response.ok) return {
|
|
130
|
+
ok: false,
|
|
131
|
+
failure: problem("server", response.status, code, message)
|
|
132
|
+
};
|
|
133
|
+
if (record.wireVersion !== 1) return {
|
|
134
|
+
ok: false,
|
|
135
|
+
failure: problem("wire-version", response.status, code, message)
|
|
136
|
+
};
|
|
137
|
+
if (code === "merge-body-missing" || code === "merge-body-not-found") return {
|
|
138
|
+
ok: false,
|
|
139
|
+
failure: problem("body-missing", response.status, code, message)
|
|
140
|
+
};
|
|
141
|
+
if (code !== void 0) return {
|
|
142
|
+
ok: false,
|
|
143
|
+
failure: problem("refused", response.status, code, message)
|
|
144
|
+
};
|
|
145
|
+
return {
|
|
146
|
+
ok: true,
|
|
147
|
+
payload: body
|
|
122
148
|
};
|
|
123
149
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
150
|
+
const toPlatformWrite = (facts) => asPlatformWrite(facts.approval.platformWrite ?? facts.platformWrite);
|
|
151
|
+
const toRun = (run) => ({
|
|
152
|
+
id: run.id,
|
|
153
|
+
state: run.state,
|
|
154
|
+
...run.command === void 0 ? {} : { command: run.command },
|
|
155
|
+
...run.stage === void 0 ? {} : { stage: run.stage },
|
|
156
|
+
...run.progress === null || run.progress === void 0 ? {} : { progress: {
|
|
157
|
+
done: run.progress.done,
|
|
158
|
+
total: run.progress.total
|
|
159
|
+
} },
|
|
160
|
+
startedAt: run.startedAt,
|
|
161
|
+
...run.endedAt === void 0 ? {} : { endedAt: run.endedAt },
|
|
162
|
+
...run.failure === void 0 ? {} : { failure: {
|
|
163
|
+
stage: run.failure.stage,
|
|
164
|
+
code: run.failure.code,
|
|
165
|
+
retryable: run.failure.retryable,
|
|
166
|
+
...run.failure.detail === void 0 ? {} : { detail: run.failure.detail }
|
|
167
|
+
} },
|
|
168
|
+
...run.parentRunId === void 0 ? {} : { parentRunId: run.parentRunId },
|
|
169
|
+
...run.currentPairKey === void 0 ? {} : { currentPairKey: run.currentPairKey },
|
|
170
|
+
...run.resultRef === void 0 ? {} : { resultRef: run.resultRef },
|
|
171
|
+
actions: (run.actions ?? []).map((action) => ({
|
|
172
|
+
id: action.id,
|
|
173
|
+
command: action.command,
|
|
174
|
+
confirm: action.confirm === true,
|
|
175
|
+
enabled: action.enabled !== false,
|
|
176
|
+
...action.disabledReason === void 0 ? {} : { disabledReason: action.disabledReason }
|
|
177
|
+
}))
|
|
178
|
+
});
|
|
179
|
+
const stageOf = (row) => {
|
|
180
|
+
const normalize = (raw) => {
|
|
181
|
+
if (typeof raw === "string") return raw === "reserved" || raw === "present" || raw === "expired" || raw === "lost" || raw === "absent" ? { state: raw } : void 0;
|
|
182
|
+
if (raw === void 0) return void 0;
|
|
183
|
+
if (raw.state === "reserved" || raw.state === "present" || raw.state === "expired" || raw.state === "lost" || raw.state === "absent") return {
|
|
184
|
+
state: raw.state,
|
|
185
|
+
...raw.expiresAt === void 0 ? {} : { expiresAt: raw.expiresAt }
|
|
186
|
+
};
|
|
187
|
+
if (raw.state === "kept") return {
|
|
188
|
+
state: "present",
|
|
189
|
+
...raw.expiresAt === void 0 ? {} : { expiresAt: raw.expiresAt }
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
const stage = normalize(row.stage);
|
|
193
|
+
const staging = normalize(row.staging);
|
|
194
|
+
if (stage === void 0) return staging;
|
|
195
|
+
const expiresAt = stage.expiresAt ?? (staging?.state === stage.state ? staging.expiresAt : void 0);
|
|
196
|
+
return expiresAt === void 0 ? stage : {
|
|
197
|
+
...stage,
|
|
198
|
+
expiresAt
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
const toRow = (row) => ({
|
|
202
|
+
id: row.id,
|
|
203
|
+
pairKey: row.id,
|
|
204
|
+
a: row.a,
|
|
205
|
+
b: row.b,
|
|
206
|
+
state: row.state,
|
|
207
|
+
queue: row.queue,
|
|
208
|
+
stage: null,
|
|
209
|
+
label: row.a + " + " + row.b,
|
|
210
|
+
updatedAt: new Date(row.updatedAt).toISOString(),
|
|
211
|
+
createdAt: new Date(row.createdAt).toISOString(),
|
|
212
|
+
...row.target === void 0 ? {} : {
|
|
213
|
+
target: row.target.requested,
|
|
214
|
+
...row.target.actual === void 0 ? {} : { targetActual: row.target.actual },
|
|
215
|
+
...row.target.created === void 0 ? {} : { targetCreated: row.target.created }
|
|
216
|
+
},
|
|
217
|
+
...row.confidence === void 0 ? {} : { confidence: row.confidence },
|
|
218
|
+
...row.summary === void 0 ? {} : { summary: {
|
|
219
|
+
a: row.summary.a,
|
|
220
|
+
b: row.summary.b,
|
|
221
|
+
rationale: row.summary.rationale
|
|
222
|
+
} },
|
|
223
|
+
...row.reason === void 0 ? {} : { reason: row.reason },
|
|
224
|
+
...row.reasonCode === void 0 ? {} : { reasonCode: row.reasonCode },
|
|
225
|
+
...row.origin === void 0 ? {} : { origin: row.origin },
|
|
226
|
+
...row.attempts === void 0 ? {} : { attempts: row.attempts },
|
|
227
|
+
...row.expiresAt === void 0 ? {} : { stagingExpiresAt: row.expiresAt },
|
|
228
|
+
...row.expired === void 0 ? {} : { expired: row.expired.kind },
|
|
229
|
+
...stageOf(row) === void 0 ? {} : { stageView: stageOf(row) },
|
|
230
|
+
...row.failure === void 0 ? {} : { failure: {
|
|
231
|
+
stage: row.failure.stage,
|
|
232
|
+
code: row.failure.code,
|
|
233
|
+
message: row.failure.detail ?? row.failure.code,
|
|
234
|
+
retryable: row.failure.retryable
|
|
235
|
+
} },
|
|
236
|
+
...row.verifySubState === void 0 ? {} : { verifySubState: row.verifySubState },
|
|
237
|
+
...row.skipKind === void 0 ? {} : { skipKind: row.skipKind },
|
|
238
|
+
...row.bodies === void 0 ? {} : { bodies: row.bodies.map((body) => ({
|
|
239
|
+
name: body.name,
|
|
240
|
+
side: body.side
|
|
241
|
+
})) },
|
|
242
|
+
actions: row.actions.map((action) => ({
|
|
243
|
+
id: action.id,
|
|
244
|
+
command: action.command,
|
|
245
|
+
confirm: action.confirm,
|
|
246
|
+
enabled: action.enabled,
|
|
247
|
+
...action.disabledReason === void 0 ? {} : { disabledReason: action.disabledReason }
|
|
248
|
+
}))
|
|
249
|
+
});
|
|
131
250
|
async function view() {
|
|
132
|
-
const answer = await
|
|
133
|
-
|
|
251
|
+
const answer = await requestWire(HOST_ROUTES.view);
|
|
252
|
+
if (!answer.ok) return answer;
|
|
253
|
+
const facts = answer.payload;
|
|
254
|
+
const platformWrite = toPlatformWrite(facts);
|
|
255
|
+
return {
|
|
134
256
|
ok: true,
|
|
135
|
-
payload:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
257
|
+
payload: {
|
|
258
|
+
counts: facts.counts.active,
|
|
259
|
+
expired: facts.counts.expired,
|
|
260
|
+
tabs: [
|
|
261
|
+
"verify",
|
|
262
|
+
"pending",
|
|
263
|
+
"fuse",
|
|
264
|
+
"skipped"
|
|
265
|
+
].map((queue) => ({
|
|
266
|
+
queue,
|
|
267
|
+
count: facts.counts.active[queue]
|
|
268
|
+
})),
|
|
269
|
+
commands: facts.fallback.map((item) => item.command),
|
|
270
|
+
startCommands: facts.startCommands,
|
|
271
|
+
notes: [...facts.notes],
|
|
272
|
+
degraded: facts.degraded,
|
|
273
|
+
...facts.last === null && facts.active === null ? {} : { latestRun: toRun(facts.last ?? facts.active) },
|
|
274
|
+
approval: {
|
|
275
|
+
mergeApproval: facts.approval.mergeApproval,
|
|
276
|
+
...platformWrite === void 0 ? {} : { platformWrite }
|
|
277
|
+
}
|
|
278
|
+
}
|
|
139
279
|
};
|
|
140
280
|
}
|
|
141
|
-
async function rows(queue, cursor =
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
ok: true,
|
|
146
|
-
payload: answer.data
|
|
147
|
-
} : {
|
|
281
|
+
async function rows(queue, cursor, expiredOnly = false) {
|
|
282
|
+
const answer = await requestWire(HOST_ROUTES.rows + "?queue=" + encodeURIComponent(queue) + (cursor === void 0 ? "" : "&cursor=" + encodeURIComponent(cursor)) + (expiredOnly ? "&expired=1" : ""));
|
|
283
|
+
if (!answer.ok) return answer;
|
|
284
|
+
if (answer.payload.queue !== queue || answer.payload.expiredOnly !== expiredOnly) return {
|
|
148
285
|
ok: false,
|
|
149
|
-
failure:
|
|
286
|
+
failure: problem("server", 200)
|
|
287
|
+
};
|
|
288
|
+
return {
|
|
289
|
+
ok: true,
|
|
290
|
+
payload: {
|
|
291
|
+
queue: answer.payload.queue,
|
|
292
|
+
expiredOnly: answer.payload.expiredOnly,
|
|
293
|
+
items: answer.payload.rows.map(toRow),
|
|
294
|
+
counts: answer.payload.counts,
|
|
295
|
+
...answer.payload.nextCursor === void 0 ? {} : { nextCursor: answer.payload.nextCursor }
|
|
296
|
+
}
|
|
150
297
|
};
|
|
151
298
|
}
|
|
152
|
-
async function body(
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
299
|
+
async function body(name, side) {
|
|
300
|
+
const answer = await requestWire(HOST_ROUTES.body + "?name=" + encodeURIComponent(name) + "&side=" + side);
|
|
301
|
+
if (!answer.ok) {
|
|
302
|
+
if (answer.failure.kind === "problem" && answer.failure.code === "bad-query" && (answer.failure.message ?? "").includes("multiple merge rows")) return {
|
|
303
|
+
ok: false,
|
|
304
|
+
failure: {
|
|
305
|
+
...answer.failure,
|
|
306
|
+
code: "body-ambiguous"
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
return answer;
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
156
312
|
ok: true,
|
|
157
|
-
payload:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
313
|
+
payload: {
|
|
314
|
+
name: answer.payload.name,
|
|
315
|
+
side: answer.payload.side,
|
|
316
|
+
text: answer.payload.text,
|
|
317
|
+
markdown: answer.payload.markdown,
|
|
318
|
+
truncated: answer.payload.truncated,
|
|
319
|
+
totalBytes: answer.payload.totalBytes
|
|
320
|
+
}
|
|
161
321
|
};
|
|
162
322
|
}
|
|
163
323
|
async function history() {
|
|
164
|
-
const answer = await
|
|
324
|
+
const answer = await requestWire(HOST_ROUTES.history);
|
|
165
325
|
return answer.ok ? {
|
|
166
326
|
ok: true,
|
|
167
|
-
payload: answer.
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
327
|
+
payload: { items: answer.payload.items.map((item) => ({
|
|
328
|
+
name: item.name,
|
|
329
|
+
kind: item.kind,
|
|
330
|
+
reason: item.reason,
|
|
331
|
+
...item.reasonCode === void 0 ? {} : { reasonCode: item.reasonCode },
|
|
332
|
+
lastVersion: item.lastVersion,
|
|
333
|
+
archivedAt: new Date(item.archivedAt).toISOString(),
|
|
334
|
+
...item.sourceRunId === void 0 ? {} : { sourceRunId: item.sourceRunId }
|
|
335
|
+
})) }
|
|
336
|
+
} : answer;
|
|
172
337
|
}
|
|
173
338
|
//#endregion
|
|
174
339
|
//#region src/client/seam.ts
|
|
@@ -178,6 +343,13 @@ window.__ModuleLoader__.load({
|
|
|
178
343
|
const NS = "evolution-merge";
|
|
179
344
|
const zh = {
|
|
180
345
|
"entry.label": "技能合并",
|
|
346
|
+
"title": "技能合并",
|
|
347
|
+
"start.scan": "复制扫描命令",
|
|
348
|
+
"start.pair": "复制配对命令",
|
|
349
|
+
"degraded": "读模型降级:",
|
|
350
|
+
"copied": "已复制:",
|
|
351
|
+
"row.noSummary": "无摘要",
|
|
352
|
+
"overlay.body": "正文",
|
|
181
353
|
"hint": "手动触发;后台逐对判定。这里只读,不写技能。",
|
|
182
354
|
"history": "历史",
|
|
183
355
|
"close": "关闭",
|
|
@@ -186,6 +358,7 @@ window.__ModuleLoader__.load({
|
|
|
186
358
|
"tab.fuse": "待合并",
|
|
187
359
|
"tab.skipped": "无需合并",
|
|
188
360
|
"empty.verify": "没有待判断的对。",
|
|
361
|
+
"empty.scope": "这里只做两轮合成;机械追加属于 skill 管理,不进入合并队列。",
|
|
189
362
|
"empty.pending": "没有待批准的合并。",
|
|
190
363
|
"empty.fuse": "没有待合并的对。",
|
|
191
364
|
"empty.skipped": "没有标记为无需合并的对。",
|
|
@@ -195,11 +368,20 @@ window.__ModuleLoader__.load({
|
|
|
195
368
|
"approval.on": "审批开:合并前需人工批准。",
|
|
196
369
|
"approval.off": "审批关:合并自动执行。",
|
|
197
370
|
"failed": "读取失败,保留上次结果。",
|
|
371
|
+
"blocked.title": "合并状态未就绪",
|
|
372
|
+
"blocked.hint": "迁移/备份修复后刷新;面板不会自动降级。",
|
|
373
|
+
"blocked.doctor": "复制诊断命令",
|
|
374
|
+
"blocked.detail": "查看原始信息",
|
|
375
|
+
"blocked.reason.migration-blocked": "合并状态需要迁移,面板已暂停读取。",
|
|
376
|
+
"blocked.reason.needs-repair": "合并状态需要修复,面板已暂停读取。",
|
|
377
|
+
"blocked.reason.forward-only": "合并状态版本过新,当前面板暂不支持。",
|
|
378
|
+
"blocked.reason.unknown": "合并状态未就绪,面板已暂停读取。",
|
|
198
379
|
"stage.decide": "判定",
|
|
199
380
|
"stage.author": "合并",
|
|
200
381
|
"stage.validate": "检查",
|
|
201
382
|
"stage.commit": "提交",
|
|
202
383
|
"row.target": "目标",
|
|
384
|
+
"row.actualTarget": "实际目标",
|
|
203
385
|
"row.confidence": "置信度",
|
|
204
386
|
"row.attempts": "尝试",
|
|
205
387
|
"row.origin": "来源",
|
|
@@ -209,6 +391,59 @@ window.__ModuleLoader__.load({
|
|
|
209
391
|
"row.failure": "失败",
|
|
210
392
|
"row.noRetry": "不可重试",
|
|
211
393
|
"row.copy": "复制命令",
|
|
394
|
+
"tab.expired": "已过期",
|
|
395
|
+
"row.targetCreated": "新建",
|
|
396
|
+
"row.verify": "判定状态",
|
|
397
|
+
"row.staging": "暂存",
|
|
398
|
+
"row.skipKind": "跳过类型",
|
|
399
|
+
"row.bodies": "正文",
|
|
400
|
+
"verify.queued": "排队",
|
|
401
|
+
"verify.running": "进行中",
|
|
402
|
+
"verify.failed": "失败",
|
|
403
|
+
"verify.cancelled": "已取消",
|
|
404
|
+
"staging.none": "无",
|
|
405
|
+
"staging.kept": "保留",
|
|
406
|
+
"staging.cleared-source-ok": "已清理(源完好)",
|
|
407
|
+
"staging.cleared-source-gone": "已清理(源已缺失)",
|
|
408
|
+
"skipKind.agent-keep": "自动保留",
|
|
409
|
+
"skipKind.human-reject": "人工拒绝",
|
|
410
|
+
"skipKind.over-limit": "超限",
|
|
411
|
+
"skipKind.forced": "强制",
|
|
412
|
+
"action.approve": "复制批准",
|
|
413
|
+
"action.reject": "复制拒绝",
|
|
414
|
+
"action.retry-candidates": "重试候选",
|
|
415
|
+
"action.retry-resume": "重试续跑",
|
|
416
|
+
"action.discard": "复制丢弃",
|
|
417
|
+
"action.restore": "恢复",
|
|
418
|
+
"action.pair": "复制配对",
|
|
419
|
+
"action.status": "状态",
|
|
420
|
+
"action.report": "报告",
|
|
421
|
+
"action.cancel": "取消",
|
|
422
|
+
"action.confirm": "确认复制",
|
|
423
|
+
"disabled.expired": "已过期,不可用",
|
|
424
|
+
"disabled.invalid": "状态不允许",
|
|
425
|
+
"disabled.not-retryable": "不可重试",
|
|
426
|
+
"disabled.source-gone": "源已缺失",
|
|
427
|
+
"disabled.owned": "已有运行",
|
|
428
|
+
"disabled.unavailable": "暂不可用",
|
|
429
|
+
"history.empty": "没有历史。",
|
|
430
|
+
"failureServer": "读取失败",
|
|
431
|
+
"failureUnauthorized": "未登录",
|
|
432
|
+
"failureForbidden": "无权访问",
|
|
433
|
+
"failureUnmounted": "宿主未挂载",
|
|
434
|
+
"failureCapability": "子代理通道不可用",
|
|
435
|
+
"failureCapabilityHint": "先运行全局诊断,或复制下方命令继续处理。preset/host-only 形态没有面板时仍可用这些命令兜底。",
|
|
436
|
+
"failureBodyAmbiguous": "同名技能匹配到多行,无法确定读取哪一个;请用唯一名称或从具体行打开。",
|
|
437
|
+
"fallbackHint": "可复制命令见下方",
|
|
438
|
+
"body.missing": "正文不存在或不可读。",
|
|
439
|
+
"expired.target-taken": "目标已被占用",
|
|
440
|
+
"expired.source-changed": "源已变更",
|
|
441
|
+
"expired.source-gone": "源已缺失",
|
|
442
|
+
"expired.skipped-ttl": "跳过已到期",
|
|
443
|
+
"history.kind.merged": "已合并",
|
|
444
|
+
"history.kind.deleted": "已删除",
|
|
445
|
+
"history.kind.split": "已拆分",
|
|
446
|
+
"history.kind.other": "其他",
|
|
212
447
|
"origin.agent": "自动",
|
|
213
448
|
"origin.human": "人工",
|
|
214
449
|
"state.verify": "待判定",
|
|
@@ -217,8 +452,98 @@ window.__ModuleLoader__.load({
|
|
|
217
452
|
"state.fuse": "待合并",
|
|
218
453
|
"state.skipped": "已跳过"
|
|
219
454
|
};
|
|
455
|
+
Object.assign(zh, {
|
|
456
|
+
"stage.screening": "筛选",
|
|
457
|
+
"stage.settle": "结算",
|
|
458
|
+
"stage.state.reserved": "已预留",
|
|
459
|
+
"stage.state.present": "已暂存",
|
|
460
|
+
"stage.state.expired": "已过期",
|
|
461
|
+
"stage.state.lost": "暂存丢失",
|
|
462
|
+
"stage.state.absent": "无暂存",
|
|
463
|
+
"origin.system": "系统",
|
|
464
|
+
"row.id": "编号",
|
|
465
|
+
"row.requestedTarget": "请求目标",
|
|
466
|
+
"row.stage": "合并暂存",
|
|
467
|
+
"row.summaryA": "摘要 A",
|
|
468
|
+
"row.summaryB": "摘要 B",
|
|
469
|
+
"row.rationale": "理由",
|
|
470
|
+
"row.notProvided": "未提供",
|
|
471
|
+
"row.fullId": "完整编号",
|
|
472
|
+
"row.actions": "操作",
|
|
473
|
+
"action.unavailable": "不可用",
|
|
474
|
+
"history.reason.target-taken": "目标已被占用",
|
|
475
|
+
"history.reason.source-changed": "源已变更",
|
|
476
|
+
"history.reason.skipped-ttl": "跳过已到期",
|
|
477
|
+
"history.reason.validation-failed": "检查失败",
|
|
478
|
+
"history.reason.merge-over-limit": "超过限制",
|
|
479
|
+
"history.reason.source-gone": "源已缺失",
|
|
480
|
+
"history.reason.merged": "已合并",
|
|
481
|
+
"history.reason.archived": "已归档",
|
|
482
|
+
"history.reason.unknown": "原因未提供",
|
|
483
|
+
"history.lastVersion": "最后版本",
|
|
484
|
+
"history.archivedAt": "归档时间",
|
|
485
|
+
"body.truncated": "正文过长,已截断。",
|
|
486
|
+
"body.empty": "正文为空。",
|
|
487
|
+
"body.totalBytes": "总字节",
|
|
488
|
+
"body.live": "当前版本",
|
|
489
|
+
"body.archive": "归档版本",
|
|
490
|
+
"failureWireVersion": "宿主返回了不兼容的数据版本,请升级页面。",
|
|
491
|
+
"failureBadQuery": "请求已失效,请刷新后重试。",
|
|
492
|
+
"failureBodyMissing": "正文不存在或不可读。",
|
|
493
|
+
"failureRefused": "宿主拒绝了这次读取。",
|
|
494
|
+
"failureDetails": "查看详情",
|
|
495
|
+
"failureFallback": "可复制命令见下方",
|
|
496
|
+
"settings.title": "审批设置",
|
|
497
|
+
"settings.hint": "两段审批分开显示;值来自宿主能力,不从另一项推导。",
|
|
498
|
+
"settings.mergeApproval": "合并审批",
|
|
499
|
+
"settings.platformWrite": "平台写入审批",
|
|
500
|
+
"settings.on": "开",
|
|
501
|
+
"settings.off": "关",
|
|
502
|
+
"settings.capabilityMissing": "宿主未提供该能力",
|
|
503
|
+
"settings.capabilityDisabled": "当前部署不可用",
|
|
504
|
+
"settings.readonly": "只读显示;修改请到平台设置页。",
|
|
505
|
+
"run.title": "运行",
|
|
506
|
+
"run.id": "运行编号",
|
|
507
|
+
"run.state": "状态",
|
|
508
|
+
"run.stage": "阶段",
|
|
509
|
+
"run.progress": "进度",
|
|
510
|
+
"run.endedAt": "结束时间",
|
|
511
|
+
"run.failure": "失败",
|
|
512
|
+
"run.currentPair": "当前对",
|
|
513
|
+
"run.parent": "父运行",
|
|
514
|
+
"run.report": "报告",
|
|
515
|
+
"run.noReport": "暂无报告",
|
|
516
|
+
"run.resultRef": "报告位置",
|
|
517
|
+
"run.actions": "运行操作",
|
|
518
|
+
"run.running": "运行中",
|
|
519
|
+
"run.ended": "已结束",
|
|
520
|
+
"run.cancelled": "已取消",
|
|
521
|
+
"run.failed": "失败",
|
|
522
|
+
"run.succeeded": "成功",
|
|
523
|
+
"run.awaiting": "等待审批",
|
|
524
|
+
"run.awaiting-approval": "等待审批",
|
|
525
|
+
"run.undone": "已撤销",
|
|
526
|
+
"run.superseded": "已失效",
|
|
527
|
+
"run.interrupted": "已中断",
|
|
528
|
+
"run.orphan": "孤立",
|
|
529
|
+
"error.title": "读取失败",
|
|
530
|
+
"error.retry": "重试",
|
|
531
|
+
"error.raw": "原始信息",
|
|
532
|
+
"doctor.open": "打开全局诊断",
|
|
533
|
+
"sort.updatedAt": "按更新时间",
|
|
534
|
+
"sort.score": "按分数",
|
|
535
|
+
"pin": "置顶",
|
|
536
|
+
"unpin": "取消置顶"
|
|
537
|
+
});
|
|
220
538
|
const en = {
|
|
221
539
|
"entry.label": "Skill merge",
|
|
540
|
+
"title": "Skill merge",
|
|
541
|
+
"start.scan": "Copy scan command",
|
|
542
|
+
"start.pair": "Copy pair command",
|
|
543
|
+
"degraded": "Degraded read model:",
|
|
544
|
+
"copied": "Copied:",
|
|
545
|
+
"row.noSummary": "No summary",
|
|
546
|
+
"overlay.body": "Body",
|
|
222
547
|
"hint": "Manual only; pairs are judged in the background. Read-only here.",
|
|
223
548
|
"history": "History",
|
|
224
549
|
"close": "Close",
|
|
@@ -227,6 +552,7 @@ window.__ModuleLoader__.load({
|
|
|
227
552
|
"tab.fuse": "Ready to merge",
|
|
228
553
|
"tab.skipped": "Skipped",
|
|
229
554
|
"empty.verify": "No pairs to judge.",
|
|
555
|
+
"empty.scope": "This panel only performs two-round synthesis; mechanical append belongs to skill management and does not enter the merge queue.",
|
|
230
556
|
"empty.pending": "No pending merges.",
|
|
231
557
|
"empty.fuse": "No pairs ready to merge.",
|
|
232
558
|
"empty.skipped": "No pairs marked as not worth merging.",
|
|
@@ -236,11 +562,20 @@ window.__ModuleLoader__.load({
|
|
|
236
562
|
"approval.on": "Approval on: merges wait for a human.",
|
|
237
563
|
"approval.off": "Approval off: merges run automatically.",
|
|
238
564
|
"failed": "Read failed; keeping the last result.",
|
|
565
|
+
"blocked.title": "Merge state blocked",
|
|
566
|
+
"blocked.hint": "Fix the migration/backup, then refresh. The panel does not fall back automatically.",
|
|
567
|
+
"blocked.doctor": "Copy diagnostics command",
|
|
568
|
+
"blocked.detail": "Show host message",
|
|
569
|
+
"blocked.reason.migration-blocked": "Merge state needs migration; the panel is paused.",
|
|
570
|
+
"blocked.reason.needs-repair": "Merge state needs repair; the panel is paused.",
|
|
571
|
+
"blocked.reason.forward-only": "Merge state was written by a newer version; this panel cannot read it.",
|
|
572
|
+
"blocked.reason.unknown": "Merge state is not ready; the panel is paused.",
|
|
239
573
|
"stage.decide": "Decide",
|
|
240
574
|
"stage.author": "Author",
|
|
241
575
|
"stage.validate": "Validate",
|
|
242
576
|
"stage.commit": "Commit",
|
|
243
577
|
"row.target": "Target",
|
|
578
|
+
"row.actualTarget": "Actual target",
|
|
244
579
|
"row.confidence": "Confidence",
|
|
245
580
|
"row.attempts": "Attempts",
|
|
246
581
|
"row.origin": "Origin",
|
|
@@ -250,6 +585,59 @@ window.__ModuleLoader__.load({
|
|
|
250
585
|
"row.failure": "Failure",
|
|
251
586
|
"row.noRetry": "not retryable",
|
|
252
587
|
"row.copy": "Copy command",
|
|
588
|
+
"tab.expired": "Expired",
|
|
589
|
+
"row.targetCreated": "created",
|
|
590
|
+
"row.verify": "Verify state",
|
|
591
|
+
"row.staging": "Staging",
|
|
592
|
+
"row.skipKind": "Skip kind",
|
|
593
|
+
"row.bodies": "Bodies",
|
|
594
|
+
"verify.queued": "queued",
|
|
595
|
+
"verify.running": "running",
|
|
596
|
+
"verify.failed": "failed",
|
|
597
|
+
"verify.cancelled": "cancelled",
|
|
598
|
+
"staging.none": "none",
|
|
599
|
+
"staging.kept": "kept",
|
|
600
|
+
"staging.cleared-source-ok": "cleared (source ok)",
|
|
601
|
+
"staging.cleared-source-gone": "cleared (source gone)",
|
|
602
|
+
"skipKind.agent-keep": "agent keep",
|
|
603
|
+
"skipKind.human-reject": "human reject",
|
|
604
|
+
"skipKind.over-limit": "over limit",
|
|
605
|
+
"skipKind.forced": "forced",
|
|
606
|
+
"action.approve": "Copy approve",
|
|
607
|
+
"action.reject": "Copy reject",
|
|
608
|
+
"action.retry-candidates": "Retry candidates",
|
|
609
|
+
"action.retry-resume": "Retry resume",
|
|
610
|
+
"action.discard": "Copy discard",
|
|
611
|
+
"action.restore": "Restore",
|
|
612
|
+
"action.pair": "Copy pair",
|
|
613
|
+
"action.status": "Status",
|
|
614
|
+
"action.report": "Report",
|
|
615
|
+
"action.cancel": "Cancel",
|
|
616
|
+
"action.confirm": "Copy confirmation",
|
|
617
|
+
"disabled.expired": "expired",
|
|
618
|
+
"disabled.invalid": "invalid state",
|
|
619
|
+
"disabled.not-retryable": "not retryable",
|
|
620
|
+
"disabled.source-gone": "source gone",
|
|
621
|
+
"disabled.owned": "already running",
|
|
622
|
+
"disabled.unavailable": "unavailable",
|
|
623
|
+
"history.empty": "No history.",
|
|
624
|
+
"failureServer": "Read failed",
|
|
625
|
+
"failureUnauthorized": "Not signed in",
|
|
626
|
+
"failureForbidden": "Forbidden",
|
|
627
|
+
"failureUnmounted": "Host not mounted",
|
|
628
|
+
"failureCapability": "Subagent channel unavailable",
|
|
629
|
+
"failureCapabilityHint": "Run global diagnostics first, or copy a command below to continue. The command fallback also covers preset/host-only shapes without a panel.",
|
|
630
|
+
"failureBodyAmbiguous": "The skill name matches multiple rows, so the body is ambiguous. Use a unique name or open it from a specific row.",
|
|
631
|
+
"fallbackHint": "Copy the command below",
|
|
632
|
+
"body.missing": "Body missing or unreadable.",
|
|
633
|
+
"expired.target-taken": "target taken",
|
|
634
|
+
"expired.source-changed": "source changed",
|
|
635
|
+
"expired.source-gone": "source gone",
|
|
636
|
+
"expired.skipped-ttl": "skip expired",
|
|
637
|
+
"history.kind.merged": "Merged",
|
|
638
|
+
"history.kind.deleted": "Deleted",
|
|
639
|
+
"history.kind.split": "Split",
|
|
640
|
+
"history.kind.other": "Other",
|
|
253
641
|
"origin.agent": "auto",
|
|
254
642
|
"origin.human": "human",
|
|
255
643
|
"state.verify": "Unverified",
|
|
@@ -258,6 +646,117 @@ window.__ModuleLoader__.load({
|
|
|
258
646
|
"state.fuse": "Ready to merge",
|
|
259
647
|
"state.skipped": "Skipped"
|
|
260
648
|
};
|
|
649
|
+
Object.assign(en, {
|
|
650
|
+
"stage.screening": "Screen",
|
|
651
|
+
"stage.settle": "Settle",
|
|
652
|
+
"stage.state.reserved": "Reserved",
|
|
653
|
+
"stage.state.present": "Staged",
|
|
654
|
+
"stage.state.expired": "Expired",
|
|
655
|
+
"stage.state.lost": "Staging lost",
|
|
656
|
+
"stage.state.absent": "Not staged",
|
|
657
|
+
"origin.system": "System",
|
|
658
|
+
"row.id": "ID",
|
|
659
|
+
"row.requestedTarget": "Requested target",
|
|
660
|
+
"row.stage": "Merge staging",
|
|
661
|
+
"row.summaryA": "Summary A",
|
|
662
|
+
"row.summaryB": "Summary B",
|
|
663
|
+
"row.rationale": "Rationale",
|
|
664
|
+
"row.notProvided": "not provided",
|
|
665
|
+
"row.fullId": "Full ID",
|
|
666
|
+
"row.actions": "Actions",
|
|
667
|
+
"action.unavailable": "Unavailable",
|
|
668
|
+
"history.reason.target-taken": "target taken",
|
|
669
|
+
"history.reason.source-changed": "source changed",
|
|
670
|
+
"history.reason.skipped-ttl": "skip expired",
|
|
671
|
+
"history.reason.validation-failed": "validation failed",
|
|
672
|
+
"history.reason.merge-over-limit": "over limit",
|
|
673
|
+
"history.reason.source-gone": "source gone",
|
|
674
|
+
"history.reason.merged": "merged",
|
|
675
|
+
"history.reason.archived": "archived",
|
|
676
|
+
"history.reason.unknown": "reason not provided",
|
|
677
|
+
"history.lastVersion": "Last version",
|
|
678
|
+
"history.archivedAt": "Archived at",
|
|
679
|
+
"body.truncated": "Body is truncated.",
|
|
680
|
+
"body.empty": "Body is empty.",
|
|
681
|
+
"body.totalBytes": "Total bytes",
|
|
682
|
+
"body.live": "Live",
|
|
683
|
+
"body.archive": "Archive",
|
|
684
|
+
"failureWireVersion": "The host returned an incompatible data version; reload the page.",
|
|
685
|
+
"failureBadQuery": "This request is stale; refresh and retry.",
|
|
686
|
+
"failureBodyMissing": "Body missing or unreadable.",
|
|
687
|
+
"failureRefused": "The host refused this read.",
|
|
688
|
+
"failureDetails": "Show details",
|
|
689
|
+
"failureFallback": "Copy a command below",
|
|
690
|
+
"settings.title": "Approvals",
|
|
691
|
+
"settings.hint": "Two independent approval values; each comes from host capability, never derived from the other.",
|
|
692
|
+
"settings.mergeApproval": "Merge approval",
|
|
693
|
+
"settings.platformWrite": "Platform write approval",
|
|
694
|
+
"settings.on": "On",
|
|
695
|
+
"settings.off": "Off",
|
|
696
|
+
"settings.capabilityMissing": "Host did not provide this capability",
|
|
697
|
+
"settings.capabilityDisabled": "Not available in this deployment",
|
|
698
|
+
"settings.readonly": "Read-only here; edit in platform settings.",
|
|
699
|
+
"run.title": "Run",
|
|
700
|
+
"run.id": "Run ID",
|
|
701
|
+
"run.state": "State",
|
|
702
|
+
"run.stage": "Stage",
|
|
703
|
+
"run.progress": "Progress",
|
|
704
|
+
"run.endedAt": "Ended at",
|
|
705
|
+
"run.failure": "Failure",
|
|
706
|
+
"run.currentPair": "Current pair",
|
|
707
|
+
"run.parent": "Parent run",
|
|
708
|
+
"run.report": "Report",
|
|
709
|
+
"run.noReport": "No report yet",
|
|
710
|
+
"run.resultRef": "Report location",
|
|
711
|
+
"run.actions": "Run actions",
|
|
712
|
+
"run.running": "Running",
|
|
713
|
+
"run.ended": "Ended",
|
|
714
|
+
"run.cancelled": "Cancelled",
|
|
715
|
+
"run.failed": "Failed",
|
|
716
|
+
"run.succeeded": "Succeeded",
|
|
717
|
+
"run.awaiting": "Awaiting approval",
|
|
718
|
+
"run.awaiting-approval": "Awaiting approval",
|
|
719
|
+
"run.undone": "Undone",
|
|
720
|
+
"run.superseded": "Superseded",
|
|
721
|
+
"run.interrupted": "Interrupted",
|
|
722
|
+
"run.orphan": "Orphan",
|
|
723
|
+
"error.title": "Read failed",
|
|
724
|
+
"error.retry": "Retry",
|
|
725
|
+
"error.raw": "Raw message",
|
|
726
|
+
"doctor.open": "Open global diagnostics",
|
|
727
|
+
"sort.updatedAt": "Last updated",
|
|
728
|
+
"sort.score": "Score",
|
|
729
|
+
"pin": "Pin",
|
|
730
|
+
"unpin": "Unpin"
|
|
731
|
+
});
|
|
732
|
+
Object.assign(zh, {
|
|
733
|
+
"settings.saved": "已保存",
|
|
734
|
+
"settings.saveFailed": "保存失败",
|
|
735
|
+
"settings.openPlatform": "打开平台设置",
|
|
736
|
+
"settings.live": "可直接在此保存;platformWrite 能力来自宿主。"
|
|
737
|
+
});
|
|
738
|
+
Object.assign(en, {
|
|
739
|
+
"settings.saved": "Saved",
|
|
740
|
+
"settings.saveFailed": "Save failed",
|
|
741
|
+
"settings.openPlatform": "Open platform settings",
|
|
742
|
+
"settings.live": "Save directly here; platformWrite capability comes from the host."
|
|
743
|
+
});
|
|
744
|
+
Object.assign(zh, { "settings.platformWriteLinkHint": "此开关属于平台设置,这里只读;请到平台设置修改。" });
|
|
745
|
+
Object.assign(en, { "settings.platformWriteLinkHint": "This switch belongs to platform settings; this card is read-only. Change it in platform settings." });
|
|
746
|
+
Object.assign(zh, {
|
|
747
|
+
"sort.drag": "拖动排序",
|
|
748
|
+
"sort.menu": "行排序",
|
|
749
|
+
"sort.pinTop": "置顶",
|
|
750
|
+
"sort.pinBottom": "置底",
|
|
751
|
+
"sort.cancel": "取消"
|
|
752
|
+
});
|
|
753
|
+
Object.assign(en, {
|
|
754
|
+
"sort.drag": "Drag to reorder",
|
|
755
|
+
"sort.menu": "Row order",
|
|
756
|
+
"sort.pinTop": "Pin to top",
|
|
757
|
+
"sort.pinBottom": "Pin to bottom",
|
|
758
|
+
"sort.cancel": "Cancel"
|
|
759
|
+
});
|
|
261
760
|
//#endregion
|
|
262
761
|
//#region src/client/styles.ts
|
|
263
762
|
const CSS_TAG_ID = "evolution-merge-panel";
|
|
@@ -272,266 +771,1051 @@ window.__ModuleLoader__.load({
|
|
|
272
771
|
".evolution-merge-panel [data-role=\"tabs\"] { display:flex; gap:var(--evo-space-6); border-bottom:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); }",
|
|
273
772
|
".evolution-merge-panel [data-role=\"tab\"] { background:none; border:0; border-bottom:var(--evo-hairline-width) solid transparent; padding:var(--evo-space-6) var(--evo-space-8); cursor:pointer; color:inherit; }",
|
|
274
773
|
".evolution-merge-panel [data-role=\"tab\"][data-active=\"true\"] { border-bottom-color:var(--dsw-alias-brand-primary); }",
|
|
774
|
+
".evolution-merge-panel button:focus-visible { outline:2px solid currentColor !important; outline-offset:2px; box-shadow:0 0 0 2px currentColor !important; }",
|
|
775
|
+
".evolution-merge-panel [data-role=\"title\"] { margin:0; font-size:var(--evo-type-lg); font-weight:600; }",
|
|
776
|
+
".evolution-merge-panel [data-role=\"start\"] { display:flex; gap:var(--evo-space-6); flex-wrap:wrap; }",
|
|
777
|
+
".evolution-merge-panel [data-role=\"degraded\"] { margin:0; color:var(--dsw-alias-state-warning-primary); font-size:var(--evo-type-xs); }",
|
|
778
|
+
".evolution-merge-panel [data-role=\"expired-toggle\"][data-active=\"true\"] { background:var(--dsw-alias-brand-primary); color:var(--dsw-alias-bg-base); }",
|
|
779
|
+
".evolution-merge-panel [data-role=\"failure\"] { display:flex; flex-direction:column; gap:var(--evo-space-6); }",
|
|
780
|
+
".evolution-merge-panel [data-role=\"failure\"] [data-tone=\"fail\"] { color:var(--dsw-alias-state-error-primary); }",
|
|
781
|
+
".evolution-merge-panel [data-role=\"fallback\"] { display:flex; gap:var(--evo-space-6); flex-wrap:wrap; }",
|
|
782
|
+
".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); }",
|
|
783
|
+
".evolution-merge-panel [data-role=\"overlay-head\"] { display:flex; align-items:center; justify-content:space-between; gap:var(--evo-space-8); }",
|
|
784
|
+
".evolution-merge-panel [data-role=\"overlay-title\"] { margin:0; font-size:var(--evo-type-lg); }",
|
|
275
785
|
".evolution-merge-panel [data-role=\"rows\"] { display:flex; flex-direction:column; gap:var(--evo-space-6); }",
|
|
276
|
-
".evolution-merge-panel [data-role=\"row\"] { display:grid; grid-template-columns:1fr auto; gap:var(--evo-space-8); padding:var(--evo-space-8); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); }",
|
|
786
|
+
".evolution-merge-panel [data-role=\"row\"] { display:grid; grid-template-columns:1fr auto; gap:var(--evo-space-8); padding:var(--evo-space-8); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); cursor:grab; }",
|
|
787
|
+
".evolution-merge-panel [data-role=\"row\"]:active { cursor:grabbing; }",
|
|
277
788
|
".evolution-merge-panel [data-role=\"row-label\"] { font-weight:600; }",
|
|
278
789
|
".evolution-merge-panel [data-role=\"row-meta\"] { color:var(--dsw-alias-label-tertiary); font-size:var(--evo-type-xs); }",
|
|
279
790
|
".evolution-merge-panel [data-role=\"note\"] { color:var(--dsw-alias-label-tertiary); font-size:var(--evo-type-xs); }",
|
|
791
|
+
".evolution-merge-panel [data-role=\"blocked\"] { display:flex; flex-direction:column; gap:var(--evo-space-8); padding:var(--evo-space-12); border:var(--evo-hairline-width) solid var(--dsw-alias-state-warning-primary); border-left-width:var(--evo-hairline-width); border-radius:var(--evo-radius-control); background:var(--dsw-alias-bg-layer-1); }",
|
|
792
|
+
".evolution-merge-panel [data-role=\"blocked-title\"] { margin:0; font-size:var(--evo-type-lg); font-weight:600; color:var(--dsw-alias-state-warning-primary); }",
|
|
793
|
+
".evolution-merge-panel [data-role=\"blocked-reason\"] { margin:0; white-space:pre-wrap; overflow-wrap:anywhere; }",
|
|
794
|
+
".evolution-merge-panel [data-role=\"blocked-hint\"] { margin:0; color:var(--dsw-alias-label-tertiary); font-size:var(--evo-type-xs); }",
|
|
795
|
+
".evolution-merge-panel [data-role=\"blocked-actions\"] { display:flex; gap:var(--evo-space-6); flex-wrap:wrap; }",
|
|
796
|
+
".evolution-merge-panel [data-role=\"content\"] { display:flex; flex-direction:column; gap:var(--evo-space-12); }",
|
|
797
|
+
".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); }",
|
|
798
|
+
".evolution-merge-panel [data-role=\"settings-title\"] { margin:0; font-size:var(--evo-type-sm); }",
|
|
799
|
+
".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); }",
|
|
800
|
+
".evolution-merge-panel [data-role=\"settings-section\"] { display:grid; grid-template-columns:minmax(0,1fr) auto auto; align-items:center; column-gap:var(--evo-space-8); }",
|
|
801
|
+
".evolution-merge-panel [data-role=\"settings-section\"][data-disabled=\"true\"] { color:var(--dsw-alias-label-tertiary); }",
|
|
802
|
+
".evolution-merge-panel [data-role=\"settings-toggle\"] { margin:0; }",
|
|
803
|
+
".evolution-merge-panel [data-role=\"settings-value\"] { font-weight:600; min-width:2.5em; text-align:right; }",
|
|
804
|
+
".evolution-merge-panel [data-role=\"settings-note\"] { grid-column:1/-1; color:var(--dsw-alias-label-tertiary); font-size:var(--evo-type-xs); }",
|
|
805
|
+
".evolution-merge-panel [data-role=\"settings-link\"] { grid-column:1/-1; color:var(--dsw-alias-brand-primary); font-size:var(--evo-type-xs); }",
|
|
806
|
+
".evolution-merge-panel [data-role=\"run-strip\"] { display:flex; gap:var(--evo-space-8); flex-wrap:wrap; align-items:center; font-size:var(--evo-type-xs); }",
|
|
807
|
+
".evolution-merge-panel [data-role=\"run-failure\"] { color:var(--dsw-alias-state-error-primary); }",
|
|
808
|
+
".evolution-merge-panel [data-role=\"stage-badge\"] { display:inline-block; margin-top:var(--evo-space-4); padding:0 var(--evo-space-4); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); font-size:var(--evo-type-xs); }",
|
|
809
|
+
".evolution-merge-panel [data-role=\"stage-badge\"][data-tone=\"warn\"] { color:var(--dsw-alias-state-warning-primary); }",
|
|
810
|
+
".evolution-merge-panel [data-role=\"stage-badge\"][data-tone=\"fail\"] { color:var(--dsw-alias-state-error-primary); border-color:var(--dsw-alias-state-error-primary); }",
|
|
811
|
+
".evolution-merge-panel [data-role=\"row-id\"] { color:var(--dsw-alias-label-tertiary); font-size:var(--evo-type-xs); }",
|
|
812
|
+
".evolution-merge-panel [data-role=\"pending-summary\"] { display:flex; flex-direction:column; gap:var(--evo-space-4); margin-top:var(--evo-space-4); }",
|
|
813
|
+
".evolution-merge-panel [data-role=\"pending-summary-slot\"] { display:flex; gap:var(--evo-space-6); }",
|
|
814
|
+
".evolution-merge-panel [data-role=\"pending-summary-label\"] { color:var(--dsw-alias-label-tertiary); min-width:calc(var(--evo-space-16) * 2); }",
|
|
815
|
+
".evolution-merge-panel [data-role=\"body-text\"] { white-space:pre-wrap; overflow-wrap:anywhere; max-height:50vh; overflow:auto; }",
|
|
816
|
+
".evolution-merge-panel [data-role=\"overlay\"] { 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); }",
|
|
817
|
+
".evolution-merge-panel button:focus-visible, .evolution-merge-panel a:focus-visible { outline:2px solid var(--dsw-alias-brand-primary); outline-offset:2px; }",
|
|
818
|
+
".evolution-merge-panel [data-role=\"sort-menu\"] { position:fixed; z-index:70; display:flex; flex-direction:column; min-width:var(--evo-measure-read); padding:var(--evo-space-4); 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-6) var(--dsw-alias-border-l2); }",
|
|
819
|
+
".evolution-merge-panel [data-role=\"sort-menu\"] button { text-align:left; }",
|
|
280
820
|
".evolution-merge-panel [data-role=\"refresh\"] { align-self:flex-start; }"
|
|
281
821
|
].join("\n");
|
|
282
822
|
//#endregion
|
|
283
|
-
//#region src/client/
|
|
284
|
-
/**
|
|
285
|
-
function
|
|
286
|
-
const
|
|
287
|
-
return
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
function
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
case "server": return failure.status === 0 ? t("failureServer") : t("failureServer") + " (HTTP " + String(failure.status) + ")";
|
|
299
|
-
case "refused": return failure.message;
|
|
823
|
+
//#region src/client/sorting.ts
|
|
824
|
+
/** Workspace scope for one tab. A missing panel workspace is the local scope. */
|
|
825
|
+
function resolveWorkspaceId(workspaceId) {
|
|
826
|
+
const value = workspaceId?.trim() ?? "";
|
|
827
|
+
return value === "" ? "local" : value;
|
|
828
|
+
}
|
|
829
|
+
/** Stable localStorage key for one workspace and queue. */
|
|
830
|
+
function rowOrderKey(workspaceId, queue) {
|
|
831
|
+
return "dsh-evolution-merge.row-order.v1:" + encodeURIComponent(resolveWorkspaceId(workspaceId)) + ":" + queue;
|
|
832
|
+
}
|
|
833
|
+
function defaultStorage() {
|
|
834
|
+
try {
|
|
835
|
+
return globalThis.localStorage;
|
|
836
|
+
} catch {
|
|
837
|
+
return;
|
|
300
838
|
}
|
|
301
839
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
840
|
+
function normalize(raw) {
|
|
841
|
+
if (raw === null) return [];
|
|
842
|
+
try {
|
|
843
|
+
const value = JSON.parse(raw);
|
|
844
|
+
if (!Array.isArray(value)) return [];
|
|
845
|
+
const ids = [];
|
|
846
|
+
const seen = /* @__PURE__ */ new Set();
|
|
847
|
+
for (const item of value) {
|
|
848
|
+
if (typeof item !== "string" || item === "" || seen.has(item)) continue;
|
|
849
|
+
seen.add(item);
|
|
850
|
+
ids.push(item);
|
|
851
|
+
}
|
|
852
|
+
return ids;
|
|
853
|
+
} catch {
|
|
854
|
+
return [];
|
|
855
|
+
}
|
|
310
856
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
857
|
+
/** One tab's persisted order; failures degrade to an empty (wire) order. */
|
|
858
|
+
function createRowOrderStore(storage = defaultStorage()) {
|
|
859
|
+
return {
|
|
860
|
+
read(workspaceId, queue) {
|
|
861
|
+
if (storage === void 0) return [];
|
|
862
|
+
try {
|
|
863
|
+
return normalize(storage.getItem(rowOrderKey(workspaceId, queue)));
|
|
864
|
+
} catch {
|
|
865
|
+
return [];
|
|
866
|
+
}
|
|
867
|
+
},
|
|
868
|
+
write(workspaceId, queue, ids) {
|
|
869
|
+
if (storage === void 0) return;
|
|
870
|
+
try {
|
|
871
|
+
storage.setItem(rowOrderKey(workspaceId, queue), JSON.stringify(ids));
|
|
872
|
+
} catch {}
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
}
|
|
876
|
+
/** Apply persisted ids first, then append unknown rows in their wire order. */
|
|
877
|
+
function orderRows(rows, order) {
|
|
878
|
+
if (order.length === 0) return rows;
|
|
879
|
+
const byId = new Map(rows.map((row) => [row.id, row]));
|
|
880
|
+
const out = [];
|
|
881
|
+
const seen = /* @__PURE__ */ new Set();
|
|
882
|
+
for (const id of order) {
|
|
883
|
+
const row = byId.get(id);
|
|
884
|
+
if (row === void 0 || seen.has(id)) continue;
|
|
885
|
+
seen.add(id);
|
|
886
|
+
out.push(row);
|
|
326
887
|
}
|
|
327
|
-
|
|
888
|
+
for (const row of rows) if (!seen.has(row.id)) out.push(row);
|
|
889
|
+
return out;
|
|
890
|
+
}
|
|
891
|
+
/** Move one visible row before another; unknown ids leave the order unchanged. */
|
|
892
|
+
function moveRow(order, fromId, beforeId) {
|
|
893
|
+
if (!order.includes(fromId)) return order;
|
|
894
|
+
const rest = order.filter((id) => id !== fromId);
|
|
895
|
+
if (beforeId === void 0) return [...rest, fromId];
|
|
896
|
+
const index = rest.indexOf(beforeId);
|
|
897
|
+
if (index < 0) return [...rest, fromId];
|
|
898
|
+
return [
|
|
899
|
+
...rest.slice(0, index),
|
|
900
|
+
fromId,
|
|
901
|
+
...rest.slice(index)
|
|
902
|
+
];
|
|
903
|
+
}
|
|
904
|
+
/** Pin one visible row to the top or bottom of the full visible order. */
|
|
905
|
+
function pinRow(order, id, edge) {
|
|
906
|
+
if (!order.includes(id)) return order;
|
|
907
|
+
const rest = order.filter((item) => item !== id);
|
|
908
|
+
return edge === "top" ? [id, ...rest] : [...rest, id];
|
|
909
|
+
}
|
|
910
|
+
//#endregion
|
|
911
|
+
//#region src/client/fallbacks.ts
|
|
912
|
+
/** Static command-face fallback for a Facts read failure; the API fallback is unavailable then. */
|
|
913
|
+
const FALLBACK_COMMANDS = [
|
|
914
|
+
"/evolution merge scan",
|
|
915
|
+
"/evolution merge pair <a> <b>",
|
|
916
|
+
"/evolution merge pending",
|
|
917
|
+
"/evolution merge pending --expired",
|
|
918
|
+
"/evolution merge skipped",
|
|
919
|
+
"/evolution merge candidates",
|
|
920
|
+
"/evolution merge status",
|
|
921
|
+
"/evolution merge report",
|
|
922
|
+
"/evolution doctor"
|
|
923
|
+
];
|
|
328
924
|
//#endregion
|
|
329
925
|
//#region src/client/Panel.ts
|
|
330
|
-
/**
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
926
|
+
/** Batch 4 merge panel: keyed read store, four tabs, local overlays, localized errors. */
|
|
927
|
+
async function saveSetting(form, field, value) {
|
|
928
|
+
try {
|
|
929
|
+
return await form.set(field, value);
|
|
930
|
+
} catch {
|
|
931
|
+
return false;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
334
934
|
const QUEUES = [
|
|
335
935
|
"verify",
|
|
336
936
|
"pending",
|
|
337
937
|
"fuse",
|
|
338
938
|
"skipped"
|
|
339
939
|
];
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
940
|
+
const DOCTOR_COMMAND = "/evolution doctor";
|
|
941
|
+
function problemKey(problem) {
|
|
942
|
+
switch (problem.code) {
|
|
943
|
+
case "unauthenticated": return "failureUnauthorized";
|
|
944
|
+
case "forbidden": return "failureForbidden";
|
|
945
|
+
case "unmounted": return "failureUnmounted";
|
|
946
|
+
case "capability": return "failureCapability";
|
|
947
|
+
case "body-ambiguous": return "failureBodyAmbiguous";
|
|
948
|
+
case "wire-version": return "failureWireVersion";
|
|
949
|
+
case "body-missing": return "failureBodyMissing";
|
|
950
|
+
case "bad-query": return "failureBadQuery";
|
|
951
|
+
case "refused": return "failureRefused";
|
|
952
|
+
case "server": return "failureServer";
|
|
953
|
+
}
|
|
346
954
|
}
|
|
347
|
-
function
|
|
348
|
-
|
|
349
|
-
const
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
})
|
|
955
|
+
function reasonText(t, reasonCode, fallback) {
|
|
956
|
+
if (reasonCode === void 0) return fallback;
|
|
957
|
+
const key = "history.reason." + reasonCode;
|
|
958
|
+
const text = t(key);
|
|
959
|
+
return text === key ? fallback : text;
|
|
960
|
+
}
|
|
961
|
+
function blockedReasonKey(failure) {
|
|
962
|
+
const code = failure.readiness.code ?? failure.code;
|
|
963
|
+
if (code.endsWith("needs-repair")) return "blocked.reason.needs-repair";
|
|
964
|
+
if (code.endsWith("forward-only")) return "blocked.reason.forward-only";
|
|
965
|
+
if (code.endsWith("migration-blocked")) return "blocked.reason.migration-blocked";
|
|
966
|
+
return "blocked.reason.unknown";
|
|
967
|
+
}
|
|
968
|
+
function failureNode(t, failure, fallback, copy) {
|
|
969
|
+
if (isBlocked(failure)) {
|
|
970
|
+
const raw = failure.readiness.message;
|
|
971
|
+
return (0, react.createElement)("div", {
|
|
972
|
+
"data-role": "blocked",
|
|
973
|
+
role: "alert",
|
|
974
|
+
"data-block-code": failure.code,
|
|
975
|
+
"data-readiness-code": failure.readiness.code ?? ""
|
|
976
|
+
}, (0, react.createElement)("h3", { "data-role": "blocked-title" }, t("blocked.title")), (0, react.createElement)("p", {
|
|
977
|
+
"data-role": "blocked-reason",
|
|
978
|
+
title: raw ?? t(blockedReasonKey(failure))
|
|
979
|
+
}, 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", {
|
|
980
|
+
type: "button",
|
|
981
|
+
"data-role": "doctor",
|
|
982
|
+
onClick: () => {
|
|
983
|
+
copy(DOCTOR_COMMAND);
|
|
984
|
+
}
|
|
985
|
+
}, t("blocked.doctor")), (0, react.createElement)("button", {
|
|
986
|
+
type: "button",
|
|
987
|
+
"data-role": "refresh",
|
|
988
|
+
onClick: () => {
|
|
989
|
+
window.dispatchEvent(new Event("evolution-merge:refresh"));
|
|
990
|
+
}
|
|
991
|
+
}, t("refresh"))));
|
|
992
|
+
}
|
|
993
|
+
const capability = failure.code === "capability";
|
|
994
|
+
return (0, react.createElement)("div", {
|
|
995
|
+
"data-role": capability ? "capability-failure" : "failure",
|
|
996
|
+
"data-error-code": failure.code,
|
|
997
|
+
"data-status": String(failure.status)
|
|
998
|
+
}, (0, react.createElement)("p", {
|
|
999
|
+
"data-role": "failure-title",
|
|
1000
|
+
title: failure.message
|
|
1001
|
+
}, 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", {
|
|
1002
|
+
key: command,
|
|
1003
|
+
type: "button",
|
|
1004
|
+
"data-role": "fallback-command",
|
|
1005
|
+
onClick: () => {
|
|
1006
|
+
copy(command);
|
|
1007
|
+
}
|
|
1008
|
+
}, command))));
|
|
1009
|
+
}
|
|
1010
|
+
function summaryNode(row, t) {
|
|
1011
|
+
if (row.state !== "pending" || row.summary === void 0) return null;
|
|
1012
|
+
return (0, react.createElement)("div", { "data-role": "pending-summary" }, [
|
|
1013
|
+
["row.summaryA", row.summary.a],
|
|
1014
|
+
["row.summaryB", row.summary.b],
|
|
1015
|
+
["row.rationale", row.summary.rationale]
|
|
1016
|
+
].map(([label, value]) => (0, react.createElement)("div", {
|
|
1017
|
+
key: label,
|
|
1018
|
+
"data-role": "pending-summary-slot"
|
|
1019
|
+
}, (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))));
|
|
1020
|
+
}
|
|
1021
|
+
function stageNode(row, t) {
|
|
1022
|
+
const stage = row.stageView;
|
|
1023
|
+
if (stage === void 0) return null;
|
|
1024
|
+
const tone = stage.state === "lost" ? "fail" : stage.state === "expired" || stage.state === "reserved" ? "warn" : "neutral";
|
|
1025
|
+
const expiry = stage.expiresAt === void 0 ? "" : " · " + t("row.expires") + " " + new Date(stage.expiresAt).toLocaleString();
|
|
1026
|
+
return (0, react.createElement)("span", {
|
|
1027
|
+
"data-role": "stage-badge",
|
|
1028
|
+
"data-stage": stage.state,
|
|
1029
|
+
"data-tone": tone
|
|
1030
|
+
}, t("stage.state." + stage.state) + expiry);
|
|
1031
|
+
}
|
|
1032
|
+
function runNode(view, t, copy) {
|
|
1033
|
+
const run = view.latestRun;
|
|
1034
|
+
if (run === void 0) return null;
|
|
1035
|
+
const report = run.actions.find((action) => action.id === "report");
|
|
1036
|
+
const reportEnabled = report?.enabled === true;
|
|
1037
|
+
return (0, react.createElement)("div", {
|
|
1038
|
+
"data-role": "run-strip",
|
|
1039
|
+
"data-run-state": run.state
|
|
1040
|
+
}, (0, react.createElement)("span", {
|
|
1041
|
+
"data-role": "run-id",
|
|
1042
|
+
title: run.id
|
|
1043
|
+
}, t("run.id") + " " + run.id), (0, react.createElement)("span", { "data-role": "run-state" }, t("run.state") + " " + t("run." + run.state)), run.stage === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-stage" }, t("stage." + run.stage)), 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)), run.endedAt === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-ended" }, t("run.endedAt") + " " + new Date(run.endedAt).toLocaleString()), run.failure === void 0 ? null : (0, react.createElement)("span", {
|
|
1044
|
+
"data-role": "run-failure",
|
|
1045
|
+
title: run.failure.detail
|
|
1046
|
+
}, t("run.failure") + " " + run.failure.code), run.currentPairKey === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-current-pair" }, t("run.currentPair") + " " + run.currentPairKey), run.parentRunId === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-parent" }, t("run.parent") + " " + run.parentRunId), run.resultRef === void 0 ? null : (0, react.createElement)("span", {
|
|
1047
|
+
"data-role": "run-result-ref",
|
|
1048
|
+
title: run.resultRef
|
|
1049
|
+
}, t("run.resultRef")), (0, react.createElement)("button", {
|
|
1050
|
+
type: "button",
|
|
1051
|
+
"data-role": "run-report",
|
|
1052
|
+
"data-action": "report",
|
|
1053
|
+
disabled: !reportEnabled,
|
|
1054
|
+
title: reportEnabled ? report?.command ?? t("run.report") : t("run.noReport"),
|
|
1055
|
+
onClick: () => {
|
|
1056
|
+
if (reportEnabled && report !== void 0) copy(report.command);
|
|
1057
|
+
}
|
|
1058
|
+
}, t("run.report")), ...run.actions.filter((action) => action.id !== "report").map((action) => (0, react.createElement)("button", {
|
|
1059
|
+
key: action.id,
|
|
1060
|
+
type: "button",
|
|
1061
|
+
"data-role": "run-action",
|
|
1062
|
+
"data-action": action.id,
|
|
1063
|
+
disabled: !action.enabled,
|
|
1064
|
+
title: action.disabledReason === void 0 ? action.command : t("disabled." + action.disabledReason),
|
|
1065
|
+
onClick: () => {
|
|
1066
|
+
if (action.enabled) copy(action.command);
|
|
1067
|
+
}
|
|
1068
|
+
}, t("action." + action.id))));
|
|
1069
|
+
}
|
|
1070
|
+
function ReadOnlySetting({ section, label, value, disabled, missing, note, link, t }) {
|
|
1071
|
+
const text = missing ? t("settings.capabilityMissing") : disabled ? t("settings.capabilityDisabled") : value === true ? t("settings.on") : t("settings.off");
|
|
1072
|
+
return (0, react.createElement)("div", {
|
|
1073
|
+
"data-role": "settings-section",
|
|
1074
|
+
"data-section": section,
|
|
1075
|
+
"data-disabled": missing || disabled ? "true" : "false"
|
|
1076
|
+
}, (0, react.createElement)("span", { "data-role": "settings-label" }, label), (0, react.createElement)("span", {
|
|
1077
|
+
"data-role": "settings-value",
|
|
1078
|
+
"data-value": missing ? "missing" : disabled ? "unavailable" : value === true ? "on" : "off"
|
|
1079
|
+
}, text), note === void 0 ? null : (0, react.createElement)("span", { "data-role": "settings-note" }, note), link === true ? (0, react.createElement)("a", {
|
|
1080
|
+
"data-role": "settings-link",
|
|
1081
|
+
href: "#/settings",
|
|
1082
|
+
onClick: () => {
|
|
1083
|
+
window.dispatchEvent(new KeyboardEvent("keydown", {
|
|
1084
|
+
key: ",",
|
|
1085
|
+
code: "Comma",
|
|
1086
|
+
ctrlKey: true,
|
|
1087
|
+
altKey: true,
|
|
1088
|
+
bubbles: true
|
|
1089
|
+
}));
|
|
1090
|
+
}
|
|
1091
|
+
}, t("settings.openPlatform")) : null);
|
|
1092
|
+
}
|
|
1093
|
+
function EditableSetting({ form, field, label, fallback, capability, t }) {
|
|
1094
|
+
const subscribe = (0, react.useCallback)((listener) => form.subscribe(listener), [form]);
|
|
1095
|
+
const readSnapshot = (0, react.useCallback)(() => form["getSnapshot"](), [form]);
|
|
1096
|
+
const snapshot = (0, react.useSyncExternalStore)(subscribe, readSnapshot, readSnapshot);
|
|
1097
|
+
const fieldPresent = snapshot.status !== "ready" || snapshot.value === void 0 || Object.prototype.hasOwnProperty.call(snapshot.value, field);
|
|
1098
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
1099
|
+
const [saved, setSaved] = (0, react.useState)(void 0);
|
|
1100
|
+
const value = snapshot.status === "ready" && typeof snapshot.value?.[field] === "boolean" ? snapshot.value[field] : fallback;
|
|
1101
|
+
const disabled = !capability || busy || snapshot.status !== "ready" || !snapshot.writable;
|
|
1102
|
+
const toggle = async () => {
|
|
1103
|
+
if (disabled) return;
|
|
1104
|
+
setBusy(true);
|
|
1105
|
+
setSaved(void 0);
|
|
1106
|
+
const ok = await saveSetting(form, field, !value);
|
|
1107
|
+
setBusy(false);
|
|
1108
|
+
setSaved(ok ? "saved" : "failed");
|
|
378
1109
|
};
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
1110
|
+
if (!fieldPresent) return (0, react.createElement)(ReadOnlySetting, {
|
|
1111
|
+
section: "platform-write",
|
|
1112
|
+
label,
|
|
1113
|
+
value: fallback,
|
|
1114
|
+
disabled: !capability,
|
|
1115
|
+
missing: false,
|
|
1116
|
+
note: t("settings.platformWriteLinkHint"),
|
|
1117
|
+
link: true,
|
|
1118
|
+
t
|
|
1119
|
+
});
|
|
1120
|
+
return (0, react.createElement)("div", {
|
|
1121
|
+
"data-role": "settings-section",
|
|
1122
|
+
"data-section": field === "mergeApproval" ? "merge-approval" : "platform-write",
|
|
1123
|
+
...disabled ? { "data-disabled": "true" } : {}
|
|
1124
|
+
}, (0, react.createElement)("label", { "data-role": "settings-label" }, label), (0, react.createElement)("input", {
|
|
1125
|
+
type: "checkbox",
|
|
1126
|
+
role: "switch",
|
|
1127
|
+
"data-role": "settings-toggle",
|
|
1128
|
+
"data-field": field,
|
|
1129
|
+
"data-value": value ? "on" : "off",
|
|
1130
|
+
checked: value,
|
|
1131
|
+
disabled,
|
|
1132
|
+
onChange: () => {
|
|
1133
|
+
toggle();
|
|
1134
|
+
}
|
|
1135
|
+
}), (0, react.createElement)("span", { "data-role": "settings-value" }, value ? t("settings.on") : t("settings.off")), ...saved === void 0 ? [] : [(0, react.createElement)("span", {
|
|
1136
|
+
"data-role": "settings-save-state",
|
|
1137
|
+
"data-save": saved
|
|
1138
|
+
}, t(saved === "saved" ? "settings.saved" : "settings.saveFailed"))]);
|
|
1139
|
+
}
|
|
1140
|
+
function SettingsCard({ view, settings, t }) {
|
|
1141
|
+
const platform = view.approval.platformWrite;
|
|
1142
|
+
const platformCapability = platform?.capability ?? settings?.platform !== void 0;
|
|
1143
|
+
const platformFallback = platform?.enabled ?? false;
|
|
1144
|
+
const mergeCapability = settings?.merge !== void 0;
|
|
1145
|
+
const mergeFallback = view.approval.mergeApproval;
|
|
1146
|
+
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")), settings?.merge === void 0 ? (0, react.createElement)(ReadOnlySetting, {
|
|
1147
|
+
section: "merge-approval",
|
|
1148
|
+
label: t("settings.mergeApproval"),
|
|
1149
|
+
value: mergeFallback,
|
|
1150
|
+
disabled: false,
|
|
1151
|
+
missing: false,
|
|
1152
|
+
t
|
|
1153
|
+
}) : (0, react.createElement)(EditableSetting, {
|
|
1154
|
+
form: settings.merge,
|
|
1155
|
+
field: "mergeApproval",
|
|
1156
|
+
label: t("settings.mergeApproval"),
|
|
1157
|
+
fallback: mergeFallback,
|
|
1158
|
+
capability: mergeCapability,
|
|
1159
|
+
t
|
|
1160
|
+
}), settings?.platform === void 0 ? (0, react.createElement)(ReadOnlySetting, {
|
|
1161
|
+
section: "platform-write",
|
|
1162
|
+
label: t("settings.platformWrite"),
|
|
1163
|
+
value: platformFallback,
|
|
1164
|
+
disabled: platformCapability === false,
|
|
1165
|
+
missing: platform === void 0,
|
|
1166
|
+
note: t("settings.platformWriteLinkHint"),
|
|
1167
|
+
link: true,
|
|
1168
|
+
t
|
|
1169
|
+
}) : (0, react.createElement)(EditableSetting, {
|
|
1170
|
+
form: settings.platform,
|
|
1171
|
+
field: "enabled",
|
|
1172
|
+
label: t("settings.platformWrite"),
|
|
1173
|
+
fallback: platformFallback,
|
|
1174
|
+
capability: platformCapability,
|
|
1175
|
+
t
|
|
1176
|
+
}), settings?.merge === void 0 || settings?.platform === void 0 ? (0, react.createElement)("a", {
|
|
1177
|
+
"data-role": "settings-link",
|
|
1178
|
+
href: "#/settings"
|
|
1179
|
+
}, t("settings.openPlatform")) : null, (0, react.createElement)("p", { "data-role": "settings-readonly" }, settings?.merge === void 0 || settings?.platform === void 0 ? t("settings.readonly") : t("settings.live")));
|
|
1180
|
+
}
|
|
1181
|
+
function rowNode(row, store, t, copy, sort) {
|
|
1182
|
+
const facts = [
|
|
1183
|
+
row.target === void 0 ? void 0 : t("row.target") + " " + row.target,
|
|
1184
|
+
row.targetActual === void 0 ? void 0 : t("row.actualTarget") + " " + row.targetActual,
|
|
1185
|
+
row.verifySubState === void 0 ? void 0 : t("row.verify") + " " + t("verify." + row.verifySubState),
|
|
1186
|
+
row.origin === void 0 ? void 0 : t("row.origin") + " " + t("origin." + row.origin),
|
|
1187
|
+
row.attempts === void 0 ? void 0 : t("row.attempts") + " " + String(row.attempts),
|
|
1188
|
+
row.confidence === void 0 ? void 0 : t("row.confidence") + " " + row.confidence.toFixed(2),
|
|
1189
|
+
row.failure === void 0 ? void 0 : t("row.failure") + " " + row.failure.code + (row.failure.retryable ? "" : " · " + t("row.noRetry")),
|
|
1190
|
+
row.expired === void 0 ? void 0 : t("row.expired") + " " + t("expired." + row.expired),
|
|
1191
|
+
row.reasonCode === void 0 && row.reason === void 0 ? void 0 : t("row.reason") + " " + reasonText(t, row.reasonCode, row.reason ?? "")
|
|
1192
|
+
].filter((value) => value !== void 0).join(" · ");
|
|
1193
|
+
const actions = row.actions.map((action) => (0, react.createElement)("button", {
|
|
1194
|
+
key: action.id,
|
|
1195
|
+
type: "button",
|
|
1196
|
+
"data-role": "row-action",
|
|
1197
|
+
"data-action": action.id,
|
|
1198
|
+
...action.disabledReason === void 0 ? {} : { "data-disabled-reason": action.disabledReason },
|
|
1199
|
+
title: action.disabledReason === void 0 ? action.command : t("disabled." + action.disabledReason),
|
|
1200
|
+
disabled: !action.enabled,
|
|
1201
|
+
onClick: () => {
|
|
1202
|
+
if (!action.enabled) return;
|
|
1203
|
+
if (action.confirm && globalThis.confirm !== void 0 && !globalThis.confirm(t("action.confirm") + " " + (t("action." + action.id) || action.id))) return;
|
|
1204
|
+
copy(action.command);
|
|
1205
|
+
}
|
|
1206
|
+
}, t("action." + action.id)));
|
|
1207
|
+
return (0, react.createElement)("div", {
|
|
1208
|
+
key: row.id,
|
|
1209
|
+
"data-role": "row",
|
|
1210
|
+
"data-row-id": row.id,
|
|
1211
|
+
"data-row-state": row.state,
|
|
1212
|
+
"data-row-queue": row.queue,
|
|
1213
|
+
draggable: true,
|
|
1214
|
+
title: t("sort.drag"),
|
|
1215
|
+
onDragStart: (event) => {
|
|
1216
|
+
if (event.dataTransfer != null) {
|
|
1217
|
+
event.dataTransfer.setData("text/plain", row.id);
|
|
1218
|
+
event.dataTransfer.effectAllowed = "move";
|
|
386
1219
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
1220
|
+
sort.start(row.id);
|
|
1221
|
+
},
|
|
1222
|
+
onDragOver: (event) => {
|
|
1223
|
+
event.preventDefault();
|
|
1224
|
+
if (event.dataTransfer != null) event.dataTransfer.dropEffect = "move";
|
|
1225
|
+
sort.over(event);
|
|
1226
|
+
},
|
|
1227
|
+
onDrop: (event) => {
|
|
1228
|
+
event.preventDefault();
|
|
1229
|
+
sort.drop(row.id);
|
|
1230
|
+
},
|
|
1231
|
+
onDragEnd: () => {
|
|
1232
|
+
sort.end();
|
|
1233
|
+
},
|
|
1234
|
+
onContextMenu: (event) => {
|
|
1235
|
+
event.preventDefault();
|
|
1236
|
+
sort.menu(row.id, event.clientX, event.clientY);
|
|
1237
|
+
}
|
|
1238
|
+
}, (0, react.createElement)("div", null, (0, react.createElement)("div", { "data-role": "row-label" }, row.label), (0, react.createElement)("div", {
|
|
1239
|
+
"data-role": "row-id",
|
|
1240
|
+
title: row.id
|
|
1241
|
+
}, t("row.id") + " " + row.id), (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), facts === "" ? null : (0, react.createElement)("div", { "data-role": "row-facts" }, facts)), (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" }, (() => {
|
|
1242
|
+
const bodyA = row.bodies?.find((body) => body.name === row.a);
|
|
1243
|
+
const bodyB = row.bodies?.find((body) => body.name === row.b);
|
|
1244
|
+
return [bodyA === void 0 ? null : (0, react.createElement)("button", {
|
|
1245
|
+
key: "a",
|
|
1246
|
+
type: "button",
|
|
1247
|
+
"data-role": "body-a",
|
|
1248
|
+
onClick: () => {
|
|
1249
|
+
store.openBody(bodyA.name, bodyA.side);
|
|
393
1250
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
1251
|
+
}, "A"), bodyB === void 0 ? null : (0, react.createElement)("button", {
|
|
1252
|
+
key: "b",
|
|
1253
|
+
type: "button",
|
|
1254
|
+
"data-role": "body-b",
|
|
1255
|
+
onClick: () => {
|
|
1256
|
+
store.openBody(bodyB.name, bodyB.side);
|
|
1257
|
+
}
|
|
1258
|
+
}, "B")];
|
|
1259
|
+
})(), actions)));
|
|
1260
|
+
}
|
|
1261
|
+
function bodyNode(overlay, t, onClose) {
|
|
1262
|
+
return (0, react.createElement)("section", {
|
|
1263
|
+
"data-role": "overlay",
|
|
1264
|
+
"data-overlay": "body",
|
|
1265
|
+
role: "dialog",
|
|
1266
|
+
"aria-modal": "true",
|
|
1267
|
+
"aria-label": t("overlay.body")
|
|
1268
|
+
}, (0, react.createElement)("div", { "data-role": "overlay-head" }, (0, react.createElement)("h3", { "data-role": "overlay-title" }, t("overlay.body") + " · " + overlay.name), (0, react.createElement)("button", {
|
|
1269
|
+
type: "button",
|
|
1270
|
+
"data-role": "overlay-close",
|
|
1271
|
+
onClick: onClose
|
|
1272
|
+
}, 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);
|
|
1273
|
+
}
|
|
1274
|
+
function historyNode(overlay, t, onClose) {
|
|
1275
|
+
return (0, react.createElement)("section", {
|
|
1276
|
+
"data-role": "overlay",
|
|
1277
|
+
"data-overlay": "history",
|
|
1278
|
+
role: "dialog",
|
|
1279
|
+
"aria-modal": "true",
|
|
1280
|
+
"aria-label": t("history")
|
|
1281
|
+
}, (0, react.createElement)("div", { "data-role": "overlay-head" }, (0, react.createElement)("h3", { "data-role": "overlay-title" }, t("history")), (0, react.createElement)("button", {
|
|
1282
|
+
type: "button",
|
|
1283
|
+
"data-role": "overlay-close",
|
|
1284
|
+
onClick: onClose
|
|
1285
|
+
}, 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", {
|
|
1286
|
+
key: item.name + ":" + item.archivedAt,
|
|
1287
|
+
"data-role": "history-item"
|
|
1288
|
+
}, item.name + " · " + (() => {
|
|
1289
|
+
const kind = t("history.kind." + item.kind);
|
|
1290
|
+
const reason = reasonText(t, item.reasonCode, item.reason);
|
|
1291
|
+
return kind === reason ? kind : kind + " · " + reason;
|
|
1292
|
+
})() + " · v" + String(item.lastVersion)))) : null);
|
|
1293
|
+
}
|
|
1294
|
+
function MergePanel(face) {
|
|
1295
|
+
const { store, t } = face;
|
|
1296
|
+
const snapshot = (0, react.useSyncExternalStore)(store.subscribe, store.read, store.read);
|
|
1297
|
+
const [copied, setCopied] = (0, react.useState)(void 0);
|
|
1298
|
+
const [orders, setOrders] = (0, react.useState)({});
|
|
1299
|
+
const [dragId, setDragId] = (0, react.useState)(void 0);
|
|
1300
|
+
const [menu, setMenu] = (0, react.useState)(void 0);
|
|
1301
|
+
const workspaceId = resolveWorkspaceId(face.workspaceId);
|
|
1302
|
+
const orderStore = (0, react.useMemo)(() => createRowOrderStore(), []);
|
|
1303
|
+
const copy = (command) => {
|
|
1304
|
+
navigator.clipboard.writeText(command);
|
|
1305
|
+
setCopied(command);
|
|
401
1306
|
};
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
1307
|
+
const doctorCommand = face.doctorCommand ?? DOCTOR_COMMAND;
|
|
1308
|
+
(0, react.useEffect)(() => {
|
|
1309
|
+
store.start();
|
|
1310
|
+
return () => {
|
|
1311
|
+
store.dispose();
|
|
1312
|
+
};
|
|
1313
|
+
}, [store]);
|
|
1314
|
+
(0, react.useEffect)(() => {
|
|
1315
|
+
const onFocus = () => {
|
|
1316
|
+
store.refresh();
|
|
1317
|
+
};
|
|
1318
|
+
const onVisibility = () => {
|
|
1319
|
+
if (document.visibilityState === "visible") store.refresh();
|
|
1320
|
+
};
|
|
1321
|
+
const onRefresh = () => {
|
|
1322
|
+
store.refresh();
|
|
1323
|
+
};
|
|
1324
|
+
window.addEventListener("focus", onFocus);
|
|
1325
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
1326
|
+
window.addEventListener("evolution-merge:refresh", onRefresh);
|
|
1327
|
+
return () => {
|
|
1328
|
+
window.removeEventListener("focus", onFocus);
|
|
1329
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
1330
|
+
window.removeEventListener("evolution-merge:refresh", onRefresh);
|
|
1331
|
+
};
|
|
1332
|
+
}, [store]);
|
|
1333
|
+
const view = snapshot.view;
|
|
1334
|
+
const fallback = [...new Set([...view.commands, ...FALLBACK_COMMANDS])];
|
|
1335
|
+
const blocked = snapshot.viewState === "blocked" && snapshot.viewFailure !== void 0 ? snapshot.viewFailure : void 0;
|
|
1336
|
+
const viewFailure = snapshot.viewState === "error" ? snapshot.viewFailure : void 0;
|
|
1337
|
+
const queue = snapshot.current;
|
|
1338
|
+
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";
|
|
1339
|
+
const orderKey = rowOrderKey(workspaceId, snapshot.queue);
|
|
1340
|
+
const visibleOrder = orders[orderKey] ?? orderStore.read(workspaceId, snapshot.queue);
|
|
1341
|
+
const visibleRows = orderRows(queue.rows, visibleOrder);
|
|
1342
|
+
const saveOrder = (ids) => {
|
|
1343
|
+
setOrders((previous) => ({
|
|
1344
|
+
...previous,
|
|
1345
|
+
[orderKey]: ids
|
|
1346
|
+
}));
|
|
1347
|
+
orderStore.write(workspaceId, snapshot.queue, ids);
|
|
418
1348
|
};
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
1349
|
+
const sortHandlers = {
|
|
1350
|
+
start: (id) => {
|
|
1351
|
+
setDragId(id);
|
|
1352
|
+
},
|
|
1353
|
+
over: () => {},
|
|
1354
|
+
end: () => {
|
|
1355
|
+
setDragId(void 0);
|
|
1356
|
+
},
|
|
1357
|
+
drop: (targetId) => {
|
|
1358
|
+
const fromId = dragId;
|
|
1359
|
+
setDragId(void 0);
|
|
1360
|
+
if (fromId === void 0 || fromId === targetId) return;
|
|
1361
|
+
saveOrder(moveRow(visibleRows.map((row) => row.id), fromId, targetId));
|
|
1362
|
+
},
|
|
1363
|
+
menu: (id, x, y) => {
|
|
1364
|
+
setMenu({
|
|
1365
|
+
id,
|
|
1366
|
+
x,
|
|
1367
|
+
y
|
|
432
1368
|
});
|
|
433
|
-
}
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
const pinMenu = (edge) => {
|
|
1372
|
+
if (menu === void 0) return;
|
|
1373
|
+
saveOrder(pinRow(visibleRows.map((row) => row.id), menu.id, edge));
|
|
1374
|
+
setMenu(void 0);
|
|
434
1375
|
};
|
|
435
|
-
(0, react.useEffect)(() => {
|
|
436
|
-
loadView();
|
|
437
|
-
loadRows("pending");
|
|
438
|
-
}, [face]);
|
|
439
|
-
(0, react.useEffect)(() => {
|
|
440
|
-
setNextCursor(void 0);
|
|
441
|
-
loadRows(tab, 0);
|
|
442
|
-
}, [tab]);
|
|
443
|
-
const counts = view.counts;
|
|
444
|
-
const stats = (0, react.createElement)("div", { "data-role": "stats" }, QUEUES.map((queue) => (0, react.createElement)("div", {
|
|
445
|
-
key: queue,
|
|
446
|
-
"data-role": "stat",
|
|
447
|
-
"data-queue": queue
|
|
448
|
-
}, (0, react.createElement)("div", { "data-role": "stat-value" }, String(counts[queue])), (0, react.createElement)("div", { "data-role": "stat-label" }, t("tab." + queue)))));
|
|
449
|
-
const latest = view.latestRun;
|
|
450
|
-
const runStrip = latest === void 0 ? null : (0, react.createElement)("div", { "data-role": "run-strip" }, (0, react.createElement)("span", { "data-role": "run-id" }, latest.id), (0, react.createElement)("span", { "data-role": "run-state" }, latest.state), latest.stage === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-stage" }, t("stage." + latest.stage)), latest.progress === void 0 ? null : (0, react.createElement)("span", { "data-role": "run-progress" }, String(latest.progress.done) + "/" + String(latest.progress.total)));
|
|
451
1376
|
const tabs = (0, react.createElement)("div", {
|
|
452
1377
|
"data-role": "tabs",
|
|
453
1378
|
role: "tablist"
|
|
454
|
-
}, QUEUES.map((
|
|
455
|
-
key:
|
|
1379
|
+
}, QUEUES.map((item) => (0, react.createElement)("button", {
|
|
1380
|
+
key: item,
|
|
456
1381
|
type: "button",
|
|
457
1382
|
role: "tab",
|
|
458
|
-
"aria-selected":
|
|
1383
|
+
"aria-selected": snapshot.queue === item ? "true" : "false",
|
|
459
1384
|
"data-role": "tab",
|
|
460
|
-
"data-active":
|
|
1385
|
+
"data-active": snapshot.queue === item ? "true" : "false",
|
|
461
1386
|
onClick: () => {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
1387
|
+
setMenu(void 0);
|
|
1388
|
+
store.select(item);
|
|
1389
|
+
}
|
|
1390
|
+
}, t("tab." + item) + " " + String(view.counts[item]))));
|
|
1391
|
+
const expiredToggle = snapshot.queue === "pending" ? (0, react.createElement)("button", {
|
|
1392
|
+
type: "button",
|
|
1393
|
+
role: "switch",
|
|
1394
|
+
"aria-checked": snapshot.expiredOnly ? "true" : "false",
|
|
1395
|
+
"data-role": "expired-toggle",
|
|
1396
|
+
"data-active": snapshot.expiredOnly ? "true" : "false",
|
|
1397
|
+
onClick: () => {
|
|
1398
|
+
store.toggleExpired();
|
|
1399
|
+
}
|
|
1400
|
+
}, t("tab.expired") + " " + String(view.expired)) : null;
|
|
1401
|
+
const list = uiState === "ready" && queue.status === "ready" ? (0, react.createElement)("div", { "data-role": "rows" }, visibleRows.map((row) => rowNode(row, store, t, copy, sortHandlers))) : null;
|
|
1402
|
+
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;
|
|
1403
|
+
const activeFailure = viewFailure !== void 0 ? viewFailure : queue.status === "error" ? queue.failure : void 0;
|
|
1404
|
+
const overlay = snapshot.overlay;
|
|
1405
|
+
const menuNode = menu === void 0 ? null : (0, react.createElement)("div", {
|
|
1406
|
+
"data-role": "sort-menu",
|
|
1407
|
+
role: "menu",
|
|
1408
|
+
"aria-label": t("sort.menu"),
|
|
1409
|
+
style: {
|
|
1410
|
+
left: String(Math.min(menu.x, Math.max(0, (globalThis.innerWidth || 1440) - 180))) + "px",
|
|
1411
|
+
top: String(Math.min(menu.y, Math.max(0, (globalThis.innerHeight || 800) - 110))) + "px"
|
|
1412
|
+
}
|
|
1413
|
+
}, (0, react.createElement)("button", {
|
|
1414
|
+
type: "button",
|
|
1415
|
+
role: "menuitem",
|
|
1416
|
+
"data-role": "sort-pin-top",
|
|
1417
|
+
onClick: () => {
|
|
1418
|
+
pinMenu("top");
|
|
1419
|
+
}
|
|
1420
|
+
}, t("sort.pinTop")), (0, react.createElement)("button", {
|
|
1421
|
+
type: "button",
|
|
1422
|
+
role: "menuitem",
|
|
1423
|
+
"data-role": "sort-pin-bottom",
|
|
1424
|
+
onClick: () => {
|
|
1425
|
+
pinMenu("bottom");
|
|
1426
|
+
}
|
|
1427
|
+
}, t("sort.pinBottom")), (0, react.createElement)("button", {
|
|
1428
|
+
type: "button",
|
|
1429
|
+
role: "menuitem",
|
|
1430
|
+
"data-role": "sort-cancel",
|
|
1431
|
+
onClick: () => {
|
|
1432
|
+
setMenu(void 0);
|
|
1433
|
+
}
|
|
1434
|
+
}, t("sort.cancel")));
|
|
502
1435
|
return (0, react.createElement)("section", {
|
|
503
1436
|
className: CSS_TAG_ID,
|
|
504
|
-
"data-state":
|
|
505
|
-
}, (0, react.createElement)("
|
|
1437
|
+
"data-state": uiState
|
|
1438
|
+
}, (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)("div", { "data-role": "start" }, (0, react.createElement)("button", {
|
|
1439
|
+
type: "button",
|
|
1440
|
+
"data-role": "start-scan",
|
|
1441
|
+
onClick: () => {
|
|
1442
|
+
copy(view.startCommands.scan);
|
|
1443
|
+
}
|
|
1444
|
+
}, t("start.scan")), (0, react.createElement)("button", {
|
|
1445
|
+
type: "button",
|
|
1446
|
+
"data-role": "start-pair",
|
|
1447
|
+
onClick: () => {
|
|
1448
|
+
copy(view.startCommands.pair);
|
|
1449
|
+
}
|
|
1450
|
+
}, t("start.pair"))), view.degraded ? (0, react.createElement)("p", { "data-role": "degraded" }, t("degraded") + " " + view.notes.join(",")) : null, (0, react.createElement)(SettingsCard, {
|
|
1451
|
+
view,
|
|
1452
|
+
settings: face.settings,
|
|
1453
|
+
t
|
|
1454
|
+
}), runNode(view, t, copy), tabs, expiredToggle, snapshot.viewState === "loading" || queue.status === "loading" ? (0, react.createElement)("p", { "data-role": "note" }, t("loading")) : null, activeFailure === void 0 ? null : failureNode(t, activeFailure, fallback, copy), copied === void 0 ? null : (0, react.createElement)("p", {
|
|
1455
|
+
"data-role": "copied",
|
|
1456
|
+
role: "status"
|
|
1457
|
+
}, t("copied") + " " + copied), list, empty, queue.nextCursor === void 0 || uiState !== "ready" ? null : (0, react.createElement)("button", {
|
|
506
1458
|
type: "button",
|
|
507
1459
|
"data-role": "load-more",
|
|
1460
|
+
disabled: queue.status === "loading",
|
|
508
1461
|
onClick: () => {
|
|
509
|
-
|
|
1462
|
+
store.loadMore();
|
|
510
1463
|
}
|
|
511
|
-
}, t("loadMore")),
|
|
1464
|
+
}, t("loadMore")), (0, react.createElement)("button", {
|
|
512
1465
|
type: "button",
|
|
513
1466
|
"data-role": "history",
|
|
514
|
-
onClick:
|
|
515
|
-
|
|
1467
|
+
onClick: () => {
|
|
1468
|
+
store.openHistory();
|
|
1469
|
+
}
|
|
1470
|
+
}, t("history")), (0, react.createElement)("button", {
|
|
516
1471
|
type: "button",
|
|
517
|
-
"data-role": "
|
|
1472
|
+
"data-role": "doctor",
|
|
518
1473
|
onClick: () => {
|
|
519
|
-
|
|
1474
|
+
copy(doctorCommand);
|
|
520
1475
|
}
|
|
521
|
-
}, t("
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
})
|
|
1476
|
+
}, t("doctor.open")), overlay === void 0 ? null : overlay.kind === "body" ? bodyNode(overlay, t, () => {
|
|
1477
|
+
store.closeOverlay();
|
|
1478
|
+
}) : historyNode(overlay, t, () => {
|
|
1479
|
+
store.closeOverlay();
|
|
1480
|
+
}), (0, react.createElement)("button", {
|
|
526
1481
|
type: "button",
|
|
527
1482
|
"data-role": "refresh",
|
|
528
1483
|
onClick: () => {
|
|
529
|
-
|
|
530
|
-
loadRows(tab, 0);
|
|
1484
|
+
store.refresh();
|
|
531
1485
|
}
|
|
532
|
-
}, t("refresh")));
|
|
1486
|
+
}, t("refresh")), menuNode));
|
|
533
1487
|
}
|
|
534
1488
|
//#endregion
|
|
1489
|
+
//#region src/client/MergeStore.ts
|
|
1490
|
+
const emptyView = () => ({
|
|
1491
|
+
counts: {
|
|
1492
|
+
verify: 0,
|
|
1493
|
+
pending: 0,
|
|
1494
|
+
fuse: 0,
|
|
1495
|
+
skipped: 0
|
|
1496
|
+
},
|
|
1497
|
+
expired: 0,
|
|
1498
|
+
tabs: [
|
|
1499
|
+
{
|
|
1500
|
+
queue: "verify",
|
|
1501
|
+
count: 0
|
|
1502
|
+
},
|
|
1503
|
+
{
|
|
1504
|
+
queue: "pending",
|
|
1505
|
+
count: 0
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
queue: "fuse",
|
|
1509
|
+
count: 0
|
|
1510
|
+
},
|
|
1511
|
+
{
|
|
1512
|
+
queue: "skipped",
|
|
1513
|
+
count: 0
|
|
1514
|
+
}
|
|
1515
|
+
],
|
|
1516
|
+
commands: [],
|
|
1517
|
+
startCommands: {
|
|
1518
|
+
scan: "/evolution merge scan",
|
|
1519
|
+
pair: "/evolution merge pair <a> <b>"
|
|
1520
|
+
},
|
|
1521
|
+
notes: [],
|
|
1522
|
+
degraded: false,
|
|
1523
|
+
approval: { mergeApproval: false }
|
|
1524
|
+
});
|
|
1525
|
+
const keyOf = (queue, expiredOnly) => queue + ":" + (expiredOnly ? "1" : "0");
|
|
1526
|
+
const loadingQueue = () => ({
|
|
1527
|
+
status: "loading",
|
|
1528
|
+
rows: []
|
|
1529
|
+
});
|
|
1530
|
+
var MergeStore = class {
|
|
1531
|
+
source;
|
|
1532
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1533
|
+
cache = /* @__PURE__ */ new Map();
|
|
1534
|
+
tokens = /* @__PURE__ */ new Map();
|
|
1535
|
+
viewToken = 0;
|
|
1536
|
+
overlayToken = 0;
|
|
1537
|
+
snapshot;
|
|
1538
|
+
started = false;
|
|
1539
|
+
disposed = false;
|
|
1540
|
+
constructor(source, initial = {}) {
|
|
1541
|
+
this.source = source;
|
|
1542
|
+
const queue = initial.queue ?? "pending";
|
|
1543
|
+
const expiredOnly = queue === "pending" ? initial.expiredOnly ?? false : false;
|
|
1544
|
+
const initialRows = initial.rows;
|
|
1545
|
+
const current = initialRows === void 0 ? loadingQueue() : {
|
|
1546
|
+
status: initialRows.length === 0 ? "empty" : "ready",
|
|
1547
|
+
rows: initialRows
|
|
1548
|
+
};
|
|
1549
|
+
if (initialRows !== void 0) this.cache.set(keyOf(queue, expiredOnly), current);
|
|
1550
|
+
this.snapshot = {
|
|
1551
|
+
view: initial.view ?? emptyView(),
|
|
1552
|
+
viewState: initial.view === void 0 ? "loading" : "ready",
|
|
1553
|
+
queue,
|
|
1554
|
+
expiredOnly,
|
|
1555
|
+
current
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
read = () => this.snapshot;
|
|
1559
|
+
subscribe = (listener) => {
|
|
1560
|
+
this.listeners.add(listener);
|
|
1561
|
+
return () => {
|
|
1562
|
+
this.listeners.delete(listener);
|
|
1563
|
+
};
|
|
1564
|
+
};
|
|
1565
|
+
emit() {
|
|
1566
|
+
if (this.disposed) return;
|
|
1567
|
+
for (const listener of this.listeners) listener();
|
|
1568
|
+
}
|
|
1569
|
+
set(next) {
|
|
1570
|
+
this.snapshot = next;
|
|
1571
|
+
this.emit();
|
|
1572
|
+
}
|
|
1573
|
+
isCurrent(queue, expiredOnly) {
|
|
1574
|
+
return this.snapshot.queue === queue && this.snapshot.expiredOnly === expiredOnly;
|
|
1575
|
+
}
|
|
1576
|
+
start() {
|
|
1577
|
+
if (this.started || this.disposed) return;
|
|
1578
|
+
this.started = true;
|
|
1579
|
+
this.loadView();
|
|
1580
|
+
this.loadQueue(this.snapshot.queue, this.snapshot.expiredOnly);
|
|
1581
|
+
}
|
|
1582
|
+
async loadView(showLoading = true) {
|
|
1583
|
+
const token = ++this.viewToken;
|
|
1584
|
+
if (showLoading) this.set({
|
|
1585
|
+
...this.snapshot,
|
|
1586
|
+
viewState: "loading",
|
|
1587
|
+
viewFailure: void 0
|
|
1588
|
+
});
|
|
1589
|
+
const outcome = await this.source.view();
|
|
1590
|
+
if (this.disposed || token !== this.viewToken) return;
|
|
1591
|
+
if (!outcome.ok) {
|
|
1592
|
+
if (outcome.failure.kind === "blocked") {
|
|
1593
|
+
this.set({
|
|
1594
|
+
...this.snapshot,
|
|
1595
|
+
viewState: "blocked",
|
|
1596
|
+
viewFailure: outcome.failure,
|
|
1597
|
+
current: {
|
|
1598
|
+
status: "idle",
|
|
1599
|
+
rows: []
|
|
1600
|
+
}
|
|
1601
|
+
});
|
|
1602
|
+
for (const key of this.cache.keys()) this.cache.set(key, {
|
|
1603
|
+
status: "idle",
|
|
1604
|
+
rows: []
|
|
1605
|
+
});
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1608
|
+
this.set({
|
|
1609
|
+
...this.snapshot,
|
|
1610
|
+
viewState: "error",
|
|
1611
|
+
viewFailure: outcome.failure
|
|
1612
|
+
});
|
|
1613
|
+
return;
|
|
1614
|
+
}
|
|
1615
|
+
this.set({
|
|
1616
|
+
...this.snapshot,
|
|
1617
|
+
view: outcome.payload,
|
|
1618
|
+
viewState: "ready",
|
|
1619
|
+
viewFailure: void 0
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1622
|
+
async loadQueue(queue, expiredOnly, cursor) {
|
|
1623
|
+
const key = keyOf(queue, expiredOnly);
|
|
1624
|
+
const token = (this.tokens.get(key) ?? 0) + 1;
|
|
1625
|
+
this.tokens.set(key, token);
|
|
1626
|
+
const previous = this.cache.get(key);
|
|
1627
|
+
const next = cursor === void 0 ? {
|
|
1628
|
+
status: "loading",
|
|
1629
|
+
rows: []
|
|
1630
|
+
} : {
|
|
1631
|
+
status: "loading",
|
|
1632
|
+
rows: previous?.rows ?? [],
|
|
1633
|
+
...previous?.nextCursor === void 0 ? {} : { nextCursor: previous.nextCursor }
|
|
1634
|
+
};
|
|
1635
|
+
this.cache.set(key, next);
|
|
1636
|
+
if (this.isCurrent(queue, expiredOnly)) this.set({
|
|
1637
|
+
...this.snapshot,
|
|
1638
|
+
current: next
|
|
1639
|
+
});
|
|
1640
|
+
const outcome = await this.source.rows(queue, cursor, queue === "pending" && expiredOnly);
|
|
1641
|
+
if (this.disposed || token !== this.tokens.get(key)) return;
|
|
1642
|
+
if (!outcome.ok) {
|
|
1643
|
+
if (outcome.failure.kind === "blocked") {
|
|
1644
|
+
this.set({
|
|
1645
|
+
...this.snapshot,
|
|
1646
|
+
viewState: "blocked",
|
|
1647
|
+
viewFailure: outcome.failure,
|
|
1648
|
+
current: {
|
|
1649
|
+
status: "idle",
|
|
1650
|
+
rows: []
|
|
1651
|
+
}
|
|
1652
|
+
});
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
const failed = {
|
|
1656
|
+
status: "error",
|
|
1657
|
+
rows: [],
|
|
1658
|
+
failure: outcome.failure
|
|
1659
|
+
};
|
|
1660
|
+
this.cache.set(key, failed);
|
|
1661
|
+
if (this.isCurrent(queue, expiredOnly)) this.set({
|
|
1662
|
+
...this.snapshot,
|
|
1663
|
+
current: failed
|
|
1664
|
+
});
|
|
1665
|
+
return;
|
|
1666
|
+
}
|
|
1667
|
+
const items = cursor === void 0 ? outcome.payload.items : [...previous?.rows ?? [], ...outcome.payload.items];
|
|
1668
|
+
const ready = {
|
|
1669
|
+
status: items.length === 0 ? "empty" : "ready",
|
|
1670
|
+
rows: items,
|
|
1671
|
+
...outcome.payload.nextCursor === void 0 ? {} : { nextCursor: outcome.payload.nextCursor }
|
|
1672
|
+
};
|
|
1673
|
+
this.cache.set(key, ready);
|
|
1674
|
+
if (this.isCurrent(queue, expiredOnly)) this.set({
|
|
1675
|
+
...this.snapshot,
|
|
1676
|
+
current: ready,
|
|
1677
|
+
expiredOnly,
|
|
1678
|
+
queue
|
|
1679
|
+
});
|
|
1680
|
+
}
|
|
1681
|
+
select(queue) {
|
|
1682
|
+
const expiredOnly = queue === "pending" ? this.snapshot.expiredOnly : false;
|
|
1683
|
+
if (queue === this.snapshot.queue && expiredOnly === this.snapshot.expiredOnly) return;
|
|
1684
|
+
const key = keyOf(queue, expiredOnly);
|
|
1685
|
+
const cached = this.cache.get(key);
|
|
1686
|
+
const current = cached ?? loadingQueue();
|
|
1687
|
+
this.set({
|
|
1688
|
+
...this.snapshot,
|
|
1689
|
+
queue,
|
|
1690
|
+
expiredOnly,
|
|
1691
|
+
current,
|
|
1692
|
+
overlay: void 0
|
|
1693
|
+
});
|
|
1694
|
+
if (cached === void 0) this.loadQueue(queue, expiredOnly);
|
|
1695
|
+
}
|
|
1696
|
+
toggleExpired() {
|
|
1697
|
+
if (this.snapshot.queue !== "pending") return;
|
|
1698
|
+
const expiredOnly = !this.snapshot.expiredOnly;
|
|
1699
|
+
const key = keyOf("pending", expiredOnly);
|
|
1700
|
+
const cached = this.cache.get(key);
|
|
1701
|
+
const current = cached ?? loadingQueue();
|
|
1702
|
+
this.set({
|
|
1703
|
+
...this.snapshot,
|
|
1704
|
+
expiredOnly,
|
|
1705
|
+
current,
|
|
1706
|
+
overlay: void 0
|
|
1707
|
+
});
|
|
1708
|
+
if (cached === void 0) this.loadQueue("pending", expiredOnly);
|
|
1709
|
+
}
|
|
1710
|
+
refresh() {
|
|
1711
|
+
if (this.disposed) return;
|
|
1712
|
+
this.loadView(true);
|
|
1713
|
+
this.loadQueue(this.snapshot.queue, this.snapshot.expiredOnly);
|
|
1714
|
+
}
|
|
1715
|
+
loadMore() {
|
|
1716
|
+
const current = this.snapshot.current;
|
|
1717
|
+
if (current.nextCursor === void 0 || current.status === "loading" || this.snapshot.viewState === "blocked") return;
|
|
1718
|
+
this.loadQueue(this.snapshot.queue, this.snapshot.expiredOnly, current.nextCursor);
|
|
1719
|
+
}
|
|
1720
|
+
async openBody(name, side) {
|
|
1721
|
+
const token = ++this.overlayToken;
|
|
1722
|
+
this.set({
|
|
1723
|
+
...this.snapshot,
|
|
1724
|
+
overlay: {
|
|
1725
|
+
kind: "body",
|
|
1726
|
+
name,
|
|
1727
|
+
side,
|
|
1728
|
+
status: "loading"
|
|
1729
|
+
}
|
|
1730
|
+
});
|
|
1731
|
+
const outcome = await this.source.body(name, side);
|
|
1732
|
+
if (this.disposed || token !== this.overlayToken) return;
|
|
1733
|
+
if (!outcome.ok) {
|
|
1734
|
+
if (outcome.failure.kind === "blocked") {
|
|
1735
|
+
this.set({
|
|
1736
|
+
...this.snapshot,
|
|
1737
|
+
viewState: "blocked",
|
|
1738
|
+
viewFailure: outcome.failure,
|
|
1739
|
+
overlay: void 0
|
|
1740
|
+
});
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
this.set({
|
|
1744
|
+
...this.snapshot,
|
|
1745
|
+
overlay: {
|
|
1746
|
+
kind: "body",
|
|
1747
|
+
name,
|
|
1748
|
+
side,
|
|
1749
|
+
status: "error",
|
|
1750
|
+
failure: outcome.failure
|
|
1751
|
+
}
|
|
1752
|
+
});
|
|
1753
|
+
return;
|
|
1754
|
+
}
|
|
1755
|
+
this.set({
|
|
1756
|
+
...this.snapshot,
|
|
1757
|
+
overlay: {
|
|
1758
|
+
kind: "body",
|
|
1759
|
+
name,
|
|
1760
|
+
side,
|
|
1761
|
+
status: "ready",
|
|
1762
|
+
body: outcome.payload
|
|
1763
|
+
}
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1766
|
+
async openHistory() {
|
|
1767
|
+
const token = ++this.overlayToken;
|
|
1768
|
+
this.set({
|
|
1769
|
+
...this.snapshot,
|
|
1770
|
+
overlay: {
|
|
1771
|
+
kind: "history",
|
|
1772
|
+
status: "loading"
|
|
1773
|
+
}
|
|
1774
|
+
});
|
|
1775
|
+
const outcome = await this.source.history();
|
|
1776
|
+
if (this.disposed || token !== this.overlayToken) return;
|
|
1777
|
+
if (!outcome.ok) {
|
|
1778
|
+
if (outcome.failure.kind === "blocked") {
|
|
1779
|
+
this.set({
|
|
1780
|
+
...this.snapshot,
|
|
1781
|
+
viewState: "blocked",
|
|
1782
|
+
viewFailure: outcome.failure,
|
|
1783
|
+
overlay: void 0
|
|
1784
|
+
});
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1787
|
+
this.set({
|
|
1788
|
+
...this.snapshot,
|
|
1789
|
+
overlay: {
|
|
1790
|
+
kind: "history",
|
|
1791
|
+
status: "error",
|
|
1792
|
+
failure: outcome.failure
|
|
1793
|
+
}
|
|
1794
|
+
});
|
|
1795
|
+
return;
|
|
1796
|
+
}
|
|
1797
|
+
this.set({
|
|
1798
|
+
...this.snapshot,
|
|
1799
|
+
overlay: {
|
|
1800
|
+
kind: "history",
|
|
1801
|
+
status: "ready",
|
|
1802
|
+
items: outcome.payload.items
|
|
1803
|
+
}
|
|
1804
|
+
});
|
|
1805
|
+
}
|
|
1806
|
+
closeOverlay() {
|
|
1807
|
+
this.overlayToken += 1;
|
|
1808
|
+
this.set({
|
|
1809
|
+
...this.snapshot,
|
|
1810
|
+
overlay: void 0
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
dispose() {
|
|
1814
|
+
this.disposed = true;
|
|
1815
|
+
this.listeners.clear();
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
//#endregion
|
|
535
1819
|
//#region src/client/index.ts
|
|
536
1820
|
const inject = ["slots", "locale"];
|
|
537
1821
|
function PanelIcon(props = {}) {
|
|
@@ -548,34 +1832,19 @@ window.__ModuleLoader__.load({
|
|
|
548
1832
|
strokeLinejoin: "round"
|
|
549
1833
|
}, (0, react.createElement)("path", { d: "M3 4h10M3 8h6M3 12h8" }));
|
|
550
1834
|
}
|
|
551
|
-
function
|
|
552
|
-
return
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
{
|
|
565
|
-
queue: "pending",
|
|
566
|
-
count: 0
|
|
567
|
-
},
|
|
568
|
-
{
|
|
569
|
-
queue: "fuse",
|
|
570
|
-
count: 0
|
|
571
|
-
},
|
|
572
|
-
{
|
|
573
|
-
queue: "skipped",
|
|
574
|
-
count: 0
|
|
575
|
-
}
|
|
576
|
-
],
|
|
577
|
-
commands: []
|
|
578
|
-
};
|
|
1835
|
+
function interpolate(text, values) {
|
|
1836
|
+
if (values === void 0) return text;
|
|
1837
|
+
return text.replace(/\{(\w+)\}/g, (_match, key) => String(values[key] ?? ""));
|
|
1838
|
+
}
|
|
1839
|
+
/** Best-effort panel workspace; the merge panel itself is not workspace-keyed. */
|
|
1840
|
+
function panelWorkspaceId(ctx) {
|
|
1841
|
+
const get = ctx.get;
|
|
1842
|
+
if (typeof get !== "function") return void 0;
|
|
1843
|
+
for (const name of ["workspace", "uiWorkspace"]) try {
|
|
1844
|
+
const seat = get.call(ctx, name);
|
|
1845
|
+
const id = seat?.workspaceId ?? seat?.currentWorkspaceId;
|
|
1846
|
+
if (typeof id === "string" && id.trim() !== "") return id;
|
|
1847
|
+
} catch {}
|
|
579
1848
|
}
|
|
580
1849
|
function apply(ctx) {
|
|
581
1850
|
const seam = ctx;
|
|
@@ -603,14 +1872,15 @@ window.__ModuleLoader__.load({
|
|
|
603
1872
|
tag.remove();
|
|
604
1873
|
};
|
|
605
1874
|
}, "evolution-merge-ui: styles");
|
|
606
|
-
const t = (key) => {
|
|
1875
|
+
const t = (key, values) => {
|
|
607
1876
|
const fallback = zh[key] ?? key;
|
|
608
|
-
|
|
609
|
-
try {
|
|
610
|
-
|
|
1877
|
+
let text = fallback;
|
|
1878
|
+
if (registered) try {
|
|
1879
|
+
text = seam.locale.bind(NS)(key);
|
|
611
1880
|
} catch {
|
|
612
|
-
|
|
1881
|
+
text = fallback;
|
|
613
1882
|
}
|
|
1883
|
+
return interpolate(text, values);
|
|
614
1884
|
};
|
|
615
1885
|
const label = () => t("entry.label");
|
|
616
1886
|
seam.slots.inject("sidebar.panellist", function* () {
|
|
@@ -623,15 +1893,31 @@ window.__ModuleLoader__.load({
|
|
|
623
1893
|
yield seam.slots.register({
|
|
624
1894
|
name: "main",
|
|
625
1895
|
key: PANEL_ID,
|
|
626
|
-
inject: () =>
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
1896
|
+
inject: () => {
|
|
1897
|
+
const source = {
|
|
1898
|
+
view,
|
|
1899
|
+
rows,
|
|
1900
|
+
body,
|
|
1901
|
+
history
|
|
1902
|
+
};
|
|
1903
|
+
let seat;
|
|
1904
|
+
try {
|
|
1905
|
+
seat = ctx.get?.("configForms");
|
|
1906
|
+
} catch {
|
|
1907
|
+
seat = void 0;
|
|
1908
|
+
}
|
|
1909
|
+
const workspaceId = panelWorkspaceId(ctx);
|
|
1910
|
+
return {
|
|
1911
|
+
store: new MergeStore(source),
|
|
1912
|
+
t,
|
|
1913
|
+
doctorCommand: "/evolution doctor",
|
|
1914
|
+
settings: { ...seat === void 0 ? {} : {
|
|
1915
|
+
merge: seat.get("evolution-merge"),
|
|
1916
|
+
platform: seat.get("evolution-approval")
|
|
1917
|
+
} },
|
|
1918
|
+
...workspaceId === void 0 ? {} : { workspaceId }
|
|
1919
|
+
};
|
|
1920
|
+
}
|
|
635
1921
|
}, MergePanel);
|
|
636
1922
|
});
|
|
637
1923
|
}
|