@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
package/dist/_chunks-es/index.js
CHANGED
|
@@ -4,11 +4,13 @@ import { TimelineIcon } from "@sanity/icons/Timeline";
|
|
|
4
4
|
|
|
5
5
|
import { Tooltip, Box, Stack, Text, useClickOutsideEvent, Popover, Flex, TextInput, Button, Select, Checkbox, Autocomplete, Card, TextArea, useToast, Dialog, Switch, TextSkeleton, Code, Spinner, useTheme_v2, Badge, MenuButton, Menu, MenuItem, useElementSize, TabList, Tab, TabPanel, MenuDivider } from "@sanity/ui";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { editFieldTarget, useWorkflowTelemetry, useRefcountedIds } from "@sanity/workflow-react";
|
|
8
|
+
|
|
9
|
+
import { createContext, useContext, useEffect, useSyncExternalStore, useCallback, useRef, useMemo, useState, Fragment as Fragment$1, createElement, isValidElement, useId, useLayoutEffect, Component, lazy, Suspense } from "react";
|
|
8
10
|
|
|
9
11
|
import { usePaneRouter } from "sanity/structure";
|
|
10
12
|
|
|
11
|
-
import { tryParseGdr, resourceFromParsed, latestDeployedDefinitions, isStartableDefinition, isSubjectEntry, isInputSourced, acceptsDocumentType, missingRequiredInputs, initialFieldIssues, gdrRef, releaseRef, refKindAcceptsTypes, rejectedRefTypes, ActionDisabledError, MutationGuardDeniedError, errorMessage, findOpenStageEntry, actionRendering, terminalState,
|
|
13
|
+
import { tryParseGdr, resourceFromParsed, latestDeployedDefinitions, isStartableDefinition, isSubjectEntry, isInputSourced, acceptsDocumentType, missingRequiredInputs, initialFieldIssues, gdrRef, releaseRef, refKindAcceptsTypes, rejectedRefTypes, ActionDisabledError, MutationGuardDeniedError, errorMessage, findOpenStageEntry, actionRendering, terminalState, isTodoListEntry, isTodoListItem, isTerminalActivityStatus, describeCondition, sentenceCase, checklistLines, findCurrentActivityEntry, ENGINE_API_VERSION, WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE, scalarValidationIssues, classifyPrincipalId, toBareId, isSingleDocRefEntry, isGdr, resolveFieldEntry, isSingleDocRefKind, isNotesEntry, parseDefinitionSnapshot, instancesQuery, assertReadableModel, projectStartSliceRow, isUnprimed, StartNotSettledError, StartNotAllowedError, humanize, unboundRequirementReads, explainStartRequirement, singleSubjectRequirementRefused, evaluateStartFilter, startKindOf, hasSingleSubjectRequirement, readsRootDocument, isTerminalStage, DEFAULT_TRANSITION_WHEN, latestDefinitionsGroq, gdrFromResource, subscriptionDocumentsForInstance, aclPathForResource, definitionLookupGroq, instanceDocId, documentActionDenials } from "@sanity/workflow-engine";
|
|
12
14
|
|
|
13
15
|
import { CheckmarkIcon } from "@sanity/icons/Checkmark";
|
|
14
16
|
|
|
@@ -16,16 +18,18 @@ import { CloseIcon } from "@sanity/icons/Close";
|
|
|
16
18
|
|
|
17
19
|
import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
|
|
18
20
|
|
|
19
|
-
import {
|
|
21
|
+
import { sameAssignee, projectMemberRow, ClearableDatePicker, MemberPicker as MemberPicker$1, AssigneePicker as AssigneePicker$1, MemberAvatar, AssigneeBadges as AssigneeBadges$1, AssigneeBadge as AssigneeBadge$1, ProgressBar, MemberAvatarGroup, clampProgress, progressCaption, DatePicker, roleListLabel } from "@sanity/workflow-components";
|
|
22
|
+
|
|
23
|
+
import { getPublishedId, getDraftId } from "@sanity/client/csm";
|
|
24
|
+
|
|
25
|
+
import { defineEvent } from "@sanity/telemetry";
|
|
20
26
|
|
|
21
27
|
import { useStudioProjectUsers, useStudioObserver, useWorkflowEngine, useWorkflowInstances, useWorkflowSession } from "@sanity/workflow-studio";
|
|
22
28
|
|
|
23
|
-
import { useCurrentUser, SanityDefaultPreview, Preview, useValuePreview, useClient, useSchema, useWorkspace, TextWithTone, usePerspective, useIsReleaseActive, useActiveReleases, useTemplates, useInitialValueResolverContext, resolveInitialValue, definePlugin, isObjectInputProps } from "sanity";
|
|
29
|
+
import { useCurrentUser, SanityDefaultPreview, Preview, useValuePreview, useClient, useSchema, useWorkspace, TextWithTone, usePerspective, useIsReleaseActive, useDocumentPreviewStore, useActiveReleases, useTemplates, useInitialValueResolverContext, resolveInitialValue, definePlugin, isObjectInputProps } from "sanity";
|
|
24
30
|
|
|
25
31
|
import { CalendarIcon } from "@sanity/icons/Calendar";
|
|
26
32
|
|
|
27
|
-
import { ClearableDatePicker, MemberPicker as MemberPicker$1, AssigneePicker as AssigneePicker$1, MemberAvatar, AssigneeBadges as AssigneeBadges$1, AssigneeBadge as AssigneeBadge$1, ProgressBar, MemberAvatarGroup, clampProgress, progressCaption, DatePicker, roleListLabel } from "@sanity/workflow-components";
|
|
28
|
-
|
|
29
33
|
import { UserIcon } from "@sanity/icons/User";
|
|
30
34
|
|
|
31
35
|
import { SearchIcon } from "@sanity/icons/Search";
|
|
@@ -70,7 +74,9 @@ import { EllipsisHorizontalIcon } from "@sanity/icons/EllipsisHorizontal";
|
|
|
70
74
|
|
|
71
75
|
import { ArrowUpIcon } from "@sanity/icons/ArrowUp";
|
|
72
76
|
|
|
73
|
-
import {
|
|
77
|
+
import { of } from "rxjs";
|
|
78
|
+
|
|
79
|
+
import { switchMap, distinctUntilChanged } from "rxjs/operators";
|
|
74
80
|
|
|
75
81
|
import { TransferIcon } from "@sanity/icons/Transfer";
|
|
76
82
|
|
|
@@ -485,67 +491,6 @@ function isLiveEntry(entry) {
|
|
|
485
491
|
return terminalState(entry.instance) === "in-flight";
|
|
486
492
|
}
|
|
487
493
|
|
|
488
|
-
const WORKFLOW_API_VERSION = ENGINE_API_VERSION, WORKFLOW_SYSTEM_TYPES = [ WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE ];
|
|
489
|
-
|
|
490
|
-
function editTargetOf(field) {
|
|
491
|
-
return {
|
|
492
|
-
scope: field.scope,
|
|
493
|
-
field: field.name,
|
|
494
|
-
...field.activity ? {
|
|
495
|
-
activity: field.activity
|
|
496
|
-
} : {}
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
const EMPTY_ENTRIES = [], WorkflowContext = createContext(null);
|
|
501
|
-
|
|
502
|
-
function useWorkflowContext() {
|
|
503
|
-
const value = useContext(WorkflowContext);
|
|
504
|
-
if (!value) throw new Error("useWorkflowContext must render inside the workflow plugin provider");
|
|
505
|
-
return value;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
function useWorkflowsForDocument(rawId) {
|
|
509
|
-
return useDocumentWorkflowEntries(rawId, !0);
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
function useCommittedWorkflowsForDocument(rawId) {
|
|
513
|
-
return useDocumentWorkflowEntries(rawId, !1);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
function useDocumentWorkflowEntries(rawId, evaluate) {
|
|
517
|
-
const {register: register, unregister: unregister, requestEvaluation: requestEvaluation, releaseEvaluation: releaseEvaluation, entries: entries} = useWorkflowContext(), docId = rawId ? getPublishedId(rawId) : void 0;
|
|
518
|
-
useEffect(() => {
|
|
519
|
-
if (docId) return register(docId), () => unregister(docId);
|
|
520
|
-
}, [ docId, register, unregister ]);
|
|
521
|
-
const list = useSyncExternalStore(entries.subscribe, useCallback(() => docId ? entries.getDocument(docId) : EMPTY_ENTRIES, [ entries, docId ])), evaluationKey = evaluate ? list.map(entry => entry.instance._id).join("\0") : "";
|
|
522
|
-
return useEffect(() => {
|
|
523
|
-
if (!evaluate) return;
|
|
524
|
-
const ids = evaluationKey === "" ? [] : evaluationKey.split("\0");
|
|
525
|
-
for (const id of ids) requestEvaluation(id);
|
|
526
|
-
return () => {
|
|
527
|
-
for (const id of ids) releaseEvaluation(id);
|
|
528
|
-
};
|
|
529
|
-
}, [ evaluate, evaluationKey, requestEvaluation, releaseEvaluation ]), {
|
|
530
|
-
docId: docId,
|
|
531
|
-
entries: list
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
function useHeldWorkflowEntry(instanceId) {
|
|
536
|
-
const {entries: entries} = useWorkflowContext();
|
|
537
|
-
return useSyncExternalStore(entries.subscribe, useCallback(() => instanceId ? entries.getInstance(instanceId) : void 0, [ entries, instanceId ]));
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
function useWorkflowInstanceEntry(instanceId, options = {}) {
|
|
541
|
-
const {requestInstance: requestInstance, releaseInstance: releaseInstance, requestEvaluation: requestEvaluation, releaseEvaluation: releaseEvaluation} = useWorkflowContext(), evaluate = options.evaluate ?? !0;
|
|
542
|
-
return useEffect(() => {
|
|
543
|
-
if (instanceId) return requestInstance(instanceId), () => releaseInstance(instanceId);
|
|
544
|
-
}, [ instanceId, requestInstance, releaseInstance ]), useEffect(() => {
|
|
545
|
-
if (!(!instanceId || !evaluate)) return requestEvaluation(instanceId), () => releaseEvaluation(instanceId);
|
|
546
|
-
}, [ instanceId, evaluate, requestEvaluation, releaseEvaluation ]), useHeldWorkflowEntry(instanceId);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
494
|
const isTodoDone = item => item.status === "done", toggledTodoStatus = item => isTodoDone(item) ? "open" : "done";
|
|
550
495
|
|
|
551
496
|
function isTodoOverdue(item, today = /* @__PURE__ */ new Date) {
|
|
@@ -621,7 +566,7 @@ function buildTickIndex(evaluation) {
|
|
|
621
566
|
function todoFieldEditability(args) {
|
|
622
567
|
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));
|
|
623
568
|
return match ? match.editable ? {
|
|
624
|
-
editTarget:
|
|
569
|
+
editTarget: editFieldTarget(match)
|
|
625
570
|
} : match.disabledReason === void 0 ? {} : {
|
|
626
571
|
editDisabledReason: match.disabledReason
|
|
627
572
|
} : {};
|
|
@@ -686,8 +631,8 @@ function assigneeMatches(member, who) {
|
|
|
686
631
|
return member.type === "user" ? member.id === who.userId : who.roles.includes(member.role);
|
|
687
632
|
}
|
|
688
633
|
|
|
689
|
-
function
|
|
690
|
-
return
|
|
634
|
+
function changedAssignee(current, next) {
|
|
635
|
+
return next.find(item => !current.some(existing => sameAssignee(item, existing))) ?? current.find(item => !next.some(existing => sameAssignee(item, existing)));
|
|
691
636
|
}
|
|
692
637
|
|
|
693
638
|
function isAssigneeShape(value) {
|
|
@@ -1062,6 +1007,112 @@ function deriveActivityDetail(args) {
|
|
|
1062
1007
|
};
|
|
1063
1008
|
}
|
|
1064
1009
|
|
|
1010
|
+
const WORKFLOW_API_VERSION = ENGINE_API_VERSION, WORKFLOW_SYSTEM_TYPES = [ WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE ], EMPTY_ENTRIES = [], WorkflowContext = createContext(null);
|
|
1011
|
+
|
|
1012
|
+
function useWorkflowContext() {
|
|
1013
|
+
const value = useContext(WorkflowContext);
|
|
1014
|
+
if (!value) throw new Error("useWorkflowContext must render inside the workflow plugin provider");
|
|
1015
|
+
return value;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
function useWorkflowsForDocument(rawId) {
|
|
1019
|
+
return useDocumentWorkflowEntries(rawId, !0);
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
function useCommittedWorkflowsForDocument(rawId) {
|
|
1023
|
+
return useDocumentWorkflowEntries(rawId, !1);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
function useDocumentWorkflowEntries(rawId, evaluate) {
|
|
1027
|
+
const {register: register, unregister: unregister, requestEvaluation: requestEvaluation, releaseEvaluation: releaseEvaluation, entries: entries} = useWorkflowContext(), docId = rawId ? getPublishedId(rawId) : void 0;
|
|
1028
|
+
useEffect(() => {
|
|
1029
|
+
if (docId) return register(docId), () => unregister(docId);
|
|
1030
|
+
}, [ docId, register, unregister ]);
|
|
1031
|
+
const list = useSyncExternalStore(entries.subscribe, useCallback(() => docId ? entries.getDocument(docId) : EMPTY_ENTRIES, [ entries, docId ])), evaluationKey = evaluate ? list.map(entry => entry.instance._id).join("\0") : "";
|
|
1032
|
+
return useEffect(() => {
|
|
1033
|
+
if (!evaluate) return;
|
|
1034
|
+
const ids = evaluationKey === "" ? [] : evaluationKey.split("\0");
|
|
1035
|
+
for (const id of ids) requestEvaluation(id);
|
|
1036
|
+
return () => {
|
|
1037
|
+
for (const id of ids) releaseEvaluation(id);
|
|
1038
|
+
};
|
|
1039
|
+
}, [ evaluate, evaluationKey, requestEvaluation, releaseEvaluation ]), {
|
|
1040
|
+
docId: docId,
|
|
1041
|
+
entries: list
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
function useHeldWorkflowEntry(instanceId) {
|
|
1046
|
+
const {entries: entries} = useWorkflowContext();
|
|
1047
|
+
return useSyncExternalStore(entries.subscribe, useCallback(() => instanceId ? entries.getInstance(instanceId) : void 0, [ entries, instanceId ]));
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
function useWorkflowInstanceEntry(instanceId, options = {}) {
|
|
1051
|
+
const {requestInstance: requestInstance, releaseInstance: releaseInstance, requestEvaluation: requestEvaluation, releaseEvaluation: releaseEvaluation} = useWorkflowContext(), evaluate = options.evaluate ?? !0;
|
|
1052
|
+
return useEffect(() => {
|
|
1053
|
+
if (instanceId) return requestInstance(instanceId), () => releaseInstance(instanceId);
|
|
1054
|
+
}, [ instanceId, requestInstance, releaseInstance ]), useEffect(() => {
|
|
1055
|
+
if (!(!instanceId || !evaluate)) return requestEvaluation(instanceId), () => releaseEvaluation(instanceId);
|
|
1056
|
+
}, [ instanceId, evaluate, requestEvaluation, releaseEvaluation ]), useHeldWorkflowEntry(instanceId);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
const WorkflowToolOpened = defineEvent({
|
|
1060
|
+
name: "Editorial Workflows Studio Plugin Tool Opened",
|
|
1061
|
+
version: 1,
|
|
1062
|
+
description: "The Workflows tool was opened or its tab was switched"
|
|
1063
|
+
}), WorkflowDocumentViewOpened = defineEvent({
|
|
1064
|
+
name: "Editorial Workflows Studio Plugin Document View Opened",
|
|
1065
|
+
version: 1,
|
|
1066
|
+
description: "The Workflows document view was opened or its tab was switched"
|
|
1067
|
+
}), WorkflowInstanceDetailViewed = defineEvent({
|
|
1068
|
+
name: "Editorial Workflows Studio Plugin Instance Detail Viewed",
|
|
1069
|
+
version: 1,
|
|
1070
|
+
description: "The Workflows tool's per-instance detail view was opened"
|
|
1071
|
+
}), WorkflowFormStripClicked = defineEvent({
|
|
1072
|
+
name: "Editorial Workflows Studio Plugin Form Strip Clicked",
|
|
1073
|
+
version: 1,
|
|
1074
|
+
description: "The form strip's instance line was clicked, opening the document view"
|
|
1075
|
+
}), WorkflowStartDialogOpened = defineEvent({
|
|
1076
|
+
name: "Editorial Workflows Studio Plugin Start Dialog Opened",
|
|
1077
|
+
version: 1,
|
|
1078
|
+
description: "The start-workflow dialog was opened"
|
|
1079
|
+
}), WorkflowStartDialogSubmitted = defineEvent({
|
|
1080
|
+
name: "Editorial Workflows Studio Plugin Start Dialog Submitted",
|
|
1081
|
+
version: 1,
|
|
1082
|
+
description: "The start-workflow dialog's confirm was pressed"
|
|
1083
|
+
}), WorkflowAutoStartRan = defineEvent({
|
|
1084
|
+
name: "Editorial Workflows Studio Plugin Auto Start Ran",
|
|
1085
|
+
version: 1,
|
|
1086
|
+
description: "A fresh document's auto-start ran — one start request per configured workflow"
|
|
1087
|
+
}), WorkflowActionControlUsed = defineEvent({
|
|
1088
|
+
name: "Editorial Workflows Studio Plugin Action Control Used",
|
|
1089
|
+
version: 1,
|
|
1090
|
+
description: "An action-firing control was used, attributed to its UI surface"
|
|
1091
|
+
}), WorkflowActivityDialogOpened = defineEvent({
|
|
1092
|
+
name: "Editorial Workflows Studio Plugin Activity Dialog Opened",
|
|
1093
|
+
version: 1,
|
|
1094
|
+
description: "The activity detail dialog was opened"
|
|
1095
|
+
}), WorkflowTaskFiltersApplied = defineEvent({
|
|
1096
|
+
name: "Editorial Workflows Studio Plugin Task Filters Applied",
|
|
1097
|
+
version: 1,
|
|
1098
|
+
description: "The tool's task-filter menu closed with a changed selection"
|
|
1099
|
+
}), WorkflowTodoToggled = defineEvent({
|
|
1100
|
+
name: "Editorial Workflows Studio Plugin Todo Toggled",
|
|
1101
|
+
version: 1,
|
|
1102
|
+
description: "A todo checkbox was toggled, attributed to its UI surface and write seam"
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
function useLogEventOnMount(event, data) {
|
|
1106
|
+
const telemetry = useWorkflowTelemetry(), logged = useRef(!1);
|
|
1107
|
+
useEffect(() => {
|
|
1108
|
+
logged.current || (logged.current = !0, telemetry.log(event, data));
|
|
1109
|
+
}, [ telemetry, event, data ]);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
function LogEventOnMount(props) {
|
|
1113
|
+
return useLogEventOnMount(props.event, props.data), null;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1065
1116
|
function isEmptyValue(value) {
|
|
1066
1117
|
return value == null || value === "" || Array.isArray(value) && value.length === 0;
|
|
1067
1118
|
}
|
|
@@ -1104,8 +1155,12 @@ function memberIndex(members) {
|
|
|
1104
1155
|
|
|
1105
1156
|
const selfUserFor = (id, me) => me != null && me.id === id ? me : void 0;
|
|
1106
1157
|
|
|
1158
|
+
function globalIdOf(users, projectScopedId) {
|
|
1159
|
+
return users.find(user => user.membership.id === projectScopedId)?.profile?.sanityUserId ?? projectScopedId;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1107
1162
|
function userDisplayFor(args) {
|
|
1108
|
-
const member = memberIndex(args.members).get(
|
|
1163
|
+
const matchId = args.matchId ?? args.id, member = memberIndex(args.members).get(matchId), self = selfUserFor(matchId, args.me);
|
|
1109
1164
|
return {
|
|
1110
1165
|
id: args.id,
|
|
1111
1166
|
name: member?.displayName ?? self?.name ?? args.id,
|
|
@@ -1114,28 +1169,52 @@ function userDisplayFor(args) {
|
|
|
1114
1169
|
}
|
|
1115
1170
|
|
|
1116
1171
|
function useUserDisplays(ids) {
|
|
1117
|
-
const {members: members} = useProjectMembers(),
|
|
1172
|
+
const {members: members} = useProjectMembers(), {users: users} = useStudioProjectUsers(), meRaw = useCurrentUser(), me = useMemo(() => meRaw === null ? null : {
|
|
1173
|
+
...meRaw,
|
|
1174
|
+
id: globalIdOf(users, meRaw.id)
|
|
1175
|
+
}, [ meRaw, users ]);
|
|
1118
1176
|
return useMemo(() => ids.map(id => userDisplayFor({
|
|
1119
1177
|
id: id,
|
|
1120
1178
|
members: members,
|
|
1121
|
-
me: me
|
|
1122
|
-
|
|
1179
|
+
me: me,
|
|
1180
|
+
matchId: globalIdOf(users, id)
|
|
1181
|
+
})), [ ids, me, members, users ]);
|
|
1123
1182
|
}
|
|
1124
1183
|
|
|
1125
1184
|
function useUserDisplay(id) {
|
|
1126
|
-
const
|
|
1127
|
-
return
|
|
1185
|
+
const ids = useMemo(() => [ id ], [ id ]), [display] = useUserDisplays(ids);
|
|
1186
|
+
return display ?? {
|
|
1187
|
+
name: id,
|
|
1188
|
+
imageUrl: void 0
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
const warnedNotMember = /* @__PURE__ */ new Set;
|
|
1193
|
+
|
|
1194
|
+
function useBridgedSelf() {
|
|
1195
|
+
const me = useCurrentUser(), {users: users, loading: loading} = useStudioProjectUsers();
|
|
1196
|
+
if (!me || loading) return;
|
|
1197
|
+
const classified = classifyPrincipalId(me.id), id = users.find(user => user.membership.id === me.id)?.profile?.sanityUserId ?? classified.globalId ?? (classified.namespace === "project" ? void 0 : me.id);
|
|
1198
|
+
if (id === void 0) {
|
|
1199
|
+
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.`));
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
return {
|
|
1128
1203
|
id: id,
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1204
|
+
roles: me.roles ?? []
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
function useSelfActor() {
|
|
1209
|
+
const self = useBridgedSelf();
|
|
1210
|
+
return self === void 0 ? void 0 : personActor(self);
|
|
1132
1211
|
}
|
|
1133
1212
|
|
|
1134
1213
|
function useAssignmentIdentity() {
|
|
1135
|
-
const
|
|
1136
|
-
if (
|
|
1137
|
-
userId:
|
|
1138
|
-
roles:
|
|
1214
|
+
const self = useBridgedSelf();
|
|
1215
|
+
if (self !== void 0) return {
|
|
1216
|
+
userId: self.id,
|
|
1217
|
+
roles: self.roles.map(r => r.name)
|
|
1139
1218
|
};
|
|
1140
1219
|
}
|
|
1141
1220
|
|
|
@@ -1144,16 +1223,13 @@ const projectMembersByUsers = /* @__PURE__ */ new WeakMap;
|
|
|
1144
1223
|
function projectMembersFrom(users) {
|
|
1145
1224
|
const cached = projectMembersByUsers.get(users);
|
|
1146
1225
|
if (cached) return cached;
|
|
1147
|
-
const members = users.map(({membership: membership, profile: profile}) => ({
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
imageUrl: profile.imageUrl
|
|
1155
|
-
} : {},
|
|
1156
|
-
roles: (membership.roles ?? []).map(role => role.name)
|
|
1226
|
+
const members = users.map(({membership: membership, profile: profile}) => projectMemberRow({
|
|
1227
|
+
membershipId: membership.id,
|
|
1228
|
+
roles: membership.roles,
|
|
1229
|
+
sanityUserId: profile?.sanityUserId,
|
|
1230
|
+
displayName: profile?.displayName,
|
|
1231
|
+
email: profile?.email,
|
|
1232
|
+
imageUrl: profile?.imageUrl ?? void 0
|
|
1157
1233
|
}));
|
|
1158
1234
|
return projectMembersByUsers.set(users, members), members;
|
|
1159
1235
|
}
|
|
@@ -1481,12 +1557,12 @@ function MemberPicker({selectedIds: selectedIds, onSelect: onSelect, unassignRow
|
|
|
1481
1557
|
});
|
|
1482
1558
|
}
|
|
1483
1559
|
|
|
1484
|
-
function AssigneePicker({value: value,
|
|
1560
|
+
function AssigneePicker({value: value, onChange: onChange}) {
|
|
1485
1561
|
const state = useProjectMembers();
|
|
1486
1562
|
/* @__PURE__ */
|
|
1487
1563
|
return jsx(AssigneePicker$1, {
|
|
1488
1564
|
...state,
|
|
1489
|
-
|
|
1565
|
+
onChange: onChange,
|
|
1490
1566
|
value: value
|
|
1491
1567
|
});
|
|
1492
1568
|
}
|
|
@@ -1816,7 +1892,7 @@ function useActionClusterPending() {
|
|
|
1816
1892
|
}
|
|
1817
1893
|
|
|
1818
1894
|
function useFireAction(args) {
|
|
1819
|
-
const {instanceId: instanceId, activity: activity, action: action, label: label} = args, {fireActionFor: fireActionFor} = useWorkflowContext(), toast = useClosableToast(), cluster = useActionClusterLock(), [localPending, setLocalPending] = useState(!1), pending = localPending || cluster?.pending === !0;
|
|
1895
|
+
const {instanceId: instanceId, activity: activity, action: action, label: label, surface: surface, viaMenu: viaMenu} = args, {fireActionFor: fireActionFor} = useWorkflowContext(), telemetry = useWorkflowTelemetry(), toast = useClosableToast(), cluster = useActionClusterLock(), [localPending, setLocalPending] = useState(!1), pending = localPending || cluster?.pending === !0;
|
|
1820
1896
|
return {
|
|
1821
1897
|
fire: useCallback(async params => {
|
|
1822
1898
|
if (pending) return !1;
|
|
@@ -1831,6 +1907,11 @@ function useFireAction(args) {
|
|
|
1831
1907
|
}), toast.push({
|
|
1832
1908
|
status: "success",
|
|
1833
1909
|
title: `${label} done`
|
|
1910
|
+
}), telemetry.log(WorkflowActionControlUsed, {
|
|
1911
|
+
instanceId: instanceId,
|
|
1912
|
+
surface: surface,
|
|
1913
|
+
viaMenu: viaMenu,
|
|
1914
|
+
success: !0
|
|
1834
1915
|
}), !0;
|
|
1835
1916
|
} catch (err) {
|
|
1836
1917
|
return console.error(`[workflow-studio-plugin] firing "${action}" on "${activity}" failed:`, err),
|
|
@@ -1838,11 +1919,16 @@ function useFireAction(args) {
|
|
|
1838
1919
|
status: "error",
|
|
1839
1920
|
title: `${label} failed`,
|
|
1840
1921
|
description: describeError(err)
|
|
1922
|
+
}), telemetry.log(WorkflowActionControlUsed, {
|
|
1923
|
+
instanceId: instanceId,
|
|
1924
|
+
surface: surface,
|
|
1925
|
+
viaMenu: viaMenu,
|
|
1926
|
+
success: !1
|
|
1841
1927
|
}), !1;
|
|
1842
1928
|
} finally {
|
|
1843
1929
|
setLocalPending(!1), cluster?.onFireChange(!1);
|
|
1844
1930
|
}
|
|
1845
|
-
}, [ fireActionFor, instanceId, activity, action, label, pending, toast, cluster ]),
|
|
1931
|
+
}, [ fireActionFor, instanceId, activity, action, label, pending, toast, cluster, telemetry, surface, viaMenu ]),
|
|
1846
1932
|
pending: pending
|
|
1847
1933
|
};
|
|
1848
1934
|
}
|
|
@@ -1883,12 +1969,14 @@ function RowClickShield({active: active, children: children}) {
|
|
|
1883
1969
|
});
|
|
1884
1970
|
}
|
|
1885
1971
|
|
|
1886
|
-
function FireButton({instanceId: instanceId, activity: activity, action: action, label: label, mode: mode = "default", chrome: chrome, tone: tone = "default", icon: icon}) {
|
|
1972
|
+
function FireButton({instanceId: instanceId, activity: activity, action: action, label: label, surface: surface, mode: mode = "default", chrome: chrome, tone: tone = "default", icon: icon}) {
|
|
1887
1973
|
const {fire: fire, pending: pending} = useFireAction({
|
|
1888
1974
|
instanceId: instanceId,
|
|
1889
1975
|
activity: activity,
|
|
1890
1976
|
action: action,
|
|
1891
|
-
label: label
|
|
1977
|
+
label: label,
|
|
1978
|
+
surface: surface,
|
|
1979
|
+
viaMenu: !1
|
|
1892
1980
|
}), handleClick = e => {
|
|
1893
1981
|
chrome?.inButtonCard === !0 && e.stopPropagation(), !pending && fire();
|
|
1894
1982
|
};
|
|
@@ -1909,7 +1997,7 @@ function FireButton({instanceId: instanceId, activity: activity, action: action,
|
|
|
1909
1997
|
});
|
|
1910
1998
|
}
|
|
1911
1999
|
|
|
1912
|
-
function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
2000
|
+
function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
1913
2001
|
const rowKind = actionRowKind(actionEval);
|
|
1914
2002
|
return rowKind.kind === "disabled" ? /* @__PURE__ */ jsx(DisabledActionButton, {
|
|
1915
2003
|
actionEval: actionEval,
|
|
@@ -1919,12 +2007,14 @@ function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, acti
|
|
|
1919
2007
|
actionEval: actionEval,
|
|
1920
2008
|
instanceId: instanceId,
|
|
1921
2009
|
activity: activity,
|
|
1922
|
-
chrome: chrome
|
|
2010
|
+
chrome: chrome,
|
|
2011
|
+
surface: surface
|
|
1923
2012
|
}) : /* @__PURE__ */ jsx(ParamsActionButton, {
|
|
1924
2013
|
actionEval: actionEval,
|
|
1925
2014
|
instanceId: instanceId,
|
|
1926
2015
|
activity: activity,
|
|
1927
|
-
chrome: chrome
|
|
2016
|
+
chrome: chrome,
|
|
2017
|
+
surface: surface
|
|
1928
2018
|
});
|
|
1929
2019
|
}
|
|
1930
2020
|
|
|
@@ -1949,7 +2039,7 @@ function DisabledActionButton({actionEval: actionEval, activity: activity, chrom
|
|
|
1949
2039
|
}) : button;
|
|
1950
2040
|
}
|
|
1951
2041
|
|
|
1952
|
-
function PlainActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
2042
|
+
function PlainActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
1953
2043
|
const {action: action} = actionEval, label = actionLabel(action), btn = actionButtonFace({
|
|
1954
2044
|
actionEval: actionEval,
|
|
1955
2045
|
activityName: activity
|
|
@@ -1961,6 +2051,7 @@ function PlainActionButton({actionEval: actionEval, instanceId: instanceId, acti
|
|
|
1961
2051
|
mode: btn.mode,
|
|
1962
2052
|
activity: activity,
|
|
1963
2053
|
chrome: chrome,
|
|
2054
|
+
surface: surface,
|
|
1964
2055
|
tone: btn.tone
|
|
1965
2056
|
});
|
|
1966
2057
|
return action.description ? /* @__PURE__ */ jsx(HoverHint, {
|
|
@@ -1969,12 +2060,14 @@ function PlainActionButton({actionEval: actionEval, instanceId: instanceId, acti
|
|
|
1969
2060
|
}) : button;
|
|
1970
2061
|
}
|
|
1971
2062
|
|
|
1972
|
-
function ParamsActionDialog({actionEval: actionEval, instanceId: instanceId, activity: activity, onClose: onClose}) {
|
|
2063
|
+
function ParamsActionDialog({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, viaMenu: viaMenu, onClose: onClose}) {
|
|
1973
2064
|
const {action: action} = actionEval, label = actionLabel(action), decls = action.params ?? [], [values, setValues] = useState({}), {fire: fire, pending: pending} = useFireAction({
|
|
1974
2065
|
instanceId: instanceId,
|
|
1975
2066
|
activity: activity,
|
|
1976
2067
|
action: action.name,
|
|
1977
|
-
label: label
|
|
2068
|
+
label: label,
|
|
2069
|
+
surface: surface,
|
|
2070
|
+
viaMenu: viaMenu
|
|
1978
2071
|
}), built = buildParams(decls, values), confirm = async () => {
|
|
1979
2072
|
await fire(built.params) && onClose();
|
|
1980
2073
|
};
|
|
@@ -2029,7 +2122,7 @@ function ParamsActionDialog({actionEval: actionEval, instanceId: instanceId, act
|
|
|
2029
2122
|
});
|
|
2030
2123
|
}
|
|
2031
2124
|
|
|
2032
|
-
function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
2125
|
+
function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
2033
2126
|
const [open, setOpen] = useState(!1), btn = actionButtonFace({
|
|
2034
2127
|
actionEval: actionEval,
|
|
2035
2128
|
activityName: activity
|
|
@@ -2054,7 +2147,9 @@ function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, act
|
|
|
2054
2147
|
actionEval: actionEval,
|
|
2055
2148
|
activity: activity,
|
|
2056
2149
|
instanceId: instanceId,
|
|
2057
|
-
onClose: () => setOpen(!1)
|
|
2150
|
+
onClose: () => setOpen(!1),
|
|
2151
|
+
surface: surface,
|
|
2152
|
+
viaMenu: !1
|
|
2058
2153
|
})
|
|
2059
2154
|
}) : null ]
|
|
2060
2155
|
});
|
|
@@ -2348,27 +2443,10 @@ function useLocalDocRef(gdr) {
|
|
|
2348
2443
|
}
|
|
2349
2444
|
|
|
2350
2445
|
function useActualDocType(bareId) {
|
|
2351
|
-
const
|
|
2352
|
-
apiVersion: WORKFLOW_API_VERSION
|
|
2353
|
-
}), [probe, setProbe] = useState();
|
|
2446
|
+
const {actualTypes: actualTypes} = useWorkflowContext();
|
|
2354
2447
|
return useEffect(() => {
|
|
2355
|
-
if (
|
|
2356
|
-
|
|
2357
|
-
return client.fetch("*[_id == $id || _id == $draft || _id in path($version)][0]._type", {
|
|
2358
|
-
id: bareId,
|
|
2359
|
-
draft: `drafts.${bareId}`,
|
|
2360
|
-
version: `versions.*.${bareId}`
|
|
2361
|
-
}, {
|
|
2362
|
-
perspective: "raw"
|
|
2363
|
-
}).then(result => {
|
|
2364
|
-
cancelled || setProbe({
|
|
2365
|
-
id: bareId,
|
|
2366
|
-
value: result
|
|
2367
|
-
});
|
|
2368
|
-
}).catch(() => {}), () => {
|
|
2369
|
-
cancelled = !0;
|
|
2370
|
-
};
|
|
2371
|
-
}, [ client, bareId ]), probe !== void 0 && probe.id === bareId ? probe.value : void 0;
|
|
2448
|
+
if (bareId !== null) return actualTypes.track(bareId);
|
|
2449
|
+
}, [ actualTypes, bareId ]), useSyncExternalStore(actualTypes.subscribe, useCallback(() => bareId === null ? void 0 : actualTypes.read(bareId), [ actualTypes, bareId ]));
|
|
2372
2450
|
}
|
|
2373
2451
|
|
|
2374
2452
|
function useDocLink(gdr) {
|
|
@@ -2948,7 +3026,7 @@ function useFieldDraft(args) {
|
|
|
2948
3026
|
}
|
|
2949
3027
|
|
|
2950
3028
|
function EditableFieldControl({instanceId: instanceId, field: field}) {
|
|
2951
|
-
const {editFieldFor: editFieldFor, previewFieldFor: previewFieldFor, discardFieldPreviewFor: discardFieldPreviewFor} = useWorkflowContext(),
|
|
3029
|
+
const {editFieldFor: editFieldFor, previewFieldFor: previewFieldFor, discardFieldPreviewFor: discardFieldPreviewFor} = useWorkflowContext(), selfActor = useSelfActor(), held = useHeldWorkflowEntry(instanceId), entry = held ? resolveFieldEntry(held.instance, field) : void 0, evaluation = held?.evaluation, target = editFieldTarget(field), consequence = fieldConsequence(evaluation, field.name), advanceTo = advanceTargetTitle(evaluation, field.name);
|
|
2952
3030
|
/* @__PURE__ */
|
|
2953
3031
|
return jsx(EditableField, {
|
|
2954
3032
|
field: field,
|
|
@@ -2984,7 +3062,7 @@ function EditableFieldControl({instanceId: instanceId, field: field}) {
|
|
|
2984
3062
|
mode: "append",
|
|
2985
3063
|
value: noteRow({
|
|
2986
3064
|
body: body,
|
|
2987
|
-
actor:
|
|
3065
|
+
actor: selfActor,
|
|
2988
3066
|
at: /* @__PURE__ */ (new Date).toISOString()
|
|
2989
3067
|
})
|
|
2990
3068
|
}).then(() => {})
|
|
@@ -3119,7 +3197,10 @@ function AssigneeField({field: field, onSave: onSave, onUnset: onUnset}) {
|
|
|
3119
3197
|
align: "center",
|
|
3120
3198
|
children: /* @__PURE__ */ jsx(DismissablePopover, {
|
|
3121
3199
|
content: /* @__PURE__ */ jsx(AssigneePicker, {
|
|
3122
|
-
|
|
3200
|
+
onChange: next => {
|
|
3201
|
+
const changed = changedAssignee(cur ? [ cur ] : [], next);
|
|
3202
|
+
changed && pickAndClose(changed);
|
|
3203
|
+
},
|
|
3123
3204
|
value: cur ? [ cur ] : []
|
|
3124
3205
|
}),
|
|
3125
3206
|
onDismiss: () => setOpen(!1),
|
|
@@ -3644,11 +3725,11 @@ function AssignActivityControl({instanceId: instanceId, state: state, assigneeId
|
|
|
3644
3725
|
setBusy(!0);
|
|
3645
3726
|
try {
|
|
3646
3727
|
selectedIds.has(memberId) ? await editFieldFor(instanceId, {
|
|
3647
|
-
target:
|
|
3728
|
+
target: editFieldTarget(field),
|
|
3648
3729
|
mode: "set",
|
|
3649
3730
|
value: members.filter(m => !(m.type === "user" && m.id === memberId))
|
|
3650
3731
|
}) : await editFieldFor(instanceId, {
|
|
3651
|
-
target:
|
|
3732
|
+
target: editFieldTarget(field),
|
|
3652
3733
|
mode: "append",
|
|
3653
3734
|
value: {
|
|
3654
3735
|
type: "user",
|
|
@@ -4077,8 +4158,8 @@ function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle,
|
|
|
4077
4158
|
});
|
|
4078
4159
|
}
|
|
4079
4160
|
|
|
4080
|
-
function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter}) {
|
|
4081
|
-
const {instance: instance} = entry, definition = useDefinition(entry), {editFieldFor: editFieldFor, fireActionFor: fireActionFor} = useWorkflowContext(), toast = useClosableToast(), [busy, setBusy] = useState(!1), derivation = deriveTodoItems(entry), rows = derivation.rows.filter(row => rowMatches(row, filter)), appendTarget = appendTargetFor(derivation.appendTargets, filter), run = async op => {
|
|
4161
|
+
function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter, surface: surface}) {
|
|
4162
|
+
const {instance: instance} = entry, definition = useDefinition(entry), {editFieldFor: editFieldFor, fireActionFor: fireActionFor} = useWorkflowContext(), telemetry = useWorkflowTelemetry(), toast = useClosableToast(), [busy, setBusy] = useState(!1), derivation = deriveTodoItems(entry), rows = derivation.rows.filter(row => rowMatches(row, filter)), appendTarget = appendTargetFor(derivation.appendTargets, filter), run = async op => {
|
|
4082
4163
|
if (busy) return !1;
|
|
4083
4164
|
setBusy(!0);
|
|
4084
4165
|
try {
|
|
@@ -4103,15 +4184,35 @@ function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter}) {
|
|
|
4103
4184
|
mode: "set",
|
|
4104
4185
|
value: next
|
|
4105
4186
|
}));
|
|
4106
|
-
}, toggleRow = row => {
|
|
4107
|
-
if (
|
|
4108
|
-
|
|
4109
|
-
|
|
4187
|
+
}, toggleRow = async row => {
|
|
4188
|
+
if (busy) return;
|
|
4189
|
+
if (row.editTarget) {
|
|
4190
|
+
const done = !isTodoDone(row.item), success = await patchItem(row, {
|
|
4191
|
+
status: toggledTodoStatus(row.item)
|
|
4192
|
+
}) === !0;
|
|
4193
|
+
telemetry.log(WorkflowTodoToggled, {
|
|
4194
|
+
instanceId: instance._id,
|
|
4195
|
+
surface: surface,
|
|
4196
|
+
via: "field-edit",
|
|
4197
|
+
done: done,
|
|
4198
|
+
success: success
|
|
4199
|
+
});
|
|
4200
|
+
return;
|
|
4201
|
+
}
|
|
4110
4202
|
const tick = row.tick;
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4203
|
+
if (tick && tick.actionEval.allowed && !isTodoDone(row.item)) {
|
|
4204
|
+
const success = await run(() => fireActionFor(instance._id, {
|
|
4205
|
+
activity: tick.activity,
|
|
4206
|
+
action: tick.actionEval.action.name
|
|
4207
|
+
}));
|
|
4208
|
+
telemetry.log(WorkflowTodoToggled, {
|
|
4209
|
+
instanceId: instance._id,
|
|
4210
|
+
surface: surface,
|
|
4211
|
+
via: "action",
|
|
4212
|
+
done: !0,
|
|
4213
|
+
success: success
|
|
4214
|
+
});
|
|
4215
|
+
}
|
|
4115
4216
|
}, addItem = label => appendTarget ? run(() => editFieldFor(instance._id, {
|
|
4116
4217
|
target: appendTarget,
|
|
4117
4218
|
mode: "append",
|
|
@@ -4228,7 +4329,7 @@ const ACTIONS_MENU_TRIGGER = {
|
|
|
4228
4329
|
padding: 2
|
|
4229
4330
|
};
|
|
4230
4331
|
|
|
4231
|
-
function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activity: activity, onCollectParams: onCollectParams}) {
|
|
4332
|
+
function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, onCollectParams: onCollectParams}) {
|
|
4232
4333
|
const rowKind = actionRowKind(actionEval), label = actionTriggerLabel(actionEval), {tone: tone, icon: icon} = actionButtonFace({
|
|
4233
4334
|
actionEval: actionEval,
|
|
4234
4335
|
activityName: activity
|
|
@@ -4238,7 +4339,9 @@ function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activit
|
|
|
4238
4339
|
instanceId: instanceId,
|
|
4239
4340
|
activity: activity,
|
|
4240
4341
|
action: actionEval.action.name,
|
|
4241
|
-
label: label
|
|
4342
|
+
label: label,
|
|
4343
|
+
surface: surface,
|
|
4344
|
+
viaMenu: !0
|
|
4242
4345
|
});
|
|
4243
4346
|
return rowKind.kind === "disabled" ? /* @__PURE__ */ jsx(MenuItem, {
|
|
4244
4347
|
disabled: !0,
|
|
@@ -4274,7 +4377,7 @@ function rowShield(menuButton) {
|
|
|
4274
4377
|
});
|
|
4275
4378
|
}
|
|
4276
4379
|
|
|
4277
|
-
function ActionsMenuButton({actions: actions, instanceId: instanceId, activity: activity, label: label, mode: mode = "ghost", inButtonCard: inButtonCard = !1}) {
|
|
4380
|
+
function ActionsMenuButton({actions: actions, instanceId: instanceId, activity: activity, label: label, surface: surface, mode: mode = "ghost", inButtonCard: inButtonCard = !1}) {
|
|
4278
4381
|
const [paramsAction, setParamsAction] = useState(void 0), clusterPending = useActionClusterPending(), menuId = useId(), menuButton = /* @__PURE__ */ jsx(MenuButton, {
|
|
4279
4382
|
button: /* @__PURE__ */ jsx(Button, {
|
|
4280
4383
|
...ACTIONS_MENU_TRIGGER,
|
|
@@ -4293,7 +4396,8 @@ function ActionsMenuButton({actions: actions, instanceId: instanceId, activity:
|
|
|
4293
4396
|
actionEval: a,
|
|
4294
4397
|
activity: activity,
|
|
4295
4398
|
instanceId: instanceId,
|
|
4296
|
-
onCollectParams: () => setParamsAction(a)
|
|
4399
|
+
onCollectParams: () => setParamsAction(a),
|
|
4400
|
+
surface: surface
|
|
4297
4401
|
}, a.action.name))
|
|
4298
4402
|
}),
|
|
4299
4403
|
popover: {
|
|
@@ -4309,7 +4413,9 @@ function ActionsMenuButton({actions: actions, instanceId: instanceId, activity:
|
|
|
4309
4413
|
actionEval: paramsAction,
|
|
4310
4414
|
activity: activity,
|
|
4311
4415
|
instanceId: instanceId,
|
|
4312
|
-
onClose: () => setParamsAction(void 0)
|
|
4416
|
+
onClose: () => setParamsAction(void 0),
|
|
4417
|
+
surface: surface,
|
|
4418
|
+
viaMenu: !0
|
|
4313
4419
|
})
|
|
4314
4420
|
}) : null ]
|
|
4315
4421
|
});
|
|
@@ -4325,7 +4431,8 @@ function TerminalFooter({actions: actions, activity: activity, instanceId: insta
|
|
|
4325
4431
|
children: /* @__PURE__ */ jsx(ActivityActionRow, {
|
|
4326
4432
|
actionEval: only,
|
|
4327
4433
|
activity: activity,
|
|
4328
|
-
instanceId: instanceId
|
|
4434
|
+
instanceId: instanceId,
|
|
4435
|
+
surface: "terminal-footer"
|
|
4329
4436
|
})
|
|
4330
4437
|
}) : /* @__PURE__ */ jsx(FittedActions, {
|
|
4331
4438
|
actions: actions,
|
|
@@ -4379,13 +4486,15 @@ function FittedActions({actions: actions, activity: activity, instanceId: instan
|
|
|
4379
4486
|
children: [ inline === void 0 ? null : actions.slice(0, inline).map(a => /* @__PURE__ */ jsx(ActivityActionRow, {
|
|
4380
4487
|
actionEval: a,
|
|
4381
4488
|
activity: activity,
|
|
4382
|
-
instanceId: instanceId
|
|
4489
|
+
instanceId: instanceId,
|
|
4490
|
+
surface: "terminal-footer"
|
|
4383
4491
|
}, a.action.name)), overflow.length > 0 ? /* @__PURE__ */ jsx(ActionsMenuButton, {
|
|
4384
4492
|
actions: overflow,
|
|
4385
4493
|
activity: activity,
|
|
4386
4494
|
instanceId: instanceId,
|
|
4387
4495
|
label: MORE_ACTIONS_LABEL,
|
|
4388
|
-
mode: "default"
|
|
4496
|
+
mode: "default",
|
|
4497
|
+
surface: "terminal-footer"
|
|
4389
4498
|
}) : null ]
|
|
4390
4499
|
}) ]
|
|
4391
4500
|
});
|
|
@@ -4428,7 +4537,7 @@ function MeasureRow({actions: actions, activity: activity, onElement: onElement}
|
|
|
4428
4537
|
});
|
|
4429
4538
|
}
|
|
4430
4539
|
|
|
4431
|
-
function ActivityDetailDialog({entry: entry, activityName: activityName, breadcrumb: breadcrumb, definition: definition, document: document, onClose: onClose}) {
|
|
4540
|
+
function ActivityDetailDialog({entry: entry, activityName: activityName, breadcrumb: breadcrumb, definition: definition, document: document, source: source, onClose: onClose}) {
|
|
4432
4541
|
const detail = deriveActivityDetail({
|
|
4433
4542
|
entry: entry,
|
|
4434
4543
|
activityName: activityName
|
|
@@ -4450,6 +4559,13 @@ function ActivityDetailDialog({entry: entry, activityName: activityName, breadcr
|
|
|
4450
4559
|
onClose: onClose,
|
|
4451
4560
|
width: 1,
|
|
4452
4561
|
children: [
|
|
4562
|
+
/* @__PURE__ */ jsx(LogEventOnMount, {
|
|
4563
|
+
data: {
|
|
4564
|
+
instanceId: instanceId,
|
|
4565
|
+
source: source
|
|
4566
|
+
},
|
|
4567
|
+
event: WorkflowActivityDialogOpened
|
|
4568
|
+
}),
|
|
4453
4569
|
/* @__PURE__ */ jsx(Card, {
|
|
4454
4570
|
borderBottom: hasBody,
|
|
4455
4571
|
style: {
|
|
@@ -4557,7 +4673,8 @@ function TopActions({detail: detail, definition: definition, instanceId: instanc
|
|
|
4557
4673
|
children: [ p.actions.map(a => /* @__PURE__ */ jsx(ActivityActionRow, {
|
|
4558
4674
|
actionEval: a,
|
|
4559
4675
|
activity: activityName,
|
|
4560
|
-
instanceId: instanceId
|
|
4676
|
+
instanceId: instanceId,
|
|
4677
|
+
surface: "dialog-strip"
|
|
4561
4678
|
}, a.action.name)), p.manualTarget ? /* @__PURE__ */ jsx(Button, {
|
|
4562
4679
|
as: "a",
|
|
4563
4680
|
fontSize: 1,
|
|
@@ -4593,7 +4710,8 @@ function FieldRow({field: field, detail: detail, entry: entry, activityName: act
|
|
|
4593
4710
|
scope: "activity",
|
|
4594
4711
|
field: field.name,
|
|
4595
4712
|
activity: activityName
|
|
4596
|
-
}
|
|
4713
|
+
},
|
|
4714
|
+
surface: "activity-dialog"
|
|
4597
4715
|
}) ]
|
|
4598
4716
|
});
|
|
4599
4717
|
if (field._type === "assignees") {
|
|
@@ -4746,29 +4864,7 @@ function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
|
4746
4864
|
});
|
|
4747
4865
|
}
|
|
4748
4866
|
|
|
4749
|
-
function
|
|
4750
|
-
const toast = useClosableToast();
|
|
4751
|
-
/* @__PURE__ */
|
|
4752
|
-
return jsx(Button, {
|
|
4753
|
-
fontSize: 1,
|
|
4754
|
-
mode: "ghost",
|
|
4755
|
-
onClick: () => {
|
|
4756
|
-
navigator.clipboard.writeText(unreadableDocsReport(unreadable)).then(() => toast.push({
|
|
4757
|
-
status: "success",
|
|
4758
|
-
title: "Details copied"
|
|
4759
|
-
}), () => toast.push({
|
|
4760
|
-
status: "error",
|
|
4761
|
-
title: "Could not copy the details"
|
|
4762
|
-
}));
|
|
4763
|
-
},
|
|
4764
|
-
padding: 2,
|
|
4765
|
-
text: "Copy details"
|
|
4766
|
-
});
|
|
4767
|
-
}
|
|
4768
|
-
|
|
4769
|
-
function UnreadableDocsNote({unreadable: unreadable}) {
|
|
4770
|
-
if (unreadable.length === 0) return null;
|
|
4771
|
-
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.`;
|
|
4867
|
+
function CautionNote({action: action, label: label}) {
|
|
4772
4868
|
/* @__PURE__ */
|
|
4773
4869
|
return jsxs(Card, {
|
|
4774
4870
|
padding: 2,
|
|
@@ -4795,10 +4891,39 @@ function UnreadableDocsNote({unreadable: unreadable}) {
|
|
|
4795
4891
|
size: 1,
|
|
4796
4892
|
children: label
|
|
4797
4893
|
}) ]
|
|
4798
|
-
}),
|
|
4799
|
-
|
|
4894
|
+
}), action ]
|
|
4895
|
+
});
|
|
4896
|
+
}
|
|
4897
|
+
|
|
4898
|
+
function CopyDetailsButton({unreadable: unreadable}) {
|
|
4899
|
+
const toast = useClosableToast();
|
|
4900
|
+
/* @__PURE__ */
|
|
4901
|
+
return jsx(Button, {
|
|
4902
|
+
fontSize: 1,
|
|
4903
|
+
mode: "ghost",
|
|
4904
|
+
onClick: () => {
|
|
4905
|
+
navigator.clipboard.writeText(unreadableDocsReport(unreadable)).then(() => toast.push({
|
|
4906
|
+
status: "success",
|
|
4907
|
+
title: "Details copied"
|
|
4908
|
+
}), () => toast.push({
|
|
4909
|
+
status: "error",
|
|
4910
|
+
title: "Could not copy the details"
|
|
4911
|
+
}));
|
|
4912
|
+
},
|
|
4913
|
+
padding: 2,
|
|
4914
|
+
text: "Copy details"
|
|
4915
|
+
});
|
|
4916
|
+
}
|
|
4917
|
+
|
|
4918
|
+
function UnreadableDocsNote({unreadable: unreadable}) {
|
|
4919
|
+
if (unreadable.length === 0) return null;
|
|
4920
|
+
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.`;
|
|
4921
|
+
/* @__PURE__ */
|
|
4922
|
+
return jsx(CautionNote, {
|
|
4923
|
+
action: /* @__PURE__ */ jsx(CopyDetailsButton, {
|
|
4800
4924
|
unreadable: unreadable
|
|
4801
|
-
})
|
|
4925
|
+
}),
|
|
4926
|
+
label: label
|
|
4802
4927
|
});
|
|
4803
4928
|
}
|
|
4804
4929
|
|
|
@@ -5120,6 +5245,25 @@ function buildStartRequest(args) {
|
|
|
5120
5245
|
};
|
|
5121
5246
|
}
|
|
5122
5247
|
|
|
5248
|
+
function sharedPreflightDataset(engine, tag) {
|
|
5249
|
+
let pending;
|
|
5250
|
+
return () => {
|
|
5251
|
+
if (pending !== void 0) return pending;
|
|
5252
|
+
const {query: query, params: params} = instancesQuery({
|
|
5253
|
+
tag: tag,
|
|
5254
|
+
filter: {
|
|
5255
|
+
includeCompleted: !0
|
|
5256
|
+
}
|
|
5257
|
+
});
|
|
5258
|
+
return pending = engine.query({
|
|
5259
|
+
groq: query,
|
|
5260
|
+
params: params
|
|
5261
|
+
}).then(rows => rows.map(assertReadableModel).map(projectStartSliceRow)).finally(() => {
|
|
5262
|
+
pending = void 0;
|
|
5263
|
+
}), pending;
|
|
5264
|
+
};
|
|
5265
|
+
}
|
|
5266
|
+
|
|
5123
5267
|
function findResumeEntry(args) {
|
|
5124
5268
|
return args.entries.find(e => isUnprimed(e.instance) && e.instance.definition === args.definitionName && (args.heldInstanceId === void 0 || e.instance._id === args.heldInstanceId));
|
|
5125
5269
|
}
|
|
@@ -5135,7 +5279,8 @@ function classifyStartError(err) {
|
|
|
5135
5279
|
instance: err.instance,
|
|
5136
5280
|
description: describeError(err.cause)
|
|
5137
5281
|
} : err instanceof StartNotAllowedError ? {
|
|
5138
|
-
kind: "not-allowed"
|
|
5282
|
+
kind: "not-allowed",
|
|
5283
|
+
description: err.unmetRequirements.map(requirementCopy).join("; ")
|
|
5139
5284
|
} : {
|
|
5140
5285
|
kind: "failed",
|
|
5141
5286
|
description: describeError(err)
|
|
@@ -5148,22 +5293,30 @@ function boundReleaseId(mapping, selectedReleaseId) {
|
|
|
5148
5293
|
|
|
5149
5294
|
function startGate(args) {
|
|
5150
5295
|
const {mapping: mapping, mappingIssue: mappingIssue, selectedReleaseId: selectedReleaseId, releaseActive: releaseActive} = args;
|
|
5151
|
-
|
|
5296
|
+
if (mappingIssue !== void 0) return {
|
|
5152
5297
|
blocked: !0,
|
|
5153
5298
|
tooltip: mappingIssue
|
|
5154
|
-
}
|
|
5299
|
+
};
|
|
5300
|
+
if (mapping.perspectiveField?.required === !0 && selectedReleaseId === void 0) return {
|
|
5155
5301
|
blocked: !0,
|
|
5156
5302
|
tooltip: "Pick a release in the perspective dropdown first"
|
|
5157
|
-
}
|
|
5303
|
+
};
|
|
5304
|
+
if (mapping.perspectiveField !== void 0 && selectedReleaseId !== void 0 && !releaseActive) return {
|
|
5158
5305
|
blocked: !0,
|
|
5159
5306
|
tooltip: `Release "${selectedReleaseId}" is not active — only active releases can host new workflows`
|
|
5160
|
-
}
|
|
5307
|
+
};
|
|
5308
|
+
if (args.startFilterFailed === !0) return {
|
|
5161
5309
|
blocked: !0,
|
|
5162
5310
|
tooltip: `${mapping.label} can't start for this document right now — the workflow's start condition isn't met`
|
|
5163
|
-
}
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5311
|
+
};
|
|
5312
|
+
if (args.unmetRequirement !== void 0) {
|
|
5313
|
+
const requirement = args.unmetRequirement;
|
|
5314
|
+
return {
|
|
5315
|
+
blocked: !0,
|
|
5316
|
+
tooltip: requirementCopy(requirement)
|
|
5317
|
+
};
|
|
5318
|
+
}
|
|
5319
|
+
return {
|
|
5167
5320
|
blocked: !1,
|
|
5168
5321
|
tooltip: void 0
|
|
5169
5322
|
};
|
|
@@ -5186,10 +5339,10 @@ async function preflightFilter(args) {
|
|
|
5186
5339
|
});
|
|
5187
5340
|
}
|
|
5188
5341
|
|
|
5189
|
-
async function
|
|
5190
|
-
const {
|
|
5191
|
-
return
|
|
5192
|
-
|
|
5342
|
+
async function preflightGroqRequirement(args) {
|
|
5343
|
+
const {query: query, mapping: mapping, fields: fields, scope: scope} = args;
|
|
5344
|
+
return unboundRequirementReads(query, fields).length > 0 ? !1 : (await explainStartRequirement({
|
|
5345
|
+
query: query,
|
|
5193
5346
|
definition: {
|
|
5194
5347
|
name: mapping.definition
|
|
5195
5348
|
},
|
|
@@ -5198,6 +5351,25 @@ async function preflightAllowed(args) {
|
|
|
5198
5351
|
})).outcome === "unsatisfied";
|
|
5199
5352
|
}
|
|
5200
5353
|
|
|
5354
|
+
async function preflightSingleSubjectRequirement(args) {
|
|
5355
|
+
const {mapping: mapping, start: start, declaredFields: declaredFields, fields: fields, scope: scope} = args;
|
|
5356
|
+
return singleSubjectRequirementRefused({
|
|
5357
|
+
definition: {
|
|
5358
|
+
name: mapping.definition,
|
|
5359
|
+
...declaredFields !== void 0 ? {
|
|
5360
|
+
fields: [ ...declaredFields ]
|
|
5361
|
+
} : {},
|
|
5362
|
+
start: start
|
|
5363
|
+
},
|
|
5364
|
+
fields: fields,
|
|
5365
|
+
scope: scope
|
|
5366
|
+
});
|
|
5367
|
+
}
|
|
5368
|
+
|
|
5369
|
+
function requirementCopy(requirement) {
|
|
5370
|
+
return requirement.description ?? requirement.title ?? humanize(requirement.name);
|
|
5371
|
+
}
|
|
5372
|
+
|
|
5201
5373
|
async function performStart(args) {
|
|
5202
5374
|
const {mapping: mapping, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId} = args, releaseId = boundReleaseId(mapping, selectedReleaseId);
|
|
5203
5375
|
try {
|
|
@@ -5224,7 +5396,21 @@ async function performStart(args) {
|
|
|
5224
5396
|
}
|
|
5225
5397
|
|
|
5226
5398
|
function useStartVerdicts(args) {
|
|
5227
|
-
const {mapping: mapping, start: start, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId} = args, skip = args.hidden || args.resumable
|
|
5399
|
+
const {mapping: mapping, start: start, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId, entries: entries} = args, {engine: engine, binding: binding} = useWorkflowContext(), fetchDataset = useMemo(() => sharedPreflightDataset(engine, binding.tag), [ engine, binding.tag ]), skip = args.hidden || args.resumable, groqRequirements = useMemo(() => start?.requirements?.filter(requirement => requirement.type === "groq") ?? [], [ start?.requirements ]), refusedGroq = useGroqRequirementVerdicts({
|
|
5400
|
+
mapping: mapping,
|
|
5401
|
+
requirements: groqRequirements,
|
|
5402
|
+
docId: docId,
|
|
5403
|
+
selectedReleaseId: selectedReleaseId,
|
|
5404
|
+
skip: skip,
|
|
5405
|
+
fetchDataset: fetchDataset
|
|
5406
|
+
}), singleSubjectRefused = useSingleSubjectVerdict({
|
|
5407
|
+
mapping: mapping,
|
|
5408
|
+
start: start,
|
|
5409
|
+
docId: docId,
|
|
5410
|
+
selectedReleaseId: selectedReleaseId,
|
|
5411
|
+
entries: entries,
|
|
5412
|
+
skip: skip
|
|
5413
|
+
}), unmetRequirement = start?.requirements?.find(requirement => requirement.type === "singleSubject" ? singleSubjectRefused : refusedGroq.includes(requirement.name));
|
|
5228
5414
|
return {
|
|
5229
5415
|
filterFailed: useFilterVerdict({
|
|
5230
5416
|
mapping: mapping,
|
|
@@ -5232,25 +5418,15 @@ function useStartVerdicts(args) {
|
|
|
5232
5418
|
docId: docId,
|
|
5233
5419
|
initialValue: initialValue,
|
|
5234
5420
|
selectedReleaseId: selectedReleaseId,
|
|
5235
|
-
skip: skip
|
|
5421
|
+
skip: skip,
|
|
5422
|
+
fetchDataset: fetchDataset
|
|
5236
5423
|
}),
|
|
5237
|
-
|
|
5238
|
-
mapping: mapping,
|
|
5239
|
-
allowed: start?.allowed,
|
|
5240
|
-
docId: docId,
|
|
5241
|
-
selectedReleaseId: selectedReleaseId,
|
|
5242
|
-
skip: skip
|
|
5243
|
-
})
|
|
5424
|
+
unmetRequirement: unmetRequirement
|
|
5244
5425
|
};
|
|
5245
5426
|
}
|
|
5246
5427
|
|
|
5247
5428
|
function preflightScope(args) {
|
|
5248
|
-
const {
|
|
5249
|
-
tag: tag,
|
|
5250
|
-
filter: {
|
|
5251
|
-
includeCompleted: !0
|
|
5252
|
-
}
|
|
5253
|
-
});
|
|
5429
|
+
const {tag: tag, mapping: mapping, contentResource: contentResource, docId: docId, fetchDataset: fetchDataset} = args;
|
|
5254
5430
|
return {
|
|
5255
5431
|
tag: tag,
|
|
5256
5432
|
now: /* @__PURE__ */ (new Date).toISOString(),
|
|
@@ -5259,15 +5435,12 @@ function preflightScope(args) {
|
|
|
5259
5435
|
contentResource: contentResource,
|
|
5260
5436
|
documentId: docId
|
|
5261
5437
|
}).id,
|
|
5262
|
-
fetchDataset:
|
|
5263
|
-
groq: query,
|
|
5264
|
-
params: params
|
|
5265
|
-
})).map(assertReadableModel)
|
|
5438
|
+
fetchDataset: fetchDataset
|
|
5266
5439
|
};
|
|
5267
5440
|
}
|
|
5268
5441
|
|
|
5269
5442
|
function useFilterVerdict(args) {
|
|
5270
|
-
const {mapping: mapping, filter: filter, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId, skip: skip} = args, {
|
|
5443
|
+
const {mapping: mapping, filter: filter, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId, skip: skip, fetchDataset: fetchDataset} = args, {binding: binding} = useWorkflowContext(), [failed, setFailed] = useState(!1), rootRead = filter !== void 0 && readsRootDocument(filter), candidateValue = rootRead ? initialValue : null;
|
|
5271
5444
|
return useEffect(() => {
|
|
5272
5445
|
if (skip || filter === void 0 || docId === void 0) {
|
|
5273
5446
|
setFailed(!1);
|
|
@@ -5281,57 +5454,112 @@ function useFilterVerdict(args) {
|
|
|
5281
5454
|
candidateValue: candidateValue,
|
|
5282
5455
|
selectedReleaseId: selectedReleaseId,
|
|
5283
5456
|
scope: preflightScope({
|
|
5284
|
-
engine: engine,
|
|
5285
5457
|
tag: binding.tag,
|
|
5286
5458
|
mapping: mapping,
|
|
5287
5459
|
contentResource: binding.contentResource,
|
|
5288
|
-
docId: docId
|
|
5460
|
+
docId: docId,
|
|
5461
|
+
fetchDataset: fetchDataset
|
|
5289
5462
|
})
|
|
5290
5463
|
}).catch(showRowOnError("start.filter", mapping)).then(verdict => {
|
|
5291
5464
|
cancelled || setFailed(verdict);
|
|
5292
5465
|
}), () => {
|
|
5293
5466
|
cancelled = !0;
|
|
5294
5467
|
};
|
|
5295
|
-
}, [ filter, rootRead, skip, docId, selectedReleaseId, candidateValue, mapping,
|
|
5468
|
+
}, [ filter, rootRead, skip, docId, selectedReleaseId, candidateValue, mapping, binding, fetchDataset ]),
|
|
5296
5469
|
failed;
|
|
5297
5470
|
}
|
|
5298
5471
|
|
|
5299
|
-
function
|
|
5300
|
-
const
|
|
5472
|
+
function preflightSeedFields(args) {
|
|
5473
|
+
const ctx = {
|
|
5474
|
+
mapping: args.mapping,
|
|
5475
|
+
subjectDocId: args.docId,
|
|
5476
|
+
selectedReleaseId: args.selectedReleaseId,
|
|
5477
|
+
contentResource: args.contentResource,
|
|
5478
|
+
declaredFields: args.declaredFields
|
|
5479
|
+
};
|
|
5480
|
+
return Object.fromEntries(buildStartFields({
|
|
5481
|
+
ctx: ctx,
|
|
5482
|
+
initFields: [],
|
|
5483
|
+
values: {}
|
|
5484
|
+
}).map(field => [ field.name, field.value ]));
|
|
5485
|
+
}
|
|
5486
|
+
|
|
5487
|
+
function useGroqRequirementVerdicts(args) {
|
|
5488
|
+
const {mapping: mapping, requirements: requirements, docId: docId, selectedReleaseId: selectedReleaseId, skip: skip, fetchDataset: fetchDataset} = args, {binding: binding, mappingFields: mappingFields} = useWorkflowContext(), [refused, setRefused] = useState([]);
|
|
5301
5489
|
return useEffect(() => {
|
|
5302
|
-
if (skip ||
|
|
5303
|
-
setRefused(
|
|
5490
|
+
if (skip || requirements.length === 0 || docId === void 0) {
|
|
5491
|
+
setRefused(current => current.length === 0 ? current : []);
|
|
5304
5492
|
return;
|
|
5305
5493
|
}
|
|
5306
5494
|
let cancelled = !1;
|
|
5307
|
-
const
|
|
5495
|
+
const fields = preflightSeedFields({
|
|
5308
5496
|
mapping: mapping,
|
|
5309
|
-
|
|
5497
|
+
docId: docId,
|
|
5310
5498
|
selectedReleaseId: selectedReleaseId,
|
|
5311
5499
|
contentResource: binding.contentResource,
|
|
5312
5500
|
declaredFields: mappingFields.get(mappingKey(mapping))
|
|
5313
|
-
},
|
|
5314
|
-
|
|
5315
|
-
initFields: [],
|
|
5316
|
-
values: {}
|
|
5317
|
-
}).map(field => [ field.name, field.value ]));
|
|
5318
|
-
return preflightAllowed({
|
|
5319
|
-
allowed: allowed,
|
|
5501
|
+
}), scope = preflightScope({
|
|
5502
|
+
tag: binding.tag,
|
|
5320
5503
|
mapping: mapping,
|
|
5321
|
-
|
|
5504
|
+
contentResource: binding.contentResource,
|
|
5505
|
+
docId: docId,
|
|
5506
|
+
fetchDataset: fetchDataset
|
|
5507
|
+
});
|
|
5508
|
+
return Promise.all(requirements.map(async requirement => ({
|
|
5509
|
+
name: requirement.name,
|
|
5510
|
+
refused: await preflightGroqRequirement({
|
|
5511
|
+
query: requirement.query,
|
|
5512
|
+
mapping: mapping,
|
|
5513
|
+
fields: fields,
|
|
5514
|
+
scope: scope
|
|
5515
|
+
}).catch(showRowOnError(`start.requirements.${requirement.name}`, mapping))
|
|
5516
|
+
}))).then(verdicts => {
|
|
5517
|
+
if (!cancelled) {
|
|
5518
|
+
const next = verdicts.filter(verdict => verdict.refused).map(verdict => verdict.name);
|
|
5519
|
+
setRefused(current => current.length === next.length && current.every((name, index) => name === next[index]) ? current : next);
|
|
5520
|
+
}
|
|
5521
|
+
}), () => {
|
|
5522
|
+
cancelled = !0;
|
|
5523
|
+
};
|
|
5524
|
+
}, [ requirements, skip, docId, selectedReleaseId, mapping, binding, mappingFields, fetchDataset ]),
|
|
5525
|
+
refused;
|
|
5526
|
+
}
|
|
5527
|
+
|
|
5528
|
+
function useSingleSubjectVerdict(args) {
|
|
5529
|
+
const {mapping: mapping, start: start, docId: docId, selectedReleaseId: selectedReleaseId, entries: entries, skip: skip} = args, {binding: binding, mappingFields: mappingFields} = useWorkflowContext(), [refused, setRefused] = useState(!1), dedupe = start !== void 0 && hasSingleSubjectRequirement({
|
|
5530
|
+
start: start
|
|
5531
|
+
});
|
|
5532
|
+
return useEffect(() => {
|
|
5533
|
+
if (skip || !dedupe || start === void 0 || docId === void 0) {
|
|
5534
|
+
setRefused(!1);
|
|
5535
|
+
return;
|
|
5536
|
+
}
|
|
5537
|
+
let cancelled = !1;
|
|
5538
|
+
const declaredFields = mappingFields.get(mappingKey(mapping));
|
|
5539
|
+
return preflightSingleSubjectRequirement({
|
|
5540
|
+
mapping: mapping,
|
|
5541
|
+
start: start,
|
|
5542
|
+
declaredFields: declaredFields,
|
|
5543
|
+
fields: preflightSeedFields({
|
|
5544
|
+
mapping: mapping,
|
|
5545
|
+
docId: docId,
|
|
5546
|
+
selectedReleaseId: selectedReleaseId,
|
|
5547
|
+
contentResource: binding.contentResource,
|
|
5548
|
+
declaredFields: declaredFields
|
|
5549
|
+
}),
|
|
5322
5550
|
scope: preflightScope({
|
|
5323
|
-
engine: engine,
|
|
5324
5551
|
tag: binding.tag,
|
|
5325
5552
|
mapping: mapping,
|
|
5553
|
+
docId: docId,
|
|
5326
5554
|
contentResource: binding.contentResource,
|
|
5327
|
-
|
|
5555
|
+
fetchDataset: () => Promise.resolve(entries.map(({instance: instance}) => projectStartSliceRow(instance)))
|
|
5328
5556
|
})
|
|
5329
|
-
}).catch(showRowOnError("
|
|
5557
|
+
}).catch(showRowOnError("singleSubject requirement", mapping)).then(verdict => {
|
|
5330
5558
|
cancelled || setRefused(verdict);
|
|
5331
5559
|
}), () => {
|
|
5332
5560
|
cancelled = !0;
|
|
5333
5561
|
};
|
|
5334
|
-
}, [
|
|
5562
|
+
}, [ dedupe, start, skip, docId, selectedReleaseId, entries, mapping, binding, mappingFields ]),
|
|
5335
5563
|
refused;
|
|
5336
5564
|
}
|
|
5337
5565
|
|
|
@@ -5341,7 +5569,7 @@ function showRowOnError(key, mapping) {
|
|
|
5341
5569
|
}
|
|
5342
5570
|
|
|
5343
5571
|
function useStartWorkflow(args) {
|
|
5344
|
-
const {mapping: mapping, docId: docId, initialValue: initialValue} = args, toast = useClosableToast(), {engine: engine, openStartDialog: openStartDialog, mappingIssues: mappingIssues2, mappingStarts: mappingStarts} = useWorkflowContext(), observer = useStudioObserver({
|
|
5572
|
+
const {mapping: mapping, docId: docId, initialValue: initialValue, source: source} = args, toast = useClosableToast(), {engine: engine, openStartDialog: openStartDialog, mappingIssues: mappingIssues2, mappingStarts: mappingStarts} = useWorkflowContext(), observer = useStudioObserver({
|
|
5345
5573
|
engine: engine
|
|
5346
5574
|
}), [starting, setStarting] = useState(!1), {selectedReleaseId: selectedReleaseId} = usePerspective(), releaseActive = useIsReleaseActive(), startBlock = mappingStarts.get(mappingKey(mapping)), hidden = startKindOf({
|
|
5347
5575
|
start: startBlock
|
|
@@ -5349,12 +5577,13 @@ function useStartWorkflow(args) {
|
|
|
5349
5577
|
entries: entries,
|
|
5350
5578
|
definitionName: mapping.definition,
|
|
5351
5579
|
heldInstanceId: void 0
|
|
5352
|
-
}) !== void 0, {filterFailed: filterFailed,
|
|
5580
|
+
}) !== void 0, {filterFailed: filterFailed, unmetRequirement: unmetRequirement} = useStartVerdicts({
|
|
5353
5581
|
mapping: mapping,
|
|
5354
5582
|
start: startBlock,
|
|
5355
5583
|
docId: docId,
|
|
5356
5584
|
initialValue: initialValue,
|
|
5357
5585
|
selectedReleaseId: selectedReleaseId,
|
|
5586
|
+
entries: entries,
|
|
5358
5587
|
hidden: hidden,
|
|
5359
5588
|
resumable: resumable
|
|
5360
5589
|
}), {blocked: blocked, tooltip: tooltip} = startGate({
|
|
@@ -5363,7 +5592,9 @@ function useStartWorkflow(args) {
|
|
|
5363
5592
|
selectedReleaseId: selectedReleaseId,
|
|
5364
5593
|
releaseActive: releaseActive,
|
|
5365
5594
|
startFilterFailed: filterFailed,
|
|
5366
|
-
|
|
5595
|
+
...unmetRequirement !== void 0 ? {
|
|
5596
|
+
unmetRequirement: unmetRequirement
|
|
5597
|
+
} : {}
|
|
5367
5598
|
});
|
|
5368
5599
|
return {
|
|
5369
5600
|
blocked: blocked,
|
|
@@ -5385,7 +5616,10 @@ function useStartWorkflow(args) {
|
|
|
5385
5616
|
title: "Could not persist the document before starting",
|
|
5386
5617
|
description: describeError(err)
|
|
5387
5618
|
}),
|
|
5388
|
-
openStartDialog: openStartDialog
|
|
5619
|
+
openStartDialog: request => openStartDialog({
|
|
5620
|
+
...request,
|
|
5621
|
+
source: source
|
|
5622
|
+
})
|
|
5389
5623
|
});
|
|
5390
5624
|
} finally {
|
|
5391
5625
|
setStarting(!1);
|
|
@@ -5395,11 +5629,12 @@ function useStartWorkflow(args) {
|
|
|
5395
5629
|
};
|
|
5396
5630
|
}
|
|
5397
5631
|
|
|
5398
|
-
function StartWorkflowButton({mapping: mapping, docId: docId, initialValue: initialValue, mode: mode = "default", label: label, iconOnly: iconOnly = !1, tone: tone = "primary"}) {
|
|
5632
|
+
function StartWorkflowButton({mapping: mapping, docId: docId, initialValue: initialValue, source: source, mode: mode = "default", label: label, iconOnly: iconOnly = !1, tone: tone = "primary"}) {
|
|
5399
5633
|
const {blocked: blocked, tooltip: tooltip, hidden: hidden, starting: starting, start: start} = useStartWorkflow({
|
|
5400
5634
|
mapping: mapping,
|
|
5401
5635
|
docId: docId,
|
|
5402
|
-
initialValue: initialValue
|
|
5636
|
+
initialValue: initialValue,
|
|
5637
|
+
source: source
|
|
5403
5638
|
});
|
|
5404
5639
|
if (hidden) return null;
|
|
5405
5640
|
const startLabel = label ?? `Start ${mapping.label}`, button = /* @__PURE__ */ jsx(Button, {
|
|
@@ -5432,7 +5667,7 @@ function useStartableMappings(mappings) {
|
|
|
5432
5667
|
}) !== "autonomous");
|
|
5433
5668
|
}
|
|
5434
5669
|
|
|
5435
|
-
function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: initialValue, label: label, iconOnly: iconOnly = !1, mode: mode = "default", tone: tone = "primary"}) {
|
|
5670
|
+
function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: initialValue, source: source, label: label, iconOnly: iconOnly = !1, mode: mode = "default", tone: tone = "primary"}) {
|
|
5436
5671
|
const menuId = useId(), startable = useStartableMappings(mappings), [first] = startable;
|
|
5437
5672
|
if (first === void 0) return null;
|
|
5438
5673
|
if (startable.length === 1) /* @__PURE__ */
|
|
@@ -5445,6 +5680,7 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5445
5680
|
},
|
|
5446
5681
|
mapping: first,
|
|
5447
5682
|
mode: mode,
|
|
5683
|
+
source: source,
|
|
5448
5684
|
tone: tone
|
|
5449
5685
|
});
|
|
5450
5686
|
const menuLabel = label ?? "Start a workflow";
|
|
@@ -5470,7 +5706,8 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5470
5706
|
children: startable.map(mapping => /* @__PURE__ */ jsx(StartWorkflowMenuItem, {
|
|
5471
5707
|
docId: docId,
|
|
5472
5708
|
initialValue: initialValue,
|
|
5473
|
-
mapping: mapping
|
|
5709
|
+
mapping: mapping,
|
|
5710
|
+
source: source
|
|
5474
5711
|
}, mappingKey(mapping)))
|
|
5475
5712
|
}),
|
|
5476
5713
|
popover: {
|
|
@@ -5481,11 +5718,12 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5481
5718
|
});
|
|
5482
5719
|
}
|
|
5483
5720
|
|
|
5484
|
-
function StartWorkflowMenuItem({mapping: mapping, docId: docId, initialValue: initialValue}) {
|
|
5721
|
+
function StartWorkflowMenuItem({mapping: mapping, docId: docId, initialValue: initialValue, source: source}) {
|
|
5485
5722
|
const {blocked: blocked, tooltip: tooltip, starting: starting, start: start} = useStartWorkflow({
|
|
5486
5723
|
mapping: mapping,
|
|
5487
5724
|
docId: docId,
|
|
5488
|
-
initialValue: initialValue
|
|
5725
|
+
initialValue: initialValue,
|
|
5726
|
+
source: source
|
|
5489
5727
|
}), item = /* @__PURE__ */ jsx(MenuItem, {
|
|
5490
5728
|
disabled: blocked || starting || !docId,
|
|
5491
5729
|
onClick: () => {
|
|
@@ -5540,13 +5778,15 @@ function RowTerminalActions({actions: actions, activity: activity, instanceId: i
|
|
|
5540
5778
|
mode: "ghost",
|
|
5541
5779
|
inButtonCard: !0
|
|
5542
5780
|
},
|
|
5543
|
-
instanceId: instanceId
|
|
5781
|
+
instanceId: instanceId,
|
|
5782
|
+
surface: "inline-row"
|
|
5544
5783
|
}) : /* @__PURE__ */ jsx(ActionsMenuButton, {
|
|
5545
5784
|
actions: actions,
|
|
5546
5785
|
activity: activity,
|
|
5547
5786
|
inButtonCard: !0,
|
|
5548
5787
|
instanceId: instanceId,
|
|
5549
|
-
label: "Select action"
|
|
5788
|
+
label: "Select action",
|
|
5789
|
+
surface: "inline-row"
|
|
5550
5790
|
})
|
|
5551
5791
|
}) : null;
|
|
5552
5792
|
}
|
|
@@ -5644,7 +5884,8 @@ function ForMeList({entry: entry, work: work, identity: identity, onOpenActivity
|
|
|
5644
5884
|
filter: {
|
|
5645
5885
|
kind: "mine",
|
|
5646
5886
|
identity: identity
|
|
5647
|
-
}
|
|
5887
|
+
},
|
|
5888
|
+
surface: "document-view-for-me"
|
|
5648
5889
|
}) : null ]
|
|
5649
5890
|
})
|
|
5650
5891
|
});
|
|
@@ -5853,7 +6094,8 @@ function TodoFieldDialog({entry: entry, scope: scope, field: field, title: title
|
|
|
5853
6094
|
kind: "field",
|
|
5854
6095
|
scope: scope,
|
|
5855
6096
|
field: field
|
|
5856
|
-
}
|
|
6097
|
+
},
|
|
6098
|
+
surface: "todo-field-dialog"
|
|
5857
6099
|
})
|
|
5858
6100
|
})
|
|
5859
6101
|
});
|
|
@@ -6066,7 +6308,7 @@ function PillButton({children: children, pill: pill, hintDisabled: hintDisabled
|
|
|
6066
6308
|
}
|
|
6067
6309
|
|
|
6068
6310
|
function useFieldCommit({entry: entry, editability: editability}) {
|
|
6069
|
-
const {editFieldFor: editFieldFor} = useWorkflowContext(), target =
|
|
6311
|
+
const {editFieldFor: editFieldFor} = useWorkflowContext(), target = editFieldTarget(editability);
|
|
6070
6312
|
return {
|
|
6071
6313
|
set: value => editFieldFor(entry.instance._id, {
|
|
6072
6314
|
target: target,
|
|
@@ -6282,8 +6524,9 @@ function AssigneePill({entry: entry, pill: pill, editability: editability}) {
|
|
|
6282
6524
|
/* @__PURE__ */
|
|
6283
6525
|
return jsx(PillPopover, {
|
|
6284
6526
|
content: /* @__PURE__ */ jsx(AssigneePicker, {
|
|
6285
|
-
|
|
6286
|
-
|
|
6527
|
+
onChange: next => {
|
|
6528
|
+
const changed = changedAssignee(current ? [ current ] : [], next);
|
|
6529
|
+
changed && (setOpen(!1), pick(changed));
|
|
6287
6530
|
},
|
|
6288
6531
|
value: current ? [ current ] : []
|
|
6289
6532
|
}),
|
|
@@ -6302,10 +6545,8 @@ function AssigneesPill({entry: entry, pill: pill, editability: editability}) {
|
|
|
6302
6545
|
/* @__PURE__ */
|
|
6303
6546
|
return jsx(PillPopover, {
|
|
6304
6547
|
content: /* @__PURE__ */ jsx(AssigneePicker, {
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
const next = current.some(a => sameAssignee(a, assignee)) ? current.filter(a => !sameAssignee(a, assignee)) : [ ...current, assignee ];
|
|
6308
|
-
save(() => set(next));
|
|
6548
|
+
onChange: next => {
|
|
6549
|
+
saving || save(() => set(next));
|
|
6309
6550
|
},
|
|
6310
6551
|
value: current
|
|
6311
6552
|
}),
|
|
@@ -6410,15 +6651,15 @@ function Hairline({weight: weight, style: style}) {
|
|
|
6410
6651
|
});
|
|
6411
6652
|
}
|
|
6412
6653
|
|
|
6413
|
-
function CollapsibleBand({header: header, children: children, background: background = !1, defaultOpen: defaultOpen = !0, sticky: sticky = !1, title: title}) {
|
|
6414
|
-
const [
|
|
6654
|
+
function CollapsibleBand({header: header, children: children, background: background = !1, defaultOpen: defaultOpen = !0, onToggle: onToggle, open: controlledOpen, sticky: sticky = !1, title: title}) {
|
|
6655
|
+
const [heldOpen, setHeldOpen] = useState(defaultOpen), open = controlledOpen ?? heldOpen, toggle = onToggle ?? (() => setHeldOpen(value => !value)), verb = open ? "Collapse" : "Expand";
|
|
6415
6656
|
/* @__PURE__ */
|
|
6416
6657
|
return jsxs(Stack, {
|
|
6417
6658
|
gap: 1,
|
|
6418
6659
|
children: [
|
|
6419
6660
|
/* @__PURE__ */ jsx(Card, {
|
|
6420
6661
|
onDoubleClick: event => {
|
|
6421
|
-
event.target instanceof Element && event.target.closest("a, button") ||
|
|
6662
|
+
event.target instanceof Element && event.target.closest("a, button") || toggle();
|
|
6422
6663
|
},
|
|
6423
6664
|
padding: 1,
|
|
6424
6665
|
radius: 3,
|
|
@@ -6439,7 +6680,7 @@ function CollapsibleBand({header: header, children: children, background: backgr
|
|
|
6439
6680
|
fontSize: 1,
|
|
6440
6681
|
icon: open ? ChevronDownIcon : ChevronRightIcon,
|
|
6441
6682
|
mode: "bleed",
|
|
6442
|
-
onClick:
|
|
6683
|
+
onClick: toggle,
|
|
6443
6684
|
padding: 2
|
|
6444
6685
|
}), header ]
|
|
6445
6686
|
})
|
|
@@ -7350,7 +7591,12 @@ function StageSection({entry: entry, onOpenActivity: onOpenActivity}) {
|
|
|
7350
7591
|
}
|
|
7351
7592
|
|
|
7352
7593
|
const VIEW_TAB_CODEC = workflowsTabCodec([ "overview", "for-me" ]), WorkflowsView = props => {
|
|
7353
|
-
const {documentId: documentId, schemaType: schemaType} = props, {isDocResolved: isDocResolved, mappings: mappings, discoveryInvalid: discoveryInvalid} = useWorkflowContext(), {entries: entries} = useWorkflowsForDocument(documentId),
|
|
7594
|
+
const {documentId: documentId, schemaType: schemaType} = props, {isDocResolved: isDocResolved, mappings: mappings, discoveryInvalid: discoveryInvalid} = useWorkflowContext(), {entries: entries} = useWorkflowsForDocument(documentId), {view: view} = useWorkflowsTab();
|
|
7595
|
+
useLogEventOnMount(WorkflowDocumentViewOpened, {
|
|
7596
|
+
tab: view,
|
|
7597
|
+
via: "open"
|
|
7598
|
+
});
|
|
7599
|
+
const resolved = isDocResolved(documentId), docTypeMappings = mappingsForDocType(mappings, schemaType.name);
|
|
7354
7600
|
if (entries.length === 0) return discoveryInvalid !== void 0 ? /* @__PURE__ */ jsx(Box, {
|
|
7355
7601
|
padding: 4,
|
|
7356
7602
|
children: /* @__PURE__ */ jsx(InvalidDocNotice, {
|
|
@@ -7428,7 +7674,7 @@ function useOpenActivity(entries) {
|
|
|
7428
7674
|
}
|
|
7429
7675
|
|
|
7430
7676
|
function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappings: docTypeMappings, initialValue: initialValue}) {
|
|
7431
|
-
const identity = useAssignmentIdentity(), panelId = useId(), {params: params} = usePaneRouter(), {view: view, setView: setView} = useWorkflowsTab(), {openActivity: openActivity, setOpenActivity: setOpenActivity, dialogEntry: dialogEntry} = useOpenActivity(entries), active = entries.filter(isLiveEntry), finished = entries.filter(e => !isLiveEntry(e)), forMe = forMeWorkOf(active, identity), [landing] = useState(() => focusedLanding(params?.[WORKFLOWS_FOCUS_PARAM], entries.map(e => e.instance._id))), assignedWorkUnknown = active.some(e => e.invalid !== void 0), booting = useDelayedFlag(active.some(e => !e.ready && e.invalid === void 0), BOOT_CUE_DELAY_MS), sectionFor = e => /* @__PURE__ */ jsx(WorkflowInstanceSection, {
|
|
7677
|
+
const identity = useAssignmentIdentity(), panelId = useId(), {params: params} = usePaneRouter(), {view: view, setView: setView} = useWorkflowsTab(), telemetry = useWorkflowTelemetry(), {openActivity: openActivity, setOpenActivity: setOpenActivity, dialogEntry: dialogEntry} = useOpenActivity(entries), active = entries.filter(isLiveEntry), finished = entries.filter(e => !isLiveEntry(e)), forMe = forMeWorkOf(active, identity), [landing] = useState(() => focusedLanding(params?.[WORKFLOWS_FOCUS_PARAM], entries.map(e => e.instance._id))), assignedWorkUnknown = active.some(e => e.invalid !== void 0), booting = useDelayedFlag(active.some(e => !e.ready && e.invalid === void 0), BOOT_CUE_DELAY_MS), sectionFor = e => /* @__PURE__ */ jsx(WorkflowInstanceSection, {
|
|
7432
7678
|
defaultOpen: landingDefaultOpen(landing, e.instance._id),
|
|
7433
7679
|
entry: e,
|
|
7434
7680
|
onOpenActivity: activityName => setOpenActivity({
|
|
@@ -7462,6 +7708,7 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7462
7708
|
initialValue: initialValue,
|
|
7463
7709
|
mappings: docTypeMappings,
|
|
7464
7710
|
mode: "bleed",
|
|
7711
|
+
source: "document-view-header",
|
|
7465
7712
|
tone: "default"
|
|
7466
7713
|
})
|
|
7467
7714
|
}),
|
|
@@ -7470,7 +7717,12 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7470
7717
|
/* @__PURE__ */ jsx(TabSwitch, {
|
|
7471
7718
|
ariaControls: `${panelId}-panel`,
|
|
7472
7719
|
idPrefix: panelId,
|
|
7473
|
-
onSelect:
|
|
7720
|
+
onSelect: next => {
|
|
7721
|
+
next !== view && telemetry.log(WorkflowDocumentViewOpened, {
|
|
7722
|
+
tab: next,
|
|
7723
|
+
via: "tab-switch"
|
|
7724
|
+
}), setView(next);
|
|
7725
|
+
},
|
|
7474
7726
|
options: [ {
|
|
7475
7727
|
value: "overview",
|
|
7476
7728
|
label: "Overview"
|
|
@@ -7544,6 +7796,7 @@ function OverviewEmptyState({mappings: mappings, docId: docId, initialValue: ini
|
|
|
7544
7796
|
label: "Start workflow",
|
|
7545
7797
|
mappings: mappings,
|
|
7546
7798
|
mode: "ghost",
|
|
7799
|
+
source: "document-view-empty-state",
|
|
7547
7800
|
tone: "default"
|
|
7548
7801
|
})
|
|
7549
7802
|
},
|
|
@@ -7577,7 +7830,8 @@ function SectionActivityDialog({entry: entry, activityName: activityName, onClos
|
|
|
7577
7830
|
breadcrumb: instanceBreadcrumb(instance, definition),
|
|
7578
7831
|
definition: definition,
|
|
7579
7832
|
entry: entry,
|
|
7580
|
-
onClose: onClose
|
|
7833
|
+
onClose: onClose,
|
|
7834
|
+
source: "document-view"
|
|
7581
7835
|
});
|
|
7582
7836
|
}
|
|
7583
7837
|
|
|
@@ -7659,13 +7913,61 @@ function workflowIssue(args) {
|
|
|
7659
7913
|
if (!isInputSourced(subject)) return `autoStart: "${docType}" → workflow "${name}" has a self-filling subject (not caller-provided), so the document can't be its subject — skipped.`;
|
|
7660
7914
|
}
|
|
7661
7915
|
|
|
7916
|
+
function actualType$(previews, bareId) {
|
|
7917
|
+
return previews.unstable_observeDocumentPairAvailability(bareId).pipe(switchMap(({draft: draft, published: published}) => draft.available ? previews.observeDocumentTypeFromId(getDraftId(bareId)) : published.available ? previews.observeDocumentTypeFromId(bareId) : draft.reason === "PERMISSION_DENIED" || published.reason === "PERMISSION_DENIED" ? of(void 0) : previews.unstable_observeVersionDocumentIds(bareId).pipe(switchMap(([firstVersionId]) => firstVersionId === void 0 ? of(null) : previews.observeDocumentTypeFromId(firstVersionId)))), distinctUntilChanged());
|
|
7918
|
+
}
|
|
7919
|
+
|
|
7920
|
+
const REBUILD_DELAY_MS = 5e3;
|
|
7921
|
+
|
|
7922
|
+
function createActualTypeProbeStore(previews) {
|
|
7923
|
+
const verdicts = /* @__PURE__ */ new Map, live = /* @__PURE__ */ new Map, listeners = /* @__PURE__ */ new Set, notify = () => {
|
|
7924
|
+
for (const listener of [ ...listeners ]) listener();
|
|
7925
|
+
}, start = (bareId, entry) => actualType$(previews, bareId).subscribe({
|
|
7926
|
+
next: value => {
|
|
7927
|
+
verdicts.has(bareId) && verdicts.get(bareId) === value || (verdicts.set(bareId, value),
|
|
7928
|
+
notify());
|
|
7929
|
+
},
|
|
7930
|
+
error: err => {
|
|
7931
|
+
console.error(`[workflow-studio-plugin] actual-type probe for "${bareId}" failed:`, err),
|
|
7932
|
+
entry.subscription = void 0, entry.rebuildTimer = setTimeout(() => {
|
|
7933
|
+
entry.rebuildTimer = void 0, !(live.get(bareId) !== entry || entry.count === 0) && (entry.subscription = start(bareId, entry));
|
|
7934
|
+
}, REBUILD_DELAY_MS);
|
|
7935
|
+
}
|
|
7936
|
+
});
|
|
7937
|
+
return {
|
|
7938
|
+
subscribe(listener) {
|
|
7939
|
+
return listeners.add(listener), () => {
|
|
7940
|
+
listeners.delete(listener);
|
|
7941
|
+
};
|
|
7942
|
+
},
|
|
7943
|
+
read: bareId => verdicts.get(bareId),
|
|
7944
|
+
track(bareId) {
|
|
7945
|
+
let entry = live.get(bareId);
|
|
7946
|
+
if (entry === void 0) {
|
|
7947
|
+
const created = {
|
|
7948
|
+
count: 0,
|
|
7949
|
+
subscription: void 0,
|
|
7950
|
+
rebuildTimer: void 0
|
|
7951
|
+
};
|
|
7952
|
+
live.set(bareId, created), created.subscription = start(bareId, created), entry = created;
|
|
7953
|
+
}
|
|
7954
|
+
entry.count += 1;
|
|
7955
|
+
let released = !1;
|
|
7956
|
+
return () => {
|
|
7957
|
+
released || (released = !0, entry.count -= 1, !(entry.count > 0) && (entry.subscription?.unsubscribe(),
|
|
7958
|
+
entry.rebuildTimer !== void 0 && clearTimeout(entry.rebuildTimer), live.get(bareId) === entry && live.delete(bareId)));
|
|
7959
|
+
};
|
|
7960
|
+
}
|
|
7961
|
+
};
|
|
7962
|
+
}
|
|
7963
|
+
|
|
7662
7964
|
function contentDocumentTypes(schema) {
|
|
7663
7965
|
return schema.getTypeNames().filter(name => schema.get(name)?.type?.name === "document" && !WORKFLOW_SYSTEM_TYPES.includes(name));
|
|
7664
7966
|
}
|
|
7665
7967
|
|
|
7666
7968
|
async function readDeployedDefinitions(engine) {
|
|
7667
7969
|
return (await engine.query({
|
|
7668
|
-
groq:
|
|
7970
|
+
groq: latestDefinitionsGroq()
|
|
7669
7971
|
})).map(assertReadableModel);
|
|
7670
7972
|
}
|
|
7671
7973
|
|
|
@@ -7999,7 +8301,7 @@ function WorkflowProvider(props) {
|
|
|
7999
8301
|
setSeeded(prev => new Map(prev).set(instance._id, instance));
|
|
8000
8302
|
}, []), [startRequest2, setStartRequest] = useState(void 0), openStartDialog = useCallback(r => setStartRequest(r), []), closeStartDialog = useCallback(() => setStartRequest(void 0), []), [entriesStore] = useState(createEntriesStore);
|
|
8001
8303
|
useEffect(() => () => entriesStore.dispose(), [ entriesStore ]);
|
|
8002
|
-
const onReport = useCallback((instanceId, report) => {
|
|
8304
|
+
const previewStore = useDocumentPreviewStore(), actualTypes = useMemo(() => createActualTypeProbeStore(previewStore), [ previewStore ]), onReport = useCallback((instanceId, report) => {
|
|
8003
8305
|
entriesStore.report(instanceId, report);
|
|
8004
8306
|
}, [ entriesStore ]), drainRef = useRef(void 0), drainCommitted = useCallback(async instanceId => {
|
|
8005
8307
|
try {
|
|
@@ -8082,6 +8384,7 @@ function WorkflowProvider(props) {
|
|
|
8082
8384
|
unregister: unregister,
|
|
8083
8385
|
isDocResolved: isDocResolved,
|
|
8084
8386
|
entries: entriesStore,
|
|
8387
|
+
actualTypes: actualTypes,
|
|
8085
8388
|
requestInstance: requestInstance,
|
|
8086
8389
|
releaseInstance: releaseInstance,
|
|
8087
8390
|
requestEvaluation: requestEvaluation,
|
|
@@ -8108,7 +8411,7 @@ function WorkflowProvider(props) {
|
|
|
8108
8411
|
effectHandlers: engine.effectHandlers,
|
|
8109
8412
|
autoStartByType: autoStartByType,
|
|
8110
8413
|
autoStartDefinitions: autoStartDefinitions
|
|
8111
|
-
}), [ register, unregister, isDocResolved, entriesStore, requestInstance, releaseInstance, requestEvaluation, releaseEvaluation, seedInstance, openStartDialog, closeStartDialog, startRequest2, loading, discoveryInvalid, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding, mappings, issues, starts, fields, latestVersions, autoStartByType, autoStartDefinitions ]);
|
|
8414
|
+
}), [ 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 ]);
|
|
8112
8415
|
/* @__PURE__ */
|
|
8113
8416
|
return jsxs(WorkflowContext.Provider, {
|
|
8114
8417
|
value: value,
|
|
@@ -8581,12 +8884,12 @@ function DocRefsFieldInput({entry: entry, mappedType: mappedType, value: value,
|
|
|
8581
8884
|
}
|
|
8582
8885
|
|
|
8583
8886
|
function NotesStartInput({onChange: onChange}) {
|
|
8584
|
-
const
|
|
8887
|
+
const selfActor = useSelfActor(), [body, setBody] = useState(""), update = next => {
|
|
8585
8888
|
setBody(next);
|
|
8586
8889
|
const trimmed = next.trim();
|
|
8587
8890
|
onChange(trimmed === "" ? [] : [ noteRow({
|
|
8588
8891
|
body: trimmed,
|
|
8589
|
-
actor:
|
|
8892
|
+
actor: selfActor,
|
|
8590
8893
|
at: /* @__PURE__ */ (new Date).toISOString()
|
|
8591
8894
|
}) ]);
|
|
8592
8895
|
};
|
|
@@ -8795,7 +9098,7 @@ function handleStartError(args) {
|
|
|
8795
9098
|
toast.push({
|
|
8796
9099
|
status: "warning",
|
|
8797
9100
|
title: `${label} can't be started right now`,
|
|
8798
|
-
description:
|
|
9101
|
+
description: outcome.description
|
|
8799
9102
|
});
|
|
8800
9103
|
return;
|
|
8801
9104
|
}
|
|
@@ -8807,7 +9110,7 @@ function handleStartError(args) {
|
|
|
8807
9110
|
}
|
|
8808
9111
|
|
|
8809
9112
|
function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
8810
|
-
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} = usePerspective(), releaseId = boundReleaseId(mapping, selectedReleaseId), [values, setValues] = useState({}), [attempt, setAttempt] = useState(void 0), starting = attempt !== void 0, [heldInstanceId, setHeldInstanceId] = useState(void 0), [startNew, setStartNew] = useState(!1), {entries: entries} = useWorkflowsForDocument(subjectDocId), resumeEntry = presentedResumeEntry({
|
|
9113
|
+
const {definition: definitionName, label: label, mapping: mapping, subjectDocId: subjectDocId} = request, {engine: engine, binding: binding, seedInstance: seedInstance} = useWorkflowContext(), telemetry = useWorkflowTelemetry(), toast = useClosableToast(), {def: definition, error: definitionError} = useLatestDefinition(definitionName), {selectedReleaseId: selectedReleaseId} = usePerspective(), releaseId = boundReleaseId(mapping, selectedReleaseId), [values, setValues] = useState({}), [attempt, setAttempt] = useState(void 0), starting = attempt !== void 0, [heldInstanceId, setHeldInstanceId] = useState(void 0), [startNew, setStartNew] = useState(!1), {entries: entries} = useWorkflowsForDocument(subjectDocId), resumeEntry = presentedResumeEntry({
|
|
8811
9114
|
entries: entries,
|
|
8812
9115
|
definitionName: definitionName,
|
|
8813
9116
|
heldInstanceId: heldInstanceId,
|
|
@@ -8830,7 +9133,10 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
|
8830
9133
|
[name]: v
|
|
8831
9134
|
})), heldInstanceId !== void 0 && declineResume();
|
|
8832
9135
|
}, onStart = async () => {
|
|
8833
|
-
|
|
9136
|
+
telemetry.log(WorkflowStartDialogSubmitted, {
|
|
9137
|
+
source: request.source,
|
|
9138
|
+
resumed: resuming
|
|
9139
|
+
}), setAttempt({
|
|
8834
9140
|
resume: resumeEntry
|
|
8835
9141
|
});
|
|
8836
9142
|
const instanceId = resumeEntry?.instance._id ?? heldInstanceId ?? instanceDocId(binding.tag);
|
|
@@ -8910,8 +9216,9 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
|
8910
9216
|
}
|
|
8911
9217
|
|
|
8912
9218
|
function StartWorkflowDialog({request: request, onClose: onClose}) {
|
|
8913
|
-
|
|
8914
|
-
|
|
9219
|
+
return useLogEventOnMount(WorkflowStartDialogOpened, {
|
|
9220
|
+
source: request.source
|
|
9221
|
+
}), /* @__PURE__ */ jsx(Dialog, {
|
|
8915
9222
|
header: `Start ${request.label}`,
|
|
8916
9223
|
id: "start-workflow",
|
|
8917
9224
|
onClose: onClose,
|
|
@@ -9050,7 +9357,7 @@ function AutoStartGate(props) {
|
|
|
9050
9357
|
}
|
|
9051
9358
|
|
|
9052
9359
|
function AutoStartDriver(props) {
|
|
9053
|
-
const {rawDocId: rawDocId, docType: docType, workflows: workflows, value: value, fallback: fallback} = props, {isDocResolved: isDocResolved, autoStartDefinitions: autoStartDefinitions, engine: engine, binding: binding, seedInstance: seedInstance} = useWorkflowContext(), observer = useStudioObserver({
|
|
9360
|
+
const {rawDocId: rawDocId, docType: docType, workflows: workflows, value: value, fallback: fallback} = props, {isDocResolved: isDocResolved, autoStartDefinitions: autoStartDefinitions, engine: engine, binding: binding, seedInstance: seedInstance} = useWorkflowContext(), telemetry = useWorkflowTelemetry(), observer = useStudioObserver({
|
|
9054
9361
|
engine: engine
|
|
9055
9362
|
}), {selectedReleaseId: selectedReleaseId} = usePerspective(), {entries: entries} = useWorkflowsForDocument(rawDocId), docId = getPublishedId(rawDocId), valueRef = useRef(value);
|
|
9056
9363
|
valueRef.current = value;
|
|
@@ -9064,7 +9371,7 @@ function AutoStartDriver(props) {
|
|
|
9064
9371
|
if (held !== void 0) return held;
|
|
9065
9372
|
const id = instanceDocId(binding.tag);
|
|
9066
9373
|
return instanceIds.current.set(workflow, id), id;
|
|
9067
|
-
}, [ binding.tag ]), [fired, setFired] = useState(!1), [settled, setSettled] = useState(!1), [failure, setFailure] = useState(void 0), firedRef = useRef(!1), startAll = useCallback(async values => {
|
|
9374
|
+
}, [ binding.tag ]), [fired, setFired] = useState(!1), [settled, setSettled] = useState(!1), [failure, setFailure] = useState(void 0), firedRef = useRef(!1), startAll = useCallback(async (values, mode) => {
|
|
9068
9375
|
if (!firedRef.current) {
|
|
9069
9376
|
firedRef.current = !0, setFired(!0);
|
|
9070
9377
|
try {
|
|
@@ -9076,20 +9383,25 @@ function AutoStartDriver(props) {
|
|
|
9076
9383
|
releaseId: selectedReleaseId
|
|
9077
9384
|
} : {}
|
|
9078
9385
|
});
|
|
9386
|
+
const requests = buildAutoStartRequests({
|
|
9387
|
+
workflows: pendingRef.current,
|
|
9388
|
+
definitions: autoStartDefinitions,
|
|
9389
|
+
subject: {
|
|
9390
|
+
docId: docId,
|
|
9391
|
+
type: docType
|
|
9392
|
+
},
|
|
9393
|
+
contentResource: binding.contentResource,
|
|
9394
|
+
values: values,
|
|
9395
|
+
instanceIdFor: instanceIdFor
|
|
9396
|
+
});
|
|
9397
|
+
telemetry.log(WorkflowAutoStartRan, {
|
|
9398
|
+
mode: mode,
|
|
9399
|
+
workflowCount: requests.length
|
|
9400
|
+
});
|
|
9079
9401
|
const {failure: failure2} = await runStarts({
|
|
9080
9402
|
engine: engine,
|
|
9081
9403
|
seed: seedInstance,
|
|
9082
|
-
requests:
|
|
9083
|
-
workflows: pendingRef.current,
|
|
9084
|
-
definitions: autoStartDefinitions,
|
|
9085
|
-
subject: {
|
|
9086
|
-
docId: docId,
|
|
9087
|
-
type: docType
|
|
9088
|
-
},
|
|
9089
|
-
contentResource: binding.contentResource,
|
|
9090
|
-
values: values,
|
|
9091
|
-
instanceIdFor: instanceIdFor
|
|
9092
|
-
})
|
|
9404
|
+
requests: requests
|
|
9093
9405
|
});
|
|
9094
9406
|
failure2 !== void 0 && setFailure(failure2);
|
|
9095
9407
|
} catch (err) {
|
|
@@ -9098,7 +9410,7 @@ function AutoStartDriver(props) {
|
|
|
9098
9410
|
setSettled(!0);
|
|
9099
9411
|
}
|
|
9100
9412
|
}
|
|
9101
|
-
}, [ autoStartDefinitions, docId, docType, binding, engine, observer, seedInstance, instanceIdFor, selectedReleaseId ]), retry = useCallback(() => {
|
|
9413
|
+
}, [ autoStartDefinitions, docId, docType, binding, engine, observer, seedInstance, instanceIdFor, selectedReleaseId, telemetry ]), retry = useCallback(() => {
|
|
9102
9414
|
firedRef.current = !1, setFired(!1), setSettled(!1), setFailure(void 0);
|
|
9103
9415
|
}, []), action = autoStartAction({
|
|
9104
9416
|
resolved: definitionsResolved && isDocResolved(docId),
|
|
@@ -9108,7 +9420,7 @@ function AutoStartDriver(props) {
|
|
|
9108
9420
|
settled: settled
|
|
9109
9421
|
});
|
|
9110
9422
|
return useEffect(() => {
|
|
9111
|
-
action === "silent-start" && startAll({});
|
|
9423
|
+
action === "silent-start" && startAll({}, "silent");
|
|
9112
9424
|
}, [ action, startAll ]), failure !== void 0 ? /* @__PURE__ */ jsx(AutoStartFailure, {
|
|
9113
9425
|
message: failure,
|
|
9114
9426
|
onProceed: () => setFailure(void 0),
|
|
@@ -9120,7 +9432,7 @@ function AutoStartDriver(props) {
|
|
|
9120
9432
|
docType: docType,
|
|
9121
9433
|
inputs: inputs,
|
|
9122
9434
|
onStart: values => {
|
|
9123
|
-
startAll(values);
|
|
9435
|
+
startAll(values, "collect");
|
|
9124
9436
|
},
|
|
9125
9437
|
starting: fired,
|
|
9126
9438
|
workflowCount: pending.length
|
|
@@ -9342,7 +9654,9 @@ function finishedLinesOf(entries) {
|
|
|
9342
9654
|
}
|
|
9343
9655
|
|
|
9344
9656
|
function WorkflowFormStrip(props) {
|
|
9345
|
-
const {mappings: mappings} = props, {isDocResolved: isDocResolved, discoveryInvalid: discoveryInvalid} = useWorkflowContext(), {docId: docId, entries: entries} = useWorkflowsForDocument(props.value?._id ?? null), {params: params, setParams: setParams} = usePaneRouter(),
|
|
9657
|
+
const {mappings: mappings} = props, {isDocResolved: isDocResolved, discoveryInvalid: discoveryInvalid} = useWorkflowContext(), {docId: docId, entries: entries} = useWorkflowsForDocument(props.value?._id ?? null), {params: params, setParams: setParams} = usePaneRouter(), telemetry = useWorkflowTelemetry(), openWorkflowsView = focusId => {
|
|
9658
|
+
telemetry.log(WorkflowFormStripClicked), setParams(focusedViewParams(params, focusId));
|
|
9659
|
+
}, active = entries.filter(isLiveEntry), finished = finishedLinesOf(entries), invalid = surfacedInvalid(discoveryInvalid, entries), resolved = docId !== void 0 && isDocResolved(docId);
|
|
9346
9660
|
/* @__PURE__ */
|
|
9347
9661
|
return jsxs(Stack, {
|
|
9348
9662
|
gap: 4,
|
|
@@ -9376,7 +9690,8 @@ function StripLines({active: active, docId: docId, finished: finished, initialVa
|
|
|
9376
9690
|
initialValue: initialValue,
|
|
9377
9691
|
label: "Start workflow",
|
|
9378
9692
|
mappings: mappings,
|
|
9379
|
-
mode: "bleed"
|
|
9693
|
+
mode: "bleed",
|
|
9694
|
+
source: "form-strip"
|
|
9380
9695
|
})
|
|
9381
9696
|
}) : null ]
|
|
9382
9697
|
});
|
|
@@ -9696,4 +10011,4 @@ function WorkflowRootInput(props) {
|
|
|
9696
10011
|
});
|
|
9697
10012
|
}
|
|
9698
10013
|
|
|
9699
|
-
export { AbortedBadge, ActivitiesList, ActivityDetailDialog, ActivityRow, BreadcrumbTail, CollapsibleBand, DismissablePopover, DocPreviewLink, DocRefFace, GroupHeading, HoverHint, InvalidDocNotice, LinkChip, LoadingRow, SpinnerSlot, StageChip, StageFace, StaleLock, TabSwitch, TodoItemsList, TrailingHairline, UnreadableDocsNote, activityRowProps, assigneeUserIdsOf, committedRowFace, dateControlKind, dateControlValue, definitionSnapshotOf, describeError,
|
|
10014
|
+
export { AbortedBadge, ActivitiesList, ActivityDetailDialog, ActivityRow, BreadcrumbTail, CautionNote, CollapsibleBand, DismissablePopover, DocPreviewLink, DocRefFace, GroupHeading, HoverHint, InvalidDocNotice, LinkChip, LoadingRow, SpinnerSlot, StageChip, StageFace, StaleLock, TabSwitch, TodoItemsList, TrailingHairline, UnreadableDocsNote, WORKFLOW_API_VERSION, WorkflowInstanceDetailViewed, WorkflowTaskFiltersApplied, WorkflowToolOpened, activityRowProps, assigneeUserIdsOf, committedRowFace, dateControlKind, dateControlValue, definitionSnapshotOf, describeError, findActivity, findActivityNode, formatDate, gdrLocality, instanceBreadcrumb, instanceNotice, instanceTitle, isActivityAssignedTo, isEvaluationStale, isOpenActivityStatus, openActivityGone, parseDateFieldValue, parseStoredDateValue, readDeployedDefinitions, rowAssignControlState, rowDateControlState, serializeDateFieldValue, stageTitle, stateByActivity, stopRowClick, stopRowMouseDown, useAssignmentIdentity, useClosableToast, useDefinition, useLogEventOnMount, useProjectMembers, useSaveField, useUserDisplays, useWorkflowContext, useWorkflowInstanceEntry, workflowDefaultDocumentNode, workflowStudioPlugin, workflowsTabCodec, workflowsView };
|