@sanity/workflow-studio-plugin 0.5.0 → 0.21.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 +232 -0
- package/README.md +45 -63
- package/dist/_chunks-cjs/index.cjs +1046 -502
- package/dist/_chunks-cjs/workflows-tool-root.cjs +551 -59
- package/dist/_chunks-es/index.js +1064 -522
- package/dist/_chunks-es/workflows-tool-root.js +556 -62
- package/dist/index.cjs +0 -6
- package/dist/index.d.cts +16 -74
- package/dist/index.d.ts +16 -74
- package/dist/index.js +2 -2
- package/package.json +16 -9
|
@@ -1,22 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var jsxRuntime = require("react/jsx-runtime"), ui = require("@sanity/ui"), react = require("react"), router = require("sanity/router"), index = require("./index.cjs"), ArrowLeft = require("@sanity/icons/ArrowLeft"), workflowDiagram = require("@sanity/workflow-diagram"), workflowEngine = require("@sanity/workflow-engine"), 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"),
|
|
4
|
-
|
|
5
|
-
function SpinnerSlot({busy: busy}) {
|
|
6
|
-
/* @__PURE__ */
|
|
7
|
-
return jsxRuntime.jsx(ui.Flex, {
|
|
8
|
-
align: "center",
|
|
9
|
-
flex: "none",
|
|
10
|
-
justify: "center",
|
|
11
|
-
style: {
|
|
12
|
-
width: 19,
|
|
13
|
-
height: 19
|
|
14
|
-
},
|
|
15
|
-
children: busy ? /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {
|
|
16
|
-
muted: !0
|
|
17
|
-
}) : null
|
|
18
|
-
});
|
|
19
|
-
}
|
|
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"), ArrowLeft = require("@sanity/icons/ArrowLeft"), workflowDiagram = require("@sanity/workflow-diagram"), workflowEngine = require("@sanity/workflow-engine"), Add = require("@sanity/icons/Add"), Search = require("@sanity/icons/Search"), sanity = require("sanity"), 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"), Calendar = require("@sanity/icons/Calendar"), workflowStudio = require("@sanity/workflow-studio");
|
|
20
4
|
|
|
21
5
|
function documentRefsOf(instance) {
|
|
22
6
|
const seen = /* @__PURE__ */ new Map;
|
|
@@ -34,14 +18,19 @@ function InstanceTaskLists({entry: entry, onOpenActivity: onOpenActivity}) {
|
|
|
34
18
|
onOpenActivity: onOpenActivity
|
|
35
19
|
}),
|
|
36
20
|
/* @__PURE__ */ jsxRuntime.jsx(index.TodoItemsList, {
|
|
37
|
-
entry: entry
|
|
21
|
+
entry: entry,
|
|
22
|
+
surface: "tool-instance-detail"
|
|
38
23
|
}) ]
|
|
39
24
|
})
|
|
40
25
|
});
|
|
41
26
|
}
|
|
42
27
|
|
|
43
28
|
function WorkflowInstanceDetail({instanceId: instanceId, onBack: onBack}) {
|
|
44
|
-
const entry = index.useWorkflowInstanceEntry(instanceId)
|
|
29
|
+
const entry = index.useWorkflowInstanceEntry(instanceId);
|
|
30
|
+
index.useLogEventOnMount(index.WorkflowInstanceDetailViewed, {
|
|
31
|
+
instanceId: instanceId
|
|
32
|
+
});
|
|
33
|
+
const [graceOver, setGraceOver] = react.useState(!1);
|
|
45
34
|
return react.useEffect(() => {
|
|
46
35
|
const timer = setTimeout(() => setGraceOver(!0), 2500);
|
|
47
36
|
return () => clearTimeout(timer);
|
|
@@ -135,7 +124,8 @@ function InstanceDetailPanel({entry: entry, onBack: onBack}) {
|
|
|
135
124
|
breadcrumb: index.instanceBreadcrumb(instance, definition),
|
|
136
125
|
definition: definition,
|
|
137
126
|
entry: entry,
|
|
138
|
-
onClose: () => setOpenActivity(null)
|
|
127
|
+
onClose: () => setOpenActivity(null),
|
|
128
|
+
source: "tool-instance-detail"
|
|
139
129
|
}) : null ]
|
|
140
130
|
});
|
|
141
131
|
}
|
|
@@ -181,7 +171,7 @@ function DetailHeader({entry: entry, definition: definition, onBack: onBack}) {
|
|
|
181
171
|
}) : /* @__PURE__ */ jsxRuntime.jsx(index.AbortedBadge, {
|
|
182
172
|
instance: instance
|
|
183
173
|
}),
|
|
184
|
-
/* @__PURE__ */ jsxRuntime.jsx(SpinnerSlot, {
|
|
174
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.SpinnerSlot, {
|
|
185
175
|
busy: !ready || index.isEvaluationStale(entry)
|
|
186
176
|
}) ]
|
|
187
177
|
})
|
|
@@ -276,7 +266,8 @@ function NewWorkflowButton() {
|
|
|
276
266
|
onPick: definition => {
|
|
277
267
|
setOpen(!1), openStartDialog({
|
|
278
268
|
definition: definition.name,
|
|
279
|
-
label: definition.title
|
|
269
|
+
label: definition.title,
|
|
270
|
+
source: "tool"
|
|
280
271
|
});
|
|
281
272
|
}
|
|
282
273
|
}) : null,
|
|
@@ -383,7 +374,8 @@ function ToolActivityDialog({target: target, onClose: onClose}) {
|
|
|
383
374
|
definition: definition,
|
|
384
375
|
document: documentRefsOf(entry.instance)[0],
|
|
385
376
|
entry: entry,
|
|
386
|
-
onClose: onClose
|
|
377
|
+
onClose: onClose,
|
|
378
|
+
source: "tool-task-list"
|
|
387
379
|
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, {
|
|
388
380
|
header: "Loading activity…",
|
|
389
381
|
id: "workflow-activity-detail",
|
|
@@ -398,13 +390,154 @@ function ToolActivityDialog({target: target, onClose: onClose}) {
|
|
|
398
390
|
});
|
|
399
391
|
}
|
|
400
392
|
|
|
393
|
+
const GROUP_DEFAULT_OPEN = !0;
|
|
394
|
+
|
|
395
|
+
function instanceBandDefaultOpen(segment) {
|
|
396
|
+
return segment === "for-me";
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const UNGROUPED_BAND_KEY = "section:no-document", PAYLOAD_VERSION = 1, MAX_ENTRIES = 200;
|
|
400
|
+
|
|
401
|
+
function bandStateStorageKey(scope) {
|
|
402
|
+
return `sanity.workflows.tool.bands:${scope}`;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function isRecord(value) {
|
|
406
|
+
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function bandEntryOf(value) {
|
|
410
|
+
if (!isRecord(value)) return;
|
|
411
|
+
const {open: open, touched: touched} = value;
|
|
412
|
+
if (!(typeof open != "boolean" || typeof touched != "number") && Number.isFinite(touched)) return {
|
|
413
|
+
open: open,
|
|
414
|
+
touched: touched
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function parsePayload(raw) {
|
|
419
|
+
try {
|
|
420
|
+
const parsed = JSON.parse(raw);
|
|
421
|
+
if (!isRecord(parsed) || parsed.version !== PAYLOAD_VERSION || !isRecord(parsed.bands)) return;
|
|
422
|
+
const entries = [];
|
|
423
|
+
for (const [key, value] of Object.entries(parsed.bands)) {
|
|
424
|
+
const entry = bandEntryOf(value);
|
|
425
|
+
if (entry === void 0) return;
|
|
426
|
+
entries.push([ key, entry ]);
|
|
427
|
+
}
|
|
428
|
+
return Object.fromEntries(entries);
|
|
429
|
+
} catch {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function readStored(storage, storageKey) {
|
|
435
|
+
if (!storage) return {
|
|
436
|
+
entries: void 0,
|
|
437
|
+
corrupt: !1
|
|
438
|
+
};
|
|
439
|
+
let raw;
|
|
440
|
+
try {
|
|
441
|
+
raw = storage.getItem(storageKey);
|
|
442
|
+
} catch {
|
|
443
|
+
return {
|
|
444
|
+
entries: void 0,
|
|
445
|
+
corrupt: !1
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
if (raw === null) return {
|
|
449
|
+
entries: {},
|
|
450
|
+
corrupt: !1
|
|
451
|
+
};
|
|
452
|
+
const entries = parsePayload(raw);
|
|
453
|
+
return {
|
|
454
|
+
entries: entries,
|
|
455
|
+
corrupt: entries === void 0
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function writeStored(args) {
|
|
460
|
+
if (!args.storage) return !1;
|
|
461
|
+
try {
|
|
462
|
+
return args.storage.setItem(args.storageKey, JSON.stringify({
|
|
463
|
+
version: PAYLOAD_VERSION,
|
|
464
|
+
bands: args.entries
|
|
465
|
+
})), !0;
|
|
466
|
+
} catch {
|
|
467
|
+
return !1;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function baseEntries(args) {
|
|
472
|
+
return args.stored === void 0 ? args.held : args.unpersisted ? mergeByTouched(args.stored, args.held) : args.stored;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function mergeByTouched(stored, held) {
|
|
476
|
+
const merged = {
|
|
477
|
+
...stored
|
|
478
|
+
};
|
|
479
|
+
for (const [key, entry] of Object.entries(held)) {
|
|
480
|
+
const persisted = merged[key];
|
|
481
|
+
(persisted === void 0 || entry.touched >= persisted.touched) && (merged[key] = entry);
|
|
482
|
+
}
|
|
483
|
+
return merged;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function prune(entries) {
|
|
487
|
+
const held = Object.entries(entries);
|
|
488
|
+
return held.length <= MAX_ENTRIES ? entries : Object.fromEntries(held.sort(([, a], [, b]) => b.touched - a.touched).slice(0, MAX_ENTRIES));
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function togglesOf(entries) {
|
|
492
|
+
return new Map(Object.entries(entries).map(([key, entry]) => [ key, entry.open ]));
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function defaultStorage() {
|
|
496
|
+
try {
|
|
497
|
+
return globalThis.localStorage;
|
|
498
|
+
} catch {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function createBandStateStore(args) {
|
|
504
|
+
const storage = args.storage ?? defaultStorage(), initial = readStored(storage, args.storageKey);
|
|
505
|
+
initial.corrupt && writeStored({
|
|
506
|
+
storage: storage,
|
|
507
|
+
storageKey: args.storageKey,
|
|
508
|
+
entries: {}
|
|
509
|
+
});
|
|
510
|
+
let held = initial.entries ?? {}, unpersisted = !1;
|
|
511
|
+
return {
|
|
512
|
+
read: () => togglesOf(held),
|
|
513
|
+
setOpen(key, open) {
|
|
514
|
+
const stored = readStored(storage, args.storageKey).entries, base = baseEntries({
|
|
515
|
+
stored: stored,
|
|
516
|
+
held: held,
|
|
517
|
+
unpersisted: unpersisted
|
|
518
|
+
});
|
|
519
|
+
return held = prune({
|
|
520
|
+
...base,
|
|
521
|
+
[key]: {
|
|
522
|
+
open: open,
|
|
523
|
+
touched: Date.now()
|
|
524
|
+
}
|
|
525
|
+
}), unpersisted = !writeStored({
|
|
526
|
+
storage: storage,
|
|
527
|
+
storageKey: args.storageKey,
|
|
528
|
+
entries: held
|
|
529
|
+
}), togglesOf(held);
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
|
|
401
534
|
function datesOf(state) {
|
|
402
535
|
return state.filter(entry => entry._type === "date" || entry._type === "datetime").map(entry => entry.value).filter(value => typeof value == "string" && value !== "");
|
|
403
536
|
}
|
|
404
537
|
|
|
405
538
|
function spawnOrigins(instances) {
|
|
406
539
|
const origins = /* @__PURE__ */ new Map;
|
|
407
|
-
for (const parent of instances) for (const row of parent.subworkflows ?? []) origins.set(workflowEngine.
|
|
540
|
+
for (const parent of instances) for (const row of parent.subworkflows ?? []) origins.set(workflowEngine.toBareId(row.ref.id), {
|
|
408
541
|
parent: parent,
|
|
409
542
|
activityName: row.activity,
|
|
410
543
|
cohortStage: row.cohortStage
|
|
@@ -414,7 +547,7 @@ function spawnOrigins(instances) {
|
|
|
414
547
|
|
|
415
548
|
function rootOf(instance, byId) {
|
|
416
549
|
const rootRef = instance.ancestors[0];
|
|
417
|
-
return rootRef ? byId.get(workflowEngine.
|
|
550
|
+
return rootRef ? byId.get(workflowEngine.toBareId(rootRef.id)) ?? instance : instance;
|
|
418
551
|
}
|
|
419
552
|
|
|
420
553
|
function taskRowsOf(args) {
|
|
@@ -555,6 +688,223 @@ function taskRowRender(row, entry) {
|
|
|
555
688
|
};
|
|
556
689
|
}
|
|
557
690
|
|
|
691
|
+
const NO_ORPHANS = {
|
|
692
|
+
groupKeys: /* @__PURE__ */ new Set,
|
|
693
|
+
workflows: []
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
function localBareIds(group, contentResource) {
|
|
697
|
+
const ids = group.documents.map(doc => index.gdrLocality(doc.id, contentResource));
|
|
698
|
+
if (!ids.some(locality => !locality.parsed || !locality.local)) return ids.flatMap(locality => locality.parsed ? [ locality.parsed.documentId ] : []);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
function orphanProbeIds(groups, contentResource) {
|
|
702
|
+
const ids = /* @__PURE__ */ new Set;
|
|
703
|
+
for (const group of groups.withDocuments) for (const id of localBareIds(group, contentResource) ?? []) ids.add(id);
|
|
704
|
+
return [ ...ids ].sort();
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
function orphanVerdict(args) {
|
|
708
|
+
const groupKeys = /* @__PURE__ */ new Set, workflows = /* @__PURE__ */ new Map;
|
|
709
|
+
for (const group of args.groups.withDocuments) {
|
|
710
|
+
const ids = localBareIds(group, args.contentResource);
|
|
711
|
+
if (!(ids === void 0 || !ids.every(id => args.missing.has(id)))) {
|
|
712
|
+
groupKeys.add(group.key);
|
|
713
|
+
for (const band of group.instances) workflows.set(band.instanceId, {
|
|
714
|
+
instanceId: band.instanceId,
|
|
715
|
+
title: band.title,
|
|
716
|
+
documentIds: ids
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return groupKeys.size === 0 ? NO_ORPHANS : {
|
|
721
|
+
groupKeys: groupKeys,
|
|
722
|
+
workflows: [ ...workflows.values() ]
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
function hideOrphanedGroups(groups, orphaned) {
|
|
727
|
+
return orphaned.size === 0 ? groups : cutTaskGroups(groups, {
|
|
728
|
+
keepRow: () => !0,
|
|
729
|
+
keepGroup: group => !orphaned.has(group.key)
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
const DRAFT_PREFIX = "drafts.";
|
|
734
|
+
|
|
735
|
+
async function missingDocIds(client, ids) {
|
|
736
|
+
const present = await client.fetch("*[_id in $ids || _id in $drafts]._id", {
|
|
737
|
+
ids: ids,
|
|
738
|
+
drafts: ids.map(id => `${DRAFT_PREFIX}${id}`)
|
|
739
|
+
}, {
|
|
740
|
+
perspective: "raw"
|
|
741
|
+
}), found = new Set(present.map(id => id.startsWith(DRAFT_PREFIX) ? id.slice(DRAFT_PREFIX.length) : id)), candidates = ids.filter(id => !found.has(id)), versions = await Promise.all(candidates.map(id => client.fetch("*[_id in path($version)][0]._id", {
|
|
742
|
+
version: `versions.*.${id}`
|
|
743
|
+
}, {
|
|
744
|
+
perspective: "raw"
|
|
745
|
+
})));
|
|
746
|
+
return new Set(candidates.filter((_, index2) => versions[index2] === null));
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
async function settleOrphans(args) {
|
|
750
|
+
const ids = [ ...new Set(args.workflows.flatMap(workflow => workflow.documentIds)) ].sort(), missing = await args.probeMissing(ids), stillOrphaned = workflow => workflow.documentIds.every(id => missing.has(id));
|
|
751
|
+
let settled = 0;
|
|
752
|
+
const failures = [];
|
|
753
|
+
for (const workflow of args.workflows.filter(stillOrphaned)) try {
|
|
754
|
+
await args.abort({
|
|
755
|
+
instanceId: workflow.instanceId,
|
|
756
|
+
reason: "Subject document deleted"
|
|
757
|
+
}), settled += 1;
|
|
758
|
+
} catch (err) {
|
|
759
|
+
failures.push({
|
|
760
|
+
workflow: workflow,
|
|
761
|
+
message: index.describeError(err)
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
return {
|
|
765
|
+
settled: settled,
|
|
766
|
+
skipped: args.workflows.filter(workflow => !stillOrphaned(workflow)),
|
|
767
|
+
failures: failures
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
function workflowTally(workflows) {
|
|
772
|
+
const counts = /* @__PURE__ */ new Map;
|
|
773
|
+
for (const workflow of workflows) counts.set(workflow.title, (counts.get(workflow.title) ?? 0) + 1);
|
|
774
|
+
return [ ...counts ].map(([title, count]) => count === 1 ? title : `${title} ×${count}`);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
function settleToast(outcome) {
|
|
778
|
+
const total = outcome.settled + outcome.skipped.length + outcome.failures.length;
|
|
779
|
+
if (outcome.skipped.length === 0 && outcome.failures.length === 0) return {
|
|
780
|
+
status: "success",
|
|
781
|
+
title: outcome.settled === 1 ? "Cleaned up 1 workflow" : `Cleaned up ${outcome.settled} workflows`
|
|
782
|
+
};
|
|
783
|
+
const lines = [ ...outcome.skipped.map(workflow => `${workflow.title}: its document exists again — left running`), ...outcome.failures.map(failure => `${failure.workflow.title}: ${failure.message}`) ];
|
|
784
|
+
return {
|
|
785
|
+
status: "warning",
|
|
786
|
+
title: `Cleaned up ${outcome.settled} of ${total} workflows`,
|
|
787
|
+
description: lines.join(`\n`)
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
function recheckFailedToast(err) {
|
|
792
|
+
return {
|
|
793
|
+
status: "error",
|
|
794
|
+
title: "Nothing was cleaned up — the documents could not be re-checked",
|
|
795
|
+
description: index.describeError(err)
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
function OrphanedWorkflowsNote({orphans: orphans}) {
|
|
800
|
+
const [confirming, setConfirming] = react.useState(!1), count = orphans.workflows.length;
|
|
801
|
+
if (count === 0) return null;
|
|
802
|
+
const label = count === 1 ? "1 workflow is attached to a deleted document — its tasks aren’t listed." : `${count} workflows are attached to deleted documents — their tasks aren’t listed.`;
|
|
803
|
+
/* @__PURE__ */
|
|
804
|
+
return jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
805
|
+
children: [
|
|
806
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.CautionNote, {
|
|
807
|
+
action: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
808
|
+
fontSize: 1,
|
|
809
|
+
mode: "ghost",
|
|
810
|
+
onClick: () => setConfirming(!0),
|
|
811
|
+
padding: 2,
|
|
812
|
+
text: "Clean up…"
|
|
813
|
+
}),
|
|
814
|
+
label: label
|
|
815
|
+
}), confirming ? /* @__PURE__ */ jsxRuntime.jsx(SettleOrphansDialog, {
|
|
816
|
+
onClose: () => setConfirming(!1),
|
|
817
|
+
workflows: orphans.workflows
|
|
818
|
+
}) : null ]
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
function SettleOrphansDialog({workflows: workflows, onClose: onClose}) {
|
|
823
|
+
const {engine: engine} = index.useWorkflowContext(), client = sanity.useClient({
|
|
824
|
+
apiVersion: index.WORKFLOW_API_VERSION
|
|
825
|
+
}), toast = index.useClosableToast(), [pending, setPending] = react.useState(!1), confirm = async () => {
|
|
826
|
+
setPending(!0);
|
|
827
|
+
try {
|
|
828
|
+
const outcome = await settleOrphans({
|
|
829
|
+
workflows: workflows,
|
|
830
|
+
probeMissing: ids => missingDocIds(client, ids),
|
|
831
|
+
abort: args => engine.abortInstance(args)
|
|
832
|
+
});
|
|
833
|
+
toast.push(settleToast(outcome));
|
|
834
|
+
} catch (err) {
|
|
835
|
+
toast.push(recheckFailedToast(err));
|
|
836
|
+
}
|
|
837
|
+
onClose();
|
|
838
|
+
};
|
|
839
|
+
/* @__PURE__ */
|
|
840
|
+
return jsxRuntime.jsx(ui.Dialog, {
|
|
841
|
+
footer: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
842
|
+
padding: 3,
|
|
843
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
844
|
+
gap: 2,
|
|
845
|
+
justify: "flex-end",
|
|
846
|
+
children: [
|
|
847
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
848
|
+
disabled: pending,
|
|
849
|
+
fontSize: 1,
|
|
850
|
+
mode: "bleed",
|
|
851
|
+
onClick: onClose,
|
|
852
|
+
padding: 2,
|
|
853
|
+
text: "Cancel"
|
|
854
|
+
}),
|
|
855
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
856
|
+
fontSize: 1,
|
|
857
|
+
loading: pending,
|
|
858
|
+
onClick: () => {
|
|
859
|
+
confirm();
|
|
860
|
+
},
|
|
861
|
+
padding: 2,
|
|
862
|
+
text: workflows.length === 1 ? "Clean up 1 workflow" : `Clean up ${workflows.length} workflows`
|
|
863
|
+
}) ]
|
|
864
|
+
})
|
|
865
|
+
}),
|
|
866
|
+
header: "Clean up workflows",
|
|
867
|
+
id: "settle-orphaned-workflows",
|
|
868
|
+
onClose: onClose,
|
|
869
|
+
width: 0,
|
|
870
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
871
|
+
padding: 4,
|
|
872
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
873
|
+
gap: 4,
|
|
874
|
+
children: [
|
|
875
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
876
|
+
muted: !0,
|
|
877
|
+
size: 1,
|
|
878
|
+
children: "The following workflows exist for documents which have since been deleted:"
|
|
879
|
+
}),
|
|
880
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Stack, {
|
|
881
|
+
as: "ul",
|
|
882
|
+
gap: 2,
|
|
883
|
+
style: {
|
|
884
|
+
listStyle: "disc",
|
|
885
|
+
margin: 0,
|
|
886
|
+
paddingLeft: "1.25em"
|
|
887
|
+
},
|
|
888
|
+
children: workflowTally(workflows).map(line => /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
889
|
+
as: "li",
|
|
890
|
+
size: 1,
|
|
891
|
+
style: {
|
|
892
|
+
display: "list-item"
|
|
893
|
+
},
|
|
894
|
+
weight: "medium",
|
|
895
|
+
children: line
|
|
896
|
+
}, line))
|
|
897
|
+
}),
|
|
898
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
899
|
+
muted: !0,
|
|
900
|
+
size: 1,
|
|
901
|
+
children: "Cleaning up these workflows will close them."
|
|
902
|
+
}) ]
|
|
903
|
+
})
|
|
904
|
+
})
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
|
|
558
908
|
function taskFilterOptions(groups) {
|
|
559
909
|
const workflows = /* @__PURE__ */ new Map, documents = /* @__PURE__ */ new Map;
|
|
560
910
|
for (const group of groups.withDocuments) {
|
|
@@ -571,8 +921,33 @@ function taskFilterOptions(groups) {
|
|
|
571
921
|
};
|
|
572
922
|
}
|
|
573
923
|
|
|
924
|
+
function activeEntries(filters) {
|
|
925
|
+
return Object.entries(filters).filter(([, value]) => value !== void 0 && (!Array.isArray(value) || value.length > 0));
|
|
926
|
+
}
|
|
927
|
+
|
|
574
928
|
function hasActiveFilters(filters) {
|
|
575
|
-
return
|
|
929
|
+
return activeEntries(filters).length > 0;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
function sameFilters(a, b) {
|
|
933
|
+
return sameValueSet(a.statuses, b.statuses) && sameValueSet(a.workflows, b.workflows) && sameValueSet(a.documentIds, b.documentIds) && sameValueSet(a.assigneeIds, b.assigneeIds) && sameDate(a.date, b.date);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
function sameValueSet(a, b) {
|
|
937
|
+
const av = a ?? [], bv = b ?? [];
|
|
938
|
+
return av.length === bv.length && av.every(value => bv.includes(value));
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
function sameDate(a, b) {
|
|
942
|
+
return typeof a == "object" && typeof b == "object" ? a.before === b.before : a === b;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
function taskFilterTelemetry(filters) {
|
|
946
|
+
const entries = activeEntries(filters);
|
|
947
|
+
return {
|
|
948
|
+
filterKinds: entries.map(([key]) => key).sort(),
|
|
949
|
+
filterCount: entries.reduce((n, [, value]) => n + (Array.isArray(value) ? value.length : 1), 0)
|
|
950
|
+
};
|
|
576
951
|
}
|
|
577
952
|
|
|
578
953
|
function toggledValue(args) {
|
|
@@ -727,7 +1102,12 @@ function useDocPreviewTitles(documents) {
|
|
|
727
1102
|
const HITS_CAP = 6;
|
|
728
1103
|
|
|
729
1104
|
function TaskFilterMenu({filters: filters, options: options, onChange: onChange}) {
|
|
730
|
-
const [open, setOpen] = react.useState(!1),
|
|
1105
|
+
const [open, setOpen] = react.useState(!1), telemetry = workflowReact.useWorkflowTelemetry(), openSnapshot = react.useRef(void 0), openMenu = () => {
|
|
1106
|
+
openSnapshot.current = filters, setOpen(!0);
|
|
1107
|
+
}, close = () => {
|
|
1108
|
+
setOpen(!1), openSnapshot.current !== void 0 && !sameFilters(openSnapshot.current, filters) && telemetry.log(index.WorkflowTaskFiltersApplied, taskFilterTelemetry(filters)),
|
|
1109
|
+
openSnapshot.current = void 0;
|
|
1110
|
+
}, active = hasActiveFilters(filters);
|
|
731
1111
|
/* @__PURE__ */
|
|
732
1112
|
return jsxRuntime.jsx(index.DismissablePopover, {
|
|
733
1113
|
content: open ? /* @__PURE__ */ jsxRuntime.jsx(FilterPanel, {
|
|
@@ -735,7 +1115,7 @@ function TaskFilterMenu({filters: filters, options: options, onChange: onChange}
|
|
|
735
1115
|
onChange: onChange,
|
|
736
1116
|
options: options
|
|
737
1117
|
}) : null,
|
|
738
|
-
onDismiss:
|
|
1118
|
+
onDismiss: close,
|
|
739
1119
|
open: open,
|
|
740
1120
|
overflow: "visible",
|
|
741
1121
|
children: /* @__PURE__ */ jsxRuntime.jsx(index.HoverHint, {
|
|
@@ -746,7 +1126,7 @@ function TaskFilterMenu({filters: filters, options: options, onChange: onChange}
|
|
|
746
1126
|
fontSize: 1,
|
|
747
1127
|
icon: Filter.FilterIcon,
|
|
748
1128
|
mode: "bleed",
|
|
749
|
-
onClick: () =>
|
|
1129
|
+
onClick: () => open ? close() : openMenu(),
|
|
750
1130
|
padding: 2,
|
|
751
1131
|
selected: active || open
|
|
752
1132
|
})
|
|
@@ -1088,7 +1468,7 @@ function DocumentField({documents: documents, activeIds: activeIds, onToggle: on
|
|
|
1088
1468
|
if (documents.length === 0) return null;
|
|
1089
1469
|
const rows = documents.map(doc => ({
|
|
1090
1470
|
key: doc.id,
|
|
1091
|
-
text: `${titles.get(doc.id) ?? ""} ${doc.type} ${workflowEngine.
|
|
1471
|
+
text: `${titles.get(doc.id) ?? ""} ${doc.type} ${workflowEngine.toBareId(doc.id)}`,
|
|
1092
1472
|
node: /* @__PURE__ */ jsxRuntime.jsx(index.DocRefFace, {
|
|
1093
1473
|
gdr: doc
|
|
1094
1474
|
})
|
|
@@ -1173,7 +1553,7 @@ function useDocumentChipLabels(documentIds, documents) {
|
|
|
1173
1553
|
const schema = sanity.useSchema(), activeDocs = documents.filter(doc => documentIds.includes(doc.id)), {titles: titles, resolved: resolved} = useDocPreviewTitles(activeDocs), labels = /* @__PURE__ */ new Map;
|
|
1174
1554
|
for (const doc of activeDocs) {
|
|
1175
1555
|
if (!resolved.has(doc.id)) continue;
|
|
1176
|
-
const label = titles.get(doc.id) ?? schemaTypeTitle(schema, doc.type) ?? workflowEngine.
|
|
1556
|
+
const label = titles.get(doc.id) ?? schemaTypeTitle(schema, doc.type) ?? workflowEngine.toBareId(doc.id);
|
|
1177
1557
|
labels.set(doc.id, label);
|
|
1178
1558
|
}
|
|
1179
1559
|
return labels;
|
|
@@ -1242,7 +1622,7 @@ function ActivityDateControl({instanceId: instanceId, state: state, dates: dates
|
|
|
1242
1622
|
});
|
|
1243
1623
|
const kind = index.dateControlKind(state), commit = (mode, value) => {
|
|
1244
1624
|
state.kind === "editable" && save(() => editFieldFor(instanceId, {
|
|
1245
|
-
target:
|
|
1625
|
+
target: workflowReact.editFieldTarget(state.field),
|
|
1246
1626
|
...mode === "set" ? {
|
|
1247
1627
|
mode: mode,
|
|
1248
1628
|
value: value
|
|
@@ -1300,6 +1680,28 @@ function ActivityDateControl({instanceId: instanceId, state: state, dates: dates
|
|
|
1300
1680
|
});
|
|
1301
1681
|
}
|
|
1302
1682
|
|
|
1683
|
+
const PREWARM_MARGIN = "600px 0px";
|
|
1684
|
+
|
|
1685
|
+
function useNearViewport() {
|
|
1686
|
+
const [element, setElement] = react.useState(null), [near, setNear] = react.useState(!1);
|
|
1687
|
+
return react.useEffect(() => {
|
|
1688
|
+
if (element === null) return;
|
|
1689
|
+
if (typeof IntersectionObserver > "u") {
|
|
1690
|
+
setNear(!0);
|
|
1691
|
+
return;
|
|
1692
|
+
}
|
|
1693
|
+
const observer = new IntersectionObserver(entries => {
|
|
1694
|
+
setNear(entries.at(-1)?.isIntersecting ?? !1);
|
|
1695
|
+
}, {
|
|
1696
|
+
rootMargin: PREWARM_MARGIN
|
|
1697
|
+
});
|
|
1698
|
+
return observer.observe(element), () => observer.disconnect();
|
|
1699
|
+
}, [ element ]), {
|
|
1700
|
+
ref: setElement,
|
|
1701
|
+
near: near
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1303
1705
|
function RefChips({refs: refs, max: max = 2}) {
|
|
1304
1706
|
if (refs.length === 0) return null;
|
|
1305
1707
|
const shown = refs.slice(0, max), overflow = refs.length - shown.length;
|
|
@@ -1321,15 +1723,17 @@ function RefChips({refs: refs, max: max = 2}) {
|
|
|
1321
1723
|
|
|
1322
1724
|
const EMPTY_NOTE = "No tasks match — adjust the filters, or start a workflow", UNGROUPED_TITLE = "Workflows without Studio documents";
|
|
1323
1725
|
|
|
1324
|
-
function TaskGroupList({groups: groups, onOpenTask: onOpenTask, onOpenWorkflow: onOpenWorkflow, showTerminalActions: showTerminalActions}) {
|
|
1726
|
+
function TaskGroupList({bands: bands, groups: groups, instanceDefaultOpen: instanceDefaultOpen, onOpenTask: onOpenTask, onOpenWorkflow: onOpenWorkflow, showTerminalActions: showTerminalActions}) {
|
|
1325
1727
|
return groups.withDocuments.length === 0 && groups.withoutDocuments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(MutedNote, {
|
|
1326
1728
|
text: EMPTY_NOTE
|
|
1327
1729
|
}) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
1328
1730
|
gap: 2,
|
|
1329
1731
|
children: [ groups.withDocuments.map(group => /* @__PURE__ */ jsxRuntime.jsx(index.CollapsibleBand, {
|
|
1330
1732
|
background: !0,
|
|
1733
|
+
onToggle: () => bands.toggle(group.key, GROUP_DEFAULT_OPEN),
|
|
1734
|
+
open: bands.isOpen(group.key, GROUP_DEFAULT_OPEN),
|
|
1331
1735
|
sticky: !0,
|
|
1332
|
-
title: workflowEngine.
|
|
1736
|
+
title: workflowEngine.toBareId(group.document.id),
|
|
1333
1737
|
header: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
1334
1738
|
align: "center",
|
|
1335
1739
|
flex: "none",
|
|
@@ -1342,6 +1746,8 @@ function TaskGroupList({groups: groups, onOpenTask: onOpenTask, onOpenWorkflow:
|
|
|
1342
1746
|
})
|
|
1343
1747
|
}),
|
|
1344
1748
|
children: /* @__PURE__ */ jsxRuntime.jsx(InstanceBands, {
|
|
1749
|
+
bands: bands,
|
|
1750
|
+
instanceDefaultOpen: instanceDefaultOpen,
|
|
1345
1751
|
instances: group.instances,
|
|
1346
1752
|
onOpenTask: onOpenTask,
|
|
1347
1753
|
onOpenWorkflow: onOpenWorkflow,
|
|
@@ -1349,6 +1755,8 @@ function TaskGroupList({groups: groups, onOpenTask: onOpenTask, onOpenWorkflow:
|
|
|
1349
1755
|
})
|
|
1350
1756
|
}, group.key)), groups.withoutDocuments.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(index.CollapsibleBand, {
|
|
1351
1757
|
background: !0,
|
|
1758
|
+
onToggle: () => bands.toggle(UNGROUPED_BAND_KEY, GROUP_DEFAULT_OPEN),
|
|
1759
|
+
open: bands.isOpen(UNGROUPED_BAND_KEY, GROUP_DEFAULT_OPEN),
|
|
1352
1760
|
sticky: !0,
|
|
1353
1761
|
title: UNGROUPED_TITLE,
|
|
1354
1762
|
header: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
@@ -1357,6 +1765,8 @@ function TaskGroupList({groups: groups, onOpenTask: onOpenTask, onOpenWorkflow:
|
|
|
1357
1765
|
children: UNGROUPED_TITLE
|
|
1358
1766
|
}),
|
|
1359
1767
|
children: /* @__PURE__ */ jsxRuntime.jsx(InstanceBands, {
|
|
1768
|
+
bands: bands,
|
|
1769
|
+
instanceDefaultOpen: instanceDefaultOpen,
|
|
1360
1770
|
instances: groups.withoutDocuments,
|
|
1361
1771
|
onOpenTask: onOpenTask,
|
|
1362
1772
|
onOpenWorkflow: onOpenWorkflow,
|
|
@@ -1374,12 +1784,14 @@ function targetOf(row) {
|
|
|
1374
1784
|
};
|
|
1375
1785
|
}
|
|
1376
1786
|
|
|
1377
|
-
function InstanceBands({instances: instances, onOpenTask: onOpenTask, onOpenWorkflow: onOpenWorkflow, showTerminalActions: showTerminalActions}) {
|
|
1787
|
+
function InstanceBands({bands: bands, instanceDefaultOpen: instanceDefaultOpen, instances: instances, onOpenTask: onOpenTask, onOpenWorkflow: onOpenWorkflow, showTerminalActions: showTerminalActions}) {
|
|
1378
1788
|
/* @__PURE__ */
|
|
1379
1789
|
return jsxRuntime.jsx(ui.Stack, {
|
|
1380
1790
|
gap: 1,
|
|
1381
1791
|
children: instances.map(band => /* @__PURE__ */ jsxRuntime.jsx(InstanceBand, {
|
|
1382
1792
|
band: band,
|
|
1793
|
+
bands: bands,
|
|
1794
|
+
instanceDefaultOpen: instanceDefaultOpen,
|
|
1383
1795
|
onOpenTask: onOpenTask,
|
|
1384
1796
|
onOpenWorkflow: onOpenWorkflow,
|
|
1385
1797
|
showTerminalActions: showTerminalActions
|
|
@@ -1387,10 +1799,12 @@ function InstanceBands({instances: instances, onOpenTask: onOpenTask, onOpenWork
|
|
|
1387
1799
|
});
|
|
1388
1800
|
}
|
|
1389
1801
|
|
|
1390
|
-
function InstanceBand({band: band, onOpenTask: onOpenTask, onOpenWorkflow: onOpenWorkflow, showTerminalActions: showTerminalActions}) {
|
|
1802
|
+
function InstanceBand({band: band, bands: bands, instanceDefaultOpen: instanceDefaultOpen, onOpenTask: onOpenTask, onOpenWorkflow: onOpenWorkflow, showTerminalActions: showTerminalActions}) {
|
|
1391
1803
|
const {resolvePathFromState: resolvePathFromState} = router.useRouter();
|
|
1392
1804
|
/* @__PURE__ */
|
|
1393
1805
|
return jsxRuntime.jsx(index.CollapsibleBand, {
|
|
1806
|
+
onToggle: () => bands.toggle(band.instanceId, instanceDefaultOpen),
|
|
1807
|
+
open: bands.isOpen(band.instanceId, instanceDefaultOpen),
|
|
1394
1808
|
title: band.title,
|
|
1395
1809
|
header: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
1396
1810
|
children: [
|
|
@@ -1452,26 +1866,86 @@ function TaskRows({rows: rows, onOpenTask: onOpenTask, showTerminalActions: show
|
|
|
1452
1866
|
}
|
|
1453
1867
|
|
|
1454
1868
|
function TaskActivityRow({row: row, onOpen: onOpen, showTerminalActions: showTerminalActions}) {
|
|
1455
|
-
const
|
|
1869
|
+
const {ref: ref, near: near} = useNearViewport(), entry = index.useWorkflowInstanceEntry(row.instanceId, {
|
|
1870
|
+
evaluate: near
|
|
1871
|
+
}), render = taskRowRender(row, entry);
|
|
1456
1872
|
/* @__PURE__ */
|
|
1457
|
-
return jsxRuntime.jsx(
|
|
1458
|
-
|
|
1459
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(index.
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1873
|
+
return jsxRuntime.jsx(ui.Box, {
|
|
1874
|
+
ref: ref,
|
|
1875
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.StaleLock, {
|
|
1876
|
+
stale: render.stale,
|
|
1877
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.ActivityRow, {
|
|
1878
|
+
assignState: render.assignState,
|
|
1879
|
+
assigneeIds: render.assigneeIds,
|
|
1880
|
+
dateControl: /* @__PURE__ */ jsxRuntime.jsx(ActivityDateControl, {
|
|
1881
|
+
dates: render.dates,
|
|
1882
|
+
instanceId: row.instanceId,
|
|
1883
|
+
state: render.dateState
|
|
1884
|
+
}),
|
|
1885
|
+
face: render.face,
|
|
1464
1886
|
instanceId: row.instanceId,
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
instanceId: row.instanceId,
|
|
1469
|
-
onOpen: onOpen,
|
|
1470
|
-
terminalActions: showTerminalActions ? render.terminalActions : []
|
|
1887
|
+
onOpen: onOpen,
|
|
1888
|
+
terminalActions: showTerminalActions ? render.terminalActions : []
|
|
1889
|
+
})
|
|
1471
1890
|
})
|
|
1472
1891
|
});
|
|
1473
1892
|
}
|
|
1474
1893
|
|
|
1894
|
+
function useBandOpenState(args) {
|
|
1895
|
+
const {segment: segment, scope: scope} = args, store = react.useMemo(() => createBandStateStore({
|
|
1896
|
+
storageKey: bandStateStorageKey(scope)
|
|
1897
|
+
}), [ scope ]), [held, setHeld] = react.useState(() => ({
|
|
1898
|
+
store: store,
|
|
1899
|
+
toggles: store.read()
|
|
1900
|
+
}));
|
|
1901
|
+
held.store !== store && setHeld({
|
|
1902
|
+
store: store,
|
|
1903
|
+
toggles: store.read()
|
|
1904
|
+
});
|
|
1905
|
+
const qualify = key => `${segment}/${key}`, isOpen = (key, defaultOpen) => held.toggles.get(qualify(key)) ?? defaultOpen;
|
|
1906
|
+
return {
|
|
1907
|
+
isOpen: isOpen,
|
|
1908
|
+
toggle: (key, defaultOpen) => {
|
|
1909
|
+
setHeld({
|
|
1910
|
+
store: store,
|
|
1911
|
+
toggles: store.setOpen(qualify(key), !isOpen(key, defaultOpen))
|
|
1912
|
+
});
|
|
1913
|
+
}
|
|
1914
|
+
};
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
const NO_MISSING = /* @__PURE__ */ new Set;
|
|
1918
|
+
|
|
1919
|
+
function sameIdSet(a, b) {
|
|
1920
|
+
if (a.size !== b.size) return !1;
|
|
1921
|
+
for (const id of a) if (!b.has(id)) return !1;
|
|
1922
|
+
return !0;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
function useOrphanedWorkflows(groups) {
|
|
1926
|
+
const {actualTypes: actualTypes, binding: binding} = index.useWorkflowContext(), contentResource = binding.contentResource, key = react.useMemo(() => orphanProbeIds(groups, contentResource), [ groups, contentResource ]).join("|"), [missing, setMissing] = react.useState(NO_MISSING);
|
|
1927
|
+
return react.useEffect(() => {
|
|
1928
|
+
if (key === "") {
|
|
1929
|
+
setMissing(NO_MISSING);
|
|
1930
|
+
return;
|
|
1931
|
+
}
|
|
1932
|
+
const tracked = key.split("|"), releases = tracked.map(id => actualTypes.track(id)), recompute = () => {
|
|
1933
|
+
const next = new Set(tracked.filter(id => actualTypes.read(id) === null));
|
|
1934
|
+
setMissing(current => sameIdSet(current, next) ? current : next);
|
|
1935
|
+
};
|
|
1936
|
+
recompute();
|
|
1937
|
+
const unsubscribe = actualTypes.subscribe(recompute);
|
|
1938
|
+
return () => {
|
|
1939
|
+
unsubscribe();
|
|
1940
|
+
for (const release of releases) release();
|
|
1941
|
+
};
|
|
1942
|
+
}, [ actualTypes, key ]), react.useMemo(() => missing.size === 0 ? NO_ORPHANS : orphanVerdict({
|
|
1943
|
+
groups: groups,
|
|
1944
|
+
contentResource: contentResource,
|
|
1945
|
+
missing: missing
|
|
1946
|
+
}), [ groups, contentResource, missing ]);
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1475
1949
|
const INSTANCE_CAP = 200, NEWEST_INSTANCES = {
|
|
1476
1950
|
includeCompleted: !0,
|
|
1477
1951
|
limit: INSTANCE_CAP
|
|
@@ -1494,18 +1968,21 @@ function useToolInstances() {
|
|
|
1494
1968
|
}, [ instances, loading, unreadable ]);
|
|
1495
1969
|
}
|
|
1496
1970
|
|
|
1497
|
-
function TasksTab({filterSlot: filterSlot, instances: instances, loading: loading, identity: identity,
|
|
1498
|
-
const
|
|
1971
|
+
function TasksTab({filterSlot: filterSlot, instances: instances, loading: loading, identity: identity, onOpenTask: onOpenTask, onOpenWorkflow: onOpenWorkflow, segment: segment, truncated: truncated, unreadable: unreadable}) {
|
|
1972
|
+
const mineOnly = segment === "for-me", {binding: binding} = index.useWorkflowContext(), bands = useBandOpenState({
|
|
1973
|
+
segment: segment,
|
|
1974
|
+
scope: binding.engineResource.id
|
|
1975
|
+
}), [filters, setFilters] = react.useState({}), groups = react.useMemo(() => deriveTaskGroups({
|
|
1499
1976
|
instances: instances,
|
|
1500
1977
|
identity: identity
|
|
1501
|
-
}), [ instances, identity ]),
|
|
1978
|
+
}), [ instances, identity ]), orphans = useOrphanedWorkflows(groups), listed = react.useMemo(() => hideOrphanedGroups(groups, orphans.groupKeys), [ groups, orphans.groupKeys ]), options = react.useMemo(() => taskFilterOptions(listed), [ listed ]), visible = react.useMemo(() => {
|
|
1502
1979
|
const filtered = applyTaskFilters({
|
|
1503
|
-
groups:
|
|
1980
|
+
groups: listed,
|
|
1504
1981
|
filters: filters,
|
|
1505
1982
|
now: /* @__PURE__ */ new Date
|
|
1506
1983
|
});
|
|
1507
1984
|
return mineOnly ? onlyMyTasks(filtered) : filtered;
|
|
1508
|
-
}, [
|
|
1985
|
+
}, [ listed, filters, mineOnly ]);
|
|
1509
1986
|
return loading ?
|
|
1510
1987
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1511
1988
|
paddingLeft: 2,
|
|
@@ -1526,8 +2003,13 @@ function TasksTab({filterSlot: filterSlot, instances: instances, loading: loadin
|
|
|
1526
2003
|
/* @__PURE__ */ jsxRuntime.jsx(index.UnreadableDocsNote, {
|
|
1527
2004
|
unreadable: unreadable
|
|
1528
2005
|
}),
|
|
2006
|
+
/* @__PURE__ */ jsxRuntime.jsx(OrphanedWorkflowsNote, {
|
|
2007
|
+
orphans: orphans
|
|
2008
|
+
}),
|
|
1529
2009
|
/* @__PURE__ */ jsxRuntime.jsx(TaskGroupList, {
|
|
2010
|
+
bands: bands,
|
|
1530
2011
|
groups: visible,
|
|
2012
|
+
instanceDefaultOpen: instanceBandDefaultOpen(segment),
|
|
1531
2013
|
onOpenTask: onOpenTask,
|
|
1532
2014
|
onOpenWorkflow: onOpenWorkflow,
|
|
1533
2015
|
showTerminalActions: mineOnly
|
|
@@ -1568,7 +2050,12 @@ function carryingSearchParams(state, searchParams) {
|
|
|
1568
2050
|
}
|
|
1569
2051
|
|
|
1570
2052
|
function WorkflowsToolRoot() {
|
|
1571
|
-
const router$1 = router.useRouter(), {seedInstance: seedInstance} = index.useWorkflowContext(),
|
|
2053
|
+
const router$1 = router.useRouter(), {seedInstance: seedInstance} = index.useWorkflowContext(), {tab: tab} = useToolTab();
|
|
2054
|
+
index.useLogEventOnMount(index.WorkflowToolOpened, {
|
|
2055
|
+
tab: tab,
|
|
2056
|
+
via: "open"
|
|
2057
|
+
});
|
|
2058
|
+
const instanceId = typeof router$1.state.instanceId == "string" ? router$1.state.instanceId : void 0;
|
|
1572
2059
|
return instanceId ? /* @__PURE__ */ jsxRuntime.jsx(WorkflowInstanceDetail, {
|
|
1573
2060
|
instanceId: instanceId,
|
|
1574
2061
|
onBack: () => router$1.navigate(carryingSearchParams({}, router$1.state._searchParams))
|
|
@@ -1582,7 +2069,7 @@ function WorkflowsToolRoot() {
|
|
|
1582
2069
|
}
|
|
1583
2070
|
|
|
1584
2071
|
function WorkflowsHome({onOpenInstance: onOpenInstance}) {
|
|
1585
|
-
const {tab: tab, setTab: setTab} = useToolTab(), instances = useToolInstances(), identity = index.useAssignmentIdentity(), [openTask, setOpenTask] = react.useState(null), openInstance = target => {
|
|
2072
|
+
const {tab: tab, setTab: setTab} = useToolTab(), telemetry = workflowReact.useWorkflowTelemetry(), instances = useToolInstances(), identity = index.useAssignmentIdentity(), [openTask, setOpenTask] = react.useState(null), openInstance = target => {
|
|
1586
2073
|
if (typeof target != "string") return onOpenInstance(target);
|
|
1587
2074
|
const held = [ ...instances.inFlight, ...instances.settled ].find(i => i._id === target);
|
|
1588
2075
|
onOpenInstance(held ?? target);
|
|
@@ -1626,7 +2113,12 @@ function WorkflowsHome({onOpenInstance: onOpenInstance}) {
|
|
|
1626
2113
|
/* @__PURE__ */ jsxRuntime.jsx(index.TabSwitch, {
|
|
1627
2114
|
ariaControls: "workflows-tool-panel",
|
|
1628
2115
|
idPrefix: "workflows-tool-tab",
|
|
1629
|
-
onSelect:
|
|
2116
|
+
onSelect: next => {
|
|
2117
|
+
next !== tab && telemetry.log(index.WorkflowToolOpened, {
|
|
2118
|
+
tab: next,
|
|
2119
|
+
via: "tab-switch"
|
|
2120
|
+
}), setTab(next);
|
|
2121
|
+
},
|
|
1630
2122
|
options: TOOL_TABS,
|
|
1631
2123
|
selected: tab
|
|
1632
2124
|
}),
|
|
@@ -1657,9 +2149,9 @@ function WorkflowsHome({onOpenInstance: onOpenInstance}) {
|
|
|
1657
2149
|
identity: identity,
|
|
1658
2150
|
instances: [ ...instances.inFlight, ...instances.settled ],
|
|
1659
2151
|
loading: instances.loading,
|
|
1660
|
-
mineOnly: tab === "for-me",
|
|
1661
2152
|
onOpenTask: setOpenTask,
|
|
1662
2153
|
onOpenWorkflow: openInstance,
|
|
2154
|
+
segment: tab,
|
|
1663
2155
|
truncated: instances.truncated,
|
|
1664
2156
|
unreadable: instances.unreadable
|
|
1665
2157
|
})
|