@sanity/workflow-studio-plugin 0.25.0 → 0.27.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 +119 -0
- package/dist/_chunks-cjs/index.cjs +1190 -545
- package/dist/_chunks-cjs/workflows-tool-root.cjs +61 -517
- package/dist/_chunks-es/index.js +1203 -538
- package/dist/_chunks-es/workflows-tool-root.js +60 -520
- 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"), workflowEngine = require("@sanity/workflow-engine"), ArrowLeft = require("@sanity/icons/ArrowLeft"), Transfer = require("@sanity/icons/Transfer"), WarningOutline = require("@sanity/icons/WarningOutline"), pluralize = require("pluralize-esm"), sanity = require("sanity"), workflowStudio = require("@sanity/workflow-studio"), Add = require("@sanity/icons/Add"), Search = require("@sanity/icons/Search"), 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"), reactDom = require("react-dom"), ChevronDown = require("@sanity/icons/ChevronDown"), ChevronRight = require("@sanity/icons/ChevronRight"), types = require("@sanity/types"), workflowDiagram = require("@sanity/workflow-diagram"), react$1 = require("motion/react");
|
|
4
4
|
|
|
5
5
|
function _interopDefaultCompat(e) {
|
|
6
6
|
return e && typeof e == "object" && "default" in e ? e : {
|
|
@@ -10,16 +10,6 @@ function _interopDefaultCompat(e) {
|
|
|
10
10
|
|
|
11
11
|
var pluralize__default = /* @__PURE__ */ _interopDefaultCompat(pluralize);
|
|
12
12
|
|
|
13
|
-
function CodeChip({value: value}) {
|
|
14
|
-
/* @__PURE__ */
|
|
15
|
-
return jsxRuntime.jsx("code", {
|
|
16
|
-
style: {
|
|
17
|
-
overflowWrap: "anywhere"
|
|
18
|
-
},
|
|
19
|
-
children: value
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
|
|
23
13
|
function SectionHeading({children: children}) {
|
|
24
14
|
/* @__PURE__ */
|
|
25
15
|
return jsxRuntime.jsx(ui.Text, {
|
|
@@ -29,146 +19,6 @@ function SectionHeading({children: children}) {
|
|
|
29
19
|
});
|
|
30
20
|
}
|
|
31
21
|
|
|
32
|
-
function normalizeAbortReason(raw) {
|
|
33
|
-
const trimmed = raw.trim();
|
|
34
|
-
return trimmed === "" ? void 0 : trimmed;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function abortCommitReport(args) {
|
|
38
|
-
return args.changed ? {
|
|
39
|
-
outcome: "aborted",
|
|
40
|
-
toast: abortedToast(args.title)
|
|
41
|
-
} : {
|
|
42
|
-
outcome: "already-settled",
|
|
43
|
-
toast: abortAlreadySettledToast(args.title)
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function abortedToast(title) {
|
|
48
|
-
return {
|
|
49
|
-
id: index.TOAST_ID.abort,
|
|
50
|
-
status: "info",
|
|
51
|
-
title: `Aborted “${title}”`
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function abortAlreadySettledToast(title) {
|
|
56
|
-
return {
|
|
57
|
-
id: index.TOAST_ID.abort,
|
|
58
|
-
status: "info",
|
|
59
|
-
title: `“${title}” had already finished`,
|
|
60
|
-
description: "Nothing was aborted — the workflow reached a terminal state first."
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function abortUnconfirmedToast(args) {
|
|
65
|
-
return {
|
|
66
|
-
id: index.TOAST_ID.abort,
|
|
67
|
-
status: "warning",
|
|
68
|
-
title: `Couldn’t confirm “${args.title}” was aborted`,
|
|
69
|
-
description: `${index.describeError(args.err)} — the abort may still have committed, so check the workflow’s state before trying again.`
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function AbortWorkflowDialog({entry: entry, onClose: onClose}) {
|
|
74
|
-
const {engine: engine} = index.useWorkflowContext(), definition = index.useDefinition(entry), toast = index.useWorkflowToast(), telemetry = workflowReact.useWorkflowTelemetry(), [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}`;
|
|
75
|
-
index.useLogEventOnMount(index.WorkflowAbortDialogOpened, {
|
|
76
|
-
instanceId: instance._id
|
|
77
|
-
});
|
|
78
|
-
const confirm = async () => {
|
|
79
|
-
if (reason === void 0) return;
|
|
80
|
-
const log = outcome => telemetry.log(index.WorkflowAbortDialogSubmitted, {
|
|
81
|
-
instanceId: instance._id,
|
|
82
|
-
outcome: outcome
|
|
83
|
-
});
|
|
84
|
-
setPending(!0);
|
|
85
|
-
try {
|
|
86
|
-
const {changed: changed} = await engine.abortInstance({
|
|
87
|
-
instanceId: instance._id,
|
|
88
|
-
reason: reason
|
|
89
|
-
}), report = abortCommitReport({
|
|
90
|
-
title: title,
|
|
91
|
-
changed: changed
|
|
92
|
-
});
|
|
93
|
-
toast.push(report.toast), log(report.outcome), onClose();
|
|
94
|
-
} catch (err) {
|
|
95
|
-
toast.push(abortUnconfirmedToast({
|
|
96
|
-
title: title,
|
|
97
|
-
err: err
|
|
98
|
-
})), log("unconfirmed"), setPending(!1);
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
/* @__PURE__ */
|
|
102
|
-
return jsxRuntime.jsx(ui.Dialog, {
|
|
103
|
-
footer: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
104
|
-
padding: 3,
|
|
105
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
106
|
-
gap: 2,
|
|
107
|
-
justify: "flex-end",
|
|
108
|
-
children: [
|
|
109
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
110
|
-
disabled: pending,
|
|
111
|
-
fontSize: 1,
|
|
112
|
-
mode: "bleed",
|
|
113
|
-
onClick: onClose,
|
|
114
|
-
padding: 2,
|
|
115
|
-
text: "Cancel"
|
|
116
|
-
}),
|
|
117
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
118
|
-
disabled: reason === void 0,
|
|
119
|
-
fontSize: 1,
|
|
120
|
-
loading: pending,
|
|
121
|
-
onClick: () => {
|
|
122
|
-
confirm();
|
|
123
|
-
},
|
|
124
|
-
padding: 2,
|
|
125
|
-
text: "Abort workflow",
|
|
126
|
-
tone: "critical"
|
|
127
|
-
}) ]
|
|
128
|
-
})
|
|
129
|
-
}),
|
|
130
|
-
header: "Abort workflow",
|
|
131
|
-
id: `abort-workflow-${instance._id}`,
|
|
132
|
-
onClose: () => {
|
|
133
|
-
pending || onClose();
|
|
134
|
-
},
|
|
135
|
-
width: 0,
|
|
136
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
137
|
-
padding: 4,
|
|
138
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
139
|
-
gap: 5,
|
|
140
|
-
children: [
|
|
141
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, {
|
|
142
|
-
size: 1,
|
|
143
|
-
children: [ "Abort the ",
|
|
144
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", {
|
|
145
|
-
children: title
|
|
146
|
-
}), " workflow? This cannot be undone." ]
|
|
147
|
-
}),
|
|
148
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
149
|
-
gap: 3,
|
|
150
|
-
children: [
|
|
151
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
152
|
-
as: "label",
|
|
153
|
-
htmlFor: reasonInputId,
|
|
154
|
-
size: 1,
|
|
155
|
-
weight: "medium",
|
|
156
|
-
children: "Reason"
|
|
157
|
-
}),
|
|
158
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.TextInput, {
|
|
159
|
-
autoFocus: !0,
|
|
160
|
-
fontSize: 1,
|
|
161
|
-
id: reasonInputId,
|
|
162
|
-
onChange: event => setTypedReason(event.currentTarget.value),
|
|
163
|
-
placeholder: "Why is this workflow being stopped?",
|
|
164
|
-
value: typedReason
|
|
165
|
-
}) ]
|
|
166
|
-
}) ]
|
|
167
|
-
})
|
|
168
|
-
})
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
|
|
172
22
|
function AbortWorkflowSection({entry: entry}) {
|
|
173
23
|
const [aborting, setAborting] = react.useState(!1);
|
|
174
24
|
return index.isLiveEntry(entry) ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
@@ -186,368 +36,13 @@ function AbortWorkflowSection({entry: entry}) {
|
|
|
186
36
|
text: "Abort workflow…",
|
|
187
37
|
tone: "critical"
|
|
188
38
|
})
|
|
189
|
-
}), aborting ? /* @__PURE__ */ jsxRuntime.jsx(AbortWorkflowDialog, {
|
|
39
|
+
}), aborting ? /* @__PURE__ */ jsxRuntime.jsx(index.AbortWorkflowDialog, {
|
|
190
40
|
entry: entry,
|
|
191
41
|
onClose: () => setAborting(!1)
|
|
192
42
|
}) : null ]
|
|
193
43
|
}) : null;
|
|
194
44
|
}
|
|
195
45
|
|
|
196
|
-
function makeTitleResolver(definition) {
|
|
197
|
-
const activities = (definition?.stages ?? []).flatMap(s => s.activities ?? []);
|
|
198
|
-
return {
|
|
199
|
-
action: (activityName, actionName) => activities.find(t => t.name === activityName)?.actions?.find(a => a.name === actionName)?.title ?? actionName,
|
|
200
|
-
activity: name => activities.find(t => t.name === name)?.title ?? name,
|
|
201
|
-
stage: name => index.stageTitle(definition, name)
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function attributed(actor, ...parts) {
|
|
206
|
-
if (actor) return {
|
|
207
|
-
actorId: actor.id,
|
|
208
|
-
parts: parts
|
|
209
|
-
};
|
|
210
|
-
const [first, ...rest] = parts;
|
|
211
|
-
return typeof first != "string" ? {
|
|
212
|
-
actorId: void 0,
|
|
213
|
-
parts: parts
|
|
214
|
-
} : {
|
|
215
|
-
actorId: void 0,
|
|
216
|
-
parts: [ first.charAt(0).toUpperCase() + first.slice(1), ...rest ]
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function standalone(...parts) {
|
|
221
|
-
return {
|
|
222
|
-
actorId: void 0,
|
|
223
|
-
parts: parts
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const historyLiner = {
|
|
228
|
-
stageEntered: (h, titles) => attributed(h.actor, `entered ${titles.stage(h.stage)}${h.fromStage ? ` from ${titles.stage(h.fromStage)}` : ""}`),
|
|
229
|
-
stageExited: (h, titles) => attributed(h.actor, `left ${titles.stage(h.stage)} for ${titles.stage(h.toStage)}`),
|
|
230
|
-
activityStatusChanged: (h, titles) => attributed(h.actor, `changed ${titles.activity(h.activity)}: ${h.from} → ${h.to}`),
|
|
231
|
-
actionFired: (h, titles) => {
|
|
232
|
-
const phrase = `fired ${titles.action(h.activity, h.action)} on ${titles.activity(h.activity)}`;
|
|
233
|
-
return h.triggered ? standalone(`The workflow ${phrase}`) : attributed(h.actor, phrase);
|
|
234
|
-
},
|
|
235
|
-
transitionFired: (h, titles) => attributed(h.actor, `moved ${titles.stage(h.fromStage)} → ${titles.stage(h.toStage)}`),
|
|
236
|
-
effectQueued: h => standalone("Effect ", {
|
|
237
|
-
code: h.effect
|
|
238
|
-
}, " queued"),
|
|
239
|
-
effectCompleted: h => {
|
|
240
|
-
const detail = h.detail ? ` — ${h.detail}` : "";
|
|
241
|
-
return h.actor ? attributed(h.actor, "resolved effect ", {
|
|
242
|
-
code: h.effect
|
|
243
|
-
}, ` — ${h.status}${detail}`) : standalone("Effect ", {
|
|
244
|
-
code: h.effect
|
|
245
|
-
}, ` ${h.status}${detail}`);
|
|
246
|
-
},
|
|
247
|
-
effectClaimReleased: h => attributed(h.actor, "released a stale claim on effect ", {
|
|
248
|
-
code: h.effect
|
|
249
|
-
}, ` ${h.via === "sweep" ? "via the sweeper" : "via a drain takeover"}`),
|
|
250
|
-
spawned: (h, titles) => attributed(h.actor, `spawned a child workflow from ${titles.activity(h.activity)}`),
|
|
251
|
-
subworkflowAdopted: (h, titles) => standalone(`Re-adopted child workflow into ${titles.activity(h.activity)} on re-entering ${titles.stage(h.stage)}`),
|
|
252
|
-
subworkflowResolved: (h, titles) => standalone(`Child workflow of ${titles.activity(h.activity)} ${h.status === "done" ? "completed" : "was aborted"}`),
|
|
253
|
-
subworkflowOrphaned: h => standalone(`Orphaned child workflow reached terminal — ${h.detail}`),
|
|
254
|
-
aborted: (h, titles) => attributed(h.actor, `aborted the workflow at ${titles.stage(h.stage)}${h.reason ? ` — ${h.reason}` : ""}`),
|
|
255
|
-
opApplied: (h, titles) => h.action ? attributed(h.actor, `changed state via action ${titles.action(h.activity ?? "", h.action)}`) : h.activity ? attributed(h.actor, `changed state via activity ${titles.activity(h.activity)}`) : attributed(h.actor, "changed state via ", {
|
|
256
|
-
code: h.opType
|
|
257
|
-
}),
|
|
258
|
-
fieldQueryDiscarded: h => standalone({
|
|
259
|
-
code: JSON.stringify(h)
|
|
260
|
-
})
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
function historyLine(h, titles) {
|
|
264
|
-
return historyLiner[h._type](h, titles);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function historyWindow(args) {
|
|
268
|
-
const {entries: entries, expanded: expanded} = args;
|
|
269
|
-
return {
|
|
270
|
-
overflows: entries.length > 6,
|
|
271
|
-
shown: expanded ? entries : entries.slice(0, 6)
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
function PendingEffectRows({instance: instance, now: now}) {
|
|
276
|
-
const {drainEffectsFor: drainEffectsFor, completeEffectFor: completeEffectFor, effectHandlers: effectHandlers} = index.useWorkflowContext(), toast = index.useWorkflowToast(), [busy, setBusy] = react.useState(!1), pending = instance.pendingEffects ?? [];
|
|
277
|
-
if (pending.length === 0) return null;
|
|
278
|
-
const runRegistered = async () => {
|
|
279
|
-
setBusy(!0);
|
|
280
|
-
try {
|
|
281
|
-
await drainEffectsFor(instance._id), toast.push({
|
|
282
|
-
id: index.TOAST_ID.effectsDrain,
|
|
283
|
-
status: "info",
|
|
284
|
-
title: "Ran the registered handlers"
|
|
285
|
-
});
|
|
286
|
-
} catch (err) {
|
|
287
|
-
toast.push({
|
|
288
|
-
id: index.TOAST_ID.effectsDrain,
|
|
289
|
-
status: "error",
|
|
290
|
-
title: "Failed to run pending effects",
|
|
291
|
-
description: index.describeError(err)
|
|
292
|
-
});
|
|
293
|
-
} finally {
|
|
294
|
-
setBusy(!1);
|
|
295
|
-
}
|
|
296
|
-
}, resolve = async (effectKey, status) => {
|
|
297
|
-
setBusy(!0);
|
|
298
|
-
try {
|
|
299
|
-
await completeEffectFor(instance._id, {
|
|
300
|
-
effectKey: effectKey,
|
|
301
|
-
status: status,
|
|
302
|
-
detail: "Resolved in Studio"
|
|
303
|
-
}), toast.push({
|
|
304
|
-
id: index.TOAST_ID.effectResolve,
|
|
305
|
-
status: "info",
|
|
306
|
-
title: `Effect marked as ${status}`
|
|
307
|
-
});
|
|
308
|
-
} catch (err) {
|
|
309
|
-
toast.push({
|
|
310
|
-
id: index.TOAST_ID.effectResolve,
|
|
311
|
-
status: "error",
|
|
312
|
-
title: "Failed to resolve the effect",
|
|
313
|
-
description: index.describeError(err)
|
|
314
|
-
});
|
|
315
|
-
} finally {
|
|
316
|
-
setBusy(!1);
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
/* @__PURE__ */
|
|
320
|
-
return jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
321
|
-
children: pending.map(fx => /* @__PURE__ */ jsxRuntime.jsx(PendingEffectRow, {
|
|
322
|
-
busy: busy,
|
|
323
|
-
effect: fx,
|
|
324
|
-
instanceId: instance._id,
|
|
325
|
-
now: now,
|
|
326
|
-
onResolve: status => resolve(fx._key, status),
|
|
327
|
-
onRunHandlers: runRegistered,
|
|
328
|
-
registered: fx.name in effectHandlers
|
|
329
|
-
}, fx._key))
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function PendingEffectRow({busy: busy, effect: effect, instanceId: instanceId, now: now, onResolve: onResolve, onRunHandlers: onRunHandlers, registered: registered}) {
|
|
334
|
-
const label = effect.title ?? effect.name, avatarSize = index.useAvatarSize();
|
|
335
|
-
/* @__PURE__ */
|
|
336
|
-
return jsxRuntime.jsxs(ui.Flex, {
|
|
337
|
-
align: "center",
|
|
338
|
-
gap: 2,
|
|
339
|
-
children: [
|
|
340
|
-
/* @__PURE__ */ jsxRuntime.jsx(FeedGlyph, {
|
|
341
|
-
hint: "Waiting to run",
|
|
342
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Clock.ClockIcon, {})
|
|
343
|
-
}),
|
|
344
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
345
|
-
align: "center",
|
|
346
|
-
flex: 1,
|
|
347
|
-
gap: 1,
|
|
348
|
-
style: {
|
|
349
|
-
minWidth: 0
|
|
350
|
-
},
|
|
351
|
-
children: [
|
|
352
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
353
|
-
style: {
|
|
354
|
-
minWidth: 0
|
|
355
|
-
},
|
|
356
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, {
|
|
357
|
-
size: 1,
|
|
358
|
-
textOverflow: "ellipsis",
|
|
359
|
-
children: [ effect.title ?? /* @__PURE__ */ jsxRuntime.jsx(CodeChip, {
|
|
360
|
-
value: effect.name
|
|
361
|
-
}), registered ? " — ready to run in Studio" : " — waiting for the runtime" ]
|
|
362
|
-
})
|
|
363
|
-
}),
|
|
364
|
-
/* @__PURE__ */ jsxRuntime.jsx(FeedStamp, {
|
|
365
|
-
at: effect.queuedAt,
|
|
366
|
-
now: now
|
|
367
|
-
}) ]
|
|
368
|
-
}),
|
|
369
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
370
|
-
align: "center",
|
|
371
|
-
flex: "none",
|
|
372
|
-
style: {
|
|
373
|
-
height: avatarSize
|
|
374
|
-
},
|
|
375
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(index.HintedMenuButton, {
|
|
376
|
-
button: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
377
|
-
"aria-label": `Resolve ${label}`,
|
|
378
|
-
disabled: busy,
|
|
379
|
-
fontSize: 1,
|
|
380
|
-
icon: EllipsisHorizontal.EllipsisHorizontalIcon,
|
|
381
|
-
mode: "bleed",
|
|
382
|
-
padding: 2
|
|
383
|
-
}),
|
|
384
|
-
hint: "Resolve",
|
|
385
|
-
id: `pending-effect-menu-${instanceId}-${effect._key}`,
|
|
386
|
-
menu: /* @__PURE__ */ jsxRuntime.jsxs(ui.Menu, {
|
|
387
|
-
children: [ registered ? /* @__PURE__ */ jsxRuntime.jsx(ui.MenuItem, {
|
|
388
|
-
onClick: onRunHandlers,
|
|
389
|
-
text: "Run registered handlers"
|
|
390
|
-
}) : null,
|
|
391
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.MenuItem, {
|
|
392
|
-
onClick: () => onResolve("done"),
|
|
393
|
-
text: "Mark done"
|
|
394
|
-
}),
|
|
395
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.MenuItem, {
|
|
396
|
-
onClick: () => onResolve("failed"),
|
|
397
|
-
text: "Mark failed",
|
|
398
|
-
tone: "critical"
|
|
399
|
-
}) ]
|
|
400
|
-
}),
|
|
401
|
-
popover: {
|
|
402
|
-
placement: "bottom-end",
|
|
403
|
-
portal: !0
|
|
404
|
-
}
|
|
405
|
-
})
|
|
406
|
-
}) ]
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
function ActivityLog({instance: instance, definition: definition}) {
|
|
411
|
-
const titles = react.useMemo(() => makeTitleResolver(definition), [ definition ]), entries = react.useMemo(() => instance.history.toReversed(), [ instance.history ]), [now, setNow] = react.useState(() => /* @__PURE__ */ new Date), [expanded, setExpanded] = react.useState(!1);
|
|
412
|
-
react.useEffect(() => {
|
|
413
|
-
const timer = setInterval(() => setNow(/* @__PURE__ */ new Date), 6e4);
|
|
414
|
-
return () => clearInterval(timer);
|
|
415
|
-
}, []);
|
|
416
|
-
const history = historyWindow({
|
|
417
|
-
entries: entries,
|
|
418
|
-
expanded: expanded
|
|
419
|
-
});
|
|
420
|
-
return entries.length === 0 && (instance.pendingEffects ?? []).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
421
|
-
muted: !0,
|
|
422
|
-
size: 1,
|
|
423
|
-
children: "No activity yet"
|
|
424
|
-
}) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
425
|
-
gap: 3,
|
|
426
|
-
children: [
|
|
427
|
-
/* @__PURE__ */ jsxRuntime.jsx(PendingEffectRows, {
|
|
428
|
-
instance: instance,
|
|
429
|
-
now: now
|
|
430
|
-
}), history.shown.map(h => /* @__PURE__ */ jsxRuntime.jsx(HistoryRow, {
|
|
431
|
-
entry: h,
|
|
432
|
-
now: now,
|
|
433
|
-
titles: titles
|
|
434
|
-
}, h._key)), history.overflows ? /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
435
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
436
|
-
fontSize: 1,
|
|
437
|
-
mode: "bleed",
|
|
438
|
-
onClick: () => setExpanded(!expanded),
|
|
439
|
-
padding: 2,
|
|
440
|
-
text: expanded ? "Show less history" : "Show all history"
|
|
441
|
-
})
|
|
442
|
-
}) : null ]
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
function FeedStamp({at: at, now: now}) {
|
|
447
|
-
/* @__PURE__ */
|
|
448
|
-
return jsxRuntime.jsxs(ui.Flex, {
|
|
449
|
-
align: "center",
|
|
450
|
-
flex: "none",
|
|
451
|
-
gap: 1,
|
|
452
|
-
children: [
|
|
453
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
454
|
-
muted: !0,
|
|
455
|
-
size: 1,
|
|
456
|
-
children: "·"
|
|
457
|
-
}),
|
|
458
|
-
/* @__PURE__ */ jsxRuntime.jsx(index.HoverHint, {
|
|
459
|
-
text: index.formatDateTime(at),
|
|
460
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
461
|
-
muted: !0,
|
|
462
|
-
size: 1,
|
|
463
|
-
style: {
|
|
464
|
-
whiteSpace: "nowrap"
|
|
465
|
-
},
|
|
466
|
-
children: index.formatShortAgo(at, now)
|
|
467
|
-
})
|
|
468
|
-
}) ]
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
function HistoryRow({entry: entry, now: now, titles: titles}) {
|
|
473
|
-
const line = historyLine(entry, titles);
|
|
474
|
-
/* @__PURE__ */
|
|
475
|
-
return jsxRuntime.jsxs(ui.Flex, {
|
|
476
|
-
align: "center",
|
|
477
|
-
gap: 2,
|
|
478
|
-
children: [ line.actorId === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(FeedGlyph, {
|
|
479
|
-
hint: "The workflow",
|
|
480
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Cog.CogIcon, {})
|
|
481
|
-
}) : /* @__PURE__ */ jsxRuntime.jsx(index.UserAvatar, {
|
|
482
|
-
id: line.actorId
|
|
483
|
-
}),
|
|
484
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
485
|
-
align: "center",
|
|
486
|
-
flex: 1,
|
|
487
|
-
gap: 1,
|
|
488
|
-
style: {
|
|
489
|
-
minWidth: 0
|
|
490
|
-
},
|
|
491
|
-
children: [
|
|
492
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
493
|
-
style: {
|
|
494
|
-
minWidth: 0
|
|
495
|
-
},
|
|
496
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, {
|
|
497
|
-
muted: !0,
|
|
498
|
-
size: 1,
|
|
499
|
-
textOverflow: "ellipsis",
|
|
500
|
-
children: [ line.actorId === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
501
|
-
children: [
|
|
502
|
-
/* @__PURE__ */ jsxRuntime.jsx(ActorNameSpan, {
|
|
503
|
-
id: line.actorId
|
|
504
|
-
}), " " ]
|
|
505
|
-
}), line.parts.map((part, index2) => typeof part == "string" ? part : /* @__PURE__ */ jsxRuntime.jsx(CodeChip, {
|
|
506
|
-
value: part.code
|
|
507
|
-
}, index2)) ]
|
|
508
|
-
})
|
|
509
|
-
}),
|
|
510
|
-
/* @__PURE__ */ jsxRuntime.jsx(FeedStamp, {
|
|
511
|
-
at: entry.at,
|
|
512
|
-
now: now
|
|
513
|
-
}) ]
|
|
514
|
-
}) ]
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
function ActorNameSpan({id: id}) {
|
|
519
|
-
const {name: name} = index.useUserDisplay(id), {font: font} = ui.useTheme_v2();
|
|
520
|
-
/* @__PURE__ */
|
|
521
|
-
return jsxRuntime.jsx("span", {
|
|
522
|
-
style: {
|
|
523
|
-
fontWeight: font.text.weights.medium
|
|
524
|
-
},
|
|
525
|
-
children: name
|
|
526
|
-
});
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
function FeedGlyph({hint: hint, icon: icon}) {
|
|
530
|
-
const size = index.useAvatarSize();
|
|
531
|
-
/* @__PURE__ */
|
|
532
|
-
return jsxRuntime.jsx(index.HoverHint, {
|
|
533
|
-
text: hint,
|
|
534
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
535
|
-
align: "center",
|
|
536
|
-
flex: "none",
|
|
537
|
-
justify: "center",
|
|
538
|
-
style: {
|
|
539
|
-
height: size,
|
|
540
|
-
width: size
|
|
541
|
-
},
|
|
542
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
543
|
-
muted: !0,
|
|
544
|
-
size: 1,
|
|
545
|
-
children: icon
|
|
546
|
-
})
|
|
547
|
-
})
|
|
548
|
-
});
|
|
549
|
-
}
|
|
550
|
-
|
|
551
46
|
function documentRefsOf(instance) {
|
|
552
47
|
const seen = /* @__PURE__ */ new Map;
|
|
553
48
|
for (const ref of workflowEngine.entryDocRefs(instance.fields)) seen.has(ref.id) || seen.set(ref.id, ref);
|
|
@@ -781,7 +276,7 @@ function NotFoundNote({id: id}) {
|
|
|
781
276
|
/* @__PURE__ */
|
|
782
277
|
return jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
783
278
|
children: [ "Unable to find workflow with id “",
|
|
784
|
-
/* @__PURE__ */ jsxRuntime.jsx(CodeChip, {
|
|
279
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.CodeChip, {
|
|
785
280
|
value: id
|
|
786
281
|
}), "”." ]
|
|
787
282
|
});
|
|
@@ -836,7 +331,7 @@ function InstanceDetailBody({entry: entry, framed: framed, subject: subject}) {
|
|
|
836
331
|
/* @__PURE__ */ jsxRuntime.jsx(SectionHeading, {
|
|
837
332
|
children: "History"
|
|
838
333
|
}),
|
|
839
|
-
/* @__PURE__ */ jsxRuntime.jsx(ActivityLog, {
|
|
334
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.ActivityLog, {
|
|
840
335
|
definition: definition,
|
|
841
336
|
instance: instance
|
|
842
337
|
}) ]
|
|
@@ -1549,7 +1044,7 @@ function taskRowsOf(args) {
|
|
|
1549
1044
|
open: index.isOpenActivityStatus(activity.status),
|
|
1550
1045
|
dates: index.datesOf(fields),
|
|
1551
1046
|
dueDates: index.dueDatesOf(fields),
|
|
1552
|
-
|
|
1047
|
+
assignees: index.assigneesOf(fields),
|
|
1553
1048
|
assignedToMe: identity !== void 0 && index.isActivityAssignedTo({
|
|
1554
1049
|
state: fields,
|
|
1555
1050
|
who: identity
|
|
@@ -1646,7 +1141,7 @@ function taskRowRender(row, entry) {
|
|
|
1646
1141
|
return entry?.evaluation === void 0 || activityEval === void 0 ? {
|
|
1647
1142
|
face: index.committedRowFace(row),
|
|
1648
1143
|
assignState: row.assignControl,
|
|
1649
|
-
|
|
1144
|
+
assignees: row.assignees,
|
|
1650
1145
|
dateState: row.dateControl,
|
|
1651
1146
|
dueDates: row.dueDates,
|
|
1652
1147
|
terminalActions: [],
|
|
@@ -2083,7 +1578,7 @@ function statusArm(row, statuses) {
|
|
|
2083
1578
|
|
|
2084
1579
|
function assigneeArm(row, assigneeIds) {
|
|
2085
1580
|
const arm = activeArm(assigneeIds);
|
|
2086
|
-
return arm ?
|
|
1581
|
+
return arm ? row.assignees.some(item => item.type === "user" && arm.includes(item.id)) : !0;
|
|
2087
1582
|
}
|
|
2088
1583
|
|
|
2089
1584
|
function rowMatches(args) {
|
|
@@ -2607,6 +2102,55 @@ function FilterRowPortal({filters: filters, onChange: onChange, options: options
|
|
|
2607
2102
|
}), slot) : null;
|
|
2608
2103
|
}
|
|
2609
2104
|
|
|
2105
|
+
function CollapsibleBand({header: header, children: children, background: background = !1, defaultOpen: defaultOpen = !0, onToggle: onToggle, open: controlledOpen, sticky: sticky = !1, title: title}) {
|
|
2106
|
+
const [heldOpen, setHeldOpen] = react.useState(defaultOpen), open = controlledOpen ?? heldOpen, toggle = onToggle ?? (() => setHeldOpen(value => !value)), verb = open ? "Collapse" : "Expand";
|
|
2107
|
+
/* @__PURE__ */
|
|
2108
|
+
return jsxRuntime.jsxs(ui.Stack, {
|
|
2109
|
+
gap: 1,
|
|
2110
|
+
children: [
|
|
2111
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
2112
|
+
onDoubleClick: event => {
|
|
2113
|
+
event.target instanceof Element && event.target.closest("a, button") || toggle();
|
|
2114
|
+
},
|
|
2115
|
+
padding: 1,
|
|
2116
|
+
radius: 3,
|
|
2117
|
+
style: {
|
|
2118
|
+
userSelect: "none",
|
|
2119
|
+
...sticky ? {
|
|
2120
|
+
position: "sticky",
|
|
2121
|
+
top: 0,
|
|
2122
|
+
zIndex: 1
|
|
2123
|
+
} : {}
|
|
2124
|
+
},
|
|
2125
|
+
tone: background ? "transparent" : "inherit",
|
|
2126
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
2127
|
+
align: "center",
|
|
2128
|
+
children: [
|
|
2129
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
2130
|
+
"aria-label": `${verb} ${title}`,
|
|
2131
|
+
fontSize: 1,
|
|
2132
|
+
icon: open ? ChevronDown.ChevronDownIcon : ChevronRight.ChevronRightIcon,
|
|
2133
|
+
mode: "bleed",
|
|
2134
|
+
onClick: toggle,
|
|
2135
|
+
padding: 2
|
|
2136
|
+
}), header ]
|
|
2137
|
+
})
|
|
2138
|
+
}), open ? children : null ]
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
function TrailingHairline() {
|
|
2143
|
+
/* @__PURE__ */
|
|
2144
|
+
return jsxRuntime.jsx(ui.Box, {
|
|
2145
|
+
flex: 1,
|
|
2146
|
+
paddingLeft: 1,
|
|
2147
|
+
paddingRight: 1,
|
|
2148
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.Hairline, {
|
|
2149
|
+
weight: .5
|
|
2150
|
+
})
|
|
2151
|
+
});
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2610
2154
|
function isPlainClick(event) {
|
|
2611
2155
|
return !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey;
|
|
2612
2156
|
}
|
|
@@ -2680,7 +2224,7 @@ function targetOf(row) {
|
|
|
2680
2224
|
function DocumentBand({group: group, ...wiring}) {
|
|
2681
2225
|
const {open: open, toggle: toggle} = useBandOpen(wiring.bands, group.key);
|
|
2682
2226
|
/* @__PURE__ */
|
|
2683
|
-
return jsxRuntime.jsx(
|
|
2227
|
+
return jsxRuntime.jsx(CollapsibleBand, {
|
|
2684
2228
|
background: !0,
|
|
2685
2229
|
onToggle: toggle,
|
|
2686
2230
|
open: open,
|
|
@@ -2707,7 +2251,7 @@ function DocumentBand({group: group, ...wiring}) {
|
|
|
2707
2251
|
function UngroupedBand({instances: instances, ...wiring}) {
|
|
2708
2252
|
const {open: open, toggle: toggle} = useBandOpen(wiring.bands, UNGROUPED_BAND_KEY);
|
|
2709
2253
|
/* @__PURE__ */
|
|
2710
|
-
return jsxRuntime.jsx(
|
|
2254
|
+
return jsxRuntime.jsx(CollapsibleBand, {
|
|
2711
2255
|
background: !0,
|
|
2712
2256
|
onToggle: toggle,
|
|
2713
2257
|
open: open,
|
|
@@ -2739,7 +2283,7 @@ function InstanceBands({instances: instances, ...wiring}) {
|
|
|
2739
2283
|
function InstanceBand({bands: bands, instance: instance, onOpenInstance: onOpenInstance, onOpenTask: onOpenTask, showTerminalActions: showTerminalActions}) {
|
|
2740
2284
|
const {open: open, toggle: toggle} = useBandOpen(bands, instance.instanceId), {resolvePathFromState: resolvePathFromState} = router.useRouter();
|
|
2741
2285
|
/* @__PURE__ */
|
|
2742
|
-
return jsxRuntime.jsx(
|
|
2286
|
+
return jsxRuntime.jsx(CollapsibleBand, {
|
|
2743
2287
|
onToggle: toggle,
|
|
2744
2288
|
open: open,
|
|
2745
2289
|
title: instance.title,
|
|
@@ -2776,7 +2320,7 @@ function InstanceBand({bands: bands, instance: instance, onOpenInstance: onOpenI
|
|
|
2776
2320
|
}) ]
|
|
2777
2321
|
})
|
|
2778
2322
|
}),
|
|
2779
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2323
|
+
/* @__PURE__ */ jsxRuntime.jsx(TrailingHairline, {}) ]
|
|
2780
2324
|
}),
|
|
2781
2325
|
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
2782
2326
|
paddingLeft: 5,
|
|
@@ -2812,7 +2356,7 @@ function TaskActivityRow({row: row, onOpen: onOpen, showTerminalActions: showTer
|
|
|
2812
2356
|
stale: render.stale,
|
|
2813
2357
|
children: /* @__PURE__ */ jsxRuntime.jsx(index.ActivityRow, {
|
|
2814
2358
|
assignState: render.assignState,
|
|
2815
|
-
|
|
2359
|
+
assignees: render.assignees,
|
|
2816
2360
|
dateState: render.dateState,
|
|
2817
2361
|
dueDates: render.dueDates,
|
|
2818
2362
|
face: render.face,
|