@sanity/workflow-studio-plugin 0.5.0 → 0.20.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 +120 -0
- package/README.md +36 -62
- package/dist/_chunks-cjs/index.cjs +471 -248
- package/dist/_chunks-cjs/workflows-tool-root.cjs +47 -36
- package/dist/_chunks-es/index.js +475 -248
- package/dist/_chunks-es/workflows-tool-root.js +49 -38
- 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 +14 -9
package/dist/_chunks-es/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { tryParseGdr, resourceFromParsed, latestDeployedDefinitions, gdrRef, isSubjectEntry, isInputSourced, missingRequiredInputs, initialFieldIssues, releaseRef, refKindAcceptsTypes, rejectedRefTypes, ActionDisabledError, MutationGuardDeniedError, errorMessage, findOpenStageEntry, actionRendering, terminalState, ENGINE_API_VERSION, WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE, isTodoListEntry, isTodoListItem, isTerminalActivityStatus, describeCondition, sentenceCase, checklistLines, findCurrentActivityEntry, scalarValidationIssues, extractDocumentId, isSingleDocRefEntry, isGdr, resolveFieldEntry, isSingleDocRefKind, isNotesEntry, parseDefinitionSnapshot, StartNotSettledError, StartNotAllowedError, isUnprimed, unboundAllowedReads, explainStartAllowed, evaluateStartFilter, startKindOf, readsRootDocument, instancesQuery, assertReadableModel, isTerminalStage, DEFAULT_TRANSITION_WHEN, isStartableDefinition, acceptsDocumentType, definitionsListGroq, gdrFromResource, instanceWatchesDocument, aclPathForResource, definitionLookupGroq, instanceDocId, documentActionDenials } from "@sanity/workflow-engine";
|
|
2
|
-
|
|
3
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
4
2
|
|
|
5
3
|
import { TimelineIcon } from "@sanity/icons/Timeline";
|
|
@@ -10,6 +8,12 @@ import { createContext, useContext, useEffect, useSyncExternalStore, useCallback
|
|
|
10
8
|
|
|
11
9
|
import { usePaneRouter } from "sanity/structure";
|
|
12
10
|
|
|
11
|
+
import { tryParseGdr, resourceFromParsed, latestDeployedDefinitions, isStartableDefinition, isSubjectEntry, isInputSourced, acceptsDocumentType, missingRequiredInputs, initialFieldIssues, gdrRef, releaseRef, refKindAcceptsTypes, rejectedRefTypes, ActionDisabledError, MutationGuardDeniedError, errorMessage, findOpenStageEntry, actionRendering, terminalState, ENGINE_API_VERSION, WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE, isTodoListEntry, isTodoListItem, isTerminalActivityStatus, describeCondition, sentenceCase, checklistLines, findCurrentActivityEntry, scalarValidationIssues, toBareId, isSingleDocRefEntry, isGdr, resolveFieldEntry, isSingleDocRefKind, isNotesEntry, parseDefinitionSnapshot, isUnprimed, StartNotSettledError, StartNotAllowedError, unboundAllowedReads, explainStartAllowed, evaluateStartFilter, startKindOf, readsRootDocument, instancesQuery, assertReadableModel, isTerminalStage, DEFAULT_TRANSITION_WHEN, definitionsListGroq, gdrFromResource, subscriptionDocumentsForInstance, aclPathForResource, definitionLookupGroq, instanceDocId, documentActionDenials } from "@sanity/workflow-engine";
|
|
12
|
+
|
|
13
|
+
import { CheckmarkIcon } from "@sanity/icons/Checkmark";
|
|
14
|
+
|
|
15
|
+
import { CloseIcon } from "@sanity/icons/Close";
|
|
16
|
+
|
|
13
17
|
import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
|
|
14
18
|
|
|
15
19
|
import { getPublishedId } from "@sanity/client/csm";
|
|
@@ -24,14 +28,10 @@ import { ClearableDatePicker, MemberPicker as MemberPicker$1, AssigneePicker as
|
|
|
24
28
|
|
|
25
29
|
import { UserIcon } from "@sanity/icons/User";
|
|
26
30
|
|
|
27
|
-
import { CloseIcon } from "@sanity/icons/Close";
|
|
28
|
-
|
|
29
31
|
import { SearchIcon } from "@sanity/icons/Search";
|
|
30
32
|
|
|
31
33
|
import { ChevronRightIcon } from "@sanity/icons/ChevronRight";
|
|
32
34
|
|
|
33
|
-
import { CheckmarkIcon } from "@sanity/icons/Checkmark";
|
|
34
|
-
|
|
35
35
|
import { EditIcon } from "@sanity/icons/Edit";
|
|
36
36
|
|
|
37
37
|
import { randomKey } from "@sanity/util/content";
|
|
@@ -87,20 +87,58 @@ function gdrLocality(id, contentResource) {
|
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
function
|
|
91
|
-
|
|
90
|
+
function assertUniqueWorkflowMappings(mappings) {
|
|
91
|
+
const keys = /* @__PURE__ */ new Set;
|
|
92
|
+
for (const mapping of mappings) {
|
|
93
|
+
const key = mappingKey(mapping);
|
|
94
|
+
if (keys.has(key)) throw new Error(`Duplicate workflow mapping for ${key}`);
|
|
95
|
+
keys.add(key);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function discoverWorkflowMappings(args) {
|
|
100
|
+
assertUniqueWorkflowMappings(args.overrides ?? []);
|
|
101
|
+
const discovered = latestDeployedDefinitions(args.definitions).flatMap(definition => {
|
|
102
|
+
if (!isStartableDefinition(definition)) return [];
|
|
103
|
+
const subject = (definition.fields ?? []).find(isSubjectEntry);
|
|
104
|
+
if (subject === void 0 || !isInputSourced(subject)) return [];
|
|
105
|
+
const source = {
|
|
106
|
+
fields: [ ...definition.fields ?? [] ]
|
|
107
|
+
};
|
|
108
|
+
return [ ...args.schemaContentTypes ].filter(docType => acceptsDocumentType(source, docType)).map(docType => ({
|
|
109
|
+
docType: docType,
|
|
110
|
+
definition: definition.name,
|
|
111
|
+
label: definition.title ?? definition.name
|
|
112
|
+
}));
|
|
113
|
+
}), byKey = new Map(discovered.map(mapping => [ mappingKey(mapping), mapping ]));
|
|
114
|
+
for (const override of args.overrides ?? []) {
|
|
115
|
+
const key = mappingKey(override);
|
|
116
|
+
byKey.set(key, override);
|
|
117
|
+
}
|
|
118
|
+
return [ ...byKey.values() ];
|
|
92
119
|
}
|
|
93
120
|
|
|
94
|
-
function
|
|
95
|
-
|
|
121
|
+
function mappingAutoStartMap(mappings) {
|
|
122
|
+
const byType = /* @__PURE__ */ Object.create(null);
|
|
123
|
+
for (const mapping of mappings) {
|
|
124
|
+
if (!mapping.autoStart) continue;
|
|
125
|
+
const definitions = byType[mapping.docType] ?? [];
|
|
126
|
+
byType[mapping.docType] = [ ...definitions, mapping.definition ];
|
|
127
|
+
}
|
|
128
|
+
return byType;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function mappingsForDocType(mappings, docType) {
|
|
132
|
+
return mappings.filter(m => m.docType === docType);
|
|
96
133
|
}
|
|
97
134
|
|
|
98
135
|
function mappingKey(mapping) {
|
|
99
136
|
return `${mapping.docType}::${mapping.definition}`;
|
|
100
137
|
}
|
|
101
138
|
|
|
102
|
-
function
|
|
103
|
-
|
|
139
|
+
function documentSubjectEntry(definition) {
|
|
140
|
+
const fields = definition.fields ?? [];
|
|
141
|
+
return fields.find(isSubjectEntry) ?? fields.find(entry => entry.type === "doc.ref" && entry.name === "subject");
|
|
104
142
|
}
|
|
105
143
|
|
|
106
144
|
function mappingStartBlocks(args) {
|
|
@@ -421,7 +459,7 @@ function stateByActivity(instance) {
|
|
|
421
459
|
}
|
|
422
460
|
|
|
423
461
|
function evaluationFreshness(args) {
|
|
424
|
-
return args.evaluation ? args.committed.lastChangedAt > args.evaluation.instance.lastChangedAt ? "stale" : "current" : "pending";
|
|
462
|
+
return args.evaluation ? Date.parse(args.committed.lastChangedAt) > Date.parse(args.evaluation.instance.lastChangedAt) ? "stale" : "current" : "pending";
|
|
425
463
|
}
|
|
426
464
|
|
|
427
465
|
function isEvaluationCurrent(args) {
|
|
@@ -468,12 +506,27 @@ function useWorkflowContext() {
|
|
|
468
506
|
}
|
|
469
507
|
|
|
470
508
|
function useWorkflowsForDocument(rawId) {
|
|
471
|
-
|
|
509
|
+
return useDocumentWorkflowEntries(rawId, !0);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function useCommittedWorkflowsForDocument(rawId) {
|
|
513
|
+
return useDocumentWorkflowEntries(rawId, !1);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function useDocumentWorkflowEntries(rawId, evaluate) {
|
|
517
|
+
const {register: register, unregister: unregister, requestEvaluation: requestEvaluation, releaseEvaluation: releaseEvaluation, entries: entries} = useWorkflowContext(), docId = rawId ? getPublishedId(rawId) : void 0;
|
|
472
518
|
useEffect(() => {
|
|
473
519
|
if (docId) return register(docId), () => unregister(docId);
|
|
474
520
|
}, [ docId, register, unregister ]);
|
|
475
|
-
const list = useSyncExternalStore(entries.subscribe, useCallback(() => docId ? entries.getDocument(docId) : EMPTY_ENTRIES, [ entries, docId ]));
|
|
476
|
-
return {
|
|
521
|
+
const list = useSyncExternalStore(entries.subscribe, useCallback(() => docId ? entries.getDocument(docId) : EMPTY_ENTRIES, [ entries, docId ])), evaluationKey = evaluate ? list.map(entry => entry.instance._id).join("\0") : "";
|
|
522
|
+
return useEffect(() => {
|
|
523
|
+
if (!evaluate) return;
|
|
524
|
+
const ids = evaluationKey === "" ? [] : evaluationKey.split("\0");
|
|
525
|
+
for (const id of ids) requestEvaluation(id);
|
|
526
|
+
return () => {
|
|
527
|
+
for (const id of ids) releaseEvaluation(id);
|
|
528
|
+
};
|
|
529
|
+
}, [ evaluate, evaluationKey, requestEvaluation, releaseEvaluation ]), {
|
|
477
530
|
docId: docId,
|
|
478
531
|
entries: list
|
|
479
532
|
};
|
|
@@ -484,11 +537,13 @@ function useHeldWorkflowEntry(instanceId) {
|
|
|
484
537
|
return useSyncExternalStore(entries.subscribe, useCallback(() => instanceId ? entries.getInstance(instanceId) : void 0, [ entries, instanceId ]));
|
|
485
538
|
}
|
|
486
539
|
|
|
487
|
-
function useWorkflowInstanceEntry(instanceId) {
|
|
488
|
-
const {requestInstance: requestInstance, releaseInstance: releaseInstance} = useWorkflowContext();
|
|
540
|
+
function useWorkflowInstanceEntry(instanceId, options = {}) {
|
|
541
|
+
const {requestInstance: requestInstance, releaseInstance: releaseInstance, requestEvaluation: requestEvaluation, releaseEvaluation: releaseEvaluation} = useWorkflowContext(), evaluate = options.evaluate ?? !0;
|
|
489
542
|
return useEffect(() => {
|
|
490
543
|
if (instanceId) return requestInstance(instanceId), () => releaseInstance(instanceId);
|
|
491
|
-
}, [ instanceId, requestInstance, releaseInstance ]),
|
|
544
|
+
}, [ instanceId, requestInstance, releaseInstance ]), useEffect(() => {
|
|
545
|
+
if (!(!instanceId || !evaluate)) return requestEvaluation(instanceId), () => releaseEvaluation(instanceId);
|
|
546
|
+
}, [ instanceId, evaluate, requestEvaluation, releaseEvaluation ]), useHeldWorkflowEntry(instanceId);
|
|
492
547
|
}
|
|
493
548
|
|
|
494
549
|
const isTodoDone = item => item.status === "done", toggledTodoStatus = item => isTodoDone(item) ? "open" : "done";
|
|
@@ -761,13 +816,29 @@ function concludesHere(actionEval, activityName) {
|
|
|
761
816
|
return changesOwnStatus(actionEval.action, activityName) || actionEval.firing?.exitsStage === !0;
|
|
762
817
|
}
|
|
763
818
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
tone: "
|
|
819
|
+
const SEMANTIC_FACE = {
|
|
820
|
+
"decision.accept": {
|
|
821
|
+
tone: "positive",
|
|
822
|
+
icon: CheckmarkIcon
|
|
823
|
+
},
|
|
824
|
+
"decision.decline": {
|
|
825
|
+
tone: "caution",
|
|
826
|
+
icon: CloseIcon
|
|
827
|
+
}
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
function actionButtonFace(args) {
|
|
831
|
+
const mode = concludesHere(args.actionEval, args.activityName) ? "default" : "ghost";
|
|
832
|
+
if (actionAdvanceStatus(args.actionEval.action, args.activityName) === "failed") return {
|
|
833
|
+
mode: mode,
|
|
834
|
+
tone: "critical",
|
|
835
|
+
icon: void 0
|
|
836
|
+
};
|
|
837
|
+
const [semantic] = args.actionEval.semantics ?? [], face = semantic === void 0 ? void 0 : SEMANTIC_FACE[semantic];
|
|
838
|
+
return {
|
|
839
|
+
mode: mode,
|
|
840
|
+
tone: face?.tone ?? "default",
|
|
841
|
+
icon: face?.icon
|
|
771
842
|
};
|
|
772
843
|
}
|
|
773
844
|
|
|
@@ -1022,10 +1093,19 @@ function personActor(user) {
|
|
|
1022
1093
|
};
|
|
1023
1094
|
}
|
|
1024
1095
|
|
|
1096
|
+
const memberIndexes = /* @__PURE__ */ new WeakMap;
|
|
1097
|
+
|
|
1098
|
+
function memberIndex(members) {
|
|
1099
|
+
const cached = memberIndexes.get(members);
|
|
1100
|
+
if (cached) return cached;
|
|
1101
|
+
const created = new Map(members.map(member => [ member.id, member ]));
|
|
1102
|
+
return memberIndexes.set(members, created), created;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1025
1105
|
const selfUserFor = (id, me) => me != null && me.id === id ? me : void 0;
|
|
1026
1106
|
|
|
1027
1107
|
function userDisplayFor(args) {
|
|
1028
|
-
const member = args.members.
|
|
1108
|
+
const member = memberIndex(args.members).get(args.id), self = selfUserFor(args.id, args.me);
|
|
1029
1109
|
return {
|
|
1030
1110
|
id: args.id,
|
|
1031
1111
|
name: member?.displayName ?? self?.name ?? args.id,
|
|
@@ -1035,19 +1115,20 @@ function userDisplayFor(args) {
|
|
|
1035
1115
|
|
|
1036
1116
|
function useUserDisplays(ids) {
|
|
1037
1117
|
const {members: members} = useProjectMembers(), me = useCurrentUser();
|
|
1038
|
-
return ids.map(id => userDisplayFor({
|
|
1118
|
+
return useMemo(() => ids.map(id => userDisplayFor({
|
|
1039
1119
|
id: id,
|
|
1040
1120
|
members: members,
|
|
1041
1121
|
me: me
|
|
1042
|
-
}));
|
|
1122
|
+
})), [ ids, me, members ]);
|
|
1043
1123
|
}
|
|
1044
1124
|
|
|
1045
1125
|
function useUserDisplay(id) {
|
|
1046
|
-
const
|
|
1047
|
-
return
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1126
|
+
const {members: members} = useProjectMembers(), me = useCurrentUser();
|
|
1127
|
+
return useMemo(() => userDisplayFor({
|
|
1128
|
+
id: id,
|
|
1129
|
+
members: members,
|
|
1130
|
+
me: me
|
|
1131
|
+
}), [ id, me, members ]);
|
|
1051
1132
|
}
|
|
1052
1133
|
|
|
1053
1134
|
function useAssignmentIdentity() {
|
|
@@ -1058,8 +1139,12 @@ function useAssignmentIdentity() {
|
|
|
1058
1139
|
};
|
|
1059
1140
|
}
|
|
1060
1141
|
|
|
1142
|
+
const projectMembersByUsers = /* @__PURE__ */ new WeakMap;
|
|
1143
|
+
|
|
1061
1144
|
function projectMembersFrom(users) {
|
|
1062
|
-
|
|
1145
|
+
const cached = projectMembersByUsers.get(users);
|
|
1146
|
+
if (cached) return cached;
|
|
1147
|
+
const members = users.map(({membership: membership, profile: profile}) => ({
|
|
1063
1148
|
id: membership.id,
|
|
1064
1149
|
displayName: profile?.displayName ?? membership.id,
|
|
1065
1150
|
...profile?.email ? {
|
|
@@ -1070,6 +1155,7 @@ function projectMembersFrom(users) {
|
|
|
1070
1155
|
} : {},
|
|
1071
1156
|
roles: (membership.roles ?? []).map(role => role.name)
|
|
1072
1157
|
}));
|
|
1158
|
+
return projectMembersByUsers.set(users, members), members;
|
|
1073
1159
|
}
|
|
1074
1160
|
|
|
1075
1161
|
function useProjectMembers() {
|
|
@@ -1511,7 +1597,7 @@ function DocPicker({value: value, onChange: onChange, types: types, readOnly: re
|
|
|
1511
1597
|
children: /* @__PURE__ */ jsx(Box, {
|
|
1512
1598
|
flex: 1,
|
|
1513
1599
|
children: /* @__PURE__ */ jsx(PreviewOrId, {
|
|
1514
|
-
id:
|
|
1600
|
+
id: toBareId(value.id),
|
|
1515
1601
|
type: value.type
|
|
1516
1602
|
})
|
|
1517
1603
|
})
|
|
@@ -1607,7 +1693,7 @@ function DocRefsInput({value: value, onChange: onChange, types: types}) {
|
|
|
1607
1693
|
/* @__PURE__ */ jsx(Box, {
|
|
1608
1694
|
flex: 1,
|
|
1609
1695
|
children: /* @__PURE__ */ jsx(PreviewOrId, {
|
|
1610
|
-
id:
|
|
1696
|
+
id: toBareId(ref.id),
|
|
1611
1697
|
type: ref.type
|
|
1612
1698
|
})
|
|
1613
1699
|
}),
|
|
@@ -1761,6 +1847,15 @@ function useFireAction(args) {
|
|
|
1761
1847
|
};
|
|
1762
1848
|
}
|
|
1763
1849
|
|
|
1850
|
+
const ACTION_ICON_GAP = 2;
|
|
1851
|
+
|
|
1852
|
+
function actionIconProps(icon) {
|
|
1853
|
+
return icon ? {
|
|
1854
|
+
gap: ACTION_ICON_GAP,
|
|
1855
|
+
icon: icon
|
|
1856
|
+
} : {};
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1764
1859
|
function stopRowMouseDown(e) {
|
|
1765
1860
|
e.preventDefault(), e.stopPropagation();
|
|
1766
1861
|
}
|
|
@@ -1788,7 +1883,7 @@ function RowClickShield({active: active, children: children}) {
|
|
|
1788
1883
|
});
|
|
1789
1884
|
}
|
|
1790
1885
|
|
|
1791
|
-
function FireButton({instanceId: instanceId, activity: activity, action: action, label: label, mode: mode = "default", chrome: chrome, tone: tone = "default"}) {
|
|
1886
|
+
function FireButton({instanceId: instanceId, activity: activity, action: action, label: label, mode: mode = "default", chrome: chrome, tone: tone = "default", icon: icon}) {
|
|
1792
1887
|
const {fire: fire, pending: pending} = useFireAction({
|
|
1793
1888
|
instanceId: instanceId,
|
|
1794
1889
|
activity: activity,
|
|
@@ -1800,6 +1895,7 @@ function FireButton({instanceId: instanceId, activity: activity, action: action,
|
|
|
1800
1895
|
/* @__PURE__ */
|
|
1801
1896
|
return jsx(Button, {
|
|
1802
1897
|
fontSize: 1,
|
|
1898
|
+
...actionIconProps(icon),
|
|
1803
1899
|
loading: pending,
|
|
1804
1900
|
mode: chrome?.mode ?? mode,
|
|
1805
1901
|
onClick: handleClick,
|
|
@@ -1817,6 +1913,7 @@ function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, acti
|
|
|
1817
1913
|
const rowKind = actionRowKind(actionEval);
|
|
1818
1914
|
return rowKind.kind === "disabled" ? /* @__PURE__ */ jsx(DisabledActionButton, {
|
|
1819
1915
|
actionEval: actionEval,
|
|
1916
|
+
activity: activity,
|
|
1820
1917
|
chrome: chrome
|
|
1821
1918
|
}) : rowKind.kind === "plain" ? /* @__PURE__ */ jsx(PlainActionButton, {
|
|
1822
1919
|
actionEval: actionEval,
|
|
@@ -1831,13 +1928,18 @@ function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, acti
|
|
|
1831
1928
|
});
|
|
1832
1929
|
}
|
|
1833
1930
|
|
|
1834
|
-
function DisabledActionButton({actionEval: actionEval, chrome: chrome}) {
|
|
1835
|
-
const label = actionTriggerLabel(actionEval),
|
|
1931
|
+
function DisabledActionButton({actionEval: actionEval, activity: activity, chrome: chrome}) {
|
|
1932
|
+
const label = actionTriggerLabel(actionEval), {tone: tone, icon: icon} = actionButtonFace({
|
|
1933
|
+
actionEval: actionEval,
|
|
1934
|
+
activityName: activity
|
|
1935
|
+
}), button = /* @__PURE__ */ jsx(Button, {
|
|
1836
1936
|
fontSize: 1,
|
|
1937
|
+
...actionIconProps(icon),
|
|
1837
1938
|
mode: chrome?.mode ?? "ghost",
|
|
1838
1939
|
onClick: e => e.stopPropagation(),
|
|
1839
1940
|
padding: 2,
|
|
1840
1941
|
text: label,
|
|
1942
|
+
tone: tone,
|
|
1841
1943
|
...spanTriggerProps(chrome),
|
|
1842
1944
|
disabled: !0
|
|
1843
1945
|
});
|
|
@@ -1848,11 +1950,12 @@ function DisabledActionButton({actionEval: actionEval, chrome: chrome}) {
|
|
|
1848
1950
|
}
|
|
1849
1951
|
|
|
1850
1952
|
function PlainActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
1851
|
-
const {action: action} = actionEval, label = actionLabel(action), btn =
|
|
1953
|
+
const {action: action} = actionEval, label = actionLabel(action), btn = actionButtonFace({
|
|
1852
1954
|
actionEval: actionEval,
|
|
1853
1955
|
activityName: activity
|
|
1854
1956
|
}), button = /* @__PURE__ */ jsx(FireButton, {
|
|
1855
1957
|
action: action.name,
|
|
1958
|
+
icon: btn.icon,
|
|
1856
1959
|
instanceId: instanceId,
|
|
1857
1960
|
label: label,
|
|
1858
1961
|
mode: btn.mode,
|
|
@@ -1927,7 +2030,7 @@ function ParamsActionDialog({actionEval: actionEval, instanceId: instanceId, act
|
|
|
1927
2030
|
}
|
|
1928
2031
|
|
|
1929
2032
|
function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
1930
|
-
const [open, setOpen] = useState(!1), btn =
|
|
2033
|
+
const [open, setOpen] = useState(!1), btn = actionButtonFace({
|
|
1931
2034
|
actionEval: actionEval,
|
|
1932
2035
|
activityName: activity
|
|
1933
2036
|
});
|
|
@@ -1936,6 +2039,7 @@ function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, act
|
|
|
1936
2039
|
children: [
|
|
1937
2040
|
/* @__PURE__ */ jsx(Button, {
|
|
1938
2041
|
fontSize: 1,
|
|
2042
|
+
...actionIconProps(btn.icon),
|
|
1939
2043
|
mode: chrome?.mode ?? btn.mode,
|
|
1940
2044
|
onClick: e => {
|
|
1941
2045
|
chrome?.inButtonCard === !0 && e.stopPropagation(), setOpen(!0);
|
|
@@ -2761,7 +2865,7 @@ function ReadOnlyDocRefs({entry: entry}) {
|
|
|
2761
2865
|
padding: 2,
|
|
2762
2866
|
radius: 2,
|
|
2763
2867
|
children: /* @__PURE__ */ jsx(PreviewOrId, {
|
|
2764
|
-
id:
|
|
2868
|
+
id: toBareId(ref.id),
|
|
2765
2869
|
type: ref.type
|
|
2766
2870
|
})
|
|
2767
2871
|
}, ref.id))
|
|
@@ -4125,7 +4229,12 @@ const ACTIONS_MENU_TRIGGER = {
|
|
|
4125
4229
|
};
|
|
4126
4230
|
|
|
4127
4231
|
function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activity: activity, onCollectParams: onCollectParams}) {
|
|
4128
|
-
const rowKind = actionRowKind(actionEval), label = actionTriggerLabel(actionEval), {
|
|
4232
|
+
const rowKind = actionRowKind(actionEval), label = actionTriggerLabel(actionEval), {tone: tone, icon: icon} = actionButtonFace({
|
|
4233
|
+
actionEval: actionEval,
|
|
4234
|
+
activityName: activity
|
|
4235
|
+
}), iconProp = icon ? {
|
|
4236
|
+
icon: icon
|
|
4237
|
+
} : {}, {fire: fire, pending: pending} = useFireAction({
|
|
4129
4238
|
instanceId: instanceId,
|
|
4130
4239
|
activity: activity,
|
|
4131
4240
|
action: actionEval.action.name,
|
|
@@ -4133,17 +4242,23 @@ function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activit
|
|
|
4133
4242
|
});
|
|
4134
4243
|
return rowKind.kind === "disabled" ? /* @__PURE__ */ jsx(MenuItem, {
|
|
4135
4244
|
disabled: !0,
|
|
4136
|
-
|
|
4245
|
+
...iconProp,
|
|
4246
|
+
text: label,
|
|
4247
|
+
tone: tone
|
|
4137
4248
|
}) : rowKind.kind === "plain" ? /* @__PURE__ */ jsx(MenuItem, {
|
|
4138
4249
|
disabled: pending,
|
|
4250
|
+
...iconProp,
|
|
4139
4251
|
onClick: () => {
|
|
4140
4252
|
fire();
|
|
4141
4253
|
},
|
|
4142
|
-
text: label
|
|
4254
|
+
text: label,
|
|
4255
|
+
tone: tone
|
|
4143
4256
|
}) : /* @__PURE__ */ jsx(MenuItem, {
|
|
4144
4257
|
disabled: pending,
|
|
4258
|
+
...iconProp,
|
|
4145
4259
|
onClick: onCollectParams,
|
|
4146
|
-
text: label
|
|
4260
|
+
text: label,
|
|
4261
|
+
tone: tone
|
|
4147
4262
|
});
|
|
4148
4263
|
}
|
|
4149
4264
|
|
|
@@ -4256,6 +4371,7 @@ function FittedActions({actions: actions, activity: activity, instanceId: instan
|
|
|
4256
4371
|
children: [
|
|
4257
4372
|
/* @__PURE__ */ jsx(MeasureRow, {
|
|
4258
4373
|
actions: actions,
|
|
4374
|
+
activity: activity,
|
|
4259
4375
|
onElement: setMeasureEl
|
|
4260
4376
|
}),
|
|
4261
4377
|
/* @__PURE__ */ jsxs(FooterRow, {
|
|
@@ -4275,7 +4391,7 @@ function FittedActions({actions: actions, activity: activity, instanceId: instan
|
|
|
4275
4391
|
});
|
|
4276
4392
|
}
|
|
4277
4393
|
|
|
4278
|
-
function MeasureRow({actions: actions, onElement: onElement}) {
|
|
4394
|
+
function MeasureRow({actions: actions, activity: activity, onElement: onElement}) {
|
|
4279
4395
|
/* @__PURE__ */
|
|
4280
4396
|
return jsx("div", {
|
|
4281
4397
|
"aria-hidden": !0,
|
|
@@ -4289,12 +4405,20 @@ function MeasureRow({actions: actions, onElement: onElement}) {
|
|
|
4289
4405
|
display: "inline-flex",
|
|
4290
4406
|
whiteSpace: "nowrap"
|
|
4291
4407
|
},
|
|
4292
|
-
children: [ actions.map(a =>
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4408
|
+
children: [ actions.map(a => {
|
|
4409
|
+
const {icon: icon} = actionButtonFace({
|
|
4410
|
+
actionEval: a,
|
|
4411
|
+
activityName: activity
|
|
4412
|
+
});
|
|
4413
|
+
/* @__PURE__ */
|
|
4414
|
+
return jsx(Button, {
|
|
4415
|
+
as: "span",
|
|
4416
|
+
fontSize: 1,
|
|
4417
|
+
...actionIconProps(icon),
|
|
4418
|
+
padding: 2,
|
|
4419
|
+
text: actionTriggerLabel(a)
|
|
4420
|
+
}, a.action.name);
|
|
4421
|
+
}),
|
|
4298
4422
|
/* @__PURE__ */ jsx(Button, {
|
|
4299
4423
|
...ACTIONS_MENU_TRIGGER,
|
|
4300
4424
|
as: "span",
|
|
@@ -4576,7 +4700,26 @@ function CountedLabel({count: count, label: label}) {
|
|
|
4576
4700
|
});
|
|
4577
4701
|
}
|
|
4578
4702
|
|
|
4579
|
-
function
|
|
4703
|
+
function SpinnerSlot({busy: busy, size: size}) {
|
|
4704
|
+
/* @__PURE__ */
|
|
4705
|
+
return jsx(Flex, {
|
|
4706
|
+
align: "center",
|
|
4707
|
+
flex: "none",
|
|
4708
|
+
justify: "center",
|
|
4709
|
+
style: {
|
|
4710
|
+
width: 19,
|
|
4711
|
+
height: 19
|
|
4712
|
+
},
|
|
4713
|
+
children: busy ? /* @__PURE__ */ jsx(Spinner, {
|
|
4714
|
+
muted: !0,
|
|
4715
|
+
...size !== void 0 ? {
|
|
4716
|
+
size: size
|
|
4717
|
+
} : {}
|
|
4718
|
+
}) : null
|
|
4719
|
+
});
|
|
4720
|
+
}
|
|
4721
|
+
|
|
4722
|
+
function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
4580
4723
|
/* @__PURE__ */
|
|
4581
4724
|
return jsxs(Flex, {
|
|
4582
4725
|
align: "center",
|
|
@@ -4591,6 +4734,9 @@ function GroupHeading({count: count, title: title, end: end}) {
|
|
|
4591
4734
|
weight: "semibold",
|
|
4592
4735
|
children: title
|
|
4593
4736
|
})
|
|
4737
|
+
}), busy === void 0 ? null : /* @__PURE__ */ jsx(SpinnerSlot, {
|
|
4738
|
+
busy: busy,
|
|
4739
|
+
size: 1
|
|
4594
4740
|
}), end === void 0 ? null : /* @__PURE__ */ jsxs(Fragment, {
|
|
4595
4741
|
children: [
|
|
4596
4742
|
/* @__PURE__ */ jsx(Flex, {
|
|
@@ -4713,6 +4859,18 @@ function TabSwitch({ariaControls: ariaControls, idPrefix: idPrefix, options: opt
|
|
|
4713
4859
|
});
|
|
4714
4860
|
}
|
|
4715
4861
|
|
|
4862
|
+
function useDelayedFlag(active, delayMs) {
|
|
4863
|
+
const [held, setHeld] = useState(!1);
|
|
4864
|
+
return useEffect(() => {
|
|
4865
|
+
if (!active) {
|
|
4866
|
+
setHeld(!1);
|
|
4867
|
+
return;
|
|
4868
|
+
}
|
|
4869
|
+
const timer = setTimeout(() => setHeld(!0), delayMs);
|
|
4870
|
+
return () => clearTimeout(timer);
|
|
4871
|
+
}, [ active, delayMs ]), held && active;
|
|
4872
|
+
}
|
|
4873
|
+
|
|
4716
4874
|
function instanceTitle(instance, definition) {
|
|
4717
4875
|
return definition?.title ?? instance.definition;
|
|
4718
4876
|
}
|
|
@@ -5551,9 +5709,16 @@ function instanceNotice(entry) {
|
|
|
5551
5709
|
size: 1,
|
|
5552
5710
|
children: "This workflow didn’t finish starting — use Start workflow to continue it"
|
|
5553
5711
|
})
|
|
5554
|
-
}) : pending ? /* @__PURE__ */ jsx(
|
|
5555
|
-
|
|
5556
|
-
|
|
5712
|
+
}) : pending ? /* @__PURE__ */ jsx(WorkRow, {
|
|
5713
|
+
lead: /* @__PURE__ */ jsx(Spinner, {
|
|
5714
|
+
muted: !0,
|
|
5715
|
+
size: 1
|
|
5716
|
+
}),
|
|
5717
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
5718
|
+
muted: !0,
|
|
5719
|
+
size: 1,
|
|
5720
|
+
children: "Loading…"
|
|
5721
|
+
})
|
|
5557
5722
|
}) : null;
|
|
5558
5723
|
}
|
|
5559
5724
|
|
|
@@ -6617,20 +6782,7 @@ function InstanceDebugMenu({entry: entry}) {
|
|
|
6617
6782
|
}
|
|
6618
6783
|
|
|
6619
6784
|
function InstanceAccordion({entry: entry, children: children, defaultOpen: defaultOpen}) {
|
|
6620
|
-
const definition = useDefinition(entry), {instance: instance
|
|
6621
|
-
align: "center",
|
|
6622
|
-
gap: 2,
|
|
6623
|
-
style: badgeTrim,
|
|
6624
|
-
children: [
|
|
6625
|
-
/* @__PURE__ */ jsx(AbortedBadge, {
|
|
6626
|
-
instance: instance
|
|
6627
|
-
}), settled ? null : /* @__PURE__ */ jsx(OlderDefinitionBadge, {
|
|
6628
|
-
instance: instance
|
|
6629
|
-
}), !ready && entry.invalid === void 0 ? /* @__PURE__ */ jsx(Spinner, {
|
|
6630
|
-
muted: !0,
|
|
6631
|
-
size: 1
|
|
6632
|
-
}) : null ]
|
|
6633
|
-
});
|
|
6785
|
+
const definition = useDefinition(entry), {instance: instance} = entry, settled = !isLiveEntry(entry), title = instanceTitle(instance, definition), badgeTrim = useBadgeCapTrim();
|
|
6634
6786
|
/* @__PURE__ */
|
|
6635
6787
|
return jsx(CollapsibleBand, {
|
|
6636
6788
|
defaultOpen: defaultOpen ?? !settled,
|
|
@@ -6653,7 +6805,18 @@ function InstanceAccordion({entry: entry, children: children, defaultOpen: defau
|
|
|
6653
6805
|
textOverflow: "ellipsis",
|
|
6654
6806
|
weight: "medium",
|
|
6655
6807
|
children: title
|
|
6656
|
-
}),
|
|
6808
|
+
}),
|
|
6809
|
+
/* @__PURE__ */ jsxs(Flex, {
|
|
6810
|
+
align: "center",
|
|
6811
|
+
gap: 2,
|
|
6812
|
+
style: badgeTrim,
|
|
6813
|
+
children: [
|
|
6814
|
+
/* @__PURE__ */ jsx(AbortedBadge, {
|
|
6815
|
+
instance: instance
|
|
6816
|
+
}), settled ? null : /* @__PURE__ */ jsx(OlderDefinitionBadge, {
|
|
6817
|
+
instance: instance
|
|
6818
|
+
}) ]
|
|
6819
|
+
}) ]
|
|
6657
6820
|
}),
|
|
6658
6821
|
/* @__PURE__ */ jsx(TrailingHairline, {}),
|
|
6659
6822
|
/* @__PURE__ */ jsx(InstanceDebugMenu, {
|
|
@@ -6671,7 +6834,7 @@ function InstanceAccordion({entry: entry, children: children, defaultOpen: defau
|
|
|
6671
6834
|
}
|
|
6672
6835
|
|
|
6673
6836
|
function PartOfBand({instance: instance}) {
|
|
6674
|
-
const parentRef = instance.ancestors.at(-1), parentId = parentRef ?
|
|
6837
|
+
const parentRef = instance.ancestors.at(-1), parentId = parentRef ? toBareId(parentRef.id) : null, parentEntry = useWorkflowInstanceEntry(parentId), parentDefinition = useDefinition(parentEntry);
|
|
6675
6838
|
if (!parentId) return null;
|
|
6676
6839
|
const title = parentEntry ? instanceTitle(parentEntry.instance, parentDefinition) : parentId;
|
|
6677
6840
|
/* @__PURE__ */
|
|
@@ -7228,11 +7391,9 @@ const VIEW_TAB_CODEC = workflowsTabCodec([ "overview", "for-me" ]), WorkflowsVie
|
|
|
7228
7391
|
};
|
|
7229
7392
|
|
|
7230
7393
|
function DiscoverySpinner() {
|
|
7231
|
-
const
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
return () => clearTimeout(timer);
|
|
7235
|
-
}, []), /* @__PURE__ */ jsx(Flex, {
|
|
7394
|
+
const visible = useDelayedFlag(!0, 1e3);
|
|
7395
|
+
/* @__PURE__ */
|
|
7396
|
+
return jsx(Flex, {
|
|
7236
7397
|
align: "center",
|
|
7237
7398
|
height: "fill",
|
|
7238
7399
|
justify: "center",
|
|
@@ -7242,7 +7403,7 @@ function DiscoverySpinner() {
|
|
|
7242
7403
|
});
|
|
7243
7404
|
}
|
|
7244
7405
|
|
|
7245
|
-
const GROUP_GAP = 1;
|
|
7406
|
+
const BOOT_CUE_DELAY_MS = 400, GROUP_GAP = 1;
|
|
7246
7407
|
|
|
7247
7408
|
function useWorkflowsTab() {
|
|
7248
7409
|
const {params: params, setParams: setParams} = usePaneRouter();
|
|
@@ -7267,7 +7428,7 @@ function useOpenActivity(entries) {
|
|
|
7267
7428
|
}
|
|
7268
7429
|
|
|
7269
7430
|
function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappings: docTypeMappings, initialValue: initialValue}) {
|
|
7270
|
-
const identity = useAssignmentIdentity(), panelId = useId(), {params: params} = usePaneRouter(), {view: view, setView: setView} = useWorkflowsTab(), {openActivity: openActivity, setOpenActivity: setOpenActivity, dialogEntry: dialogEntry} = useOpenActivity(entries), active = entries.filter(isLiveEntry), finished = entries.filter(e => !isLiveEntry(e)), forMe = forMeWorkOf(active, identity), [landing] = useState(() => focusedLanding(params?.[WORKFLOWS_FOCUS_PARAM], entries.map(e => e.instance._id))), assignedWorkUnknown = active.some(e => e.invalid !== void 0), sectionFor = e => /* @__PURE__ */ jsx(WorkflowInstanceSection, {
|
|
7431
|
+
const identity = useAssignmentIdentity(), panelId = useId(), {params: params} = usePaneRouter(), {view: view, setView: setView} = useWorkflowsTab(), {openActivity: openActivity, setOpenActivity: setOpenActivity, dialogEntry: dialogEntry} = useOpenActivity(entries), active = entries.filter(isLiveEntry), finished = entries.filter(e => !isLiveEntry(e)), forMe = forMeWorkOf(active, identity), [landing] = useState(() => focusedLanding(params?.[WORKFLOWS_FOCUS_PARAM], entries.map(e => e.instance._id))), assignedWorkUnknown = active.some(e => e.invalid !== void 0), booting = useDelayedFlag(active.some(e => !e.ready && e.invalid === void 0), BOOT_CUE_DELAY_MS), sectionFor = e => /* @__PURE__ */ jsx(WorkflowInstanceSection, {
|
|
7271
7432
|
defaultOpen: landingDefaultOpen(landing, e.instance._id),
|
|
7272
7433
|
entry: e,
|
|
7273
7434
|
onOpenActivity: activityName => setOpenActivity({
|
|
@@ -7288,6 +7449,7 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7288
7449
|
padding: 3,
|
|
7289
7450
|
children: [
|
|
7290
7451
|
/* @__PURE__ */ jsx(GroupHeading, {
|
|
7452
|
+
busy: booting,
|
|
7291
7453
|
count: active.length,
|
|
7292
7454
|
end:
|
|
7293
7455
|
/* @__PURE__ */ jsx(Box, {
|
|
@@ -7423,10 +7585,8 @@ function workflowsView(S) {
|
|
|
7423
7585
|
return S.view.component(WorkflowsView).id(WORKFLOWS_VIEW_ID).title("Workflows");
|
|
7424
7586
|
}
|
|
7425
7587
|
|
|
7426
|
-
function workflowDefaultDocumentNode(
|
|
7427
|
-
return (S,
|
|
7428
|
-
if (mappingForDocType(options.mappings, ctx.schemaType)) return S.document().views([ S.view.form(), workflowsView(S) ]);
|
|
7429
|
-
};
|
|
7588
|
+
function workflowDefaultDocumentNode() {
|
|
7589
|
+
return S => S.document().views([ S.view.form(), workflowsView(S) ]);
|
|
7430
7590
|
}
|
|
7431
7591
|
|
|
7432
7592
|
function lockTitleFor(args) {
|
|
@@ -7439,26 +7599,12 @@ function lockTitleFor(args) {
|
|
|
7439
7599
|
return workflows.length === 1 ? `The ${workflowList} workflow is holding this document.` : `The ${workflowList} workflows are holding this document.`;
|
|
7440
7600
|
}
|
|
7441
7601
|
|
|
7442
|
-
const EMPTY = {
|
|
7443
|
-
byType: /* @__PURE__ */ new Map,
|
|
7444
|
-
definitions: /* @__PURE__ */ new Map,
|
|
7445
|
-
warnings: []
|
|
7446
|
-
};
|
|
7447
|
-
|
|
7448
7602
|
function resolveAutoStart(args) {
|
|
7449
|
-
const {autoStart: autoStart,
|
|
7450
|
-
|
|
7451
|
-
const evaluated = evaluateMap(autoStart, context);
|
|
7452
|
-
if ("warning" in evaluated) return {
|
|
7453
|
-
byType: /* @__PURE__ */ new Map,
|
|
7454
|
-
definitions: /* @__PURE__ */ new Map,
|
|
7455
|
-
warnings: [ evaluated.warning ]
|
|
7456
|
-
};
|
|
7457
|
-
const map = evaluated.map, latestByName = new Map(latestDeployedDefinitions(definitions).map(d => [ d.name, d ])), byType = /* @__PURE__ */ new Map, resolvedDefinitions = /* @__PURE__ */ new Map, warnings = [];
|
|
7458
|
-
for (const [docType, spec] of Object.entries(map)) {
|
|
7603
|
+
const {autoStart: autoStart, knownDocTypes: knownDocTypes, definitions: definitions} = args, latestByName = new Map(latestDeployedDefinitions(definitions).map(d => [ d.name, d ])), byType = /* @__PURE__ */ new Map, resolvedDefinitions = /* @__PURE__ */ new Map, warnings = [];
|
|
7604
|
+
for (const [docType, names] of Object.entries(autoStart)) {
|
|
7459
7605
|
const entry = resolveEntry({
|
|
7460
7606
|
docType: docType,
|
|
7461
|
-
|
|
7607
|
+
names: names,
|
|
7462
7608
|
knownDocTypes: knownDocTypes,
|
|
7463
7609
|
latestByName: latestByName
|
|
7464
7610
|
});
|
|
@@ -7474,35 +7620,15 @@ function resolveAutoStart(args) {
|
|
|
7474
7620
|
};
|
|
7475
7621
|
}
|
|
7476
7622
|
|
|
7477
|
-
function evaluateMap(autoStart, context) {
|
|
7478
|
-
let map;
|
|
7479
|
-
try {
|
|
7480
|
-
map = typeof autoStart == "function" ? autoStart(context) : autoStart;
|
|
7481
|
-
} catch (err) {
|
|
7482
|
-
return {
|
|
7483
|
-
warning: `autoStart: config function threw — ignoring it (${describeError(err)}).`
|
|
7484
|
-
};
|
|
7485
|
-
}
|
|
7486
|
-
return typeof map != "object" || map === null ? {
|
|
7487
|
-
warning: "autoStart: config did not resolve to an object — ignoring it."
|
|
7488
|
-
} : {
|
|
7489
|
-
map: map
|
|
7490
|
-
};
|
|
7491
|
-
}
|
|
7492
|
-
|
|
7493
|
-
function specNames(spec) {
|
|
7494
|
-
return typeof spec == "string" ? [ spec ] : Array.isArray(spec) ? spec : [];
|
|
7495
|
-
}
|
|
7496
|
-
|
|
7497
7623
|
function resolveEntry(args) {
|
|
7498
|
-
const {docType: docType,
|
|
7624
|
+
const {docType: docType, names: names, knownDocTypes: knownDocTypes, latestByName: latestByName} = args;
|
|
7499
7625
|
if (!knownDocTypes.has(docType)) return {
|
|
7500
7626
|
valid: [],
|
|
7501
7627
|
definitions: [],
|
|
7502
7628
|
warnings: [ `autoStart: no schema type "${docType}" — entry skipped.` ]
|
|
7503
7629
|
};
|
|
7504
7630
|
const valid = [], definitions = [], warnings = [];
|
|
7505
|
-
for (const name of
|
|
7631
|
+
for (const name of names) {
|
|
7506
7632
|
const definition = latestByName.get(name), issue = workflowIssue({
|
|
7507
7633
|
name: name,
|
|
7508
7634
|
docType: docType,
|
|
@@ -7528,11 +7654,9 @@ function workflowIssue(args) {
|
|
|
7528
7654
|
const {name: name, docType: docType, definition: definition} = args;
|
|
7529
7655
|
if (definition === void 0) return `autoStart: "${docType}" → workflow "${name}" is not deployed — skipped.`;
|
|
7530
7656
|
if (!isStartableDefinition(definition)) return `autoStart: "${docType}" → workflow "${name}" is spawn-only, not startable — skipped.`;
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
const subject = (definition.fields ?? []).find(isSubjectEntry);
|
|
7535
|
-
if (subject !== void 0 && !isInputSourced(subject)) return `autoStart: "${docType}" → workflow "${name}" has a self-filling subject (not caller-provided), so the document can't be its subject — skipped.`;
|
|
7657
|
+
const subject = documentSubjectEntry(definition), acceptsType = subject?.types === void 0 || subject.types.includes(docType);
|
|
7658
|
+
if (subject === void 0 || !acceptsType) return `autoStart: "${docType}" → workflow "${name}" has no document subject accepting "${docType}" — skipped.`;
|
|
7659
|
+
if (!isInputSourced(subject)) return `autoStart: "${docType}" → workflow "${name}" has a self-filling subject (not caller-provided), so the document can't be its subject — skipped.`;
|
|
7536
7660
|
}
|
|
7537
7661
|
|
|
7538
7662
|
function contentDocumentTypes(schema) {
|
|
@@ -7552,20 +7676,31 @@ const EMPTY_SNAPSHOT = {
|
|
|
7552
7676
|
};
|
|
7553
7677
|
|
|
7554
7678
|
function useDiscoveryState(args) {
|
|
7555
|
-
const {
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
watching || (setLatest(EMPTY_SNAPSHOT), setResolved(EMPTY_SNAPSHOT));
|
|
7560
|
-
}, [ watching ]);
|
|
7561
|
-
const filter = useMemo(() => ({
|
|
7562
|
-
documents: registered.map(id => gdrFromResource(contentResource, id)),
|
|
7679
|
+
const {observed: observed, requested: requested, contentResource: contentResource} = args, documentWatching = observed.length > 0, requestedWatching = requested.length > 0, documents = useDiscoveryStream(documentWatching), explicit = useDiscoveryStream(requestedWatching), documentFilter = useMemo(() => documentWatching ? {
|
|
7680
|
+
documents: observed.map(id => gdrFromResource(contentResource, id)),
|
|
7681
|
+
includeCompleted: !0
|
|
7682
|
+
} : void 0, [ documentWatching, observed, contentResource ]), requestedFilter = useMemo(() => requestedWatching ? {
|
|
7563
7683
|
ids: requested,
|
|
7564
7684
|
includeCompleted: !0
|
|
7565
|
-
}
|
|
7685
|
+
} : void 0, [ requestedWatching, requested ]), resolved = useMemo(() => mergeResolved(documents.resolved, explicit.resolved), [ documents.resolved, explicit.resolved ]);
|
|
7566
7686
|
return {
|
|
7567
|
-
|
|
7568
|
-
|
|
7687
|
+
documentFilter: documentFilter,
|
|
7688
|
+
requestedFilter: requestedFilter,
|
|
7689
|
+
loading: documents.loading || explicit.loading,
|
|
7690
|
+
invalid: documents.invalid ?? explicit.invalid,
|
|
7691
|
+
resolved: resolved,
|
|
7692
|
+
onDocumentSnapshot: documents.onSnapshot,
|
|
7693
|
+
onRequestedSnapshot: explicit.onSnapshot
|
|
7694
|
+
};
|
|
7695
|
+
}
|
|
7696
|
+
|
|
7697
|
+
function useDiscoveryStream(watching) {
|
|
7698
|
+
const [latest, setLatest] = useState(EMPTY_SNAPSHOT), [resolved, setResolved] = useState(EMPTY_SNAPSHOT), onSnapshot = useCallback(snapshot => {
|
|
7699
|
+
setLatest(snapshot), snapshot.instances !== void 0 && setResolved(snapshot);
|
|
7700
|
+
}, []);
|
|
7701
|
+
return useEffect(() => {
|
|
7702
|
+
watching || (setLatest(EMPTY_SNAPSHOT), setResolved(EMPTY_SNAPSHOT));
|
|
7703
|
+
}, [ watching ]), {
|
|
7569
7704
|
loading: watching && latest.instances === void 0 && latest.invalid === void 0,
|
|
7570
7705
|
invalid: watching ? latest.invalid : void 0,
|
|
7571
7706
|
resolved: resolved,
|
|
@@ -7573,18 +7708,62 @@ function useDiscoveryState(args) {
|
|
|
7573
7708
|
};
|
|
7574
7709
|
}
|
|
7575
7710
|
|
|
7576
|
-
function
|
|
7577
|
-
const
|
|
7578
|
-
for (const
|
|
7579
|
-
const
|
|
7580
|
-
|
|
7711
|
+
function mergeResolved(documents, explicit) {
|
|
7712
|
+
const rows = [ ...documents.instances ?? [], ...explicit.instances ?? [] ], freshest = /* @__PURE__ */ new Map;
|
|
7713
|
+
for (const instance of rows) {
|
|
7714
|
+
const current = freshest.get(instance._id);
|
|
7715
|
+
(current === void 0 || Date.parse(instance.lastChangedAt) > Date.parse(current.lastChangedAt)) && freshest.set(instance._id, instance);
|
|
7581
7716
|
}
|
|
7717
|
+
return {
|
|
7718
|
+
instances: documents.instances === void 0 && explicit.instances === void 0 ? void 0 : [ ...freshest.values() ],
|
|
7719
|
+
invalid: documents.invalid ?? explicit.invalid,
|
|
7720
|
+
registered: documents.registered
|
|
7721
|
+
};
|
|
7722
|
+
}
|
|
7723
|
+
|
|
7724
|
+
function createDiscoveryIndexer(deriveWatchSet = subscriptionDocumentsForInstance) {
|
|
7725
|
+
const cached = /* @__PURE__ */ new Map;
|
|
7726
|
+
return {
|
|
7727
|
+
index(args) {
|
|
7728
|
+
const liveIds = new Set(args.instances.map(instance => instance._id));
|
|
7729
|
+
for (const id of cached.keys()) liveIds.has(id) || cached.delete(id);
|
|
7730
|
+
const watchedById = /* @__PURE__ */ new Map;
|
|
7731
|
+
for (const instance of args.instances) {
|
|
7732
|
+
let row = cached.get(instance._id);
|
|
7733
|
+
row?.source !== instance && (row = {
|
|
7734
|
+
source: instance,
|
|
7735
|
+
globalDocumentIds: [ ...new Set(deriveWatchSet(instance).documents.map(document => document.globalDocumentId)) ]
|
|
7736
|
+
}, cached.set(instance._id, row)), watchedById.set(instance._id, row.globalDocumentIds);
|
|
7737
|
+
}
|
|
7738
|
+
return buildDiscoveryIndex(args, watchedById);
|
|
7739
|
+
}
|
|
7740
|
+
};
|
|
7741
|
+
}
|
|
7742
|
+
|
|
7743
|
+
function buildDiscoveryIndex(args, watchedById) {
|
|
7744
|
+
const {instances: instances, registered: registered, contentResource: contentResource} = args, ordered = [ ...instances ].sort((a, b) => b.startedAt.localeCompare(a.startedAt)), index = /* @__PURE__ */ new Map, registeredByUri = new Map(registered.map(bareId => [ gdrFromResource(contentResource, bareId), bareId ]));
|
|
7745
|
+
for (const instance of ordered) appendInstanceWatches({
|
|
7746
|
+
index: index,
|
|
7747
|
+
registeredByUri: registeredByUri,
|
|
7748
|
+
instanceId: instance._id,
|
|
7749
|
+
watched: watchedById.get(instance._id) ?? []
|
|
7750
|
+
});
|
|
7582
7751
|
return {
|
|
7583
7752
|
instances: new Map(ordered.map(inst => [ inst._id, inst ])),
|
|
7584
7753
|
index: index
|
|
7585
7754
|
};
|
|
7586
7755
|
}
|
|
7587
7756
|
|
|
7757
|
+
function appendInstanceWatches(args) {
|
|
7758
|
+
const {index: index, registeredByUri: registeredByUri, instanceId: instanceId, watched: watched} = args;
|
|
7759
|
+
for (const uri of watched) {
|
|
7760
|
+
const bareId = registeredByUri.get(uri);
|
|
7761
|
+
if (bareId === void 0) continue;
|
|
7762
|
+
const ids = index.get(bareId);
|
|
7763
|
+
ids === void 0 ? index.set(bareId, [ instanceId ]) : ids.push(instanceId);
|
|
7764
|
+
}
|
|
7765
|
+
}
|
|
7766
|
+
|
|
7588
7767
|
function sameInstance(a, b) {
|
|
7589
7768
|
return a === b || a._id === b._id && a._rev === b._rev;
|
|
7590
7769
|
}
|
|
@@ -7608,7 +7787,7 @@ function entryOf(inst, report) {
|
|
|
7608
7787
|
instance: report?.evaluation?.instance ?? inst,
|
|
7609
7788
|
committed: inst,
|
|
7610
7789
|
evaluation: report?.evaluation,
|
|
7611
|
-
ready: report?.ready ??
|
|
7790
|
+
ready: report?.ready ?? terminalState(inst) !== "in-flight",
|
|
7612
7791
|
invalid: report?.invalid,
|
|
7613
7792
|
guards: report?.guards
|
|
7614
7793
|
};
|
|
@@ -7701,7 +7880,19 @@ function createEntriesStore() {
|
|
|
7701
7880
|
};
|
|
7702
7881
|
}
|
|
7703
7882
|
|
|
7704
|
-
|
|
7883
|
+
function sessionPlan(args) {
|
|
7884
|
+
const demandedIds = new Set(args.demanded), evaluated = [ ...args.discovered.values() ].filter(inst => demandedIds.has(inst._id));
|
|
7885
|
+
return {
|
|
7886
|
+
evaluated: evaluated,
|
|
7887
|
+
guardScope: evaluated.map(inst => inst._id).sort()
|
|
7888
|
+
};
|
|
7889
|
+
}
|
|
7890
|
+
|
|
7891
|
+
function useDefaultLayout(props) {
|
|
7892
|
+
return useMemo(() => props.renderDefault(props), [ props ]);
|
|
7893
|
+
}
|
|
7894
|
+
|
|
7895
|
+
const notReady = (..._args) => Promise.reject(new Error("workflow session not ready yet")), NO_REGISTERED_DOCUMENTS = [], DEMAND_RELEASE_GRACE_MS = 500;
|
|
7705
7896
|
|
|
7706
7897
|
function workspaceParts(config) {
|
|
7707
7898
|
if (!config.projectId || !config.dataset) throw new Error("workflow plugin requires a workspace with projectId and dataset");
|
|
@@ -7729,10 +7920,11 @@ class InstanceEvaluatorBoundary extends Component {
|
|
|
7729
7920
|
}
|
|
7730
7921
|
|
|
7731
7922
|
function InstanceEvaluator(props) {
|
|
7732
|
-
const {engine: engine, instanceId: instanceId, grantsFromPath: grantsFromPath, onReport: onReport} = props, {evaluation: evaluation, ready: ready, invalid: invalid, guards: guards, fireAction: fireAction, editField: editField, previewField: previewField, discardFieldPreview: discardFieldPreview} = useWorkflowSession({
|
|
7923
|
+
const {engine: engine, instanceId: instanceId, grantsFromPath: grantsFromPath, guardScope: guardScope, onReport: onReport} = props, {evaluation: evaluation, ready: ready, invalid: invalid, guards: guards, fireAction: fireAction, editField: editField, previewField: previewField, discardFieldPreview: discardFieldPreview} = useWorkflowSession({
|
|
7733
7924
|
engine: engine,
|
|
7734
7925
|
instanceId: instanceId,
|
|
7735
|
-
grantsFromPath: grantsFromPath
|
|
7926
|
+
grantsFromPath: grantsFromPath,
|
|
7927
|
+
guardScope: guardScope
|
|
7736
7928
|
});
|
|
7737
7929
|
return useEffect(() => {
|
|
7738
7930
|
onReport(instanceId, {
|
|
@@ -7775,9 +7967,9 @@ function engineOptionsFrom(config) {
|
|
|
7775
7967
|
}
|
|
7776
7968
|
|
|
7777
7969
|
function WorkflowProvider(props) {
|
|
7778
|
-
const {config: config} = props, studioClient = useClient({
|
|
7970
|
+
const {config: config} = props, defaultLayout = useDefaultLayout(props), studioClient = useClient({
|
|
7779
7971
|
apiVersion: WORKFLOW_API_VERSION
|
|
7780
|
-
}), schema = useSchema(), {
|
|
7972
|
+
}), schema = useSchema(), {projectId: projectId, dataset: contentDataset} = workspaceParts(studioClient.config()), workflowDataset = config.workflowDataset ?? contentDataset, binding = useMemo(() => ({
|
|
7781
7973
|
engineResource: {
|
|
7782
7974
|
type: "dataset",
|
|
7783
7975
|
id: `${projectId}.${workflowDataset}`
|
|
@@ -7795,7 +7987,15 @@ function WorkflowProvider(props) {
|
|
|
7795
7987
|
}), grantsFromPath = aclPathForResource({
|
|
7796
7988
|
type: "dataset",
|
|
7797
7989
|
id: `${projectId}.${workflowDataset}`
|
|
7798
|
-
}), {ids: registered, acquire:
|
|
7990
|
+
}), {ids: registered, acquire: registerActive, release: unregisterActive} = useRefcountedIds(), {ids: observed, acquire: retainRegistration, release: releaseRegistration} = useRefcountedIds({
|
|
7991
|
+
releaseDelayMs: DEMAND_RELEASE_GRACE_MS
|
|
7992
|
+
}), register = useCallback(id => {
|
|
7993
|
+
registerActive(id), retainRegistration(id);
|
|
7994
|
+
}, [ registerActive, retainRegistration ]), unregister = useCallback(id => {
|
|
7995
|
+
unregisterActive(id), releaseRegistration(id);
|
|
7996
|
+
}, [ unregisterActive, releaseRegistration ]), {ids: requested, acquire: requestInstance, release: releaseInstance} = useRefcountedIds(), {ids: evaluationDemand, acquire: requestEvaluation, release: releaseEvaluation} = useRefcountedIds({
|
|
7997
|
+
releaseDelayMs: DEMAND_RELEASE_GRACE_MS
|
|
7998
|
+
}), [seeded, setSeeded] = useState(/* @__PURE__ */ new Map), seedInstance = useCallback(instance => {
|
|
7799
7999
|
setSeeded(prev => new Map(prev).set(instance._id, instance));
|
|
7800
8000
|
}, []), [startRequest2, setStartRequest] = useState(void 0), openStartDialog = useCallback(r => setStartRequest(r), []), closeStartDialog = useCallback(() => setStartRequest(void 0), []), [entriesStore] = useState(createEntriesStore);
|
|
7801
8001
|
useEffect(() => () => entriesStore.dispose(), [ entriesStore ]);
|
|
@@ -7846,15 +8046,18 @@ function WorkflowProvider(props) {
|
|
|
7846
8046
|
});
|
|
7847
8047
|
}, [ engine ]);
|
|
7848
8048
|
drainRef.current = drainEffectsFor;
|
|
7849
|
-
const {
|
|
7850
|
-
|
|
8049
|
+
const {documentFilter: documentFilter, requestedFilter: requestedFilter, loading: loading, invalid: discoveryInvalid, resolved: resolved, onDocumentSnapshot: onDocumentSnapshot, onRequestedSnapshot: onRequestedSnapshot} = useDiscoveryState({
|
|
8050
|
+
observed: observed,
|
|
7851
8051
|
requested: requested,
|
|
7852
8052
|
contentResource: binding.contentResource
|
|
7853
|
-
}), {instances: discovered, index: docIndex} = useMemo(() =>
|
|
8053
|
+
}), discoveryIndexer = useMemo(createDiscoveryIndexer, []), {instances: discovered, index: docIndex} = useMemo(() => discoveryIndexer.index({
|
|
7854
8054
|
instances: resolved.instances ?? [],
|
|
7855
8055
|
registered: resolved.registered,
|
|
7856
8056
|
contentResource: binding.contentResource
|
|
7857
|
-
}), [ resolved, binding.contentResource ]),
|
|
8057
|
+
}), [ discoveryIndexer, resolved, binding.contentResource ]), {evaluated: evaluated, guardScope: guardScope} = useMemo(() => sessionPlan({
|
|
8058
|
+
discovered: discovered,
|
|
8059
|
+
demanded: evaluationDemand
|
|
8060
|
+
}), [ discovered, evaluationDemand ]), resolvedDocs = useMemo(() => new Set(resolved.registered), [ resolved.registered ]);
|
|
7858
8061
|
useEffect(() => {
|
|
7859
8062
|
setSeeded(prev => {
|
|
7860
8063
|
const kept = [ ...prev ].filter(([id]) => !discovered.has(id));
|
|
@@ -7867,15 +8070,13 @@ function WorkflowProvider(props) {
|
|
|
7867
8070
|
docIndex: docIndex
|
|
7868
8071
|
});
|
|
7869
8072
|
}, [ entriesStore, seeded, discovered, docIndex ]);
|
|
7870
|
-
const isDocResolved = useCallback(docId => resolvedDocs.has(docId), [ resolvedDocs ]), schemaContentTypes = useMemo(() => new Set(contentDocumentTypes(schema)), [ schema ]), {issues: issues, starts: starts, fields: fields, latestVersions: latestVersions, autoStartByType: autoStartByType, autoStartDefinitions: autoStartDefinitions} = useDeployedDefinitions({
|
|
8073
|
+
const isDocResolved = useCallback(docId => resolvedDocs.has(docId), [ resolvedDocs ]), schemaContentTypes = useMemo(() => new Set(contentDocumentTypes(schema)), [ schema ]), {mappings: mappings, issues: issues, starts: starts, fields: fields, latestVersions: latestVersions, autoStartByType: autoStartByType, autoStartDefinitions: autoStartDefinitions} = useDeployedDefinitions({
|
|
7871
8074
|
engine: engine,
|
|
7872
|
-
|
|
8075
|
+
overrides: config.mappings,
|
|
7873
8076
|
contentResource: binding.contentResource,
|
|
7874
8077
|
schemaContentTypes: schemaContentTypes,
|
|
7875
8078
|
startRequest: startRequest2,
|
|
7876
|
-
|
|
7877
|
-
schema: schema,
|
|
7878
|
-
workspaceName: workspaceName
|
|
8079
|
+
schema: schema
|
|
7879
8080
|
}), value = useMemo(() => ({
|
|
7880
8081
|
register: register,
|
|
7881
8082
|
unregister: unregister,
|
|
@@ -7883,6 +8084,8 @@ function WorkflowProvider(props) {
|
|
|
7883
8084
|
entries: entriesStore,
|
|
7884
8085
|
requestInstance: requestInstance,
|
|
7885
8086
|
releaseInstance: releaseInstance,
|
|
8087
|
+
requestEvaluation: requestEvaluation,
|
|
8088
|
+
releaseEvaluation: releaseEvaluation,
|
|
7886
8089
|
seedInstance: seedInstance,
|
|
7887
8090
|
openStartDialog: openStartDialog,
|
|
7888
8091
|
closeStartDialog: closeStartDialog,
|
|
@@ -7897,7 +8100,7 @@ function WorkflowProvider(props) {
|
|
|
7897
8100
|
completeEffectFor: completeEffectFor,
|
|
7898
8101
|
engine: engine,
|
|
7899
8102
|
binding: binding,
|
|
7900
|
-
mappings:
|
|
8103
|
+
mappings: mappings,
|
|
7901
8104
|
mappingIssues: issues,
|
|
7902
8105
|
mappingStarts: starts,
|
|
7903
8106
|
mappingFields: fields,
|
|
@@ -7905,24 +8108,30 @@ function WorkflowProvider(props) {
|
|
|
7905
8108
|
effectHandlers: engine.effectHandlers,
|
|
7906
8109
|
autoStartByType: autoStartByType,
|
|
7907
8110
|
autoStartDefinitions: autoStartDefinitions
|
|
7908
|
-
}), [ register, unregister, isDocResolved, entriesStore, requestInstance, releaseInstance, seedInstance, openStartDialog, closeStartDialog, startRequest2, loading, discoveryInvalid, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding,
|
|
8111
|
+
}), [ register, unregister, isDocResolved, entriesStore, requestInstance, releaseInstance, requestEvaluation, releaseEvaluation, seedInstance, openStartDialog, closeStartDialog, startRequest2, loading, discoveryInvalid, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding, mappings, issues, starts, fields, latestVersions, autoStartByType, autoStartDefinitions ]);
|
|
7909
8112
|
/* @__PURE__ */
|
|
7910
8113
|
return jsxs(WorkflowContext.Provider, {
|
|
7911
8114
|
value: value,
|
|
7912
|
-
children: [
|
|
8115
|
+
children: [ documentFilter ? /* @__PURE__ */ jsx(DiscoverySubscription, {
|
|
7913
8116
|
engine: engine,
|
|
7914
|
-
filter:
|
|
7915
|
-
onSnapshot:
|
|
8117
|
+
filter: documentFilter,
|
|
8118
|
+
onSnapshot: onDocumentSnapshot,
|
|
7916
8119
|
registered: registered
|
|
7917
|
-
}) : null,
|
|
8120
|
+
}) : null, requestedFilter ? /* @__PURE__ */ jsx(DiscoverySubscription, {
|
|
8121
|
+
engine: engine,
|
|
8122
|
+
filter: requestedFilter,
|
|
8123
|
+
onSnapshot: onRequestedSnapshot,
|
|
8124
|
+
registered: NO_REGISTERED_DOCUMENTS
|
|
8125
|
+
}) : null, evaluated.map(inst => /* @__PURE__ */ jsx(InstanceEvaluatorBoundary, {
|
|
7918
8126
|
instanceId: inst._id,
|
|
7919
8127
|
children: /* @__PURE__ */ jsx(InstanceEvaluator, {
|
|
7920
8128
|
engine: engine,
|
|
7921
8129
|
grantsFromPath: grantsFromPath,
|
|
8130
|
+
guardScope: guardScope,
|
|
7922
8131
|
instanceId: inst._id,
|
|
7923
8132
|
onReport: onReport
|
|
7924
8133
|
})
|
|
7925
|
-
}, inst._id)),
|
|
8134
|
+
}, inst._id)), defaultLayout, props.overlay ]
|
|
7926
8135
|
});
|
|
7927
8136
|
}
|
|
7928
8137
|
|
|
@@ -7932,14 +8141,25 @@ function sameEntries(a, b) {
|
|
|
7932
8141
|
return !0;
|
|
7933
8142
|
}
|
|
7934
8143
|
|
|
8144
|
+
function sameMappings(a, b) {
|
|
8145
|
+
return a.length === b.length && a.every((mapping, index) => {
|
|
8146
|
+
const other = b[index];
|
|
8147
|
+
return other !== void 0 && mappingKey(mapping) === mappingKey(other) && mapping.label === other.label && mapping.autoStart === other.autoStart && mapping.initialStateBuilder === other.initialStateBuilder && mapping.contextBuilder === other.contextBuilder && mapping.perspectiveField === other.perspectiveField;
|
|
8148
|
+
});
|
|
8149
|
+
}
|
|
8150
|
+
|
|
7935
8151
|
function useDeployedDefinitions(args) {
|
|
7936
|
-
const {engine: engine,
|
|
8152
|
+
const {engine: engine, overrides: overrides, contentResource: contentResource, schemaContentTypes: schemaContentTypes, startRequest: startRequest2, schema: schema} = args, [mappings, setMappings] = useState([]), [issues, setIssues] = useState(/* @__PURE__ */ new Map), [starts, setStarts] = useState(/* @__PURE__ */ new Map), [fields, setFields] = useState(/* @__PURE__ */ new Map), [latestVersions, setLatestVersions] = useState(/* @__PURE__ */ new Map), [autoStartByType, setAutoStartByType] = useState(
|
|
7937
8153
|
/* @__PURE__ */ new Map), [autoStartDefinitions, setAutoStartDefinitions] = useState(/* @__PURE__ */ new Map), logged = useRef(/* @__PURE__ */ new Set);
|
|
7938
8154
|
return useEffect(() => {
|
|
7939
8155
|
let cancelled = !1;
|
|
7940
8156
|
return (async () => {
|
|
7941
|
-
const definitions = await readDeployedDefinitions(engine),
|
|
7942
|
-
|
|
8157
|
+
const definitions = await readDeployedDefinitions(engine), effectiveMappings = discoverWorkflowMappings({
|
|
8158
|
+
definitions: definitions,
|
|
8159
|
+
schemaContentTypes: schemaContentTypes,
|
|
8160
|
+
overrides: overrides
|
|
8161
|
+
}), found = mappingIssues({
|
|
8162
|
+
mappings: effectiveMappings,
|
|
7943
8163
|
definitions: definitions,
|
|
7944
8164
|
contentResource: contentResource,
|
|
7945
8165
|
schemaContentTypes: schemaContentTypes
|
|
@@ -7949,32 +8169,30 @@ function useDeployedDefinitions(args) {
|
|
|
7949
8169
|
logged.current.has(signature) || (logged.current.add(signature), console.error(`[workflow-studio-plugin] ${message}`));
|
|
7950
8170
|
}
|
|
7951
8171
|
const resolvedAutoStart = resolveAutoStart({
|
|
7952
|
-
autoStart:
|
|
7953
|
-
context: {
|
|
7954
|
-
workspaceName: workspaceName,
|
|
7955
|
-
schema: schema
|
|
7956
|
-
},
|
|
8172
|
+
autoStart: mappingAutoStartMap(effectiveMappings),
|
|
7957
8173
|
knownDocTypes: new Set(schema.getTypeNames()),
|
|
7958
8174
|
definitions: definitions
|
|
7959
8175
|
});
|
|
7960
8176
|
if (logOnce(resolvedAutoStart.warnings, logged.current), cancelled) return;
|
|
8177
|
+
setMappings(prev => sameMappings(prev, effectiveMappings) ? prev : effectiveMappings),
|
|
7961
8178
|
setIssues(prev => sameEntries(prev, found) ? prev : found), setStarts(mappingStartBlocks({
|
|
7962
|
-
mappings:
|
|
8179
|
+
mappings: effectiveMappings,
|
|
7963
8180
|
definitions: definitions
|
|
7964
8181
|
})), setFields(mappingDeclaredFields({
|
|
7965
|
-
mappings:
|
|
8182
|
+
mappings: effectiveMappings,
|
|
7966
8183
|
definitions: definitions
|
|
7967
8184
|
}));
|
|
7968
8185
|
const versions = new Map(latestDeployedDefinitions(definitions).map(d => [ d.name, d.version ]));
|
|
7969
8186
|
setLatestVersions(prev => sameEntries(prev, versions) ? prev : versions), setAutoStartByType(resolvedAutoStart.byType),
|
|
7970
8187
|
setAutoStartDefinitions(resolvedAutoStart.definitions);
|
|
7971
8188
|
})().catch(err => {
|
|
7972
|
-
console.error("[workflow-studio-plugin] mapping
|
|
8189
|
+
console.error("[workflow-studio-plugin] mapping discovery failed — keeping the last resolved workflow state:", err);
|
|
7973
8190
|
}), () => {
|
|
7974
8191
|
cancelled = !0;
|
|
7975
8192
|
};
|
|
7976
|
-
}, [ engine,
|
|
8193
|
+
}, [ engine, overrides, contentResource, schemaContentTypes, startRequest2, schema ]),
|
|
7977
8194
|
{
|
|
8195
|
+
mappings: mappings,
|
|
7978
8196
|
issues: issues,
|
|
7979
8197
|
starts: starts,
|
|
7980
8198
|
fields: fields,
|
|
@@ -8760,7 +8978,7 @@ function isFreshDocument(value) {
|
|
|
8760
8978
|
}
|
|
8761
8979
|
|
|
8762
8980
|
function subjectEntry(definition) {
|
|
8763
|
-
return (definition
|
|
8981
|
+
return documentSubjectEntry(definition);
|
|
8764
8982
|
}
|
|
8765
8983
|
|
|
8766
8984
|
function autoStartInputs(args) {
|
|
@@ -8787,11 +9005,11 @@ function pendingWorkflows(workflows, live) {
|
|
|
8787
9005
|
}
|
|
8788
9006
|
|
|
8789
9007
|
function extraRequiredInputs(definition) {
|
|
8790
|
-
const fields = definition.fields ?? [],
|
|
9008
|
+
const fields = definition.fields ?? [], subjectName = subjectEntry(definition)?.name, requiredNames = new Set(missingRequiredInputs({
|
|
8791
9009
|
entryDefs: fields,
|
|
8792
9010
|
initialFields: []
|
|
8793
9011
|
}).map(input => input.name));
|
|
8794
|
-
return fields.filter(entry => requiredNames.has(entry.name) &&
|
|
9012
|
+
return fields.filter(entry => requiredNames.has(entry.name) && entry.name !== subjectName);
|
|
8795
9013
|
}
|
|
8796
9014
|
|
|
8797
9015
|
function buildAutoStartRequests(args) {
|
|
@@ -8839,7 +9057,7 @@ function AutoStartDriver(props) {
|
|
|
8839
9057
|
const pending = useMemo(() => pendingWorkflows(workflows, new Set(entries.map(entry => entry.instance.definition))), [ workflows, entries ]), inputs = useMemo(() => autoStartInputs({
|
|
8840
9058
|
workflows: pending,
|
|
8841
9059
|
definitions: autoStartDefinitions
|
|
8842
|
-
}), [ pending, autoStartDefinitions ]), pendingRef = useRef(pending);
|
|
9060
|
+
}), [ pending, autoStartDefinitions ]), definitionsResolved = workflows.every(name => autoStartDefinitions.has(name)), pendingRef = useRef(pending);
|
|
8843
9061
|
pendingRef.current = pending;
|
|
8844
9062
|
const instanceIds = useRef(/* @__PURE__ */ new Map), instanceIdFor = useCallback(workflow => {
|
|
8845
9063
|
const held = instanceIds.current.get(workflow);
|
|
@@ -8883,7 +9101,7 @@ function AutoStartDriver(props) {
|
|
|
8883
9101
|
}, [ autoStartDefinitions, docId, docType, binding, engine, observer, seedInstance, instanceIdFor, selectedReleaseId ]), retry = useCallback(() => {
|
|
8884
9102
|
firedRef.current = !1, setFired(!1), setSettled(!1), setFailure(void 0);
|
|
8885
9103
|
}, []), action = autoStartAction({
|
|
8886
|
-
resolved: isDocResolved(docId),
|
|
9104
|
+
resolved: definitionsResolved && isDocResolved(docId),
|
|
8887
9105
|
pendingCount: pending.length,
|
|
8888
9106
|
needsInput: inputs.length > 0,
|
|
8889
9107
|
fired: fired,
|
|
@@ -9305,6 +9523,61 @@ function TaskCountSpinner({entry: entry}) {
|
|
|
9305
9523
|
});
|
|
9306
9524
|
}
|
|
9307
9525
|
|
|
9526
|
+
function stagePillState(instance) {
|
|
9527
|
+
const definition = definitionSnapshotOf(instance), stage = definition?.stages.find(candidate => candidate.name === instance.currentStage), state = terminalState(instance);
|
|
9528
|
+
return {
|
|
9529
|
+
title: stageTitle(definition, instance.currentStage),
|
|
9530
|
+
terminal: stage !== void 0 && isTerminalStage(stage) || state !== "in-flight",
|
|
9531
|
+
state: state,
|
|
9532
|
+
stageKnown: stage !== void 0
|
|
9533
|
+
};
|
|
9534
|
+
}
|
|
9535
|
+
|
|
9536
|
+
function WorkflowStagePreview(props) {
|
|
9537
|
+
const {mappings: mappings} = useWorkflowContext(), mapped = props.schemaType !== void 0 && mappingsForDocType(mappings, props.schemaType.name).length > 0, {entries: entries} = useCommittedWorkflowsForDocument(mapped ? props._id ?? null : null), lead = entries.find(isLiveEntry) ?? entries[0], extraLive = entries.filter(e => e !== lead && isLiveEntry(e)).length;
|
|
9538
|
+
return props.renderDefault({
|
|
9539
|
+
...props,
|
|
9540
|
+
status: lead ? /* @__PURE__ */ jsx(StagePill, {
|
|
9541
|
+
entry: lead,
|
|
9542
|
+
extraLive: extraLive
|
|
9543
|
+
}) : props.status
|
|
9544
|
+
});
|
|
9545
|
+
}
|
|
9546
|
+
|
|
9547
|
+
function StagePill({entry: entry, extraLive: extraLive}) {
|
|
9548
|
+
/* @__PURE__ */
|
|
9549
|
+
return jsxs(Flex, {
|
|
9550
|
+
align: "center",
|
|
9551
|
+
gap: 2,
|
|
9552
|
+
children: [
|
|
9553
|
+
/* @__PURE__ */ jsx(LeadBadge, {
|
|
9554
|
+
entry: entry
|
|
9555
|
+
}), extraLive > 0 ? /* @__PURE__ */ jsxs(Badge, {
|
|
9556
|
+
fontSize: 1,
|
|
9557
|
+
mode: "outline",
|
|
9558
|
+
tone: "default",
|
|
9559
|
+
children: [ "+", extraLive ]
|
|
9560
|
+
}) : null ]
|
|
9561
|
+
});
|
|
9562
|
+
}
|
|
9563
|
+
|
|
9564
|
+
function LeadBadge({entry: entry}) {
|
|
9565
|
+
const {instance: instance} = entry;
|
|
9566
|
+
if (isUnprimed(instance)) /* @__PURE__ */ return jsx(StartIncompleteBadge, {});
|
|
9567
|
+
const pill = stagePillState(instance);
|
|
9568
|
+
/* @__PURE__ */
|
|
9569
|
+
return jsxs(Badge, {
|
|
9570
|
+
fontSize: 1,
|
|
9571
|
+
mode: pill.terminal ? "default" : "outline",
|
|
9572
|
+
tone: pillTone(pill),
|
|
9573
|
+
children: [ pill.title, pill.state === "completed" ? " ✓" : "" ]
|
|
9574
|
+
});
|
|
9575
|
+
}
|
|
9576
|
+
|
|
9577
|
+
function pillTone(args) {
|
|
9578
|
+
return args.state === "aborted" ? "critical" : args.terminal ? "positive" : args.stageKnown ? "primary" : "default";
|
|
9579
|
+
}
|
|
9580
|
+
|
|
9308
9581
|
function StartWorkflowDialogHost() {
|
|
9309
9582
|
const {startRequest: startRequest2, closeStartDialog: closeStartDialog} = useWorkflowContext();
|
|
9310
9583
|
return startRequest2 ? /* @__PURE__ */ jsx(StartWorkflowDialog, {
|
|
@@ -9377,7 +9650,8 @@ function withWorkflowLock(Action, guardAction) {
|
|
|
9377
9650
|
Locked;
|
|
9378
9651
|
}
|
|
9379
9652
|
|
|
9380
|
-
const workflowStudioPlugin = definePlugin(config => (
|
|
9653
|
+
const workflowStudioPlugin = definePlugin(config => (assertUniqueWorkflowMappings(config.mappings ?? []),
|
|
9654
|
+
{
|
|
9381
9655
|
name: "workflow-studio-plugin",
|
|
9382
9656
|
tools: prev => [ ...prev, workflowsTool ],
|
|
9383
9657
|
studio: {
|
|
@@ -9391,82 +9665,35 @@ const workflowStudioPlugin = definePlugin(config => ({
|
|
|
9391
9665
|
},
|
|
9392
9666
|
form: {
|
|
9393
9667
|
components: {
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
mappings: docTypeMappings
|
|
9399
|
-
}) : props.renderDefault(props);
|
|
9400
|
-
/* @__PURE__ */
|
|
9401
|
-
return jsx(AutoStartGate, {
|
|
9402
|
-
...props,
|
|
9403
|
-
fallback: fallback
|
|
9404
|
-
});
|
|
9405
|
-
}
|
|
9406
|
-
return props.renderDefault(props);
|
|
9407
|
-
}
|
|
9668
|
+
preview: WorkflowStagePreview,
|
|
9669
|
+
input: props => props.id === "root" && isObjectInputProps(props) ? /* @__PURE__ */ jsx(WorkflowRootInput, {
|
|
9670
|
+
...props
|
|
9671
|
+
}) : props.renderDefault(props)
|
|
9408
9672
|
}
|
|
9409
9673
|
},
|
|
9410
9674
|
document: {
|
|
9411
9675
|
badges: (prev, ctx) => {
|
|
9412
|
-
if (!
|
|
9676
|
+
if (!ctx.documentId) return prev;
|
|
9413
9677
|
const docId = ctx.documentId;
|
|
9414
9678
|
return [ makeActiveWorkflowsBadge(docId), makePerspectiveBadge(docId), ...prev ];
|
|
9415
9679
|
},
|
|
9416
|
-
actions:
|
|
9680
|
+
actions: prev => prev.map(Action => {
|
|
9417
9681
|
const guardAction = Action.action ? LOCKABLE_ACTIONS.get(Action.action) : void 0;
|
|
9418
9682
|
return guardAction ? withWorkflowLock(Action, guardAction) : Action;
|
|
9419
|
-
})
|
|
9683
|
+
})
|
|
9420
9684
|
}
|
|
9421
9685
|
}));
|
|
9422
9686
|
|
|
9423
|
-
function
|
|
9424
|
-
const {
|
|
9425
|
-
return props.renderDefault({
|
|
9687
|
+
function WorkflowRootInput(props) {
|
|
9688
|
+
const {mappings: mappings} = useWorkflowContext(), docTypeMappings = mappingsForDocType(mappings, props.schemaType.name), fallback = docTypeMappings.length > 0 ? /* @__PURE__ */ jsx(WorkflowFormStrip, {
|
|
9426
9689
|
...props,
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
extraLive: extraLive
|
|
9430
|
-
}) : props.status
|
|
9431
|
-
});
|
|
9432
|
-
}
|
|
9433
|
-
|
|
9434
|
-
function StagePill({entry: entry, extraLive: extraLive}) {
|
|
9690
|
+
mappings: docTypeMappings
|
|
9691
|
+
}) : props.renderDefault(props);
|
|
9435
9692
|
/* @__PURE__ */
|
|
9436
|
-
return
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
children: [
|
|
9440
|
-
/* @__PURE__ */ jsx(LeadBadge, {
|
|
9441
|
-
entry: entry
|
|
9442
|
-
}), extraLive > 0 ? /* @__PURE__ */ jsxs(Badge, {
|
|
9443
|
-
fontSize: 1,
|
|
9444
|
-
mode: "outline",
|
|
9445
|
-
tone: "default",
|
|
9446
|
-
children: [ "+", extraLive ]
|
|
9447
|
-
}) : null ]
|
|
9448
|
-
});
|
|
9449
|
-
}
|
|
9450
|
-
|
|
9451
|
-
function LeadBadge({entry: entry}) {
|
|
9452
|
-
const {instance: instance, evaluation: evaluation} = entry;
|
|
9453
|
-
if (isUnprimed(instance)) /* @__PURE__ */ return jsx(StartIncompleteBadge, {});
|
|
9454
|
-
const stage = evaluation?.currentStage?.stage, title = stage?.title ?? stageTitle(definitionSnapshotOf(instance), instance.currentStage), state = terminalState(instance), isTerminal = (stage ? isTerminalStage(stage) : !1) || state !== "in-flight";
|
|
9455
|
-
/* @__PURE__ */
|
|
9456
|
-
return jsxs(Badge, {
|
|
9457
|
-
fontSize: 1,
|
|
9458
|
-
mode: isTerminal ? "default" : "outline",
|
|
9459
|
-
tone: pillTone({
|
|
9460
|
-
state: state,
|
|
9461
|
-
isTerminal: isTerminal,
|
|
9462
|
-
stageKnown: stage !== void 0
|
|
9463
|
-
}),
|
|
9464
|
-
children: [ title, state === "completed" ? " ✓" : "" ]
|
|
9693
|
+
return jsx(AutoStartGate, {
|
|
9694
|
+
...props,
|
|
9695
|
+
fallback: fallback
|
|
9465
9696
|
});
|
|
9466
9697
|
}
|
|
9467
9698
|
|
|
9468
|
-
|
|
9469
|
-
return args.state === "aborted" ? "critical" : args.isTerminal ? "positive" : args.stageKnown ? "primary" : "default";
|
|
9470
|
-
}
|
|
9471
|
-
|
|
9472
|
-
export { AbortedBadge, ActivitiesList, ActivityDetailDialog, ActivityRow, BreadcrumbTail, CollapsibleBand, DismissablePopover, DocPreviewLink, DocRefFace, GroupHeading, HoverHint, InvalidDocNotice, LinkChip, LoadingRow, StageChip, StageFace, StaleLock, TabSwitch, TodoItemsList, TrailingHairline, UnreadableDocsNote, WorkflowStagePreview, activityRowProps, assigneeUserIdsOf, committedRowFace, dateControlKind, dateControlValue, definitionSnapshotOf, describeError, editTargetOf, findActivity, findActivityNode, formatDate, gdrLocality, instanceBreadcrumb, instanceNotice, instanceTitle, isActivityAssignedTo, isEvaluationStale, isOpenActivityStatus, mappingForDocType, openActivityGone, parseDateFieldValue, parseStoredDateValue, readDeployedDefinitions, rowAssignControlState, rowDateControlState, serializeDateFieldValue, stageTitle, stateByActivity, stopRowClick, stopRowMouseDown, useAssignmentIdentity, useDefinition, useProjectMembers, useSaveField, useUserDisplays, useWorkflowContext, useWorkflowInstanceEntry, workflowDefaultDocumentNode, workflowDocTypes, workflowStudioPlugin, workflowsTabCodec, workflowsView };
|
|
9699
|
+
export { AbortedBadge, ActivitiesList, ActivityDetailDialog, ActivityRow, BreadcrumbTail, CollapsibleBand, DismissablePopover, DocPreviewLink, DocRefFace, GroupHeading, HoverHint, InvalidDocNotice, LinkChip, LoadingRow, SpinnerSlot, StageChip, StageFace, StaleLock, TabSwitch, TodoItemsList, TrailingHairline, UnreadableDocsNote, activityRowProps, assigneeUserIdsOf, committedRowFace, dateControlKind, dateControlValue, definitionSnapshotOf, describeError, editTargetOf, findActivity, findActivityNode, formatDate, gdrLocality, instanceBreadcrumb, instanceNotice, instanceTitle, isActivityAssignedTo, isEvaluationStale, isOpenActivityStatus, openActivityGone, parseDateFieldValue, parseStoredDateValue, readDeployedDefinitions, rowAssignControlState, rowDateControlState, serializeDateFieldValue, stageTitle, stateByActivity, stopRowClick, stopRowMouseDown, useAssignmentIdentity, useDefinition, useProjectMembers, useSaveField, useUserDisplays, useWorkflowContext, useWorkflowInstanceEntry, workflowDefaultDocumentNode, workflowStudioPlugin, workflowsTabCodec, workflowsView };
|