@sanity/workflow-studio-plugin 0.5.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +232 -0
- package/README.md +45 -63
- package/dist/_chunks-cjs/index.cjs +1046 -502
- package/dist/_chunks-cjs/workflows-tool-root.cjs +551 -59
- package/dist/_chunks-es/index.js +1064 -522
- package/dist/_chunks-es/workflows-tool-root.js +556 -62
- package/dist/index.cjs +0 -6
- package/dist/index.d.cts +16 -74
- package/dist/index.d.ts +16 -74
- package/dist/index.js +2 -2
- package/package.json +16 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var jsxRuntime = require("react/jsx-runtime"), Timeline = require("@sanity/icons/Timeline"), ui = require("@sanity/ui"), workflowReact = require("@sanity/workflow-react"), react = require("react"), structure = require("sanity/structure"), workflowEngine = require("@sanity/workflow-engine"), Checkmark = require("@sanity/icons/Checkmark"), Close = require("@sanity/icons/Close"), formatDistanceToNow = require("date-fns/formatDistanceToNow"), workflowComponents = require("@sanity/workflow-components"), csm = require("@sanity/client/csm"), telemetry = require("@sanity/telemetry"), workflowStudio = require("@sanity/workflow-studio"), sanity = require("sanity"), Calendar = require("@sanity/icons/Calendar"), User = require("@sanity/icons/User"), Search = require("@sanity/icons/Search"), ChevronRight = require("@sanity/icons/ChevronRight"), Edit = require("@sanity/icons/Edit"), content = require("@sanity/util/content"), InfoOutline = require("@sanity/icons/InfoOutline"), Document = require("@sanity/icons/Document"), WarningOutline = require("@sanity/icons/WarningOutline"), router = require("sanity/router"), types = require("@sanity/types"), Launch = require("@sanity/icons/Launch"), Empty$1 = require("@sanity/icons/Empty"), ErrorFilled = require("@sanity/icons/ErrorFilled"), RemoveCircle = require("@sanity/icons/RemoveCircle"), Add = require("@sanity/icons/Add"), Bolt = require("@sanity/icons/Bolt"), ChevronDown = require("@sanity/icons/ChevronDown"), CheckmarkCircle = require("@sanity/icons/CheckmarkCircle"), Ulist = require("@sanity/icons/Ulist"), pluralize = require("pluralize-esm"), EllipsisHorizontal = require("@sanity/icons/EllipsisHorizontal"), ArrowUp = require("@sanity/icons/ArrowUp"), rxjs = require("rxjs"), operators = require("rxjs/operators"), Transfer = require("@sanity/icons/Transfer");
|
|
4
4
|
|
|
5
5
|
function _interopDefaultCompat(e) {
|
|
6
6
|
return e && typeof e == "object" && "default" in e ? e : {
|
|
@@ -23,20 +23,58 @@ function gdrLocality(id, contentResource) {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function
|
|
27
|
-
|
|
26
|
+
function assertUniqueWorkflowMappings(mappings) {
|
|
27
|
+
const keys = /* @__PURE__ */ new Set;
|
|
28
|
+
for (const mapping of mappings) {
|
|
29
|
+
const key = mappingKey(mapping);
|
|
30
|
+
if (keys.has(key)) throw new Error(`Duplicate workflow mapping for ${key}`);
|
|
31
|
+
keys.add(key);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function discoverWorkflowMappings(args) {
|
|
36
|
+
assertUniqueWorkflowMappings(args.overrides ?? []);
|
|
37
|
+
const discovered = workflowEngine.latestDeployedDefinitions(args.definitions).flatMap(definition => {
|
|
38
|
+
if (!workflowEngine.isStartableDefinition(definition)) return [];
|
|
39
|
+
const subject = (definition.fields ?? []).find(workflowEngine.isSubjectEntry);
|
|
40
|
+
if (subject === void 0 || !workflowEngine.isInputSourced(subject)) return [];
|
|
41
|
+
const source = {
|
|
42
|
+
fields: [ ...definition.fields ?? [] ]
|
|
43
|
+
};
|
|
44
|
+
return [ ...args.schemaContentTypes ].filter(docType => workflowEngine.acceptsDocumentType(source, docType)).map(docType => ({
|
|
45
|
+
docType: docType,
|
|
46
|
+
definition: definition.name,
|
|
47
|
+
label: definition.title ?? definition.name
|
|
48
|
+
}));
|
|
49
|
+
}), byKey = new Map(discovered.map(mapping => [ mappingKey(mapping), mapping ]));
|
|
50
|
+
for (const override of args.overrides ?? []) {
|
|
51
|
+
const key = mappingKey(override);
|
|
52
|
+
byKey.set(key, override);
|
|
53
|
+
}
|
|
54
|
+
return [ ...byKey.values() ];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function mappingAutoStartMap(mappings) {
|
|
58
|
+
const byType = /* @__PURE__ */ Object.create(null);
|
|
59
|
+
for (const mapping of mappings) {
|
|
60
|
+
if (!mapping.autoStart) continue;
|
|
61
|
+
const definitions = byType[mapping.docType] ?? [];
|
|
62
|
+
byType[mapping.docType] = [ ...definitions, mapping.definition ];
|
|
63
|
+
}
|
|
64
|
+
return byType;
|
|
28
65
|
}
|
|
29
66
|
|
|
30
|
-
function
|
|
31
|
-
return
|
|
67
|
+
function mappingsForDocType(mappings, docType) {
|
|
68
|
+
return mappings.filter(m => m.docType === docType);
|
|
32
69
|
}
|
|
33
70
|
|
|
34
71
|
function mappingKey(mapping) {
|
|
35
72
|
return `${mapping.docType}::${mapping.definition}`;
|
|
36
73
|
}
|
|
37
74
|
|
|
38
|
-
function
|
|
39
|
-
|
|
75
|
+
function documentSubjectEntry(definition) {
|
|
76
|
+
const fields = definition.fields ?? [];
|
|
77
|
+
return fields.find(workflowEngine.isSubjectEntry) ?? fields.find(entry => entry.type === "doc.ref" && entry.name === "subject");
|
|
40
78
|
}
|
|
41
79
|
|
|
42
80
|
function mappingStartBlocks(args) {
|
|
@@ -357,7 +395,7 @@ function stateByActivity(instance) {
|
|
|
357
395
|
}
|
|
358
396
|
|
|
359
397
|
function evaluationFreshness(args) {
|
|
360
|
-
return args.evaluation ? args.committed.lastChangedAt > args.evaluation.instance.lastChangedAt ? "stale" : "current" : "pending";
|
|
398
|
+
return args.evaluation ? Date.parse(args.committed.lastChangedAt) > Date.parse(args.evaluation.instance.lastChangedAt) ? "stale" : "current" : "pending";
|
|
361
399
|
}
|
|
362
400
|
|
|
363
401
|
function isEvaluationCurrent(args) {
|
|
@@ -383,50 +421,6 @@ function isLiveEntry(entry) {
|
|
|
383
421
|
return workflowEngine.terminalState(entry.instance) === "in-flight";
|
|
384
422
|
}
|
|
385
423
|
|
|
386
|
-
const WORKFLOW_API_VERSION = workflowEngine.ENGINE_API_VERSION, WORKFLOW_SYSTEM_TYPES = [ workflowEngine.WORKFLOW_INSTANCE_TYPE, workflowEngine.WORKFLOW_DEFINITION_TYPE, workflowEngine.GUARD_DOC_TYPE ];
|
|
387
|
-
|
|
388
|
-
function editTargetOf(field) {
|
|
389
|
-
return {
|
|
390
|
-
scope: field.scope,
|
|
391
|
-
field: field.name,
|
|
392
|
-
...field.activity ? {
|
|
393
|
-
activity: field.activity
|
|
394
|
-
} : {}
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
const EMPTY_ENTRIES = [], WorkflowContext = react.createContext(null);
|
|
399
|
-
|
|
400
|
-
function useWorkflowContext() {
|
|
401
|
-
const value = react.useContext(WorkflowContext);
|
|
402
|
-
if (!value) throw new Error("useWorkflowContext must render inside the workflow plugin provider");
|
|
403
|
-
return value;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function useWorkflowsForDocument(rawId) {
|
|
407
|
-
const {register: register, unregister: unregister, entries: entries} = useWorkflowContext(), docId = rawId ? csm.getPublishedId(rawId) : void 0;
|
|
408
|
-
react.useEffect(() => {
|
|
409
|
-
if (docId) return register(docId), () => unregister(docId);
|
|
410
|
-
}, [ docId, register, unregister ]);
|
|
411
|
-
const list = react.useSyncExternalStore(entries.subscribe, react.useCallback(() => docId ? entries.getDocument(docId) : EMPTY_ENTRIES, [ entries, docId ]));
|
|
412
|
-
return {
|
|
413
|
-
docId: docId,
|
|
414
|
-
entries: list
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
function useHeldWorkflowEntry(instanceId) {
|
|
419
|
-
const {entries: entries} = useWorkflowContext();
|
|
420
|
-
return react.useSyncExternalStore(entries.subscribe, react.useCallback(() => instanceId ? entries.getInstance(instanceId) : void 0, [ entries, instanceId ]));
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
function useWorkflowInstanceEntry(instanceId) {
|
|
424
|
-
const {requestInstance: requestInstance, releaseInstance: releaseInstance} = useWorkflowContext();
|
|
425
|
-
return react.useEffect(() => {
|
|
426
|
-
if (instanceId) return requestInstance(instanceId), () => releaseInstance(instanceId);
|
|
427
|
-
}, [ instanceId, requestInstance, releaseInstance ]), useHeldWorkflowEntry(instanceId);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
424
|
const isTodoDone = item => item.status === "done", toggledTodoStatus = item => isTodoDone(item) ? "open" : "done";
|
|
431
425
|
|
|
432
426
|
function isTodoOverdue(item, today = /* @__PURE__ */ new Date) {
|
|
@@ -502,7 +496,7 @@ function buildTickIndex(evaluation) {
|
|
|
502
496
|
function todoFieldEditability(args) {
|
|
503
497
|
const {evaluation: evaluation, source: source, fieldName: fieldName} = args, match = evaluation?.editableFields.find(f => f.name === fieldName && f.scope === source.scope && (source.scope !== "activity" || f.activity === source.activityName));
|
|
504
498
|
return match ? match.editable ? {
|
|
505
|
-
editTarget:
|
|
499
|
+
editTarget: workflowReact.editFieldTarget(match)
|
|
506
500
|
} : match.disabledReason === void 0 ? {} : {
|
|
507
501
|
editDisabledReason: match.disabledReason
|
|
508
502
|
} : {};
|
|
@@ -567,8 +561,8 @@ function assigneeMatches(member, who) {
|
|
|
567
561
|
return member.type === "user" ? member.id === who.userId : who.roles.includes(member.role);
|
|
568
562
|
}
|
|
569
563
|
|
|
570
|
-
function
|
|
571
|
-
return
|
|
564
|
+
function changedAssignee(current, next) {
|
|
565
|
+
return next.find(item => !current.some(existing => workflowComponents.sameAssignee(item, existing))) ?? current.find(item => !next.some(existing => workflowComponents.sameAssignee(item, existing)));
|
|
572
566
|
}
|
|
573
567
|
|
|
574
568
|
function isAssigneeShape(value) {
|
|
@@ -697,13 +691,29 @@ function concludesHere(actionEval, activityName) {
|
|
|
697
691
|
return changesOwnStatus(actionEval.action, activityName) || actionEval.firing?.exitsStage === !0;
|
|
698
692
|
}
|
|
699
693
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
tone: "
|
|
694
|
+
const SEMANTIC_FACE = {
|
|
695
|
+
"decision.accept": {
|
|
696
|
+
tone: "positive",
|
|
697
|
+
icon: Checkmark.CheckmarkIcon
|
|
698
|
+
},
|
|
699
|
+
"decision.decline": {
|
|
700
|
+
tone: "caution",
|
|
701
|
+
icon: Close.CloseIcon
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
function actionButtonFace(args) {
|
|
706
|
+
const mode = concludesHere(args.actionEval, args.activityName) ? "default" : "ghost";
|
|
707
|
+
if (actionAdvanceStatus(args.actionEval.action, args.activityName) === "failed") return {
|
|
708
|
+
mode: mode,
|
|
709
|
+
tone: "critical",
|
|
710
|
+
icon: void 0
|
|
711
|
+
};
|
|
712
|
+
const [semantic] = args.actionEval.semantics ?? [], face = semantic === void 0 ? void 0 : SEMANTIC_FACE[semantic];
|
|
713
|
+
return {
|
|
714
|
+
mode: mode,
|
|
715
|
+
tone: face?.tone ?? "default",
|
|
716
|
+
icon: face?.icon
|
|
707
717
|
};
|
|
708
718
|
}
|
|
709
719
|
|
|
@@ -927,6 +937,112 @@ function deriveActivityDetail(args) {
|
|
|
927
937
|
};
|
|
928
938
|
}
|
|
929
939
|
|
|
940
|
+
const WORKFLOW_API_VERSION = workflowEngine.ENGINE_API_VERSION, WORKFLOW_SYSTEM_TYPES = [ workflowEngine.WORKFLOW_INSTANCE_TYPE, workflowEngine.WORKFLOW_DEFINITION_TYPE, workflowEngine.GUARD_DOC_TYPE ], EMPTY_ENTRIES = [], WorkflowContext = react.createContext(null);
|
|
941
|
+
|
|
942
|
+
function useWorkflowContext() {
|
|
943
|
+
const value = react.useContext(WorkflowContext);
|
|
944
|
+
if (!value) throw new Error("useWorkflowContext must render inside the workflow plugin provider");
|
|
945
|
+
return value;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
function useWorkflowsForDocument(rawId) {
|
|
949
|
+
return useDocumentWorkflowEntries(rawId, !0);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
function useCommittedWorkflowsForDocument(rawId) {
|
|
953
|
+
return useDocumentWorkflowEntries(rawId, !1);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
function useDocumentWorkflowEntries(rawId, evaluate) {
|
|
957
|
+
const {register: register, unregister: unregister, requestEvaluation: requestEvaluation, releaseEvaluation: releaseEvaluation, entries: entries} = useWorkflowContext(), docId = rawId ? csm.getPublishedId(rawId) : void 0;
|
|
958
|
+
react.useEffect(() => {
|
|
959
|
+
if (docId) return register(docId), () => unregister(docId);
|
|
960
|
+
}, [ docId, register, unregister ]);
|
|
961
|
+
const list = react.useSyncExternalStore(entries.subscribe, react.useCallback(() => docId ? entries.getDocument(docId) : EMPTY_ENTRIES, [ entries, docId ])), evaluationKey = evaluate ? list.map(entry => entry.instance._id).join("\0") : "";
|
|
962
|
+
return react.useEffect(() => {
|
|
963
|
+
if (!evaluate) return;
|
|
964
|
+
const ids = evaluationKey === "" ? [] : evaluationKey.split("\0");
|
|
965
|
+
for (const id of ids) requestEvaluation(id);
|
|
966
|
+
return () => {
|
|
967
|
+
for (const id of ids) releaseEvaluation(id);
|
|
968
|
+
};
|
|
969
|
+
}, [ evaluate, evaluationKey, requestEvaluation, releaseEvaluation ]), {
|
|
970
|
+
docId: docId,
|
|
971
|
+
entries: list
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
function useHeldWorkflowEntry(instanceId) {
|
|
976
|
+
const {entries: entries} = useWorkflowContext();
|
|
977
|
+
return react.useSyncExternalStore(entries.subscribe, react.useCallback(() => instanceId ? entries.getInstance(instanceId) : void 0, [ entries, instanceId ]));
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
function useWorkflowInstanceEntry(instanceId, options = {}) {
|
|
981
|
+
const {requestInstance: requestInstance, releaseInstance: releaseInstance, requestEvaluation: requestEvaluation, releaseEvaluation: releaseEvaluation} = useWorkflowContext(), evaluate = options.evaluate ?? !0;
|
|
982
|
+
return react.useEffect(() => {
|
|
983
|
+
if (instanceId) return requestInstance(instanceId), () => releaseInstance(instanceId);
|
|
984
|
+
}, [ instanceId, requestInstance, releaseInstance ]), react.useEffect(() => {
|
|
985
|
+
if (!(!instanceId || !evaluate)) return requestEvaluation(instanceId), () => releaseEvaluation(instanceId);
|
|
986
|
+
}, [ instanceId, evaluate, requestEvaluation, releaseEvaluation ]), useHeldWorkflowEntry(instanceId);
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
const WorkflowToolOpened = telemetry.defineEvent({
|
|
990
|
+
name: "Editorial Workflows Studio Plugin Tool Opened",
|
|
991
|
+
version: 1,
|
|
992
|
+
description: "The Workflows tool was opened or its tab was switched"
|
|
993
|
+
}), WorkflowDocumentViewOpened = telemetry.defineEvent({
|
|
994
|
+
name: "Editorial Workflows Studio Plugin Document View Opened",
|
|
995
|
+
version: 1,
|
|
996
|
+
description: "The Workflows document view was opened or its tab was switched"
|
|
997
|
+
}), WorkflowInstanceDetailViewed = telemetry.defineEvent({
|
|
998
|
+
name: "Editorial Workflows Studio Plugin Instance Detail Viewed",
|
|
999
|
+
version: 1,
|
|
1000
|
+
description: "The Workflows tool's per-instance detail view was opened"
|
|
1001
|
+
}), WorkflowFormStripClicked = telemetry.defineEvent({
|
|
1002
|
+
name: "Editorial Workflows Studio Plugin Form Strip Clicked",
|
|
1003
|
+
version: 1,
|
|
1004
|
+
description: "The form strip's instance line was clicked, opening the document view"
|
|
1005
|
+
}), WorkflowStartDialogOpened = telemetry.defineEvent({
|
|
1006
|
+
name: "Editorial Workflows Studio Plugin Start Dialog Opened",
|
|
1007
|
+
version: 1,
|
|
1008
|
+
description: "The start-workflow dialog was opened"
|
|
1009
|
+
}), WorkflowStartDialogSubmitted = telemetry.defineEvent({
|
|
1010
|
+
name: "Editorial Workflows Studio Plugin Start Dialog Submitted",
|
|
1011
|
+
version: 1,
|
|
1012
|
+
description: "The start-workflow dialog's confirm was pressed"
|
|
1013
|
+
}), WorkflowAutoStartRan = telemetry.defineEvent({
|
|
1014
|
+
name: "Editorial Workflows Studio Plugin Auto Start Ran",
|
|
1015
|
+
version: 1,
|
|
1016
|
+
description: "A fresh document's auto-start ran — one start request per configured workflow"
|
|
1017
|
+
}), WorkflowActionControlUsed = telemetry.defineEvent({
|
|
1018
|
+
name: "Editorial Workflows Studio Plugin Action Control Used",
|
|
1019
|
+
version: 1,
|
|
1020
|
+
description: "An action-firing control was used, attributed to its UI surface"
|
|
1021
|
+
}), WorkflowActivityDialogOpened = telemetry.defineEvent({
|
|
1022
|
+
name: "Editorial Workflows Studio Plugin Activity Dialog Opened",
|
|
1023
|
+
version: 1,
|
|
1024
|
+
description: "The activity detail dialog was opened"
|
|
1025
|
+
}), WorkflowTaskFiltersApplied = telemetry.defineEvent({
|
|
1026
|
+
name: "Editorial Workflows Studio Plugin Task Filters Applied",
|
|
1027
|
+
version: 1,
|
|
1028
|
+
description: "The tool's task-filter menu closed with a changed selection"
|
|
1029
|
+
}), WorkflowTodoToggled = telemetry.defineEvent({
|
|
1030
|
+
name: "Editorial Workflows Studio Plugin Todo Toggled",
|
|
1031
|
+
version: 1,
|
|
1032
|
+
description: "A todo checkbox was toggled, attributed to its UI surface and write seam"
|
|
1033
|
+
});
|
|
1034
|
+
|
|
1035
|
+
function useLogEventOnMount(event, data) {
|
|
1036
|
+
const telemetry2 = workflowReact.useWorkflowTelemetry(), logged = react.useRef(!1);
|
|
1037
|
+
react.useEffect(() => {
|
|
1038
|
+
logged.current || (logged.current = !0, telemetry2.log(event, data));
|
|
1039
|
+
}, [ telemetry2, event, data ]);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
function LogEventOnMount(props) {
|
|
1043
|
+
return useLogEventOnMount(props.event, props.data), null;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
930
1046
|
function isEmptyValue(value) {
|
|
931
1047
|
return value == null || value === "" || Array.isArray(value) && value.length === 0;
|
|
932
1048
|
}
|
|
@@ -958,10 +1074,23 @@ function personActor(user) {
|
|
|
958
1074
|
};
|
|
959
1075
|
}
|
|
960
1076
|
|
|
1077
|
+
const memberIndexes = /* @__PURE__ */ new WeakMap;
|
|
1078
|
+
|
|
1079
|
+
function memberIndex(members) {
|
|
1080
|
+
const cached = memberIndexes.get(members);
|
|
1081
|
+
if (cached) return cached;
|
|
1082
|
+
const created = new Map(members.map(member => [ member.id, member ]));
|
|
1083
|
+
return memberIndexes.set(members, created), created;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
961
1086
|
const selfUserFor = (id, me) => me != null && me.id === id ? me : void 0;
|
|
962
1087
|
|
|
1088
|
+
function globalIdOf(users, projectScopedId) {
|
|
1089
|
+
return users.find(user => user.membership.id === projectScopedId)?.profile?.sanityUserId ?? projectScopedId;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
963
1092
|
function userDisplayFor(args) {
|
|
964
|
-
const
|
|
1093
|
+
const matchId = args.matchId ?? args.id, member = memberIndex(args.members).get(matchId), self = selfUserFor(matchId, args.me);
|
|
965
1094
|
return {
|
|
966
1095
|
id: args.id,
|
|
967
1096
|
name: member?.displayName ?? self?.name ?? args.id,
|
|
@@ -970,42 +1099,69 @@ function userDisplayFor(args) {
|
|
|
970
1099
|
}
|
|
971
1100
|
|
|
972
1101
|
function useUserDisplays(ids) {
|
|
973
|
-
const {members: members} = useProjectMembers(),
|
|
974
|
-
|
|
1102
|
+
const {members: members} = useProjectMembers(), {users: users} = workflowStudio.useStudioProjectUsers(), meRaw = sanity.useCurrentUser(), me = react.useMemo(() => meRaw === null ? null : {
|
|
1103
|
+
...meRaw,
|
|
1104
|
+
id: globalIdOf(users, meRaw.id)
|
|
1105
|
+
}, [ meRaw, users ]);
|
|
1106
|
+
return react.useMemo(() => ids.map(id => userDisplayFor({
|
|
975
1107
|
id: id,
|
|
976
1108
|
members: members,
|
|
977
|
-
me: me
|
|
978
|
-
|
|
1109
|
+
me: me,
|
|
1110
|
+
matchId: globalIdOf(users, id)
|
|
1111
|
+
})), [ ids, me, members, users ]);
|
|
979
1112
|
}
|
|
980
1113
|
|
|
981
1114
|
function useUserDisplay(id) {
|
|
982
|
-
const
|
|
1115
|
+
const ids = react.useMemo(() => [ id ], [ id ]), [display] = useUserDisplays(ids);
|
|
983
1116
|
return display ?? {
|
|
984
1117
|
name: id,
|
|
985
1118
|
imageUrl: void 0
|
|
986
1119
|
};
|
|
987
1120
|
}
|
|
988
1121
|
|
|
1122
|
+
const warnedNotMember = /* @__PURE__ */ new Set;
|
|
1123
|
+
|
|
1124
|
+
function useBridgedSelf() {
|
|
1125
|
+
const me = sanity.useCurrentUser(), {users: users, loading: loading} = workflowStudio.useStudioProjectUsers();
|
|
1126
|
+
if (!me || loading) return;
|
|
1127
|
+
const classified = workflowEngine.classifyPrincipalId(me.id), id = users.find(user => user.membership.id === me.id)?.profile?.sanityUserId ?? classified.globalId ?? (classified.namespace === "project" ? void 0 : me.id);
|
|
1128
|
+
if (id === void 0) {
|
|
1129
|
+
warnedNotMember.has(me.id) || (warnedNotMember.add(me.id), console.warn(`workflow: the project member directory cannot resolve the logged-in user ("${me.id}") to an account-global identity — the engine stores account-global user ids only, so workflow assignment and authoring controls stay disabled. Typically this user is not a member of this project.`));
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
return {
|
|
1133
|
+
id: id,
|
|
1134
|
+
roles: me.roles ?? []
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
function useSelfActor() {
|
|
1139
|
+
const self = useBridgedSelf();
|
|
1140
|
+
return self === void 0 ? void 0 : personActor(self);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
989
1143
|
function useAssignmentIdentity() {
|
|
990
|
-
const
|
|
991
|
-
if (
|
|
992
|
-
userId:
|
|
993
|
-
roles:
|
|
1144
|
+
const self = useBridgedSelf();
|
|
1145
|
+
if (self !== void 0) return {
|
|
1146
|
+
userId: self.id,
|
|
1147
|
+
roles: self.roles.map(r => r.name)
|
|
994
1148
|
};
|
|
995
1149
|
}
|
|
996
1150
|
|
|
1151
|
+
const projectMembersByUsers = /* @__PURE__ */ new WeakMap;
|
|
1152
|
+
|
|
997
1153
|
function projectMembersFrom(users) {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
roles: (membership.roles ?? []).map(role => role.name)
|
|
1154
|
+
const cached = projectMembersByUsers.get(users);
|
|
1155
|
+
if (cached) return cached;
|
|
1156
|
+
const members = users.map(({membership: membership, profile: profile}) => workflowComponents.projectMemberRow({
|
|
1157
|
+
membershipId: membership.id,
|
|
1158
|
+
roles: membership.roles,
|
|
1159
|
+
sanityUserId: profile?.sanityUserId,
|
|
1160
|
+
displayName: profile?.displayName,
|
|
1161
|
+
email: profile?.email,
|
|
1162
|
+
imageUrl: profile?.imageUrl ?? void 0
|
|
1008
1163
|
}));
|
|
1164
|
+
return projectMembersByUsers.set(users, members), members;
|
|
1009
1165
|
}
|
|
1010
1166
|
|
|
1011
1167
|
function useProjectMembers() {
|
|
@@ -1331,12 +1487,12 @@ function MemberPicker({selectedIds: selectedIds, onSelect: onSelect, unassignRow
|
|
|
1331
1487
|
});
|
|
1332
1488
|
}
|
|
1333
1489
|
|
|
1334
|
-
function AssigneePicker({value: value,
|
|
1490
|
+
function AssigneePicker({value: value, onChange: onChange}) {
|
|
1335
1491
|
const state = useProjectMembers();
|
|
1336
1492
|
/* @__PURE__ */
|
|
1337
1493
|
return jsxRuntime.jsx(workflowComponents.AssigneePicker, {
|
|
1338
1494
|
...state,
|
|
1339
|
-
|
|
1495
|
+
onChange: onChange,
|
|
1340
1496
|
value: value
|
|
1341
1497
|
});
|
|
1342
1498
|
}
|
|
@@ -1447,7 +1603,7 @@ function DocPicker({value: value, onChange: onChange, types: types2, readOnly: r
|
|
|
1447
1603
|
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1448
1604
|
flex: 1,
|
|
1449
1605
|
children: /* @__PURE__ */ jsxRuntime.jsx(PreviewOrId, {
|
|
1450
|
-
id: workflowEngine.
|
|
1606
|
+
id: workflowEngine.toBareId(value.id),
|
|
1451
1607
|
type: value.type
|
|
1452
1608
|
})
|
|
1453
1609
|
})
|
|
@@ -1543,7 +1699,7 @@ function DocRefsInput({value: value, onChange: onChange, types: types2}) {
|
|
|
1543
1699
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
1544
1700
|
flex: 1,
|
|
1545
1701
|
children: /* @__PURE__ */ jsxRuntime.jsx(PreviewOrId, {
|
|
1546
|
-
id: workflowEngine.
|
|
1702
|
+
id: workflowEngine.toBareId(ref.id),
|
|
1547
1703
|
type: ref.type
|
|
1548
1704
|
})
|
|
1549
1705
|
}),
|
|
@@ -1666,7 +1822,7 @@ function useActionClusterPending() {
|
|
|
1666
1822
|
}
|
|
1667
1823
|
|
|
1668
1824
|
function useFireAction(args) {
|
|
1669
|
-
const {instanceId: instanceId, activity: activity, action: action, label: label} = args, {fireActionFor: fireActionFor} = useWorkflowContext(), toast = useClosableToast(), cluster = useActionClusterLock(), [localPending, setLocalPending] = react.useState(!1), pending = localPending || cluster?.pending === !0;
|
|
1825
|
+
const {instanceId: instanceId, activity: activity, action: action, label: label, surface: surface, viaMenu: viaMenu} = args, {fireActionFor: fireActionFor} = useWorkflowContext(), telemetry2 = workflowReact.useWorkflowTelemetry(), toast = useClosableToast(), cluster = useActionClusterLock(), [localPending, setLocalPending] = react.useState(!1), pending = localPending || cluster?.pending === !0;
|
|
1670
1826
|
return {
|
|
1671
1827
|
fire: react.useCallback(async params => {
|
|
1672
1828
|
if (pending) return !1;
|
|
@@ -1681,6 +1837,11 @@ function useFireAction(args) {
|
|
|
1681
1837
|
}), toast.push({
|
|
1682
1838
|
status: "success",
|
|
1683
1839
|
title: `${label} done`
|
|
1840
|
+
}), telemetry2.log(WorkflowActionControlUsed, {
|
|
1841
|
+
instanceId: instanceId,
|
|
1842
|
+
surface: surface,
|
|
1843
|
+
viaMenu: viaMenu,
|
|
1844
|
+
success: !0
|
|
1684
1845
|
}), !0;
|
|
1685
1846
|
} catch (err) {
|
|
1686
1847
|
return console.error(`[workflow-studio-plugin] firing "${action}" on "${activity}" failed:`, err),
|
|
@@ -1688,15 +1849,29 @@ function useFireAction(args) {
|
|
|
1688
1849
|
status: "error",
|
|
1689
1850
|
title: `${label} failed`,
|
|
1690
1851
|
description: describeError(err)
|
|
1852
|
+
}), telemetry2.log(WorkflowActionControlUsed, {
|
|
1853
|
+
instanceId: instanceId,
|
|
1854
|
+
surface: surface,
|
|
1855
|
+
viaMenu: viaMenu,
|
|
1856
|
+
success: !1
|
|
1691
1857
|
}), !1;
|
|
1692
1858
|
} finally {
|
|
1693
1859
|
setLocalPending(!1), cluster?.onFireChange(!1);
|
|
1694
1860
|
}
|
|
1695
|
-
}, [ fireActionFor, instanceId, activity, action, label, pending, toast, cluster ]),
|
|
1861
|
+
}, [ fireActionFor, instanceId, activity, action, label, pending, toast, cluster, telemetry2, surface, viaMenu ]),
|
|
1696
1862
|
pending: pending
|
|
1697
1863
|
};
|
|
1698
1864
|
}
|
|
1699
1865
|
|
|
1866
|
+
const ACTION_ICON_GAP = 2;
|
|
1867
|
+
|
|
1868
|
+
function actionIconProps(icon) {
|
|
1869
|
+
return icon ? {
|
|
1870
|
+
gap: ACTION_ICON_GAP,
|
|
1871
|
+
icon: icon
|
|
1872
|
+
} : {};
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1700
1875
|
function stopRowMouseDown(e) {
|
|
1701
1876
|
e.preventDefault(), e.stopPropagation();
|
|
1702
1877
|
}
|
|
@@ -1724,18 +1899,21 @@ function RowClickShield({active: active, children: children}) {
|
|
|
1724
1899
|
});
|
|
1725
1900
|
}
|
|
1726
1901
|
|
|
1727
|
-
function FireButton({instanceId: instanceId, activity: activity, action: action, label: label, mode: mode = "default", chrome: chrome, tone: tone = "default"}) {
|
|
1902
|
+
function FireButton({instanceId: instanceId, activity: activity, action: action, label: label, surface: surface, mode: mode = "default", chrome: chrome, tone: tone = "default", icon: icon}) {
|
|
1728
1903
|
const {fire: fire, pending: pending} = useFireAction({
|
|
1729
1904
|
instanceId: instanceId,
|
|
1730
1905
|
activity: activity,
|
|
1731
1906
|
action: action,
|
|
1732
|
-
label: label
|
|
1907
|
+
label: label,
|
|
1908
|
+
surface: surface,
|
|
1909
|
+
viaMenu: !1
|
|
1733
1910
|
}), handleClick = e => {
|
|
1734
1911
|
chrome?.inButtonCard === !0 && e.stopPropagation(), !pending && fire();
|
|
1735
1912
|
};
|
|
1736
1913
|
/* @__PURE__ */
|
|
1737
1914
|
return jsxRuntime.jsx(ui.Button, {
|
|
1738
1915
|
fontSize: 1,
|
|
1916
|
+
...actionIconProps(icon),
|
|
1739
1917
|
loading: pending,
|
|
1740
1918
|
mode: chrome?.mode ?? mode,
|
|
1741
1919
|
onClick: handleClick,
|
|
@@ -1749,31 +1927,39 @@ function FireButton({instanceId: instanceId, activity: activity, action: action,
|
|
|
1749
1927
|
});
|
|
1750
1928
|
}
|
|
1751
1929
|
|
|
1752
|
-
function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
1930
|
+
function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
1753
1931
|
const rowKind = actionRowKind(actionEval);
|
|
1754
1932
|
return rowKind.kind === "disabled" ? /* @__PURE__ */ jsxRuntime.jsx(DisabledActionButton, {
|
|
1755
1933
|
actionEval: actionEval,
|
|
1934
|
+
activity: activity,
|
|
1756
1935
|
chrome: chrome
|
|
1757
1936
|
}) : rowKind.kind === "plain" ? /* @__PURE__ */ jsxRuntime.jsx(PlainActionButton, {
|
|
1758
1937
|
actionEval: actionEval,
|
|
1759
1938
|
instanceId: instanceId,
|
|
1760
1939
|
activity: activity,
|
|
1761
|
-
chrome: chrome
|
|
1940
|
+
chrome: chrome,
|
|
1941
|
+
surface: surface
|
|
1762
1942
|
}) : /* @__PURE__ */ jsxRuntime.jsx(ParamsActionButton, {
|
|
1763
1943
|
actionEval: actionEval,
|
|
1764
1944
|
instanceId: instanceId,
|
|
1765
1945
|
activity: activity,
|
|
1766
|
-
chrome: chrome
|
|
1946
|
+
chrome: chrome,
|
|
1947
|
+
surface: surface
|
|
1767
1948
|
});
|
|
1768
1949
|
}
|
|
1769
1950
|
|
|
1770
|
-
function DisabledActionButton({actionEval: actionEval, chrome: chrome}) {
|
|
1771
|
-
const label = actionTriggerLabel(actionEval),
|
|
1951
|
+
function DisabledActionButton({actionEval: actionEval, activity: activity, chrome: chrome}) {
|
|
1952
|
+
const label = actionTriggerLabel(actionEval), {tone: tone, icon: icon} = actionButtonFace({
|
|
1953
|
+
actionEval: actionEval,
|
|
1954
|
+
activityName: activity
|
|
1955
|
+
}), button = /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
1772
1956
|
fontSize: 1,
|
|
1957
|
+
...actionIconProps(icon),
|
|
1773
1958
|
mode: chrome?.mode ?? "ghost",
|
|
1774
1959
|
onClick: e => e.stopPropagation(),
|
|
1775
1960
|
padding: 2,
|
|
1776
1961
|
text: label,
|
|
1962
|
+
tone: tone,
|
|
1777
1963
|
...spanTriggerProps(chrome),
|
|
1778
1964
|
disabled: !0
|
|
1779
1965
|
});
|
|
@@ -1783,17 +1969,19 @@ function DisabledActionButton({actionEval: actionEval, chrome: chrome}) {
|
|
|
1783
1969
|
}) : button;
|
|
1784
1970
|
}
|
|
1785
1971
|
|
|
1786
|
-
function PlainActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
1787
|
-
const {action: action} = actionEval, label = actionLabel(action), btn =
|
|
1972
|
+
function PlainActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
1973
|
+
const {action: action} = actionEval, label = actionLabel(action), btn = actionButtonFace({
|
|
1788
1974
|
actionEval: actionEval,
|
|
1789
1975
|
activityName: activity
|
|
1790
1976
|
}), button = /* @__PURE__ */ jsxRuntime.jsx(FireButton, {
|
|
1791
1977
|
action: action.name,
|
|
1978
|
+
icon: btn.icon,
|
|
1792
1979
|
instanceId: instanceId,
|
|
1793
1980
|
label: label,
|
|
1794
1981
|
mode: btn.mode,
|
|
1795
1982
|
activity: activity,
|
|
1796
1983
|
chrome: chrome,
|
|
1984
|
+
surface: surface,
|
|
1797
1985
|
tone: btn.tone
|
|
1798
1986
|
});
|
|
1799
1987
|
return action.description ? /* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
@@ -1802,12 +1990,14 @@ function PlainActionButton({actionEval: actionEval, instanceId: instanceId, acti
|
|
|
1802
1990
|
}) : button;
|
|
1803
1991
|
}
|
|
1804
1992
|
|
|
1805
|
-
function ParamsActionDialog({actionEval: actionEval, instanceId: instanceId, activity: activity, onClose: onClose}) {
|
|
1993
|
+
function ParamsActionDialog({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, viaMenu: viaMenu, onClose: onClose}) {
|
|
1806
1994
|
const {action: action} = actionEval, label = actionLabel(action), decls = action.params ?? [], [values, setValues] = react.useState({}), {fire: fire, pending: pending} = useFireAction({
|
|
1807
1995
|
instanceId: instanceId,
|
|
1808
1996
|
activity: activity,
|
|
1809
1997
|
action: action.name,
|
|
1810
|
-
label: label
|
|
1998
|
+
label: label,
|
|
1999
|
+
surface: surface,
|
|
2000
|
+
viaMenu: viaMenu
|
|
1811
2001
|
}), built = buildParams(decls, values), confirm = async () => {
|
|
1812
2002
|
await fire(built.params) && onClose();
|
|
1813
2003
|
};
|
|
@@ -1862,8 +2052,8 @@ function ParamsActionDialog({actionEval: actionEval, instanceId: instanceId, act
|
|
|
1862
2052
|
});
|
|
1863
2053
|
}
|
|
1864
2054
|
|
|
1865
|
-
function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
1866
|
-
const [open, setOpen] = react.useState(!1), btn =
|
|
2055
|
+
function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
2056
|
+
const [open, setOpen] = react.useState(!1), btn = actionButtonFace({
|
|
1867
2057
|
actionEval: actionEval,
|
|
1868
2058
|
activityName: activity
|
|
1869
2059
|
});
|
|
@@ -1872,6 +2062,7 @@ function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, act
|
|
|
1872
2062
|
children: [
|
|
1873
2063
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
1874
2064
|
fontSize: 1,
|
|
2065
|
+
...actionIconProps(btn.icon),
|
|
1875
2066
|
mode: chrome?.mode ?? btn.mode,
|
|
1876
2067
|
onClick: e => {
|
|
1877
2068
|
chrome?.inButtonCard === !0 && e.stopPropagation(), setOpen(!0);
|
|
@@ -1886,7 +2077,9 @@ function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, act
|
|
|
1886
2077
|
actionEval: actionEval,
|
|
1887
2078
|
activity: activity,
|
|
1888
2079
|
instanceId: instanceId,
|
|
1889
|
-
onClose: () => setOpen(!1)
|
|
2080
|
+
onClose: () => setOpen(!1),
|
|
2081
|
+
surface: surface,
|
|
2082
|
+
viaMenu: !1
|
|
1890
2083
|
})
|
|
1891
2084
|
}) : null ]
|
|
1892
2085
|
});
|
|
@@ -2180,27 +2373,10 @@ function useLocalDocRef(gdr) {
|
|
|
2180
2373
|
}
|
|
2181
2374
|
|
|
2182
2375
|
function useActualDocType(bareId) {
|
|
2183
|
-
const
|
|
2184
|
-
apiVersion: WORKFLOW_API_VERSION
|
|
2185
|
-
}), [probe, setProbe] = react.useState();
|
|
2376
|
+
const {actualTypes: actualTypes} = useWorkflowContext();
|
|
2186
2377
|
return react.useEffect(() => {
|
|
2187
|
-
if (
|
|
2188
|
-
|
|
2189
|
-
return client.fetch("*[_id == $id || _id == $draft || _id in path($version)][0]._type", {
|
|
2190
|
-
id: bareId,
|
|
2191
|
-
draft: `drafts.${bareId}`,
|
|
2192
|
-
version: `versions.*.${bareId}`
|
|
2193
|
-
}, {
|
|
2194
|
-
perspective: "raw"
|
|
2195
|
-
}).then(result => {
|
|
2196
|
-
cancelled || setProbe({
|
|
2197
|
-
id: bareId,
|
|
2198
|
-
value: result
|
|
2199
|
-
});
|
|
2200
|
-
}).catch(() => {}), () => {
|
|
2201
|
-
cancelled = !0;
|
|
2202
|
-
};
|
|
2203
|
-
}, [ client, bareId ]), probe !== void 0 && probe.id === bareId ? probe.value : void 0;
|
|
2378
|
+
if (bareId !== null) return actualTypes.track(bareId);
|
|
2379
|
+
}, [ actualTypes, bareId ]), react.useSyncExternalStore(actualTypes.subscribe, react.useCallback(() => bareId === null ? void 0 : actualTypes.read(bareId), [ actualTypes, bareId ]));
|
|
2204
2380
|
}
|
|
2205
2381
|
|
|
2206
2382
|
function useDocLink(gdr) {
|
|
@@ -2697,7 +2873,7 @@ function ReadOnlyDocRefs({entry: entry}) {
|
|
|
2697
2873
|
padding: 2,
|
|
2698
2874
|
radius: 2,
|
|
2699
2875
|
children: /* @__PURE__ */ jsxRuntime.jsx(PreviewOrId, {
|
|
2700
|
-
id: workflowEngine.
|
|
2876
|
+
id: workflowEngine.toBareId(ref.id),
|
|
2701
2877
|
type: ref.type
|
|
2702
2878
|
})
|
|
2703
2879
|
}, ref.id))
|
|
@@ -2780,7 +2956,7 @@ function useFieldDraft(args) {
|
|
|
2780
2956
|
}
|
|
2781
2957
|
|
|
2782
2958
|
function EditableFieldControl({instanceId: instanceId, field: field}) {
|
|
2783
|
-
const {editFieldFor: editFieldFor, previewFieldFor: previewFieldFor, discardFieldPreviewFor: discardFieldPreviewFor} = useWorkflowContext(),
|
|
2959
|
+
const {editFieldFor: editFieldFor, previewFieldFor: previewFieldFor, discardFieldPreviewFor: discardFieldPreviewFor} = useWorkflowContext(), selfActor = useSelfActor(), held = useHeldWorkflowEntry(instanceId), entry = held ? workflowEngine.resolveFieldEntry(held.instance, field) : void 0, evaluation = held?.evaluation, target = workflowReact.editFieldTarget(field), consequence = fieldConsequence(evaluation, field.name), advanceTo = advanceTargetTitle(evaluation, field.name);
|
|
2784
2960
|
/* @__PURE__ */
|
|
2785
2961
|
return jsxRuntime.jsx(EditableField, {
|
|
2786
2962
|
field: field,
|
|
@@ -2816,7 +2992,7 @@ function EditableFieldControl({instanceId: instanceId, field: field}) {
|
|
|
2816
2992
|
mode: "append",
|
|
2817
2993
|
value: noteRow({
|
|
2818
2994
|
body: body,
|
|
2819
|
-
actor:
|
|
2995
|
+
actor: selfActor,
|
|
2820
2996
|
at: /* @__PURE__ */ (new Date).toISOString()
|
|
2821
2997
|
})
|
|
2822
2998
|
}).then(() => {})
|
|
@@ -2929,7 +3105,7 @@ function useAssigneePick(args) {
|
|
|
2929
3105
|
saving: saving,
|
|
2930
3106
|
pick: assignee => {
|
|
2931
3107
|
if (!saving) {
|
|
2932
|
-
if (current && sameAssignee(assignee, current)) {
|
|
3108
|
+
if (current && workflowComponents.sameAssignee(assignee, current)) {
|
|
2933
3109
|
onUnset !== void 0 && save(onUnset);
|
|
2934
3110
|
return;
|
|
2935
3111
|
}
|
|
@@ -2951,7 +3127,10 @@ function AssigneeField({field: field, onSave: onSave, onUnset: onUnset}) {
|
|
|
2951
3127
|
align: "center",
|
|
2952
3128
|
children: /* @__PURE__ */ jsxRuntime.jsx(DismissablePopover, {
|
|
2953
3129
|
content: /* @__PURE__ */ jsxRuntime.jsx(AssigneePicker, {
|
|
2954
|
-
|
|
3130
|
+
onChange: next => {
|
|
3131
|
+
const changed = changedAssignee(cur ? [ cur ] : [], next);
|
|
3132
|
+
changed && pickAndClose(changed);
|
|
3133
|
+
},
|
|
2955
3134
|
value: cur ? [ cur ] : []
|
|
2956
3135
|
}),
|
|
2957
3136
|
onDismiss: () => setOpen(!1),
|
|
@@ -3476,11 +3655,11 @@ function AssignActivityControl({instanceId: instanceId, state: state, assigneeId
|
|
|
3476
3655
|
setBusy(!0);
|
|
3477
3656
|
try {
|
|
3478
3657
|
selectedIds.has(memberId) ? await editFieldFor(instanceId, {
|
|
3479
|
-
target:
|
|
3658
|
+
target: workflowReact.editFieldTarget(field),
|
|
3480
3659
|
mode: "set",
|
|
3481
3660
|
value: members.filter(m => !(m.type === "user" && m.id === memberId))
|
|
3482
3661
|
}) : await editFieldFor(instanceId, {
|
|
3483
|
-
target:
|
|
3662
|
+
target: workflowReact.editFieldTarget(field),
|
|
3484
3663
|
mode: "append",
|
|
3485
3664
|
value: {
|
|
3486
3665
|
type: "user",
|
|
@@ -3909,8 +4088,8 @@ function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle,
|
|
|
3909
4088
|
});
|
|
3910
4089
|
}
|
|
3911
4090
|
|
|
3912
|
-
function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter}) {
|
|
3913
|
-
const {instance: instance} = entry, definition = useDefinition(entry), {editFieldFor: editFieldFor, fireActionFor: fireActionFor} = useWorkflowContext(), toast = useClosableToast(), [busy, setBusy] = react.useState(!1), derivation = deriveTodoItems(entry), rows = derivation.rows.filter(row => rowMatches(row, filter)), appendTarget = appendTargetFor(derivation.appendTargets, filter), run = async op => {
|
|
4091
|
+
function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter, surface: surface}) {
|
|
4092
|
+
const {instance: instance} = entry, definition = useDefinition(entry), {editFieldFor: editFieldFor, fireActionFor: fireActionFor} = useWorkflowContext(), telemetry2 = workflowReact.useWorkflowTelemetry(), toast = useClosableToast(), [busy, setBusy] = react.useState(!1), derivation = deriveTodoItems(entry), rows = derivation.rows.filter(row => rowMatches(row, filter)), appendTarget = appendTargetFor(derivation.appendTargets, filter), run = async op => {
|
|
3914
4093
|
if (busy) return !1;
|
|
3915
4094
|
setBusy(!0);
|
|
3916
4095
|
try {
|
|
@@ -3935,15 +4114,35 @@ function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter}) {
|
|
|
3935
4114
|
mode: "set",
|
|
3936
4115
|
value: next
|
|
3937
4116
|
}));
|
|
3938
|
-
}, toggleRow = row => {
|
|
3939
|
-
if (
|
|
3940
|
-
|
|
3941
|
-
|
|
4117
|
+
}, toggleRow = async row => {
|
|
4118
|
+
if (busy) return;
|
|
4119
|
+
if (row.editTarget) {
|
|
4120
|
+
const done = !isTodoDone(row.item), success = await patchItem(row, {
|
|
4121
|
+
status: toggledTodoStatus(row.item)
|
|
4122
|
+
}) === !0;
|
|
4123
|
+
telemetry2.log(WorkflowTodoToggled, {
|
|
4124
|
+
instanceId: instance._id,
|
|
4125
|
+
surface: surface,
|
|
4126
|
+
via: "field-edit",
|
|
4127
|
+
done: done,
|
|
4128
|
+
success: success
|
|
4129
|
+
});
|
|
4130
|
+
return;
|
|
4131
|
+
}
|
|
3942
4132
|
const tick = row.tick;
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
4133
|
+
if (tick && tick.actionEval.allowed && !isTodoDone(row.item)) {
|
|
4134
|
+
const success = await run(() => fireActionFor(instance._id, {
|
|
4135
|
+
activity: tick.activity,
|
|
4136
|
+
action: tick.actionEval.action.name
|
|
4137
|
+
}));
|
|
4138
|
+
telemetry2.log(WorkflowTodoToggled, {
|
|
4139
|
+
instanceId: instance._id,
|
|
4140
|
+
surface: surface,
|
|
4141
|
+
via: "action",
|
|
4142
|
+
done: !0,
|
|
4143
|
+
success: success
|
|
4144
|
+
});
|
|
4145
|
+
}
|
|
3947
4146
|
}, addItem = label => appendTarget ? run(() => editFieldFor(instance._id, {
|
|
3948
4147
|
target: appendTarget,
|
|
3949
4148
|
mode: "append",
|
|
@@ -4060,26 +4259,39 @@ const ACTIONS_MENU_TRIGGER = {
|
|
|
4060
4259
|
padding: 2
|
|
4061
4260
|
};
|
|
4062
4261
|
|
|
4063
|
-
function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activity: activity, onCollectParams: onCollectParams}) {
|
|
4064
|
-
const rowKind = actionRowKind(actionEval), label = actionTriggerLabel(actionEval), {
|
|
4262
|
+
function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, onCollectParams: onCollectParams}) {
|
|
4263
|
+
const rowKind = actionRowKind(actionEval), label = actionTriggerLabel(actionEval), {tone: tone, icon: icon} = actionButtonFace({
|
|
4264
|
+
actionEval: actionEval,
|
|
4265
|
+
activityName: activity
|
|
4266
|
+
}), iconProp = icon ? {
|
|
4267
|
+
icon: icon
|
|
4268
|
+
} : {}, {fire: fire, pending: pending} = useFireAction({
|
|
4065
4269
|
instanceId: instanceId,
|
|
4066
4270
|
activity: activity,
|
|
4067
4271
|
action: actionEval.action.name,
|
|
4068
|
-
label: label
|
|
4272
|
+
label: label,
|
|
4273
|
+
surface: surface,
|
|
4274
|
+
viaMenu: !0
|
|
4069
4275
|
});
|
|
4070
4276
|
return rowKind.kind === "disabled" ? /* @__PURE__ */ jsxRuntime.jsx(ui.MenuItem, {
|
|
4071
4277
|
disabled: !0,
|
|
4072
|
-
|
|
4278
|
+
...iconProp,
|
|
4279
|
+
text: label,
|
|
4280
|
+
tone: tone
|
|
4073
4281
|
}) : rowKind.kind === "plain" ? /* @__PURE__ */ jsxRuntime.jsx(ui.MenuItem, {
|
|
4074
4282
|
disabled: pending,
|
|
4283
|
+
...iconProp,
|
|
4075
4284
|
onClick: () => {
|
|
4076
4285
|
fire();
|
|
4077
4286
|
},
|
|
4078
|
-
text: label
|
|
4287
|
+
text: label,
|
|
4288
|
+
tone: tone
|
|
4079
4289
|
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.MenuItem, {
|
|
4080
4290
|
disabled: pending,
|
|
4291
|
+
...iconProp,
|
|
4081
4292
|
onClick: onCollectParams,
|
|
4082
|
-
text: label
|
|
4293
|
+
text: label,
|
|
4294
|
+
tone: tone
|
|
4083
4295
|
});
|
|
4084
4296
|
}
|
|
4085
4297
|
|
|
@@ -4095,7 +4307,7 @@ function rowShield(menuButton) {
|
|
|
4095
4307
|
});
|
|
4096
4308
|
}
|
|
4097
4309
|
|
|
4098
|
-
function ActionsMenuButton({actions: actions, instanceId: instanceId, activity: activity, label: label, mode: mode = "ghost", inButtonCard: inButtonCard = !1}) {
|
|
4310
|
+
function ActionsMenuButton({actions: actions, instanceId: instanceId, activity: activity, label: label, surface: surface, mode: mode = "ghost", inButtonCard: inButtonCard = !1}) {
|
|
4099
4311
|
const [paramsAction, setParamsAction] = react.useState(void 0), clusterPending = useActionClusterPending(), menuId = react.useId(), menuButton = /* @__PURE__ */ jsxRuntime.jsx(ui.MenuButton, {
|
|
4100
4312
|
button: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
4101
4313
|
...ACTIONS_MENU_TRIGGER,
|
|
@@ -4114,7 +4326,8 @@ function ActionsMenuButton({actions: actions, instanceId: instanceId, activity:
|
|
|
4114
4326
|
actionEval: a,
|
|
4115
4327
|
activity: activity,
|
|
4116
4328
|
instanceId: instanceId,
|
|
4117
|
-
onCollectParams: () => setParamsAction(a)
|
|
4329
|
+
onCollectParams: () => setParamsAction(a),
|
|
4330
|
+
surface: surface
|
|
4118
4331
|
}, a.action.name))
|
|
4119
4332
|
}),
|
|
4120
4333
|
popover: {
|
|
@@ -4130,7 +4343,9 @@ function ActionsMenuButton({actions: actions, instanceId: instanceId, activity:
|
|
|
4130
4343
|
actionEval: paramsAction,
|
|
4131
4344
|
activity: activity,
|
|
4132
4345
|
instanceId: instanceId,
|
|
4133
|
-
onClose: () => setParamsAction(void 0)
|
|
4346
|
+
onClose: () => setParamsAction(void 0),
|
|
4347
|
+
surface: surface,
|
|
4348
|
+
viaMenu: !0
|
|
4134
4349
|
})
|
|
4135
4350
|
}) : null ]
|
|
4136
4351
|
});
|
|
@@ -4146,7 +4361,8 @@ function TerminalFooter({actions: actions, activity: activity, instanceId: insta
|
|
|
4146
4361
|
children: /* @__PURE__ */ jsxRuntime.jsx(ActivityActionRow, {
|
|
4147
4362
|
actionEval: only,
|
|
4148
4363
|
activity: activity,
|
|
4149
|
-
instanceId: instanceId
|
|
4364
|
+
instanceId: instanceId,
|
|
4365
|
+
surface: "terminal-footer"
|
|
4150
4366
|
})
|
|
4151
4367
|
}) : /* @__PURE__ */ jsxRuntime.jsx(FittedActions, {
|
|
4152
4368
|
actions: actions,
|
|
@@ -4192,6 +4408,7 @@ function FittedActions({actions: actions, activity: activity, instanceId: instan
|
|
|
4192
4408
|
children: [
|
|
4193
4409
|
/* @__PURE__ */ jsxRuntime.jsx(MeasureRow, {
|
|
4194
4410
|
actions: actions,
|
|
4411
|
+
activity: activity,
|
|
4195
4412
|
onElement: setMeasureEl
|
|
4196
4413
|
}),
|
|
4197
4414
|
/* @__PURE__ */ jsxRuntime.jsxs(FooterRow, {
|
|
@@ -4199,19 +4416,21 @@ function FittedActions({actions: actions, activity: activity, instanceId: instan
|
|
|
4199
4416
|
children: [ inline === void 0 ? null : actions.slice(0, inline).map(a => /* @__PURE__ */ jsxRuntime.jsx(ActivityActionRow, {
|
|
4200
4417
|
actionEval: a,
|
|
4201
4418
|
activity: activity,
|
|
4202
|
-
instanceId: instanceId
|
|
4419
|
+
instanceId: instanceId,
|
|
4420
|
+
surface: "terminal-footer"
|
|
4203
4421
|
}, a.action.name)), overflow.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ActionsMenuButton, {
|
|
4204
4422
|
actions: overflow,
|
|
4205
4423
|
activity: activity,
|
|
4206
4424
|
instanceId: instanceId,
|
|
4207
4425
|
label: MORE_ACTIONS_LABEL,
|
|
4208
|
-
mode: "default"
|
|
4426
|
+
mode: "default",
|
|
4427
|
+
surface: "terminal-footer"
|
|
4209
4428
|
}) : null ]
|
|
4210
4429
|
}) ]
|
|
4211
4430
|
});
|
|
4212
4431
|
}
|
|
4213
4432
|
|
|
4214
|
-
function MeasureRow({actions: actions, onElement: onElement}) {
|
|
4433
|
+
function MeasureRow({actions: actions, activity: activity, onElement: onElement}) {
|
|
4215
4434
|
/* @__PURE__ */
|
|
4216
4435
|
return jsxRuntime.jsx("div", {
|
|
4217
4436
|
"aria-hidden": !0,
|
|
@@ -4225,12 +4444,20 @@ function MeasureRow({actions: actions, onElement: onElement}) {
|
|
|
4225
4444
|
display: "inline-flex",
|
|
4226
4445
|
whiteSpace: "nowrap"
|
|
4227
4446
|
},
|
|
4228
|
-
children: [ actions.map(a =>
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4447
|
+
children: [ actions.map(a => {
|
|
4448
|
+
const {icon: icon} = actionButtonFace({
|
|
4449
|
+
actionEval: a,
|
|
4450
|
+
activityName: activity
|
|
4451
|
+
});
|
|
4452
|
+
/* @__PURE__ */
|
|
4453
|
+
return jsxRuntime.jsx(ui.Button, {
|
|
4454
|
+
as: "span",
|
|
4455
|
+
fontSize: 1,
|
|
4456
|
+
...actionIconProps(icon),
|
|
4457
|
+
padding: 2,
|
|
4458
|
+
text: actionTriggerLabel(a)
|
|
4459
|
+
}, a.action.name);
|
|
4460
|
+
}),
|
|
4234
4461
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
4235
4462
|
...ACTIONS_MENU_TRIGGER,
|
|
4236
4463
|
as: "span",
|
|
@@ -4240,7 +4467,7 @@ function MeasureRow({actions: actions, onElement: onElement}) {
|
|
|
4240
4467
|
});
|
|
4241
4468
|
}
|
|
4242
4469
|
|
|
4243
|
-
function ActivityDetailDialog({entry: entry, activityName: activityName, breadcrumb: breadcrumb, definition: definition, document: document, onClose: onClose}) {
|
|
4470
|
+
function ActivityDetailDialog({entry: entry, activityName: activityName, breadcrumb: breadcrumb, definition: definition, document: document, source: source, onClose: onClose}) {
|
|
4244
4471
|
const detail = deriveActivityDetail({
|
|
4245
4472
|
entry: entry,
|
|
4246
4473
|
activityName: activityName
|
|
@@ -4262,6 +4489,13 @@ function ActivityDetailDialog({entry: entry, activityName: activityName, breadcr
|
|
|
4262
4489
|
onClose: onClose,
|
|
4263
4490
|
width: 1,
|
|
4264
4491
|
children: [
|
|
4492
|
+
/* @__PURE__ */ jsxRuntime.jsx(LogEventOnMount, {
|
|
4493
|
+
data: {
|
|
4494
|
+
instanceId: instanceId,
|
|
4495
|
+
source: source
|
|
4496
|
+
},
|
|
4497
|
+
event: WorkflowActivityDialogOpened
|
|
4498
|
+
}),
|
|
4265
4499
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
4266
4500
|
borderBottom: hasBody,
|
|
4267
4501
|
style: {
|
|
@@ -4369,7 +4603,8 @@ function TopActions({detail: detail, definition: definition, instanceId: instanc
|
|
|
4369
4603
|
children: [ p.actions.map(a => /* @__PURE__ */ jsxRuntime.jsx(ActivityActionRow, {
|
|
4370
4604
|
actionEval: a,
|
|
4371
4605
|
activity: activityName,
|
|
4372
|
-
instanceId: instanceId
|
|
4606
|
+
instanceId: instanceId,
|
|
4607
|
+
surface: "dialog-strip"
|
|
4373
4608
|
}, a.action.name)), p.manualTarget ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
4374
4609
|
as: "a",
|
|
4375
4610
|
fontSize: 1,
|
|
@@ -4405,7 +4640,8 @@ function FieldRow({field: field, detail: detail, entry: entry, activityName: act
|
|
|
4405
4640
|
scope: "activity",
|
|
4406
4641
|
field: field.name,
|
|
4407
4642
|
activity: activityName
|
|
4408
|
-
}
|
|
4643
|
+
},
|
|
4644
|
+
surface: "activity-dialog"
|
|
4409
4645
|
}) ]
|
|
4410
4646
|
});
|
|
4411
4647
|
if (field._type === "assignees") {
|
|
@@ -4512,7 +4748,26 @@ function CountedLabel({count: count, label: label}) {
|
|
|
4512
4748
|
});
|
|
4513
4749
|
}
|
|
4514
4750
|
|
|
4515
|
-
function
|
|
4751
|
+
function SpinnerSlot({busy: busy, size: size}) {
|
|
4752
|
+
/* @__PURE__ */
|
|
4753
|
+
return jsxRuntime.jsx(ui.Flex, {
|
|
4754
|
+
align: "center",
|
|
4755
|
+
flex: "none",
|
|
4756
|
+
justify: "center",
|
|
4757
|
+
style: {
|
|
4758
|
+
width: 19,
|
|
4759
|
+
height: 19
|
|
4760
|
+
},
|
|
4761
|
+
children: busy ? /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {
|
|
4762
|
+
muted: !0,
|
|
4763
|
+
...size !== void 0 ? {
|
|
4764
|
+
size: size
|
|
4765
|
+
} : {}
|
|
4766
|
+
}) : null
|
|
4767
|
+
});
|
|
4768
|
+
}
|
|
4769
|
+
|
|
4770
|
+
function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
4516
4771
|
/* @__PURE__ */
|
|
4517
4772
|
return jsxRuntime.jsxs(ui.Flex, {
|
|
4518
4773
|
align: "center",
|
|
@@ -4527,6 +4782,9 @@ function GroupHeading({count: count, title: title, end: end}) {
|
|
|
4527
4782
|
weight: "semibold",
|
|
4528
4783
|
children: title
|
|
4529
4784
|
})
|
|
4785
|
+
}), busy === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(SpinnerSlot, {
|
|
4786
|
+
busy: busy,
|
|
4787
|
+
size: 1
|
|
4530
4788
|
}), end === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
4531
4789
|
children: [
|
|
4532
4790
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
@@ -4536,29 +4794,7 @@ function GroupHeading({count: count, title: title, end: end}) {
|
|
|
4536
4794
|
});
|
|
4537
4795
|
}
|
|
4538
4796
|
|
|
4539
|
-
function
|
|
4540
|
-
const toast = useClosableToast();
|
|
4541
|
-
/* @__PURE__ */
|
|
4542
|
-
return jsxRuntime.jsx(ui.Button, {
|
|
4543
|
-
fontSize: 1,
|
|
4544
|
-
mode: "ghost",
|
|
4545
|
-
onClick: () => {
|
|
4546
|
-
navigator.clipboard.writeText(unreadableDocsReport(unreadable)).then(() => toast.push({
|
|
4547
|
-
status: "success",
|
|
4548
|
-
title: "Details copied"
|
|
4549
|
-
}), () => toast.push({
|
|
4550
|
-
status: "error",
|
|
4551
|
-
title: "Could not copy the details"
|
|
4552
|
-
}));
|
|
4553
|
-
},
|
|
4554
|
-
padding: 2,
|
|
4555
|
-
text: "Copy details"
|
|
4556
|
-
});
|
|
4557
|
-
}
|
|
4558
|
-
|
|
4559
|
-
function UnreadableDocsNote({unreadable: unreadable}) {
|
|
4560
|
-
if (unreadable.length === 0) return null;
|
|
4561
|
-
const label = unreadable.length === 1 ? "1 workflow document isn’t listed — this Studio can’t read it. Share the details with your Studio maintainers." : `${unreadable.length} workflow documents aren’t listed — this Studio can’t read them. Share the details with your Studio maintainers.`;
|
|
4797
|
+
function CautionNote({action: action, label: label}) {
|
|
4562
4798
|
/* @__PURE__ */
|
|
4563
4799
|
return jsxRuntime.jsxs(ui.Card, {
|
|
4564
4800
|
padding: 2,
|
|
@@ -4585,10 +4821,39 @@ function UnreadableDocsNote({unreadable: unreadable}) {
|
|
|
4585
4821
|
size: 1,
|
|
4586
4822
|
children: label
|
|
4587
4823
|
}) ]
|
|
4588
|
-
}),
|
|
4589
|
-
|
|
4824
|
+
}), action ]
|
|
4825
|
+
});
|
|
4826
|
+
}
|
|
4827
|
+
|
|
4828
|
+
function CopyDetailsButton({unreadable: unreadable}) {
|
|
4829
|
+
const toast = useClosableToast();
|
|
4830
|
+
/* @__PURE__ */
|
|
4831
|
+
return jsxRuntime.jsx(ui.Button, {
|
|
4832
|
+
fontSize: 1,
|
|
4833
|
+
mode: "ghost",
|
|
4834
|
+
onClick: () => {
|
|
4835
|
+
navigator.clipboard.writeText(unreadableDocsReport(unreadable)).then(() => toast.push({
|
|
4836
|
+
status: "success",
|
|
4837
|
+
title: "Details copied"
|
|
4838
|
+
}), () => toast.push({
|
|
4839
|
+
status: "error",
|
|
4840
|
+
title: "Could not copy the details"
|
|
4841
|
+
}));
|
|
4842
|
+
},
|
|
4843
|
+
padding: 2,
|
|
4844
|
+
text: "Copy details"
|
|
4845
|
+
});
|
|
4846
|
+
}
|
|
4847
|
+
|
|
4848
|
+
function UnreadableDocsNote({unreadable: unreadable}) {
|
|
4849
|
+
if (unreadable.length === 0) return null;
|
|
4850
|
+
const label = unreadable.length === 1 ? "1 workflow document isn’t listed — this Studio can’t read it. Share the details with your Studio maintainers." : `${unreadable.length} workflow documents aren’t listed — this Studio can’t read them. Share the details with your Studio maintainers.`;
|
|
4851
|
+
/* @__PURE__ */
|
|
4852
|
+
return jsxRuntime.jsx(CautionNote, {
|
|
4853
|
+
action: /* @__PURE__ */ jsxRuntime.jsx(CopyDetailsButton, {
|
|
4590
4854
|
unreadable: unreadable
|
|
4591
|
-
})
|
|
4855
|
+
}),
|
|
4856
|
+
label: label
|
|
4592
4857
|
});
|
|
4593
4858
|
}
|
|
4594
4859
|
|
|
@@ -4649,6 +4914,18 @@ function TabSwitch({ariaControls: ariaControls, idPrefix: idPrefix, options: opt
|
|
|
4649
4914
|
});
|
|
4650
4915
|
}
|
|
4651
4916
|
|
|
4917
|
+
function useDelayedFlag(active, delayMs) {
|
|
4918
|
+
const [held, setHeld] = react.useState(!1);
|
|
4919
|
+
return react.useEffect(() => {
|
|
4920
|
+
if (!active) {
|
|
4921
|
+
setHeld(!1);
|
|
4922
|
+
return;
|
|
4923
|
+
}
|
|
4924
|
+
const timer = setTimeout(() => setHeld(!0), delayMs);
|
|
4925
|
+
return () => clearTimeout(timer);
|
|
4926
|
+
}, [ active, delayMs ]), held && active;
|
|
4927
|
+
}
|
|
4928
|
+
|
|
4652
4929
|
function instanceTitle(instance, definition) {
|
|
4653
4930
|
return definition?.title ?? instance.definition;
|
|
4654
4931
|
}
|
|
@@ -4898,10 +5175,29 @@ function buildStartRequest(args) {
|
|
|
4898
5175
|
};
|
|
4899
5176
|
}
|
|
4900
5177
|
|
|
4901
|
-
function
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
5178
|
+
function sharedPreflightDataset(engine, tag) {
|
|
5179
|
+
let pending;
|
|
5180
|
+
return () => {
|
|
5181
|
+
if (pending !== void 0) return pending;
|
|
5182
|
+
const {query: query, params: params} = workflowEngine.instancesQuery({
|
|
5183
|
+
tag: tag,
|
|
5184
|
+
filter: {
|
|
5185
|
+
includeCompleted: !0
|
|
5186
|
+
}
|
|
5187
|
+
});
|
|
5188
|
+
return pending = engine.query({
|
|
5189
|
+
groq: query,
|
|
5190
|
+
params: params
|
|
5191
|
+
}).then(rows => rows.map(workflowEngine.assertReadableModel).map(workflowEngine.projectStartSliceRow)).finally(() => {
|
|
5192
|
+
pending = void 0;
|
|
5193
|
+
}), pending;
|
|
5194
|
+
};
|
|
5195
|
+
}
|
|
5196
|
+
|
|
5197
|
+
function findResumeEntry(args) {
|
|
5198
|
+
return args.entries.find(e => workflowEngine.isUnprimed(e.instance) && e.instance.definition === args.definitionName && (args.heldInstanceId === void 0 || e.instance._id === args.heldInstanceId));
|
|
5199
|
+
}
|
|
5200
|
+
|
|
4905
5201
|
function presentedResumeEntry(args) {
|
|
4906
5202
|
if (args.attempt !== void 0) return args.attempt.resume;
|
|
4907
5203
|
if (!args.startNew) return findResumeEntry(args);
|
|
@@ -4913,7 +5209,8 @@ function classifyStartError(err) {
|
|
|
4913
5209
|
instance: err.instance,
|
|
4914
5210
|
description: describeError(err.cause)
|
|
4915
5211
|
} : err instanceof workflowEngine.StartNotAllowedError ? {
|
|
4916
|
-
kind: "not-allowed"
|
|
5212
|
+
kind: "not-allowed",
|
|
5213
|
+
description: err.unmetRequirements.map(requirementCopy).join("; ")
|
|
4917
5214
|
} : {
|
|
4918
5215
|
kind: "failed",
|
|
4919
5216
|
description: describeError(err)
|
|
@@ -4926,22 +5223,30 @@ function boundReleaseId(mapping, selectedReleaseId) {
|
|
|
4926
5223
|
|
|
4927
5224
|
function startGate(args) {
|
|
4928
5225
|
const {mapping: mapping, mappingIssue: mappingIssue, selectedReleaseId: selectedReleaseId, releaseActive: releaseActive} = args;
|
|
4929
|
-
|
|
5226
|
+
if (mappingIssue !== void 0) return {
|
|
4930
5227
|
blocked: !0,
|
|
4931
5228
|
tooltip: mappingIssue
|
|
4932
|
-
}
|
|
5229
|
+
};
|
|
5230
|
+
if (mapping.perspectiveField?.required === !0 && selectedReleaseId === void 0) return {
|
|
4933
5231
|
blocked: !0,
|
|
4934
5232
|
tooltip: "Pick a release in the perspective dropdown first"
|
|
4935
|
-
}
|
|
5233
|
+
};
|
|
5234
|
+
if (mapping.perspectiveField !== void 0 && selectedReleaseId !== void 0 && !releaseActive) return {
|
|
4936
5235
|
blocked: !0,
|
|
4937
5236
|
tooltip: `Release "${selectedReleaseId}" is not active — only active releases can host new workflows`
|
|
4938
|
-
}
|
|
5237
|
+
};
|
|
5238
|
+
if (args.startFilterFailed === !0) return {
|
|
4939
5239
|
blocked: !0,
|
|
4940
5240
|
tooltip: `${mapping.label} can't start for this document right now — the workflow's start condition isn't met`
|
|
4941
|
-
}
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
5241
|
+
};
|
|
5242
|
+
if (args.unmetRequirement !== void 0) {
|
|
5243
|
+
const requirement = args.unmetRequirement;
|
|
5244
|
+
return {
|
|
5245
|
+
blocked: !0,
|
|
5246
|
+
tooltip: requirementCopy(requirement)
|
|
5247
|
+
};
|
|
5248
|
+
}
|
|
5249
|
+
return {
|
|
4945
5250
|
blocked: !1,
|
|
4946
5251
|
tooltip: void 0
|
|
4947
5252
|
};
|
|
@@ -4964,10 +5269,10 @@ async function preflightFilter(args) {
|
|
|
4964
5269
|
});
|
|
4965
5270
|
}
|
|
4966
5271
|
|
|
4967
|
-
async function
|
|
4968
|
-
const {
|
|
4969
|
-
return workflowEngine.
|
|
4970
|
-
|
|
5272
|
+
async function preflightGroqRequirement(args) {
|
|
5273
|
+
const {query: query, mapping: mapping, fields: fields, scope: scope} = args;
|
|
5274
|
+
return workflowEngine.unboundRequirementReads(query, fields).length > 0 ? !1 : (await workflowEngine.explainStartRequirement({
|
|
5275
|
+
query: query,
|
|
4971
5276
|
definition: {
|
|
4972
5277
|
name: mapping.definition
|
|
4973
5278
|
},
|
|
@@ -4976,6 +5281,25 @@ async function preflightAllowed(args) {
|
|
|
4976
5281
|
})).outcome === "unsatisfied";
|
|
4977
5282
|
}
|
|
4978
5283
|
|
|
5284
|
+
async function preflightSingleSubjectRequirement(args) {
|
|
5285
|
+
const {mapping: mapping, start: start, declaredFields: declaredFields, fields: fields, scope: scope} = args;
|
|
5286
|
+
return workflowEngine.singleSubjectRequirementRefused({
|
|
5287
|
+
definition: {
|
|
5288
|
+
name: mapping.definition,
|
|
5289
|
+
...declaredFields !== void 0 ? {
|
|
5290
|
+
fields: [ ...declaredFields ]
|
|
5291
|
+
} : {},
|
|
5292
|
+
start: start
|
|
5293
|
+
},
|
|
5294
|
+
fields: fields,
|
|
5295
|
+
scope: scope
|
|
5296
|
+
});
|
|
5297
|
+
}
|
|
5298
|
+
|
|
5299
|
+
function requirementCopy(requirement) {
|
|
5300
|
+
return requirement.description ?? requirement.title ?? workflowEngine.humanize(requirement.name);
|
|
5301
|
+
}
|
|
5302
|
+
|
|
4979
5303
|
async function performStart(args) {
|
|
4980
5304
|
const {mapping: mapping, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId} = args, releaseId = boundReleaseId(mapping, selectedReleaseId);
|
|
4981
5305
|
try {
|
|
@@ -5002,7 +5326,21 @@ async function performStart(args) {
|
|
|
5002
5326
|
}
|
|
5003
5327
|
|
|
5004
5328
|
function useStartVerdicts(args) {
|
|
5005
|
-
const {mapping: mapping, start: start, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId} = args, skip = args.hidden || args.resumable
|
|
5329
|
+
const {mapping: mapping, start: start, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId, entries: entries} = args, {engine: engine, binding: binding} = useWorkflowContext(), fetchDataset = react.useMemo(() => sharedPreflightDataset(engine, binding.tag), [ engine, binding.tag ]), skip = args.hidden || args.resumable, groqRequirements = react.useMemo(() => start?.requirements?.filter(requirement => requirement.type === "groq") ?? [], [ start?.requirements ]), refusedGroq = useGroqRequirementVerdicts({
|
|
5330
|
+
mapping: mapping,
|
|
5331
|
+
requirements: groqRequirements,
|
|
5332
|
+
docId: docId,
|
|
5333
|
+
selectedReleaseId: selectedReleaseId,
|
|
5334
|
+
skip: skip,
|
|
5335
|
+
fetchDataset: fetchDataset
|
|
5336
|
+
}), singleSubjectRefused = useSingleSubjectVerdict({
|
|
5337
|
+
mapping: mapping,
|
|
5338
|
+
start: start,
|
|
5339
|
+
docId: docId,
|
|
5340
|
+
selectedReleaseId: selectedReleaseId,
|
|
5341
|
+
entries: entries,
|
|
5342
|
+
skip: skip
|
|
5343
|
+
}), unmetRequirement = start?.requirements?.find(requirement => requirement.type === "singleSubject" ? singleSubjectRefused : refusedGroq.includes(requirement.name));
|
|
5006
5344
|
return {
|
|
5007
5345
|
filterFailed: useFilterVerdict({
|
|
5008
5346
|
mapping: mapping,
|
|
@@ -5010,25 +5348,15 @@ function useStartVerdicts(args) {
|
|
|
5010
5348
|
docId: docId,
|
|
5011
5349
|
initialValue: initialValue,
|
|
5012
5350
|
selectedReleaseId: selectedReleaseId,
|
|
5013
|
-
skip: skip
|
|
5351
|
+
skip: skip,
|
|
5352
|
+
fetchDataset: fetchDataset
|
|
5014
5353
|
}),
|
|
5015
|
-
|
|
5016
|
-
mapping: mapping,
|
|
5017
|
-
allowed: start?.allowed,
|
|
5018
|
-
docId: docId,
|
|
5019
|
-
selectedReleaseId: selectedReleaseId,
|
|
5020
|
-
skip: skip
|
|
5021
|
-
})
|
|
5354
|
+
unmetRequirement: unmetRequirement
|
|
5022
5355
|
};
|
|
5023
5356
|
}
|
|
5024
5357
|
|
|
5025
5358
|
function preflightScope(args) {
|
|
5026
|
-
const {
|
|
5027
|
-
tag: tag,
|
|
5028
|
-
filter: {
|
|
5029
|
-
includeCompleted: !0
|
|
5030
|
-
}
|
|
5031
|
-
});
|
|
5359
|
+
const {tag: tag, mapping: mapping, contentResource: contentResource, docId: docId, fetchDataset: fetchDataset} = args;
|
|
5032
5360
|
return {
|
|
5033
5361
|
tag: tag,
|
|
5034
5362
|
now: /* @__PURE__ */ (new Date).toISOString(),
|
|
@@ -5037,15 +5365,12 @@ function preflightScope(args) {
|
|
|
5037
5365
|
contentResource: contentResource,
|
|
5038
5366
|
documentId: docId
|
|
5039
5367
|
}).id,
|
|
5040
|
-
fetchDataset:
|
|
5041
|
-
groq: query,
|
|
5042
|
-
params: params
|
|
5043
|
-
})).map(workflowEngine.assertReadableModel)
|
|
5368
|
+
fetchDataset: fetchDataset
|
|
5044
5369
|
};
|
|
5045
5370
|
}
|
|
5046
5371
|
|
|
5047
5372
|
function useFilterVerdict(args) {
|
|
5048
|
-
const {mapping: mapping, filter: filter, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId, skip: skip} = args, {
|
|
5373
|
+
const {mapping: mapping, filter: filter, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId, skip: skip, fetchDataset: fetchDataset} = args, {binding: binding} = useWorkflowContext(), [failed, setFailed] = react.useState(!1), rootRead = filter !== void 0 && workflowEngine.readsRootDocument(filter), candidateValue = rootRead ? initialValue : null;
|
|
5049
5374
|
return react.useEffect(() => {
|
|
5050
5375
|
if (skip || filter === void 0 || docId === void 0) {
|
|
5051
5376
|
setFailed(!1);
|
|
@@ -5059,57 +5384,112 @@ function useFilterVerdict(args) {
|
|
|
5059
5384
|
candidateValue: candidateValue,
|
|
5060
5385
|
selectedReleaseId: selectedReleaseId,
|
|
5061
5386
|
scope: preflightScope({
|
|
5062
|
-
engine: engine,
|
|
5063
5387
|
tag: binding.tag,
|
|
5064
5388
|
mapping: mapping,
|
|
5065
5389
|
contentResource: binding.contentResource,
|
|
5066
|
-
docId: docId
|
|
5390
|
+
docId: docId,
|
|
5391
|
+
fetchDataset: fetchDataset
|
|
5067
5392
|
})
|
|
5068
5393
|
}).catch(showRowOnError("start.filter", mapping)).then(verdict => {
|
|
5069
5394
|
cancelled || setFailed(verdict);
|
|
5070
5395
|
}), () => {
|
|
5071
5396
|
cancelled = !0;
|
|
5072
5397
|
};
|
|
5073
|
-
}, [ filter, rootRead, skip, docId, selectedReleaseId, candidateValue, mapping,
|
|
5398
|
+
}, [ filter, rootRead, skip, docId, selectedReleaseId, candidateValue, mapping, binding, fetchDataset ]),
|
|
5074
5399
|
failed;
|
|
5075
5400
|
}
|
|
5076
5401
|
|
|
5077
|
-
function
|
|
5078
|
-
const
|
|
5402
|
+
function preflightSeedFields(args) {
|
|
5403
|
+
const ctx = {
|
|
5404
|
+
mapping: args.mapping,
|
|
5405
|
+
subjectDocId: args.docId,
|
|
5406
|
+
selectedReleaseId: args.selectedReleaseId,
|
|
5407
|
+
contentResource: args.contentResource,
|
|
5408
|
+
declaredFields: args.declaredFields
|
|
5409
|
+
};
|
|
5410
|
+
return Object.fromEntries(buildStartFields({
|
|
5411
|
+
ctx: ctx,
|
|
5412
|
+
initFields: [],
|
|
5413
|
+
values: {}
|
|
5414
|
+
}).map(field => [ field.name, field.value ]));
|
|
5415
|
+
}
|
|
5416
|
+
|
|
5417
|
+
function useGroqRequirementVerdicts(args) {
|
|
5418
|
+
const {mapping: mapping, requirements: requirements, docId: docId, selectedReleaseId: selectedReleaseId, skip: skip, fetchDataset: fetchDataset} = args, {binding: binding, mappingFields: mappingFields} = useWorkflowContext(), [refused, setRefused] = react.useState([]);
|
|
5079
5419
|
return react.useEffect(() => {
|
|
5080
|
-
if (skip ||
|
|
5081
|
-
setRefused(
|
|
5420
|
+
if (skip || requirements.length === 0 || docId === void 0) {
|
|
5421
|
+
setRefused(current => current.length === 0 ? current : []);
|
|
5082
5422
|
return;
|
|
5083
5423
|
}
|
|
5084
5424
|
let cancelled = !1;
|
|
5085
|
-
const
|
|
5425
|
+
const fields = preflightSeedFields({
|
|
5086
5426
|
mapping: mapping,
|
|
5087
|
-
|
|
5427
|
+
docId: docId,
|
|
5088
5428
|
selectedReleaseId: selectedReleaseId,
|
|
5089
5429
|
contentResource: binding.contentResource,
|
|
5090
5430
|
declaredFields: mappingFields.get(mappingKey(mapping))
|
|
5091
|
-
},
|
|
5092
|
-
|
|
5093
|
-
initFields: [],
|
|
5094
|
-
values: {}
|
|
5095
|
-
}).map(field => [ field.name, field.value ]));
|
|
5096
|
-
return preflightAllowed({
|
|
5097
|
-
allowed: allowed,
|
|
5431
|
+
}), scope = preflightScope({
|
|
5432
|
+
tag: binding.tag,
|
|
5098
5433
|
mapping: mapping,
|
|
5099
|
-
|
|
5434
|
+
contentResource: binding.contentResource,
|
|
5435
|
+
docId: docId,
|
|
5436
|
+
fetchDataset: fetchDataset
|
|
5437
|
+
});
|
|
5438
|
+
return Promise.all(requirements.map(async requirement => ({
|
|
5439
|
+
name: requirement.name,
|
|
5440
|
+
refused: await preflightGroqRequirement({
|
|
5441
|
+
query: requirement.query,
|
|
5442
|
+
mapping: mapping,
|
|
5443
|
+
fields: fields,
|
|
5444
|
+
scope: scope
|
|
5445
|
+
}).catch(showRowOnError(`start.requirements.${requirement.name}`, mapping))
|
|
5446
|
+
}))).then(verdicts => {
|
|
5447
|
+
if (!cancelled) {
|
|
5448
|
+
const next = verdicts.filter(verdict => verdict.refused).map(verdict => verdict.name);
|
|
5449
|
+
setRefused(current => current.length === next.length && current.every((name, index) => name === next[index]) ? current : next);
|
|
5450
|
+
}
|
|
5451
|
+
}), () => {
|
|
5452
|
+
cancelled = !0;
|
|
5453
|
+
};
|
|
5454
|
+
}, [ requirements, skip, docId, selectedReleaseId, mapping, binding, mappingFields, fetchDataset ]),
|
|
5455
|
+
refused;
|
|
5456
|
+
}
|
|
5457
|
+
|
|
5458
|
+
function useSingleSubjectVerdict(args) {
|
|
5459
|
+
const {mapping: mapping, start: start, docId: docId, selectedReleaseId: selectedReleaseId, entries: entries, skip: skip} = args, {binding: binding, mappingFields: mappingFields} = useWorkflowContext(), [refused, setRefused] = react.useState(!1), dedupe = start !== void 0 && workflowEngine.hasSingleSubjectRequirement({
|
|
5460
|
+
start: start
|
|
5461
|
+
});
|
|
5462
|
+
return react.useEffect(() => {
|
|
5463
|
+
if (skip || !dedupe || start === void 0 || docId === void 0) {
|
|
5464
|
+
setRefused(!1);
|
|
5465
|
+
return;
|
|
5466
|
+
}
|
|
5467
|
+
let cancelled = !1;
|
|
5468
|
+
const declaredFields = mappingFields.get(mappingKey(mapping));
|
|
5469
|
+
return preflightSingleSubjectRequirement({
|
|
5470
|
+
mapping: mapping,
|
|
5471
|
+
start: start,
|
|
5472
|
+
declaredFields: declaredFields,
|
|
5473
|
+
fields: preflightSeedFields({
|
|
5474
|
+
mapping: mapping,
|
|
5475
|
+
docId: docId,
|
|
5476
|
+
selectedReleaseId: selectedReleaseId,
|
|
5477
|
+
contentResource: binding.contentResource,
|
|
5478
|
+
declaredFields: declaredFields
|
|
5479
|
+
}),
|
|
5100
5480
|
scope: preflightScope({
|
|
5101
|
-
engine: engine,
|
|
5102
5481
|
tag: binding.tag,
|
|
5103
5482
|
mapping: mapping,
|
|
5483
|
+
docId: docId,
|
|
5104
5484
|
contentResource: binding.contentResource,
|
|
5105
|
-
|
|
5485
|
+
fetchDataset: () => Promise.resolve(entries.map(({instance: instance}) => workflowEngine.projectStartSliceRow(instance)))
|
|
5106
5486
|
})
|
|
5107
|
-
}).catch(showRowOnError("
|
|
5487
|
+
}).catch(showRowOnError("singleSubject requirement", mapping)).then(verdict => {
|
|
5108
5488
|
cancelled || setRefused(verdict);
|
|
5109
5489
|
}), () => {
|
|
5110
5490
|
cancelled = !0;
|
|
5111
5491
|
};
|
|
5112
|
-
}, [
|
|
5492
|
+
}, [ dedupe, start, skip, docId, selectedReleaseId, entries, mapping, binding, mappingFields ]),
|
|
5113
5493
|
refused;
|
|
5114
5494
|
}
|
|
5115
5495
|
|
|
@@ -5119,7 +5499,7 @@ function showRowOnError(key, mapping) {
|
|
|
5119
5499
|
}
|
|
5120
5500
|
|
|
5121
5501
|
function useStartWorkflow(args) {
|
|
5122
|
-
const {mapping: mapping, docId: docId, initialValue: initialValue} = args, toast = useClosableToast(), {engine: engine, openStartDialog: openStartDialog, mappingIssues: mappingIssues2, mappingStarts: mappingStarts} = useWorkflowContext(), observer = workflowStudio.useStudioObserver({
|
|
5502
|
+
const {mapping: mapping, docId: docId, initialValue: initialValue, source: source} = args, toast = useClosableToast(), {engine: engine, openStartDialog: openStartDialog, mappingIssues: mappingIssues2, mappingStarts: mappingStarts} = useWorkflowContext(), observer = workflowStudio.useStudioObserver({
|
|
5123
5503
|
engine: engine
|
|
5124
5504
|
}), [starting, setStarting] = react.useState(!1), {selectedReleaseId: selectedReleaseId} = sanity.usePerspective(), releaseActive = sanity.useIsReleaseActive(), startBlock = mappingStarts.get(mappingKey(mapping)), hidden = workflowEngine.startKindOf({
|
|
5125
5505
|
start: startBlock
|
|
@@ -5127,12 +5507,13 @@ function useStartWorkflow(args) {
|
|
|
5127
5507
|
entries: entries,
|
|
5128
5508
|
definitionName: mapping.definition,
|
|
5129
5509
|
heldInstanceId: void 0
|
|
5130
|
-
}) !== void 0, {filterFailed: filterFailed,
|
|
5510
|
+
}) !== void 0, {filterFailed: filterFailed, unmetRequirement: unmetRequirement} = useStartVerdicts({
|
|
5131
5511
|
mapping: mapping,
|
|
5132
5512
|
start: startBlock,
|
|
5133
5513
|
docId: docId,
|
|
5134
5514
|
initialValue: initialValue,
|
|
5135
5515
|
selectedReleaseId: selectedReleaseId,
|
|
5516
|
+
entries: entries,
|
|
5136
5517
|
hidden: hidden,
|
|
5137
5518
|
resumable: resumable
|
|
5138
5519
|
}), {blocked: blocked, tooltip: tooltip} = startGate({
|
|
@@ -5141,7 +5522,9 @@ function useStartWorkflow(args) {
|
|
|
5141
5522
|
selectedReleaseId: selectedReleaseId,
|
|
5142
5523
|
releaseActive: releaseActive,
|
|
5143
5524
|
startFilterFailed: filterFailed,
|
|
5144
|
-
|
|
5525
|
+
...unmetRequirement !== void 0 ? {
|
|
5526
|
+
unmetRequirement: unmetRequirement
|
|
5527
|
+
} : {}
|
|
5145
5528
|
});
|
|
5146
5529
|
return {
|
|
5147
5530
|
blocked: blocked,
|
|
@@ -5163,7 +5546,10 @@ function useStartWorkflow(args) {
|
|
|
5163
5546
|
title: "Could not persist the document before starting",
|
|
5164
5547
|
description: describeError(err)
|
|
5165
5548
|
}),
|
|
5166
|
-
openStartDialog: openStartDialog
|
|
5549
|
+
openStartDialog: request => openStartDialog({
|
|
5550
|
+
...request,
|
|
5551
|
+
source: source
|
|
5552
|
+
})
|
|
5167
5553
|
});
|
|
5168
5554
|
} finally {
|
|
5169
5555
|
setStarting(!1);
|
|
@@ -5173,11 +5559,12 @@ function useStartWorkflow(args) {
|
|
|
5173
5559
|
};
|
|
5174
5560
|
}
|
|
5175
5561
|
|
|
5176
|
-
function StartWorkflowButton({mapping: mapping, docId: docId, initialValue: initialValue, mode: mode = "default", label: label, iconOnly: iconOnly = !1, tone: tone = "primary"}) {
|
|
5562
|
+
function StartWorkflowButton({mapping: mapping, docId: docId, initialValue: initialValue, source: source, mode: mode = "default", label: label, iconOnly: iconOnly = !1, tone: tone = "primary"}) {
|
|
5177
5563
|
const {blocked: blocked, tooltip: tooltip, hidden: hidden, starting: starting, start: start} = useStartWorkflow({
|
|
5178
5564
|
mapping: mapping,
|
|
5179
5565
|
docId: docId,
|
|
5180
|
-
initialValue: initialValue
|
|
5566
|
+
initialValue: initialValue,
|
|
5567
|
+
source: source
|
|
5181
5568
|
});
|
|
5182
5569
|
if (hidden) return null;
|
|
5183
5570
|
const startLabel = label ?? `Start ${mapping.label}`, button = /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
@@ -5210,7 +5597,7 @@ function useStartableMappings(mappings) {
|
|
|
5210
5597
|
}) !== "autonomous");
|
|
5211
5598
|
}
|
|
5212
5599
|
|
|
5213
|
-
function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: initialValue, label: label, iconOnly: iconOnly = !1, mode: mode = "default", tone: tone = "primary"}) {
|
|
5600
|
+
function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: initialValue, source: source, label: label, iconOnly: iconOnly = !1, mode: mode = "default", tone: tone = "primary"}) {
|
|
5214
5601
|
const menuId = react.useId(), startable = useStartableMappings(mappings), [first] = startable;
|
|
5215
5602
|
if (first === void 0) return null;
|
|
5216
5603
|
if (startable.length === 1) /* @__PURE__ */
|
|
@@ -5223,6 +5610,7 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5223
5610
|
},
|
|
5224
5611
|
mapping: first,
|
|
5225
5612
|
mode: mode,
|
|
5613
|
+
source: source,
|
|
5226
5614
|
tone: tone
|
|
5227
5615
|
});
|
|
5228
5616
|
const menuLabel = label ?? "Start a workflow";
|
|
@@ -5248,7 +5636,8 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5248
5636
|
children: startable.map(mapping => /* @__PURE__ */ jsxRuntime.jsx(StartWorkflowMenuItem, {
|
|
5249
5637
|
docId: docId,
|
|
5250
5638
|
initialValue: initialValue,
|
|
5251
|
-
mapping: mapping
|
|
5639
|
+
mapping: mapping,
|
|
5640
|
+
source: source
|
|
5252
5641
|
}, mappingKey(mapping)))
|
|
5253
5642
|
}),
|
|
5254
5643
|
popover: {
|
|
@@ -5259,11 +5648,12 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5259
5648
|
});
|
|
5260
5649
|
}
|
|
5261
5650
|
|
|
5262
|
-
function StartWorkflowMenuItem({mapping: mapping, docId: docId, initialValue: initialValue}) {
|
|
5651
|
+
function StartWorkflowMenuItem({mapping: mapping, docId: docId, initialValue: initialValue, source: source}) {
|
|
5263
5652
|
const {blocked: blocked, tooltip: tooltip, starting: starting, start: start} = useStartWorkflow({
|
|
5264
5653
|
mapping: mapping,
|
|
5265
5654
|
docId: docId,
|
|
5266
|
-
initialValue: initialValue
|
|
5655
|
+
initialValue: initialValue,
|
|
5656
|
+
source: source
|
|
5267
5657
|
}), item = /* @__PURE__ */ jsxRuntime.jsx(ui.MenuItem, {
|
|
5268
5658
|
disabled: blocked || starting || !docId,
|
|
5269
5659
|
onClick: () => {
|
|
@@ -5318,13 +5708,15 @@ function RowTerminalActions({actions: actions, activity: activity, instanceId: i
|
|
|
5318
5708
|
mode: "ghost",
|
|
5319
5709
|
inButtonCard: !0
|
|
5320
5710
|
},
|
|
5321
|
-
instanceId: instanceId
|
|
5711
|
+
instanceId: instanceId,
|
|
5712
|
+
surface: "inline-row"
|
|
5322
5713
|
}) : /* @__PURE__ */ jsxRuntime.jsx(ActionsMenuButton, {
|
|
5323
5714
|
actions: actions,
|
|
5324
5715
|
activity: activity,
|
|
5325
5716
|
inButtonCard: !0,
|
|
5326
5717
|
instanceId: instanceId,
|
|
5327
|
-
label: "Select action"
|
|
5718
|
+
label: "Select action",
|
|
5719
|
+
surface: "inline-row"
|
|
5328
5720
|
})
|
|
5329
5721
|
}) : null;
|
|
5330
5722
|
}
|
|
@@ -5422,7 +5814,8 @@ function ForMeList({entry: entry, work: work, identity: identity, onOpenActivity
|
|
|
5422
5814
|
filter: {
|
|
5423
5815
|
kind: "mine",
|
|
5424
5816
|
identity: identity
|
|
5425
|
-
}
|
|
5817
|
+
},
|
|
5818
|
+
surface: "document-view-for-me"
|
|
5426
5819
|
}) : null ]
|
|
5427
5820
|
})
|
|
5428
5821
|
});
|
|
@@ -5487,9 +5880,16 @@ function instanceNotice(entry) {
|
|
|
5487
5880
|
size: 1,
|
|
5488
5881
|
children: "This workflow didn’t finish starting — use Start workflow to continue it"
|
|
5489
5882
|
})
|
|
5490
|
-
}) : pending ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5491
|
-
|
|
5492
|
-
|
|
5883
|
+
}) : pending ? /* @__PURE__ */ jsxRuntime.jsx(WorkRow, {
|
|
5884
|
+
lead: /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {
|
|
5885
|
+
muted: !0,
|
|
5886
|
+
size: 1
|
|
5887
|
+
}),
|
|
5888
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
5889
|
+
muted: !0,
|
|
5890
|
+
size: 1,
|
|
5891
|
+
children: "Loading…"
|
|
5892
|
+
})
|
|
5493
5893
|
}) : null;
|
|
5494
5894
|
}
|
|
5495
5895
|
|
|
@@ -5624,7 +6024,8 @@ function TodoFieldDialog({entry: entry, scope: scope, field: field, title: title
|
|
|
5624
6024
|
kind: "field",
|
|
5625
6025
|
scope: scope,
|
|
5626
6026
|
field: field
|
|
5627
|
-
}
|
|
6027
|
+
},
|
|
6028
|
+
surface: "todo-field-dialog"
|
|
5628
6029
|
})
|
|
5629
6030
|
})
|
|
5630
6031
|
});
|
|
@@ -5837,7 +6238,7 @@ function PillButton({children: children, pill: pill, hintDisabled: hintDisabled
|
|
|
5837
6238
|
}
|
|
5838
6239
|
|
|
5839
6240
|
function useFieldCommit({entry: entry, editability: editability}) {
|
|
5840
|
-
const {editFieldFor: editFieldFor} = useWorkflowContext(), target =
|
|
6241
|
+
const {editFieldFor: editFieldFor} = useWorkflowContext(), target = workflowReact.editFieldTarget(editability);
|
|
5841
6242
|
return {
|
|
5842
6243
|
set: value => editFieldFor(entry.instance._id, {
|
|
5843
6244
|
target: target,
|
|
@@ -6053,8 +6454,9 @@ function AssigneePill({entry: entry, pill: pill, editability: editability}) {
|
|
|
6053
6454
|
/* @__PURE__ */
|
|
6054
6455
|
return jsxRuntime.jsx(PillPopover, {
|
|
6055
6456
|
content: /* @__PURE__ */ jsxRuntime.jsx(AssigneePicker, {
|
|
6056
|
-
|
|
6057
|
-
|
|
6457
|
+
onChange: next => {
|
|
6458
|
+
const changed = changedAssignee(current ? [ current ] : [], next);
|
|
6459
|
+
changed && (setOpen(!1), pick(changed));
|
|
6058
6460
|
},
|
|
6059
6461
|
value: current ? [ current ] : []
|
|
6060
6462
|
}),
|
|
@@ -6073,10 +6475,8 @@ function AssigneesPill({entry: entry, pill: pill, editability: editability}) {
|
|
|
6073
6475
|
/* @__PURE__ */
|
|
6074
6476
|
return jsxRuntime.jsx(PillPopover, {
|
|
6075
6477
|
content: /* @__PURE__ */ jsxRuntime.jsx(AssigneePicker, {
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
const next = current.some(a => sameAssignee(a, assignee)) ? current.filter(a => !sameAssignee(a, assignee)) : [ ...current, assignee ];
|
|
6079
|
-
save(() => set(next));
|
|
6478
|
+
onChange: next => {
|
|
6479
|
+
saving || save(() => set(next));
|
|
6080
6480
|
},
|
|
6081
6481
|
value: current
|
|
6082
6482
|
}),
|
|
@@ -6181,15 +6581,15 @@ function Hairline({weight: weight, style: style}) {
|
|
|
6181
6581
|
});
|
|
6182
6582
|
}
|
|
6183
6583
|
|
|
6184
|
-
function CollapsibleBand({header: header, children: children, background: background = !1, defaultOpen: defaultOpen = !0, sticky: sticky = !1, title: title}) {
|
|
6185
|
-
const [
|
|
6584
|
+
function CollapsibleBand({header: header, children: children, background: background = !1, defaultOpen: defaultOpen = !0, onToggle: onToggle, open: controlledOpen, sticky: sticky = !1, title: title}) {
|
|
6585
|
+
const [heldOpen, setHeldOpen] = react.useState(defaultOpen), open = controlledOpen ?? heldOpen, toggle = onToggle ?? (() => setHeldOpen(value => !value)), verb = open ? "Collapse" : "Expand";
|
|
6186
6586
|
/* @__PURE__ */
|
|
6187
6587
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
6188
6588
|
gap: 1,
|
|
6189
6589
|
children: [
|
|
6190
6590
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
6191
6591
|
onDoubleClick: event => {
|
|
6192
|
-
event.target instanceof Element && event.target.closest("a, button") ||
|
|
6592
|
+
event.target instanceof Element && event.target.closest("a, button") || toggle();
|
|
6193
6593
|
},
|
|
6194
6594
|
padding: 1,
|
|
6195
6595
|
radius: 3,
|
|
@@ -6210,7 +6610,7 @@ function CollapsibleBand({header: header, children: children, background: backgr
|
|
|
6210
6610
|
fontSize: 1,
|
|
6211
6611
|
icon: open ? ChevronDown.ChevronDownIcon : ChevronRight.ChevronRightIcon,
|
|
6212
6612
|
mode: "bleed",
|
|
6213
|
-
onClick:
|
|
6613
|
+
onClick: toggle,
|
|
6214
6614
|
padding: 2
|
|
6215
6615
|
}), header ]
|
|
6216
6616
|
})
|
|
@@ -6553,20 +6953,7 @@ function InstanceDebugMenu({entry: entry}) {
|
|
|
6553
6953
|
}
|
|
6554
6954
|
|
|
6555
6955
|
function InstanceAccordion({entry: entry, children: children, defaultOpen: defaultOpen}) {
|
|
6556
|
-
const definition = useDefinition(entry), {instance: instance
|
|
6557
|
-
align: "center",
|
|
6558
|
-
gap: 2,
|
|
6559
|
-
style: badgeTrim,
|
|
6560
|
-
children: [
|
|
6561
|
-
/* @__PURE__ */ jsxRuntime.jsx(AbortedBadge, {
|
|
6562
|
-
instance: instance
|
|
6563
|
-
}), settled ? null : /* @__PURE__ */ jsxRuntime.jsx(OlderDefinitionBadge, {
|
|
6564
|
-
instance: instance
|
|
6565
|
-
}), !ready && entry.invalid === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {
|
|
6566
|
-
muted: !0,
|
|
6567
|
-
size: 1
|
|
6568
|
-
}) : null ]
|
|
6569
|
-
});
|
|
6956
|
+
const definition = useDefinition(entry), {instance: instance} = entry, settled = !isLiveEntry(entry), title = instanceTitle(instance, definition), badgeTrim = useBadgeCapTrim();
|
|
6570
6957
|
/* @__PURE__ */
|
|
6571
6958
|
return jsxRuntime.jsx(CollapsibleBand, {
|
|
6572
6959
|
defaultOpen: defaultOpen ?? !settled,
|
|
@@ -6589,7 +6976,18 @@ function InstanceAccordion({entry: entry, children: children, defaultOpen: defau
|
|
|
6589
6976
|
textOverflow: "ellipsis",
|
|
6590
6977
|
weight: "medium",
|
|
6591
6978
|
children: title
|
|
6592
|
-
}),
|
|
6979
|
+
}),
|
|
6980
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
6981
|
+
align: "center",
|
|
6982
|
+
gap: 2,
|
|
6983
|
+
style: badgeTrim,
|
|
6984
|
+
children: [
|
|
6985
|
+
/* @__PURE__ */ jsxRuntime.jsx(AbortedBadge, {
|
|
6986
|
+
instance: instance
|
|
6987
|
+
}), settled ? null : /* @__PURE__ */ jsxRuntime.jsx(OlderDefinitionBadge, {
|
|
6988
|
+
instance: instance
|
|
6989
|
+
}) ]
|
|
6990
|
+
}) ]
|
|
6593
6991
|
}),
|
|
6594
6992
|
/* @__PURE__ */ jsxRuntime.jsx(TrailingHairline, {}),
|
|
6595
6993
|
/* @__PURE__ */ jsxRuntime.jsx(InstanceDebugMenu, {
|
|
@@ -6607,7 +7005,7 @@ function InstanceAccordion({entry: entry, children: children, defaultOpen: defau
|
|
|
6607
7005
|
}
|
|
6608
7006
|
|
|
6609
7007
|
function PartOfBand({instance: instance}) {
|
|
6610
|
-
const parentRef = instance.ancestors.at(-1), parentId = parentRef ? workflowEngine.
|
|
7008
|
+
const parentRef = instance.ancestors.at(-1), parentId = parentRef ? workflowEngine.toBareId(parentRef.id) : null, parentEntry = useWorkflowInstanceEntry(parentId), parentDefinition = useDefinition(parentEntry);
|
|
6611
7009
|
if (!parentId) return null;
|
|
6612
7010
|
const title = parentEntry ? instanceTitle(parentEntry.instance, parentDefinition) : parentId;
|
|
6613
7011
|
/* @__PURE__ */
|
|
@@ -7123,7 +7521,12 @@ function StageSection({entry: entry, onOpenActivity: onOpenActivity}) {
|
|
|
7123
7521
|
}
|
|
7124
7522
|
|
|
7125
7523
|
const VIEW_TAB_CODEC = workflowsTabCodec([ "overview", "for-me" ]), WorkflowsView = props => {
|
|
7126
|
-
const {documentId: documentId, schemaType: schemaType} = props, {isDocResolved: isDocResolved, mappings: mappings, discoveryInvalid: discoveryInvalid} = useWorkflowContext(), {entries: entries} = useWorkflowsForDocument(documentId),
|
|
7524
|
+
const {documentId: documentId, schemaType: schemaType} = props, {isDocResolved: isDocResolved, mappings: mappings, discoveryInvalid: discoveryInvalid} = useWorkflowContext(), {entries: entries} = useWorkflowsForDocument(documentId), {view: view} = useWorkflowsTab();
|
|
7525
|
+
useLogEventOnMount(WorkflowDocumentViewOpened, {
|
|
7526
|
+
tab: view,
|
|
7527
|
+
via: "open"
|
|
7528
|
+
});
|
|
7529
|
+
const resolved = isDocResolved(documentId), docTypeMappings = mappingsForDocType(mappings, schemaType.name);
|
|
7127
7530
|
if (entries.length === 0) return discoveryInvalid !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
7128
7531
|
padding: 4,
|
|
7129
7532
|
children: /* @__PURE__ */ jsxRuntime.jsx(InvalidDocNotice, {
|
|
@@ -7164,11 +7567,9 @@ const VIEW_TAB_CODEC = workflowsTabCodec([ "overview", "for-me" ]), WorkflowsVie
|
|
|
7164
7567
|
};
|
|
7165
7568
|
|
|
7166
7569
|
function DiscoverySpinner() {
|
|
7167
|
-
const
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
return () => clearTimeout(timer);
|
|
7171
|
-
}, []), /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
7570
|
+
const visible = useDelayedFlag(!0, 1e3);
|
|
7571
|
+
/* @__PURE__ */
|
|
7572
|
+
return jsxRuntime.jsx(ui.Flex, {
|
|
7172
7573
|
align: "center",
|
|
7173
7574
|
height: "fill",
|
|
7174
7575
|
justify: "center",
|
|
@@ -7178,7 +7579,7 @@ function DiscoverySpinner() {
|
|
|
7178
7579
|
});
|
|
7179
7580
|
}
|
|
7180
7581
|
|
|
7181
|
-
const GROUP_GAP = 1;
|
|
7582
|
+
const BOOT_CUE_DELAY_MS = 400, GROUP_GAP = 1;
|
|
7182
7583
|
|
|
7183
7584
|
function useWorkflowsTab() {
|
|
7184
7585
|
const {params: params, setParams: setParams} = structure.usePaneRouter();
|
|
@@ -7203,7 +7604,7 @@ function useOpenActivity(entries) {
|
|
|
7203
7604
|
}
|
|
7204
7605
|
|
|
7205
7606
|
function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappings: docTypeMappings, initialValue: initialValue}) {
|
|
7206
|
-
const identity = useAssignmentIdentity(), panelId = react.useId(), {params: params} = structure.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] = react.useState(() => focusedLanding(params?.[WORKFLOWS_FOCUS_PARAM], entries.map(e => e.instance._id))), assignedWorkUnknown = active.some(e => e.invalid !== void 0), sectionFor = e => /* @__PURE__ */ jsxRuntime.jsx(WorkflowInstanceSection, {
|
|
7607
|
+
const identity = useAssignmentIdentity(), panelId = react.useId(), {params: params} = structure.usePaneRouter(), {view: view, setView: setView} = useWorkflowsTab(), telemetry2 = workflowReact.useWorkflowTelemetry(), {openActivity: openActivity, setOpenActivity: setOpenActivity, dialogEntry: dialogEntry} = useOpenActivity(entries), active = entries.filter(isLiveEntry), finished = entries.filter(e => !isLiveEntry(e)), forMe = forMeWorkOf(active, identity), [landing] = react.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__ */ jsxRuntime.jsx(WorkflowInstanceSection, {
|
|
7207
7608
|
defaultOpen: landingDefaultOpen(landing, e.instance._id),
|
|
7208
7609
|
entry: e,
|
|
7209
7610
|
onOpenActivity: activityName => setOpenActivity({
|
|
@@ -7224,6 +7625,7 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7224
7625
|
padding: 3,
|
|
7225
7626
|
children: [
|
|
7226
7627
|
/* @__PURE__ */ jsxRuntime.jsx(GroupHeading, {
|
|
7628
|
+
busy: booting,
|
|
7227
7629
|
count: active.length,
|
|
7228
7630
|
end:
|
|
7229
7631
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
@@ -7236,6 +7638,7 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7236
7638
|
initialValue: initialValue,
|
|
7237
7639
|
mappings: docTypeMappings,
|
|
7238
7640
|
mode: "bleed",
|
|
7641
|
+
source: "document-view-header",
|
|
7239
7642
|
tone: "default"
|
|
7240
7643
|
})
|
|
7241
7644
|
}),
|
|
@@ -7244,7 +7647,12 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7244
7647
|
/* @__PURE__ */ jsxRuntime.jsx(TabSwitch, {
|
|
7245
7648
|
ariaControls: `${panelId}-panel`,
|
|
7246
7649
|
idPrefix: panelId,
|
|
7247
|
-
onSelect:
|
|
7650
|
+
onSelect: next => {
|
|
7651
|
+
next !== view && telemetry2.log(WorkflowDocumentViewOpened, {
|
|
7652
|
+
tab: next,
|
|
7653
|
+
via: "tab-switch"
|
|
7654
|
+
}), setView(next);
|
|
7655
|
+
},
|
|
7248
7656
|
options: [ {
|
|
7249
7657
|
value: "overview",
|
|
7250
7658
|
label: "Overview"
|
|
@@ -7318,6 +7726,7 @@ function OverviewEmptyState({mappings: mappings, docId: docId, initialValue: ini
|
|
|
7318
7726
|
label: "Start workflow",
|
|
7319
7727
|
mappings: mappings,
|
|
7320
7728
|
mode: "ghost",
|
|
7729
|
+
source: "document-view-empty-state",
|
|
7321
7730
|
tone: "default"
|
|
7322
7731
|
})
|
|
7323
7732
|
},
|
|
@@ -7351,7 +7760,8 @@ function SectionActivityDialog({entry: entry, activityName: activityName, onClos
|
|
|
7351
7760
|
breadcrumb: instanceBreadcrumb(instance, definition),
|
|
7352
7761
|
definition: definition,
|
|
7353
7762
|
entry: entry,
|
|
7354
|
-
onClose: onClose
|
|
7763
|
+
onClose: onClose,
|
|
7764
|
+
source: "document-view"
|
|
7355
7765
|
});
|
|
7356
7766
|
}
|
|
7357
7767
|
|
|
@@ -7359,10 +7769,8 @@ function workflowsView(S) {
|
|
|
7359
7769
|
return S.view.component(WorkflowsView).id(WORKFLOWS_VIEW_ID).title("Workflows");
|
|
7360
7770
|
}
|
|
7361
7771
|
|
|
7362
|
-
function workflowDefaultDocumentNode(
|
|
7363
|
-
return (S,
|
|
7364
|
-
if (mappingForDocType(options.mappings, ctx.schemaType)) return S.document().views([ S.view.form(), workflowsView(S) ]);
|
|
7365
|
-
};
|
|
7772
|
+
function workflowDefaultDocumentNode() {
|
|
7773
|
+
return S => S.document().views([ S.view.form(), workflowsView(S) ]);
|
|
7366
7774
|
}
|
|
7367
7775
|
|
|
7368
7776
|
function lockTitleFor(args) {
|
|
@@ -7375,26 +7783,12 @@ function lockTitleFor(args) {
|
|
|
7375
7783
|
return workflows.length === 1 ? `The ${workflowList} workflow is holding this document.` : `The ${workflowList} workflows are holding this document.`;
|
|
7376
7784
|
}
|
|
7377
7785
|
|
|
7378
|
-
const EMPTY = {
|
|
7379
|
-
byType: /* @__PURE__ */ new Map,
|
|
7380
|
-
definitions: /* @__PURE__ */ new Map,
|
|
7381
|
-
warnings: []
|
|
7382
|
-
};
|
|
7383
|
-
|
|
7384
7786
|
function resolveAutoStart(args) {
|
|
7385
|
-
const {autoStart: autoStart,
|
|
7386
|
-
|
|
7387
|
-
const evaluated = evaluateMap(autoStart, context);
|
|
7388
|
-
if ("warning" in evaluated) return {
|
|
7389
|
-
byType: /* @__PURE__ */ new Map,
|
|
7390
|
-
definitions: /* @__PURE__ */ new Map,
|
|
7391
|
-
warnings: [ evaluated.warning ]
|
|
7392
|
-
};
|
|
7393
|
-
const map = evaluated.map, latestByName = new Map(workflowEngine.latestDeployedDefinitions(definitions).map(d => [ d.name, d ])), byType = /* @__PURE__ */ new Map, resolvedDefinitions = /* @__PURE__ */ new Map, warnings = [];
|
|
7394
|
-
for (const [docType, spec] of Object.entries(map)) {
|
|
7787
|
+
const {autoStart: autoStart, knownDocTypes: knownDocTypes, definitions: definitions} = args, latestByName = new Map(workflowEngine.latestDeployedDefinitions(definitions).map(d => [ d.name, d ])), byType = /* @__PURE__ */ new Map, resolvedDefinitions = /* @__PURE__ */ new Map, warnings = [];
|
|
7788
|
+
for (const [docType, names] of Object.entries(autoStart)) {
|
|
7395
7789
|
const entry = resolveEntry({
|
|
7396
7790
|
docType: docType,
|
|
7397
|
-
|
|
7791
|
+
names: names,
|
|
7398
7792
|
knownDocTypes: knownDocTypes,
|
|
7399
7793
|
latestByName: latestByName
|
|
7400
7794
|
});
|
|
@@ -7410,35 +7804,15 @@ function resolveAutoStart(args) {
|
|
|
7410
7804
|
};
|
|
7411
7805
|
}
|
|
7412
7806
|
|
|
7413
|
-
function evaluateMap(autoStart, context) {
|
|
7414
|
-
let map;
|
|
7415
|
-
try {
|
|
7416
|
-
map = typeof autoStart == "function" ? autoStart(context) : autoStart;
|
|
7417
|
-
} catch (err) {
|
|
7418
|
-
return {
|
|
7419
|
-
warning: `autoStart: config function threw — ignoring it (${describeError(err)}).`
|
|
7420
|
-
};
|
|
7421
|
-
}
|
|
7422
|
-
return typeof map != "object" || map === null ? {
|
|
7423
|
-
warning: "autoStart: config did not resolve to an object — ignoring it."
|
|
7424
|
-
} : {
|
|
7425
|
-
map: map
|
|
7426
|
-
};
|
|
7427
|
-
}
|
|
7428
|
-
|
|
7429
|
-
function specNames(spec) {
|
|
7430
|
-
return typeof spec == "string" ? [ spec ] : Array.isArray(spec) ? spec : [];
|
|
7431
|
-
}
|
|
7432
|
-
|
|
7433
7807
|
function resolveEntry(args) {
|
|
7434
|
-
const {docType: docType,
|
|
7808
|
+
const {docType: docType, names: names, knownDocTypes: knownDocTypes, latestByName: latestByName} = args;
|
|
7435
7809
|
if (!knownDocTypes.has(docType)) return {
|
|
7436
7810
|
valid: [],
|
|
7437
7811
|
definitions: [],
|
|
7438
7812
|
warnings: [ `autoStart: no schema type "${docType}" — entry skipped.` ]
|
|
7439
7813
|
};
|
|
7440
7814
|
const valid = [], definitions = [], warnings = [];
|
|
7441
|
-
for (const name of
|
|
7815
|
+
for (const name of names) {
|
|
7442
7816
|
const definition = latestByName.get(name), issue = workflowIssue({
|
|
7443
7817
|
name: name,
|
|
7444
7818
|
docType: docType,
|
|
@@ -7464,11 +7838,57 @@ function workflowIssue(args) {
|
|
|
7464
7838
|
const {name: name, docType: docType, definition: definition} = args;
|
|
7465
7839
|
if (definition === void 0) return `autoStart: "${docType}" → workflow "${name}" is not deployed — skipped.`;
|
|
7466
7840
|
if (!workflowEngine.isStartableDefinition(definition)) return `autoStart: "${docType}" → workflow "${name}" is spawn-only, not startable — skipped.`;
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7841
|
+
const subject = documentSubjectEntry(definition), acceptsType = subject?.types === void 0 || subject.types.includes(docType);
|
|
7842
|
+
if (subject === void 0 || !acceptsType) return `autoStart: "${docType}" → workflow "${name}" has no document subject accepting "${docType}" — skipped.`;
|
|
7843
|
+
if (!workflowEngine.isInputSourced(subject)) return `autoStart: "${docType}" → workflow "${name}" has a self-filling subject (not caller-provided), so the document can't be its subject — skipped.`;
|
|
7844
|
+
}
|
|
7845
|
+
|
|
7846
|
+
function actualType$(previews, bareId) {
|
|
7847
|
+
return previews.unstable_observeDocumentPairAvailability(bareId).pipe(operators.switchMap(({draft: draft, published: published}) => draft.available ? previews.observeDocumentTypeFromId(csm.getDraftId(bareId)) : published.available ? previews.observeDocumentTypeFromId(bareId) : draft.reason === "PERMISSION_DENIED" || published.reason === "PERMISSION_DENIED" ? rxjs.of(void 0) : previews.unstable_observeVersionDocumentIds(bareId).pipe(operators.switchMap(([firstVersionId]) => firstVersionId === void 0 ? rxjs.of(null) : previews.observeDocumentTypeFromId(firstVersionId)))), operators.distinctUntilChanged());
|
|
7848
|
+
}
|
|
7849
|
+
|
|
7850
|
+
const REBUILD_DELAY_MS = 5e3;
|
|
7851
|
+
|
|
7852
|
+
function createActualTypeProbeStore(previews) {
|
|
7853
|
+
const verdicts = /* @__PURE__ */ new Map, live = /* @__PURE__ */ new Map, listeners = /* @__PURE__ */ new Set, notify = () => {
|
|
7854
|
+
for (const listener of [ ...listeners ]) listener();
|
|
7855
|
+
}, start = (bareId, entry) => actualType$(previews, bareId).subscribe({
|
|
7856
|
+
next: value => {
|
|
7857
|
+
verdicts.has(bareId) && verdicts.get(bareId) === value || (verdicts.set(bareId, value),
|
|
7858
|
+
notify());
|
|
7859
|
+
},
|
|
7860
|
+
error: err => {
|
|
7861
|
+
console.error(`[workflow-studio-plugin] actual-type probe for "${bareId}" failed:`, err),
|
|
7862
|
+
entry.subscription = void 0, entry.rebuildTimer = setTimeout(() => {
|
|
7863
|
+
entry.rebuildTimer = void 0, !(live.get(bareId) !== entry || entry.count === 0) && (entry.subscription = start(bareId, entry));
|
|
7864
|
+
}, REBUILD_DELAY_MS);
|
|
7865
|
+
}
|
|
7866
|
+
});
|
|
7867
|
+
return {
|
|
7868
|
+
subscribe(listener) {
|
|
7869
|
+
return listeners.add(listener), () => {
|
|
7870
|
+
listeners.delete(listener);
|
|
7871
|
+
};
|
|
7872
|
+
},
|
|
7873
|
+
read: bareId => verdicts.get(bareId),
|
|
7874
|
+
track(bareId) {
|
|
7875
|
+
let entry = live.get(bareId);
|
|
7876
|
+
if (entry === void 0) {
|
|
7877
|
+
const created = {
|
|
7878
|
+
count: 0,
|
|
7879
|
+
subscription: void 0,
|
|
7880
|
+
rebuildTimer: void 0
|
|
7881
|
+
};
|
|
7882
|
+
live.set(bareId, created), created.subscription = start(bareId, created), entry = created;
|
|
7883
|
+
}
|
|
7884
|
+
entry.count += 1;
|
|
7885
|
+
let released = !1;
|
|
7886
|
+
return () => {
|
|
7887
|
+
released || (released = !0, entry.count -= 1, !(entry.count > 0) && (entry.subscription?.unsubscribe(),
|
|
7888
|
+
entry.rebuildTimer !== void 0 && clearTimeout(entry.rebuildTimer), live.get(bareId) === entry && live.delete(bareId)));
|
|
7889
|
+
};
|
|
7890
|
+
}
|
|
7891
|
+
};
|
|
7472
7892
|
}
|
|
7473
7893
|
|
|
7474
7894
|
function contentDocumentTypes(schema) {
|
|
@@ -7477,7 +7897,7 @@ function contentDocumentTypes(schema) {
|
|
|
7477
7897
|
|
|
7478
7898
|
async function readDeployedDefinitions(engine) {
|
|
7479
7899
|
return (await engine.query({
|
|
7480
|
-
groq: workflowEngine.
|
|
7900
|
+
groq: workflowEngine.latestDefinitionsGroq()
|
|
7481
7901
|
})).map(workflowEngine.assertReadableModel);
|
|
7482
7902
|
}
|
|
7483
7903
|
|
|
@@ -7488,20 +7908,31 @@ const EMPTY_SNAPSHOT = {
|
|
|
7488
7908
|
};
|
|
7489
7909
|
|
|
7490
7910
|
function useDiscoveryState(args) {
|
|
7491
|
-
const {
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
react.
|
|
7495
|
-
watching || (setLatest(EMPTY_SNAPSHOT), setResolved(EMPTY_SNAPSHOT));
|
|
7496
|
-
}, [ watching ]);
|
|
7497
|
-
const filter = react.useMemo(() => ({
|
|
7498
|
-
documents: registered.map(id => workflowEngine.gdrFromResource(contentResource, id)),
|
|
7911
|
+
const {observed: observed, requested: requested, contentResource: contentResource} = args, documentWatching = observed.length > 0, requestedWatching = requested.length > 0, documents = useDiscoveryStream(documentWatching), explicit = useDiscoveryStream(requestedWatching), documentFilter = react.useMemo(() => documentWatching ? {
|
|
7912
|
+
documents: observed.map(id => workflowEngine.gdrFromResource(contentResource, id)),
|
|
7913
|
+
includeCompleted: !0
|
|
7914
|
+
} : void 0, [ documentWatching, observed, contentResource ]), requestedFilter = react.useMemo(() => requestedWatching ? {
|
|
7499
7915
|
ids: requested,
|
|
7500
7916
|
includeCompleted: !0
|
|
7501
|
-
}
|
|
7917
|
+
} : void 0, [ requestedWatching, requested ]), resolved = react.useMemo(() => mergeResolved(documents.resolved, explicit.resolved), [ documents.resolved, explicit.resolved ]);
|
|
7502
7918
|
return {
|
|
7503
|
-
|
|
7504
|
-
|
|
7919
|
+
documentFilter: documentFilter,
|
|
7920
|
+
requestedFilter: requestedFilter,
|
|
7921
|
+
loading: documents.loading || explicit.loading,
|
|
7922
|
+
invalid: documents.invalid ?? explicit.invalid,
|
|
7923
|
+
resolved: resolved,
|
|
7924
|
+
onDocumentSnapshot: documents.onSnapshot,
|
|
7925
|
+
onRequestedSnapshot: explicit.onSnapshot
|
|
7926
|
+
};
|
|
7927
|
+
}
|
|
7928
|
+
|
|
7929
|
+
function useDiscoveryStream(watching) {
|
|
7930
|
+
const [latest, setLatest] = react.useState(EMPTY_SNAPSHOT), [resolved, setResolved] = react.useState(EMPTY_SNAPSHOT), onSnapshot = react.useCallback(snapshot => {
|
|
7931
|
+
setLatest(snapshot), snapshot.instances !== void 0 && setResolved(snapshot);
|
|
7932
|
+
}, []);
|
|
7933
|
+
return react.useEffect(() => {
|
|
7934
|
+
watching || (setLatest(EMPTY_SNAPSHOT), setResolved(EMPTY_SNAPSHOT));
|
|
7935
|
+
}, [ watching ]), {
|
|
7505
7936
|
loading: watching && latest.instances === void 0 && latest.invalid === void 0,
|
|
7506
7937
|
invalid: watching ? latest.invalid : void 0,
|
|
7507
7938
|
resolved: resolved,
|
|
@@ -7509,18 +7940,62 @@ function useDiscoveryState(args) {
|
|
|
7509
7940
|
};
|
|
7510
7941
|
}
|
|
7511
7942
|
|
|
7512
|
-
function
|
|
7513
|
-
const
|
|
7514
|
-
for (const
|
|
7515
|
-
const
|
|
7516
|
-
|
|
7943
|
+
function mergeResolved(documents, explicit) {
|
|
7944
|
+
const rows = [ ...documents.instances ?? [], ...explicit.instances ?? [] ], freshest = /* @__PURE__ */ new Map;
|
|
7945
|
+
for (const instance of rows) {
|
|
7946
|
+
const current = freshest.get(instance._id);
|
|
7947
|
+
(current === void 0 || Date.parse(instance.lastChangedAt) > Date.parse(current.lastChangedAt)) && freshest.set(instance._id, instance);
|
|
7517
7948
|
}
|
|
7949
|
+
return {
|
|
7950
|
+
instances: documents.instances === void 0 && explicit.instances === void 0 ? void 0 : [ ...freshest.values() ],
|
|
7951
|
+
invalid: documents.invalid ?? explicit.invalid,
|
|
7952
|
+
registered: documents.registered
|
|
7953
|
+
};
|
|
7954
|
+
}
|
|
7955
|
+
|
|
7956
|
+
function createDiscoveryIndexer(deriveWatchSet = workflowEngine.subscriptionDocumentsForInstance) {
|
|
7957
|
+
const cached = /* @__PURE__ */ new Map;
|
|
7958
|
+
return {
|
|
7959
|
+
index(args) {
|
|
7960
|
+
const liveIds = new Set(args.instances.map(instance => instance._id));
|
|
7961
|
+
for (const id of cached.keys()) liveIds.has(id) || cached.delete(id);
|
|
7962
|
+
const watchedById = /* @__PURE__ */ new Map;
|
|
7963
|
+
for (const instance of args.instances) {
|
|
7964
|
+
let row = cached.get(instance._id);
|
|
7965
|
+
row?.source !== instance && (row = {
|
|
7966
|
+
source: instance,
|
|
7967
|
+
globalDocumentIds: [ ...new Set(deriveWatchSet(instance).documents.map(document => document.globalDocumentId)) ]
|
|
7968
|
+
}, cached.set(instance._id, row)), watchedById.set(instance._id, row.globalDocumentIds);
|
|
7969
|
+
}
|
|
7970
|
+
return buildDiscoveryIndex(args, watchedById);
|
|
7971
|
+
}
|
|
7972
|
+
};
|
|
7973
|
+
}
|
|
7974
|
+
|
|
7975
|
+
function buildDiscoveryIndex(args, watchedById) {
|
|
7976
|
+
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 => [ workflowEngine.gdrFromResource(contentResource, bareId), bareId ]));
|
|
7977
|
+
for (const instance of ordered) appendInstanceWatches({
|
|
7978
|
+
index: index,
|
|
7979
|
+
registeredByUri: registeredByUri,
|
|
7980
|
+
instanceId: instance._id,
|
|
7981
|
+
watched: watchedById.get(instance._id) ?? []
|
|
7982
|
+
});
|
|
7518
7983
|
return {
|
|
7519
7984
|
instances: new Map(ordered.map(inst => [ inst._id, inst ])),
|
|
7520
7985
|
index: index
|
|
7521
7986
|
};
|
|
7522
7987
|
}
|
|
7523
7988
|
|
|
7989
|
+
function appendInstanceWatches(args) {
|
|
7990
|
+
const {index: index, registeredByUri: registeredByUri, instanceId: instanceId, watched: watched} = args;
|
|
7991
|
+
for (const uri of watched) {
|
|
7992
|
+
const bareId = registeredByUri.get(uri);
|
|
7993
|
+
if (bareId === void 0) continue;
|
|
7994
|
+
const ids = index.get(bareId);
|
|
7995
|
+
ids === void 0 ? index.set(bareId, [ instanceId ]) : ids.push(instanceId);
|
|
7996
|
+
}
|
|
7997
|
+
}
|
|
7998
|
+
|
|
7524
7999
|
function sameInstance(a, b) {
|
|
7525
8000
|
return a === b || a._id === b._id && a._rev === b._rev;
|
|
7526
8001
|
}
|
|
@@ -7544,7 +8019,7 @@ function entryOf(inst, report) {
|
|
|
7544
8019
|
instance: report?.evaluation?.instance ?? inst,
|
|
7545
8020
|
committed: inst,
|
|
7546
8021
|
evaluation: report?.evaluation,
|
|
7547
|
-
ready: report?.ready ??
|
|
8022
|
+
ready: report?.ready ?? workflowEngine.terminalState(inst) !== "in-flight",
|
|
7548
8023
|
invalid: report?.invalid,
|
|
7549
8024
|
guards: report?.guards
|
|
7550
8025
|
};
|
|
@@ -7637,7 +8112,19 @@ function createEntriesStore() {
|
|
|
7637
8112
|
};
|
|
7638
8113
|
}
|
|
7639
8114
|
|
|
7640
|
-
|
|
8115
|
+
function sessionPlan(args) {
|
|
8116
|
+
const demandedIds = new Set(args.demanded), evaluated = [ ...args.discovered.values() ].filter(inst => demandedIds.has(inst._id));
|
|
8117
|
+
return {
|
|
8118
|
+
evaluated: evaluated,
|
|
8119
|
+
guardScope: evaluated.map(inst => inst._id).sort()
|
|
8120
|
+
};
|
|
8121
|
+
}
|
|
8122
|
+
|
|
8123
|
+
function useDefaultLayout(props) {
|
|
8124
|
+
return react.useMemo(() => props.renderDefault(props), [ props ]);
|
|
8125
|
+
}
|
|
8126
|
+
|
|
8127
|
+
const notReady = (..._args) => Promise.reject(new Error("workflow session not ready yet")), NO_REGISTERED_DOCUMENTS = [], DEMAND_RELEASE_GRACE_MS = 500;
|
|
7641
8128
|
|
|
7642
8129
|
function workspaceParts(config) {
|
|
7643
8130
|
if (!config.projectId || !config.dataset) throw new Error("workflow plugin requires a workspace with projectId and dataset");
|
|
@@ -7665,10 +8152,11 @@ class InstanceEvaluatorBoundary extends react.Component {
|
|
|
7665
8152
|
}
|
|
7666
8153
|
|
|
7667
8154
|
function InstanceEvaluator(props) {
|
|
7668
|
-
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} = workflowStudio.useWorkflowSession({
|
|
8155
|
+
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} = workflowStudio.useWorkflowSession({
|
|
7669
8156
|
engine: engine,
|
|
7670
8157
|
instanceId: instanceId,
|
|
7671
|
-
grantsFromPath: grantsFromPath
|
|
8158
|
+
grantsFromPath: grantsFromPath,
|
|
8159
|
+
guardScope: guardScope
|
|
7672
8160
|
});
|
|
7673
8161
|
return react.useEffect(() => {
|
|
7674
8162
|
onReport(instanceId, {
|
|
@@ -7712,9 +8200,9 @@ function engineOptionsFrom(config) {
|
|
|
7712
8200
|
}
|
|
7713
8201
|
|
|
7714
8202
|
function WorkflowProvider(props) {
|
|
7715
|
-
const {config: config} = props, studioClient = sanity.useClient({
|
|
8203
|
+
const {config: config} = props, defaultLayout = useDefaultLayout(props), studioClient = sanity.useClient({
|
|
7716
8204
|
apiVersion: WORKFLOW_API_VERSION
|
|
7717
|
-
}), schema = sanity.useSchema(), {
|
|
8205
|
+
}), schema = sanity.useSchema(), {projectId: projectId, dataset: contentDataset} = workspaceParts(studioClient.config()), workflowDataset = config.workflowDataset ?? contentDataset, binding = react.useMemo(() => ({
|
|
7718
8206
|
engineResource: {
|
|
7719
8207
|
type: "dataset",
|
|
7720
8208
|
id: `${projectId}.${workflowDataset}`
|
|
@@ -7732,11 +8220,19 @@ function WorkflowProvider(props) {
|
|
|
7732
8220
|
}), grantsFromPath = workflowEngine.aclPathForResource({
|
|
7733
8221
|
type: "dataset",
|
|
7734
8222
|
id: `${projectId}.${workflowDataset}`
|
|
7735
|
-
}), {ids: registered, acquire:
|
|
8223
|
+
}), {ids: registered, acquire: registerActive, release: unregisterActive} = workflowReact.useRefcountedIds(), {ids: observed, acquire: retainRegistration, release: releaseRegistration} = workflowReact.useRefcountedIds({
|
|
8224
|
+
releaseDelayMs: DEMAND_RELEASE_GRACE_MS
|
|
8225
|
+
}), register = react.useCallback(id => {
|
|
8226
|
+
registerActive(id), retainRegistration(id);
|
|
8227
|
+
}, [ registerActive, retainRegistration ]), unregister = react.useCallback(id => {
|
|
8228
|
+
unregisterActive(id), releaseRegistration(id);
|
|
8229
|
+
}, [ unregisterActive, releaseRegistration ]), {ids: requested, acquire: requestInstance, release: releaseInstance} = workflowReact.useRefcountedIds(), {ids: evaluationDemand, acquire: requestEvaluation, release: releaseEvaluation} = workflowReact.useRefcountedIds({
|
|
8230
|
+
releaseDelayMs: DEMAND_RELEASE_GRACE_MS
|
|
8231
|
+
}), [seeded, setSeeded] = react.useState(/* @__PURE__ */ new Map), seedInstance = react.useCallback(instance => {
|
|
7736
8232
|
setSeeded(prev => new Map(prev).set(instance._id, instance));
|
|
7737
8233
|
}, []), [startRequest2, setStartRequest] = react.useState(void 0), openStartDialog = react.useCallback(r => setStartRequest(r), []), closeStartDialog = react.useCallback(() => setStartRequest(void 0), []), [entriesStore] = react.useState(createEntriesStore);
|
|
7738
8234
|
react.useEffect(() => () => entriesStore.dispose(), [ entriesStore ]);
|
|
7739
|
-
const onReport = react.useCallback((instanceId, report) => {
|
|
8235
|
+
const previewStore = sanity.useDocumentPreviewStore(), actualTypes = react.useMemo(() => createActualTypeProbeStore(previewStore), [ previewStore ]), onReport = react.useCallback((instanceId, report) => {
|
|
7740
8236
|
entriesStore.report(instanceId, report);
|
|
7741
8237
|
}, [ entriesStore ]), drainRef = react.useRef(void 0), drainCommitted = react.useCallback(async instanceId => {
|
|
7742
8238
|
try {
|
|
@@ -7783,15 +8279,18 @@ function WorkflowProvider(props) {
|
|
|
7783
8279
|
});
|
|
7784
8280
|
}, [ engine ]);
|
|
7785
8281
|
drainRef.current = drainEffectsFor;
|
|
7786
|
-
const {
|
|
7787
|
-
|
|
8282
|
+
const {documentFilter: documentFilter, requestedFilter: requestedFilter, loading: loading, invalid: discoveryInvalid, resolved: resolved, onDocumentSnapshot: onDocumentSnapshot, onRequestedSnapshot: onRequestedSnapshot} = useDiscoveryState({
|
|
8283
|
+
observed: observed,
|
|
7788
8284
|
requested: requested,
|
|
7789
8285
|
contentResource: binding.contentResource
|
|
7790
|
-
}), {instances: discovered, index: docIndex} = react.useMemo(() =>
|
|
8286
|
+
}), discoveryIndexer = react.useMemo(createDiscoveryIndexer, []), {instances: discovered, index: docIndex} = react.useMemo(() => discoveryIndexer.index({
|
|
7791
8287
|
instances: resolved.instances ?? [],
|
|
7792
8288
|
registered: resolved.registered,
|
|
7793
8289
|
contentResource: binding.contentResource
|
|
7794
|
-
}), [ resolved, binding.contentResource ]),
|
|
8290
|
+
}), [ discoveryIndexer, resolved, binding.contentResource ]), {evaluated: evaluated, guardScope: guardScope} = react.useMemo(() => sessionPlan({
|
|
8291
|
+
discovered: discovered,
|
|
8292
|
+
demanded: evaluationDemand
|
|
8293
|
+
}), [ discovered, evaluationDemand ]), resolvedDocs = react.useMemo(() => new Set(resolved.registered), [ resolved.registered ]);
|
|
7795
8294
|
react.useEffect(() => {
|
|
7796
8295
|
setSeeded(prev => {
|
|
7797
8296
|
const kept = [ ...prev ].filter(([id]) => !discovered.has(id));
|
|
@@ -7804,22 +8303,23 @@ function WorkflowProvider(props) {
|
|
|
7804
8303
|
docIndex: docIndex
|
|
7805
8304
|
});
|
|
7806
8305
|
}, [ entriesStore, seeded, discovered, docIndex ]);
|
|
7807
|
-
const isDocResolved = react.useCallback(docId => resolvedDocs.has(docId), [ resolvedDocs ]), schemaContentTypes = react.useMemo(() => new Set(contentDocumentTypes(schema)), [ schema ]), {issues: issues, starts: starts, fields: fields, latestVersions: latestVersions, autoStartByType: autoStartByType, autoStartDefinitions: autoStartDefinitions} = useDeployedDefinitions({
|
|
8306
|
+
const isDocResolved = react.useCallback(docId => resolvedDocs.has(docId), [ resolvedDocs ]), schemaContentTypes = react.useMemo(() => new Set(contentDocumentTypes(schema)), [ schema ]), {mappings: mappings, issues: issues, starts: starts, fields: fields, latestVersions: latestVersions, autoStartByType: autoStartByType, autoStartDefinitions: autoStartDefinitions} = useDeployedDefinitions({
|
|
7808
8307
|
engine: engine,
|
|
7809
|
-
|
|
8308
|
+
overrides: config.mappings,
|
|
7810
8309
|
contentResource: binding.contentResource,
|
|
7811
8310
|
schemaContentTypes: schemaContentTypes,
|
|
7812
8311
|
startRequest: startRequest2,
|
|
7813
|
-
|
|
7814
|
-
schema: schema,
|
|
7815
|
-
workspaceName: workspaceName
|
|
8312
|
+
schema: schema
|
|
7816
8313
|
}), value = react.useMemo(() => ({
|
|
7817
8314
|
register: register,
|
|
7818
8315
|
unregister: unregister,
|
|
7819
8316
|
isDocResolved: isDocResolved,
|
|
7820
8317
|
entries: entriesStore,
|
|
8318
|
+
actualTypes: actualTypes,
|
|
7821
8319
|
requestInstance: requestInstance,
|
|
7822
8320
|
releaseInstance: releaseInstance,
|
|
8321
|
+
requestEvaluation: requestEvaluation,
|
|
8322
|
+
releaseEvaluation: releaseEvaluation,
|
|
7823
8323
|
seedInstance: seedInstance,
|
|
7824
8324
|
openStartDialog: openStartDialog,
|
|
7825
8325
|
closeStartDialog: closeStartDialog,
|
|
@@ -7834,7 +8334,7 @@ function WorkflowProvider(props) {
|
|
|
7834
8334
|
completeEffectFor: completeEffectFor,
|
|
7835
8335
|
engine: engine,
|
|
7836
8336
|
binding: binding,
|
|
7837
|
-
mappings:
|
|
8337
|
+
mappings: mappings,
|
|
7838
8338
|
mappingIssues: issues,
|
|
7839
8339
|
mappingStarts: starts,
|
|
7840
8340
|
mappingFields: fields,
|
|
@@ -7842,24 +8342,30 @@ function WorkflowProvider(props) {
|
|
|
7842
8342
|
effectHandlers: engine.effectHandlers,
|
|
7843
8343
|
autoStartByType: autoStartByType,
|
|
7844
8344
|
autoStartDefinitions: autoStartDefinitions
|
|
7845
|
-
}), [ register, unregister, isDocResolved, entriesStore, requestInstance, releaseInstance, seedInstance, openStartDialog, closeStartDialog, startRequest2, loading, discoveryInvalid, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding,
|
|
8345
|
+
}), [ register, unregister, isDocResolved, entriesStore, actualTypes, 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 ]);
|
|
7846
8346
|
/* @__PURE__ */
|
|
7847
8347
|
return jsxRuntime.jsxs(WorkflowContext.Provider, {
|
|
7848
8348
|
value: value,
|
|
7849
|
-
children: [
|
|
8349
|
+
children: [ documentFilter ? /* @__PURE__ */ jsxRuntime.jsx(DiscoverySubscription, {
|
|
7850
8350
|
engine: engine,
|
|
7851
|
-
filter:
|
|
7852
|
-
onSnapshot:
|
|
8351
|
+
filter: documentFilter,
|
|
8352
|
+
onSnapshot: onDocumentSnapshot,
|
|
7853
8353
|
registered: registered
|
|
7854
|
-
}) : null,
|
|
8354
|
+
}) : null, requestedFilter ? /* @__PURE__ */ jsxRuntime.jsx(DiscoverySubscription, {
|
|
8355
|
+
engine: engine,
|
|
8356
|
+
filter: requestedFilter,
|
|
8357
|
+
onSnapshot: onRequestedSnapshot,
|
|
8358
|
+
registered: NO_REGISTERED_DOCUMENTS
|
|
8359
|
+
}) : null, evaluated.map(inst => /* @__PURE__ */ jsxRuntime.jsx(InstanceEvaluatorBoundary, {
|
|
7855
8360
|
instanceId: inst._id,
|
|
7856
8361
|
children: /* @__PURE__ */ jsxRuntime.jsx(InstanceEvaluator, {
|
|
7857
8362
|
engine: engine,
|
|
7858
8363
|
grantsFromPath: grantsFromPath,
|
|
8364
|
+
guardScope: guardScope,
|
|
7859
8365
|
instanceId: inst._id,
|
|
7860
8366
|
onReport: onReport
|
|
7861
8367
|
})
|
|
7862
|
-
}, inst._id)),
|
|
8368
|
+
}, inst._id)), defaultLayout, props.overlay ]
|
|
7863
8369
|
});
|
|
7864
8370
|
}
|
|
7865
8371
|
|
|
@@ -7869,14 +8375,25 @@ function sameEntries(a, b) {
|
|
|
7869
8375
|
return !0;
|
|
7870
8376
|
}
|
|
7871
8377
|
|
|
8378
|
+
function sameMappings(a, b) {
|
|
8379
|
+
return a.length === b.length && a.every((mapping, index) => {
|
|
8380
|
+
const other = b[index];
|
|
8381
|
+
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;
|
|
8382
|
+
});
|
|
8383
|
+
}
|
|
8384
|
+
|
|
7872
8385
|
function useDeployedDefinitions(args) {
|
|
7873
|
-
const {engine: engine,
|
|
8386
|
+
const {engine: engine, overrides: overrides, contentResource: contentResource, schemaContentTypes: schemaContentTypes, startRequest: startRequest2, schema: schema} = args, [mappings, setMappings] = react.useState([]), [issues, setIssues] = react.useState(/* @__PURE__ */ new Map), [starts, setStarts] = react.useState(/* @__PURE__ */ new Map), [fields, setFields] = react.useState(/* @__PURE__ */ new Map), [latestVersions, setLatestVersions] = react.useState(/* @__PURE__ */ new Map), [autoStartByType, setAutoStartByType] = react.useState(
|
|
7874
8387
|
/* @__PURE__ */ new Map), [autoStartDefinitions, setAutoStartDefinitions] = react.useState(/* @__PURE__ */ new Map), logged = react.useRef(/* @__PURE__ */ new Set);
|
|
7875
8388
|
return react.useEffect(() => {
|
|
7876
8389
|
let cancelled = !1;
|
|
7877
8390
|
return (async () => {
|
|
7878
|
-
const definitions = await readDeployedDefinitions(engine),
|
|
7879
|
-
|
|
8391
|
+
const definitions = await readDeployedDefinitions(engine), effectiveMappings = discoverWorkflowMappings({
|
|
8392
|
+
definitions: definitions,
|
|
8393
|
+
schemaContentTypes: schemaContentTypes,
|
|
8394
|
+
overrides: overrides
|
|
8395
|
+
}), found = mappingIssues({
|
|
8396
|
+
mappings: effectiveMappings,
|
|
7880
8397
|
definitions: definitions,
|
|
7881
8398
|
contentResource: contentResource,
|
|
7882
8399
|
schemaContentTypes: schemaContentTypes
|
|
@@ -7886,32 +8403,30 @@ function useDeployedDefinitions(args) {
|
|
|
7886
8403
|
logged.current.has(signature) || (logged.current.add(signature), console.error(`[workflow-studio-plugin] ${message}`));
|
|
7887
8404
|
}
|
|
7888
8405
|
const resolvedAutoStart = resolveAutoStart({
|
|
7889
|
-
autoStart:
|
|
7890
|
-
context: {
|
|
7891
|
-
workspaceName: workspaceName,
|
|
7892
|
-
schema: schema
|
|
7893
|
-
},
|
|
8406
|
+
autoStart: mappingAutoStartMap(effectiveMappings),
|
|
7894
8407
|
knownDocTypes: new Set(schema.getTypeNames()),
|
|
7895
8408
|
definitions: definitions
|
|
7896
8409
|
});
|
|
7897
8410
|
if (logOnce(resolvedAutoStart.warnings, logged.current), cancelled) return;
|
|
8411
|
+
setMappings(prev => sameMappings(prev, effectiveMappings) ? prev : effectiveMappings),
|
|
7898
8412
|
setIssues(prev => sameEntries(prev, found) ? prev : found), setStarts(mappingStartBlocks({
|
|
7899
|
-
mappings:
|
|
8413
|
+
mappings: effectiveMappings,
|
|
7900
8414
|
definitions: definitions
|
|
7901
8415
|
})), setFields(mappingDeclaredFields({
|
|
7902
|
-
mappings:
|
|
8416
|
+
mappings: effectiveMappings,
|
|
7903
8417
|
definitions: definitions
|
|
7904
8418
|
}));
|
|
7905
8419
|
const versions = new Map(workflowEngine.latestDeployedDefinitions(definitions).map(d => [ d.name, d.version ]));
|
|
7906
8420
|
setLatestVersions(prev => sameEntries(prev, versions) ? prev : versions), setAutoStartByType(resolvedAutoStart.byType),
|
|
7907
8421
|
setAutoStartDefinitions(resolvedAutoStart.definitions);
|
|
7908
8422
|
})().catch(err => {
|
|
7909
|
-
console.error("[workflow-studio-plugin] mapping
|
|
8423
|
+
console.error("[workflow-studio-plugin] mapping discovery failed — keeping the last resolved workflow state:", err);
|
|
7910
8424
|
}), () => {
|
|
7911
8425
|
cancelled = !0;
|
|
7912
8426
|
};
|
|
7913
|
-
}, [ engine,
|
|
8427
|
+
}, [ engine, overrides, contentResource, schemaContentTypes, startRequest2, schema ]),
|
|
7914
8428
|
{
|
|
8429
|
+
mappings: mappings,
|
|
7915
8430
|
issues: issues,
|
|
7916
8431
|
starts: starts,
|
|
7917
8432
|
fields: fields,
|
|
@@ -7927,13 +8442,13 @@ function logOnce(messages, logged) {
|
|
|
7927
8442
|
|
|
7928
8443
|
function AssigneesInput({value: value, onChange: onChange}) {
|
|
7929
8444
|
const {members: members} = useProjectMembers(), [membersOpen, setMembersOpen] = react.useState(!1), roles = react.useMemo(() => [ ...new Set(members.flatMap(m => m.roles)) ].toSorted(), [ members ]), userIds = react.useMemo(() => new Set(value.flatMap(a => a.type === "user" ? [ a.id ] : [])), [ value ]), add = a => {
|
|
7930
|
-
value.some(x => sameAssignee(x, a)) || onChange([ ...value, a ]);
|
|
8445
|
+
value.some(x => workflowComponents.sameAssignee(x, a)) || onChange([ ...value, a ]);
|
|
7931
8446
|
}, remove = i => onChange(value.filter((_, idx) => idx !== i)), toggleUser = id => {
|
|
7932
8447
|
const user = {
|
|
7933
8448
|
type: "user",
|
|
7934
8449
|
id: id
|
|
7935
8450
|
};
|
|
7936
|
-
userIds.has(id) ? onChange(value.filter(a => !sameAssignee(a, user))) : add(user);
|
|
8451
|
+
userIds.has(id) ? onChange(value.filter(a => !workflowComponents.sameAssignee(a, user))) : add(user);
|
|
7937
8452
|
};
|
|
7938
8453
|
/* @__PURE__ */
|
|
7939
8454
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
@@ -8300,12 +8815,12 @@ function DocRefsFieldInput({entry: entry, mappedType: mappedType, value: value,
|
|
|
8300
8815
|
}
|
|
8301
8816
|
|
|
8302
8817
|
function NotesStartInput({onChange: onChange}) {
|
|
8303
|
-
const
|
|
8818
|
+
const selfActor = useSelfActor(), [body, setBody] = react.useState(""), update = next => {
|
|
8304
8819
|
setBody(next);
|
|
8305
8820
|
const trimmed = next.trim();
|
|
8306
8821
|
onChange(trimmed === "" ? [] : [ noteRow({
|
|
8307
8822
|
body: trimmed,
|
|
8308
|
-
actor:
|
|
8823
|
+
actor: selfActor,
|
|
8309
8824
|
at: /* @__PURE__ */ (new Date).toISOString()
|
|
8310
8825
|
}) ]);
|
|
8311
8826
|
};
|
|
@@ -8514,7 +9029,7 @@ function handleStartError(args) {
|
|
|
8514
9029
|
toast.push({
|
|
8515
9030
|
status: "warning",
|
|
8516
9031
|
title: `${label} can't be started right now`,
|
|
8517
|
-
description:
|
|
9032
|
+
description: outcome.description
|
|
8518
9033
|
});
|
|
8519
9034
|
return;
|
|
8520
9035
|
}
|
|
@@ -8526,7 +9041,7 @@ function handleStartError(args) {
|
|
|
8526
9041
|
}
|
|
8527
9042
|
|
|
8528
9043
|
function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
8529
|
-
const {definition: definitionName, label: label, mapping: mapping, subjectDocId: subjectDocId} = request, {engine: engine, binding: binding, seedInstance: seedInstance} = useWorkflowContext(), toast = useClosableToast(), {def: definition, error: definitionError} = useLatestDefinition(definitionName), {selectedReleaseId: selectedReleaseId} = sanity.usePerspective(), releaseId = boundReleaseId(mapping, selectedReleaseId), [values, setValues] = react.useState({}), [attempt, setAttempt] = react.useState(void 0), starting = attempt !== void 0, [heldInstanceId, setHeldInstanceId] = react.useState(void 0), [startNew, setStartNew] = react.useState(!1), {entries: entries} = useWorkflowsForDocument(subjectDocId), resumeEntry = presentedResumeEntry({
|
|
9044
|
+
const {definition: definitionName, label: label, mapping: mapping, subjectDocId: subjectDocId} = request, {engine: engine, binding: binding, seedInstance: seedInstance} = useWorkflowContext(), telemetry2 = workflowReact.useWorkflowTelemetry(), toast = useClosableToast(), {def: definition, error: definitionError} = useLatestDefinition(definitionName), {selectedReleaseId: selectedReleaseId} = sanity.usePerspective(), releaseId = boundReleaseId(mapping, selectedReleaseId), [values, setValues] = react.useState({}), [attempt, setAttempt] = react.useState(void 0), starting = attempt !== void 0, [heldInstanceId, setHeldInstanceId] = react.useState(void 0), [startNew, setStartNew] = react.useState(!1), {entries: entries} = useWorkflowsForDocument(subjectDocId), resumeEntry = presentedResumeEntry({
|
|
8530
9045
|
entries: entries,
|
|
8531
9046
|
definitionName: definitionName,
|
|
8532
9047
|
heldInstanceId: heldInstanceId,
|
|
@@ -8549,7 +9064,10 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
|
8549
9064
|
[name]: v
|
|
8550
9065
|
})), heldInstanceId !== void 0 && declineResume();
|
|
8551
9066
|
}, onStart = async () => {
|
|
8552
|
-
|
|
9067
|
+
telemetry2.log(WorkflowStartDialogSubmitted, {
|
|
9068
|
+
source: request.source,
|
|
9069
|
+
resumed: resuming
|
|
9070
|
+
}), setAttempt({
|
|
8553
9071
|
resume: resumeEntry
|
|
8554
9072
|
});
|
|
8555
9073
|
const instanceId = resumeEntry?.instance._id ?? heldInstanceId ?? workflowEngine.instanceDocId(binding.tag);
|
|
@@ -8629,8 +9147,9 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
|
8629
9147
|
}
|
|
8630
9148
|
|
|
8631
9149
|
function StartWorkflowDialog({request: request, onClose: onClose}) {
|
|
8632
|
-
|
|
8633
|
-
|
|
9150
|
+
return useLogEventOnMount(WorkflowStartDialogOpened, {
|
|
9151
|
+
source: request.source
|
|
9152
|
+
}), /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, {
|
|
8634
9153
|
header: `Start ${request.label}`,
|
|
8635
9154
|
id: "start-workflow",
|
|
8636
9155
|
onClose: onClose,
|
|
@@ -8697,7 +9216,7 @@ function isFreshDocument(value) {
|
|
|
8697
9216
|
}
|
|
8698
9217
|
|
|
8699
9218
|
function subjectEntry(definition) {
|
|
8700
|
-
return (definition
|
|
9219
|
+
return documentSubjectEntry(definition);
|
|
8701
9220
|
}
|
|
8702
9221
|
|
|
8703
9222
|
function autoStartInputs(args) {
|
|
@@ -8724,11 +9243,11 @@ function pendingWorkflows(workflows, live) {
|
|
|
8724
9243
|
}
|
|
8725
9244
|
|
|
8726
9245
|
function extraRequiredInputs(definition) {
|
|
8727
|
-
const fields = definition.fields ?? [],
|
|
9246
|
+
const fields = definition.fields ?? [], subjectName = subjectEntry(definition)?.name, requiredNames = new Set(workflowEngine.missingRequiredInputs({
|
|
8728
9247
|
entryDefs: fields,
|
|
8729
9248
|
initialFields: []
|
|
8730
9249
|
}).map(input => input.name));
|
|
8731
|
-
return fields.filter(entry => requiredNames.has(entry.name) &&
|
|
9250
|
+
return fields.filter(entry => requiredNames.has(entry.name) && entry.name !== subjectName);
|
|
8732
9251
|
}
|
|
8733
9252
|
|
|
8734
9253
|
function buildAutoStartRequests(args) {
|
|
@@ -8769,21 +9288,21 @@ function AutoStartGate(props) {
|
|
|
8769
9288
|
}
|
|
8770
9289
|
|
|
8771
9290
|
function AutoStartDriver(props) {
|
|
8772
|
-
const {rawDocId: rawDocId, docType: docType, workflows: workflows, value: value, fallback: fallback} = props, {isDocResolved: isDocResolved, autoStartDefinitions: autoStartDefinitions, engine: engine, binding: binding, seedInstance: seedInstance} = useWorkflowContext(), observer = workflowStudio.useStudioObserver({
|
|
9291
|
+
const {rawDocId: rawDocId, docType: docType, workflows: workflows, value: value, fallback: fallback} = props, {isDocResolved: isDocResolved, autoStartDefinitions: autoStartDefinitions, engine: engine, binding: binding, seedInstance: seedInstance} = useWorkflowContext(), telemetry2 = workflowReact.useWorkflowTelemetry(), observer = workflowStudio.useStudioObserver({
|
|
8773
9292
|
engine: engine
|
|
8774
9293
|
}), {selectedReleaseId: selectedReleaseId} = sanity.usePerspective(), {entries: entries} = useWorkflowsForDocument(rawDocId), docId = csm.getPublishedId(rawDocId), valueRef = react.useRef(value);
|
|
8775
9294
|
valueRef.current = value;
|
|
8776
9295
|
const pending = react.useMemo(() => pendingWorkflows(workflows, new Set(entries.map(entry => entry.instance.definition))), [ workflows, entries ]), inputs = react.useMemo(() => autoStartInputs({
|
|
8777
9296
|
workflows: pending,
|
|
8778
9297
|
definitions: autoStartDefinitions
|
|
8779
|
-
}), [ pending, autoStartDefinitions ]), pendingRef = react.useRef(pending);
|
|
9298
|
+
}), [ pending, autoStartDefinitions ]), definitionsResolved = workflows.every(name => autoStartDefinitions.has(name)), pendingRef = react.useRef(pending);
|
|
8780
9299
|
pendingRef.current = pending;
|
|
8781
9300
|
const instanceIds = react.useRef(/* @__PURE__ */ new Map), instanceIdFor = react.useCallback(workflow => {
|
|
8782
9301
|
const held = instanceIds.current.get(workflow);
|
|
8783
9302
|
if (held !== void 0) return held;
|
|
8784
9303
|
const id = workflowEngine.instanceDocId(binding.tag);
|
|
8785
9304
|
return instanceIds.current.set(workflow, id), id;
|
|
8786
|
-
}, [ binding.tag ]), [fired, setFired] = react.useState(!1), [settled, setSettled] = react.useState(!1), [failure, setFailure] = react.useState(void 0), firedRef = react.useRef(!1), startAll = react.useCallback(async values => {
|
|
9305
|
+
}, [ binding.tag ]), [fired, setFired] = react.useState(!1), [settled, setSettled] = react.useState(!1), [failure, setFailure] = react.useState(void 0), firedRef = react.useRef(!1), startAll = react.useCallback(async (values, mode) => {
|
|
8787
9306
|
if (!firedRef.current) {
|
|
8788
9307
|
firedRef.current = !0, setFired(!0);
|
|
8789
9308
|
try {
|
|
@@ -8795,20 +9314,25 @@ function AutoStartDriver(props) {
|
|
|
8795
9314
|
releaseId: selectedReleaseId
|
|
8796
9315
|
} : {}
|
|
8797
9316
|
});
|
|
9317
|
+
const requests = buildAutoStartRequests({
|
|
9318
|
+
workflows: pendingRef.current,
|
|
9319
|
+
definitions: autoStartDefinitions,
|
|
9320
|
+
subject: {
|
|
9321
|
+
docId: docId,
|
|
9322
|
+
type: docType
|
|
9323
|
+
},
|
|
9324
|
+
contentResource: binding.contentResource,
|
|
9325
|
+
values: values,
|
|
9326
|
+
instanceIdFor: instanceIdFor
|
|
9327
|
+
});
|
|
9328
|
+
telemetry2.log(WorkflowAutoStartRan, {
|
|
9329
|
+
mode: mode,
|
|
9330
|
+
workflowCount: requests.length
|
|
9331
|
+
});
|
|
8798
9332
|
const {failure: failure2} = await runStarts({
|
|
8799
9333
|
engine: engine,
|
|
8800
9334
|
seed: seedInstance,
|
|
8801
|
-
requests:
|
|
8802
|
-
workflows: pendingRef.current,
|
|
8803
|
-
definitions: autoStartDefinitions,
|
|
8804
|
-
subject: {
|
|
8805
|
-
docId: docId,
|
|
8806
|
-
type: docType
|
|
8807
|
-
},
|
|
8808
|
-
contentResource: binding.contentResource,
|
|
8809
|
-
values: values,
|
|
8810
|
-
instanceIdFor: instanceIdFor
|
|
8811
|
-
})
|
|
9335
|
+
requests: requests
|
|
8812
9336
|
});
|
|
8813
9337
|
failure2 !== void 0 && setFailure(failure2);
|
|
8814
9338
|
} catch (err) {
|
|
@@ -8817,17 +9341,17 @@ function AutoStartDriver(props) {
|
|
|
8817
9341
|
setSettled(!0);
|
|
8818
9342
|
}
|
|
8819
9343
|
}
|
|
8820
|
-
}, [ autoStartDefinitions, docId, docType, binding, engine, observer, seedInstance, instanceIdFor, selectedReleaseId ]), retry = react.useCallback(() => {
|
|
9344
|
+
}, [ autoStartDefinitions, docId, docType, binding, engine, observer, seedInstance, instanceIdFor, selectedReleaseId, telemetry2 ]), retry = react.useCallback(() => {
|
|
8821
9345
|
firedRef.current = !1, setFired(!1), setSettled(!1), setFailure(void 0);
|
|
8822
9346
|
}, []), action = autoStartAction({
|
|
8823
|
-
resolved: isDocResolved(docId),
|
|
9347
|
+
resolved: definitionsResolved && isDocResolved(docId),
|
|
8824
9348
|
pendingCount: pending.length,
|
|
8825
9349
|
needsInput: inputs.length > 0,
|
|
8826
9350
|
fired: fired,
|
|
8827
9351
|
settled: settled
|
|
8828
9352
|
});
|
|
8829
9353
|
return react.useEffect(() => {
|
|
8830
|
-
action === "silent-start" && startAll({});
|
|
9354
|
+
action === "silent-start" && startAll({}, "silent");
|
|
8831
9355
|
}, [ action, startAll ]), failure !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(AutoStartFailure, {
|
|
8832
9356
|
message: failure,
|
|
8833
9357
|
onProceed: () => setFailure(void 0),
|
|
@@ -8839,7 +9363,7 @@ function AutoStartDriver(props) {
|
|
|
8839
9363
|
docType: docType,
|
|
8840
9364
|
inputs: inputs,
|
|
8841
9365
|
onStart: values => {
|
|
8842
|
-
startAll(values);
|
|
9366
|
+
startAll(values, "collect");
|
|
8843
9367
|
},
|
|
8844
9368
|
starting: fired,
|
|
8845
9369
|
workflowCount: pending.length
|
|
@@ -9061,7 +9585,9 @@ function finishedLinesOf(entries) {
|
|
|
9061
9585
|
}
|
|
9062
9586
|
|
|
9063
9587
|
function WorkflowFormStrip(props) {
|
|
9064
|
-
const {mappings: mappings} = props, {isDocResolved: isDocResolved, discoveryInvalid: discoveryInvalid} = useWorkflowContext(), {docId: docId, entries: entries} = useWorkflowsForDocument(props.value?._id ?? null), {params: params, setParams: setParams} = structure.usePaneRouter(),
|
|
9588
|
+
const {mappings: mappings} = props, {isDocResolved: isDocResolved, discoveryInvalid: discoveryInvalid} = useWorkflowContext(), {docId: docId, entries: entries} = useWorkflowsForDocument(props.value?._id ?? null), {params: params, setParams: setParams} = structure.usePaneRouter(), telemetry2 = workflowReact.useWorkflowTelemetry(), openWorkflowsView = focusId => {
|
|
9589
|
+
telemetry2.log(WorkflowFormStripClicked), setParams(focusedViewParams(params, focusId));
|
|
9590
|
+
}, active = entries.filter(isLiveEntry), finished = finishedLinesOf(entries), invalid = surfacedInvalid(discoveryInvalid, entries), resolved = docId !== void 0 && isDocResolved(docId);
|
|
9065
9591
|
/* @__PURE__ */
|
|
9066
9592
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
9067
9593
|
gap: 4,
|
|
@@ -9095,7 +9621,8 @@ function StripLines({active: active, docId: docId, finished: finished, initialVa
|
|
|
9095
9621
|
initialValue: initialValue,
|
|
9096
9622
|
label: "Start workflow",
|
|
9097
9623
|
mappings: mappings,
|
|
9098
|
-
mode: "bleed"
|
|
9624
|
+
mode: "bleed",
|
|
9625
|
+
source: "form-strip"
|
|
9099
9626
|
})
|
|
9100
9627
|
}) : null ]
|
|
9101
9628
|
});
|
|
@@ -9242,6 +9769,61 @@ function TaskCountSpinner({entry: entry}) {
|
|
|
9242
9769
|
});
|
|
9243
9770
|
}
|
|
9244
9771
|
|
|
9772
|
+
function stagePillState(instance) {
|
|
9773
|
+
const definition = definitionSnapshotOf(instance), stage = definition?.stages.find(candidate => candidate.name === instance.currentStage), state = workflowEngine.terminalState(instance);
|
|
9774
|
+
return {
|
|
9775
|
+
title: stageTitle(definition, instance.currentStage),
|
|
9776
|
+
terminal: stage !== void 0 && workflowEngine.isTerminalStage(stage) || state !== "in-flight",
|
|
9777
|
+
state: state,
|
|
9778
|
+
stageKnown: stage !== void 0
|
|
9779
|
+
};
|
|
9780
|
+
}
|
|
9781
|
+
|
|
9782
|
+
function WorkflowStagePreview(props) {
|
|
9783
|
+
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;
|
|
9784
|
+
return props.renderDefault({
|
|
9785
|
+
...props,
|
|
9786
|
+
status: lead ? /* @__PURE__ */ jsxRuntime.jsx(StagePill, {
|
|
9787
|
+
entry: lead,
|
|
9788
|
+
extraLive: extraLive
|
|
9789
|
+
}) : props.status
|
|
9790
|
+
});
|
|
9791
|
+
}
|
|
9792
|
+
|
|
9793
|
+
function StagePill({entry: entry, extraLive: extraLive}) {
|
|
9794
|
+
/* @__PURE__ */
|
|
9795
|
+
return jsxRuntime.jsxs(ui.Flex, {
|
|
9796
|
+
align: "center",
|
|
9797
|
+
gap: 2,
|
|
9798
|
+
children: [
|
|
9799
|
+
/* @__PURE__ */ jsxRuntime.jsx(LeadBadge, {
|
|
9800
|
+
entry: entry
|
|
9801
|
+
}), extraLive > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, {
|
|
9802
|
+
fontSize: 1,
|
|
9803
|
+
mode: "outline",
|
|
9804
|
+
tone: "default",
|
|
9805
|
+
children: [ "+", extraLive ]
|
|
9806
|
+
}) : null ]
|
|
9807
|
+
});
|
|
9808
|
+
}
|
|
9809
|
+
|
|
9810
|
+
function LeadBadge({entry: entry}) {
|
|
9811
|
+
const {instance: instance} = entry;
|
|
9812
|
+
if (workflowEngine.isUnprimed(instance)) /* @__PURE__ */ return jsxRuntime.jsx(StartIncompleteBadge, {});
|
|
9813
|
+
const pill = stagePillState(instance);
|
|
9814
|
+
/* @__PURE__ */
|
|
9815
|
+
return jsxRuntime.jsxs(ui.Badge, {
|
|
9816
|
+
fontSize: 1,
|
|
9817
|
+
mode: pill.terminal ? "default" : "outline",
|
|
9818
|
+
tone: pillTone(pill),
|
|
9819
|
+
children: [ pill.title, pill.state === "completed" ? " ✓" : "" ]
|
|
9820
|
+
});
|
|
9821
|
+
}
|
|
9822
|
+
|
|
9823
|
+
function pillTone(args) {
|
|
9824
|
+
return args.state === "aborted" ? "critical" : args.terminal ? "positive" : args.stageKnown ? "primary" : "default";
|
|
9825
|
+
}
|
|
9826
|
+
|
|
9245
9827
|
function StartWorkflowDialogHost() {
|
|
9246
9828
|
const {startRequest: startRequest2, closeStartDialog: closeStartDialog} = useWorkflowContext();
|
|
9247
9829
|
return startRequest2 ? /* @__PURE__ */ jsxRuntime.jsx(StartWorkflowDialog, {
|
|
@@ -9316,7 +9898,8 @@ function withWorkflowLock(Action, guardAction) {
|
|
|
9316
9898
|
Locked;
|
|
9317
9899
|
}
|
|
9318
9900
|
|
|
9319
|
-
const workflowStudioPlugin = sanity.definePlugin(config => (
|
|
9901
|
+
const workflowStudioPlugin = sanity.definePlugin(config => (assertUniqueWorkflowMappings(config.mappings ?? []),
|
|
9902
|
+
{
|
|
9320
9903
|
name: "workflow-studio-plugin",
|
|
9321
9904
|
tools: prev => [ ...prev, workflowsTool ],
|
|
9322
9905
|
studio: {
|
|
@@ -9330,84 +9913,37 @@ const workflowStudioPlugin = sanity.definePlugin(config => ({
|
|
|
9330
9913
|
},
|
|
9331
9914
|
form: {
|
|
9332
9915
|
components: {
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
mappings: docTypeMappings
|
|
9338
|
-
}) : props.renderDefault(props);
|
|
9339
|
-
/* @__PURE__ */
|
|
9340
|
-
return jsxRuntime.jsx(AutoStartGate, {
|
|
9341
|
-
...props,
|
|
9342
|
-
fallback: fallback
|
|
9343
|
-
});
|
|
9344
|
-
}
|
|
9345
|
-
return props.renderDefault(props);
|
|
9346
|
-
}
|
|
9916
|
+
preview: WorkflowStagePreview,
|
|
9917
|
+
input: props => props.id === "root" && sanity.isObjectInputProps(props) ? /* @__PURE__ */ jsxRuntime.jsx(WorkflowRootInput, {
|
|
9918
|
+
...props
|
|
9919
|
+
}) : props.renderDefault(props)
|
|
9347
9920
|
}
|
|
9348
9921
|
},
|
|
9349
9922
|
document: {
|
|
9350
9923
|
badges: (prev, ctx) => {
|
|
9351
|
-
if (!
|
|
9924
|
+
if (!ctx.documentId) return prev;
|
|
9352
9925
|
const docId = ctx.documentId;
|
|
9353
9926
|
return [ makeActiveWorkflowsBadge(docId), makePerspectiveBadge(docId), ...prev ];
|
|
9354
9927
|
},
|
|
9355
|
-
actions:
|
|
9928
|
+
actions: prev => prev.map(Action => {
|
|
9356
9929
|
const guardAction = Action.action ? LOCKABLE_ACTIONS.get(Action.action) : void 0;
|
|
9357
9930
|
return guardAction ? withWorkflowLock(Action, guardAction) : Action;
|
|
9358
|
-
})
|
|
9931
|
+
})
|
|
9359
9932
|
}
|
|
9360
9933
|
}));
|
|
9361
9934
|
|
|
9362
|
-
function
|
|
9363
|
-
const {
|
|
9364
|
-
return props.renderDefault({
|
|
9935
|
+
function WorkflowRootInput(props) {
|
|
9936
|
+
const {mappings: mappings} = useWorkflowContext(), docTypeMappings = mappingsForDocType(mappings, props.schemaType.name), fallback = docTypeMappings.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(WorkflowFormStrip, {
|
|
9365
9937
|
...props,
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
extraLive: extraLive
|
|
9369
|
-
}) : props.status
|
|
9370
|
-
});
|
|
9371
|
-
}
|
|
9372
|
-
|
|
9373
|
-
function StagePill({entry: entry, extraLive: extraLive}) {
|
|
9374
|
-
/* @__PURE__ */
|
|
9375
|
-
return jsxRuntime.jsxs(ui.Flex, {
|
|
9376
|
-
align: "center",
|
|
9377
|
-
gap: 2,
|
|
9378
|
-
children: [
|
|
9379
|
-
/* @__PURE__ */ jsxRuntime.jsx(LeadBadge, {
|
|
9380
|
-
entry: entry
|
|
9381
|
-
}), extraLive > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, {
|
|
9382
|
-
fontSize: 1,
|
|
9383
|
-
mode: "outline",
|
|
9384
|
-
tone: "default",
|
|
9385
|
-
children: [ "+", extraLive ]
|
|
9386
|
-
}) : null ]
|
|
9387
|
-
});
|
|
9388
|
-
}
|
|
9389
|
-
|
|
9390
|
-
function LeadBadge({entry: entry}) {
|
|
9391
|
-
const {instance: instance, evaluation: evaluation} = entry;
|
|
9392
|
-
if (workflowEngine.isUnprimed(instance)) /* @__PURE__ */ return jsxRuntime.jsx(StartIncompleteBadge, {});
|
|
9393
|
-
const stage = evaluation?.currentStage?.stage, title = stage?.title ?? stageTitle(definitionSnapshotOf(instance), instance.currentStage), state = workflowEngine.terminalState(instance), isTerminal = (stage ? workflowEngine.isTerminalStage(stage) : !1) || state !== "in-flight";
|
|
9938
|
+
mappings: docTypeMappings
|
|
9939
|
+
}) : props.renderDefault(props);
|
|
9394
9940
|
/* @__PURE__ */
|
|
9395
|
-
return jsxRuntime.
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
tone: pillTone({
|
|
9399
|
-
state: state,
|
|
9400
|
-
isTerminal: isTerminal,
|
|
9401
|
-
stageKnown: stage !== void 0
|
|
9402
|
-
}),
|
|
9403
|
-
children: [ title, state === "completed" ? " ✓" : "" ]
|
|
9941
|
+
return jsxRuntime.jsx(AutoStartGate, {
|
|
9942
|
+
...props,
|
|
9943
|
+
fallback: fallback
|
|
9404
9944
|
});
|
|
9405
9945
|
}
|
|
9406
9946
|
|
|
9407
|
-
function pillTone(args) {
|
|
9408
|
-
return args.state === "aborted" ? "critical" : args.isTerminal ? "positive" : args.stageKnown ? "primary" : "default";
|
|
9409
|
-
}
|
|
9410
|
-
|
|
9411
9947
|
exports.AbortedBadge = AbortedBadge;
|
|
9412
9948
|
|
|
9413
9949
|
exports.ActivitiesList = ActivitiesList;
|
|
@@ -9418,6 +9954,8 @@ exports.ActivityRow = ActivityRow;
|
|
|
9418
9954
|
|
|
9419
9955
|
exports.BreadcrumbTail = BreadcrumbTail;
|
|
9420
9956
|
|
|
9957
|
+
exports.CautionNote = CautionNote;
|
|
9958
|
+
|
|
9421
9959
|
exports.CollapsibleBand = CollapsibleBand;
|
|
9422
9960
|
|
|
9423
9961
|
exports.DismissablePopover = DismissablePopover;
|
|
@@ -9436,6 +9974,8 @@ exports.LinkChip = LinkChip;
|
|
|
9436
9974
|
|
|
9437
9975
|
exports.LoadingRow = LoadingRow;
|
|
9438
9976
|
|
|
9977
|
+
exports.SpinnerSlot = SpinnerSlot;
|
|
9978
|
+
|
|
9439
9979
|
exports.StageChip = StageChip;
|
|
9440
9980
|
|
|
9441
9981
|
exports.StageFace = StageFace;
|
|
@@ -9450,7 +9990,13 @@ exports.TrailingHairline = TrailingHairline;
|
|
|
9450
9990
|
|
|
9451
9991
|
exports.UnreadableDocsNote = UnreadableDocsNote;
|
|
9452
9992
|
|
|
9453
|
-
exports.
|
|
9993
|
+
exports.WORKFLOW_API_VERSION = WORKFLOW_API_VERSION;
|
|
9994
|
+
|
|
9995
|
+
exports.WorkflowInstanceDetailViewed = WorkflowInstanceDetailViewed;
|
|
9996
|
+
|
|
9997
|
+
exports.WorkflowTaskFiltersApplied = WorkflowTaskFiltersApplied;
|
|
9998
|
+
|
|
9999
|
+
exports.WorkflowToolOpened = WorkflowToolOpened;
|
|
9454
10000
|
|
|
9455
10001
|
exports.activityRowProps = activityRowProps;
|
|
9456
10002
|
|
|
@@ -9466,8 +10012,6 @@ exports.definitionSnapshotOf = definitionSnapshotOf;
|
|
|
9466
10012
|
|
|
9467
10013
|
exports.describeError = describeError;
|
|
9468
10014
|
|
|
9469
|
-
exports.editTargetOf = editTargetOf;
|
|
9470
|
-
|
|
9471
10015
|
exports.findActivity = findActivity;
|
|
9472
10016
|
|
|
9473
10017
|
exports.findActivityNode = findActivityNode;
|
|
@@ -9488,8 +10032,6 @@ exports.isEvaluationStale = isEvaluationStale;
|
|
|
9488
10032
|
|
|
9489
10033
|
exports.isOpenActivityStatus = isOpenActivityStatus;
|
|
9490
10034
|
|
|
9491
|
-
exports.mappingForDocType = mappingForDocType;
|
|
9492
|
-
|
|
9493
10035
|
exports.openActivityGone = openActivityGone;
|
|
9494
10036
|
|
|
9495
10037
|
exports.parseDateFieldValue = parseDateFieldValue;
|
|
@@ -9514,8 +10056,12 @@ exports.stopRowMouseDown = stopRowMouseDown;
|
|
|
9514
10056
|
|
|
9515
10057
|
exports.useAssignmentIdentity = useAssignmentIdentity;
|
|
9516
10058
|
|
|
10059
|
+
exports.useClosableToast = useClosableToast;
|
|
10060
|
+
|
|
9517
10061
|
exports.useDefinition = useDefinition;
|
|
9518
10062
|
|
|
10063
|
+
exports.useLogEventOnMount = useLogEventOnMount;
|
|
10064
|
+
|
|
9519
10065
|
exports.useProjectMembers = useProjectMembers;
|
|
9520
10066
|
|
|
9521
10067
|
exports.useSaveField = useSaveField;
|
|
@@ -9528,8 +10074,6 @@ exports.useWorkflowInstanceEntry = useWorkflowInstanceEntry;
|
|
|
9528
10074
|
|
|
9529
10075
|
exports.workflowDefaultDocumentNode = workflowDefaultDocumentNode;
|
|
9530
10076
|
|
|
9531
|
-
exports.workflowDocTypes = workflowDocTypes;
|
|
9532
|
-
|
|
9533
10077
|
exports.workflowStudioPlugin = workflowStudioPlugin;
|
|
9534
10078
|
|
|
9535
10079
|
exports.workflowsTabCodec = workflowsTabCodec;
|