@sanity/workflow-studio-plugin 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +136 -0
- package/README.md +11 -4
- package/dist/_chunks-cjs/index.cjs +1041 -439
- package/dist/_chunks-cjs/workflows-tool-root.cjs +2016 -664
- package/dist/_chunks-es/index.js +998 -440
- package/dist/_chunks-es/workflows-tool-root.js +2056 -692
- package/package.json +12 -12
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var jsxRuntime = require("react/jsx-runtime"), ui = require("@sanity/ui"), workflowReact = require("@sanity/workflow-react"), react = require("react"), router = require("sanity/router"), index = require("./index.cjs"),
|
|
3
|
+
var jsxRuntime = require("react/jsx-runtime"), ui = require("@sanity/ui"), workflowReact = require("@sanity/workflow-react"), react = require("react"), router = require("sanity/router"), index = require("./index.cjs"), Search = require("@sanity/icons/Search"), workflowEngine = require("@sanity/workflow-engine"), ChevronDown = require("@sanity/icons/ChevronDown"), Inline = require("@sanity/icons/Inline"), StackCompact = require("@sanity/icons/StackCompact"), reactDom = require("react-dom"), types = require("@sanity/types"), sanity = require("sanity"), workflowStudio = require("@sanity/workflow-studio"), WarningOutline = require("@sanity/icons/WarningOutline"), workflowDiagram = require("@sanity/workflow-diagram"), ArrowLeft = require("@sanity/icons/ArrowLeft"), InfoOutline = require("@sanity/icons/InfoOutline"), Transfer = require("@sanity/icons/Transfer"), pluralize = require("pluralize-esm"), Clock = require("@sanity/icons/Clock"), Cog = require("@sanity/icons/Cog"), EllipsisHorizontal = require("@sanity/icons/EllipsisHorizontal"), Add = require("@sanity/icons/Add"), Checkmark = require("@sanity/icons/Checkmark"), Close = require("@sanity/icons/Close"), Filter = require("@sanity/icons/Filter"), workflowComponents = require("@sanity/workflow-components"), endOfDay = require("date-fns/endOfDay"), Calendar = require("@sanity/icons/Calendar");
|
|
4
4
|
|
|
5
5
|
function _interopDefaultCompat(e) {
|
|
6
6
|
return e && typeof e == "object" && "default" in e ? e : {
|
|
@@ -22,25 +22,1235 @@ function MutedNote({text: text}) {
|
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
function TabStatusRow({children: children}) {
|
|
26
|
+
/* @__PURE__ */
|
|
27
|
+
return jsxRuntime.jsx(ui.Box, {
|
|
28
|
+
paddingLeft: 2,
|
|
29
|
+
paddingY: 3,
|
|
30
|
+
children: children
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const TOOL_PANEL_PADDING = 3, UNREADABLE = {
|
|
35
|
+
readable: !1,
|
|
36
|
+
raw: void 0
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function defaultStorage() {
|
|
40
|
+
try {
|
|
41
|
+
return globalThis.localStorage;
|
|
42
|
+
} catch {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function readItem(storage, key) {
|
|
48
|
+
if (!storage) return UNREADABLE;
|
|
49
|
+
try {
|
|
50
|
+
const raw = storage.getItem(key);
|
|
51
|
+
return {
|
|
52
|
+
readable: !0,
|
|
53
|
+
raw: raw === null ? void 0 : raw
|
|
54
|
+
};
|
|
55
|
+
} catch {
|
|
56
|
+
return UNREADABLE;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function writeItem(args) {
|
|
61
|
+
if (!args.storage) return !1;
|
|
62
|
+
try {
|
|
63
|
+
return args.storage.setItem(args.key, args.value), !0;
|
|
64
|
+
} catch {
|
|
65
|
+
return !1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const BAND_DEFAULT_OPEN = !0, UNGROUPED_BAND_KEY = "section:no-document", PAYLOAD_VERSION = 2, MAX_ENTRIES = 200;
|
|
70
|
+
|
|
71
|
+
function bandStateStorageKey(scope) {
|
|
72
|
+
return `sanity.workflows.tool.bands:${scope}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function isRecord(value) {
|
|
76
|
+
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function bandEntryOf(value) {
|
|
80
|
+
if (!isRecord(value)) return;
|
|
81
|
+
const {open: open, touched: touched} = value;
|
|
82
|
+
if (!(typeof open != "boolean" || typeof touched != "number") && Number.isFinite(touched)) return {
|
|
83
|
+
open: open,
|
|
84
|
+
touched: touched
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function parsePayload(raw) {
|
|
89
|
+
try {
|
|
90
|
+
const parsed = JSON.parse(raw);
|
|
91
|
+
if (!isRecord(parsed) || parsed.version !== PAYLOAD_VERSION || !isRecord(parsed.bands)) return;
|
|
92
|
+
const entries = [];
|
|
93
|
+
for (const [key, value] of Object.entries(parsed.bands)) {
|
|
94
|
+
const entry = bandEntryOf(value);
|
|
95
|
+
if (entry === void 0) return;
|
|
96
|
+
entries.push([ key, entry ]);
|
|
97
|
+
}
|
|
98
|
+
return Object.fromEntries(entries);
|
|
99
|
+
} catch {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function readStored(storage, storageKey) {
|
|
105
|
+
const {readable: readable, raw: raw} = readItem(storage, storageKey);
|
|
106
|
+
if (!readable) return {
|
|
107
|
+
entries: void 0,
|
|
108
|
+
corrupt: !1
|
|
109
|
+
};
|
|
110
|
+
if (raw === void 0) return {
|
|
111
|
+
entries: {},
|
|
112
|
+
corrupt: !1
|
|
113
|
+
};
|
|
114
|
+
const entries = parsePayload(raw);
|
|
115
|
+
return {
|
|
116
|
+
entries: entries,
|
|
117
|
+
corrupt: entries === void 0
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function writeStored(args) {
|
|
122
|
+
return writeItem({
|
|
123
|
+
storage: args.storage,
|
|
124
|
+
key: args.storageKey,
|
|
125
|
+
value: JSON.stringify({
|
|
126
|
+
version: PAYLOAD_VERSION,
|
|
127
|
+
bands: args.entries
|
|
128
|
+
})
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function baseEntries(args) {
|
|
133
|
+
return args.stored === void 0 ? args.held : args.unpersisted ? mergeByTouched(args.stored, args.held) : args.stored;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function mergeByTouched(stored, held) {
|
|
137
|
+
const merged = {
|
|
138
|
+
...stored
|
|
139
|
+
};
|
|
140
|
+
for (const [key, entry] of Object.entries(held)) {
|
|
141
|
+
const persisted = merged[key];
|
|
142
|
+
(persisted === void 0 || entry.touched >= persisted.touched) && (merged[key] = entry);
|
|
143
|
+
}
|
|
144
|
+
return merged;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function prune(entries) {
|
|
148
|
+
const held = Object.entries(entries);
|
|
149
|
+
return held.length <= MAX_ENTRIES ? entries : Object.fromEntries(held.sort(([, a], [, b]) => b.touched - a.touched).slice(0, MAX_ENTRIES));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function togglesOf(entries) {
|
|
153
|
+
return new Map(Object.entries(entries).map(([key, entry]) => [ key, entry.open ]));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function createBandStateStore(args) {
|
|
157
|
+
const storage = args.storage ?? defaultStorage(), initial = readStored(storage, args.storageKey);
|
|
158
|
+
initial.corrupt && writeStored({
|
|
159
|
+
storage: storage,
|
|
160
|
+
storageKey: args.storageKey,
|
|
161
|
+
entries: {}
|
|
162
|
+
});
|
|
163
|
+
let held = initial.entries ?? {}, toggles = togglesOf(held);
|
|
164
|
+
const subscribers = index.createSubscribers();
|
|
165
|
+
let unpersisted = !1;
|
|
166
|
+
return {
|
|
167
|
+
subscribe: subscribers.subscribe,
|
|
168
|
+
read: () => toggles,
|
|
169
|
+
setOpen(key, open) {
|
|
170
|
+
const stored = readStored(storage, args.storageKey).entries, base = baseEntries({
|
|
171
|
+
stored: stored,
|
|
172
|
+
held: held,
|
|
173
|
+
unpersisted: unpersisted
|
|
174
|
+
});
|
|
175
|
+
held = prune({
|
|
176
|
+
...base,
|
|
177
|
+
[key]: {
|
|
178
|
+
open: open,
|
|
179
|
+
touched: Date.now()
|
|
180
|
+
}
|
|
181
|
+
}), toggles = togglesOf(held), unpersisted = !writeStored({
|
|
182
|
+
storage: storage,
|
|
183
|
+
storageKey: args.storageKey,
|
|
184
|
+
entries: held
|
|
185
|
+
}), subscribers.notify();
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function useBandOpenState(args) {
|
|
191
|
+
const {segment: segment, scope: scope} = args, store = react.useMemo(() => createBandStateStore({
|
|
192
|
+
storageKey: bandStateStorageKey(scope)
|
|
193
|
+
}), [ scope ]);
|
|
194
|
+
return react.useMemo(() => ({
|
|
195
|
+
segment: segment,
|
|
196
|
+
store: store
|
|
197
|
+
}), [ segment, store ]);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function openOf(store, qualified) {
|
|
201
|
+
return store.read().get(qualified) ?? BAND_DEFAULT_OPEN;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function useBandOpen(bands, key) {
|
|
205
|
+
const {segment: segment, store: store} = bands, qualified = `${segment}/${key}`;
|
|
206
|
+
return {
|
|
207
|
+
open: react.useSyncExternalStore(store.subscribe, react.useCallback(() => openOf(store, qualified), [ store, qualified ])),
|
|
208
|
+
toggle: () => store.setOpen(qualified, !openOf(store, qualified))
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const lastRead = /* @__PURE__ */ new WeakMap, issuedReads = /* @__PURE__ */ new WeakMap;
|
|
213
|
+
|
|
214
|
+
function useDeployedDefinitions() {
|
|
215
|
+
const {engine: engine} = index.useWorkflowContext(), [definitions, setDefinitions] = react.useState(() => lastRead.get(engine)?.rows), [error, setError] = react.useState(void 0);
|
|
216
|
+
return react.useEffect(() => {
|
|
217
|
+
let cancelled = !1;
|
|
218
|
+
setDefinitions(lastRead.get(engine)?.rows), setError(void 0);
|
|
219
|
+
const seq = (issuedReads.get(engine) ?? 0) + 1;
|
|
220
|
+
return issuedReads.set(engine, seq), (async () => {
|
|
221
|
+
const rows = await index.readDeployedDefinitions(engine), latest = workflowEngine.latestDeployedDefinitions(rows), held = lastRead.get(engine);
|
|
222
|
+
(held === void 0 || seq > held.seq) && lastRead.set(engine, {
|
|
223
|
+
seq: seq,
|
|
224
|
+
rows: latest
|
|
225
|
+
}), cancelled || (setDefinitions(latest), setError(void 0));
|
|
226
|
+
})().catch(err => {
|
|
227
|
+
cancelled || setError(index.describeError(err));
|
|
228
|
+
}), () => {
|
|
229
|
+
cancelled = !0;
|
|
230
|
+
};
|
|
231
|
+
}, [ engine ]), {
|
|
232
|
+
definitions: definitions,
|
|
233
|
+
error: error
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const REVEAL_MAX_WAIT_MS = 2e3;
|
|
238
|
+
|
|
239
|
+
function useRevealGate(args) {
|
|
240
|
+
const {loading: loading, ready: ready} = args, settled = !loading && ready, expired = index.useDelayedFlag(!loading && !ready, REVEAL_MAX_WAIT_MS), [revealed, setRevealed] = react.useState(!1);
|
|
241
|
+
return react.useEffect(() => {
|
|
242
|
+
!revealed && (settled || expired) && setRevealed(!0);
|
|
243
|
+
}, [ expired, revealed, settled ]), revealed || settled || expired;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function documentRefsOf(instance) {
|
|
247
|
+
const seen = /* @__PURE__ */ new Map;
|
|
248
|
+
for (const ref of workflowEngine.entryDocRefs(instance.fields)) seen.has(ref.id) || seen.set(ref.id, ref);
|
|
249
|
+
return [ ...seen.values() ];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function byTitleThenName(a, b) {
|
|
253
|
+
return a.title.localeCompare(b.title) || a.name.localeCompare(b.name);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function byResolvedTitle(titleOf, keyOf) {
|
|
257
|
+
return (a, b) => {
|
|
258
|
+
const aTitle = titleOf(a), bTitle = titleOf(b);
|
|
259
|
+
return aTitle !== void 0 && bTitle !== void 0 ? aTitle.localeCompare(bTitle) || keyOf(a).localeCompare(keyOf(b)) : aTitle !== void 0 ? -1 : bTitle !== void 0 ? 1 : keyOf(a).localeCompare(keyOf(b));
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const BOARD_EMPTY_STAGE_NOTE = "No items";
|
|
264
|
+
|
|
265
|
+
function faceOf(instance) {
|
|
266
|
+
const document = documentRefsOf(instance)[0];
|
|
267
|
+
return document ? {
|
|
268
|
+
kind: "document",
|
|
269
|
+
document: document
|
|
270
|
+
} : {
|
|
271
|
+
kind: "instance",
|
|
272
|
+
title: index.instanceTitle(instance, index.definitionSnapshotOf(instance))
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function boardRuns(instances) {
|
|
277
|
+
return instances.filter(instance => workflowEngine.terminalState(instance) !== "aborted");
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function groupsOf(args) {
|
|
281
|
+
const declared = args.definition.stages.map(stage => stage.name), retired = [ ...args.byStage.keys() ].filter(stage => !declared.includes(stage)).sort();
|
|
282
|
+
return [ ...declared, ...retired ].map(stage => ({
|
|
283
|
+
stage: stage,
|
|
284
|
+
title: index.stageTitle(args.definition, stage),
|
|
285
|
+
cards: args.byStage.get(stage) ?? [],
|
|
286
|
+
retired: !declared.includes(stage)
|
|
287
|
+
}));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function deriveBoard(args) {
|
|
291
|
+
const byStage = /* @__PURE__ */ new Map;
|
|
292
|
+
for (const instance of boardRuns(args.instances)) {
|
|
293
|
+
const card = {
|
|
294
|
+
instanceId: instance._id,
|
|
295
|
+
face: faceOf(instance)
|
|
296
|
+
}, held = byStage.get(instance.currentStage);
|
|
297
|
+
held ? held.push(card) : byStage.set(instance.currentStage, [ card ]);
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
groups: groupsOf({
|
|
301
|
+
definition: args.definition,
|
|
302
|
+
byStage: byStage
|
|
303
|
+
})
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function orderBoardByPreviewTitle(board, titles) {
|
|
308
|
+
const compare = byResolvedTitle(card => card.face.kind === "instance" ? card.face.title : titles.get(card.face.document.id), card => card.instanceId);
|
|
309
|
+
return {
|
|
310
|
+
groups: board.groups.map(group => ({
|
|
311
|
+
...group,
|
|
312
|
+
cards: [ ...group.cards ].sort(compare)
|
|
313
|
+
}))
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function boardDocuments(board) {
|
|
318
|
+
return board.groups.flatMap(group => group.cards.flatMap(card => card.face.kind === "document" ? [ card.face.document ] : []));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function BoardCard({card: card, size: size}) {
|
|
322
|
+
return size === "slim" ? card.face.kind === "instance" ? /* @__PURE__ */ jsxRuntime.jsx(InstanceFace, {
|
|
323
|
+
size: size,
|
|
324
|
+
title: card.face.title
|
|
325
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(index.DocPreviewLink, {
|
|
326
|
+
gdr: card.face.document,
|
|
327
|
+
layout: "row",
|
|
328
|
+
source: "board-card"
|
|
329
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
330
|
+
border: !0,
|
|
331
|
+
radius: 3,
|
|
332
|
+
children: card.face.kind === "instance" ? /* @__PURE__ */ jsxRuntime.jsx(InstanceFace, {
|
|
333
|
+
size: size,
|
|
334
|
+
title: card.face.title
|
|
335
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(index.DocPreviewLink, {
|
|
336
|
+
gdr: card.face.document,
|
|
337
|
+
layout: "bare",
|
|
338
|
+
source: "board-card"
|
|
339
|
+
})
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function InstanceFace({size: size, title: title}) {
|
|
344
|
+
const fill = size === "slim";
|
|
345
|
+
/* @__PURE__ */
|
|
346
|
+
return jsxRuntime.jsx(ui.Box, {
|
|
347
|
+
padding: fill ? index.chipPadding(!0) : index.NOTICE_PADDING,
|
|
348
|
+
style: fill ? {
|
|
349
|
+
width: "100%"
|
|
350
|
+
} : {},
|
|
351
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
352
|
+
size: 1,
|
|
353
|
+
textOverflow: "ellipsis",
|
|
354
|
+
weight: "medium",
|
|
355
|
+
children: title
|
|
356
|
+
})
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function StageGroupHeading({group: group}) {
|
|
361
|
+
/* @__PURE__ */
|
|
362
|
+
return jsxRuntime.jsxs(ui.Flex, {
|
|
363
|
+
align: "center",
|
|
364
|
+
gap: 2,
|
|
365
|
+
children: [
|
|
366
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.CountedLabel, {
|
|
367
|
+
count: group.cards.length,
|
|
368
|
+
label: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
369
|
+
size: 1,
|
|
370
|
+
weight: "medium",
|
|
371
|
+
children: group.title
|
|
372
|
+
})
|
|
373
|
+
}), group.retired ?
|
|
374
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
375
|
+
muted: !0,
|
|
376
|
+
size: 1,
|
|
377
|
+
children: "No longer in this workflow"
|
|
378
|
+
}) : null ]
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const COLUMN_WIDTH = 320, PANEL_FADE = "linear-gradient(to bottom, rgb(0 0 0) 50%, rgb(0 0 0 / 0) 75%)";
|
|
383
|
+
|
|
384
|
+
function StageColumn({group: group}) {
|
|
385
|
+
/* @__PURE__ */
|
|
386
|
+
return jsxRuntime.jsxs(ui.Box, {
|
|
387
|
+
flex: "none",
|
|
388
|
+
style: {
|
|
389
|
+
display: "flex",
|
|
390
|
+
flexDirection: "column",
|
|
391
|
+
position: "relative",
|
|
392
|
+
width: COLUMN_WIDTH
|
|
393
|
+
},
|
|
394
|
+
children: [
|
|
395
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
396
|
+
"aria-hidden": !0,
|
|
397
|
+
radius: 3,
|
|
398
|
+
style: {
|
|
399
|
+
inset: 0,
|
|
400
|
+
maskImage: PANEL_FADE,
|
|
401
|
+
position: "absolute",
|
|
402
|
+
WebkitMaskImage: PANEL_FADE
|
|
403
|
+
},
|
|
404
|
+
tone: "transparent"
|
|
405
|
+
}),
|
|
406
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
407
|
+
flex: "none",
|
|
408
|
+
paddingX: 3,
|
|
409
|
+
paddingY: 4,
|
|
410
|
+
style: {
|
|
411
|
+
position: "relative"
|
|
412
|
+
},
|
|
413
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(StageGroupHeading, {
|
|
414
|
+
group: group
|
|
415
|
+
})
|
|
416
|
+
}), group.cards.length === 0 ?
|
|
417
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
418
|
+
align: "center",
|
|
419
|
+
flex: 1,
|
|
420
|
+
justify: "center",
|
|
421
|
+
padding: 2,
|
|
422
|
+
style: {
|
|
423
|
+
position: "relative"
|
|
424
|
+
},
|
|
425
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
426
|
+
muted: !0,
|
|
427
|
+
size: 1,
|
|
428
|
+
children: BOARD_EMPTY_STAGE_NOTE
|
|
429
|
+
})
|
|
430
|
+
}) :
|
|
431
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
432
|
+
flex: 1,
|
|
433
|
+
overflow: "auto",
|
|
434
|
+
paddingBottom: 2,
|
|
435
|
+
paddingX: 2,
|
|
436
|
+
style: {
|
|
437
|
+
minHeight: 0,
|
|
438
|
+
position: "relative"
|
|
439
|
+
},
|
|
440
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, {
|
|
441
|
+
gap: 1,
|
|
442
|
+
children: group.cards.map(card => /* @__PURE__ */ jsxRuntime.jsx(BoardCard, {
|
|
443
|
+
card: card,
|
|
444
|
+
size: "block"
|
|
445
|
+
}, card.instanceId))
|
|
446
|
+
})
|
|
447
|
+
}) ]
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function StageGroups({board: board}) {
|
|
452
|
+
const topGap = index.useSpaceToken(TOOL_PANEL_PADDING);
|
|
453
|
+
/* @__PURE__ */
|
|
454
|
+
return jsxRuntime.jsx(ui.Box, {
|
|
455
|
+
flex: 1,
|
|
456
|
+
style: {
|
|
457
|
+
minHeight: 0,
|
|
458
|
+
position: "relative"
|
|
459
|
+
},
|
|
460
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
461
|
+
style: {
|
|
462
|
+
bottom: 0,
|
|
463
|
+
left: 0,
|
|
464
|
+
overflowX: "auto",
|
|
465
|
+
overflowY: "hidden",
|
|
466
|
+
position: "absolute",
|
|
467
|
+
right: 0,
|
|
468
|
+
top: topGap
|
|
469
|
+
},
|
|
470
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
471
|
+
align: "stretch",
|
|
472
|
+
gap: 2,
|
|
473
|
+
paddingX: TOOL_PANEL_PADDING,
|
|
474
|
+
style: {
|
|
475
|
+
boxSizing: "border-box",
|
|
476
|
+
height: "100%",
|
|
477
|
+
width: "max-content"
|
|
478
|
+
},
|
|
479
|
+
children: board.groups.map(group => /* @__PURE__ */ jsxRuntime.jsx(StageColumn, {
|
|
480
|
+
group: group
|
|
481
|
+
}, group.stage))
|
|
482
|
+
})
|
|
483
|
+
})
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
function isPlainClick(event) {
|
|
488
|
+
return !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const BOARD_LAYOUTS = [ "columns", "stack" ], BOARD_DEFAULT_LAYOUT = "columns";
|
|
492
|
+
|
|
493
|
+
function boardLayoutStorageKey(scope) {
|
|
494
|
+
return `sanity.workflows.tool.board-layout:${scope}`;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function layoutOf(raw) {
|
|
498
|
+
return BOARD_LAYOUTS.find(layout => layout === raw) ?? BOARD_DEFAULT_LAYOUT;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function createBoardLayoutStore(args) {
|
|
502
|
+
const storage = args.storage ?? defaultStorage();
|
|
503
|
+
return {
|
|
504
|
+
read: () => layoutOf(readItem(storage, args.storageKey).raw),
|
|
505
|
+
set(layout) {
|
|
506
|
+
return writeItem({
|
|
507
|
+
storage: storage,
|
|
508
|
+
key: args.storageKey,
|
|
509
|
+
value: layout
|
|
510
|
+
}), layout;
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const PICKER_RADIUS = 3;
|
|
516
|
+
|
|
517
|
+
function pickerLabel(face) {
|
|
518
|
+
return face.kind === "named" ? face.title : face.kind === "loading" ? "Loading" : "Select a workflow";
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function WorkflowPicker({face: face, onSelect: onSelect, options: options}) {
|
|
522
|
+
const empty = options.length === 0, innerRadius = index.useRadiusToken(PICKER_RADIUS) - 1;
|
|
523
|
+
/* @__PURE__ */
|
|
524
|
+
return jsxRuntime.jsx(ui.Card, {
|
|
525
|
+
border: !0,
|
|
526
|
+
radius: PICKER_RADIUS,
|
|
527
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
528
|
+
align: "center",
|
|
529
|
+
children: [
|
|
530
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
531
|
+
paddingLeft: 2,
|
|
532
|
+
paddingRight: 2,
|
|
533
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
534
|
+
muted: !0,
|
|
535
|
+
size: 1,
|
|
536
|
+
children: "Workflow"
|
|
537
|
+
})
|
|
538
|
+
}),
|
|
539
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.MenuButton, {
|
|
540
|
+
button: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
541
|
+
fontSize: 1,
|
|
542
|
+
gap: 2,
|
|
543
|
+
iconRight: ChevronDown.ChevronDownIcon,
|
|
544
|
+
mode: "bleed",
|
|
545
|
+
disabled: empty,
|
|
546
|
+
padding: 2,
|
|
547
|
+
radius: 0,
|
|
548
|
+
style: {
|
|
549
|
+
borderRadius: `0 ${innerRadius}px ${innerRadius}px 0`
|
|
550
|
+
},
|
|
551
|
+
text: pickerLabel(face)
|
|
552
|
+
}),
|
|
553
|
+
id: "workflows-board-picker",
|
|
554
|
+
menu: /* @__PURE__ */ jsxRuntime.jsx(ui.Menu, {
|
|
555
|
+
children: options.map(option => /* @__PURE__ */ jsxRuntime.jsx(ui.MenuItem, {
|
|
556
|
+
fontSize: 1,
|
|
557
|
+
onClick: () => onSelect(option.name),
|
|
558
|
+
pressed: face.kind === "named" && option.name === face.name,
|
|
559
|
+
text: option.title
|
|
560
|
+
}, option.name))
|
|
561
|
+
}),
|
|
562
|
+
popover: {
|
|
563
|
+
constrainSize: !0,
|
|
564
|
+
fallbackPlacements: [ "top-start" ],
|
|
565
|
+
placement: "bottom-start",
|
|
566
|
+
portal: !0
|
|
567
|
+
}
|
|
568
|
+
}) ]
|
|
569
|
+
})
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const LAYOUT_LABELS = {
|
|
574
|
+
columns: {
|
|
575
|
+
icon: Inline.InlineIcon,
|
|
576
|
+
label: "Show as boards"
|
|
577
|
+
},
|
|
578
|
+
stack: {
|
|
579
|
+
icon: StackCompact.StackCompactIcon,
|
|
580
|
+
label: "Show as list"
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
function LayoutToggle({layout: layout, onChange: onChange}) {
|
|
585
|
+
/* @__PURE__ */
|
|
586
|
+
return jsxRuntime.jsx(ui.Flex, {
|
|
587
|
+
align: "center",
|
|
588
|
+
gap: 1,
|
|
589
|
+
children: BOARD_LAYOUTS.map(value => {
|
|
590
|
+
const {icon: icon, label: label} = LAYOUT_LABELS[value];
|
|
591
|
+
/* @__PURE__ */
|
|
592
|
+
return jsxRuntime.jsx(index.HoverHint, {
|
|
593
|
+
text: label,
|
|
594
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
595
|
+
"aria-label": label,
|
|
596
|
+
"aria-pressed": value === layout,
|
|
597
|
+
fontSize: 1,
|
|
598
|
+
icon: icon,
|
|
599
|
+
mode: "bleed",
|
|
600
|
+
onClick: () => onChange(value),
|
|
601
|
+
padding: 2,
|
|
602
|
+
selected: value === layout
|
|
603
|
+
})
|
|
604
|
+
}, value);
|
|
605
|
+
})
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
function DefinitionLink({name: name, onOpen: onOpen}) {
|
|
610
|
+
const {resolvePathFromState: resolvePathFromState} = router.useRouter();
|
|
611
|
+
/* @__PURE__ */
|
|
612
|
+
return jsxRuntime.jsx(ui.Button, {
|
|
613
|
+
as: "a",
|
|
614
|
+
fontSize: 1,
|
|
615
|
+
href: resolvePathFromState({
|
|
616
|
+
definitionName: name
|
|
617
|
+
}),
|
|
618
|
+
mode: "bleed",
|
|
619
|
+
onClick: event => {
|
|
620
|
+
isPlainClick(event) && (event.preventDefault(), onOpen(name));
|
|
621
|
+
},
|
|
622
|
+
padding: 2,
|
|
623
|
+
text: "View definition"
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
function BoardControlsPortal({definitionName: definitionName, layout: layout, onChangeLayout: onChangeLayout, face: face, onOpenDefinition: onOpenDefinition, onSelectWorkflow: onSelectWorkflow, options: options, slot: slot}) {
|
|
628
|
+
return slot ? reactDom.createPortal(
|
|
629
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
630
|
+
align: "center",
|
|
631
|
+
gap: 2,
|
|
632
|
+
children: [
|
|
633
|
+
/* @__PURE__ */ jsxRuntime.jsx(WorkflowPicker, {
|
|
634
|
+
face: face,
|
|
635
|
+
onSelect: onSelectWorkflow,
|
|
636
|
+
options: options
|
|
637
|
+
}), definitionName === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(DefinitionLink, {
|
|
638
|
+
name: definitionName,
|
|
639
|
+
onOpen: onOpenDefinition
|
|
640
|
+
}),
|
|
641
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
642
|
+
flex: 1
|
|
643
|
+
}),
|
|
644
|
+
/* @__PURE__ */ jsxRuntime.jsx(LayoutToggle, {
|
|
645
|
+
layout: layout,
|
|
646
|
+
onChange: onChangeLayout
|
|
647
|
+
}) ]
|
|
648
|
+
}), slot) : null;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function boardWorkflowOptions(definitions) {
|
|
652
|
+
return definitions.map(definition => ({
|
|
653
|
+
name: definition.name,
|
|
654
|
+
title: definition.title
|
|
655
|
+
})).sort(byTitleThenName);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
function boardLandingName(selection) {
|
|
659
|
+
if (!(selection.kind !== "resolved" || selection.via !== "default")) return selection.definition.name;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function boardPickerFace(args) {
|
|
663
|
+
const {selection: selection, routeName: routeName} = args;
|
|
664
|
+
if (selection.kind === "resolved") {
|
|
665
|
+
const {name: name, title: title} = selection.definition;
|
|
666
|
+
return {
|
|
667
|
+
kind: "named",
|
|
668
|
+
name: name,
|
|
669
|
+
title: title
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
return selection.kind === "loading" && routeName !== void 0 ? {
|
|
673
|
+
kind: "loading"
|
|
674
|
+
} : {
|
|
675
|
+
kind: "none"
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function boardSelectedPayload(selection) {
|
|
680
|
+
if (selection.kind === "resolved") return {
|
|
681
|
+
via: selection.via,
|
|
682
|
+
...index.definitionFingerprint(selection.definition)
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function resolveBoardSelection(args) {
|
|
687
|
+
const {definitions: definitions, routeName: routeName} = args;
|
|
688
|
+
if (definitions === void 0) return {
|
|
689
|
+
kind: "loading"
|
|
690
|
+
};
|
|
691
|
+
if (routeName !== void 0) {
|
|
692
|
+
const named = definitions.find(definition => definition.name === routeName);
|
|
693
|
+
return named ? {
|
|
694
|
+
kind: "resolved",
|
|
695
|
+
definition: named,
|
|
696
|
+
via: "address"
|
|
697
|
+
} : {
|
|
698
|
+
kind: "unknown",
|
|
699
|
+
name: routeName
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
const [landing] = [ ...definitions ].sort(byTitleThenName);
|
|
703
|
+
return landing ? {
|
|
704
|
+
kind: "resolved",
|
|
705
|
+
definition: landing,
|
|
706
|
+
via: "default"
|
|
707
|
+
} : {
|
|
708
|
+
kind: "empty"
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
function StageBand({bands: bands, group: group}) {
|
|
713
|
+
const {open: open, toggle: toggle} = useBandOpen(bands, group.stage);
|
|
714
|
+
/* @__PURE__ */
|
|
715
|
+
return jsxRuntime.jsx(index.CollapsibleBand, {
|
|
716
|
+
background: !0,
|
|
717
|
+
onToggle: toggle,
|
|
718
|
+
open: open,
|
|
719
|
+
sticky: !0,
|
|
720
|
+
title: group.title,
|
|
721
|
+
header: /* @__PURE__ */ jsxRuntime.jsx(StageGroupHeading, {
|
|
722
|
+
group: group
|
|
723
|
+
}),
|
|
724
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, {
|
|
725
|
+
gap: 1,
|
|
726
|
+
paddingLeft: 5,
|
|
727
|
+
children: group.cards.length === 0 ?
|
|
728
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
729
|
+
padding: 3,
|
|
730
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
731
|
+
muted: !0,
|
|
732
|
+
size: 1,
|
|
733
|
+
children: BOARD_EMPTY_STAGE_NOTE
|
|
734
|
+
})
|
|
735
|
+
}) : group.cards.map(card => /* @__PURE__ */ jsxRuntime.jsx(BoardCard, {
|
|
736
|
+
card: card,
|
|
737
|
+
size: "slim"
|
|
738
|
+
}, card.instanceId))
|
|
739
|
+
})
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
function BoardStack({bands: bands, board: board}) {
|
|
744
|
+
/* @__PURE__ */
|
|
745
|
+
return jsxRuntime.jsx(ui.Stack, {
|
|
746
|
+
gap: 1,
|
|
747
|
+
paddingBottom: 4,
|
|
748
|
+
paddingTop: 3,
|
|
749
|
+
paddingX: TOOL_PANEL_PADDING,
|
|
750
|
+
children: board.groups.map(group => /* @__PURE__ */ jsxRuntime.jsx(StageBand, {
|
|
751
|
+
bands: bands,
|
|
752
|
+
group: group
|
|
753
|
+
}, group.stage))
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
const ALIAS_PREFIX = "__seed_", MAX_PATH_DEPTH = 3, IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
758
|
+
|
|
759
|
+
function previewSelectOf(schemaType) {
|
|
760
|
+
const select = schemaType.preview?.select;
|
|
761
|
+
if (!(select === void 0 || Object.keys(select).length === 0)) return select;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function fieldTypeOf(parent, name) {
|
|
765
|
+
if (!(!("fields" in parent) || !Array.isArray(parent.fields))) return parent.fields.find(field => field.name === name)?.type;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
function stepOf(args) {
|
|
769
|
+
const {parent: parent, segment: segment, terminal: terminal} = args, fieldType = fieldTypeOf(parent, segment);
|
|
770
|
+
if (fieldType !== void 0) {
|
|
771
|
+
if (terminal) return {
|
|
772
|
+
part: segment,
|
|
773
|
+
next: fieldType
|
|
774
|
+
};
|
|
775
|
+
if (types.isReferenceSchemaType(fieldType)) {
|
|
776
|
+
const target = fieldType.to.length === 1 ? fieldType.to[0] : void 0;
|
|
777
|
+
return target === void 0 ? void 0 : {
|
|
778
|
+
part: `${segment}->`,
|
|
779
|
+
next: target
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
return {
|
|
783
|
+
part: `${segment}.`,
|
|
784
|
+
next: fieldType
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
function compilePath(root, path) {
|
|
790
|
+
const segments = path.split(".");
|
|
791
|
+
if (segments.length > MAX_PATH_DEPTH || segments.some(s => !IDENTIFIER.test(s))) return;
|
|
792
|
+
let parent = root;
|
|
793
|
+
const parts = [];
|
|
794
|
+
for (const [index2, segment] of segments.entries()) {
|
|
795
|
+
const step = stepOf({
|
|
796
|
+
parent: parent,
|
|
797
|
+
segment: segment,
|
|
798
|
+
terminal: index2 === segments.length - 1
|
|
799
|
+
});
|
|
800
|
+
if (step === void 0) return;
|
|
801
|
+
parts.push(step.part), parent = step.next;
|
|
802
|
+
}
|
|
803
|
+
return parts.join("");
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
function selectArmOf(schemaType) {
|
|
807
|
+
const select = previewSelectOf(schemaType);
|
|
808
|
+
if (select === void 0) return;
|
|
809
|
+
const entries = [];
|
|
810
|
+
for (const [key, path] of Object.entries(select)) {
|
|
811
|
+
const compiled = compilePath(schemaType, path);
|
|
812
|
+
if (compiled === void 0) return;
|
|
813
|
+
entries.push(`${JSON.stringify(ALIAS_PREFIX + key)}: ${compiled}`);
|
|
814
|
+
}
|
|
815
|
+
return `_type == ${JSON.stringify(schemaType.name)} => {${entries.join(", ")}}`;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
function planTitleSeed(types2) {
|
|
819
|
+
const seedable = /* @__PURE__ */ new Map, arms = [];
|
|
820
|
+
for (const type of types2) {
|
|
821
|
+
const arm = selectArmOf(type);
|
|
822
|
+
arm !== void 0 && (seedable.set(type.name, type), arms.push(arm));
|
|
823
|
+
}
|
|
824
|
+
return {
|
|
825
|
+
query: `*[_id in $ids]{_id, _type${arms.length > 0 ? `, ...select(${arms.join(", ")})` : ""}}`,
|
|
826
|
+
seedable: seedable
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
function isSeedRow(value) {
|
|
831
|
+
if (typeof value != "object" || value === null) return !1;
|
|
832
|
+
const row = value;
|
|
833
|
+
return typeof row._id == "string" && typeof row._type == "string";
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
function seededTitleOf(row, schemaType) {
|
|
837
|
+
const select = previewSelectOf(schemaType);
|
|
838
|
+
if (select === void 0) return;
|
|
839
|
+
const selected = {};
|
|
840
|
+
for (const key of Object.keys(select)) selected[key] = row[ALIAS_PREFIX + key];
|
|
841
|
+
const prepare = schemaType.preview?.prepare;
|
|
842
|
+
let title;
|
|
843
|
+
if (prepare === void 0) title = selected.title; else try {
|
|
844
|
+
title = prepare(selected).title;
|
|
845
|
+
} catch (err) {
|
|
846
|
+
console.error(`[workflow-studio-plugin] preview prepare for "${schemaType.name}" failed on seed:`, err);
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
return typeof title == "string" ? title : void 0;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
function seedFromRows(args) {
|
|
853
|
+
const rows = args.rows.filter(isSeedRow), byBareId = new Map(rows.map(row => [ row._id, row ])), types2 = new Map(rows.map(row => [ row._id, row._type ])), titles = /* @__PURE__ */ new Map, resolved = /* @__PURE__ */ new Set;
|
|
854
|
+
for (const {gdrId: gdrId, bareId: bareId} of args.docs) {
|
|
855
|
+
const row = byBareId.get(bareId);
|
|
856
|
+
if (row === void 0) continue;
|
|
857
|
+
const schemaType = args.seedable.get(row._type);
|
|
858
|
+
if (schemaType === void 0) continue;
|
|
859
|
+
resolved.add(gdrId);
|
|
860
|
+
const title = seededTitleOf(row, schemaType);
|
|
861
|
+
title !== void 0 && titles.set(gdrId, title);
|
|
862
|
+
}
|
|
863
|
+
return {
|
|
864
|
+
types: types2,
|
|
865
|
+
titles: {
|
|
866
|
+
titles: titles,
|
|
867
|
+
resolved: resolved
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
function titleDrift(seed, live) {
|
|
873
|
+
const drifted = [];
|
|
874
|
+
for (const gdrId of seed.resolved) {
|
|
875
|
+
if (!live.resolved.has(gdrId)) continue;
|
|
876
|
+
const seeded = seed.titles.get(gdrId), observed = live.titles.get(gdrId);
|
|
877
|
+
seeded !== observed && drifted.push({
|
|
878
|
+
gdrId: gdrId,
|
|
879
|
+
seeded: seeded,
|
|
880
|
+
observed: observed
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
return drifted;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
function mergeSeededTitles(live, seed) {
|
|
887
|
+
if (seed.resolved.size === 0) return live;
|
|
888
|
+
const titles = new Map(live.titles), resolved = new Set(live.resolved);
|
|
889
|
+
for (const gdrId of seed.resolved) {
|
|
890
|
+
if (live.resolved.has(gdrId)) continue;
|
|
891
|
+
resolved.add(gdrId);
|
|
892
|
+
const title = seed.titles.get(gdrId);
|
|
893
|
+
title !== void 0 && titles.set(gdrId, title);
|
|
894
|
+
}
|
|
895
|
+
return {
|
|
896
|
+
titles: titles,
|
|
897
|
+
resolved: resolved
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
const NO_TITLES = {
|
|
902
|
+
titles: /* @__PURE__ */ new Map,
|
|
903
|
+
resolved: /* @__PURE__ */ new Set
|
|
904
|
+
};
|
|
905
|
+
|
|
906
|
+
function useDocPreviewTitles(documents) {
|
|
907
|
+
const previewStore = sanity.useDocumentPreviewStore(), schema = sanity.useSchema(), {perspectiveStack: perspectiveStack} = sanity.usePerspective(), {actualTypes: actualTypes, binding: binding} = index.useWorkflowContext(), [state, setState] = react.useState(NO_TITLES), key = documents.map(doc => doc.id).join("|");
|
|
908
|
+
return react.useEffect(() => {
|
|
909
|
+
const titles = /* @__PURE__ */ new Map, resolved = /* @__PURE__ */ new Set, previews = /* @__PURE__ */ new Map, publish = () => setState({
|
|
910
|
+
titles: new Map(titles),
|
|
911
|
+
resolved: new Set(resolved)
|
|
912
|
+
}), localDocs = documents.flatMap(doc => {
|
|
913
|
+
const {parsed: parsed, local: local} = index.gdrLocality(doc.id, binding.contentResource);
|
|
914
|
+
return !parsed || !local ? (resolved.add(doc.id), []) : [ {
|
|
915
|
+
doc: doc,
|
|
916
|
+
bareId: parsed.documentId
|
|
917
|
+
} ];
|
|
918
|
+
}), untracks = localDocs.map(({bareId: bareId}) => actualTypes.track(bareId)), dropPreview = docId => {
|
|
919
|
+
previews.get(docId)?.unsubscribe(), previews.delete(docId), titles.delete(docId);
|
|
920
|
+
}, observe = ({docId: docId, bareId: bareId, typeName: typeName}) => {
|
|
921
|
+
const schemaType = index.openableSchemaType(schema, typeName);
|
|
922
|
+
if (!schemaType) return !1;
|
|
923
|
+
if (previews.get(docId)?.typeName === typeName) return !0;
|
|
924
|
+
dropPreview(docId), resolved.delete(docId);
|
|
925
|
+
const subscription = previewStore.observeForPreview({
|
|
926
|
+
_id: bareId,
|
|
927
|
+
_type: schemaType.name
|
|
928
|
+
}, schemaType, {
|
|
929
|
+
perspective: perspectiveStack
|
|
930
|
+
}).subscribe({
|
|
931
|
+
next: event => {
|
|
932
|
+
resolved.add(docId);
|
|
933
|
+
const title = event.snapshot?.title;
|
|
934
|
+
typeof title == "string" ? titles.set(docId, title) : titles.delete(docId), publish();
|
|
935
|
+
},
|
|
936
|
+
error: err => {
|
|
937
|
+
console.error(`[workflow-studio-plugin] preview for "${docId}" failed:`, err), resolved.add(docId),
|
|
938
|
+
publish();
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
return previews.set(docId, {
|
|
942
|
+
typeName: typeName,
|
|
943
|
+
unsubscribe: () => subscription.unsubscribe()
|
|
944
|
+
}), !0;
|
|
945
|
+
}, evaluate = () => {
|
|
946
|
+
for (const {doc: doc, bareId: bareId} of localDocs) {
|
|
947
|
+
const probe = actualTypes.read(bareId);
|
|
948
|
+
if (probe === null) {
|
|
949
|
+
dropPreview(doc.id), resolved.add(doc.id);
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
!observe({
|
|
953
|
+
docId: doc.id,
|
|
954
|
+
bareId: bareId,
|
|
955
|
+
typeName: probe ?? doc.type
|
|
956
|
+
}) && typeof probe == "string" && (dropPreview(doc.id), resolved.add(doc.id));
|
|
957
|
+
}
|
|
958
|
+
publish();
|
|
959
|
+
}, unsubscribeProbes = actualTypes.subscribe(evaluate);
|
|
960
|
+
return evaluate(), () => {
|
|
961
|
+
unsubscribeProbes(), untracks.forEach(untrack => untrack()), previews.forEach(preview => preview.unsubscribe());
|
|
962
|
+
};
|
|
963
|
+
}, [ key, previewStore, schema, actualTypes, binding.contentResource.id, perspectiveStack.join("|") ]),
|
|
964
|
+
state;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
function usePreviewSeed(documents) {
|
|
968
|
+
const client = sanity.useClient({
|
|
969
|
+
apiVersion: index.WORKFLOW_API_VERSION
|
|
970
|
+
}), schema = sanity.useSchema(), {perspectiveStack: perspectiveStack} = sanity.usePerspective(), {actualTypes: actualTypes, binding: binding} = index.useWorkflowContext(), [seed, setSeed] = react.useState(NO_TITLES), docs = react.useMemo(() => documents.flatMap(doc => {
|
|
971
|
+
const {parsed: parsed, local: local} = index.gdrLocality(doc.id, binding.contentResource);
|
|
972
|
+
return parsed === void 0 || !local ? [] : [ {
|
|
973
|
+
gdrId: doc.id,
|
|
974
|
+
bareId: parsed.documentId
|
|
975
|
+
} ];
|
|
976
|
+
}), [ documents, binding.contentResource ]), key = docs.map(doc => doc.gdrId).join("|");
|
|
977
|
+
return react.useEffect(() => {
|
|
978
|
+
if (setSeed(NO_TITLES), key === "") return;
|
|
979
|
+
const plan = planTitleSeed(schema.getTypeNames().flatMap(name => index.openableSchemaType(schema, name) ?? []));
|
|
980
|
+
let cancelled = !1;
|
|
981
|
+
return client.fetch(plan.query, {
|
|
982
|
+
ids: docs.map(doc => doc.bareId)
|
|
983
|
+
}, {
|
|
984
|
+
tag: "workflows.preview-seed",
|
|
985
|
+
...perspectiveStack.length > 0 ? {
|
|
986
|
+
perspective: [ ...perspectiveStack ]
|
|
987
|
+
} : {}
|
|
988
|
+
}).then(rows => {
|
|
989
|
+
if (cancelled) return;
|
|
990
|
+
const result = seedFromRows({
|
|
991
|
+
rows: rows,
|
|
992
|
+
docs: docs,
|
|
993
|
+
seedable: plan.seedable
|
|
994
|
+
});
|
|
995
|
+
actualTypes.seed(result.types), setSeed(result.titles);
|
|
996
|
+
}).catch(err => {
|
|
997
|
+
cancelled || console.error("[workflow-studio-plugin] preview seed failed:", err);
|
|
998
|
+
}), () => {
|
|
999
|
+
cancelled = !0;
|
|
1000
|
+
};
|
|
1001
|
+
}, [ key, client, schema, actualTypes, binding.contentResource.id, perspectiveStack.join("|") ]),
|
|
1002
|
+
seed;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
function useSeededTitles(args) {
|
|
1006
|
+
const {ordering: ordering, warm: warm} = args, seed = usePreviewSeed(warm), live = useDocPreviewTitles(ordering), telemetry = workflowReact.useWorkflowTelemetry(), warned = react.useRef(/* @__PURE__ */ new Set);
|
|
1007
|
+
return react.useEffect(() => {
|
|
1008
|
+
const fresh = titleDrift(seed, live).filter(drift => !warned.current.has(drift.gdrId));
|
|
1009
|
+
if (fresh.length !== 0) {
|
|
1010
|
+
warned.current.size === 0 && telemetry.log(index.WorkflowTitleSeedDrifted, {
|
|
1011
|
+
driftCount: fresh.length
|
|
1012
|
+
});
|
|
1013
|
+
for (const drift of fresh) warned.current.add(drift.gdrId), console.warn(`[workflow-studio-plugin] seeded preview title for "${drift.gdrId}" diverged from the live pipeline — the seed projection or prepare mirroring is drifting from Studio preview resolution`);
|
|
1014
|
+
}
|
|
1015
|
+
}, [ seed, live, telemetry ]), react.useMemo(() => {
|
|
1016
|
+
const merged = mergeSeededTitles(live, seed);
|
|
1017
|
+
return {
|
|
1018
|
+
...merged,
|
|
1019
|
+
ready: ordering.every(doc => merged.resolved.has(doc.id))
|
|
1020
|
+
};
|
|
1021
|
+
}, [ ordering, live, seed ]);
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
function useGroupTitles(groups) {
|
|
1025
|
+
const ordering = react.useMemo(() => groups.withDocuments.map(group => group.document), [ groups ]), warm = react.useMemo(() => groups.withDocuments.flatMap(group => group.documents), [ groups ]);
|
|
1026
|
+
return useSeededTitles({
|
|
1027
|
+
ordering: ordering,
|
|
1028
|
+
warm: warm
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
const NO_DOCUMENTS = [];
|
|
1033
|
+
|
|
1034
|
+
function useBoard(args) {
|
|
1035
|
+
const {definition: definition, instances: instances} = args, derived = react.useMemo(() => definition ? deriveBoard({
|
|
1036
|
+
instances: instances,
|
|
1037
|
+
definition: definition
|
|
1038
|
+
}) : void 0, [ definition, instances ]), documents = react.useMemo(() => derived ? boardDocuments(derived) : NO_DOCUMENTS, [ derived ]), {titles: titles, ready: ready} = useSeededTitles({
|
|
1039
|
+
ordering: documents,
|
|
1040
|
+
warm: documents
|
|
1041
|
+
}), board = react.useMemo(() => derived ? orderBoardByPreviewTitle(derived, titles) : void 0, [ derived, titles ]);
|
|
1042
|
+
return react.useMemo(() => ({
|
|
1043
|
+
board: board,
|
|
1044
|
+
ready: ready
|
|
1045
|
+
}), [ board, ready ]);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
const INSTANCE_CAP = 200;
|
|
1049
|
+
|
|
1050
|
+
function useCappedInstances(filter) {
|
|
1051
|
+
const {engine: engine} = index.useWorkflowContext(), capped = react.useMemo(() => ({
|
|
1052
|
+
...filter,
|
|
1053
|
+
limit: INSTANCE_CAP
|
|
1054
|
+
}), [ filter ]), {instances: instances, loading: loading, unreadable: unreadable} = workflowStudio.useWorkflowInstances({
|
|
1055
|
+
engine: engine,
|
|
1056
|
+
filter: capped
|
|
1057
|
+
});
|
|
1058
|
+
return react.useMemo(() => {
|
|
1059
|
+
const rows = instances ?? [];
|
|
1060
|
+
return {
|
|
1061
|
+
rows: rows,
|
|
1062
|
+
truncated: rows.length + unreadable.length === INSTANCE_CAP,
|
|
1063
|
+
loading: loading,
|
|
1064
|
+
unreadable: unreadable
|
|
1065
|
+
};
|
|
1066
|
+
}, [ instances, loading, unreadable ]);
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
const BOARD_CAP_NOTE = `Showing the latest ${INSTANCE_CAP} workflows — older ones aren’t on the board.`, NOTHING = {
|
|
1070
|
+
ids: []
|
|
1071
|
+
};
|
|
1072
|
+
|
|
1073
|
+
function useBoardInstances(definitionName) {
|
|
1074
|
+
const filter = react.useMemo(() => definitionName === void 0 ? NOTHING : {
|
|
1075
|
+
definition: definitionName,
|
|
1076
|
+
includeCompleted: !0
|
|
1077
|
+
}, [ definitionName ]);
|
|
1078
|
+
return useCappedInstances(filter);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
function useBoardLayout(scope) {
|
|
1082
|
+
const store = react.useMemo(() => createBoardLayoutStore({
|
|
1083
|
+
storageKey: boardLayoutStorageKey(scope)
|
|
1084
|
+
}), [ scope ]), [held, setHeld] = react.useState(() => ({
|
|
1085
|
+
store: store,
|
|
1086
|
+
layout: store.read()
|
|
1087
|
+
}));
|
|
1088
|
+
return held.store !== store && setHeld({
|
|
1089
|
+
store: store,
|
|
1090
|
+
layout: store.read()
|
|
1091
|
+
}), {
|
|
1092
|
+
layout: held.layout,
|
|
1093
|
+
setLayout: layout => setHeld({
|
|
1094
|
+
store: store,
|
|
1095
|
+
layout: store.set(layout)
|
|
1096
|
+
})
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
function DocumentsTab({filterSlot: filterSlot, onOpenDefinition: onOpenDefinition, onSelectWorkflow: onSelectWorkflow, routeDefinition: routeDefinition}) {
|
|
1101
|
+
const {binding: binding} = index.useWorkflowContext(), telemetry = workflowReact.useWorkflowTelemetry(), {definitions: definitions, error: error} = useDeployedDefinitions(), {layout: layout, setLayout: setLayout} = useBoardLayout(binding.engineResource.id), bands = useBandOpenState({
|
|
1102
|
+
segment: "documents",
|
|
1103
|
+
scope: binding.engineResource.id
|
|
1104
|
+
}), selection = resolveBoardSelection({
|
|
1105
|
+
definitions: definitions,
|
|
1106
|
+
routeName: routeDefinition
|
|
1107
|
+
}), selected = selection.kind === "resolved" ? selection.definition : void 0, instances = useBoardInstances(selected?.name), {board: board, ready: ready} = useBoard({
|
|
1108
|
+
definition: selected,
|
|
1109
|
+
instances: instances.rows
|
|
1110
|
+
}), revealed = useRevealGate({
|
|
1111
|
+
loading: instances.loading,
|
|
1112
|
+
ready: ready
|
|
1113
|
+
}), landing = boardLandingName(selection);
|
|
1114
|
+
react.useEffect(() => {
|
|
1115
|
+
landing !== void 0 && onSelectWorkflow(landing, {
|
|
1116
|
+
replace: !0
|
|
1117
|
+
});
|
|
1118
|
+
}, [ landing, onSelectWorkflow ]);
|
|
1119
|
+
const selectedPayload = boardSelectedPayload(selection);
|
|
1120
|
+
/* @__PURE__ */
|
|
1121
|
+
return jsxRuntime.jsxs(ui.Flex, {
|
|
1122
|
+
direction: "column",
|
|
1123
|
+
flex: 1,
|
|
1124
|
+
style: {
|
|
1125
|
+
minHeight: 0
|
|
1126
|
+
},
|
|
1127
|
+
children: [
|
|
1128
|
+
/* @__PURE__ */ jsxRuntime.jsx(BoardControlsPortal, {
|
|
1129
|
+
definitionName: selected?.name,
|
|
1130
|
+
layout: layout,
|
|
1131
|
+
onOpenDefinition: onOpenDefinition,
|
|
1132
|
+
onChangeLayout: next => {
|
|
1133
|
+
next !== layout && (telemetry.log(index.WorkflowBoardLayoutChanged, {
|
|
1134
|
+
layout: next
|
|
1135
|
+
}), setLayout(next));
|
|
1136
|
+
},
|
|
1137
|
+
onSelectWorkflow: onSelectWorkflow,
|
|
1138
|
+
options: boardWorkflowOptions(definitions ?? []),
|
|
1139
|
+
face: boardPickerFace({
|
|
1140
|
+
selection: selection,
|
|
1141
|
+
routeName: routeDefinition
|
|
1142
|
+
}),
|
|
1143
|
+
slot: filterSlot
|
|
1144
|
+
}),
|
|
1145
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
1146
|
+
direction: "column",
|
|
1147
|
+
flex: 1,
|
|
1148
|
+
gap: 2,
|
|
1149
|
+
style: {
|
|
1150
|
+
minHeight: 0
|
|
1151
|
+
},
|
|
1152
|
+
children: [ instances.unreadable.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1153
|
+
paddingX: TOOL_PANEL_PADDING,
|
|
1154
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.UnreadableDocsNote, {
|
|
1155
|
+
unreadable: instances.unreadable
|
|
1156
|
+
})
|
|
1157
|
+
}),
|
|
1158
|
+
/* @__PURE__ */ jsxRuntime.jsx(BoardBody, {
|
|
1159
|
+
bands: bands,
|
|
1160
|
+
board: board,
|
|
1161
|
+
error: error,
|
|
1162
|
+
layout: layout,
|
|
1163
|
+
loading: !revealed,
|
|
1164
|
+
selection: selection
|
|
1165
|
+
}), instances.truncated ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1166
|
+
paddingX: TOOL_PANEL_PADDING,
|
|
1167
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MutedNote, {
|
|
1168
|
+
text: BOARD_CAP_NOTE
|
|
1169
|
+
})
|
|
1170
|
+
}) : null ]
|
|
1171
|
+
}), selectedPayload === void 0 ? null :
|
|
1172
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.LogEventOnMount, {
|
|
1173
|
+
data: selectedPayload,
|
|
1174
|
+
event: index.WorkflowBoardWorkflowSelected
|
|
1175
|
+
}, selected?.name) ]
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
function BoardBody({bands: bands, board: board, error: error, layout: layout, loading: loading, selection: selection}) {
|
|
1180
|
+
return error !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(StatusBox, {
|
|
1181
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MutedNote, {
|
|
1182
|
+
text: `Could not load the deployed workflows: ${error}`
|
|
1183
|
+
})
|
|
1184
|
+
}) : selection.kind === "loading" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBox, {
|
|
1185
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(TabStatusRow, {
|
|
1186
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.LoadingRow, {
|
|
1187
|
+
label: "Loading workflows…"
|
|
1188
|
+
})
|
|
1189
|
+
})
|
|
1190
|
+
}) : selection.kind === "empty" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBox, {
|
|
1191
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.EmptyState, {
|
|
1192
|
+
description: "Deploy a workflow to see its documents here",
|
|
1193
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Search.SearchIcon, {}),
|
|
1194
|
+
title: "No workflows deployed"
|
|
1195
|
+
})
|
|
1196
|
+
}) : selection.kind === "unknown" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBox, {
|
|
1197
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.EmptyState, {
|
|
1198
|
+
description: `No deployed workflow is named “${selection.name}” — pick one above`,
|
|
1199
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Search.SearchIcon, {}),
|
|
1200
|
+
title: "Workflow not found"
|
|
1201
|
+
})
|
|
1202
|
+
}) : loading || board === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(StatusBox, {
|
|
1203
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(TabStatusRow, {
|
|
1204
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.LoadingRow, {
|
|
1205
|
+
label: "Loading documents…"
|
|
1206
|
+
})
|
|
1207
|
+
})
|
|
1208
|
+
}) : layout === "stack" ? /* @__PURE__ */ jsxRuntime.jsx(BoardStack, {
|
|
1209
|
+
bands: bands,
|
|
1210
|
+
board: board
|
|
1211
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(StageGroups, {
|
|
1212
|
+
board: board
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
function StatusBox({children: children}) {
|
|
1217
|
+
/* @__PURE__ */
|
|
1218
|
+
return jsxRuntime.jsx(ui.Flex, {
|
|
1219
|
+
direction: "column",
|
|
1220
|
+
flex: 1,
|
|
1221
|
+
paddingX: TOOL_PANEL_PADDING,
|
|
1222
|
+
children: children
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
|
|
25
1226
|
function definitionCatalog(args) {
|
|
1227
|
+
const rejected = [ ...args.issues.values() ];
|
|
26
1228
|
return args.definitions.map(definition => ({
|
|
27
1229
|
name: definition.name,
|
|
28
1230
|
title: definition.title ?? definition.name,
|
|
29
1231
|
description: definition.description,
|
|
30
1232
|
activeCount: args.inFlight.filter(instance => instance.definition === definition.name).length,
|
|
31
|
-
docTypes: [ ...new Set(args.mappings.filter(mapping => mapping.definition === definition.name).map(mapping => mapping.docType)) ]
|
|
32
|
-
|
|
1233
|
+
docTypes: [ ...new Set(args.mappings.filter(mapping => mapping.definition === definition.name).map(mapping => mapping.docType)) ],
|
|
1234
|
+
brokenBindings: rejected.filter(issue => issue.definition === definition.name && issue.version === definition.version).map(issue => ({
|
|
1235
|
+
docType: issue.docType,
|
|
1236
|
+
detail: index.mappingIssueDetail(issue)
|
|
1237
|
+
})).sort((a, b) => a.docType.localeCompare(b.docType))
|
|
1238
|
+
})).sort(byTitleThenName);
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
function undeployedWorkflowNotices(args) {
|
|
1242
|
+
return [ ...args.issues.values() ].filter(index.namesNoDeployedDefinition).sort((a, b) => a.definition.localeCompare(b.definition) || a.docType.localeCompare(b.docType)).map(issue => `“${issue.definition}” is set up to run on ${args.titleOf(issue.docType) ?? issue.docType} documents, but no deployed workflow has that name`);
|
|
33
1243
|
}
|
|
34
1244
|
|
|
35
1245
|
function docTypeLabels(docTypes, titleOf) {
|
|
36
1246
|
return docTypes.map(name => ({
|
|
37
1247
|
name: name,
|
|
38
1248
|
title: titleOf(name) ?? name
|
|
39
|
-
})).sort(
|
|
1249
|
+
})).sort(byTitleThenName);
|
|
40
1250
|
}
|
|
41
1251
|
|
|
42
1252
|
function startPhrase(definition) {
|
|
43
|
-
if (definition.lifecycle === "child") return "
|
|
1253
|
+
if (definition.lifecycle === "child") return "Started by a parent workflow";
|
|
44
1254
|
if (workflowEngine.startKindOf(definition) === "autonomous") return "Starts automatically";
|
|
45
1255
|
const subject = (definition.fields ?? []).find(workflowEngine.isSubjectEntry);
|
|
46
1256
|
return subject !== void 0 && workflowEngine.isInputSourced(subject) ? "Started manually, from a document" : "Started manually";
|
|
@@ -50,6 +1260,37 @@ function deployedAtOf(definition) {
|
|
|
50
1260
|
return typeof definition._updatedAt == "string" ? definition._updatedAt : void 0;
|
|
51
1261
|
}
|
|
52
1262
|
|
|
1263
|
+
function deployedPhrase(definition) {
|
|
1264
|
+
const deployedAt = deployedAtOf(definition);
|
|
1265
|
+
if (deployedAt === void 0) return `v${definition.version}`;
|
|
1266
|
+
const ago = index.formatTimeAgo(deployedAt);
|
|
1267
|
+
return ago === "" ? index.formatShortDateTime(deployedAt) : `${index.formatShortDateTime(deployedAt)} (${ago})`;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
function DetailNotFound({back: back, message: message}) {
|
|
1271
|
+
/* @__PURE__ */
|
|
1272
|
+
return jsxRuntime.jsxs(ui.Stack, {
|
|
1273
|
+
gap: 4,
|
|
1274
|
+
children: [
|
|
1275
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1276
|
+
muted: !0,
|
|
1277
|
+
size: 1,
|
|
1278
|
+
children: message
|
|
1279
|
+
}),
|
|
1280
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
1281
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
1282
|
+
fontSize: 1,
|
|
1283
|
+
gap: 2,
|
|
1284
|
+
icon: ArrowLeft.ArrowLeftIcon,
|
|
1285
|
+
mode: "ghost",
|
|
1286
|
+
onClick: back.go,
|
|
1287
|
+
padding: 2,
|
|
1288
|
+
text: back.label
|
|
1289
|
+
})
|
|
1290
|
+
}) ]
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
|
|
53
1294
|
function DetailTitle({busy: busy = !1, documentGdr: documentGdr, title: title}) {
|
|
54
1295
|
const chipPullback = -index.useSpaceToken(1);
|
|
55
1296
|
/* @__PURE__ */
|
|
@@ -84,7 +1325,8 @@ function DetailTitle({busy: busy = !1, documentGdr: documentGdr, title: title})
|
|
|
84
1325
|
},
|
|
85
1326
|
children: /* @__PURE__ */ jsxRuntime.jsx(index.DocPreviewLink, {
|
|
86
1327
|
gdr: documentGdr,
|
|
87
|
-
layout: "inline"
|
|
1328
|
+
layout: "inline",
|
|
1329
|
+
source: "detail-title"
|
|
88
1330
|
})
|
|
89
1331
|
}) ]
|
|
90
1332
|
}),
|
|
@@ -94,46 +1336,59 @@ function DetailTitle({busy: busy = !1, documentGdr: documentGdr, title: title})
|
|
|
94
1336
|
});
|
|
95
1337
|
}
|
|
96
1338
|
|
|
97
|
-
const
|
|
1339
|
+
const INSTANCE_CAP_COUNT_NOTE = `Counts from the latest ${INSTANCE_CAP} workflows — older ones aren’t counted.`, NEWEST_INSTANCES = {
|
|
1340
|
+
includeCompleted: !0
|
|
1341
|
+
};
|
|
98
1342
|
|
|
99
|
-
function
|
|
100
|
-
const {
|
|
101
|
-
return react.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
seq: seq,
|
|
109
|
-
rows: latest
|
|
110
|
-
}), cancelled || (setDefinitions(latest), setError(void 0));
|
|
111
|
-
})().catch(err => {
|
|
112
|
-
cancelled || setError(index.describeError(err));
|
|
113
|
-
}), () => {
|
|
114
|
-
cancelled = !0;
|
|
115
|
-
};
|
|
116
|
-
}, [ engine ]), {
|
|
117
|
-
definitions: definitions,
|
|
118
|
-
error: error
|
|
119
|
-
};
|
|
1343
|
+
function useToolInstances() {
|
|
1344
|
+
const {rows: rows, truncated: truncated, loading: loading, unreadable: unreadable} = useCappedInstances(NEWEST_INSTANCES);
|
|
1345
|
+
return react.useMemo(() => ({
|
|
1346
|
+
inFlight: rows.filter(instance => workflowEngine.terminalState(instance) === "in-flight"),
|
|
1347
|
+
settled: rows.filter(instance => workflowEngine.terminalState(instance) !== "in-flight"),
|
|
1348
|
+
truncated: truncated,
|
|
1349
|
+
loading: loading,
|
|
1350
|
+
unreadable: unreadable
|
|
1351
|
+
}), [ rows, truncated, loading, unreadable ]);
|
|
120
1352
|
}
|
|
121
1353
|
|
|
122
|
-
function DefinitionDetail({definitionName: definitionName}) {
|
|
123
|
-
const {definitions: definitions, error: error} = useDeployedDefinitions(),
|
|
124
|
-
|
|
125
|
-
|
|
1354
|
+
function DefinitionDetail({definitionName: definitionName, backToList: backToList}) {
|
|
1355
|
+
const {definitions: definitions, error: error} = useDeployedDefinitions(), definition = definitions?.find(row => row.name === definitionName), loading = definitions === void 0 && error === void 0, viewed = loading || error !== void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(index.LogEventOnMount, {
|
|
1356
|
+
data: {
|
|
1357
|
+
found: definition !== void 0,
|
|
1358
|
+
...index.definitionFingerprint(definition)
|
|
1359
|
+
},
|
|
1360
|
+
event: index.WorkflowDefinitionDetailViewed
|
|
1361
|
+
});
|
|
1362
|
+
return !loading && error === void 0 && definition === void 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, {
|
|
1363
|
+
paddingX: 3,
|
|
1364
|
+
children: [ viewed,
|
|
1365
|
+
/* @__PURE__ */ jsxRuntime.jsx(TabStatusRow, {
|
|
1366
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DetailNotFound, {
|
|
1367
|
+
back: backToList,
|
|
1368
|
+
message: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
1369
|
+
children: [ "Unable to find a definition with name “",
|
|
1370
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", {
|
|
1371
|
+
children: definitionName
|
|
1372
|
+
}), "”." ]
|
|
1373
|
+
})
|
|
1374
|
+
})
|
|
1375
|
+
}) ]
|
|
1376
|
+
}) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
126
1377
|
direction: "column",
|
|
127
1378
|
height: "fill",
|
|
128
1379
|
overflow: "hidden",
|
|
129
|
-
children: [
|
|
1380
|
+
children: [ viewed,
|
|
130
1381
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
131
1382
|
flex: "none",
|
|
132
1383
|
paddingBottom: 2,
|
|
133
1384
|
paddingTop: 3,
|
|
134
1385
|
paddingX: 3,
|
|
135
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
136
|
-
|
|
1386
|
+
children: loading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1387
|
+
paddingLeft: 2,
|
|
1388
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.LoadingRow, {
|
|
1389
|
+
label: "Loading definition…"
|
|
1390
|
+
})
|
|
1391
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(DetailTitle, {
|
|
137
1392
|
title: definition?.title ?? definitionName
|
|
138
1393
|
})
|
|
139
1394
|
}),
|
|
@@ -141,125 +1396,176 @@ function DefinitionDetail({definitionName: definitionName}) {
|
|
|
141
1396
|
flex: 1,
|
|
142
1397
|
overflow: "auto",
|
|
143
1398
|
paddingX: 3,
|
|
144
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.
|
|
1399
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
1400
|
+
direction: "column",
|
|
145
1401
|
paddingBottom: 5,
|
|
146
1402
|
paddingLeft: 2,
|
|
147
|
-
paddingTop:
|
|
1403
|
+
paddingTop: 4,
|
|
148
1404
|
style: {
|
|
149
|
-
|
|
1405
|
+
boxSizing: "border-box",
|
|
1406
|
+
minHeight: "100%"
|
|
150
1407
|
},
|
|
151
1408
|
children: /* @__PURE__ */ jsxRuntime.jsx(DefinitionBody, {
|
|
152
1409
|
definition: definition,
|
|
153
|
-
error: error
|
|
154
|
-
loaded: definitions !== void 0
|
|
1410
|
+
error: error
|
|
155
1411
|
})
|
|
156
1412
|
})
|
|
157
1413
|
}) ]
|
|
158
1414
|
});
|
|
159
1415
|
}
|
|
160
1416
|
|
|
161
|
-
function DefinitionBody({definition: definition, error: error
|
|
1417
|
+
function DefinitionBody({definition: definition, error: error}) {
|
|
162
1418
|
return error !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(MutedNote, {
|
|
163
1419
|
text: `Could not load the deployed workflows: ${error}`
|
|
164
|
-
}) :
|
|
165
|
-
text: "No deployed workflow definition with this name — it may have been retracted."
|
|
166
|
-
}) : /* @__PURE__ */ jsxRuntime.jsx(DefinitionFacts, {
|
|
1420
|
+
}) : definition === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(DefinitionFacts, {
|
|
167
1421
|
definition: definition
|
|
168
|
-
})
|
|
169
|
-
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
function SetupIssues({bindings: bindings}) {
|
|
1426
|
+
const schema = sanity.useSchema();
|
|
1427
|
+
return bindings.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
1428
|
+
padding: 3,
|
|
1429
|
+
radius: 3,
|
|
1430
|
+
tone: "caution",
|
|
1431
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
1432
|
+
align: "flex-start",
|
|
1433
|
+
gap: 3,
|
|
1434
|
+
children: [
|
|
1435
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1436
|
+
size: 1,
|
|
1437
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WarningOutline.WarningOutlineIcon, {})
|
|
1438
|
+
}),
|
|
1439
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
1440
|
+
flex: 1,
|
|
1441
|
+
gap: 3,
|
|
1442
|
+
children: [
|
|
1443
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1444
|
+
size: 1,
|
|
1445
|
+
weight: "semibold",
|
|
1446
|
+
children: "Setup issue"
|
|
1447
|
+
}), bindings.map(binding => /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1448
|
+
size: 1,
|
|
1449
|
+
children: `${schema.get(binding.docType)?.title ?? binding.docType}: ${binding.detail}.`
|
|
1450
|
+
}, binding.docType)),
|
|
1451
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1452
|
+
muted: !0,
|
|
1453
|
+
size: 1,
|
|
1454
|
+
children: "Editors see this workflow disabled on these document types until a developer fixes it."
|
|
1455
|
+
}) ]
|
|
1456
|
+
}) ]
|
|
1457
|
+
})
|
|
170
1458
|
});
|
|
171
1459
|
}
|
|
172
1460
|
|
|
173
1461
|
function DefinitionFacts({definition: definition}) {
|
|
174
|
-
const {
|
|
1462
|
+
const {mappingIssues: mappingIssues, mappings: mappings} = index.useWorkflowContext(), schema = sanity.useSchema(), instances = useToolInstances(), snapshotWidth = index.useContainerToken(2), [row] = definitionCatalog({
|
|
175
1463
|
definitions: [ definition ],
|
|
176
1464
|
mappings: mappings,
|
|
177
|
-
inFlight:
|
|
1465
|
+
inFlight: instances.inFlight,
|
|
1466
|
+
issues: mappingIssues
|
|
178
1467
|
}), runsOn = docTypeLabels(row?.docTypes ?? [], name => schema.get(name)?.title).map(docType => docType.title);
|
|
179
1468
|
/* @__PURE__ */
|
|
180
|
-
return jsxRuntime.jsxs(ui.
|
|
1469
|
+
return jsxRuntime.jsxs(ui.Flex, {
|
|
1470
|
+
direction: "column",
|
|
1471
|
+
flex: 1,
|
|
181
1472
|
gap: 4,
|
|
182
|
-
children: [
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
size: 1,
|
|
187
|
-
children: [ deployedAt === void 0 ? `v${definition.version}` : index.formatDate(deployedAt), " ·", " ", binding.tag ]
|
|
188
|
-
})
|
|
189
|
-
}),
|
|
190
|
-
/* @__PURE__ */ jsxRuntime.jsx(index.MetaRow, {
|
|
191
|
-
label: "Trigger",
|
|
192
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
193
|
-
size: 1,
|
|
194
|
-
children: startPhrase(definition)
|
|
1473
|
+
children: [ row === void 0 || row.brokenBindings.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1474
|
+
flex: "none",
|
|
1475
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SetupIssues, {
|
|
1476
|
+
bindings: row.brokenBindings
|
|
195
1477
|
})
|
|
196
1478
|
}),
|
|
197
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
1479
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1480
|
+
flex: "none",
|
|
1481
|
+
style: {
|
|
1482
|
+
maxWidth: snapshotWidth
|
|
1483
|
+
},
|
|
1484
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
1485
|
+
gap: 4,
|
|
1486
|
+
children: [
|
|
1487
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.MetaRow, {
|
|
1488
|
+
label: "Deployed",
|
|
1489
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1490
|
+
size: 1,
|
|
1491
|
+
children: deployedPhrase(definition)
|
|
1492
|
+
})
|
|
1493
|
+
}),
|
|
1494
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.MetaRow, {
|
|
1495
|
+
label: "Active instances",
|
|
1496
|
+
children: instances.loading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1497
|
+
muted: !0,
|
|
1498
|
+
size: 1,
|
|
1499
|
+
children: "—"
|
|
1500
|
+
}) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
1501
|
+
gap: 2,
|
|
1502
|
+
children: [
|
|
1503
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1504
|
+
size: 1,
|
|
1505
|
+
children: row?.activeCount ?? 0
|
|
1506
|
+
}), instances.truncated ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1507
|
+
muted: !0,
|
|
1508
|
+
size: 1,
|
|
1509
|
+
children: INSTANCE_CAP_COUNT_NOTE
|
|
1510
|
+
}) : null ]
|
|
1511
|
+
})
|
|
1512
|
+
}),
|
|
1513
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.MetaRow, {
|
|
1514
|
+
label: "Trigger",
|
|
1515
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1516
|
+
size: 1,
|
|
1517
|
+
children: startPhrase(definition)
|
|
1518
|
+
})
|
|
1519
|
+
}),
|
|
1520
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.MetaRow, {
|
|
1521
|
+
label: "Document types",
|
|
1522
|
+
children: runsOn.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1523
|
+
muted: !0,
|
|
1524
|
+
size: 1,
|
|
1525
|
+
children: "No document types in this Studio"
|
|
1526
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1527
|
+
size: 1,
|
|
1528
|
+
children: runsOn.join(", ")
|
|
1529
|
+
})
|
|
1530
|
+
}),
|
|
1531
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.MetaRow, {
|
|
1532
|
+
label: "Description",
|
|
1533
|
+
children: definition.description === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1534
|
+
muted: !0,
|
|
1535
|
+
size: 1,
|
|
1536
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("em", {
|
|
1537
|
+
children: "No description"
|
|
1538
|
+
})
|
|
1539
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1540
|
+
size: 1,
|
|
1541
|
+
style: {
|
|
1542
|
+
whiteSpace: "pre-wrap"
|
|
1543
|
+
},
|
|
1544
|
+
children: definition.description
|
|
1545
|
+
})
|
|
1546
|
+
}) ]
|
|
206
1547
|
})
|
|
207
1548
|
}),
|
|
208
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
1549
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
1550
|
+
direction: "column",
|
|
1551
|
+
flex: 1,
|
|
1552
|
+
style: {
|
|
1553
|
+
minHeight: 340
|
|
1554
|
+
},
|
|
1555
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.MetaRow, {
|
|
1556
|
+
fillHeight: !0,
|
|
1557
|
+
label: "Stages",
|
|
1558
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(workflowDiagram.WorkflowDiagram, {
|
|
1559
|
+
definition: definition,
|
|
1560
|
+
explain: !0,
|
|
1561
|
+
fill: !0,
|
|
1562
|
+
height: "100%"
|
|
215
1563
|
})
|
|
216
|
-
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
217
|
-
size: 1,
|
|
218
|
-
style: {
|
|
219
|
-
whiteSpace: "pre-wrap"
|
|
220
|
-
},
|
|
221
|
-
children: definition.description
|
|
222
1564
|
})
|
|
223
|
-
}),
|
|
224
|
-
/* @__PURE__ */ jsxRuntime.jsx(workflowDiagram.WorkflowDiagram, {
|
|
225
|
-
definition: definition,
|
|
226
|
-
explain: !0,
|
|
227
|
-
height: 340
|
|
228
1565
|
}) ]
|
|
229
1566
|
});
|
|
230
1567
|
}
|
|
231
1568
|
|
|
232
|
-
function TabStatusRow({children: children}) {
|
|
233
|
-
/* @__PURE__ */
|
|
234
|
-
return jsxRuntime.jsx(ui.Box, {
|
|
235
|
-
paddingLeft: 2,
|
|
236
|
-
paddingY: 3,
|
|
237
|
-
children: children
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const INSTANCE_CAP = 200, NEWEST_INSTANCES = {
|
|
242
|
-
includeCompleted: !0,
|
|
243
|
-
limit: INSTANCE_CAP
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
function useToolInstances() {
|
|
247
|
-
const {engine: engine} = index.useWorkflowContext(), {instances: instances, loading: loading, unreadable: unreadable} = workflowStudio.useWorkflowInstances({
|
|
248
|
-
engine: engine,
|
|
249
|
-
filter: NEWEST_INSTANCES
|
|
250
|
-
});
|
|
251
|
-
return react.useMemo(() => {
|
|
252
|
-
const rows = instances ?? [];
|
|
253
|
-
return {
|
|
254
|
-
inFlight: rows.filter(instance => workflowEngine.terminalState(instance) === "in-flight"),
|
|
255
|
-
settled: rows.filter(instance => workflowEngine.terminalState(instance) !== "in-flight"),
|
|
256
|
-
truncated: rows.length + unreadable.length === INSTANCE_CAP,
|
|
257
|
-
loading: loading,
|
|
258
|
-
unreadable: unreadable
|
|
259
|
-
};
|
|
260
|
-
}, [ instances, loading, unreadable ]);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
1569
|
const MAX_VISIBLE_DOC_TYPES = 4, COLUMNS = {
|
|
264
1570
|
definition: 6,
|
|
265
1571
|
instances: 2,
|
|
@@ -276,7 +1582,12 @@ function Col({flex: flex, children: children}) {
|
|
|
276
1582
|
}
|
|
277
1583
|
|
|
278
1584
|
function DefinitionsTab({onOpenDefinition: onOpenDefinition}) {
|
|
279
|
-
const {definitions: definitions, error: error} = useDeployedDefinitions(), {mappings: mappings} = index.useWorkflowContext(), instances = useToolInstances()
|
|
1585
|
+
const {definitions: definitions, error: error} = useDeployedDefinitions(), {mappingIssues: mappingIssues, mappings: mappings} = index.useWorkflowContext(), schema = sanity.useSchema(), instances = useToolInstances(), undeployed = /* @__PURE__ */ jsxRuntime.jsx(UndeployedWorkflows, {
|
|
1586
|
+
notices: undeployedWorkflowNotices({
|
|
1587
|
+
issues: mappingIssues,
|
|
1588
|
+
titleOf: name => schema.get(name)?.title
|
|
1589
|
+
})
|
|
1590
|
+
});
|
|
280
1591
|
if (error !== void 0) /* @__PURE__ */
|
|
281
1592
|
return jsxRuntime.jsx(TabStatusRow, {
|
|
282
1593
|
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
@@ -292,25 +1603,32 @@ function DefinitionsTab({onOpenDefinition: onOpenDefinition}) {
|
|
|
292
1603
|
})
|
|
293
1604
|
});
|
|
294
1605
|
if (definitions.length === 0) /* @__PURE__ */
|
|
295
|
-
return jsxRuntime.
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
1606
|
+
return jsxRuntime.jsxs(ui.Flex, {
|
|
1607
|
+
direction: "column",
|
|
1608
|
+
flex: 1,
|
|
1609
|
+
gap: 3,
|
|
1610
|
+
paddingBottom: 4,
|
|
1611
|
+
paddingTop: 3,
|
|
1612
|
+
children: [ undeployed,
|
|
1613
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.EmptyState, {
|
|
1614
|
+
description: "Workflow definitions deployed to this project will appear here",
|
|
1615
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Transfer.TransferIcon, {}),
|
|
1616
|
+
title: "No definitions deployed"
|
|
1617
|
+
}) ]
|
|
301
1618
|
});
|
|
302
1619
|
const rows = definitionCatalog({
|
|
303
1620
|
definitions: definitions,
|
|
304
1621
|
mappings: mappings,
|
|
305
|
-
inFlight: instances.inFlight
|
|
1622
|
+
inFlight: instances.inFlight,
|
|
1623
|
+
issues: mappingIssues
|
|
306
1624
|
}), active = rows.reduce((sum, row) => sum + row.activeCount, 0);
|
|
307
1625
|
/* @__PURE__ */
|
|
308
1626
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
309
1627
|
gap: 3,
|
|
310
1628
|
paddingBottom: 4,
|
|
311
|
-
|
|
1629
|
+
paddingTop: 3,
|
|
1630
|
+
children: [ undeployed,
|
|
312
1631
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
313
|
-
paddingTop: 3,
|
|
314
1632
|
paddingX: 2,
|
|
315
1633
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
316
1634
|
align: "center",
|
|
@@ -397,7 +1715,7 @@ function DefinitionsTab({onOpenDefinition: onOpenDefinition}) {
|
|
|
397
1715
|
}, row.name))
|
|
398
1716
|
}) ]
|
|
399
1717
|
}), instances.truncated ? /* @__PURE__ */ jsxRuntime.jsx(MutedNote, {
|
|
400
|
-
text:
|
|
1718
|
+
text: INSTANCE_CAP_COUNT_NOTE
|
|
401
1719
|
}) : null ]
|
|
402
1720
|
});
|
|
403
1721
|
}
|
|
@@ -406,88 +1724,277 @@ function activeSummary(active) {
|
|
|
406
1724
|
return `${pluralize__default.default("active instance", active, !0)}`;
|
|
407
1725
|
}
|
|
408
1726
|
|
|
1727
|
+
const ROW_ISSUES_HINT = "This definition has issues";
|
|
1728
|
+
|
|
1729
|
+
function UndeployedWorkflows({notices: notices}) {
|
|
1730
|
+
return notices.length === 0 ? null :
|
|
1731
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Stack, {
|
|
1732
|
+
gap: 2,
|
|
1733
|
+
paddingBottom: 1,
|
|
1734
|
+
children: notices.map(notice => /* @__PURE__ */ jsxRuntime.jsx(index.CautionNote, {
|
|
1735
|
+
label: notice
|
|
1736
|
+
}, notice))
|
|
1737
|
+
});
|
|
1738
|
+
}
|
|
1739
|
+
|
|
409
1740
|
function DefinitionRow({countPending: countPending, onOpen: onOpen, row: row}) {
|
|
410
|
-
/* @__PURE__ */
|
|
411
|
-
return jsxRuntime.jsx(ui.Card, {
|
|
1741
|
+
const flagged = row.brokenBindings.length > 0, card = /* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
412
1742
|
as: "button",
|
|
413
1743
|
onClick: onOpen,
|
|
414
1744
|
paddingX: 2,
|
|
415
1745
|
paddingY: 3,
|
|
416
1746
|
radius: 2,
|
|
417
1747
|
style: {
|
|
418
|
-
textAlign: "left"
|
|
1748
|
+
textAlign: "left",
|
|
1749
|
+
width: "100%"
|
|
419
1750
|
},
|
|
1751
|
+
...flagged ? {
|
|
1752
|
+
tone: "caution"
|
|
1753
|
+
} : {},
|
|
420
1754
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
421
1755
|
align: "flex-start",
|
|
422
1756
|
gap: 4,
|
|
423
1757
|
children: [
|
|
424
1758
|
/* @__PURE__ */ jsxRuntime.jsx(Col, {
|
|
425
1759
|
flex: COLUMNS.definition,
|
|
426
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.
|
|
1760
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
1761
|
+
align: "flex-start",
|
|
1762
|
+
gap: 3,
|
|
1763
|
+
paddingLeft: flagged ? 1 : 0,
|
|
1764
|
+
children: [ flagged ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1765
|
+
size: 1,
|
|
1766
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WarningOutline.WarningOutlineIcon, {})
|
|
1767
|
+
}) : null,
|
|
1768
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
1769
|
+
flex: 1,
|
|
1770
|
+
gap: 3,
|
|
1771
|
+
style: {
|
|
1772
|
+
minWidth: 0
|
|
1773
|
+
},
|
|
1774
|
+
children: [
|
|
1775
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1776
|
+
size: 1,
|
|
1777
|
+
weight: "semibold",
|
|
1778
|
+
children: row.title
|
|
1779
|
+
}), row.description === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1780
|
+
muted: !0,
|
|
1781
|
+
size: 1,
|
|
1782
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("em", {
|
|
1783
|
+
children: "No description"
|
|
1784
|
+
})
|
|
1785
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1786
|
+
muted: !0,
|
|
1787
|
+
size: 1,
|
|
1788
|
+
children: row.description
|
|
1789
|
+
}) ]
|
|
1790
|
+
}) ]
|
|
1791
|
+
})
|
|
1792
|
+
}),
|
|
1793
|
+
/* @__PURE__ */ jsxRuntime.jsx(Col, {
|
|
1794
|
+
flex: COLUMNS.instances,
|
|
1795
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1796
|
+
muted: !0,
|
|
1797
|
+
size: 1,
|
|
1798
|
+
children: countPending ? "—" : `${row.activeCount} active`
|
|
1799
|
+
})
|
|
1800
|
+
}),
|
|
1801
|
+
/* @__PURE__ */ jsxRuntime.jsx(Col, {
|
|
1802
|
+
flex: COLUMNS.docTypes,
|
|
1803
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DocTypeChips, {
|
|
1804
|
+
docTypes: row.docTypes
|
|
1805
|
+
})
|
|
1806
|
+
}) ]
|
|
1807
|
+
})
|
|
1808
|
+
});
|
|
1809
|
+
return flagged ? /* @__PURE__ */ jsxRuntime.jsx(index.HoverHint, {
|
|
1810
|
+
fill: !0,
|
|
1811
|
+
text: ROW_ISSUES_HINT,
|
|
1812
|
+
children: card
|
|
1813
|
+
}) : card;
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
function DocTypeChips({docTypes: docTypes}) {
|
|
1817
|
+
const schema = sanity.useSchema(), badgeTrim = index.useBadgeCapTrim();
|
|
1818
|
+
if (docTypes.length === 0) /* @__PURE__ */
|
|
1819
|
+
return jsxRuntime.jsx(ui.Text, {
|
|
1820
|
+
muted: !0,
|
|
1821
|
+
size: 1,
|
|
1822
|
+
children: "—"
|
|
1823
|
+
});
|
|
1824
|
+
const labels = docTypeLabels(docTypes, name => schema.get(name)?.title), shown = labels.slice(0, MAX_VISIBLE_DOC_TYPES), overflow = labels.length - shown.length;
|
|
1825
|
+
/* @__PURE__ */
|
|
1826
|
+
return jsxRuntime.jsxs(ui.Flex, {
|
|
1827
|
+
align: "center",
|
|
1828
|
+
gap: 2,
|
|
1829
|
+
style: badgeTrim,
|
|
1830
|
+
wrap: "wrap",
|
|
1831
|
+
children: [ shown.map(docType =>
|
|
1832
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Badge, {
|
|
1833
|
+
fontSize: 1,
|
|
1834
|
+
style: {
|
|
1835
|
+
minWidth: 0
|
|
1836
|
+
},
|
|
1837
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
1838
|
+
style: {
|
|
1839
|
+
display: "block",
|
|
1840
|
+
overflow: "hidden",
|
|
1841
|
+
textOverflow: "ellipsis",
|
|
1842
|
+
whiteSpace: "nowrap"
|
|
1843
|
+
},
|
|
1844
|
+
children: docType.title
|
|
1845
|
+
})
|
|
1846
|
+
}, docType.name)), overflow > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, {
|
|
1847
|
+
muted: !0,
|
|
1848
|
+
size: 1,
|
|
1849
|
+
children: [ "+", overflow, " more" ]
|
|
1850
|
+
}) : null ]
|
|
1851
|
+
});
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
function normalizeAbortReason(raw) {
|
|
1855
|
+
const trimmed = raw.trim();
|
|
1856
|
+
return trimmed === "" ? void 0 : trimmed;
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
function abortedToast(title) {
|
|
1860
|
+
return {
|
|
1861
|
+
id: index.TOAST_ID.abort,
|
|
1862
|
+
status: "info",
|
|
1863
|
+
title: `Aborted “${title}”`
|
|
1864
|
+
};
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
function abortAlreadySettledToast(title) {
|
|
1868
|
+
return {
|
|
1869
|
+
id: index.TOAST_ID.abort,
|
|
1870
|
+
status: "info",
|
|
1871
|
+
title: `“${title}” had already finished`,
|
|
1872
|
+
description: "Nothing was aborted — the workflow reached a terminal state first."
|
|
1873
|
+
};
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
function abortUnconfirmedToast(args) {
|
|
1877
|
+
return {
|
|
1878
|
+
id: index.TOAST_ID.abort,
|
|
1879
|
+
status: "warning",
|
|
1880
|
+
title: `Couldn’t confirm “${args.title}” was aborted`,
|
|
1881
|
+
description: `${index.describeError(args.err)} — the abort may still have committed, so check the workflow’s state before trying again.`
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
function AbortWorkflowDialog({entry: entry, onClose: onClose}) {
|
|
1886
|
+
const {engine: engine} = index.useWorkflowContext(), definition = index.useDefinition(entry), toast = index.useWorkflowToast(), [typedReason, setTypedReason] = react.useState(""), [pending, setPending] = react.useState(!1), {instance: instance} = entry, title = index.instanceTitle(instance, definition), reason = normalizeAbortReason(typedReason), reasonInputId = `abort-workflow-reason-${instance._id}`, confirm = async () => {
|
|
1887
|
+
if (reason !== void 0) {
|
|
1888
|
+
setPending(!0);
|
|
1889
|
+
try {
|
|
1890
|
+
const {changed: changed} = await engine.abortInstance({
|
|
1891
|
+
instanceId: instance._id,
|
|
1892
|
+
reason: reason
|
|
1893
|
+
});
|
|
1894
|
+
toast.push(changed ? abortedToast(title) : abortAlreadySettledToast(title)), onClose();
|
|
1895
|
+
} catch (err) {
|
|
1896
|
+
toast.push(abortUnconfirmedToast({
|
|
1897
|
+
title: title,
|
|
1898
|
+
err: err
|
|
1899
|
+
})), setPending(!1);
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
};
|
|
1903
|
+
/* @__PURE__ */
|
|
1904
|
+
return jsxRuntime.jsx(ui.Dialog, {
|
|
1905
|
+
footer: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1906
|
+
padding: 3,
|
|
1907
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
1908
|
+
gap: 2,
|
|
1909
|
+
justify: "flex-end",
|
|
1910
|
+
children: [
|
|
1911
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
1912
|
+
disabled: pending,
|
|
1913
|
+
fontSize: 1,
|
|
1914
|
+
mode: "bleed",
|
|
1915
|
+
onClick: onClose,
|
|
1916
|
+
padding: 2,
|
|
1917
|
+
text: "Cancel"
|
|
1918
|
+
}),
|
|
1919
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
1920
|
+
disabled: reason === void 0,
|
|
1921
|
+
fontSize: 1,
|
|
1922
|
+
loading: pending,
|
|
1923
|
+
onClick: () => {
|
|
1924
|
+
confirm();
|
|
1925
|
+
},
|
|
1926
|
+
padding: 2,
|
|
1927
|
+
text: "Abort workflow",
|
|
1928
|
+
tone: "critical"
|
|
1929
|
+
}) ]
|
|
1930
|
+
})
|
|
1931
|
+
}),
|
|
1932
|
+
header: "Abort workflow",
|
|
1933
|
+
id: `abort-workflow-${instance._id}`,
|
|
1934
|
+
onClose: () => {
|
|
1935
|
+
pending || onClose();
|
|
1936
|
+
},
|
|
1937
|
+
width: 0,
|
|
1938
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1939
|
+
padding: 4,
|
|
1940
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
1941
|
+
gap: 5,
|
|
1942
|
+
children: [
|
|
1943
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, {
|
|
1944
|
+
size: 1,
|
|
1945
|
+
children: [ "Abort the ",
|
|
1946
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", {
|
|
1947
|
+
children: title
|
|
1948
|
+
}), " workflow? This cannot be undone." ]
|
|
1949
|
+
}),
|
|
1950
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
427
1951
|
gap: 3,
|
|
428
|
-
style: {
|
|
429
|
-
minWidth: 0
|
|
430
|
-
},
|
|
431
1952
|
children: [
|
|
432
1953
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1954
|
+
as: "label",
|
|
1955
|
+
htmlFor: reasonInputId,
|
|
433
1956
|
size: 1,
|
|
434
|
-
weight: "
|
|
435
|
-
children:
|
|
436
|
-
}),
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
size: 1,
|
|
445
|
-
children: row.description
|
|
1957
|
+
weight: "medium",
|
|
1958
|
+
children: "Reason"
|
|
1959
|
+
}),
|
|
1960
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TextInput, {
|
|
1961
|
+
autoFocus: !0,
|
|
1962
|
+
fontSize: 1,
|
|
1963
|
+
id: reasonInputId,
|
|
1964
|
+
onChange: event => setTypedReason(event.currentTarget.value),
|
|
1965
|
+
placeholder: "Why is this workflow being stopped?",
|
|
1966
|
+
value: typedReason
|
|
446
1967
|
}) ]
|
|
447
|
-
})
|
|
448
|
-
})
|
|
449
|
-
/* @__PURE__ */ jsxRuntime.jsx(Col, {
|
|
450
|
-
flex: COLUMNS.instances,
|
|
451
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
452
|
-
muted: !0,
|
|
453
|
-
size: 1,
|
|
454
|
-
children: countPending ? "—" : `${row.activeCount} active`
|
|
455
|
-
})
|
|
456
|
-
}),
|
|
457
|
-
/* @__PURE__ */ jsxRuntime.jsx(Col, {
|
|
458
|
-
flex: COLUMNS.docTypes,
|
|
459
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(DocTypeChips, {
|
|
460
|
-
docTypes: row.docTypes
|
|
461
|
-
})
|
|
462
|
-
}) ]
|
|
1968
|
+
}) ]
|
|
1969
|
+
})
|
|
463
1970
|
})
|
|
464
1971
|
});
|
|
465
1972
|
}
|
|
466
1973
|
|
|
467
|
-
function
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
children: "—"
|
|
474
|
-
});
|
|
475
|
-
const labels = docTypeLabels(docTypes, name => schema.get(name)?.title), shown = labels.slice(0, MAX_VISIBLE_DOC_TYPES), overflow = labels.length - shown.length;
|
|
476
|
-
/* @__PURE__ */
|
|
477
|
-
return jsxRuntime.jsxs(ui.Flex, {
|
|
478
|
-
align: "center",
|
|
479
|
-
gap: 2,
|
|
480
|
-
style: badgeTrim,
|
|
481
|
-
wrap: "wrap",
|
|
482
|
-
children: [ shown.map(docType => /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, {
|
|
483
|
-
fontSize: 1,
|
|
484
|
-
children: docType.title
|
|
485
|
-
}, docType.name)), overflow > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, {
|
|
486
|
-
muted: !0,
|
|
1974
|
+
function AbortWorkflowSection({entry: entry}) {
|
|
1975
|
+
const [aborting, setAborting] = react.useState(!1);
|
|
1976
|
+
return index.isLiveEntry(entry) ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
1977
|
+
gap: 4,
|
|
1978
|
+
children: [
|
|
1979
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
487
1980
|
size: 1,
|
|
488
|
-
|
|
1981
|
+
weight: "semibold",
|
|
1982
|
+
children: "Manage workflow"
|
|
1983
|
+
}),
|
|
1984
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
1985
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
1986
|
+
fontSize: 1,
|
|
1987
|
+
mode: "ghost",
|
|
1988
|
+
onClick: () => setAborting(!0),
|
|
1989
|
+
padding: 2,
|
|
1990
|
+
text: "Abort workflow…",
|
|
1991
|
+
tone: "critical"
|
|
1992
|
+
})
|
|
1993
|
+
}), aborting ? /* @__PURE__ */ jsxRuntime.jsx(AbortWorkflowDialog, {
|
|
1994
|
+
entry: entry,
|
|
1995
|
+
onClose: () => setAborting(!1)
|
|
489
1996
|
}) : null ]
|
|
490
|
-
});
|
|
1997
|
+
}) : null;
|
|
491
1998
|
}
|
|
492
1999
|
|
|
493
2000
|
function makeTitleResolver(definition) {
|
|
@@ -562,19 +2069,21 @@ function historyLine(h, titles) {
|
|
|
562
2069
|
}
|
|
563
2070
|
|
|
564
2071
|
function PendingEffectRows({instance: instance, now: now}) {
|
|
565
|
-
const {drainEffectsFor: drainEffectsFor, completeEffectFor: completeEffectFor, effectHandlers: effectHandlers} = index.useWorkflowContext(), toast = index.
|
|
2072
|
+
const {drainEffectsFor: drainEffectsFor, completeEffectFor: completeEffectFor, effectHandlers: effectHandlers} = index.useWorkflowContext(), toast = index.useWorkflowToast(), [busy, setBusy] = react.useState(!1), pending = instance.pendingEffects ?? [];
|
|
566
2073
|
if (pending.length === 0) return null;
|
|
567
2074
|
const runRegistered = async () => {
|
|
568
2075
|
setBusy(!0);
|
|
569
2076
|
try {
|
|
570
2077
|
await drainEffectsFor(instance._id), toast.push({
|
|
571
|
-
|
|
572
|
-
|
|
2078
|
+
id: index.TOAST_ID.effectsDrain,
|
|
2079
|
+
status: "info",
|
|
2080
|
+
title: "Ran the registered handlers"
|
|
573
2081
|
});
|
|
574
2082
|
} catch (err) {
|
|
575
2083
|
toast.push({
|
|
2084
|
+
id: index.TOAST_ID.effectsDrain,
|
|
576
2085
|
status: "error",
|
|
577
|
-
title: "
|
|
2086
|
+
title: "Failed to run pending effects",
|
|
578
2087
|
description: index.describeError(err)
|
|
579
2088
|
});
|
|
580
2089
|
} finally {
|
|
@@ -588,13 +2097,15 @@ function PendingEffectRows({instance: instance, now: now}) {
|
|
|
588
2097
|
status: status,
|
|
589
2098
|
detail: "Resolved in Studio"
|
|
590
2099
|
}), toast.push({
|
|
591
|
-
|
|
592
|
-
|
|
2100
|
+
id: index.TOAST_ID.effectResolve,
|
|
2101
|
+
status: "info",
|
|
2102
|
+
title: `Effect marked as ${status}`
|
|
593
2103
|
});
|
|
594
2104
|
} catch (err) {
|
|
595
2105
|
toast.push({
|
|
2106
|
+
id: index.TOAST_ID.effectResolve,
|
|
596
2107
|
status: "error",
|
|
597
|
-
title: "
|
|
2108
|
+
title: "Failed to resolve the effect",
|
|
598
2109
|
description: index.describeError(err)
|
|
599
2110
|
});
|
|
600
2111
|
} finally {
|
|
@@ -824,13 +2335,7 @@ function FeedGlyph({hint: hint, icon: icon}) {
|
|
|
824
2335
|
});
|
|
825
2336
|
}
|
|
826
2337
|
|
|
827
|
-
function
|
|
828
|
-
const seen = /* @__PURE__ */ new Map;
|
|
829
|
-
for (const ref of workflowEngine.entryDocRefs(instance.fields)) seen.has(ref.id) || seen.set(ref.id, ref);
|
|
830
|
-
return [ ...seen.values() ];
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
function WorkflowInstanceDetail({instanceId: instanceId, onBack: onBack}) {
|
|
2338
|
+
function WorkflowInstanceDetail({instanceId: instanceId, backToList: backToList}) {
|
|
834
2339
|
const entry = index.useWorkflowInstanceEntry(instanceId);
|
|
835
2340
|
index.useLogEventOnMount(index.WorkflowInstanceDetailViewed, {
|
|
836
2341
|
instanceId: instanceId
|
|
@@ -849,9 +2354,14 @@ function WorkflowInstanceDetail({instanceId: instanceId, onBack: onBack}) {
|
|
|
849
2354
|
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
850
2355
|
paddingX: 3,
|
|
851
2356
|
children: /* @__PURE__ */ jsxRuntime.jsx(TabStatusRow, {
|
|
852
|
-
children: graceOver ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
853
|
-
|
|
854
|
-
|
|
2357
|
+
children: graceOver ? /* @__PURE__ */ jsxRuntime.jsx(DetailNotFound, {
|
|
2358
|
+
back: backToList,
|
|
2359
|
+
message: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
2360
|
+
children: [ "Unable to find workflow with id “",
|
|
2361
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", {
|
|
2362
|
+
children: instanceId
|
|
2363
|
+
}), "”." ]
|
|
2364
|
+
})
|
|
855
2365
|
}) : /* @__PURE__ */ jsxRuntime.jsx(index.LoadingRow, {
|
|
856
2366
|
label: "Loading workflow…"
|
|
857
2367
|
})
|
|
@@ -859,29 +2369,6 @@ function WorkflowInstanceDetail({instanceId: instanceId, onBack: onBack}) {
|
|
|
859
2369
|
});
|
|
860
2370
|
}
|
|
861
2371
|
|
|
862
|
-
function NotFound({id: id, onBack: onBack}) {
|
|
863
|
-
/* @__PURE__ */
|
|
864
|
-
return jsxRuntime.jsxs(ui.Stack, {
|
|
865
|
-
gap: 4,
|
|
866
|
-
children: [
|
|
867
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, {
|
|
868
|
-
muted: !0,
|
|
869
|
-
size: 1,
|
|
870
|
-
children: [ "No workflow with id “", id, "” — it may have been deleted." ]
|
|
871
|
-
}),
|
|
872
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
873
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
874
|
-
fontSize: 1,
|
|
875
|
-
icon: ArrowLeft.ArrowLeftIcon,
|
|
876
|
-
mode: "ghost",
|
|
877
|
-
onClick: onBack,
|
|
878
|
-
padding: 2,
|
|
879
|
-
text: "Back to workflows"
|
|
880
|
-
})
|
|
881
|
-
}) ]
|
|
882
|
-
});
|
|
883
|
-
}
|
|
884
|
-
|
|
885
2372
|
function InstanceDetailPanel({entry: entry}) {
|
|
886
2373
|
const definition = index.useDefinition(entry), snapshotWidth = index.useContainerToken(2), [openActivity, setOpenActivity] = react.useState(null), {instance: instance, ready: ready} = entry;
|
|
887
2374
|
return react.useEffect(() => {
|
|
@@ -924,7 +2411,11 @@ function InstanceDetailPanel({entry: entry}) {
|
|
|
924
2411
|
onOpenActivity: name => setOpenActivity({
|
|
925
2412
|
stage: instance.currentStage,
|
|
926
2413
|
activityName: name
|
|
927
|
-
})
|
|
2414
|
+
}),
|
|
2415
|
+
surface: "tool-instance-detail"
|
|
2416
|
+
}),
|
|
2417
|
+
/* @__PURE__ */ jsxRuntime.jsx(AbortWorkflowSection, {
|
|
2418
|
+
entry: entry
|
|
928
2419
|
}),
|
|
929
2420
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
930
2421
|
gap: 4,
|
|
@@ -1028,217 +2519,76 @@ function DefinitionPickerPanel({onPick: onPick}) {
|
|
|
1028
2519
|
overflowY: "auto"
|
|
1029
2520
|
},
|
|
1030
2521
|
children: visible.map(definition => /* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
1031
|
-
as: "button",
|
|
1032
|
-
onClick: () => onPick(definition),
|
|
1033
|
-
padding: 3,
|
|
1034
|
-
radius: 2,
|
|
1035
|
-
style: {
|
|
1036
|
-
cursor: "pointer",
|
|
1037
|
-
textAlign: "left"
|
|
1038
|
-
},
|
|
1039
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
1040
|
-
gap: 2,
|
|
1041
|
-
children: [
|
|
1042
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1043
|
-
size: 1,
|
|
1044
|
-
weight: "medium",
|
|
1045
|
-
children: definition.title
|
|
1046
|
-
}), definition.description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1047
|
-
muted: !0,
|
|
1048
|
-
size: 1,
|
|
1049
|
-
textOverflow: "ellipsis",
|
|
1050
|
-
children: definition.description
|
|
1051
|
-
}) : null ]
|
|
1052
|
-
})
|
|
1053
|
-
}, definition.name))
|
|
1054
|
-
}) ]
|
|
1055
|
-
})
|
|
1056
|
-
});
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
function ToolActivityDialog({target: target, onClose: onClose}) {
|
|
1060
|
-
const entry = index.useWorkflowInstanceEntry(target.instanceId), definition = index.useDefinition(entry), resolvedOnce = react.useRef(!1);
|
|
1061
|
-
return entry && (resolvedOnce.current = !0), react.useEffect(() => {
|
|
1062
|
-
resolvedOnce.current && index.openActivityGone({
|
|
1063
|
-
entry: entry,
|
|
1064
|
-
target: target
|
|
1065
|
-
}) && onClose();
|
|
1066
|
-
}, [ entry, target, onClose ]), entry?.invalid ? /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, {
|
|
1067
|
-
header: "Workflow unavailable",
|
|
1068
|
-
id: "workflow-activity-detail",
|
|
1069
|
-
onClose: onClose,
|
|
1070
|
-
width: 1,
|
|
1071
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1072
|
-
padding: 4,
|
|
1073
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(index.InvalidDocNotice, {
|
|
1074
|
-
invalid: entry.invalid
|
|
1075
|
-
})
|
|
1076
|
-
})
|
|
1077
|
-
}) : entry?.evaluation ? /* @__PURE__ */ jsxRuntime.jsx(index.ActivityDetailDialog, {
|
|
1078
|
-
activityName: target.activityName,
|
|
1079
|
-
breadcrumb: index.instanceBreadcrumb(entry.instance, definition),
|
|
1080
|
-
definition: definition,
|
|
1081
|
-
document: documentRefsOf(entry.instance)[0],
|
|
1082
|
-
entry: entry,
|
|
1083
|
-
onClose: onClose,
|
|
1084
|
-
source: "tool-task-list"
|
|
1085
|
-
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, {
|
|
1086
|
-
header: "Loading activity…",
|
|
1087
|
-
id: "workflow-activity-detail",
|
|
1088
|
-
onClose: onClose,
|
|
1089
|
-
width: 1,
|
|
1090
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1091
|
-
padding: 4,
|
|
1092
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(index.LoadingRow, {
|
|
1093
|
-
label: "Fetching the live workflow state…"
|
|
1094
|
-
})
|
|
1095
|
-
})
|
|
1096
|
-
});
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
const GROUP_DEFAULT_OPEN = !0;
|
|
1100
|
-
|
|
1101
|
-
function instanceBandDefaultOpen(segment) {
|
|
1102
|
-
return segment === "for-me";
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
const UNGROUPED_BAND_KEY = "section:no-document", PAYLOAD_VERSION = 1, MAX_ENTRIES = 200;
|
|
1106
|
-
|
|
1107
|
-
function bandStateStorageKey(scope) {
|
|
1108
|
-
return `sanity.workflows.tool.bands:${scope}`;
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
function isRecord(value) {
|
|
1112
|
-
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
function bandEntryOf(value) {
|
|
1116
|
-
if (!isRecord(value)) return;
|
|
1117
|
-
const {open: open, touched: touched} = value;
|
|
1118
|
-
if (!(typeof open != "boolean" || typeof touched != "number") && Number.isFinite(touched)) return {
|
|
1119
|
-
open: open,
|
|
1120
|
-
touched: touched
|
|
1121
|
-
};
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
function parsePayload(raw) {
|
|
1125
|
-
try {
|
|
1126
|
-
const parsed = JSON.parse(raw);
|
|
1127
|
-
if (!isRecord(parsed) || parsed.version !== PAYLOAD_VERSION || !isRecord(parsed.bands)) return;
|
|
1128
|
-
const entries = [];
|
|
1129
|
-
for (const [key, value] of Object.entries(parsed.bands)) {
|
|
1130
|
-
const entry = bandEntryOf(value);
|
|
1131
|
-
if (entry === void 0) return;
|
|
1132
|
-
entries.push([ key, entry ]);
|
|
1133
|
-
}
|
|
1134
|
-
return Object.fromEntries(entries);
|
|
1135
|
-
} catch {
|
|
1136
|
-
return;
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
function readStored(storage, storageKey) {
|
|
1141
|
-
if (!storage) return {
|
|
1142
|
-
entries: void 0,
|
|
1143
|
-
corrupt: !1
|
|
1144
|
-
};
|
|
1145
|
-
let raw;
|
|
1146
|
-
try {
|
|
1147
|
-
raw = storage.getItem(storageKey);
|
|
1148
|
-
} catch {
|
|
1149
|
-
return {
|
|
1150
|
-
entries: void 0,
|
|
1151
|
-
corrupt: !1
|
|
1152
|
-
};
|
|
1153
|
-
}
|
|
1154
|
-
if (raw === null) return {
|
|
1155
|
-
entries: {},
|
|
1156
|
-
corrupt: !1
|
|
1157
|
-
};
|
|
1158
|
-
const entries = parsePayload(raw);
|
|
1159
|
-
return {
|
|
1160
|
-
entries: entries,
|
|
1161
|
-
corrupt: entries === void 0
|
|
1162
|
-
};
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
function writeStored(args) {
|
|
1166
|
-
if (!args.storage) return !1;
|
|
1167
|
-
try {
|
|
1168
|
-
return args.storage.setItem(args.storageKey, JSON.stringify({
|
|
1169
|
-
version: PAYLOAD_VERSION,
|
|
1170
|
-
bands: args.entries
|
|
1171
|
-
})), !0;
|
|
1172
|
-
} catch {
|
|
1173
|
-
return !1;
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
function baseEntries(args) {
|
|
1178
|
-
return args.stored === void 0 ? args.held : args.unpersisted ? mergeByTouched(args.stored, args.held) : args.stored;
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
|
-
function mergeByTouched(stored, held) {
|
|
1182
|
-
const merged = {
|
|
1183
|
-
...stored
|
|
1184
|
-
};
|
|
1185
|
-
for (const [key, entry] of Object.entries(held)) {
|
|
1186
|
-
const persisted = merged[key];
|
|
1187
|
-
(persisted === void 0 || entry.touched >= persisted.touched) && (merged[key] = entry);
|
|
1188
|
-
}
|
|
1189
|
-
return merged;
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
function prune(entries) {
|
|
1193
|
-
const held = Object.entries(entries);
|
|
1194
|
-
return held.length <= MAX_ENTRIES ? entries : Object.fromEntries(held.sort(([, a], [, b]) => b.touched - a.touched).slice(0, MAX_ENTRIES));
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
function togglesOf(entries) {
|
|
1198
|
-
return new Map(Object.entries(entries).map(([key, entry]) => [ key, entry.open ]));
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
function defaultStorage() {
|
|
1202
|
-
try {
|
|
1203
|
-
return globalThis.localStorage;
|
|
1204
|
-
} catch {
|
|
1205
|
-
return;
|
|
1206
|
-
}
|
|
2522
|
+
as: "button",
|
|
2523
|
+
onClick: () => onPick(definition),
|
|
2524
|
+
padding: 3,
|
|
2525
|
+
radius: 2,
|
|
2526
|
+
style: {
|
|
2527
|
+
cursor: "pointer",
|
|
2528
|
+
textAlign: "left"
|
|
2529
|
+
},
|
|
2530
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
2531
|
+
gap: 2,
|
|
2532
|
+
children: [
|
|
2533
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
2534
|
+
size: 1,
|
|
2535
|
+
weight: "medium",
|
|
2536
|
+
children: definition.title
|
|
2537
|
+
}), definition.description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
2538
|
+
muted: !0,
|
|
2539
|
+
size: 1,
|
|
2540
|
+
textOverflow: "ellipsis",
|
|
2541
|
+
children: definition.description
|
|
2542
|
+
}) : null ]
|
|
2543
|
+
})
|
|
2544
|
+
}, definition.name))
|
|
2545
|
+
}) ]
|
|
2546
|
+
})
|
|
2547
|
+
});
|
|
1207
2548
|
}
|
|
1208
2549
|
|
|
1209
|
-
function
|
|
1210
|
-
const
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
2550
|
+
function ToolActivityDialog({target: target, onClose: onClose}) {
|
|
2551
|
+
const entry = index.useWorkflowInstanceEntry(target.instanceId), definition = index.useDefinition(entry), resolvedOnce = react.useRef(!1);
|
|
2552
|
+
return entry && (resolvedOnce.current = !0), react.useEffect(() => {
|
|
2553
|
+
resolvedOnce.current && index.openActivityGone({
|
|
2554
|
+
entry: entry,
|
|
2555
|
+
target: target
|
|
2556
|
+
}) && onClose();
|
|
2557
|
+
}, [ entry, target, onClose ]), entry?.invalid ? /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, {
|
|
2558
|
+
header: "Workflow unavailable",
|
|
2559
|
+
id: "workflow-activity-detail",
|
|
2560
|
+
onClose: onClose,
|
|
2561
|
+
width: 1,
|
|
2562
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
2563
|
+
padding: 4,
|
|
2564
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.InvalidDocNotice, {
|
|
2565
|
+
invalid: entry.invalid
|
|
2566
|
+
})
|
|
2567
|
+
})
|
|
2568
|
+
}) : entry?.evaluation ? /* @__PURE__ */ jsxRuntime.jsx(index.ActivityDetailDialog, {
|
|
2569
|
+
activityName: target.activityName,
|
|
2570
|
+
breadcrumb: index.instanceBreadcrumb(entry.instance, definition),
|
|
2571
|
+
definition: definition,
|
|
2572
|
+
document: documentRefsOf(entry.instance)[0],
|
|
2573
|
+
entry: entry,
|
|
2574
|
+
onClose: onClose,
|
|
2575
|
+
source: "tool-task-list"
|
|
2576
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, {
|
|
2577
|
+
header: "Loading activity…",
|
|
2578
|
+
id: "workflow-activity-detail",
|
|
2579
|
+
onClose: onClose,
|
|
2580
|
+
width: 1,
|
|
2581
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
2582
|
+
padding: 4,
|
|
2583
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.LoadingRow, {
|
|
2584
|
+
label: "Fetching the live workflow state…"
|
|
2585
|
+
})
|
|
2586
|
+
})
|
|
1215
2587
|
});
|
|
1216
|
-
let held = initial.entries ?? {}, unpersisted = !1;
|
|
1217
|
-
return {
|
|
1218
|
-
read: () => togglesOf(held),
|
|
1219
|
-
setOpen(key, open) {
|
|
1220
|
-
const stored = readStored(storage, args.storageKey).entries, base = baseEntries({
|
|
1221
|
-
stored: stored,
|
|
1222
|
-
held: held,
|
|
1223
|
-
unpersisted: unpersisted
|
|
1224
|
-
});
|
|
1225
|
-
return held = prune({
|
|
1226
|
-
...base,
|
|
1227
|
-
[key]: {
|
|
1228
|
-
open: open,
|
|
1229
|
-
touched: Date.now()
|
|
1230
|
-
}
|
|
1231
|
-
}), unpersisted = !writeStored({
|
|
1232
|
-
storage: storage,
|
|
1233
|
-
storageKey: args.storageKey,
|
|
1234
|
-
entries: held
|
|
1235
|
-
}), togglesOf(held);
|
|
1236
|
-
}
|
|
1237
|
-
};
|
|
1238
2588
|
}
|
|
1239
2589
|
|
|
1240
2590
|
function datesOf(state) {
|
|
1241
|
-
return state.filter(entry =>
|
|
2591
|
+
return state.filter(entry => index.isDateFieldKind(entry._type)).map(entry => entry.value).filter(value => typeof value == "string" && value !== "");
|
|
1242
2592
|
}
|
|
1243
2593
|
|
|
1244
2594
|
function spawnOrigins(instances) {
|
|
@@ -1339,10 +2689,7 @@ function deriveTaskGroups(args) {
|
|
|
1339
2689
|
}
|
|
1340
2690
|
|
|
1341
2691
|
function orderGroupsByPreviewTitle(groups, titles) {
|
|
1342
|
-
const withDocuments = [ ...groups.withDocuments ].sort((
|
|
1343
|
-
const aTitle = titles.get(a.document.id), bTitle = titles.get(b.document.id);
|
|
1344
|
-
return aTitle !== void 0 && bTitle !== void 0 ? aTitle.localeCompare(bTitle) || a.key.localeCompare(b.key) : aTitle !== void 0 ? -1 : bTitle !== void 0 ? 1 : a.key.localeCompare(b.key);
|
|
1345
|
-
});
|
|
2692
|
+
const withDocuments = [ ...groups.withDocuments ].sort(byResolvedTitle(group => titles.get(group.document.id), group => group.key));
|
|
1346
2693
|
return {
|
|
1347
2694
|
...groups,
|
|
1348
2695
|
withDocuments: withDocuments
|
|
@@ -1494,11 +2841,13 @@ function workflowTally(workflows) {
|
|
|
1494
2841
|
function settleToast(outcome) {
|
|
1495
2842
|
const total = outcome.settled + outcome.skipped.length + outcome.failures.length;
|
|
1496
2843
|
if (outcome.skipped.length === 0 && outcome.failures.length === 0) return {
|
|
1497
|
-
|
|
2844
|
+
id: index.TOAST_ID.orphanSettle,
|
|
2845
|
+
status: "info",
|
|
1498
2846
|
title: outcome.settled === 1 ? "Cleaned up 1 workflow" : `Cleaned up ${outcome.settled} workflows`
|
|
1499
2847
|
};
|
|
1500
2848
|
const lines = [ ...outcome.skipped.map(workflow => `${workflow.title}: its document exists again — left running`), ...outcome.failures.map(failure => `${failure.workflow.title}: ${failure.message}`) ];
|
|
1501
2849
|
return {
|
|
2850
|
+
id: index.TOAST_ID.orphanSettle,
|
|
1502
2851
|
status: "warning",
|
|
1503
2852
|
title: `Cleaned up ${outcome.settled} of ${total} workflows`,
|
|
1504
2853
|
description: lines.join(`\n`)
|
|
@@ -1507,9 +2856,10 @@ function settleToast(outcome) {
|
|
|
1507
2856
|
|
|
1508
2857
|
function recheckFailedToast(err) {
|
|
1509
2858
|
return {
|
|
2859
|
+
id: index.TOAST_ID.orphanSettle,
|
|
1510
2860
|
status: "error",
|
|
1511
|
-
title: "Nothing was cleaned up
|
|
1512
|
-
description: index.describeError(err)
|
|
2861
|
+
title: "Nothing was cleaned up",
|
|
2862
|
+
description: `The documents could not be re-checked: ${index.describeError(err)}`
|
|
1513
2863
|
};
|
|
1514
2864
|
}
|
|
1515
2865
|
|
|
@@ -1539,7 +2889,7 @@ function OrphanedWorkflowsNote({orphans: orphans}) {
|
|
|
1539
2889
|
function SettleOrphansDialog({workflows: workflows, onClose: onClose}) {
|
|
1540
2890
|
const {engine: engine} = index.useWorkflowContext(), client = sanity.useClient({
|
|
1541
2891
|
apiVersion: index.WORKFLOW_API_VERSION
|
|
1542
|
-
}), toast = index.
|
|
2892
|
+
}), toast = index.useWorkflowToast(), [pending, setPending] = react.useState(!1), confirm = async () => {
|
|
1543
2893
|
setPending(!0);
|
|
1544
2894
|
try {
|
|
1545
2895
|
const outcome = await settleOrphans({
|
|
@@ -1784,72 +3134,6 @@ function applyTaskFilters(args) {
|
|
|
1784
3134
|
});
|
|
1785
3135
|
}
|
|
1786
3136
|
|
|
1787
|
-
const NOTHING = {
|
|
1788
|
-
titles: /* @__PURE__ */ new Map,
|
|
1789
|
-
resolved: /* @__PURE__ */ new Set
|
|
1790
|
-
};
|
|
1791
|
-
|
|
1792
|
-
function useDocPreviewTitles(documents) {
|
|
1793
|
-
const previewStore = sanity.useDocumentPreviewStore(), schema = sanity.useSchema(), {perspectiveStack: perspectiveStack} = sanity.usePerspective(), {actualTypes: actualTypes, binding: binding} = index.useWorkflowContext(), [state, setState] = react.useState(NOTHING), key = documents.map(doc => doc.id).join("|");
|
|
1794
|
-
return react.useEffect(() => {
|
|
1795
|
-
const titles = /* @__PURE__ */ new Map, resolved = /* @__PURE__ */ new Set, previews = /* @__PURE__ */ new Map, publish = () => setState({
|
|
1796
|
-
titles: new Map(titles),
|
|
1797
|
-
resolved: new Set(resolved)
|
|
1798
|
-
}), localDocs = documents.flatMap(doc => {
|
|
1799
|
-
const {parsed: parsed, local: local} = index.gdrLocality(doc.id, binding.contentResource);
|
|
1800
|
-
return !parsed || !local ? (resolved.add(doc.id), []) : [ {
|
|
1801
|
-
doc: doc,
|
|
1802
|
-
bareId: parsed.documentId
|
|
1803
|
-
} ];
|
|
1804
|
-
}), untracks = localDocs.map(({bareId: bareId}) => actualTypes.track(bareId)), dropPreview = docId => {
|
|
1805
|
-
previews.get(docId)?.unsubscribe(), previews.delete(docId), titles.delete(docId);
|
|
1806
|
-
}, observe = ({docId: docId, bareId: bareId, typeName: typeName}) => {
|
|
1807
|
-
const schemaType = index.openableSchemaType(schema, typeName);
|
|
1808
|
-
if (!schemaType) return !1;
|
|
1809
|
-
if (previews.get(docId)?.typeName === typeName) return !0;
|
|
1810
|
-
dropPreview(docId), resolved.delete(docId);
|
|
1811
|
-
const subscription = previewStore.observeForPreview({
|
|
1812
|
-
_id: bareId,
|
|
1813
|
-
_type: schemaType.name
|
|
1814
|
-
}, schemaType, {
|
|
1815
|
-
perspective: perspectiveStack
|
|
1816
|
-
}).subscribe({
|
|
1817
|
-
next: event => {
|
|
1818
|
-
resolved.add(docId);
|
|
1819
|
-
const title = event.snapshot?.title;
|
|
1820
|
-
typeof title == "string" ? titles.set(docId, title) : titles.delete(docId), publish();
|
|
1821
|
-
},
|
|
1822
|
-
error: err => {
|
|
1823
|
-
console.error(`[workflow-studio-plugin] preview for "${docId}" failed:`, err), resolved.add(docId),
|
|
1824
|
-
publish();
|
|
1825
|
-
}
|
|
1826
|
-
});
|
|
1827
|
-
return previews.set(docId, {
|
|
1828
|
-
typeName: typeName,
|
|
1829
|
-
unsubscribe: () => subscription.unsubscribe()
|
|
1830
|
-
}), !0;
|
|
1831
|
-
}, evaluate = () => {
|
|
1832
|
-
for (const {doc: doc, bareId: bareId} of localDocs) {
|
|
1833
|
-
const probe = actualTypes.read(bareId);
|
|
1834
|
-
if (probe === null) {
|
|
1835
|
-
dropPreview(doc.id), resolved.add(doc.id);
|
|
1836
|
-
continue;
|
|
1837
|
-
}
|
|
1838
|
-
!observe({
|
|
1839
|
-
docId: doc.id,
|
|
1840
|
-
bareId: bareId,
|
|
1841
|
-
typeName: probe ?? doc.type
|
|
1842
|
-
}) && typeof probe == "string" && (dropPreview(doc.id), resolved.add(doc.id));
|
|
1843
|
-
}
|
|
1844
|
-
publish();
|
|
1845
|
-
}, unsubscribeProbes = actualTypes.subscribe(evaluate);
|
|
1846
|
-
return evaluate(), () => {
|
|
1847
|
-
unsubscribeProbes(), untracks.forEach(untrack => untrack()), previews.forEach(preview => preview.unsubscribe());
|
|
1848
|
-
};
|
|
1849
|
-
}, [ key, previewStore, schema, actualTypes, binding.contentResource.id, perspectiveStack.join("|") ]),
|
|
1850
|
-
state;
|
|
1851
|
-
}
|
|
1852
|
-
|
|
1853
3137
|
const HITS_CAP = 6;
|
|
1854
3138
|
|
|
1855
3139
|
function TaskFilterMenu({filters: filters, options: options, onChange: onChange}) {
|
|
@@ -2348,8 +3632,10 @@ function FilterRowPortal({filters: filters, onChange: onChange, options: options
|
|
|
2348
3632
|
}), slot) : null;
|
|
2349
3633
|
}
|
|
2350
3634
|
|
|
2351
|
-
function ActivityDateControl({instanceId: instanceId, state: state, dates: dates}) {
|
|
2352
|
-
const
|
|
3635
|
+
function ActivityDateControl({instanceId: instanceId, state: state, surface: surface, dates: dates}) {
|
|
3636
|
+
const editField = index.useEditField(surface), {save: save} = index.useSaveField({
|
|
3637
|
+
instanceId: instanceId
|
|
3638
|
+
}), [open, setOpen] = react.useState(!1), raw = index.dateControlValue({
|
|
2353
3639
|
state: state,
|
|
2354
3640
|
dates: dates
|
|
2355
3641
|
}), display = raw === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
@@ -2372,15 +3658,16 @@ function ActivityDateControl({instanceId: instanceId, state: state, dates: dates
|
|
|
2372
3658
|
})
|
|
2373
3659
|
});
|
|
2374
3660
|
const kind = index.dateControlKind(state), commit = (mode, value) => {
|
|
2375
|
-
state.kind === "editable" && save(() =>
|
|
2376
|
-
|
|
3661
|
+
state.kind === "editable" && save(() => editField({
|
|
3662
|
+
instanceId: instanceId,
|
|
3663
|
+
field: state.field,
|
|
2377
3664
|
...mode === "set" ? {
|
|
2378
3665
|
mode: mode,
|
|
2379
3666
|
value: value
|
|
2380
3667
|
} : {
|
|
2381
3668
|
mode: mode
|
|
2382
3669
|
}
|
|
2383
|
-
})
|
|
3670
|
+
}));
|
|
2384
3671
|
}, handleClick = e => {
|
|
2385
3672
|
e.stopPropagation(), setOpen(v => !v);
|
|
2386
3673
|
};
|
|
@@ -2397,9 +3684,9 @@ function ActivityDateControl({instanceId: instanceId, state: state, dates: dates
|
|
|
2397
3684
|
setOpen(!1), commit("unset");
|
|
2398
3685
|
},
|
|
2399
3686
|
onPick: next => {
|
|
2400
|
-
kind
|
|
3687
|
+
index.hasTimeOfDay(kind) || setOpen(!1), commit("set", index.serializeDateFieldValue(next, kind));
|
|
2401
3688
|
},
|
|
2402
|
-
selectTime: kind
|
|
3689
|
+
selectTime: index.hasTimeOfDay(kind),
|
|
2403
3690
|
value: index.parseDateFieldValue(state.field.value, kind)
|
|
2404
3691
|
})
|
|
2405
3692
|
}),
|
|
@@ -2463,7 +3750,8 @@ function RefChips({refs: refs, max: max = 2}) {
|
|
|
2463
3750
|
wrap: "wrap",
|
|
2464
3751
|
children: [ shown.map(ref => /* @__PURE__ */ jsxRuntime.jsx(index.DocPreviewLink, {
|
|
2465
3752
|
gdr: ref,
|
|
2466
|
-
layout: "inline"
|
|
3753
|
+
layout: "inline",
|
|
3754
|
+
source: "doc-ref-chip"
|
|
2467
3755
|
}, ref.id)), overflow > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, {
|
|
2468
3756
|
muted: !0,
|
|
2469
3757
|
size: 1,
|
|
@@ -2474,54 +3762,16 @@ function RefChips({refs: refs, max: max = 2}) {
|
|
|
2474
3762
|
|
|
2475
3763
|
const UNGROUPED_TITLE = "Workflows without Studio documents";
|
|
2476
3764
|
|
|
2477
|
-
function TaskGroupList({
|
|
3765
|
+
function TaskGroupList({groups: groups, ...wiring}) {
|
|
2478
3766
|
/* @__PURE__ */
|
|
2479
3767
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
2480
3768
|
gap: 1,
|
|
2481
|
-
children: [ groups.withDocuments.map(group => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
header: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
2488
|
-
align: "center",
|
|
2489
|
-
flex: "none",
|
|
2490
|
-
style: {
|
|
2491
|
-
maxWidth: "60%"
|
|
2492
|
-
},
|
|
2493
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(RefChips, {
|
|
2494
|
-
max: 2,
|
|
2495
|
-
refs: group.documents
|
|
2496
|
-
})
|
|
2497
|
-
}),
|
|
2498
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(InstanceBands, {
|
|
2499
|
-
bands: bands,
|
|
2500
|
-
instanceDefaultOpen: instanceDefaultOpen,
|
|
2501
|
-
instances: group.instances,
|
|
2502
|
-
onOpenTask: onOpenTask,
|
|
2503
|
-
onOpenWorkflow: onOpenWorkflow,
|
|
2504
|
-
showTerminalActions: showTerminalActions
|
|
2505
|
-
})
|
|
2506
|
-
}, group.key)), groups.withoutDocuments.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(index.CollapsibleBand, {
|
|
2507
|
-
background: !0,
|
|
2508
|
-
onToggle: () => bands.toggle(UNGROUPED_BAND_KEY, GROUP_DEFAULT_OPEN),
|
|
2509
|
-
open: bands.isOpen(UNGROUPED_BAND_KEY, GROUP_DEFAULT_OPEN),
|
|
2510
|
-
sticky: !0,
|
|
2511
|
-
title: UNGROUPED_TITLE,
|
|
2512
|
-
header: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
2513
|
-
size: 1,
|
|
2514
|
-
weight: "semibold",
|
|
2515
|
-
children: UNGROUPED_TITLE
|
|
2516
|
-
}),
|
|
2517
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(InstanceBands, {
|
|
2518
|
-
bands: bands,
|
|
2519
|
-
instanceDefaultOpen: instanceDefaultOpen,
|
|
2520
|
-
instances: groups.withoutDocuments,
|
|
2521
|
-
onOpenTask: onOpenTask,
|
|
2522
|
-
onOpenWorkflow: onOpenWorkflow,
|
|
2523
|
-
showTerminalActions: showTerminalActions
|
|
2524
|
-
})
|
|
3769
|
+
children: [ groups.withDocuments.map(group => /* @__PURE__ */ jsxRuntime.jsx(DocumentBand, {
|
|
3770
|
+
group: group,
|
|
3771
|
+
...wiring
|
|
3772
|
+
}, group.key)), groups.withoutDocuments.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(UngroupedBand, {
|
|
3773
|
+
instances: groups.withoutDocuments,
|
|
3774
|
+
...wiring
|
|
2525
3775
|
}) : null ]
|
|
2526
3776
|
});
|
|
2527
3777
|
}
|
|
@@ -2534,38 +3784,81 @@ function targetOf(row) {
|
|
|
2534
3784
|
};
|
|
2535
3785
|
}
|
|
2536
3786
|
|
|
2537
|
-
function
|
|
3787
|
+
function DocumentBand({group: group, ...wiring}) {
|
|
3788
|
+
const {open: open, toggle: toggle} = useBandOpen(wiring.bands, group.key);
|
|
3789
|
+
/* @__PURE__ */
|
|
3790
|
+
return jsxRuntime.jsx(index.CollapsibleBand, {
|
|
3791
|
+
background: !0,
|
|
3792
|
+
onToggle: toggle,
|
|
3793
|
+
open: open,
|
|
3794
|
+
sticky: !0,
|
|
3795
|
+
title: workflowEngine.toBareId(group.document.id),
|
|
3796
|
+
header: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
3797
|
+
align: "center",
|
|
3798
|
+
flex: "none",
|
|
3799
|
+
style: {
|
|
3800
|
+
maxWidth: "60%"
|
|
3801
|
+
},
|
|
3802
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(RefChips, {
|
|
3803
|
+
max: 2,
|
|
3804
|
+
refs: group.documents
|
|
3805
|
+
})
|
|
3806
|
+
}),
|
|
3807
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(InstanceBands, {
|
|
3808
|
+
instances: group.instances,
|
|
3809
|
+
...wiring
|
|
3810
|
+
})
|
|
3811
|
+
});
|
|
3812
|
+
}
|
|
3813
|
+
|
|
3814
|
+
function UngroupedBand({instances: instances, ...wiring}) {
|
|
3815
|
+
const {open: open, toggle: toggle} = useBandOpen(wiring.bands, UNGROUPED_BAND_KEY);
|
|
3816
|
+
/* @__PURE__ */
|
|
3817
|
+
return jsxRuntime.jsx(index.CollapsibleBand, {
|
|
3818
|
+
background: !0,
|
|
3819
|
+
onToggle: toggle,
|
|
3820
|
+
open: open,
|
|
3821
|
+
sticky: !0,
|
|
3822
|
+
title: UNGROUPED_TITLE,
|
|
3823
|
+
header: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
3824
|
+
size: 1,
|
|
3825
|
+
weight: "semibold",
|
|
3826
|
+
children: UNGROUPED_TITLE
|
|
3827
|
+
}),
|
|
3828
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(InstanceBands, {
|
|
3829
|
+
instances: instances,
|
|
3830
|
+
...wiring
|
|
3831
|
+
})
|
|
3832
|
+
});
|
|
3833
|
+
}
|
|
3834
|
+
|
|
3835
|
+
function InstanceBands({instances: instances, ...wiring}) {
|
|
2538
3836
|
/* @__PURE__ */
|
|
2539
3837
|
return jsxRuntime.jsx(ui.Stack, {
|
|
2540
3838
|
gap: 1,
|
|
2541
|
-
children: instances.map(
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
onOpenTask: onOpenTask,
|
|
2546
|
-
onOpenWorkflow: onOpenWorkflow,
|
|
2547
|
-
showTerminalActions: showTerminalActions
|
|
2548
|
-
}, band.instanceId))
|
|
3839
|
+
children: instances.map(instance => /* @__PURE__ */ jsxRuntime.jsx(InstanceBand, {
|
|
3840
|
+
instance: instance,
|
|
3841
|
+
...wiring
|
|
3842
|
+
}, instance.instanceId))
|
|
2549
3843
|
});
|
|
2550
3844
|
}
|
|
2551
3845
|
|
|
2552
|
-
function InstanceBand({
|
|
2553
|
-
const {resolvePathFromState: resolvePathFromState} = router.useRouter();
|
|
3846
|
+
function InstanceBand({bands: bands, instance: instance, onOpenTask: onOpenTask, onOpenWorkflow: onOpenWorkflow, showTerminalActions: showTerminalActions}) {
|
|
3847
|
+
const {open: open, toggle: toggle} = useBandOpen(bands, instance.instanceId), {resolvePathFromState: resolvePathFromState} = router.useRouter();
|
|
2554
3848
|
/* @__PURE__ */
|
|
2555
3849
|
return jsxRuntime.jsx(index.CollapsibleBand, {
|
|
2556
|
-
onToggle:
|
|
2557
|
-
open:
|
|
2558
|
-
title:
|
|
3850
|
+
onToggle: toggle,
|
|
3851
|
+
open: open,
|
|
3852
|
+
title: instance.title,
|
|
2559
3853
|
header: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
2560
3854
|
children: [
|
|
2561
3855
|
/* @__PURE__ */ jsxRuntime.jsx(index.LinkChip, {
|
|
2562
3856
|
hint: "View workflow",
|
|
2563
3857
|
href: resolvePathFromState({
|
|
2564
|
-
instanceId:
|
|
3858
|
+
instanceId: instance.instanceId
|
|
2565
3859
|
}),
|
|
2566
3860
|
onClick: event => {
|
|
2567
|
-
event
|
|
2568
|
-
onOpenWorkflow(band.instanceId));
|
|
3861
|
+
isPlainClick(event) && (event.preventDefault(), onOpenWorkflow(instance.instanceId));
|
|
2569
3862
|
},
|
|
2570
3863
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
2571
3864
|
align: "center",
|
|
@@ -2581,12 +3874,12 @@ function InstanceBand({band: band, bands: bands, instanceDefaultOpen: instanceDe
|
|
|
2581
3874
|
},
|
|
2582
3875
|
textOverflow: "ellipsis",
|
|
2583
3876
|
weight: "medium",
|
|
2584
|
-
children:
|
|
2585
|
-
}),
|
|
2586
|
-
segments: [
|
|
3877
|
+
children: instance.title
|
|
3878
|
+
}), instance.breadcrumb === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(index.BreadcrumbTail, {
|
|
3879
|
+
segments: [ instance.breadcrumb ]
|
|
2587
3880
|
}),
|
|
2588
3881
|
/* @__PURE__ */ jsxRuntime.jsx(index.StageFace, {
|
|
2589
|
-
title:
|
|
3882
|
+
title: instance.stageTitle
|
|
2590
3883
|
}) ]
|
|
2591
3884
|
})
|
|
2592
3885
|
}),
|
|
@@ -2596,7 +3889,7 @@ function InstanceBand({band: band, bands: bands, instanceDefaultOpen: instanceDe
|
|
|
2596
3889
|
paddingLeft: 5,
|
|
2597
3890
|
children: /* @__PURE__ */ jsxRuntime.jsx(TaskRows, {
|
|
2598
3891
|
onOpenTask: onOpenTask,
|
|
2599
|
-
rows:
|
|
3892
|
+
rows: instance.rows,
|
|
2600
3893
|
showTerminalActions: showTerminalActions
|
|
2601
3894
|
})
|
|
2602
3895
|
})
|
|
@@ -2630,40 +3923,19 @@ function TaskActivityRow({row: row, onOpen: onOpen, showTerminalActions: showTer
|
|
|
2630
3923
|
dateControl: /* @__PURE__ */ jsxRuntime.jsx(ActivityDateControl, {
|
|
2631
3924
|
dates: render.dates,
|
|
2632
3925
|
instanceId: row.instanceId,
|
|
2633
|
-
state: render.dateState
|
|
3926
|
+
state: render.dateState,
|
|
3927
|
+
surface: "tool-task-list"
|
|
2634
3928
|
}),
|
|
2635
3929
|
face: render.face,
|
|
2636
3930
|
instanceId: row.instanceId,
|
|
2637
3931
|
onOpen: onOpen,
|
|
3932
|
+
surface: "tool-task-list",
|
|
2638
3933
|
terminalActions: showTerminalActions ? render.terminalActions : []
|
|
2639
3934
|
})
|
|
2640
3935
|
})
|
|
2641
3936
|
});
|
|
2642
3937
|
}
|
|
2643
3938
|
|
|
2644
|
-
function useBandOpenState(args) {
|
|
2645
|
-
const {segment: segment, scope: scope} = args, store = react.useMemo(() => createBandStateStore({
|
|
2646
|
-
storageKey: bandStateStorageKey(scope)
|
|
2647
|
-
}), [ scope ]), [held, setHeld] = react.useState(() => ({
|
|
2648
|
-
store: store,
|
|
2649
|
-
toggles: store.read()
|
|
2650
|
-
}));
|
|
2651
|
-
held.store !== store && setHeld({
|
|
2652
|
-
store: store,
|
|
2653
|
-
toggles: store.read()
|
|
2654
|
-
});
|
|
2655
|
-
const qualify = key => `${segment}/${key}`, isOpen = (key, defaultOpen) => held.toggles.get(qualify(key)) ?? defaultOpen;
|
|
2656
|
-
return {
|
|
2657
|
-
isOpen: isOpen,
|
|
2658
|
-
toggle: (key, defaultOpen) => {
|
|
2659
|
-
setHeld({
|
|
2660
|
-
store: store,
|
|
2661
|
-
toggles: store.setOpen(qualify(key), !isOpen(key, defaultOpen))
|
|
2662
|
-
});
|
|
2663
|
-
}
|
|
2664
|
-
};
|
|
2665
|
-
}
|
|
2666
|
-
|
|
2667
3939
|
const NO_MISSING = /* @__PURE__ */ new Set;
|
|
2668
3940
|
|
|
2669
3941
|
function sameIdSet(a, b) {
|
|
@@ -2703,15 +3975,18 @@ function TasksTab({filterSlot: filterSlot, instances: instances, loading: loadin
|
|
|
2703
3975
|
}), [filters, setFilters] = react.useState({}), groups = react.useMemo(() => deriveTaskGroups({
|
|
2704
3976
|
instances: instances,
|
|
2705
3977
|
identity: identity
|
|
2706
|
-
}), [ instances, identity ]), orphans = useOrphanedWorkflows(groups), listed = react.useMemo(() => hideOrphanedGroups(groups, orphans.groupKeys), [ groups, orphans.groupKeys ]), options = react.useMemo(() => taskFilterOptions(listed), [ listed ]),
|
|
3978
|
+
}), [ instances, identity ]), orphans = useOrphanedWorkflows(groups), listed = react.useMemo(() => hideOrphanedGroups(groups, orphans.groupKeys), [ groups, orphans.groupKeys ]), options = react.useMemo(() => taskFilterOptions(listed), [ listed ]), titles = useGroupTitles(listed), revealed = useRevealGate({
|
|
3979
|
+
loading: loading,
|
|
3980
|
+
ready: titles.ready
|
|
3981
|
+
}), visible = react.useMemo(() => {
|
|
2707
3982
|
const filtered = applyTaskFilters({
|
|
2708
3983
|
groups: listed,
|
|
2709
3984
|
filters: filters,
|
|
2710
3985
|
now: /* @__PURE__ */ new Date
|
|
2711
3986
|
}), cut = mineOnly ? onlyMyTasks(filtered) : filtered;
|
|
2712
|
-
return orderGroupsByPreviewTitle(cut,
|
|
2713
|
-
}, [ listed, filters, mineOnly,
|
|
2714
|
-
if (loading) /* @__PURE__ */
|
|
3987
|
+
return orderGroupsByPreviewTitle(cut, titles.titles);
|
|
3988
|
+
}, [ listed, filters, mineOnly, titles ]);
|
|
3989
|
+
if (loading || !revealed) /* @__PURE__ */
|
|
2715
3990
|
return jsxRuntime.jsx(TabStatusRow, {
|
|
2716
3991
|
children: /* @__PURE__ */ jsxRuntime.jsx(index.LoadingRow, {
|
|
2717
3992
|
label: "Loading tasks…"
|
|
@@ -2719,16 +3994,13 @@ function TasksTab({filterSlot: filterSlot, instances: instances, loading: loadin
|
|
|
2719
3994
|
});
|
|
2720
3995
|
const empty = visible.withDocuments.length === 0 && visible.withoutDocuments.length === 0;
|
|
2721
3996
|
let body;
|
|
2722
|
-
return empty ? mineOnly ? body = /* @__PURE__ */ jsxRuntime.jsx(index.ForMeEmptyState, {}) : body = /* @__PURE__ */ jsxRuntime.jsx(
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
children: "No tasks match — adjust the filters, or start a workflow"
|
|
2727
|
-
})
|
|
3997
|
+
return empty ? mineOnly ? body = /* @__PURE__ */ jsxRuntime.jsx(index.ForMeEmptyState, {}) : body = /* @__PURE__ */ jsxRuntime.jsx(index.EmptyState, {
|
|
3998
|
+
description: "Adjust the filters, or start a workflow",
|
|
3999
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Search.SearchIcon, {}),
|
|
4000
|
+
title: "No tasks match"
|
|
2728
4001
|
}) : body = /* @__PURE__ */ jsxRuntime.jsx(TaskGroupList, {
|
|
2729
4002
|
bands: bands,
|
|
2730
4003
|
groups: visible,
|
|
2731
|
-
instanceDefaultOpen: instanceBandDefaultOpen(segment),
|
|
2732
4004
|
onOpenTask: onOpenTask,
|
|
2733
4005
|
onOpenWorkflow: onOpenWorkflow,
|
|
2734
4006
|
showTerminalActions: mineOnly
|
|
@@ -2754,52 +4026,106 @@ function TasksTab({filterSlot: filterSlot, instances: instances, loading: loadin
|
|
|
2754
4026
|
/* @__PURE__ */ jsxRuntime.jsx(OrphanedWorkflowsNote, {
|
|
2755
4027
|
orphans: orphans
|
|
2756
4028
|
}), body, truncated ? /* @__PURE__ */ jsxRuntime.jsx(MutedNote, {
|
|
2757
|
-
text: `Tasks from the latest ${INSTANCE_CAP} workflows — older ones aren
|
|
4029
|
+
text: `Tasks from the latest ${INSTANCE_CAP} workflows — older ones aren’t listed.`
|
|
2758
4030
|
}) : null ]
|
|
2759
4031
|
}) ]
|
|
2760
4032
|
});
|
|
2761
4033
|
}
|
|
2762
4034
|
|
|
2763
|
-
const
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
4035
|
+
const TOOL_TAB_LABELS = {
|
|
4036
|
+
definitions: "Definitions",
|
|
4037
|
+
documents: "Documents",
|
|
4038
|
+
tasks: "Tasks",
|
|
4039
|
+
"for-me": "For me"
|
|
4040
|
+
}, TOOL_TAB_VALUES = Object.keys(TOOL_TAB_LABELS), TOOL_TABS = TOOL_TAB_VALUES.map(value => ({
|
|
4041
|
+
value: value,
|
|
4042
|
+
label: TOOL_TAB_LABELS[value]
|
|
4043
|
+
})), DEFAULT_TOOL_TAB = "definitions";
|
|
4044
|
+
|
|
4045
|
+
function toolTabState(tab) {
|
|
4046
|
+
return tab === DEFAULT_TOOL_TAB ? {} : {
|
|
4047
|
+
workflowsTab: tab
|
|
4048
|
+
};
|
|
4049
|
+
}
|
|
4050
|
+
|
|
4051
|
+
function boardState(definitionName) {
|
|
4052
|
+
return {
|
|
4053
|
+
boardDefinition: definitionName
|
|
4054
|
+
};
|
|
4055
|
+
}
|
|
4056
|
+
|
|
4057
|
+
function tabSelectionNavigates(route, tab) {
|
|
4058
|
+
return !(route.kind === "home" && tab === route.tab);
|
|
4059
|
+
}
|
|
4060
|
+
|
|
4061
|
+
function backToAllLabel(tab) {
|
|
4062
|
+
return `Back to all ${TOOL_TAB_LABELS[tab].toLowerCase()}`;
|
|
4063
|
+
}
|
|
4064
|
+
|
|
4065
|
+
function toolRoute(state) {
|
|
4066
|
+
const {instanceId: instanceId, definitionName: definitionName, boardDefinition: boardDefinition} = state;
|
|
4067
|
+
if (typeof instanceId == "string") return {
|
|
4068
|
+
kind: "instance",
|
|
4069
|
+
instanceId: instanceId,
|
|
4070
|
+
tab: "tasks"
|
|
4071
|
+
};
|
|
4072
|
+
if (typeof definitionName == "string") return {
|
|
4073
|
+
kind: "definition",
|
|
4074
|
+
definitionName: definitionName,
|
|
4075
|
+
tab: "definitions"
|
|
4076
|
+
};
|
|
4077
|
+
if (typeof boardDefinition == "string") return {
|
|
4078
|
+
kind: "home",
|
|
4079
|
+
tab: "documents",
|
|
4080
|
+
boardDefinition: boardDefinition
|
|
4081
|
+
};
|
|
4082
|
+
const tab = index.pathSegmentTab({
|
|
4083
|
+
segment: state.workflowsTab,
|
|
4084
|
+
tabs: TOOL_TAB_VALUES,
|
|
4085
|
+
fallback: DEFAULT_TOOL_TAB
|
|
4086
|
+
});
|
|
4087
|
+
return tab === void 0 ? {
|
|
4088
|
+
kind: "not-found",
|
|
4089
|
+
tab: void 0
|
|
4090
|
+
} : {
|
|
4091
|
+
kind: "home",
|
|
4092
|
+
tab: tab,
|
|
4093
|
+
boardDefinition: void 0
|
|
4094
|
+
};
|
|
4095
|
+
}
|
|
2773
4096
|
|
|
2774
4097
|
function InstanceStreamKeepAlive() {
|
|
2775
4098
|
return useToolInstances(), null;
|
|
2776
4099
|
}
|
|
2777
4100
|
|
|
2778
4101
|
function WorkflowsToolRoot() {
|
|
2779
|
-
const router$1 = router.useRouter(), {seedInstance: seedInstance} = index.useWorkflowContext(), telemetry = workflowReact.useWorkflowTelemetry(), [filterSlot, setFilterSlot] = react.useState(null),
|
|
4102
|
+
const router$1 = router.useRouter(), {seedInstance: seedInstance} = index.useWorkflowContext(), telemetry = workflowReact.useWorkflowTelemetry(), [filterSlot, setFilterSlot] = react.useState(null), route = toolRoute(router$1.state), isHome = route.kind === "home" || route.kind === "not-found", [instanceStreamLatched, setInstanceStreamLatched] = react.useState(isHome);
|
|
2780
4103
|
react.useEffect(() => {
|
|
2781
4104
|
isHome && setInstanceStreamLatched(!0);
|
|
2782
4105
|
}, [ isHome ]);
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
});
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
4106
|
+
const setTab = next => router$1.navigate(toolTabState(next)), selectBoardWorkflow = react.useCallback((name, opts) => router$1.navigate(boardState(name), opts?.replace === !0 ? {
|
|
4107
|
+
replace: !0
|
|
4108
|
+
} : {}), [ router$1 ]), backToList = tab => ({
|
|
4109
|
+
label: backToAllLabel(tab),
|
|
4110
|
+
go: () => setTab(tab)
|
|
4111
|
+
}), badSegment = route.kind === "not-found";
|
|
4112
|
+
react.useEffect(() => {
|
|
4113
|
+
badSegment && router$1.navigate({}, {
|
|
4114
|
+
replace: !0
|
|
4115
|
+
});
|
|
4116
|
+
}, [ badSegment, router$1 ]), index.useLogEventOnMount(index.WorkflowToolOpened, {
|
|
4117
|
+
tab: route.tab ?? "not-found",
|
|
2794
4118
|
via: "open"
|
|
2795
4119
|
});
|
|
2796
4120
|
let panel;
|
|
2797
|
-
return
|
|
2798
|
-
instanceId: instanceId,
|
|
2799
|
-
|
|
2800
|
-
}, instanceId) :
|
|
2801
|
-
definitionName: definitionName
|
|
2802
|
-
|
|
4121
|
+
return route.kind === "instance" ? panel = /* @__PURE__ */ jsxRuntime.jsx(WorkflowInstanceDetail, {
|
|
4122
|
+
instanceId: route.instanceId,
|
|
4123
|
+
backToList: backToList(route.tab)
|
|
4124
|
+
}, route.instanceId) : route.kind === "definition" ? panel = /* @__PURE__ */ jsxRuntime.jsx(DefinitionDetail, {
|
|
4125
|
+
definitionName: route.definitionName,
|
|
4126
|
+
backToList: backToList(route.tab)
|
|
4127
|
+
}, route.definitionName) : route.kind === "not-found" ? panel = null : panel = /* @__PURE__ */ jsxRuntime.jsx(WorkflowsHome, {
|
|
4128
|
+
boardDefinition: route.boardDefinition,
|
|
2803
4129
|
filterSlot: filterSlot,
|
|
2804
4130
|
onOpenDefinition: name => router$1.navigate({
|
|
2805
4131
|
definitionName: name
|
|
@@ -2809,7 +4135,8 @@ function WorkflowsToolRoot() {
|
|
|
2809
4135
|
instanceId: typeof instance == "string" ? instance : instance._id
|
|
2810
4136
|
});
|
|
2811
4137
|
},
|
|
2812
|
-
|
|
4138
|
+
onSelectWorkflow: selectBoardWorkflow,
|
|
4139
|
+
tab: route.tab
|
|
2813
4140
|
}),
|
|
2814
4141
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Card, {
|
|
2815
4142
|
height: "fill",
|
|
@@ -2844,13 +4171,13 @@ function WorkflowsToolRoot() {
|
|
|
2844
4171
|
ariaControls: "workflows-tool-panel",
|
|
2845
4172
|
idPrefix: "workflows-tool-tab",
|
|
2846
4173
|
onSelect: next => {
|
|
2847
|
-
next !== tab && telemetry.log(index.WorkflowToolOpened, {
|
|
4174
|
+
tabSelectionNavigates(route, next) && (next !== route.tab && telemetry.log(index.WorkflowToolOpened, {
|
|
2848
4175
|
tab: next,
|
|
2849
4176
|
via: "tab-switch"
|
|
2850
|
-
}), setTab(next);
|
|
4177
|
+
}), setTab(next));
|
|
2851
4178
|
},
|
|
2852
4179
|
options: TOOL_TABS,
|
|
2853
|
-
selected: tab
|
|
4180
|
+
selected: route.tab
|
|
2854
4181
|
}),
|
|
2855
4182
|
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
2856
4183
|
ref: setFilterSlot
|
|
@@ -2866,17 +4193,20 @@ function WorkflowsToolRoot() {
|
|
|
2866
4193
|
});
|
|
2867
4194
|
}
|
|
2868
4195
|
|
|
2869
|
-
function WorkflowsHome({filterSlot: filterSlot, onOpenDefinition: onOpenDefinition, onOpenInstance: onOpenInstance, tab: tab}) {
|
|
4196
|
+
function WorkflowsHome({boardDefinition: boardDefinition, filterSlot: filterSlot, onOpenDefinition: onOpenDefinition, onOpenInstance: onOpenInstance, onSelectWorkflow: onSelectWorkflow, tab: tab}) {
|
|
2870
4197
|
const instances = useToolInstances(), identity = index.useAssignmentIdentity(), [openTask, setOpenTask] = react.useState(null), openInstance = target => {
|
|
2871
4198
|
if (typeof target != "string") return onOpenInstance(target);
|
|
2872
4199
|
const held = [ ...instances.inFlight, ...instances.settled ].find(i => i._id === target);
|
|
2873
4200
|
onOpenInstance(held ?? target);
|
|
2874
4201
|
}, scrollerRef = react.useRef(null);
|
|
2875
|
-
|
|
4202
|
+
react.useEffect(() => {
|
|
2876
4203
|
scrollerRef.current?.scrollTo({
|
|
2877
4204
|
top: 0
|
|
2878
4205
|
});
|
|
2879
|
-
}, [ tab ])
|
|
4206
|
+
}, [ tab ]);
|
|
4207
|
+
const bleeds = tab === "documents";
|
|
4208
|
+
/* @__PURE__ */
|
|
4209
|
+
return jsxRuntime.jsxs(ui.Flex, {
|
|
2880
4210
|
direction: "column",
|
|
2881
4211
|
height: "fill",
|
|
2882
4212
|
overflow: "hidden",
|
|
@@ -2885,9 +4215,9 @@ function WorkflowsHome({filterSlot: filterSlot, onOpenDefinition: onOpenDefiniti
|
|
|
2885
4215
|
ref: scrollerRef,
|
|
2886
4216
|
flex: 1,
|
|
2887
4217
|
overflow: "auto",
|
|
2888
|
-
paddingX:
|
|
4218
|
+
paddingX: bleeds ? 0 : TOOL_PANEL_PADDING,
|
|
2889
4219
|
style: {
|
|
2890
|
-
scrollbarGutter: "stable"
|
|
4220
|
+
scrollbarGutter: bleeds ? "auto" : "stable"
|
|
2891
4221
|
},
|
|
2892
4222
|
children: /* @__PURE__ */ jsxRuntime.jsx(ui.TabPanel, {
|
|
2893
4223
|
"aria-labelledby": `workflows-tool-tab-${tab}`,
|
|
@@ -2900,18 +4230,19 @@ function WorkflowsHome({filterSlot: filterSlot, onOpenDefinition: onOpenDefiniti
|
|
|
2900
4230
|
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
2901
4231
|
direction: "column",
|
|
2902
4232
|
flex: 1,
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
}
|
|
4233
|
+
style: {
|
|
4234
|
+
minHeight: 0
|
|
4235
|
+
},
|
|
4236
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(HomePanel, {
|
|
4237
|
+
boardDefinition: boardDefinition,
|
|
2906
4238
|
filterSlot: filterSlot,
|
|
2907
4239
|
identity: identity,
|
|
2908
|
-
instances:
|
|
2909
|
-
|
|
4240
|
+
instances: instances,
|
|
4241
|
+
onOpenDefinition: onOpenDefinition,
|
|
2910
4242
|
onOpenTask: setOpenTask,
|
|
2911
4243
|
onOpenWorkflow: openInstance,
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
unreadable: instances.unreadable
|
|
4244
|
+
onSelectWorkflow: onSelectWorkflow,
|
|
4245
|
+
tab: tab
|
|
2915
4246
|
})
|
|
2916
4247
|
})
|
|
2917
4248
|
})
|
|
@@ -2922,4 +4253,25 @@ function WorkflowsHome({filterSlot: filterSlot, onOpenDefinition: onOpenDefiniti
|
|
|
2922
4253
|
});
|
|
2923
4254
|
}
|
|
2924
4255
|
|
|
4256
|
+
function HomePanel({boardDefinition: boardDefinition, filterSlot: filterSlot, identity: identity, instances: instances, onOpenDefinition: onOpenDefinition, onOpenTask: onOpenTask, onOpenWorkflow: onOpenWorkflow, onSelectWorkflow: onSelectWorkflow, tab: tab}) {
|
|
4257
|
+
return tab === "definitions" ? /* @__PURE__ */ jsxRuntime.jsx(DefinitionsTab, {
|
|
4258
|
+
onOpenDefinition: onOpenDefinition
|
|
4259
|
+
}) : tab === "documents" ? /* @__PURE__ */ jsxRuntime.jsx(DocumentsTab, {
|
|
4260
|
+
filterSlot: filterSlot,
|
|
4261
|
+
onOpenDefinition: onOpenDefinition,
|
|
4262
|
+
onSelectWorkflow: onSelectWorkflow,
|
|
4263
|
+
routeDefinition: boardDefinition
|
|
4264
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(TasksTab, {
|
|
4265
|
+
filterSlot: filterSlot,
|
|
4266
|
+
identity: identity,
|
|
4267
|
+
instances: [ ...instances.inFlight, ...instances.settled ],
|
|
4268
|
+
loading: instances.loading,
|
|
4269
|
+
onOpenTask: onOpenTask,
|
|
4270
|
+
onOpenWorkflow: onOpenWorkflow,
|
|
4271
|
+
segment: tab,
|
|
4272
|
+
truncated: instances.truncated,
|
|
4273
|
+
unreadable: instances.unreadable
|
|
4274
|
+
});
|
|
4275
|
+
}
|
|
4276
|
+
|
|
2925
4277
|
exports.default = WorkflowsToolRoot;
|