@sanity/workflow-studio-plugin 0.28.0 → 0.29.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 +295 -0
- package/dist/_chunks-cjs/index.cjs +563 -193
- package/dist/_chunks-cjs/workflows-tool-root.cjs +698 -257
- package/dist/_chunks-es/index.js +549 -189
- package/dist/_chunks-es/workflows-tool-root.js +712 -261
- 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"), workflowEngine = require("@sanity/workflow-engine"), ArrowLeft = require("@sanity/icons/ArrowLeft"),
|
|
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"), Calendar = require("@sanity/icons/Calendar"), Clock = require("@sanity/icons/Clock"), Document = require("@sanity/icons/Document"), ErrorOutline = require("@sanity/icons/ErrorOutline"), Transfer = require("@sanity/icons/Transfer"), sanity = require("sanity"), workflowStudio = require("@sanity/workflow-studio"), pluralize = require("pluralize-esm"), 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"), Empty = require("@sanity/icons/Empty"), WarningOutline = require("@sanity/icons/WarningOutline"), 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 : {
|
|
@@ -49,11 +49,22 @@ function documentRefsOf(instance) {
|
|
|
49
49
|
return [ ...seen.values() ];
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
function rootInstanceOf(instance, byId) {
|
|
53
|
+
const rootRef = instance.ancestors[0];
|
|
54
|
+
return rootRef ? byId.get(workflowEngine.toBareId(rootRef.id)) ?? instance : instance;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const TOOL_PANEL_PADDING = 3, TOOL_HEADING_PADDING = 2, PANEL_STEP = 3;
|
|
58
|
+
|
|
52
59
|
function TabStatusRow({children: children}) {
|
|
60
|
+
const firstLineOffset = index.useSpaceToken(PANEL_STEP) + index.useSpaceToken(TOOL_HEADING_PADDING);
|
|
53
61
|
/* @__PURE__ */
|
|
54
62
|
return jsxRuntime.jsx(ui.Box, {
|
|
55
|
-
|
|
56
|
-
|
|
63
|
+
paddingBottom: PANEL_STEP,
|
|
64
|
+
paddingLeft: TOOL_HEADING_PADDING,
|
|
65
|
+
style: {
|
|
66
|
+
paddingTop: firstLineOffset
|
|
67
|
+
},
|
|
57
68
|
children: children
|
|
58
69
|
});
|
|
59
70
|
}
|
|
@@ -304,14 +315,24 @@ function InstanceDetailBody({entry: entry, framed: framed, subject: subject}) {
|
|
|
304
315
|
},
|
|
305
316
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
306
317
|
gap: 5,
|
|
307
|
-
children: [
|
|
318
|
+
children: [
|
|
319
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.InstanceFaultNote, {
|
|
320
|
+
entry: entry,
|
|
321
|
+
scope: {
|
|
322
|
+
kind: "run",
|
|
323
|
+
onOpenActivity: activityName => setOpenActivity({
|
|
324
|
+
stage: instance.currentStage,
|
|
325
|
+
activityName: activityName
|
|
326
|
+
})
|
|
327
|
+
}
|
|
328
|
+
}), subject === "preview" ? /* @__PURE__ */ jsxRuntime.jsx(SubjectPreview, {
|
|
308
329
|
instance: instance
|
|
309
330
|
}) : null,
|
|
310
331
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
311
332
|
gap: 4,
|
|
312
333
|
children: [
|
|
313
334
|
/* @__PURE__ */ jsxRuntime.jsx(SectionHeading, {
|
|
314
|
-
children: "Stages
|
|
335
|
+
children: "Stages"
|
|
315
336
|
}),
|
|
316
337
|
/* @__PURE__ */ jsxRuntime.jsx(index.InstanceSnapshotBody, {
|
|
317
338
|
entry: entry,
|
|
@@ -393,12 +414,140 @@ function byResolvedTitle(titleOf, keyOf) {
|
|
|
393
414
|
};
|
|
394
415
|
}
|
|
395
416
|
|
|
417
|
+
function openActivitiesOf(instance) {
|
|
418
|
+
return (workflowEngine.findOpenStageEntry(instance)?.activities ?? []).filter(activity => index.isOpenActivityStatus(activity.status));
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function overdueTaskCount(instance, now) {
|
|
422
|
+
return openActivitiesOf(instance).filter(activity => index.dueDatesOf(activity.fields ?? []).some(due => index.isDueDatePast(due, now))).length;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const NO_SIGNALS = {
|
|
426
|
+
activeCount: 0,
|
|
427
|
+
assignedToMe: 0,
|
|
428
|
+
documentCount: 0,
|
|
429
|
+
documentlessCount: 0,
|
|
430
|
+
initialStageDocumentCount: 0,
|
|
431
|
+
lastTransition: void 0,
|
|
432
|
+
overdueDocumentCount: 0,
|
|
433
|
+
overdueDocumentlessCount: 0,
|
|
434
|
+
stuckCount: 0
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
function noDefinitionSignals() {
|
|
438
|
+
return NO_SIGNALS;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function holdsWorkFor(instance, who) {
|
|
442
|
+
return openActivitiesOf(instance).some(activity => index.isActivityAssignedTo({
|
|
443
|
+
state: activity.fields ?? [],
|
|
444
|
+
who: who
|
|
445
|
+
}));
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function arrivalOf(instance, byId) {
|
|
449
|
+
const stage = workflowEngine.findOpenStageEntry(instance);
|
|
450
|
+
if (stage !== void 0) return {
|
|
451
|
+
at: stage.enteredAt,
|
|
452
|
+
document: documentRefOf(instance, byId),
|
|
453
|
+
stage: index.stageTitle(index.definitionSnapshotOf(instance), stage.name)
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function laterArrival(held, next) {
|
|
458
|
+
return next === void 0 ? held : held === void 0 || next.at > held.at ? next : held;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function documentRefOf(instance, byId) {
|
|
462
|
+
return documentRefsOf(rootInstanceOf(instance, byId))[0];
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const NO_DRAFT = {
|
|
466
|
+
...NO_SIGNALS,
|
|
467
|
+
documents: /* @__PURE__ */ new Set,
|
|
468
|
+
initialStageDocuments: /* @__PURE__ */ new Set,
|
|
469
|
+
overdueDocuments: /* @__PURE__ */ new Set
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
function withDocument(held, document2) {
|
|
473
|
+
return document2 === void 0 ? held : new Set(held).add(document2);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function atInitialStage(instance) {
|
|
477
|
+
const snapshot = index.definitionSnapshotOf(instance);
|
|
478
|
+
return snapshot !== void 0 && instance.currentStage === snapshot.initialStage;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function fold(args) {
|
|
482
|
+
const {byId: byId, held: held, instance: instance, now: now, who: who} = args, stuck = workflowEngine.documentStuckCause({
|
|
483
|
+
instance: instance,
|
|
484
|
+
definition: index.definitionSnapshotOf(instance)
|
|
485
|
+
}), document2 = documentRefOf(instance, byId)?.id, overdue = overdueTaskCount(instance, now) > 0;
|
|
486
|
+
return {
|
|
487
|
+
activeCount: held.activeCount + 1,
|
|
488
|
+
assignedToMe: held.assignedToMe + (who !== void 0 && holdsWorkFor(instance, who) ? 1 : 0),
|
|
489
|
+
documentlessCount: held.documentlessCount + (document2 === void 0 ? 1 : 0),
|
|
490
|
+
documents: withDocument(held.documents, document2),
|
|
491
|
+
initialStageDocuments: atInitialStage(instance) ? withDocument(held.initialStageDocuments, document2) : held.initialStageDocuments,
|
|
492
|
+
lastTransition: laterArrival(held.lastTransition, arrivalOf(instance, byId)),
|
|
493
|
+
overdueDocumentlessCount: held.overdueDocumentlessCount + (overdue && document2 === void 0 ? 1 : 0),
|
|
494
|
+
overdueDocuments: overdue ? withDocument(held.overdueDocuments, document2) : held.overdueDocuments,
|
|
495
|
+
stuckCount: held.stuckCount + (stuck === void 0 ? 0 : 1)
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function settle(draft) {
|
|
500
|
+
const {documents: documents, initialStageDocuments: initialStageDocuments, overdueDocuments: overdueDocuments, ...rest} = draft;
|
|
501
|
+
return {
|
|
502
|
+
...rest,
|
|
503
|
+
documentCount: documents.size,
|
|
504
|
+
initialStageDocumentCount: initialStageDocuments.size,
|
|
505
|
+
overdueDocumentCount: overdueDocuments.size
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function definitionSignals(args) {
|
|
510
|
+
const byId = new Map(args.instances.map(instance => [ instance._id, instance ])), drafts = /* @__PURE__ */ new Map;
|
|
511
|
+
for (const instance of args.instances) {
|
|
512
|
+
if (workflowEngine.terminalState(instance) !== "in-flight") continue;
|
|
513
|
+
const held = drafts.get(instance.definition) ?? NO_DRAFT;
|
|
514
|
+
drafts.set(instance.definition, fold({
|
|
515
|
+
byId: byId,
|
|
516
|
+
held: held,
|
|
517
|
+
instance: instance,
|
|
518
|
+
now: args.now,
|
|
519
|
+
who: args.identity
|
|
520
|
+
}));
|
|
521
|
+
}
|
|
522
|
+
return new Map([ ...drafts ].map(([name, draft]) => [ name, settle(draft) ]));
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function catalogBands(rows) {
|
|
526
|
+
const assigned = rows.filter(row => row.signals.assignedToMe > 0);
|
|
527
|
+
if (assigned.length === 0) return [ {
|
|
528
|
+
rows: rows,
|
|
529
|
+
title: void 0
|
|
530
|
+
} ];
|
|
531
|
+
const rest = rows.filter(row => row.signals.assignedToMe === 0);
|
|
532
|
+
return [ {
|
|
533
|
+
rows: assigned,
|
|
534
|
+
title: "Assigned to you"
|
|
535
|
+
}, {
|
|
536
|
+
rows: rest,
|
|
537
|
+
title: "Other workflows"
|
|
538
|
+
} ].filter(band => band.rows.length > 0);
|
|
539
|
+
}
|
|
540
|
+
|
|
396
541
|
function definitionCatalog(args) {
|
|
397
|
-
const rejected = [ ...args.issues.values() ]
|
|
542
|
+
const rejected = [ ...args.issues.values() ], signals = definitionSignals({
|
|
543
|
+
identity: args.identity,
|
|
544
|
+
instances: args.instances,
|
|
545
|
+
now: args.now
|
|
546
|
+
});
|
|
398
547
|
return args.definitions.map(definition => ({
|
|
399
548
|
name: definition.name,
|
|
400
549
|
title: definition.title ?? definition.name,
|
|
401
|
-
|
|
550
|
+
signals: signals.get(definition.name) ?? noDefinitionSignals(),
|
|
402
551
|
docTypes: [ ...new Set(args.mappings.filter(mapping => mapping.definition === definition.name).map(mapping => mapping.docType)) ],
|
|
403
552
|
brokenBindings: rejected.filter(issue => issue.definition === definition.name && issue.version === definition.version).map(issue => ({
|
|
404
553
|
docType: issue.docType,
|
|
@@ -436,7 +585,7 @@ function deployedPhrase(definition) {
|
|
|
436
585
|
return ago === "" ? index.formatShortDateTime(deployedAt) : `${index.formatShortDateTime(deployedAt)} (${ago})`;
|
|
437
586
|
}
|
|
438
587
|
|
|
439
|
-
const
|
|
588
|
+
const logged = /* @__PURE__ */ new WeakSet;
|
|
440
589
|
|
|
441
590
|
function logReadFailure(what, error) {
|
|
442
591
|
if (typeof error == "object" && error !== null) {
|
|
@@ -474,17 +623,17 @@ function useCappedInstances(filter) {
|
|
|
474
623
|
}, [ instances, loading, unreadable, error ]);
|
|
475
624
|
}
|
|
476
625
|
|
|
477
|
-
const CATALOG_READ_FAILED = "Couldn’t load the deployed workflows. Try again later.", lastRead = /* @__PURE__ */ new WeakMap, issuedReads = /* @__PURE__ */ new WeakMap;
|
|
626
|
+
const CATALOG_READ_FAILED = "Couldn’t load the deployed workflows. Try again later.", lastRead$1 = /* @__PURE__ */ new WeakMap, issuedReads = /* @__PURE__ */ new WeakMap;
|
|
478
627
|
|
|
479
628
|
function useDeployedDefinitions() {
|
|
480
|
-
const {engine: engine} = index.useWorkflowContext(), [definitions, setDefinitions] = react.useState(() => lastRead.get(engine)?.rows), [error, setError] = react.useState(void 0);
|
|
629
|
+
const {engine: engine} = index.useWorkflowContext(), [definitions, setDefinitions] = react.useState(() => lastRead$1.get(engine)?.rows), [error, setError] = react.useState(void 0);
|
|
481
630
|
return react.useEffect(() => {
|
|
482
631
|
let cancelled = !1;
|
|
483
|
-
setDefinitions(lastRead.get(engine)?.rows), setError(void 0);
|
|
632
|
+
setDefinitions(lastRead$1.get(engine)?.rows), setError(void 0);
|
|
484
633
|
const seq = (issuedReads.get(engine) ?? 0) + 1;
|
|
485
634
|
return issuedReads.set(engine, seq), (async () => {
|
|
486
|
-
const rows = await index.readDeployedDefinitions(engine), latest = workflowEngine.latestDeployedDefinitions(rows), held = lastRead.get(engine);
|
|
487
|
-
(held === void 0 || seq > held.seq) && lastRead.set(engine, {
|
|
635
|
+
const rows = await index.readDeployedDefinitions(engine), latest = workflowEngine.latestDeployedDefinitions(rows), held = lastRead$1.get(engine);
|
|
636
|
+
(held === void 0 || seq > held.seq) && lastRead$1.set(engine, {
|
|
488
637
|
seq: seq,
|
|
489
638
|
rows: latest
|
|
490
639
|
}), cancelled || (setDefinitions(latest), setError(void 0));
|
|
@@ -499,13 +648,78 @@ function useDeployedDefinitions() {
|
|
|
499
648
|
};
|
|
500
649
|
}
|
|
501
650
|
|
|
651
|
+
const NO_TITLES = {
|
|
652
|
+
titles: /* @__PURE__ */ new Map,
|
|
653
|
+
resolved: /* @__PURE__ */ new Set
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
function useDocPreviewTitles(documents) {
|
|
657
|
+
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("|");
|
|
658
|
+
return react.useEffect(() => {
|
|
659
|
+
const titles = /* @__PURE__ */ new Map, resolved = /* @__PURE__ */ new Set, previews = /* @__PURE__ */ new Map, publish = () => setState({
|
|
660
|
+
titles: new Map(titles),
|
|
661
|
+
resolved: new Set(resolved)
|
|
662
|
+
}), localDocs = documents.flatMap(doc => {
|
|
663
|
+
const {parsed: parsed, local: local} = index.gdrLocality(doc.id, binding.contentResource);
|
|
664
|
+
return !parsed || !local ? (resolved.add(doc.id), []) : [ {
|
|
665
|
+
doc: doc,
|
|
666
|
+
bareId: parsed.documentId
|
|
667
|
+
} ];
|
|
668
|
+
}), untracks = localDocs.map(({bareId: bareId}) => actualTypes.track(bareId)), dropPreview = docId => {
|
|
669
|
+
previews.get(docId)?.unsubscribe(), previews.delete(docId), titles.delete(docId);
|
|
670
|
+
}, observe = ({docId: docId, bareId: bareId, typeName: typeName}) => {
|
|
671
|
+
const schemaType = index.openableSchemaType(schema, typeName);
|
|
672
|
+
if (!schemaType) return !1;
|
|
673
|
+
if (previews.get(docId)?.typeName === typeName) return !0;
|
|
674
|
+
dropPreview(docId), resolved.delete(docId);
|
|
675
|
+
const subscription = previewStore.observeForPreview({
|
|
676
|
+
_id: bareId,
|
|
677
|
+
_type: schemaType.name
|
|
678
|
+
}, schemaType, {
|
|
679
|
+
perspective: perspectiveStack
|
|
680
|
+
}).subscribe({
|
|
681
|
+
next: event => {
|
|
682
|
+
resolved.add(docId);
|
|
683
|
+
const title = event.snapshot?.title;
|
|
684
|
+
typeof title == "string" ? titles.set(docId, title) : titles.delete(docId), publish();
|
|
685
|
+
},
|
|
686
|
+
error: err => {
|
|
687
|
+
console.error(`[workflow-studio-plugin] preview for "${docId}" failed:`, err), resolved.add(docId),
|
|
688
|
+
publish();
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
return previews.set(docId, {
|
|
692
|
+
typeName: typeName,
|
|
693
|
+
unsubscribe: () => subscription.unsubscribe()
|
|
694
|
+
}), !0;
|
|
695
|
+
}, evaluate = () => {
|
|
696
|
+
for (const {doc: doc, bareId: bareId} of localDocs) {
|
|
697
|
+
const probe = actualTypes.read(bareId);
|
|
698
|
+
if (probe === null) {
|
|
699
|
+
dropPreview(doc.id), resolved.add(doc.id);
|
|
700
|
+
continue;
|
|
701
|
+
}
|
|
702
|
+
!observe({
|
|
703
|
+
docId: doc.id,
|
|
704
|
+
bareId: bareId,
|
|
705
|
+
typeName: probe ?? doc.type
|
|
706
|
+
}) && typeof probe == "string" && (dropPreview(doc.id), resolved.add(doc.id));
|
|
707
|
+
}
|
|
708
|
+
publish();
|
|
709
|
+
}, unsubscribeProbes = actualTypes.subscribe(evaluate);
|
|
710
|
+
return evaluate(), () => {
|
|
711
|
+
unsubscribeProbes(), untracks.forEach(untrack => untrack()), previews.forEach(preview => preview.unsubscribe());
|
|
712
|
+
};
|
|
713
|
+
}, [ key, previewStore, schema, actualTypes, binding.contentResource.id, perspectiveStack.join("|") ]),
|
|
714
|
+
state;
|
|
715
|
+
}
|
|
716
|
+
|
|
502
717
|
const INSTANCE_CAP_COUNT_NOTE = `Counts from the latest ${INSTANCE_CAP} workflows — older ones aren’t counted.`, NEWEST_INSTANCES = {
|
|
503
718
|
includeCompleted: !0
|
|
504
|
-
};
|
|
719
|
+
}, lastRead = /* @__PURE__ */ new WeakMap;
|
|
505
720
|
|
|
506
721
|
function useToolInstances() {
|
|
507
|
-
const {rows: rows, truncated: truncated, loading: loading, unreadable: unreadable, error: error} = useCappedInstances(NEWEST_INSTANCES)
|
|
508
|
-
return react.useMemo(() => ({
|
|
722
|
+
const {engine: engine} = index.useWorkflowContext(), {rows: rows, truncated: truncated, loading: loading, unreadable: unreadable, error: error} = useCappedInstances(NEWEST_INSTANCES), fresh = react.useMemo(() => ({
|
|
509
723
|
inFlight: rows.filter(instance => workflowEngine.terminalState(instance) === "in-flight"),
|
|
510
724
|
settled: rows.filter(instance => workflowEngine.terminalState(instance) !== "in-flight"),
|
|
511
725
|
truncated: truncated,
|
|
@@ -513,41 +727,118 @@ function useToolInstances() {
|
|
|
513
727
|
unreadable: unreadable,
|
|
514
728
|
error: error
|
|
515
729
|
}), [ rows, truncated, loading, unreadable, error ]);
|
|
730
|
+
return react.useEffect(() => {
|
|
731
|
+
!fresh.loading && fresh.error === void 0 && lastRead.set(engine, fresh);
|
|
732
|
+
}, [ engine, fresh ]), loading ? lastRead.get(engine) ?? fresh : fresh;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
function documentPhrase(count) {
|
|
736
|
+
return count === 0 ? "No documents" : pluralize__default.default("document", count, !0);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
function documentlessTail(count) {
|
|
740
|
+
return count === 0 ? "" : ` (${pluralize__default.default("instance", count, !0)})`;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
function documentlessNote(work) {
|
|
744
|
+
return work.documentCount > 0 ? "" : documentlessTail(work.documentlessCount);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
function documentFace(work, atStart) {
|
|
748
|
+
const lead = `${documentPhrase(work.documentCount)} with an active workflow${documentlessNote(work)}`;
|
|
749
|
+
return atStart === 0 ? {
|
|
750
|
+
lead: lead,
|
|
751
|
+
startLine: void 0
|
|
752
|
+
} : atStart === work.documentCount ? {
|
|
753
|
+
lead: `${lead}, yet to leave the starting stage`,
|
|
754
|
+
startLine: void 0
|
|
755
|
+
} : {
|
|
756
|
+
lead: lead,
|
|
757
|
+
startLine: `${atStart} still at the starting stage`
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
function overdueHint(work) {
|
|
762
|
+
return `${documentPhrase(work.documentCount)} with overdue tasks${documentlessTail(work.documentlessCount)}`;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const UNTITLED_DOCUMENT = "Untitled", TRANSITION_HINT_PENDING = "Loading…";
|
|
766
|
+
|
|
767
|
+
function transitionHeading(at) {
|
|
768
|
+
return `Last stage change at ${index.formatShortDateTime(at)}`;
|
|
516
769
|
}
|
|
517
770
|
|
|
518
|
-
function
|
|
519
|
-
return
|
|
771
|
+
function transitionFace(args) {
|
|
772
|
+
return args.documentPending ? {
|
|
773
|
+
state: "pending"
|
|
774
|
+
} : {
|
|
775
|
+
state: "ready",
|
|
776
|
+
document: args.documentTitle,
|
|
777
|
+
heading: transitionHeading(args.at),
|
|
778
|
+
lead: args.documentTitle === void 0 ? "Changed to" : "changed to",
|
|
779
|
+
stage: args.stage
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
function catalogView(args) {
|
|
784
|
+
if (args.error !== void 0) return {
|
|
785
|
+
kind: "unreadable"
|
|
786
|
+
};
|
|
787
|
+
if (args.definitions === void 0 || args.instances.loading || args.identity.kind === "pending") return {
|
|
788
|
+
kind: "loading"
|
|
789
|
+
};
|
|
790
|
+
if (args.definitions.length === 0) return {
|
|
791
|
+
kind: "empty"
|
|
792
|
+
};
|
|
793
|
+
const rows = definitionCatalog({
|
|
794
|
+
definitions: args.definitions,
|
|
795
|
+
identity: index.identityOf(args.identity),
|
|
796
|
+
instances: [ ...args.instances.inFlight, ...args.instances.settled ],
|
|
797
|
+
issues: args.issues,
|
|
798
|
+
mappings: args.mappings,
|
|
799
|
+
now: args.now
|
|
800
|
+
});
|
|
801
|
+
return {
|
|
802
|
+
kind: "bands",
|
|
803
|
+
bands: catalogBands(rows)
|
|
804
|
+
};
|
|
520
805
|
}
|
|
521
806
|
|
|
522
|
-
function
|
|
523
|
-
if (
|
|
807
|
+
function definitionAlert(row) {
|
|
808
|
+
if (row.signals.stuckCount !== 0) return {
|
|
809
|
+
hint: `${pluralize__default.default("run", row.signals.stuckCount, !0)} here can’t continue without help`
|
|
810
|
+
};
|
|
524
811
|
}
|
|
525
812
|
|
|
526
|
-
const CARD_MIN_WIDTH = 280, CARD_RADIUS$1 = 3, CARD_PADDING = 4, CARD_MIN_HEIGHT =
|
|
813
|
+
const CARD_MIN_WIDTH = 280, CARD_RADIUS$1 = 3, CARD_PADDING = 4, HINT_DOCUMENT_MAX_WIDTH = 200, BAND_GAP = 6, CARD_MIN_HEIGHT = 120;
|
|
527
814
|
|
|
528
|
-
function OverviewTab({onOpenWorkflow: onOpenWorkflow}) {
|
|
529
|
-
const {definitions: definitions, error: error} = useDeployedDefinitions(), {mappingIssues: mappingIssues, mappings: mappings} = index.useWorkflowContext(), schema = sanity.useSchema(), instances = useToolInstances(),
|
|
815
|
+
function OverviewTab({identity: identity, onOpenWorkflow: onOpenWorkflow}) {
|
|
816
|
+
const {definitions: definitions, error: error} = useDeployedDefinitions(), {mappingIssues: mappingIssues, mappings: mappings} = index.useWorkflowContext(), schema = sanity.useSchema(), instances = useToolInstances(), now = index.useMinuteClock(), view = catalogView({
|
|
817
|
+
definitions: definitions,
|
|
818
|
+
error: error,
|
|
819
|
+
identity: identity,
|
|
820
|
+
instances: instances,
|
|
821
|
+
issues: mappingIssues,
|
|
822
|
+
mappings: mappings,
|
|
823
|
+
now: now
|
|
824
|
+
}), undeployed = /* @__PURE__ */ jsxRuntime.jsx(UndeployedWorkflows, {
|
|
530
825
|
notices: undeployedWorkflowNotices({
|
|
531
826
|
issues: mappingIssues,
|
|
532
827
|
titleOf: name => schema.get(name)?.title
|
|
533
828
|
})
|
|
534
829
|
});
|
|
535
|
-
|
|
830
|
+
return view.kind === "unreadable" ? /* @__PURE__ */ jsxRuntime.jsx(index.NoteBanner, {
|
|
536
831
|
label: CATALOG_READ_FAILED,
|
|
537
832
|
tone: "critical"
|
|
538
|
-
})
|
|
539
|
-
if (definitions === void 0) /* @__PURE__ */
|
|
540
|
-
return jsxRuntime.jsx(TabStatusRow, {
|
|
833
|
+
}) : view.kind === "loading" ? /* @__PURE__ */ jsxRuntime.jsx(TabStatusRow, {
|
|
541
834
|
children: /* @__PURE__ */ jsxRuntime.jsx(index.LoadingRow, {
|
|
542
835
|
label: "Loading workflows…"
|
|
543
836
|
})
|
|
544
|
-
})
|
|
545
|
-
if (definitions.length === 0) /* @__PURE__ */
|
|
546
|
-
return jsxRuntime.jsxs(ui.Flex, {
|
|
837
|
+
}) : view.kind === "empty" ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
547
838
|
direction: "column",
|
|
548
839
|
flex: 1,
|
|
549
840
|
gap: 3,
|
|
550
|
-
paddingBottom:
|
|
841
|
+
paddingBottom: 3,
|
|
551
842
|
paddingTop: 3,
|
|
552
843
|
children: [ undeployed,
|
|
553
844
|
/* @__PURE__ */ jsxRuntime.jsx(index.EmptyState, {
|
|
@@ -555,19 +846,7 @@ function OverviewTab({onOpenWorkflow: onOpenWorkflow}) {
|
|
|
555
846
|
icon: /* @__PURE__ */ jsxRuntime.jsx(Transfer.TransferIcon, {}),
|
|
556
847
|
title: "No workflows deployed"
|
|
557
848
|
}) ]
|
|
558
|
-
})
|
|
559
|
-
const rows = definitionCatalog({
|
|
560
|
-
definitions: definitions,
|
|
561
|
-
mappings: mappings,
|
|
562
|
-
inFlight: instances.inFlight,
|
|
563
|
-
issues: mappingIssues
|
|
564
|
-
}), active = rows.reduce((sum, row) => sum + row.activeCount, 0), activity = activeHeadline({
|
|
565
|
-
active: active,
|
|
566
|
-
error: instances.error,
|
|
567
|
-
loading: instances.loading
|
|
568
|
-
});
|
|
569
|
-
/* @__PURE__ */
|
|
570
|
-
return jsxRuntime.jsxs(ui.Stack, {
|
|
849
|
+
}) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
571
850
|
gap: 3,
|
|
572
851
|
paddingBottom: 4,
|
|
573
852
|
paddingTop: 3,
|
|
@@ -575,39 +854,48 @@ function OverviewTab({onOpenWorkflow: onOpenWorkflow}) {
|
|
|
575
854
|
label: INSTANCES_READ_FAILED,
|
|
576
855
|
tone: "critical"
|
|
577
856
|
}),
|
|
578
|
-
/* @__PURE__ */ jsxRuntime.
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
gridAutoRows: `minmax(${CARD_MIN_HEIGHT}px, auto)`,
|
|
597
|
-
gridTemplateColumns: `repeat(auto-fill, minmax(${CARD_MIN_WIDTH}px, 1fr))`
|
|
598
|
-
},
|
|
599
|
-
children: rows.map(row => /* @__PURE__ */ jsxRuntime.jsx(WorkflowCard, {
|
|
600
|
-
countKnown: instances.error === void 0 && !instances.loading,
|
|
601
|
-
onOpen: () => onOpenWorkflow(row.name),
|
|
602
|
-
row: row
|
|
603
|
-
}, row.name))
|
|
857
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Stack, {
|
|
858
|
+
gap: BAND_GAP,
|
|
859
|
+
children: view.bands.map(band => /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
860
|
+
gap: 3,
|
|
861
|
+
children: [ band.title === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
862
|
+
padding: TOOL_HEADING_PADDING,
|
|
863
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.CountedHeading, {
|
|
864
|
+
count: band.rows.length,
|
|
865
|
+
title: band.title
|
|
866
|
+
})
|
|
867
|
+
}),
|
|
868
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardGrid, {
|
|
869
|
+
countKnown: instances.error === void 0,
|
|
870
|
+
now: now,
|
|
871
|
+
onOpenWorkflow: onOpenWorkflow,
|
|
872
|
+
rows: band.rows
|
|
873
|
+
}) ]
|
|
874
|
+
}, band.title ?? UNBANDED_KEY))
|
|
604
875
|
}), instances.truncated ? /* @__PURE__ */ jsxRuntime.jsx(MutedNote, {
|
|
605
876
|
text: INSTANCE_CAP_COUNT_NOTE
|
|
606
877
|
}) : null ]
|
|
607
878
|
});
|
|
608
879
|
}
|
|
609
880
|
|
|
610
|
-
const
|
|
881
|
+
const UNBANDED_KEY = "all";
|
|
882
|
+
|
|
883
|
+
function CardGrid({countKnown: countKnown, now: now, onOpenWorkflow: onOpenWorkflow, rows: rows}) {
|
|
884
|
+
/* @__PURE__ */
|
|
885
|
+
return jsxRuntime.jsx(ui.Grid, {
|
|
886
|
+
gap: 3,
|
|
887
|
+
style: {
|
|
888
|
+
gridAutoRows: `minmax(${CARD_MIN_HEIGHT}px, auto)`,
|
|
889
|
+
gridTemplateColumns: `repeat(auto-fill, minmax(${CARD_MIN_WIDTH}px, 1fr))`
|
|
890
|
+
},
|
|
891
|
+
children: rows.map(row => /* @__PURE__ */ jsxRuntime.jsx(WorkflowCard, {
|
|
892
|
+
countKnown: countKnown,
|
|
893
|
+
now: now,
|
|
894
|
+
onOpen: () => onOpenWorkflow(row.name),
|
|
895
|
+
row: row
|
|
896
|
+
}, row.name))
|
|
897
|
+
});
|
|
898
|
+
}
|
|
611
899
|
|
|
612
900
|
function UndeployedWorkflows({notices: notices}) {
|
|
613
901
|
return notices.length === 0 ? null :
|
|
@@ -620,8 +908,104 @@ function UndeployedWorkflows({notices: notices}) {
|
|
|
620
908
|
});
|
|
621
909
|
}
|
|
622
910
|
|
|
623
|
-
function
|
|
624
|
-
const
|
|
911
|
+
function LastTransitionHint({transition: transition}) {
|
|
912
|
+
const documents = react.useMemo(() => transition.document === void 0 ? [] : [ transition.document ], [ transition.document ]), {resolved: resolved, titles: titles} = useDocPreviewTitles(documents), id = transition.document?.id, face = transitionFace({
|
|
913
|
+
at: transition.at,
|
|
914
|
+
documentPending: id !== void 0 && !resolved.has(id),
|
|
915
|
+
documentTitle: id === void 0 ? void 0 : titles.get(id) ?? UNTITLED_DOCUMENT,
|
|
916
|
+
stage: transition.stage
|
|
917
|
+
});
|
|
918
|
+
return face.state === "pending" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
919
|
+
muted: !0,
|
|
920
|
+
size: 1,
|
|
921
|
+
children: TRANSITION_HINT_PENDING
|
|
922
|
+
}) :
|
|
923
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
924
|
+
gap: 3,
|
|
925
|
+
children: [
|
|
926
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
927
|
+
muted: !0,
|
|
928
|
+
size: 1,
|
|
929
|
+
children: face.heading
|
|
930
|
+
}),
|
|
931
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, {
|
|
932
|
+
size: 1,
|
|
933
|
+
textOverflow: "ellipsis",
|
|
934
|
+
children: [ face.document === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(HintDocument, {
|
|
935
|
+
children: face.document
|
|
936
|
+
}), face.document === void 0 ? "" : " ", face.lead, " ",
|
|
937
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.InlineEmphasis, {
|
|
938
|
+
children: face.stage
|
|
939
|
+
}) ]
|
|
940
|
+
}) ]
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
function HintDocument({children: children}) {
|
|
945
|
+
/* @__PURE__ */
|
|
946
|
+
return jsxRuntime.jsx("span", {
|
|
947
|
+
style: {
|
|
948
|
+
display: "inline-block",
|
|
949
|
+
maxWidth: HINT_DOCUMENT_MAX_WIDTH,
|
|
950
|
+
overflow: "hidden",
|
|
951
|
+
textOverflow: "ellipsis",
|
|
952
|
+
verticalAlign: "bottom",
|
|
953
|
+
whiteSpace: "nowrap"
|
|
954
|
+
},
|
|
955
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.InlineEmphasis, {
|
|
956
|
+
children: children
|
|
957
|
+
})
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
function overdueWork(signals) {
|
|
962
|
+
return {
|
|
963
|
+
documentCount: signals.overdueDocumentCount,
|
|
964
|
+
documentlessCount: signals.overdueDocumentlessCount
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
function CardMetrics$1({now: now, signals: signals}) {
|
|
969
|
+
const overdue = overdueWork(signals), overdueTotal = overdue.documentCount + overdue.documentlessCount, documents = documentFace(signals, signals.initialStageDocumentCount);
|
|
970
|
+
/* @__PURE__ */
|
|
971
|
+
return jsxRuntime.jsxs(ui.Flex, {
|
|
972
|
+
align: "center",
|
|
973
|
+
gap: 3,
|
|
974
|
+
children: [
|
|
975
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.MetricPair, {
|
|
976
|
+
Icon: Document.DocumentIcon,
|
|
977
|
+
empty: signals.documentCount === 0 && signals.documentlessCount === 0,
|
|
978
|
+
face: {
|
|
979
|
+
text: documents.lead,
|
|
980
|
+
...documents.startLine === void 0 ? {} : {
|
|
981
|
+
description: documents.startLine
|
|
982
|
+
}
|
|
983
|
+
},
|
|
984
|
+
value: String(signals.documentCount)
|
|
985
|
+
}), signals.lastTransition === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(index.MetricPair, {
|
|
986
|
+
Icon: Clock.ClockIcon,
|
|
987
|
+
face: {
|
|
988
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(LastTransitionHint, {
|
|
989
|
+
transition: signals.lastTransition
|
|
990
|
+
}),
|
|
991
|
+
wide: !0
|
|
992
|
+
},
|
|
993
|
+
value: index.formatShortAgo(signals.lastTransition.at, now)
|
|
994
|
+
}), overdueTotal === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(index.MetricPair, {
|
|
995
|
+
Icon: Calendar.CalendarIcon,
|
|
996
|
+
face: {
|
|
997
|
+
text: overdueHint(overdue)
|
|
998
|
+
},
|
|
999
|
+
tone: "caution",
|
|
1000
|
+
value: String(overdueTotal)
|
|
1001
|
+
}) ]
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
function WorkflowCard({countKnown: countKnown, now: now, onOpen: onOpen, row: row}) {
|
|
1006
|
+
const alert = definitionAlert(row);
|
|
1007
|
+
/* @__PURE__ */
|
|
1008
|
+
return jsxRuntime.jsxs(ui.Card, {
|
|
625
1009
|
as: "button",
|
|
626
1010
|
onClick: onOpen,
|
|
627
1011
|
padding: CARD_PADDING,
|
|
@@ -634,50 +1018,44 @@ function WorkflowCard({countKnown: countKnown, onOpen: onOpen, row: row}) {
|
|
|
634
1018
|
textAlign: "left",
|
|
635
1019
|
width: "100%"
|
|
636
1020
|
},
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
} : {},
|
|
640
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
1021
|
+
children: [
|
|
1022
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
641
1023
|
align: "flex-start",
|
|
642
|
-
gap:
|
|
643
|
-
|
|
644
|
-
size: 1,
|
|
645
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(WarningOutline.WarningOutlineIcon, {})
|
|
646
|
-
}) : null,
|
|
647
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
1024
|
+
gap: 2,
|
|
1025
|
+
style: {
|
|
648
1026
|
flex: 1,
|
|
649
|
-
|
|
1027
|
+
minWidth: 0
|
|
1028
|
+
},
|
|
1029
|
+
children: [
|
|
1030
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1031
|
+
size: 1,
|
|
650
1032
|
style: {
|
|
1033
|
+
flex: 1,
|
|
651
1034
|
minWidth: 0
|
|
652
1035
|
},
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
muted: !0,
|
|
660
|
-
size: 1,
|
|
661
|
-
children: activeSummary(row.activeCount)
|
|
662
|
-
}) : null ]
|
|
1036
|
+
weight: "medium",
|
|
1037
|
+
children: row.title
|
|
1038
|
+
}), alert === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(index.AlertGlyph, {
|
|
1039
|
+
Icon: ErrorOutline.ErrorOutlineIcon,
|
|
1040
|
+
hint: alert.hint,
|
|
1041
|
+
tone: "critical"
|
|
663
1042
|
}) ]
|
|
664
|
-
})
|
|
1043
|
+
}), countKnown ? /* @__PURE__ */ jsxRuntime.jsx(CardMetrics$1, {
|
|
1044
|
+
now: now,
|
|
1045
|
+
signals: row.signals
|
|
1046
|
+
}) : null ]
|
|
665
1047
|
});
|
|
666
|
-
return flagged ? /* @__PURE__ */ jsxRuntime.jsx(index.HoverHint, {
|
|
667
|
-
fill: !0,
|
|
668
|
-
text: CARD_ISSUES_HINT,
|
|
669
|
-
children: card
|
|
670
|
-
}) : card;
|
|
671
1048
|
}
|
|
672
1049
|
|
|
673
1050
|
function useStartableDefinitions() {
|
|
674
|
-
const {definitions: definitions, error: error} = useDeployedDefinitions()
|
|
1051
|
+
const {definitions: definitions, error: error} = useDeployedDefinitions(), startable = react.useMemo(() => definitions?.filter(row => workflowEngine.isStartableDefinition(row)).map(row => ({
|
|
1052
|
+
name: row.name,
|
|
1053
|
+
title: row.title ?? row.name,
|
|
1054
|
+
description: row.description
|
|
1055
|
+
})), [ definitions ]);
|
|
675
1056
|
return {
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
title: row.title ?? row.name,
|
|
679
|
-
description: row.description
|
|
680
|
-
})), [ definitions ]),
|
|
1057
|
+
catalogEmpty: definitions?.length === 0,
|
|
1058
|
+
definitions: startable,
|
|
681
1059
|
error: error
|
|
682
1060
|
};
|
|
683
1061
|
}
|
|
@@ -709,16 +1087,45 @@ function NewWorkflowButton() {
|
|
|
709
1087
|
});
|
|
710
1088
|
}
|
|
711
1089
|
|
|
1090
|
+
const PANEL_WIDTH = 340;
|
|
1091
|
+
|
|
1092
|
+
function NothingToStart({catalogEmpty: catalogEmpty}) {
|
|
1093
|
+
/* @__PURE__ */
|
|
1094
|
+
return jsxRuntime.jsx(ui.Box, {
|
|
1095
|
+
padding: 4,
|
|
1096
|
+
style: {
|
|
1097
|
+
width: PANEL_WIDTH
|
|
1098
|
+
},
|
|
1099
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
1100
|
+
gap: 3,
|
|
1101
|
+
children: [
|
|
1102
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1103
|
+
align: "center",
|
|
1104
|
+
size: 1,
|
|
1105
|
+
weight: "medium",
|
|
1106
|
+
children: catalogEmpty ? "No workflows deployed" : "Nothing to start by hand"
|
|
1107
|
+
}),
|
|
1108
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
1109
|
+
align: "center",
|
|
1110
|
+
muted: !0,
|
|
1111
|
+
size: 1,
|
|
1112
|
+
children: catalogEmpty ? "Deploy a workflow to this project to start one from here" : "Every deployed workflow here is started by a parent workflow, never by hand"
|
|
1113
|
+
}) ]
|
|
1114
|
+
})
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
|
|
712
1118
|
function DefinitionPickerPanel({onPick: onPick}) {
|
|
713
|
-
const {definitions: definitions, error: error} = useStartableDefinitions(), [query, setQuery] = react.useState(""), visible = react.useMemo(() => {
|
|
1119
|
+
const {catalogEmpty: catalogEmpty, definitions: definitions, error: error} = useStartableDefinitions(), [query, setQuery] = react.useState(""), visible = react.useMemo(() => {
|
|
714
1120
|
const q = query.trim().toLowerCase();
|
|
715
1121
|
return definitions ? q ? definitions.filter(d => `${d.title} ${d.name}`.toLowerCase().includes(q)) : definitions : [];
|
|
716
1122
|
}, [ definitions, query ]), settled = error === void 0 ? definitions : void 0;
|
|
717
|
-
/* @__PURE__ */
|
|
718
|
-
|
|
1123
|
+
return settled?.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(NothingToStart, {
|
|
1124
|
+
catalogEmpty: catalogEmpty
|
|
1125
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
719
1126
|
padding: 2,
|
|
720
1127
|
style: {
|
|
721
|
-
width:
|
|
1128
|
+
width: PANEL_WIDTH
|
|
722
1129
|
},
|
|
723
1130
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
724
1131
|
gap: 2,
|
|
@@ -735,8 +1142,6 @@ function DefinitionPickerPanel({onPick: onPick}) {
|
|
|
735
1142
|
tone: "critical"
|
|
736
1143
|
}) : null, !definitions && !error ? /* @__PURE__ */ jsxRuntime.jsx(index.LoadingRow, {
|
|
737
1144
|
label: "Loading workflows…"
|
|
738
|
-
}) : null, settled?.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(MutedNote, {
|
|
739
|
-
text: "No startable workflows are deployed"
|
|
740
1145
|
}) : null, settled !== void 0 && settled.length > 0 && visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(MutedNote, {
|
|
741
1146
|
text: "No workflows match"
|
|
742
1147
|
}) : null,
|
|
@@ -1015,13 +1420,20 @@ function useBandOpen(bands, key) {
|
|
|
1015
1420
|
};
|
|
1016
1421
|
}
|
|
1017
1422
|
|
|
1018
|
-
const
|
|
1423
|
+
const REVEAL_STALL_MS = 2e3, REVEAL_COLD_MS = 15e3;
|
|
1019
1424
|
|
|
1020
1425
|
function useRevealGate(args) {
|
|
1021
|
-
const {loading: loading, ready: ready} = args, settled = !loading && ready,
|
|
1426
|
+
const {loading: loading, progress: progress, ready: ready} = args, settled = !loading && ready, [stalled, setStalled] = react.useState(!1);
|
|
1427
|
+
react.useEffect(() => {
|
|
1428
|
+
if (loading || ready) return;
|
|
1429
|
+
setStalled(!1);
|
|
1430
|
+
const budget = progress > 0 ? REVEAL_STALL_MS : REVEAL_COLD_MS, timer = setTimeout(() => setStalled(!0), budget);
|
|
1431
|
+
return () => clearTimeout(timer);
|
|
1432
|
+
}, [ loading, progress, ready ]);
|
|
1433
|
+
const [revealed, setRevealed] = react.useState(!1);
|
|
1022
1434
|
return react.useEffect(() => {
|
|
1023
|
-
!revealed && (settled ||
|
|
1024
|
-
}, [
|
|
1435
|
+
!revealed && (settled || stalled) && setRevealed(!0);
|
|
1436
|
+
}, [ revealed, settled, stalled ]), revealed || settled || stalled;
|
|
1025
1437
|
}
|
|
1026
1438
|
|
|
1027
1439
|
function spawnOrigins(instances) {
|
|
@@ -1034,16 +1446,11 @@ function spawnOrigins(instances) {
|
|
|
1034
1446
|
return origins;
|
|
1035
1447
|
}
|
|
1036
1448
|
|
|
1037
|
-
function rootOf(instance, byId) {
|
|
1038
|
-
const rootRef = instance.ancestors[0];
|
|
1039
|
-
return rootRef ? byId.get(workflowEngine.toBareId(rootRef.id)) ?? instance : instance;
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
1449
|
function taskRowsOf(args) {
|
|
1043
1450
|
const {instance: instance, identity: identity} = args, open = workflowEngine.findOpenStageEntry(instance);
|
|
1044
1451
|
if (!open) return [];
|
|
1045
1452
|
const definition = index.definitionSnapshotOf(instance), state = index.stateByActivity(instance), rows = (open.activities ?? []).map(activity => {
|
|
1046
|
-
const fields = state.get(activity.name) ?? [], declared =
|
|
1453
|
+
const fields = state.get(activity.name) ?? [], declared = workflowEngine.findActivityNode({
|
|
1047
1454
|
definition: definition,
|
|
1048
1455
|
stageName: open.name,
|
|
1049
1456
|
activityName: activity.name
|
|
@@ -1098,7 +1505,7 @@ function deriveTaskGroups(args) {
|
|
|
1098
1505
|
activityName: origin.activityName
|
|
1099
1506
|
}).title : void 0,
|
|
1100
1507
|
rows: rows
|
|
1101
|
-
}, root =
|
|
1508
|
+
}, root = rootInstanceOf(instance, byId), documents = documentRefsOf(root), document2 = documents[0];
|
|
1102
1509
|
if (!document2) {
|
|
1103
1510
|
withoutDocuments.push(entry);
|
|
1104
1511
|
continue;
|
|
@@ -1404,72 +1811,6 @@ function SettleOrphansDialog({workflows: workflows, onClose: onClose}) {
|
|
|
1404
1811
|
});
|
|
1405
1812
|
}
|
|
1406
1813
|
|
|
1407
|
-
const NO_TITLES = {
|
|
1408
|
-
titles: /* @__PURE__ */ new Map,
|
|
1409
|
-
resolved: /* @__PURE__ */ new Set
|
|
1410
|
-
};
|
|
1411
|
-
|
|
1412
|
-
function useDocPreviewTitles(documents) {
|
|
1413
|
-
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("|");
|
|
1414
|
-
return react.useEffect(() => {
|
|
1415
|
-
const titles = /* @__PURE__ */ new Map, resolved = /* @__PURE__ */ new Set, previews = /* @__PURE__ */ new Map, publish = () => setState({
|
|
1416
|
-
titles: new Map(titles),
|
|
1417
|
-
resolved: new Set(resolved)
|
|
1418
|
-
}), localDocs = documents.flatMap(doc => {
|
|
1419
|
-
const {parsed: parsed, local: local} = index.gdrLocality(doc.id, binding.contentResource);
|
|
1420
|
-
return !parsed || !local ? (resolved.add(doc.id), []) : [ {
|
|
1421
|
-
doc: doc,
|
|
1422
|
-
bareId: parsed.documentId
|
|
1423
|
-
} ];
|
|
1424
|
-
}), untracks = localDocs.map(({bareId: bareId}) => actualTypes.track(bareId)), dropPreview = docId => {
|
|
1425
|
-
previews.get(docId)?.unsubscribe(), previews.delete(docId), titles.delete(docId);
|
|
1426
|
-
}, observe = ({docId: docId, bareId: bareId, typeName: typeName}) => {
|
|
1427
|
-
const schemaType = index.openableSchemaType(schema, typeName);
|
|
1428
|
-
if (!schemaType) return !1;
|
|
1429
|
-
if (previews.get(docId)?.typeName === typeName) return !0;
|
|
1430
|
-
dropPreview(docId), resolved.delete(docId);
|
|
1431
|
-
const subscription = previewStore.observeForPreview({
|
|
1432
|
-
_id: bareId,
|
|
1433
|
-
_type: schemaType.name
|
|
1434
|
-
}, schemaType, {
|
|
1435
|
-
perspective: perspectiveStack
|
|
1436
|
-
}).subscribe({
|
|
1437
|
-
next: event => {
|
|
1438
|
-
resolved.add(docId);
|
|
1439
|
-
const title = event.snapshot?.title;
|
|
1440
|
-
typeof title == "string" ? titles.set(docId, title) : titles.delete(docId), publish();
|
|
1441
|
-
},
|
|
1442
|
-
error: err => {
|
|
1443
|
-
console.error(`[workflow-studio-plugin] preview for "${docId}" failed:`, err), resolved.add(docId),
|
|
1444
|
-
publish();
|
|
1445
|
-
}
|
|
1446
|
-
});
|
|
1447
|
-
return previews.set(docId, {
|
|
1448
|
-
typeName: typeName,
|
|
1449
|
-
unsubscribe: () => subscription.unsubscribe()
|
|
1450
|
-
}), !0;
|
|
1451
|
-
}, evaluate = () => {
|
|
1452
|
-
for (const {doc: doc, bareId: bareId} of localDocs) {
|
|
1453
|
-
const probe = actualTypes.read(bareId);
|
|
1454
|
-
if (probe === null) {
|
|
1455
|
-
dropPreview(doc.id), resolved.add(doc.id);
|
|
1456
|
-
continue;
|
|
1457
|
-
}
|
|
1458
|
-
!observe({
|
|
1459
|
-
docId: doc.id,
|
|
1460
|
-
bareId: bareId,
|
|
1461
|
-
typeName: probe ?? doc.type
|
|
1462
|
-
}) && typeof probe == "string" && (dropPreview(doc.id), resolved.add(doc.id));
|
|
1463
|
-
}
|
|
1464
|
-
publish();
|
|
1465
|
-
}, unsubscribeProbes = actualTypes.subscribe(evaluate);
|
|
1466
|
-
return evaluate(), () => {
|
|
1467
|
-
unsubscribeProbes(), untracks.forEach(untrack => untrack()), previews.forEach(preview => preview.unsubscribe());
|
|
1468
|
-
};
|
|
1469
|
-
}, [ key, previewStore, schema, actualTypes, binding.contentResource.id, perspectiveStack.join("|") ]),
|
|
1470
|
-
state;
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1473
1814
|
function taskFilterOptions(groups) {
|
|
1474
1815
|
const workflows = /* @__PURE__ */ new Map, documents = /* @__PURE__ */ new Map;
|
|
1475
1816
|
for (const group of groups.withDocuments) {
|
|
@@ -2647,6 +2988,7 @@ function TasksTab({error: error, filterSlot: filterSlot, instances: instances, l
|
|
|
2647
2988
|
identity: identity
|
|
2648
2989
|
}), [ 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({
|
|
2649
2990
|
loading: loading,
|
|
2991
|
+
progress: titles.resolved.size,
|
|
2650
2992
|
ready: titles.ready
|
|
2651
2993
|
}), visible = react.useMemo(() => {
|
|
2652
2994
|
const filtered = applyTaskFilters({
|
|
@@ -2706,6 +3048,30 @@ function TasksTab({error: error, filterSlot: filterSlot, instances: instances, l
|
|
|
2706
3048
|
});
|
|
2707
3049
|
}
|
|
2708
3050
|
|
|
3051
|
+
function cardFacts(args) {
|
|
3052
|
+
return new Map(args.instances.map(instance => [ instance._id, {
|
|
3053
|
+
pending: openActivitiesOf(instance).length,
|
|
3054
|
+
overdue: overdueTaskCount(instance, args.now),
|
|
3055
|
+
stuck: workflowEngine.documentStuckCause({
|
|
3056
|
+
instance: instance,
|
|
3057
|
+
definition: index.definitionSnapshotOf(instance)
|
|
3058
|
+
}) !== void 0,
|
|
3059
|
+
settled: workflowEngine.terminalState(instance) !== "in-flight"
|
|
3060
|
+
} ]));
|
|
3061
|
+
}
|
|
3062
|
+
|
|
3063
|
+
function laneTotals(cards, facts) {
|
|
3064
|
+
let overdue = 0, stuck = 0;
|
|
3065
|
+
for (const card of cards) {
|
|
3066
|
+
const held = facts.get(card.instanceId);
|
|
3067
|
+
held !== void 0 && (held.overdue > 0 && (overdue += 1), held.stuck && (stuck += 1));
|
|
3068
|
+
}
|
|
3069
|
+
return {
|
|
3070
|
+
overdue: overdue,
|
|
3071
|
+
stuck: stuck
|
|
3072
|
+
};
|
|
3073
|
+
}
|
|
3074
|
+
|
|
2709
3075
|
const BOARD_EMPTY_STAGE_NOTE = "No items";
|
|
2710
3076
|
|
|
2711
3077
|
function faceOf(instance) {
|
|
@@ -2764,6 +3130,24 @@ function boardDocuments(board) {
|
|
|
2764
3130
|
return board.groups.flatMap(group => group.cards.flatMap(card => card.face.kind === "document" ? [ card.face.document ] : []));
|
|
2765
3131
|
}
|
|
2766
3132
|
|
|
3133
|
+
function pendingHint(pending) {
|
|
3134
|
+
return pending === 0 ? "All tasks done" : `${pluralize__default.default("task", pending, !0)} still open`;
|
|
3135
|
+
}
|
|
3136
|
+
|
|
3137
|
+
function overdueTasksHint(overdue) {
|
|
3138
|
+
return `${pluralize__default.default("task", overdue, !0)} past ${overdue === 1 ? "its" : "their"} due date`;
|
|
3139
|
+
}
|
|
3140
|
+
|
|
3141
|
+
const STUCK_RUN_HINT = "This run can’t continue without help";
|
|
3142
|
+
|
|
3143
|
+
function laneOverdueHint(overdue) {
|
|
3144
|
+
return `${overdue} of these ${overdue === 1 ? "has" : "have"} overdue tasks`;
|
|
3145
|
+
}
|
|
3146
|
+
|
|
3147
|
+
function laneStuckHint(stuck) {
|
|
3148
|
+
return `${stuck} of these can’t continue without help`;
|
|
3149
|
+
}
|
|
3150
|
+
|
|
2767
3151
|
function CardTitleFace({title: title}) {
|
|
2768
3152
|
return title.kind === "title" ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
2769
3153
|
children: title.title
|
|
@@ -2790,23 +3174,10 @@ function cardTitle(args) {
|
|
|
2790
3174
|
};
|
|
2791
3175
|
}
|
|
2792
3176
|
|
|
2793
|
-
function ownOpenTasks(instance) {
|
|
2794
|
-
const open = workflowEngine.findOpenStageEntry(instance);
|
|
2795
|
-
return open ? (open.activities ?? []).filter(activity => index.isOpenActivityStatus(activity.status)).length : 0;
|
|
2796
|
-
}
|
|
2797
|
-
|
|
2798
|
-
function pendingTaskCounts(instances) {
|
|
2799
|
-
return new Map(instances.map(instance => [ instance._id, ownOpenTasks(instance) ]));
|
|
2800
|
-
}
|
|
2801
|
-
|
|
2802
|
-
function pendingTasksPhrase(pending) {
|
|
2803
|
-
if (pending !== void 0) return pending === 0 ? "All tasks done" : pluralize__default.default("pending task", pending, !0);
|
|
2804
|
-
}
|
|
2805
|
-
|
|
2806
3177
|
const CARD_RADIUS = 3;
|
|
2807
3178
|
|
|
2808
3179
|
function BoardCard({card: card, wiring: wiring}) {
|
|
2809
|
-
const {
|
|
3180
|
+
const {facts: facts, onSelect: onSelect, selectedInstanceId: selectedInstanceId, titles: titles} = wiring, {color: color} = ui.useTheme_v2(), selected = card.instanceId === selectedInstanceId, held = facts.get(card.instanceId);
|
|
2810
3181
|
/* @__PURE__ */
|
|
2811
3182
|
return jsxRuntime.jsx(ui.Card, {
|
|
2812
3183
|
"aria-pressed": selected,
|
|
@@ -2824,54 +3195,93 @@ function BoardCard({card: card, wiring: wiring}) {
|
|
|
2824
3195
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
2825
3196
|
gap: 3,
|
|
2826
3197
|
children: [
|
|
2827
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
children:
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
3198
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
3199
|
+
align: "flex-start",
|
|
3200
|
+
gap: 2,
|
|
3201
|
+
children: [
|
|
3202
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
3203
|
+
size: 1,
|
|
3204
|
+
style: {
|
|
3205
|
+
flex: 1,
|
|
3206
|
+
minWidth: 0
|
|
3207
|
+
},
|
|
3208
|
+
weight: "medium",
|
|
3209
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(CardTitleFace, {
|
|
3210
|
+
title: cardTitle({
|
|
3211
|
+
face: card.face,
|
|
3212
|
+
titles: titles
|
|
3213
|
+
})
|
|
2834
3214
|
})
|
|
2835
|
-
})
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
3215
|
+
}), held?.stuck === !0 ? /* @__PURE__ */ jsxRuntime.jsx(index.AlertGlyph, {
|
|
3216
|
+
Icon: ErrorOutline.ErrorOutlineIcon,
|
|
3217
|
+
hint: STUCK_RUN_HINT,
|
|
3218
|
+
tone: "critical"
|
|
3219
|
+
}) : null ]
|
|
3220
|
+
}), held === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(CardMetrics, {
|
|
3221
|
+
facts: held
|
|
2839
3222
|
}) ]
|
|
2840
3223
|
})
|
|
2841
3224
|
});
|
|
2842
3225
|
}
|
|
2843
3226
|
|
|
2844
|
-
function
|
|
2845
|
-
|
|
2846
|
-
return phrase === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
3227
|
+
function CardMetrics({facts: facts}) {
|
|
3228
|
+
return facts.settled ? null : /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
2847
3229
|
align: "center",
|
|
2848
|
-
|
|
2849
|
-
children:
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
3230
|
+
gap: 3,
|
|
3231
|
+
children: [
|
|
3232
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.MetricPair, {
|
|
3233
|
+
Icon: Empty.EmptyIcon,
|
|
3234
|
+
empty: facts.pending === 0,
|
|
3235
|
+
face: {
|
|
3236
|
+
text: pendingHint(facts.pending)
|
|
3237
|
+
},
|
|
3238
|
+
value: String(facts.pending)
|
|
3239
|
+
}), facts.overdue === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(index.MetricPair, {
|
|
3240
|
+
Icon: Calendar.CalendarIcon,
|
|
3241
|
+
face: {
|
|
3242
|
+
text: overdueTasksHint(facts.overdue)
|
|
3243
|
+
},
|
|
3244
|
+
tone: "caution",
|
|
3245
|
+
value: String(facts.overdue)
|
|
3246
|
+
}) ]
|
|
2859
3247
|
});
|
|
2860
3248
|
}
|
|
2861
3249
|
|
|
2862
|
-
function StageGroupHeading({group: group}) {
|
|
3250
|
+
function StageGroupHeading({facts: facts, group: group}) {
|
|
3251
|
+
const totals = laneTotals(group.cards, facts);
|
|
2863
3252
|
/* @__PURE__ */
|
|
2864
3253
|
return jsxRuntime.jsxs(ui.Flex, {
|
|
2865
3254
|
align: "center",
|
|
2866
3255
|
gap: 2,
|
|
2867
3256
|
children: [
|
|
2868
|
-
/* @__PURE__ */ jsxRuntime.jsx(index.
|
|
3257
|
+
/* @__PURE__ */ jsxRuntime.jsx(index.CountedHeading, {
|
|
2869
3258
|
count: group.cards.length,
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
3259
|
+
title: group.title
|
|
3260
|
+
}), totals.overdue === 0 && totals.stuck === 0 ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
3261
|
+
children: [
|
|
3262
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
3263
|
+
flex: 1
|
|
3264
|
+
}),
|
|
3265
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
3266
|
+
align: "center",
|
|
3267
|
+
flex: "none",
|
|
3268
|
+
gap: 3,
|
|
3269
|
+
children: [ totals.overdue === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(index.MetricPair, {
|
|
3270
|
+
Icon: Calendar.CalendarIcon,
|
|
3271
|
+
face: {
|
|
3272
|
+
text: laneOverdueHint(totals.overdue)
|
|
3273
|
+
},
|
|
3274
|
+
tone: "caution",
|
|
3275
|
+
value: String(totals.overdue)
|
|
3276
|
+
}), totals.stuck === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(index.MetricPair, {
|
|
3277
|
+
Icon: ErrorOutline.ErrorOutlineIcon,
|
|
3278
|
+
face: {
|
|
3279
|
+
text: laneStuckHint(totals.stuck)
|
|
3280
|
+
},
|
|
3281
|
+
tone: "critical",
|
|
3282
|
+
value: String(totals.stuck)
|
|
3283
|
+
}) ]
|
|
3284
|
+
}) ]
|
|
2875
3285
|
}), group.retired ?
|
|
2876
3286
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
2877
3287
|
muted: !0,
|
|
@@ -2920,6 +3330,7 @@ function StageColumn({group: group, leadingRule: leadingRule, trailingRule: trai
|
|
|
2920
3330
|
paddingTop: 4,
|
|
2921
3331
|
paddingX: LANE_PADDING,
|
|
2922
3332
|
children: /* @__PURE__ */ jsxRuntime.jsx(StageGroupHeading, {
|
|
3333
|
+
facts: wiring.facts,
|
|
2923
3334
|
group: group
|
|
2924
3335
|
})
|
|
2925
3336
|
}), group.cards.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
@@ -3060,7 +3471,7 @@ function useBoard(args) {
|
|
|
3060
3471
|
}), {titles: titles, ready: ready} = seeded, board = react.useMemo(() => derived ? orderBoardByPreviewTitle(derived, titles) : void 0, [ derived, titles ]);
|
|
3061
3472
|
return react.useMemo(() => ({
|
|
3062
3473
|
board: board,
|
|
3063
|
-
ready: ready,
|
|
3474
|
+
ready: board !== void 0 && ready,
|
|
3064
3475
|
titles: seeded
|
|
3065
3476
|
}), [ board, ready, seeded ]);
|
|
3066
3477
|
}
|
|
@@ -3167,11 +3578,13 @@ function ActiveCount({face: face}) {
|
|
|
3167
3578
|
}
|
|
3168
3579
|
|
|
3169
3580
|
function DefinitionFacts({definition: definition}) {
|
|
3170
|
-
const {mappingIssues: mappingIssues, mappings: mappings} = index.useWorkflowContext(), schema = sanity.useSchema(), instances = useToolInstances(), snapshotWidth = index.useContainerToken(2), [row] = definitionCatalog({
|
|
3581
|
+
const {mappingIssues: mappingIssues, mappings: mappings} = index.useWorkflowContext(), schema = sanity.useSchema(), instances = useToolInstances(), now = index.useMinuteClock(), snapshotWidth = index.useContainerToken(2), [row] = definitionCatalog({
|
|
3171
3582
|
definitions: [ definition ],
|
|
3583
|
+
identity: void 0,
|
|
3172
3584
|
mappings: mappings,
|
|
3173
|
-
|
|
3174
|
-
issues: mappingIssues
|
|
3585
|
+
instances: [ ...instances.inFlight, ...instances.settled ],
|
|
3586
|
+
issues: mappingIssues,
|
|
3587
|
+
now: now
|
|
3175
3588
|
}), runsOn = docTypeLabels(row?.docTypes ?? [], name => schema.get(name)?.title).map(docType => docType.title);
|
|
3176
3589
|
/* @__PURE__ */
|
|
3177
3590
|
return jsxRuntime.jsxs(ui.Flex, {
|
|
@@ -3209,7 +3622,7 @@ function DefinitionFacts({definition: definition}) {
|
|
|
3209
3622
|
label: "Active instances",
|
|
3210
3623
|
children: /* @__PURE__ */ jsxRuntime.jsx(ActiveCount, {
|
|
3211
3624
|
face: activeCountFace({
|
|
3212
|
-
count: row?.activeCount ?? 0,
|
|
3625
|
+
count: row?.signals.activeCount ?? 0,
|
|
3213
3626
|
error: instances.error,
|
|
3214
3627
|
loading: instances.loading,
|
|
3215
3628
|
truncated: instances.truncated
|
|
@@ -3277,7 +3690,7 @@ function pickerLabel(face) {
|
|
|
3277
3690
|
}
|
|
3278
3691
|
|
|
3279
3692
|
function WorkflowPicker({face: face, onSelect: onSelect, options: options}) {
|
|
3280
|
-
const empty = options.length === 0;
|
|
3693
|
+
const empty = options.length === 0, reclaimed = -index.useSpaceToken(TOOL_HEADING_PADDING);
|
|
3281
3694
|
/* @__PURE__ */
|
|
3282
3695
|
return jsxRuntime.jsx(ui.MenuButton, {
|
|
3283
3696
|
button: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
@@ -3287,6 +3700,9 @@ function WorkflowPicker({face: face, onSelect: onSelect, options: options}) {
|
|
|
3287
3700
|
iconRight: ChevronDown.ChevronDownIcon,
|
|
3288
3701
|
mode: "bleed",
|
|
3289
3702
|
padding: TOOL_HEADING_PADDING,
|
|
3703
|
+
style: {
|
|
3704
|
+
margin: reclaimed
|
|
3705
|
+
},
|
|
3290
3706
|
text: pickerLabel(face),
|
|
3291
3707
|
textWeight: "semibold"
|
|
3292
3708
|
}),
|
|
@@ -3317,6 +3733,7 @@ function WorkflowPageHeader({face: face, onSelectPage: onSelectPage, onSelectWor
|
|
|
3317
3733
|
children: [
|
|
3318
3734
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
3319
3735
|
align: "center",
|
|
3736
|
+
padding: TOOL_HEADING_PADDING,
|
|
3320
3737
|
children: /* @__PURE__ */ jsxRuntime.jsx(WorkflowPicker, {
|
|
3321
3738
|
face: face,
|
|
3322
3739
|
onSelect: onSelectWorkflow,
|
|
@@ -3760,20 +4177,28 @@ function WorkflowPage({onOpenWorkflow: onOpenWorkflow, onSelectPage: onSelectPag
|
|
|
3760
4177
|
}), instances = useBoardInstances(view.streamName), {board: board, ready: ready, titles: titles} = useBoard({
|
|
3761
4178
|
definition: selected,
|
|
3762
4179
|
instances: instances.rows
|
|
3763
|
-
}), {select: select, selectedInstanceId: selectedInstanceId} = usePageSelection(page), panel = usePanelPresence(panelSubject({
|
|
4180
|
+
}), {select: select, selectedInstanceId: selectedInstanceId} = usePageSelection(page), now = index.useMinuteClock(), panel = usePanelPresence(panelSubject({
|
|
3764
4181
|
board: board,
|
|
3765
4182
|
selectedInstanceId: selectedInstanceId
|
|
3766
4183
|
})), revealed = useRevealGate({
|
|
3767
4184
|
loading: instances.loading,
|
|
4185
|
+
progress: titles.resolved.size,
|
|
3768
4186
|
ready: ready
|
|
3769
|
-
})
|
|
4187
|
+
});
|
|
3770
4188
|
if (selection.kind === "loading") /* @__PURE__ */ return jsxRuntime.jsx(UnresolvedPage, {
|
|
3771
|
-
error: catalogError
|
|
3772
|
-
|
|
4189
|
+
error: catalogError
|
|
4190
|
+
});
|
|
4191
|
+
const catalogEmpty = (definitions ?? []).length === 0;
|
|
4192
|
+
if (selection.kind === "unknown" && catalogEmpty) /* @__PURE__ */
|
|
4193
|
+
return jsxRuntime.jsx(EmptyCatalogPage, {
|
|
4194
|
+
name: selection.name
|
|
3773
4195
|
});
|
|
3774
4196
|
const wiring = {
|
|
3775
4197
|
onSelect: select,
|
|
3776
|
-
|
|
4198
|
+
facts: cardFacts({
|
|
4199
|
+
instances: instances.rows,
|
|
4200
|
+
now: now
|
|
4201
|
+
}),
|
|
3777
4202
|
selectedInstanceId: selectedInstanceId,
|
|
3778
4203
|
titles: titles
|
|
3779
4204
|
};
|
|
@@ -3826,7 +4251,7 @@ function WorkflowPage({onOpenWorkflow: onOpenWorkflow, onSelectPage: onSelectPag
|
|
|
3826
4251
|
}),
|
|
3827
4252
|
/* @__PURE__ */ jsxRuntime.jsx(PageBody, {
|
|
3828
4253
|
board: board,
|
|
3829
|
-
catalogEmpty:
|
|
4254
|
+
catalogEmpty: catalogEmpty,
|
|
3830
4255
|
catalogError: catalogError,
|
|
3831
4256
|
instancesError: instances.error,
|
|
3832
4257
|
loading: !revealed,
|
|
@@ -3856,30 +4281,45 @@ function WorkflowPage({onOpenWorkflow: onOpenWorkflow, onSelectPage: onSelectPag
|
|
|
3856
4281
|
});
|
|
3857
4282
|
}
|
|
3858
4283
|
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
function UnresolvedPage({error: error, waiting: waiting}) {
|
|
4284
|
+
function UnresolvedPage({error: error}) {
|
|
3862
4285
|
/* @__PURE__ */
|
|
3863
4286
|
return jsxRuntime.jsx(ui.Flex, {
|
|
3864
4287
|
direction: "column",
|
|
3865
4288
|
height: "fill",
|
|
3866
4289
|
overflow: "hidden",
|
|
3867
|
-
children: error === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(WaitingFace, {
|
|
3868
|
-
waiting: waiting
|
|
3869
|
-
}) : /* @__PURE__ */ jsxRuntime.jsx(ReadErrorFace, {
|
|
4290
|
+
children: error === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(WaitingFace, {}) : /* @__PURE__ */ jsxRuntime.jsx(ReadErrorFace, {
|
|
3870
4291
|
text: CATALOG_READ_FAILED
|
|
3871
4292
|
})
|
|
3872
4293
|
});
|
|
3873
4294
|
}
|
|
3874
4295
|
|
|
3875
|
-
function WaitingFace(
|
|
4296
|
+
function WaitingFace() {
|
|
3876
4297
|
/* @__PURE__ */
|
|
3877
4298
|
return jsxRuntime.jsx(StatusBox, {
|
|
3878
|
-
children:
|
|
4299
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(TabStatusRow, {
|
|
3879
4300
|
children: /* @__PURE__ */ jsxRuntime.jsx(index.LoadingRow, {
|
|
3880
4301
|
label: "Loading workflow…"
|
|
3881
4302
|
})
|
|
3882
|
-
})
|
|
4303
|
+
})
|
|
4304
|
+
});
|
|
4305
|
+
}
|
|
4306
|
+
|
|
4307
|
+
function EmptyCatalogPage({name: name}) {
|
|
4308
|
+
const face = unknownWorkflowFace({
|
|
4309
|
+
catalogEmpty: !0,
|
|
4310
|
+
name: name
|
|
4311
|
+
});
|
|
4312
|
+
/* @__PURE__ */
|
|
4313
|
+
return jsxRuntime.jsx(ui.Flex, {
|
|
4314
|
+
direction: "column",
|
|
4315
|
+
height: "fill",
|
|
4316
|
+
overflow: "hidden",
|
|
4317
|
+
padding: LANE_PADDING,
|
|
4318
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(index.EmptyState, {
|
|
4319
|
+
description: face.description,
|
|
4320
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Search.SearchIcon, {}),
|
|
4321
|
+
title: face.title
|
|
4322
|
+
})
|
|
3883
4323
|
});
|
|
3884
4324
|
}
|
|
3885
4325
|
|
|
@@ -4084,11 +4524,12 @@ function WorkflowsHome({filterSlot: filterSlot, onOpenInstance: onOpenInstance,
|
|
|
4084
4524
|
|
|
4085
4525
|
function HomePanel({filterSlot: filterSlot, identity: identity, instances: instances, onOpenInstance: onOpenInstance, onOpenTask: onOpenTask, onOpenWorkflow: onOpenWorkflow, tab: tab}) {
|
|
4086
4526
|
return tab === "overview" ? /* @__PURE__ */ jsxRuntime.jsx(OverviewTab, {
|
|
4527
|
+
identity: identity,
|
|
4087
4528
|
onOpenWorkflow: onOpenWorkflow
|
|
4088
4529
|
}) : /* @__PURE__ */ jsxRuntime.jsx(TasksTab, {
|
|
4089
4530
|
error: instances.error,
|
|
4090
4531
|
filterSlot: filterSlot,
|
|
4091
|
-
identity: identity,
|
|
4532
|
+
identity: index.identityOf(identity),
|
|
4092
4533
|
instances: [ ...instances.inFlight, ...instances.settled ],
|
|
4093
4534
|
loading: instances.loading,
|
|
4094
4535
|
onOpenInstance: onOpenInstance,
|