@sanity/workflow-studio-plugin 0.20.0 → 0.22.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 +123 -0
- package/README.md +9 -1
- package/dist/_chunks-cjs/index.cjs +611 -290
- package/dist/_chunks-cjs/workflows-tool-root.cjs +504 -23
- package/dist/_chunks-es/index.js +607 -292
- package/dist/_chunks-es/workflows-tool-root.js +508 -25
- package/package.json +16 -14
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var jsxRuntime = require("react/jsx-runtime"), Timeline = require("@sanity/icons/Timeline"), ui = require("@sanity/ui"), 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"), csm = require("@sanity/client/csm"),
|
|
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 : {
|
|
@@ -421,67 +421,6 @@ function isLiveEntry(entry) {
|
|
|
421
421
|
return workflowEngine.terminalState(entry.instance) === "in-flight";
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
-
const WORKFLOW_API_VERSION = workflowEngine.ENGINE_API_VERSION, WORKFLOW_SYSTEM_TYPES = [ workflowEngine.WORKFLOW_INSTANCE_TYPE, workflowEngine.WORKFLOW_DEFINITION_TYPE, workflowEngine.GUARD_DOC_TYPE ];
|
|
425
|
-
|
|
426
|
-
function editTargetOf(field) {
|
|
427
|
-
return {
|
|
428
|
-
scope: field.scope,
|
|
429
|
-
field: field.name,
|
|
430
|
-
...field.activity ? {
|
|
431
|
-
activity: field.activity
|
|
432
|
-
} : {}
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
const EMPTY_ENTRIES = [], WorkflowContext = react.createContext(null);
|
|
437
|
-
|
|
438
|
-
function useWorkflowContext() {
|
|
439
|
-
const value = react.useContext(WorkflowContext);
|
|
440
|
-
if (!value) throw new Error("useWorkflowContext must render inside the workflow plugin provider");
|
|
441
|
-
return value;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
function useWorkflowsForDocument(rawId) {
|
|
445
|
-
return useDocumentWorkflowEntries(rawId, !0);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
function useCommittedWorkflowsForDocument(rawId) {
|
|
449
|
-
return useDocumentWorkflowEntries(rawId, !1);
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
function useDocumentWorkflowEntries(rawId, evaluate) {
|
|
453
|
-
const {register: register, unregister: unregister, requestEvaluation: requestEvaluation, releaseEvaluation: releaseEvaluation, entries: entries} = useWorkflowContext(), docId = rawId ? csm.getPublishedId(rawId) : void 0;
|
|
454
|
-
react.useEffect(() => {
|
|
455
|
-
if (docId) return register(docId), () => unregister(docId);
|
|
456
|
-
}, [ docId, register, unregister ]);
|
|
457
|
-
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") : "";
|
|
458
|
-
return react.useEffect(() => {
|
|
459
|
-
if (!evaluate) return;
|
|
460
|
-
const ids = evaluationKey === "" ? [] : evaluationKey.split("\0");
|
|
461
|
-
for (const id of ids) requestEvaluation(id);
|
|
462
|
-
return () => {
|
|
463
|
-
for (const id of ids) releaseEvaluation(id);
|
|
464
|
-
};
|
|
465
|
-
}, [ evaluate, evaluationKey, requestEvaluation, releaseEvaluation ]), {
|
|
466
|
-
docId: docId,
|
|
467
|
-
entries: list
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
function useHeldWorkflowEntry(instanceId) {
|
|
472
|
-
const {entries: entries} = useWorkflowContext();
|
|
473
|
-
return react.useSyncExternalStore(entries.subscribe, react.useCallback(() => instanceId ? entries.getInstance(instanceId) : void 0, [ entries, instanceId ]));
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
function useWorkflowInstanceEntry(instanceId, options = {}) {
|
|
477
|
-
const {requestInstance: requestInstance, releaseInstance: releaseInstance, requestEvaluation: requestEvaluation, releaseEvaluation: releaseEvaluation} = useWorkflowContext(), evaluate = options.evaluate ?? !0;
|
|
478
|
-
return react.useEffect(() => {
|
|
479
|
-
if (instanceId) return requestInstance(instanceId), () => releaseInstance(instanceId);
|
|
480
|
-
}, [ instanceId, requestInstance, releaseInstance ]), react.useEffect(() => {
|
|
481
|
-
if (!(!instanceId || !evaluate)) return requestEvaluation(instanceId), () => releaseEvaluation(instanceId);
|
|
482
|
-
}, [ instanceId, evaluate, requestEvaluation, releaseEvaluation ]), useHeldWorkflowEntry(instanceId);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
424
|
const isTodoDone = item => item.status === "done", toggledTodoStatus = item => isTodoDone(item) ? "open" : "done";
|
|
486
425
|
|
|
487
426
|
function isTodoOverdue(item, today = /* @__PURE__ */ new Date) {
|
|
@@ -557,7 +496,7 @@ function buildTickIndex(evaluation) {
|
|
|
557
496
|
function todoFieldEditability(args) {
|
|
558
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));
|
|
559
498
|
return match ? match.editable ? {
|
|
560
|
-
editTarget:
|
|
499
|
+
editTarget: workflowReact.editFieldTarget(match)
|
|
561
500
|
} : match.disabledReason === void 0 ? {} : {
|
|
562
501
|
editDisabledReason: match.disabledReason
|
|
563
502
|
} : {};
|
|
@@ -622,8 +561,8 @@ function assigneeMatches(member, who) {
|
|
|
622
561
|
return member.type === "user" ? member.id === who.userId : who.roles.includes(member.role);
|
|
623
562
|
}
|
|
624
563
|
|
|
625
|
-
function
|
|
626
|
-
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)));
|
|
627
566
|
}
|
|
628
567
|
|
|
629
568
|
function isAssigneeShape(value) {
|
|
@@ -998,6 +937,112 @@ function deriveActivityDetail(args) {
|
|
|
998
937
|
};
|
|
999
938
|
}
|
|
1000
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
|
+
|
|
1001
1046
|
function isEmptyValue(value) {
|
|
1002
1047
|
return value == null || value === "" || Array.isArray(value) && value.length === 0;
|
|
1003
1048
|
}
|
|
@@ -1040,8 +1085,12 @@ function memberIndex(members) {
|
|
|
1040
1085
|
|
|
1041
1086
|
const selfUserFor = (id, me) => me != null && me.id === id ? me : void 0;
|
|
1042
1087
|
|
|
1088
|
+
function globalIdOf(users, projectScopedId) {
|
|
1089
|
+
return users.find(user => user.membership.id === projectScopedId)?.profile?.sanityUserId ?? projectScopedId;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1043
1092
|
function userDisplayFor(args) {
|
|
1044
|
-
const member = memberIndex(args.members).get(
|
|
1093
|
+
const matchId = args.matchId ?? args.id, member = memberIndex(args.members).get(matchId), self = selfUserFor(matchId, args.me);
|
|
1045
1094
|
return {
|
|
1046
1095
|
id: args.id,
|
|
1047
1096
|
name: member?.displayName ?? self?.name ?? args.id,
|
|
@@ -1050,28 +1099,52 @@ function userDisplayFor(args) {
|
|
|
1050
1099
|
}
|
|
1051
1100
|
|
|
1052
1101
|
function useUserDisplays(ids) {
|
|
1053
|
-
const {members: members} = useProjectMembers(),
|
|
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 ]);
|
|
1054
1106
|
return react.useMemo(() => ids.map(id => userDisplayFor({
|
|
1055
1107
|
id: id,
|
|
1056
1108
|
members: members,
|
|
1057
|
-
me: me
|
|
1058
|
-
|
|
1109
|
+
me: me,
|
|
1110
|
+
matchId: globalIdOf(users, id)
|
|
1111
|
+
})), [ ids, me, members, users ]);
|
|
1059
1112
|
}
|
|
1060
1113
|
|
|
1061
1114
|
function useUserDisplay(id) {
|
|
1062
|
-
const
|
|
1063
|
-
return
|
|
1115
|
+
const ids = react.useMemo(() => [ id ], [ id ]), [display] = useUserDisplays(ids);
|
|
1116
|
+
return display ?? {
|
|
1117
|
+
name: id,
|
|
1118
|
+
imageUrl: void 0
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
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 {
|
|
1064
1133
|
id: id,
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1134
|
+
roles: me.roles ?? []
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
function useSelfActor() {
|
|
1139
|
+
const self = useBridgedSelf();
|
|
1140
|
+
return self === void 0 ? void 0 : personActor(self);
|
|
1068
1141
|
}
|
|
1069
1142
|
|
|
1070
1143
|
function useAssignmentIdentity() {
|
|
1071
|
-
const
|
|
1072
|
-
if (
|
|
1073
|
-
userId:
|
|
1074
|
-
roles:
|
|
1144
|
+
const self = useBridgedSelf();
|
|
1145
|
+
if (self !== void 0) return {
|
|
1146
|
+
userId: self.id,
|
|
1147
|
+
roles: self.roles.map(r => r.name)
|
|
1075
1148
|
};
|
|
1076
1149
|
}
|
|
1077
1150
|
|
|
@@ -1080,16 +1153,13 @@ const projectMembersByUsers = /* @__PURE__ */ new WeakMap;
|
|
|
1080
1153
|
function projectMembersFrom(users) {
|
|
1081
1154
|
const cached = projectMembersByUsers.get(users);
|
|
1082
1155
|
if (cached) return cached;
|
|
1083
|
-
const members = users.map(({membership: membership, profile: profile}) => ({
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
imageUrl: profile.imageUrl
|
|
1091
|
-
} : {},
|
|
1092
|
-
roles: (membership.roles ?? []).map(role => role.name)
|
|
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
|
|
1093
1163
|
}));
|
|
1094
1164
|
return projectMembersByUsers.set(users, members), members;
|
|
1095
1165
|
}
|
|
@@ -1417,12 +1487,12 @@ function MemberPicker({selectedIds: selectedIds, onSelect: onSelect, unassignRow
|
|
|
1417
1487
|
});
|
|
1418
1488
|
}
|
|
1419
1489
|
|
|
1420
|
-
function AssigneePicker({value: value,
|
|
1490
|
+
function AssigneePicker({value: value, onChange: onChange}) {
|
|
1421
1491
|
const state = useProjectMembers();
|
|
1422
1492
|
/* @__PURE__ */
|
|
1423
1493
|
return jsxRuntime.jsx(workflowComponents.AssigneePicker, {
|
|
1424
1494
|
...state,
|
|
1425
|
-
|
|
1495
|
+
onChange: onChange,
|
|
1426
1496
|
value: value
|
|
1427
1497
|
});
|
|
1428
1498
|
}
|
|
@@ -1752,7 +1822,7 @@ function useActionClusterPending() {
|
|
|
1752
1822
|
}
|
|
1753
1823
|
|
|
1754
1824
|
function useFireAction(args) {
|
|
1755
|
-
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;
|
|
1756
1826
|
return {
|
|
1757
1827
|
fire: react.useCallback(async params => {
|
|
1758
1828
|
if (pending) return !1;
|
|
@@ -1767,6 +1837,11 @@ function useFireAction(args) {
|
|
|
1767
1837
|
}), toast.push({
|
|
1768
1838
|
status: "success",
|
|
1769
1839
|
title: `${label} done`
|
|
1840
|
+
}), telemetry2.log(WorkflowActionControlUsed, {
|
|
1841
|
+
instanceId: instanceId,
|
|
1842
|
+
surface: surface,
|
|
1843
|
+
viaMenu: viaMenu,
|
|
1844
|
+
success: !0
|
|
1770
1845
|
}), !0;
|
|
1771
1846
|
} catch (err) {
|
|
1772
1847
|
return console.error(`[workflow-studio-plugin] firing "${action}" on "${activity}" failed:`, err),
|
|
@@ -1774,11 +1849,16 @@ function useFireAction(args) {
|
|
|
1774
1849
|
status: "error",
|
|
1775
1850
|
title: `${label} failed`,
|
|
1776
1851
|
description: describeError(err)
|
|
1852
|
+
}), telemetry2.log(WorkflowActionControlUsed, {
|
|
1853
|
+
instanceId: instanceId,
|
|
1854
|
+
surface: surface,
|
|
1855
|
+
viaMenu: viaMenu,
|
|
1856
|
+
success: !1
|
|
1777
1857
|
}), !1;
|
|
1778
1858
|
} finally {
|
|
1779
1859
|
setLocalPending(!1), cluster?.onFireChange(!1);
|
|
1780
1860
|
}
|
|
1781
|
-
}, [ fireActionFor, instanceId, activity, action, label, pending, toast, cluster ]),
|
|
1861
|
+
}, [ fireActionFor, instanceId, activity, action, label, pending, toast, cluster, telemetry2, surface, viaMenu ]),
|
|
1782
1862
|
pending: pending
|
|
1783
1863
|
};
|
|
1784
1864
|
}
|
|
@@ -1819,12 +1899,14 @@ function RowClickShield({active: active, children: children}) {
|
|
|
1819
1899
|
});
|
|
1820
1900
|
}
|
|
1821
1901
|
|
|
1822
|
-
function FireButton({instanceId: instanceId, activity: activity, action: action, label: label, mode: mode = "default", chrome: chrome, tone: tone = "default", icon: icon}) {
|
|
1902
|
+
function FireButton({instanceId: instanceId, activity: activity, action: action, label: label, surface: surface, mode: mode = "default", chrome: chrome, tone: tone = "default", icon: icon}) {
|
|
1823
1903
|
const {fire: fire, pending: pending} = useFireAction({
|
|
1824
1904
|
instanceId: instanceId,
|
|
1825
1905
|
activity: activity,
|
|
1826
1906
|
action: action,
|
|
1827
|
-
label: label
|
|
1907
|
+
label: label,
|
|
1908
|
+
surface: surface,
|
|
1909
|
+
viaMenu: !1
|
|
1828
1910
|
}), handleClick = e => {
|
|
1829
1911
|
chrome?.inButtonCard === !0 && e.stopPropagation(), !pending && fire();
|
|
1830
1912
|
};
|
|
@@ -1845,7 +1927,7 @@ function FireButton({instanceId: instanceId, activity: activity, action: action,
|
|
|
1845
1927
|
});
|
|
1846
1928
|
}
|
|
1847
1929
|
|
|
1848
|
-
function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
1930
|
+
function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
1849
1931
|
const rowKind = actionRowKind(actionEval);
|
|
1850
1932
|
return rowKind.kind === "disabled" ? /* @__PURE__ */ jsxRuntime.jsx(DisabledActionButton, {
|
|
1851
1933
|
actionEval: actionEval,
|
|
@@ -1855,12 +1937,14 @@ function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, acti
|
|
|
1855
1937
|
actionEval: actionEval,
|
|
1856
1938
|
instanceId: instanceId,
|
|
1857
1939
|
activity: activity,
|
|
1858
|
-
chrome: chrome
|
|
1940
|
+
chrome: chrome,
|
|
1941
|
+
surface: surface
|
|
1859
1942
|
}) : /* @__PURE__ */ jsxRuntime.jsx(ParamsActionButton, {
|
|
1860
1943
|
actionEval: actionEval,
|
|
1861
1944
|
instanceId: instanceId,
|
|
1862
1945
|
activity: activity,
|
|
1863
|
-
chrome: chrome
|
|
1946
|
+
chrome: chrome,
|
|
1947
|
+
surface: surface
|
|
1864
1948
|
});
|
|
1865
1949
|
}
|
|
1866
1950
|
|
|
@@ -1885,7 +1969,7 @@ function DisabledActionButton({actionEval: actionEval, activity: activity, chrom
|
|
|
1885
1969
|
}) : button;
|
|
1886
1970
|
}
|
|
1887
1971
|
|
|
1888
|
-
function PlainActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
1972
|
+
function PlainActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
1889
1973
|
const {action: action} = actionEval, label = actionLabel(action), btn = actionButtonFace({
|
|
1890
1974
|
actionEval: actionEval,
|
|
1891
1975
|
activityName: activity
|
|
@@ -1897,6 +1981,7 @@ function PlainActionButton({actionEval: actionEval, instanceId: instanceId, acti
|
|
|
1897
1981
|
mode: btn.mode,
|
|
1898
1982
|
activity: activity,
|
|
1899
1983
|
chrome: chrome,
|
|
1984
|
+
surface: surface,
|
|
1900
1985
|
tone: btn.tone
|
|
1901
1986
|
});
|
|
1902
1987
|
return action.description ? /* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
@@ -1905,12 +1990,14 @@ function PlainActionButton({actionEval: actionEval, instanceId: instanceId, acti
|
|
|
1905
1990
|
}) : button;
|
|
1906
1991
|
}
|
|
1907
1992
|
|
|
1908
|
-
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}) {
|
|
1909
1994
|
const {action: action} = actionEval, label = actionLabel(action), decls = action.params ?? [], [values, setValues] = react.useState({}), {fire: fire, pending: pending} = useFireAction({
|
|
1910
1995
|
instanceId: instanceId,
|
|
1911
1996
|
activity: activity,
|
|
1912
1997
|
action: action.name,
|
|
1913
|
-
label: label
|
|
1998
|
+
label: label,
|
|
1999
|
+
surface: surface,
|
|
2000
|
+
viaMenu: viaMenu
|
|
1914
2001
|
}), built = buildParams(decls, values), confirm = async () => {
|
|
1915
2002
|
await fire(built.params) && onClose();
|
|
1916
2003
|
};
|
|
@@ -1965,7 +2052,7 @@ function ParamsActionDialog({actionEval: actionEval, instanceId: instanceId, act
|
|
|
1965
2052
|
});
|
|
1966
2053
|
}
|
|
1967
2054
|
|
|
1968
|
-
function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
2055
|
+
function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
1969
2056
|
const [open, setOpen] = react.useState(!1), btn = actionButtonFace({
|
|
1970
2057
|
actionEval: actionEval,
|
|
1971
2058
|
activityName: activity
|
|
@@ -1990,7 +2077,9 @@ function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, act
|
|
|
1990
2077
|
actionEval: actionEval,
|
|
1991
2078
|
activity: activity,
|
|
1992
2079
|
instanceId: instanceId,
|
|
1993
|
-
onClose: () => setOpen(!1)
|
|
2080
|
+
onClose: () => setOpen(!1),
|
|
2081
|
+
surface: surface,
|
|
2082
|
+
viaMenu: !1
|
|
1994
2083
|
})
|
|
1995
2084
|
}) : null ]
|
|
1996
2085
|
});
|
|
@@ -2284,27 +2373,10 @@ function useLocalDocRef(gdr) {
|
|
|
2284
2373
|
}
|
|
2285
2374
|
|
|
2286
2375
|
function useActualDocType(bareId) {
|
|
2287
|
-
const
|
|
2288
|
-
apiVersion: WORKFLOW_API_VERSION
|
|
2289
|
-
}), [probe, setProbe] = react.useState();
|
|
2376
|
+
const {actualTypes: actualTypes} = useWorkflowContext();
|
|
2290
2377
|
return react.useEffect(() => {
|
|
2291
|
-
if (
|
|
2292
|
-
|
|
2293
|
-
return client.fetch("*[_id == $id || _id == $draft || _id in path($version)][0]._type", {
|
|
2294
|
-
id: bareId,
|
|
2295
|
-
draft: `drafts.${bareId}`,
|
|
2296
|
-
version: `versions.*.${bareId}`
|
|
2297
|
-
}, {
|
|
2298
|
-
perspective: "raw"
|
|
2299
|
-
}).then(result => {
|
|
2300
|
-
cancelled || setProbe({
|
|
2301
|
-
id: bareId,
|
|
2302
|
-
value: result
|
|
2303
|
-
});
|
|
2304
|
-
}).catch(() => {}), () => {
|
|
2305
|
-
cancelled = !0;
|
|
2306
|
-
};
|
|
2307
|
-
}, [ 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 ]));
|
|
2308
2380
|
}
|
|
2309
2381
|
|
|
2310
2382
|
function useDocLink(gdr) {
|
|
@@ -2884,7 +2956,7 @@ function useFieldDraft(args) {
|
|
|
2884
2956
|
}
|
|
2885
2957
|
|
|
2886
2958
|
function EditableFieldControl({instanceId: instanceId, field: field}) {
|
|
2887
|
-
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);
|
|
2888
2960
|
/* @__PURE__ */
|
|
2889
2961
|
return jsxRuntime.jsx(EditableField, {
|
|
2890
2962
|
field: field,
|
|
@@ -2920,7 +2992,7 @@ function EditableFieldControl({instanceId: instanceId, field: field}) {
|
|
|
2920
2992
|
mode: "append",
|
|
2921
2993
|
value: noteRow({
|
|
2922
2994
|
body: body,
|
|
2923
|
-
actor:
|
|
2995
|
+
actor: selfActor,
|
|
2924
2996
|
at: /* @__PURE__ */ (new Date).toISOString()
|
|
2925
2997
|
})
|
|
2926
2998
|
}).then(() => {})
|
|
@@ -3033,7 +3105,7 @@ function useAssigneePick(args) {
|
|
|
3033
3105
|
saving: saving,
|
|
3034
3106
|
pick: assignee => {
|
|
3035
3107
|
if (!saving) {
|
|
3036
|
-
if (current && sameAssignee(assignee, current)) {
|
|
3108
|
+
if (current && workflowComponents.sameAssignee(assignee, current)) {
|
|
3037
3109
|
onUnset !== void 0 && save(onUnset);
|
|
3038
3110
|
return;
|
|
3039
3111
|
}
|
|
@@ -3055,7 +3127,10 @@ function AssigneeField({field: field, onSave: onSave, onUnset: onUnset}) {
|
|
|
3055
3127
|
align: "center",
|
|
3056
3128
|
children: /* @__PURE__ */ jsxRuntime.jsx(DismissablePopover, {
|
|
3057
3129
|
content: /* @__PURE__ */ jsxRuntime.jsx(AssigneePicker, {
|
|
3058
|
-
|
|
3130
|
+
onChange: next => {
|
|
3131
|
+
const changed = changedAssignee(cur ? [ cur ] : [], next);
|
|
3132
|
+
changed && pickAndClose(changed);
|
|
3133
|
+
},
|
|
3059
3134
|
value: cur ? [ cur ] : []
|
|
3060
3135
|
}),
|
|
3061
3136
|
onDismiss: () => setOpen(!1),
|
|
@@ -3580,11 +3655,11 @@ function AssignActivityControl({instanceId: instanceId, state: state, assigneeId
|
|
|
3580
3655
|
setBusy(!0);
|
|
3581
3656
|
try {
|
|
3582
3657
|
selectedIds.has(memberId) ? await editFieldFor(instanceId, {
|
|
3583
|
-
target:
|
|
3658
|
+
target: workflowReact.editFieldTarget(field),
|
|
3584
3659
|
mode: "set",
|
|
3585
3660
|
value: members.filter(m => !(m.type === "user" && m.id === memberId))
|
|
3586
3661
|
}) : await editFieldFor(instanceId, {
|
|
3587
|
-
target:
|
|
3662
|
+
target: workflowReact.editFieldTarget(field),
|
|
3588
3663
|
mode: "append",
|
|
3589
3664
|
value: {
|
|
3590
3665
|
type: "user",
|
|
@@ -4013,8 +4088,8 @@ function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle,
|
|
|
4013
4088
|
});
|
|
4014
4089
|
}
|
|
4015
4090
|
|
|
4016
|
-
function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter}) {
|
|
4017
|
-
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 => {
|
|
4018
4093
|
if (busy) return !1;
|
|
4019
4094
|
setBusy(!0);
|
|
4020
4095
|
try {
|
|
@@ -4039,15 +4114,35 @@ function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter}) {
|
|
|
4039
4114
|
mode: "set",
|
|
4040
4115
|
value: next
|
|
4041
4116
|
}));
|
|
4042
|
-
}, toggleRow = row => {
|
|
4043
|
-
if (
|
|
4044
|
-
|
|
4045
|
-
|
|
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
|
+
}
|
|
4046
4132
|
const tick = row.tick;
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
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
|
+
}
|
|
4051
4146
|
}, addItem = label => appendTarget ? run(() => editFieldFor(instance._id, {
|
|
4052
4147
|
target: appendTarget,
|
|
4053
4148
|
mode: "append",
|
|
@@ -4164,7 +4259,7 @@ const ACTIONS_MENU_TRIGGER = {
|
|
|
4164
4259
|
padding: 2
|
|
4165
4260
|
};
|
|
4166
4261
|
|
|
4167
|
-
function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activity: activity, onCollectParams: onCollectParams}) {
|
|
4262
|
+
function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, onCollectParams: onCollectParams}) {
|
|
4168
4263
|
const rowKind = actionRowKind(actionEval), label = actionTriggerLabel(actionEval), {tone: tone, icon: icon} = actionButtonFace({
|
|
4169
4264
|
actionEval: actionEval,
|
|
4170
4265
|
activityName: activity
|
|
@@ -4174,7 +4269,9 @@ function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activit
|
|
|
4174
4269
|
instanceId: instanceId,
|
|
4175
4270
|
activity: activity,
|
|
4176
4271
|
action: actionEval.action.name,
|
|
4177
|
-
label: label
|
|
4272
|
+
label: label,
|
|
4273
|
+
surface: surface,
|
|
4274
|
+
viaMenu: !0
|
|
4178
4275
|
});
|
|
4179
4276
|
return rowKind.kind === "disabled" ? /* @__PURE__ */ jsxRuntime.jsx(ui.MenuItem, {
|
|
4180
4277
|
disabled: !0,
|
|
@@ -4210,7 +4307,7 @@ function rowShield(menuButton) {
|
|
|
4210
4307
|
});
|
|
4211
4308
|
}
|
|
4212
4309
|
|
|
4213
|
-
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}) {
|
|
4214
4311
|
const [paramsAction, setParamsAction] = react.useState(void 0), clusterPending = useActionClusterPending(), menuId = react.useId(), menuButton = /* @__PURE__ */ jsxRuntime.jsx(ui.MenuButton, {
|
|
4215
4312
|
button: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
4216
4313
|
...ACTIONS_MENU_TRIGGER,
|
|
@@ -4229,7 +4326,8 @@ function ActionsMenuButton({actions: actions, instanceId: instanceId, activity:
|
|
|
4229
4326
|
actionEval: a,
|
|
4230
4327
|
activity: activity,
|
|
4231
4328
|
instanceId: instanceId,
|
|
4232
|
-
onCollectParams: () => setParamsAction(a)
|
|
4329
|
+
onCollectParams: () => setParamsAction(a),
|
|
4330
|
+
surface: surface
|
|
4233
4331
|
}, a.action.name))
|
|
4234
4332
|
}),
|
|
4235
4333
|
popover: {
|
|
@@ -4245,7 +4343,9 @@ function ActionsMenuButton({actions: actions, instanceId: instanceId, activity:
|
|
|
4245
4343
|
actionEval: paramsAction,
|
|
4246
4344
|
activity: activity,
|
|
4247
4345
|
instanceId: instanceId,
|
|
4248
|
-
onClose: () => setParamsAction(void 0)
|
|
4346
|
+
onClose: () => setParamsAction(void 0),
|
|
4347
|
+
surface: surface,
|
|
4348
|
+
viaMenu: !0
|
|
4249
4349
|
})
|
|
4250
4350
|
}) : null ]
|
|
4251
4351
|
});
|
|
@@ -4261,7 +4361,8 @@ function TerminalFooter({actions: actions, activity: activity, instanceId: insta
|
|
|
4261
4361
|
children: /* @__PURE__ */ jsxRuntime.jsx(ActivityActionRow, {
|
|
4262
4362
|
actionEval: only,
|
|
4263
4363
|
activity: activity,
|
|
4264
|
-
instanceId: instanceId
|
|
4364
|
+
instanceId: instanceId,
|
|
4365
|
+
surface: "terminal-footer"
|
|
4265
4366
|
})
|
|
4266
4367
|
}) : /* @__PURE__ */ jsxRuntime.jsx(FittedActions, {
|
|
4267
4368
|
actions: actions,
|
|
@@ -4315,13 +4416,15 @@ function FittedActions({actions: actions, activity: activity, instanceId: instan
|
|
|
4315
4416
|
children: [ inline === void 0 ? null : actions.slice(0, inline).map(a => /* @__PURE__ */ jsxRuntime.jsx(ActivityActionRow, {
|
|
4316
4417
|
actionEval: a,
|
|
4317
4418
|
activity: activity,
|
|
4318
|
-
instanceId: instanceId
|
|
4419
|
+
instanceId: instanceId,
|
|
4420
|
+
surface: "terminal-footer"
|
|
4319
4421
|
}, a.action.name)), overflow.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ActionsMenuButton, {
|
|
4320
4422
|
actions: overflow,
|
|
4321
4423
|
activity: activity,
|
|
4322
4424
|
instanceId: instanceId,
|
|
4323
4425
|
label: MORE_ACTIONS_LABEL,
|
|
4324
|
-
mode: "default"
|
|
4426
|
+
mode: "default",
|
|
4427
|
+
surface: "terminal-footer"
|
|
4325
4428
|
}) : null ]
|
|
4326
4429
|
}) ]
|
|
4327
4430
|
});
|
|
@@ -4364,7 +4467,7 @@ function MeasureRow({actions: actions, activity: activity, onElement: onElement}
|
|
|
4364
4467
|
});
|
|
4365
4468
|
}
|
|
4366
4469
|
|
|
4367
|
-
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}) {
|
|
4368
4471
|
const detail = deriveActivityDetail({
|
|
4369
4472
|
entry: entry,
|
|
4370
4473
|
activityName: activityName
|
|
@@ -4386,6 +4489,13 @@ function ActivityDetailDialog({entry: entry, activityName: activityName, breadcr
|
|
|
4386
4489
|
onClose: onClose,
|
|
4387
4490
|
width: 1,
|
|
4388
4491
|
children: [
|
|
4492
|
+
/* @__PURE__ */ jsxRuntime.jsx(LogEventOnMount, {
|
|
4493
|
+
data: {
|
|
4494
|
+
instanceId: instanceId,
|
|
4495
|
+
source: source
|
|
4496
|
+
},
|
|
4497
|
+
event: WorkflowActivityDialogOpened
|
|
4498
|
+
}),
|
|
4389
4499
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
4390
4500
|
borderBottom: hasBody,
|
|
4391
4501
|
style: {
|
|
@@ -4493,7 +4603,8 @@ function TopActions({detail: detail, definition: definition, instanceId: instanc
|
|
|
4493
4603
|
children: [ p.actions.map(a => /* @__PURE__ */ jsxRuntime.jsx(ActivityActionRow, {
|
|
4494
4604
|
actionEval: a,
|
|
4495
4605
|
activity: activityName,
|
|
4496
|
-
instanceId: instanceId
|
|
4606
|
+
instanceId: instanceId,
|
|
4607
|
+
surface: "dialog-strip"
|
|
4497
4608
|
}, a.action.name)), p.manualTarget ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
4498
4609
|
as: "a",
|
|
4499
4610
|
fontSize: 1,
|
|
@@ -4529,7 +4640,8 @@ function FieldRow({field: field, detail: detail, entry: entry, activityName: act
|
|
|
4529
4640
|
scope: "activity",
|
|
4530
4641
|
field: field.name,
|
|
4531
4642
|
activity: activityName
|
|
4532
|
-
}
|
|
4643
|
+
},
|
|
4644
|
+
surface: "activity-dialog"
|
|
4533
4645
|
}) ]
|
|
4534
4646
|
});
|
|
4535
4647
|
if (field._type === "assignees") {
|
|
@@ -4682,29 +4794,7 @@ function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
|
4682
4794
|
});
|
|
4683
4795
|
}
|
|
4684
4796
|
|
|
4685
|
-
function
|
|
4686
|
-
const toast = useClosableToast();
|
|
4687
|
-
/* @__PURE__ */
|
|
4688
|
-
return jsxRuntime.jsx(ui.Button, {
|
|
4689
|
-
fontSize: 1,
|
|
4690
|
-
mode: "ghost",
|
|
4691
|
-
onClick: () => {
|
|
4692
|
-
navigator.clipboard.writeText(unreadableDocsReport(unreadable)).then(() => toast.push({
|
|
4693
|
-
status: "success",
|
|
4694
|
-
title: "Details copied"
|
|
4695
|
-
}), () => toast.push({
|
|
4696
|
-
status: "error",
|
|
4697
|
-
title: "Could not copy the details"
|
|
4698
|
-
}));
|
|
4699
|
-
},
|
|
4700
|
-
padding: 2,
|
|
4701
|
-
text: "Copy details"
|
|
4702
|
-
});
|
|
4703
|
-
}
|
|
4704
|
-
|
|
4705
|
-
function UnreadableDocsNote({unreadable: unreadable}) {
|
|
4706
|
-
if (unreadable.length === 0) return null;
|
|
4707
|
-
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}) {
|
|
4708
4798
|
/* @__PURE__ */
|
|
4709
4799
|
return jsxRuntime.jsxs(ui.Card, {
|
|
4710
4800
|
padding: 2,
|
|
@@ -4731,10 +4821,39 @@ function UnreadableDocsNote({unreadable: unreadable}) {
|
|
|
4731
4821
|
size: 1,
|
|
4732
4822
|
children: label
|
|
4733
4823
|
}) ]
|
|
4734
|
-
}),
|
|
4735
|
-
|
|
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, {
|
|
4736
4854
|
unreadable: unreadable
|
|
4737
|
-
})
|
|
4855
|
+
}),
|
|
4856
|
+
label: label
|
|
4738
4857
|
});
|
|
4739
4858
|
}
|
|
4740
4859
|
|
|
@@ -5056,6 +5175,25 @@ function buildStartRequest(args) {
|
|
|
5056
5175
|
};
|
|
5057
5176
|
}
|
|
5058
5177
|
|
|
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
|
+
|
|
5059
5197
|
function findResumeEntry(args) {
|
|
5060
5198
|
return args.entries.find(e => workflowEngine.isUnprimed(e.instance) && e.instance.definition === args.definitionName && (args.heldInstanceId === void 0 || e.instance._id === args.heldInstanceId));
|
|
5061
5199
|
}
|
|
@@ -5071,7 +5209,8 @@ function classifyStartError(err) {
|
|
|
5071
5209
|
instance: err.instance,
|
|
5072
5210
|
description: describeError(err.cause)
|
|
5073
5211
|
} : err instanceof workflowEngine.StartNotAllowedError ? {
|
|
5074
|
-
kind: "not-allowed"
|
|
5212
|
+
kind: "not-allowed",
|
|
5213
|
+
description: err.unmetRequirements.map(requirementCopy).join("; ")
|
|
5075
5214
|
} : {
|
|
5076
5215
|
kind: "failed",
|
|
5077
5216
|
description: describeError(err)
|
|
@@ -5084,22 +5223,30 @@ function boundReleaseId(mapping, selectedReleaseId) {
|
|
|
5084
5223
|
|
|
5085
5224
|
function startGate(args) {
|
|
5086
5225
|
const {mapping: mapping, mappingIssue: mappingIssue, selectedReleaseId: selectedReleaseId, releaseActive: releaseActive} = args;
|
|
5087
|
-
|
|
5226
|
+
if (mappingIssue !== void 0) return {
|
|
5088
5227
|
blocked: !0,
|
|
5089
5228
|
tooltip: mappingIssue
|
|
5090
|
-
}
|
|
5229
|
+
};
|
|
5230
|
+
if (mapping.perspectiveField?.required === !0 && selectedReleaseId === void 0) return {
|
|
5091
5231
|
blocked: !0,
|
|
5092
5232
|
tooltip: "Pick a release in the perspective dropdown first"
|
|
5093
|
-
}
|
|
5233
|
+
};
|
|
5234
|
+
if (mapping.perspectiveField !== void 0 && selectedReleaseId !== void 0 && !releaseActive) return {
|
|
5094
5235
|
blocked: !0,
|
|
5095
5236
|
tooltip: `Release "${selectedReleaseId}" is not active — only active releases can host new workflows`
|
|
5096
|
-
}
|
|
5237
|
+
};
|
|
5238
|
+
if (args.startFilterFailed === !0) return {
|
|
5097
5239
|
blocked: !0,
|
|
5098
5240
|
tooltip: `${mapping.label} can't start for this document right now — the workflow's start condition isn't met`
|
|
5099
|
-
}
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
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 {
|
|
5103
5250
|
blocked: !1,
|
|
5104
5251
|
tooltip: void 0
|
|
5105
5252
|
};
|
|
@@ -5122,10 +5269,10 @@ async function preflightFilter(args) {
|
|
|
5122
5269
|
});
|
|
5123
5270
|
}
|
|
5124
5271
|
|
|
5125
|
-
async function
|
|
5126
|
-
const {
|
|
5127
|
-
return workflowEngine.
|
|
5128
|
-
|
|
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,
|
|
5129
5276
|
definition: {
|
|
5130
5277
|
name: mapping.definition
|
|
5131
5278
|
},
|
|
@@ -5134,6 +5281,25 @@ async function preflightAllowed(args) {
|
|
|
5134
5281
|
})).outcome === "unsatisfied";
|
|
5135
5282
|
}
|
|
5136
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
|
+
|
|
5137
5303
|
async function performStart(args) {
|
|
5138
5304
|
const {mapping: mapping, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId} = args, releaseId = boundReleaseId(mapping, selectedReleaseId);
|
|
5139
5305
|
try {
|
|
@@ -5160,7 +5326,21 @@ async function performStart(args) {
|
|
|
5160
5326
|
}
|
|
5161
5327
|
|
|
5162
5328
|
function useStartVerdicts(args) {
|
|
5163
|
-
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));
|
|
5164
5344
|
return {
|
|
5165
5345
|
filterFailed: useFilterVerdict({
|
|
5166
5346
|
mapping: mapping,
|
|
@@ -5168,25 +5348,15 @@ function useStartVerdicts(args) {
|
|
|
5168
5348
|
docId: docId,
|
|
5169
5349
|
initialValue: initialValue,
|
|
5170
5350
|
selectedReleaseId: selectedReleaseId,
|
|
5171
|
-
skip: skip
|
|
5351
|
+
skip: skip,
|
|
5352
|
+
fetchDataset: fetchDataset
|
|
5172
5353
|
}),
|
|
5173
|
-
|
|
5174
|
-
mapping: mapping,
|
|
5175
|
-
allowed: start?.allowed,
|
|
5176
|
-
docId: docId,
|
|
5177
|
-
selectedReleaseId: selectedReleaseId,
|
|
5178
|
-
skip: skip
|
|
5179
|
-
})
|
|
5354
|
+
unmetRequirement: unmetRequirement
|
|
5180
5355
|
};
|
|
5181
5356
|
}
|
|
5182
5357
|
|
|
5183
5358
|
function preflightScope(args) {
|
|
5184
|
-
const {
|
|
5185
|
-
tag: tag,
|
|
5186
|
-
filter: {
|
|
5187
|
-
includeCompleted: !0
|
|
5188
|
-
}
|
|
5189
|
-
});
|
|
5359
|
+
const {tag: tag, mapping: mapping, contentResource: contentResource, docId: docId, fetchDataset: fetchDataset} = args;
|
|
5190
5360
|
return {
|
|
5191
5361
|
tag: tag,
|
|
5192
5362
|
now: /* @__PURE__ */ (new Date).toISOString(),
|
|
@@ -5195,15 +5365,12 @@ function preflightScope(args) {
|
|
|
5195
5365
|
contentResource: contentResource,
|
|
5196
5366
|
documentId: docId
|
|
5197
5367
|
}).id,
|
|
5198
|
-
fetchDataset:
|
|
5199
|
-
groq: query,
|
|
5200
|
-
params: params
|
|
5201
|
-
})).map(workflowEngine.assertReadableModel)
|
|
5368
|
+
fetchDataset: fetchDataset
|
|
5202
5369
|
};
|
|
5203
5370
|
}
|
|
5204
5371
|
|
|
5205
5372
|
function useFilterVerdict(args) {
|
|
5206
|
-
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;
|
|
5207
5374
|
return react.useEffect(() => {
|
|
5208
5375
|
if (skip || filter === void 0 || docId === void 0) {
|
|
5209
5376
|
setFailed(!1);
|
|
@@ -5217,57 +5384,112 @@ function useFilterVerdict(args) {
|
|
|
5217
5384
|
candidateValue: candidateValue,
|
|
5218
5385
|
selectedReleaseId: selectedReleaseId,
|
|
5219
5386
|
scope: preflightScope({
|
|
5220
|
-
engine: engine,
|
|
5221
5387
|
tag: binding.tag,
|
|
5222
5388
|
mapping: mapping,
|
|
5223
5389
|
contentResource: binding.contentResource,
|
|
5224
|
-
docId: docId
|
|
5390
|
+
docId: docId,
|
|
5391
|
+
fetchDataset: fetchDataset
|
|
5225
5392
|
})
|
|
5226
5393
|
}).catch(showRowOnError("start.filter", mapping)).then(verdict => {
|
|
5227
5394
|
cancelled || setFailed(verdict);
|
|
5228
5395
|
}), () => {
|
|
5229
5396
|
cancelled = !0;
|
|
5230
5397
|
};
|
|
5231
|
-
}, [ filter, rootRead, skip, docId, selectedReleaseId, candidateValue, mapping,
|
|
5398
|
+
}, [ filter, rootRead, skip, docId, selectedReleaseId, candidateValue, mapping, binding, fetchDataset ]),
|
|
5232
5399
|
failed;
|
|
5233
5400
|
}
|
|
5234
5401
|
|
|
5235
|
-
function
|
|
5236
|
-
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([]);
|
|
5237
5419
|
return react.useEffect(() => {
|
|
5238
|
-
if (skip ||
|
|
5239
|
-
setRefused(
|
|
5420
|
+
if (skip || requirements.length === 0 || docId === void 0) {
|
|
5421
|
+
setRefused(current => current.length === 0 ? current : []);
|
|
5240
5422
|
return;
|
|
5241
5423
|
}
|
|
5242
5424
|
let cancelled = !1;
|
|
5243
|
-
const
|
|
5425
|
+
const fields = preflightSeedFields({
|
|
5244
5426
|
mapping: mapping,
|
|
5245
|
-
|
|
5427
|
+
docId: docId,
|
|
5246
5428
|
selectedReleaseId: selectedReleaseId,
|
|
5247
5429
|
contentResource: binding.contentResource,
|
|
5248
5430
|
declaredFields: mappingFields.get(mappingKey(mapping))
|
|
5249
|
-
},
|
|
5250
|
-
|
|
5251
|
-
initFields: [],
|
|
5252
|
-
values: {}
|
|
5253
|
-
}).map(field => [ field.name, field.value ]));
|
|
5254
|
-
return preflightAllowed({
|
|
5255
|
-
allowed: allowed,
|
|
5431
|
+
}), scope = preflightScope({
|
|
5432
|
+
tag: binding.tag,
|
|
5256
5433
|
mapping: mapping,
|
|
5257
|
-
|
|
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
|
+
}),
|
|
5258
5480
|
scope: preflightScope({
|
|
5259
|
-
engine: engine,
|
|
5260
5481
|
tag: binding.tag,
|
|
5261
5482
|
mapping: mapping,
|
|
5483
|
+
docId: docId,
|
|
5262
5484
|
contentResource: binding.contentResource,
|
|
5263
|
-
|
|
5485
|
+
fetchDataset: () => Promise.resolve(entries.map(({instance: instance}) => workflowEngine.projectStartSliceRow(instance)))
|
|
5264
5486
|
})
|
|
5265
|
-
}).catch(showRowOnError("
|
|
5487
|
+
}).catch(showRowOnError("singleSubject requirement", mapping)).then(verdict => {
|
|
5266
5488
|
cancelled || setRefused(verdict);
|
|
5267
5489
|
}), () => {
|
|
5268
5490
|
cancelled = !0;
|
|
5269
5491
|
};
|
|
5270
|
-
}, [
|
|
5492
|
+
}, [ dedupe, start, skip, docId, selectedReleaseId, entries, mapping, binding, mappingFields ]),
|
|
5271
5493
|
refused;
|
|
5272
5494
|
}
|
|
5273
5495
|
|
|
@@ -5277,7 +5499,7 @@ function showRowOnError(key, mapping) {
|
|
|
5277
5499
|
}
|
|
5278
5500
|
|
|
5279
5501
|
function useStartWorkflow(args) {
|
|
5280
|
-
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({
|
|
5281
5503
|
engine: engine
|
|
5282
5504
|
}), [starting, setStarting] = react.useState(!1), {selectedReleaseId: selectedReleaseId} = sanity.usePerspective(), releaseActive = sanity.useIsReleaseActive(), startBlock = mappingStarts.get(mappingKey(mapping)), hidden = workflowEngine.startKindOf({
|
|
5283
5505
|
start: startBlock
|
|
@@ -5285,12 +5507,13 @@ function useStartWorkflow(args) {
|
|
|
5285
5507
|
entries: entries,
|
|
5286
5508
|
definitionName: mapping.definition,
|
|
5287
5509
|
heldInstanceId: void 0
|
|
5288
|
-
}) !== void 0, {filterFailed: filterFailed,
|
|
5510
|
+
}) !== void 0, {filterFailed: filterFailed, unmetRequirement: unmetRequirement} = useStartVerdicts({
|
|
5289
5511
|
mapping: mapping,
|
|
5290
5512
|
start: startBlock,
|
|
5291
5513
|
docId: docId,
|
|
5292
5514
|
initialValue: initialValue,
|
|
5293
5515
|
selectedReleaseId: selectedReleaseId,
|
|
5516
|
+
entries: entries,
|
|
5294
5517
|
hidden: hidden,
|
|
5295
5518
|
resumable: resumable
|
|
5296
5519
|
}), {blocked: blocked, tooltip: tooltip} = startGate({
|
|
@@ -5299,7 +5522,9 @@ function useStartWorkflow(args) {
|
|
|
5299
5522
|
selectedReleaseId: selectedReleaseId,
|
|
5300
5523
|
releaseActive: releaseActive,
|
|
5301
5524
|
startFilterFailed: filterFailed,
|
|
5302
|
-
|
|
5525
|
+
...unmetRequirement !== void 0 ? {
|
|
5526
|
+
unmetRequirement: unmetRequirement
|
|
5527
|
+
} : {}
|
|
5303
5528
|
});
|
|
5304
5529
|
return {
|
|
5305
5530
|
blocked: blocked,
|
|
@@ -5321,7 +5546,10 @@ function useStartWorkflow(args) {
|
|
|
5321
5546
|
title: "Could not persist the document before starting",
|
|
5322
5547
|
description: describeError(err)
|
|
5323
5548
|
}),
|
|
5324
|
-
openStartDialog: openStartDialog
|
|
5549
|
+
openStartDialog: request => openStartDialog({
|
|
5550
|
+
...request,
|
|
5551
|
+
source: source
|
|
5552
|
+
})
|
|
5325
5553
|
});
|
|
5326
5554
|
} finally {
|
|
5327
5555
|
setStarting(!1);
|
|
@@ -5331,11 +5559,12 @@ function useStartWorkflow(args) {
|
|
|
5331
5559
|
};
|
|
5332
5560
|
}
|
|
5333
5561
|
|
|
5334
|
-
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"}) {
|
|
5335
5563
|
const {blocked: blocked, tooltip: tooltip, hidden: hidden, starting: starting, start: start} = useStartWorkflow({
|
|
5336
5564
|
mapping: mapping,
|
|
5337
5565
|
docId: docId,
|
|
5338
|
-
initialValue: initialValue
|
|
5566
|
+
initialValue: initialValue,
|
|
5567
|
+
source: source
|
|
5339
5568
|
});
|
|
5340
5569
|
if (hidden) return null;
|
|
5341
5570
|
const startLabel = label ?? `Start ${mapping.label}`, button = /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
@@ -5368,7 +5597,7 @@ function useStartableMappings(mappings) {
|
|
|
5368
5597
|
}) !== "autonomous");
|
|
5369
5598
|
}
|
|
5370
5599
|
|
|
5371
|
-
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"}) {
|
|
5372
5601
|
const menuId = react.useId(), startable = useStartableMappings(mappings), [first] = startable;
|
|
5373
5602
|
if (first === void 0) return null;
|
|
5374
5603
|
if (startable.length === 1) /* @__PURE__ */
|
|
@@ -5381,6 +5610,7 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5381
5610
|
},
|
|
5382
5611
|
mapping: first,
|
|
5383
5612
|
mode: mode,
|
|
5613
|
+
source: source,
|
|
5384
5614
|
tone: tone
|
|
5385
5615
|
});
|
|
5386
5616
|
const menuLabel = label ?? "Start a workflow";
|
|
@@ -5406,7 +5636,8 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5406
5636
|
children: startable.map(mapping => /* @__PURE__ */ jsxRuntime.jsx(StartWorkflowMenuItem, {
|
|
5407
5637
|
docId: docId,
|
|
5408
5638
|
initialValue: initialValue,
|
|
5409
|
-
mapping: mapping
|
|
5639
|
+
mapping: mapping,
|
|
5640
|
+
source: source
|
|
5410
5641
|
}, mappingKey(mapping)))
|
|
5411
5642
|
}),
|
|
5412
5643
|
popover: {
|
|
@@ -5417,11 +5648,12 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5417
5648
|
});
|
|
5418
5649
|
}
|
|
5419
5650
|
|
|
5420
|
-
function StartWorkflowMenuItem({mapping: mapping, docId: docId, initialValue: initialValue}) {
|
|
5651
|
+
function StartWorkflowMenuItem({mapping: mapping, docId: docId, initialValue: initialValue, source: source}) {
|
|
5421
5652
|
const {blocked: blocked, tooltip: tooltip, starting: starting, start: start} = useStartWorkflow({
|
|
5422
5653
|
mapping: mapping,
|
|
5423
5654
|
docId: docId,
|
|
5424
|
-
initialValue: initialValue
|
|
5655
|
+
initialValue: initialValue,
|
|
5656
|
+
source: source
|
|
5425
5657
|
}), item = /* @__PURE__ */ jsxRuntime.jsx(ui.MenuItem, {
|
|
5426
5658
|
disabled: blocked || starting || !docId,
|
|
5427
5659
|
onClick: () => {
|
|
@@ -5476,13 +5708,15 @@ function RowTerminalActions({actions: actions, activity: activity, instanceId: i
|
|
|
5476
5708
|
mode: "ghost",
|
|
5477
5709
|
inButtonCard: !0
|
|
5478
5710
|
},
|
|
5479
|
-
instanceId: instanceId
|
|
5711
|
+
instanceId: instanceId,
|
|
5712
|
+
surface: "inline-row"
|
|
5480
5713
|
}) : /* @__PURE__ */ jsxRuntime.jsx(ActionsMenuButton, {
|
|
5481
5714
|
actions: actions,
|
|
5482
5715
|
activity: activity,
|
|
5483
5716
|
inButtonCard: !0,
|
|
5484
5717
|
instanceId: instanceId,
|
|
5485
|
-
label: "Select action"
|
|
5718
|
+
label: "Select action",
|
|
5719
|
+
surface: "inline-row"
|
|
5486
5720
|
})
|
|
5487
5721
|
}) : null;
|
|
5488
5722
|
}
|
|
@@ -5580,7 +5814,8 @@ function ForMeList({entry: entry, work: work, identity: identity, onOpenActivity
|
|
|
5580
5814
|
filter: {
|
|
5581
5815
|
kind: "mine",
|
|
5582
5816
|
identity: identity
|
|
5583
|
-
}
|
|
5817
|
+
},
|
|
5818
|
+
surface: "document-view-for-me"
|
|
5584
5819
|
}) : null ]
|
|
5585
5820
|
})
|
|
5586
5821
|
});
|
|
@@ -5789,7 +6024,8 @@ function TodoFieldDialog({entry: entry, scope: scope, field: field, title: title
|
|
|
5789
6024
|
kind: "field",
|
|
5790
6025
|
scope: scope,
|
|
5791
6026
|
field: field
|
|
5792
|
-
}
|
|
6027
|
+
},
|
|
6028
|
+
surface: "todo-field-dialog"
|
|
5793
6029
|
})
|
|
5794
6030
|
})
|
|
5795
6031
|
});
|
|
@@ -6002,7 +6238,7 @@ function PillButton({children: children, pill: pill, hintDisabled: hintDisabled
|
|
|
6002
6238
|
}
|
|
6003
6239
|
|
|
6004
6240
|
function useFieldCommit({entry: entry, editability: editability}) {
|
|
6005
|
-
const {editFieldFor: editFieldFor} = useWorkflowContext(), target =
|
|
6241
|
+
const {editFieldFor: editFieldFor} = useWorkflowContext(), target = workflowReact.editFieldTarget(editability);
|
|
6006
6242
|
return {
|
|
6007
6243
|
set: value => editFieldFor(entry.instance._id, {
|
|
6008
6244
|
target: target,
|
|
@@ -6218,8 +6454,9 @@ function AssigneePill({entry: entry, pill: pill, editability: editability}) {
|
|
|
6218
6454
|
/* @__PURE__ */
|
|
6219
6455
|
return jsxRuntime.jsx(PillPopover, {
|
|
6220
6456
|
content: /* @__PURE__ */ jsxRuntime.jsx(AssigneePicker, {
|
|
6221
|
-
|
|
6222
|
-
|
|
6457
|
+
onChange: next => {
|
|
6458
|
+
const changed = changedAssignee(current ? [ current ] : [], next);
|
|
6459
|
+
changed && (setOpen(!1), pick(changed));
|
|
6223
6460
|
},
|
|
6224
6461
|
value: current ? [ current ] : []
|
|
6225
6462
|
}),
|
|
@@ -6238,10 +6475,8 @@ function AssigneesPill({entry: entry, pill: pill, editability: editability}) {
|
|
|
6238
6475
|
/* @__PURE__ */
|
|
6239
6476
|
return jsxRuntime.jsx(PillPopover, {
|
|
6240
6477
|
content: /* @__PURE__ */ jsxRuntime.jsx(AssigneePicker, {
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
const next = current.some(a => sameAssignee(a, assignee)) ? current.filter(a => !sameAssignee(a, assignee)) : [ ...current, assignee ];
|
|
6244
|
-
save(() => set(next));
|
|
6478
|
+
onChange: next => {
|
|
6479
|
+
saving || save(() => set(next));
|
|
6245
6480
|
},
|
|
6246
6481
|
value: current
|
|
6247
6482
|
}),
|
|
@@ -6346,15 +6581,15 @@ function Hairline({weight: weight, style: style}) {
|
|
|
6346
6581
|
});
|
|
6347
6582
|
}
|
|
6348
6583
|
|
|
6349
|
-
function CollapsibleBand({header: header, children: children, background: background = !1, defaultOpen: defaultOpen = !0, sticky: sticky = !1, title: title}) {
|
|
6350
|
-
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";
|
|
6351
6586
|
/* @__PURE__ */
|
|
6352
6587
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
6353
6588
|
gap: 1,
|
|
6354
6589
|
children: [
|
|
6355
6590
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
6356
6591
|
onDoubleClick: event => {
|
|
6357
|
-
event.target instanceof Element && event.target.closest("a, button") ||
|
|
6592
|
+
event.target instanceof Element && event.target.closest("a, button") || toggle();
|
|
6358
6593
|
},
|
|
6359
6594
|
padding: 1,
|
|
6360
6595
|
radius: 3,
|
|
@@ -6375,7 +6610,7 @@ function CollapsibleBand({header: header, children: children, background: backgr
|
|
|
6375
6610
|
fontSize: 1,
|
|
6376
6611
|
icon: open ? ChevronDown.ChevronDownIcon : ChevronRight.ChevronRightIcon,
|
|
6377
6612
|
mode: "bleed",
|
|
6378
|
-
onClick:
|
|
6613
|
+
onClick: toggle,
|
|
6379
6614
|
padding: 2
|
|
6380
6615
|
}), header ]
|
|
6381
6616
|
})
|
|
@@ -7286,7 +7521,12 @@ function StageSection({entry: entry, onOpenActivity: onOpenActivity}) {
|
|
|
7286
7521
|
}
|
|
7287
7522
|
|
|
7288
7523
|
const VIEW_TAB_CODEC = workflowsTabCodec([ "overview", "for-me" ]), WorkflowsView = props => {
|
|
7289
|
-
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);
|
|
7290
7530
|
if (entries.length === 0) return discoveryInvalid !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
7291
7531
|
padding: 4,
|
|
7292
7532
|
children: /* @__PURE__ */ jsxRuntime.jsx(InvalidDocNotice, {
|
|
@@ -7364,7 +7604,7 @@ function useOpenActivity(entries) {
|
|
|
7364
7604
|
}
|
|
7365
7605
|
|
|
7366
7606
|
function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappings: docTypeMappings, initialValue: initialValue}) {
|
|
7367
|
-
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), booting = useDelayedFlag(active.some(e => !e.ready && e.invalid === void 0), BOOT_CUE_DELAY_MS), 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, {
|
|
7368
7608
|
defaultOpen: landingDefaultOpen(landing, e.instance._id),
|
|
7369
7609
|
entry: e,
|
|
7370
7610
|
onOpenActivity: activityName => setOpenActivity({
|
|
@@ -7398,6 +7638,7 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7398
7638
|
initialValue: initialValue,
|
|
7399
7639
|
mappings: docTypeMappings,
|
|
7400
7640
|
mode: "bleed",
|
|
7641
|
+
source: "document-view-header",
|
|
7401
7642
|
tone: "default"
|
|
7402
7643
|
})
|
|
7403
7644
|
}),
|
|
@@ -7406,7 +7647,12 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7406
7647
|
/* @__PURE__ */ jsxRuntime.jsx(TabSwitch, {
|
|
7407
7648
|
ariaControls: `${panelId}-panel`,
|
|
7408
7649
|
idPrefix: panelId,
|
|
7409
|
-
onSelect:
|
|
7650
|
+
onSelect: next => {
|
|
7651
|
+
next !== view && telemetry2.log(WorkflowDocumentViewOpened, {
|
|
7652
|
+
tab: next,
|
|
7653
|
+
via: "tab-switch"
|
|
7654
|
+
}), setView(next);
|
|
7655
|
+
},
|
|
7410
7656
|
options: [ {
|
|
7411
7657
|
value: "overview",
|
|
7412
7658
|
label: "Overview"
|
|
@@ -7480,6 +7726,7 @@ function OverviewEmptyState({mappings: mappings, docId: docId, initialValue: ini
|
|
|
7480
7726
|
label: "Start workflow",
|
|
7481
7727
|
mappings: mappings,
|
|
7482
7728
|
mode: "ghost",
|
|
7729
|
+
source: "document-view-empty-state",
|
|
7483
7730
|
tone: "default"
|
|
7484
7731
|
})
|
|
7485
7732
|
},
|
|
@@ -7513,7 +7760,8 @@ function SectionActivityDialog({entry: entry, activityName: activityName, onClos
|
|
|
7513
7760
|
breadcrumb: instanceBreadcrumb(instance, definition),
|
|
7514
7761
|
definition: definition,
|
|
7515
7762
|
entry: entry,
|
|
7516
|
-
onClose: onClose
|
|
7763
|
+
onClose: onClose,
|
|
7764
|
+
source: "document-view"
|
|
7517
7765
|
});
|
|
7518
7766
|
}
|
|
7519
7767
|
|
|
@@ -7595,13 +7843,61 @@ function workflowIssue(args) {
|
|
|
7595
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.`;
|
|
7596
7844
|
}
|
|
7597
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
|
+
};
|
|
7892
|
+
}
|
|
7893
|
+
|
|
7598
7894
|
function contentDocumentTypes(schema) {
|
|
7599
7895
|
return schema.getTypeNames().filter(name => schema.get(name)?.type?.name === "document" && !WORKFLOW_SYSTEM_TYPES.includes(name));
|
|
7600
7896
|
}
|
|
7601
7897
|
|
|
7602
7898
|
async function readDeployedDefinitions(engine) {
|
|
7603
7899
|
return (await engine.query({
|
|
7604
|
-
groq: workflowEngine.
|
|
7900
|
+
groq: workflowEngine.latestDefinitionsGroq()
|
|
7605
7901
|
})).map(workflowEngine.assertReadableModel);
|
|
7606
7902
|
}
|
|
7607
7903
|
|
|
@@ -7936,7 +8232,7 @@ function WorkflowProvider(props) {
|
|
|
7936
8232
|
setSeeded(prev => new Map(prev).set(instance._id, instance));
|
|
7937
8233
|
}, []), [startRequest2, setStartRequest] = react.useState(void 0), openStartDialog = react.useCallback(r => setStartRequest(r), []), closeStartDialog = react.useCallback(() => setStartRequest(void 0), []), [entriesStore] = react.useState(createEntriesStore);
|
|
7938
8234
|
react.useEffect(() => () => entriesStore.dispose(), [ entriesStore ]);
|
|
7939
|
-
const onReport = react.useCallback((instanceId, report) => {
|
|
8235
|
+
const previewStore = sanity.useDocumentPreviewStore(), actualTypes = react.useMemo(() => createActualTypeProbeStore(previewStore), [ previewStore ]), onReport = react.useCallback((instanceId, report) => {
|
|
7940
8236
|
entriesStore.report(instanceId, report);
|
|
7941
8237
|
}, [ entriesStore ]), drainRef = react.useRef(void 0), drainCommitted = react.useCallback(async instanceId => {
|
|
7942
8238
|
try {
|
|
@@ -8019,6 +8315,7 @@ function WorkflowProvider(props) {
|
|
|
8019
8315
|
unregister: unregister,
|
|
8020
8316
|
isDocResolved: isDocResolved,
|
|
8021
8317
|
entries: entriesStore,
|
|
8318
|
+
actualTypes: actualTypes,
|
|
8022
8319
|
requestInstance: requestInstance,
|
|
8023
8320
|
releaseInstance: releaseInstance,
|
|
8024
8321
|
requestEvaluation: requestEvaluation,
|
|
@@ -8045,7 +8342,7 @@ function WorkflowProvider(props) {
|
|
|
8045
8342
|
effectHandlers: engine.effectHandlers,
|
|
8046
8343
|
autoStartByType: autoStartByType,
|
|
8047
8344
|
autoStartDefinitions: autoStartDefinitions
|
|
8048
|
-
}), [ register, unregister, isDocResolved, entriesStore, requestInstance, releaseInstance, requestEvaluation, releaseEvaluation, seedInstance, openStartDialog, closeStartDialog, startRequest2, loading, discoveryInvalid, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding, mappings, issues, starts, fields, latestVersions, autoStartByType, autoStartDefinitions ]);
|
|
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 ]);
|
|
8049
8346
|
/* @__PURE__ */
|
|
8050
8347
|
return jsxRuntime.jsxs(WorkflowContext.Provider, {
|
|
8051
8348
|
value: value,
|
|
@@ -8145,13 +8442,13 @@ function logOnce(messages, logged) {
|
|
|
8145
8442
|
|
|
8146
8443
|
function AssigneesInput({value: value, onChange: onChange}) {
|
|
8147
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 => {
|
|
8148
|
-
value.some(x => sameAssignee(x, a)) || onChange([ ...value, a ]);
|
|
8445
|
+
value.some(x => workflowComponents.sameAssignee(x, a)) || onChange([ ...value, a ]);
|
|
8149
8446
|
}, remove = i => onChange(value.filter((_, idx) => idx !== i)), toggleUser = id => {
|
|
8150
8447
|
const user = {
|
|
8151
8448
|
type: "user",
|
|
8152
8449
|
id: id
|
|
8153
8450
|
};
|
|
8154
|
-
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);
|
|
8155
8452
|
};
|
|
8156
8453
|
/* @__PURE__ */
|
|
8157
8454
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
@@ -8518,12 +8815,12 @@ function DocRefsFieldInput({entry: entry, mappedType: mappedType, value: value,
|
|
|
8518
8815
|
}
|
|
8519
8816
|
|
|
8520
8817
|
function NotesStartInput({onChange: onChange}) {
|
|
8521
|
-
const
|
|
8818
|
+
const selfActor = useSelfActor(), [body, setBody] = react.useState(""), update = next => {
|
|
8522
8819
|
setBody(next);
|
|
8523
8820
|
const trimmed = next.trim();
|
|
8524
8821
|
onChange(trimmed === "" ? [] : [ noteRow({
|
|
8525
8822
|
body: trimmed,
|
|
8526
|
-
actor:
|
|
8823
|
+
actor: selfActor,
|
|
8527
8824
|
at: /* @__PURE__ */ (new Date).toISOString()
|
|
8528
8825
|
}) ]);
|
|
8529
8826
|
};
|
|
@@ -8732,7 +9029,7 @@ function handleStartError(args) {
|
|
|
8732
9029
|
toast.push({
|
|
8733
9030
|
status: "warning",
|
|
8734
9031
|
title: `${label} can't be started right now`,
|
|
8735
|
-
description:
|
|
9032
|
+
description: outcome.description
|
|
8736
9033
|
});
|
|
8737
9034
|
return;
|
|
8738
9035
|
}
|
|
@@ -8744,7 +9041,7 @@ function handleStartError(args) {
|
|
|
8744
9041
|
}
|
|
8745
9042
|
|
|
8746
9043
|
function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
8747
|
-
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({
|
|
8748
9045
|
entries: entries,
|
|
8749
9046
|
definitionName: definitionName,
|
|
8750
9047
|
heldInstanceId: heldInstanceId,
|
|
@@ -8767,7 +9064,10 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
|
8767
9064
|
[name]: v
|
|
8768
9065
|
})), heldInstanceId !== void 0 && declineResume();
|
|
8769
9066
|
}, onStart = async () => {
|
|
8770
|
-
|
|
9067
|
+
telemetry2.log(WorkflowStartDialogSubmitted, {
|
|
9068
|
+
source: request.source,
|
|
9069
|
+
resumed: resuming
|
|
9070
|
+
}), setAttempt({
|
|
8771
9071
|
resume: resumeEntry
|
|
8772
9072
|
});
|
|
8773
9073
|
const instanceId = resumeEntry?.instance._id ?? heldInstanceId ?? workflowEngine.instanceDocId(binding.tag);
|
|
@@ -8847,8 +9147,9 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
|
8847
9147
|
}
|
|
8848
9148
|
|
|
8849
9149
|
function StartWorkflowDialog({request: request, onClose: onClose}) {
|
|
8850
|
-
|
|
8851
|
-
|
|
9150
|
+
return useLogEventOnMount(WorkflowStartDialogOpened, {
|
|
9151
|
+
source: request.source
|
|
9152
|
+
}), /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, {
|
|
8852
9153
|
header: `Start ${request.label}`,
|
|
8853
9154
|
id: "start-workflow",
|
|
8854
9155
|
onClose: onClose,
|
|
@@ -8987,7 +9288,7 @@ function AutoStartGate(props) {
|
|
|
8987
9288
|
}
|
|
8988
9289
|
|
|
8989
9290
|
function AutoStartDriver(props) {
|
|
8990
|
-
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({
|
|
8991
9292
|
engine: engine
|
|
8992
9293
|
}), {selectedReleaseId: selectedReleaseId} = sanity.usePerspective(), {entries: entries} = useWorkflowsForDocument(rawDocId), docId = csm.getPublishedId(rawDocId), valueRef = react.useRef(value);
|
|
8993
9294
|
valueRef.current = value;
|
|
@@ -9001,7 +9302,7 @@ function AutoStartDriver(props) {
|
|
|
9001
9302
|
if (held !== void 0) return held;
|
|
9002
9303
|
const id = workflowEngine.instanceDocId(binding.tag);
|
|
9003
9304
|
return instanceIds.current.set(workflow, id), id;
|
|
9004
|
-
}, [ 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) => {
|
|
9005
9306
|
if (!firedRef.current) {
|
|
9006
9307
|
firedRef.current = !0, setFired(!0);
|
|
9007
9308
|
try {
|
|
@@ -9013,20 +9314,25 @@ function AutoStartDriver(props) {
|
|
|
9013
9314
|
releaseId: selectedReleaseId
|
|
9014
9315
|
} : {}
|
|
9015
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
|
+
});
|
|
9016
9332
|
const {failure: failure2} = await runStarts({
|
|
9017
9333
|
engine: engine,
|
|
9018
9334
|
seed: seedInstance,
|
|
9019
|
-
requests:
|
|
9020
|
-
workflows: pendingRef.current,
|
|
9021
|
-
definitions: autoStartDefinitions,
|
|
9022
|
-
subject: {
|
|
9023
|
-
docId: docId,
|
|
9024
|
-
type: docType
|
|
9025
|
-
},
|
|
9026
|
-
contentResource: binding.contentResource,
|
|
9027
|
-
values: values,
|
|
9028
|
-
instanceIdFor: instanceIdFor
|
|
9029
|
-
})
|
|
9335
|
+
requests: requests
|
|
9030
9336
|
});
|
|
9031
9337
|
failure2 !== void 0 && setFailure(failure2);
|
|
9032
9338
|
} catch (err) {
|
|
@@ -9035,7 +9341,7 @@ function AutoStartDriver(props) {
|
|
|
9035
9341
|
setSettled(!0);
|
|
9036
9342
|
}
|
|
9037
9343
|
}
|
|
9038
|
-
}, [ 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(() => {
|
|
9039
9345
|
firedRef.current = !1, setFired(!1), setSettled(!1), setFailure(void 0);
|
|
9040
9346
|
}, []), action = autoStartAction({
|
|
9041
9347
|
resolved: definitionsResolved && isDocResolved(docId),
|
|
@@ -9045,7 +9351,7 @@ function AutoStartDriver(props) {
|
|
|
9045
9351
|
settled: settled
|
|
9046
9352
|
});
|
|
9047
9353
|
return react.useEffect(() => {
|
|
9048
|
-
action === "silent-start" && startAll({});
|
|
9354
|
+
action === "silent-start" && startAll({}, "silent");
|
|
9049
9355
|
}, [ action, startAll ]), failure !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(AutoStartFailure, {
|
|
9050
9356
|
message: failure,
|
|
9051
9357
|
onProceed: () => setFailure(void 0),
|
|
@@ -9057,7 +9363,7 @@ function AutoStartDriver(props) {
|
|
|
9057
9363
|
docType: docType,
|
|
9058
9364
|
inputs: inputs,
|
|
9059
9365
|
onStart: values => {
|
|
9060
|
-
startAll(values);
|
|
9366
|
+
startAll(values, "collect");
|
|
9061
9367
|
},
|
|
9062
9368
|
starting: fired,
|
|
9063
9369
|
workflowCount: pending.length
|
|
@@ -9279,7 +9585,9 @@ function finishedLinesOf(entries) {
|
|
|
9279
9585
|
}
|
|
9280
9586
|
|
|
9281
9587
|
function WorkflowFormStrip(props) {
|
|
9282
|
-
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);
|
|
9283
9591
|
/* @__PURE__ */
|
|
9284
9592
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
9285
9593
|
gap: 4,
|
|
@@ -9313,7 +9621,8 @@ function StripLines({active: active, docId: docId, finished: finished, initialVa
|
|
|
9313
9621
|
initialValue: initialValue,
|
|
9314
9622
|
label: "Start workflow",
|
|
9315
9623
|
mappings: mappings,
|
|
9316
|
-
mode: "bleed"
|
|
9624
|
+
mode: "bleed",
|
|
9625
|
+
source: "form-strip"
|
|
9317
9626
|
})
|
|
9318
9627
|
}) : null ]
|
|
9319
9628
|
});
|
|
@@ -9645,6 +9954,8 @@ exports.ActivityRow = ActivityRow;
|
|
|
9645
9954
|
|
|
9646
9955
|
exports.BreadcrumbTail = BreadcrumbTail;
|
|
9647
9956
|
|
|
9957
|
+
exports.CautionNote = CautionNote;
|
|
9958
|
+
|
|
9648
9959
|
exports.CollapsibleBand = CollapsibleBand;
|
|
9649
9960
|
|
|
9650
9961
|
exports.DismissablePopover = DismissablePopover;
|
|
@@ -9679,6 +9990,14 @@ exports.TrailingHairline = TrailingHairline;
|
|
|
9679
9990
|
|
|
9680
9991
|
exports.UnreadableDocsNote = UnreadableDocsNote;
|
|
9681
9992
|
|
|
9993
|
+
exports.WORKFLOW_API_VERSION = WORKFLOW_API_VERSION;
|
|
9994
|
+
|
|
9995
|
+
exports.WorkflowInstanceDetailViewed = WorkflowInstanceDetailViewed;
|
|
9996
|
+
|
|
9997
|
+
exports.WorkflowTaskFiltersApplied = WorkflowTaskFiltersApplied;
|
|
9998
|
+
|
|
9999
|
+
exports.WorkflowToolOpened = WorkflowToolOpened;
|
|
10000
|
+
|
|
9682
10001
|
exports.activityRowProps = activityRowProps;
|
|
9683
10002
|
|
|
9684
10003
|
exports.assigneeUserIdsOf = assigneeUserIdsOf;
|
|
@@ -9693,8 +10012,6 @@ exports.definitionSnapshotOf = definitionSnapshotOf;
|
|
|
9693
10012
|
|
|
9694
10013
|
exports.describeError = describeError;
|
|
9695
10014
|
|
|
9696
|
-
exports.editTargetOf = editTargetOf;
|
|
9697
|
-
|
|
9698
10015
|
exports.findActivity = findActivity;
|
|
9699
10016
|
|
|
9700
10017
|
exports.findActivityNode = findActivityNode;
|
|
@@ -9739,8 +10056,12 @@ exports.stopRowMouseDown = stopRowMouseDown;
|
|
|
9739
10056
|
|
|
9740
10057
|
exports.useAssignmentIdentity = useAssignmentIdentity;
|
|
9741
10058
|
|
|
10059
|
+
exports.useClosableToast = useClosableToast;
|
|
10060
|
+
|
|
9742
10061
|
exports.useDefinition = useDefinition;
|
|
9743
10062
|
|
|
10063
|
+
exports.useLogEventOnMount = useLogEventOnMount;
|
|
10064
|
+
|
|
9744
10065
|
exports.useProjectMembers = useProjectMembers;
|
|
9745
10066
|
|
|
9746
10067
|
exports.useSaveField = useSaveField;
|