@sanity/workflow-studio-plugin 0.5.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +232 -0
- package/README.md +45 -63
- package/dist/_chunks-cjs/index.cjs +1046 -502
- package/dist/_chunks-cjs/workflows-tool-root.cjs +551 -59
- package/dist/_chunks-es/index.js +1064 -522
- package/dist/_chunks-es/workflows-tool-root.js +556 -62
- package/dist/index.cjs +0 -6
- package/dist/index.d.cts +16 -74
- package/dist/index.d.ts +16 -74
- package/dist/index.js +2 -2
- package/package.json +16 -9
package/dist/_chunks-es/index.js
CHANGED
|
@@ -1,37 +1,41 @@
|
|
|
1
|
-
import { tryParseGdr, resourceFromParsed, latestDeployedDefinitions, gdrRef, isSubjectEntry, isInputSourced, missingRequiredInputs, initialFieldIssues, releaseRef, refKindAcceptsTypes, rejectedRefTypes, ActionDisabledError, MutationGuardDeniedError, errorMessage, findOpenStageEntry, actionRendering, terminalState, ENGINE_API_VERSION, WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE, isTodoListEntry, isTodoListItem, isTerminalActivityStatus, describeCondition, sentenceCase, checklistLines, findCurrentActivityEntry, scalarValidationIssues, extractDocumentId, isSingleDocRefEntry, isGdr, resolveFieldEntry, isSingleDocRefKind, isNotesEntry, parseDefinitionSnapshot, StartNotSettledError, StartNotAllowedError, isUnprimed, unboundAllowedReads, explainStartAllowed, evaluateStartFilter, startKindOf, readsRootDocument, instancesQuery, assertReadableModel, isTerminalStage, DEFAULT_TRANSITION_WHEN, isStartableDefinition, acceptsDocumentType, definitionsListGroq, gdrFromResource, instanceWatchesDocument, aclPathForResource, definitionLookupGroq, instanceDocId, documentActionDenials } from "@sanity/workflow-engine";
|
|
2
|
-
|
|
3
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
4
2
|
|
|
5
3
|
import { TimelineIcon } from "@sanity/icons/Timeline";
|
|
6
4
|
|
|
7
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";
|
|
8
6
|
|
|
9
|
-
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";
|
|
10
10
|
|
|
11
11
|
import { usePaneRouter } from "sanity/structure";
|
|
12
12
|
|
|
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";
|
|
14
|
+
|
|
15
|
+
import { CheckmarkIcon } from "@sanity/icons/Checkmark";
|
|
16
|
+
|
|
17
|
+
import { CloseIcon } from "@sanity/icons/Close";
|
|
18
|
+
|
|
13
19
|
import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
|
|
14
20
|
|
|
15
|
-
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";
|
|
16
26
|
|
|
17
27
|
import { useStudioProjectUsers, useStudioObserver, useWorkflowEngine, useWorkflowInstances, useWorkflowSession } from "@sanity/workflow-studio";
|
|
18
28
|
|
|
19
|
-
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";
|
|
20
30
|
|
|
21
31
|
import { CalendarIcon } from "@sanity/icons/Calendar";
|
|
22
32
|
|
|
23
|
-
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";
|
|
24
|
-
|
|
25
33
|
import { UserIcon } from "@sanity/icons/User";
|
|
26
34
|
|
|
27
|
-
import { CloseIcon } from "@sanity/icons/Close";
|
|
28
|
-
|
|
29
35
|
import { SearchIcon } from "@sanity/icons/Search";
|
|
30
36
|
|
|
31
37
|
import { ChevronRightIcon } from "@sanity/icons/ChevronRight";
|
|
32
38
|
|
|
33
|
-
import { CheckmarkIcon } from "@sanity/icons/Checkmark";
|
|
34
|
-
|
|
35
39
|
import { EditIcon } from "@sanity/icons/Edit";
|
|
36
40
|
|
|
37
41
|
import { randomKey } from "@sanity/util/content";
|
|
@@ -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
|
|
|
@@ -87,20 +93,58 @@ function gdrLocality(id, contentResource) {
|
|
|
87
93
|
};
|
|
88
94
|
}
|
|
89
95
|
|
|
90
|
-
function
|
|
91
|
-
|
|
96
|
+
function assertUniqueWorkflowMappings(mappings) {
|
|
97
|
+
const keys = /* @__PURE__ */ new Set;
|
|
98
|
+
for (const mapping of mappings) {
|
|
99
|
+
const key = mappingKey(mapping);
|
|
100
|
+
if (keys.has(key)) throw new Error(`Duplicate workflow mapping for ${key}`);
|
|
101
|
+
keys.add(key);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function discoverWorkflowMappings(args) {
|
|
106
|
+
assertUniqueWorkflowMappings(args.overrides ?? []);
|
|
107
|
+
const discovered = latestDeployedDefinitions(args.definitions).flatMap(definition => {
|
|
108
|
+
if (!isStartableDefinition(definition)) return [];
|
|
109
|
+
const subject = (definition.fields ?? []).find(isSubjectEntry);
|
|
110
|
+
if (subject === void 0 || !isInputSourced(subject)) return [];
|
|
111
|
+
const source = {
|
|
112
|
+
fields: [ ...definition.fields ?? [] ]
|
|
113
|
+
};
|
|
114
|
+
return [ ...args.schemaContentTypes ].filter(docType => acceptsDocumentType(source, docType)).map(docType => ({
|
|
115
|
+
docType: docType,
|
|
116
|
+
definition: definition.name,
|
|
117
|
+
label: definition.title ?? definition.name
|
|
118
|
+
}));
|
|
119
|
+
}), byKey = new Map(discovered.map(mapping => [ mappingKey(mapping), mapping ]));
|
|
120
|
+
for (const override of args.overrides ?? []) {
|
|
121
|
+
const key = mappingKey(override);
|
|
122
|
+
byKey.set(key, override);
|
|
123
|
+
}
|
|
124
|
+
return [ ...byKey.values() ];
|
|
92
125
|
}
|
|
93
126
|
|
|
94
|
-
function
|
|
95
|
-
|
|
127
|
+
function mappingAutoStartMap(mappings) {
|
|
128
|
+
const byType = /* @__PURE__ */ Object.create(null);
|
|
129
|
+
for (const mapping of mappings) {
|
|
130
|
+
if (!mapping.autoStart) continue;
|
|
131
|
+
const definitions = byType[mapping.docType] ?? [];
|
|
132
|
+
byType[mapping.docType] = [ ...definitions, mapping.definition ];
|
|
133
|
+
}
|
|
134
|
+
return byType;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function mappingsForDocType(mappings, docType) {
|
|
138
|
+
return mappings.filter(m => m.docType === docType);
|
|
96
139
|
}
|
|
97
140
|
|
|
98
141
|
function mappingKey(mapping) {
|
|
99
142
|
return `${mapping.docType}::${mapping.definition}`;
|
|
100
143
|
}
|
|
101
144
|
|
|
102
|
-
function
|
|
103
|
-
|
|
145
|
+
function documentSubjectEntry(definition) {
|
|
146
|
+
const fields = definition.fields ?? [];
|
|
147
|
+
return fields.find(isSubjectEntry) ?? fields.find(entry => entry.type === "doc.ref" && entry.name === "subject");
|
|
104
148
|
}
|
|
105
149
|
|
|
106
150
|
function mappingStartBlocks(args) {
|
|
@@ -421,7 +465,7 @@ function stateByActivity(instance) {
|
|
|
421
465
|
}
|
|
422
466
|
|
|
423
467
|
function evaluationFreshness(args) {
|
|
424
|
-
return args.evaluation ? args.committed.lastChangedAt > args.evaluation.instance.lastChangedAt ? "stale" : "current" : "pending";
|
|
468
|
+
return args.evaluation ? Date.parse(args.committed.lastChangedAt) > Date.parse(args.evaluation.instance.lastChangedAt) ? "stale" : "current" : "pending";
|
|
425
469
|
}
|
|
426
470
|
|
|
427
471
|
function isEvaluationCurrent(args) {
|
|
@@ -447,50 +491,6 @@ function isLiveEntry(entry) {
|
|
|
447
491
|
return terminalState(entry.instance) === "in-flight";
|
|
448
492
|
}
|
|
449
493
|
|
|
450
|
-
const WORKFLOW_API_VERSION = ENGINE_API_VERSION, WORKFLOW_SYSTEM_TYPES = [ WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE ];
|
|
451
|
-
|
|
452
|
-
function editTargetOf(field) {
|
|
453
|
-
return {
|
|
454
|
-
scope: field.scope,
|
|
455
|
-
field: field.name,
|
|
456
|
-
...field.activity ? {
|
|
457
|
-
activity: field.activity
|
|
458
|
-
} : {}
|
|
459
|
-
};
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
const EMPTY_ENTRIES = [], WorkflowContext = createContext(null);
|
|
463
|
-
|
|
464
|
-
function useWorkflowContext() {
|
|
465
|
-
const value = useContext(WorkflowContext);
|
|
466
|
-
if (!value) throw new Error("useWorkflowContext must render inside the workflow plugin provider");
|
|
467
|
-
return value;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
function useWorkflowsForDocument(rawId) {
|
|
471
|
-
const {register: register, unregister: unregister, entries: entries} = useWorkflowContext(), docId = rawId ? getPublishedId(rawId) : void 0;
|
|
472
|
-
useEffect(() => {
|
|
473
|
-
if (docId) return register(docId), () => unregister(docId);
|
|
474
|
-
}, [ docId, register, unregister ]);
|
|
475
|
-
const list = useSyncExternalStore(entries.subscribe, useCallback(() => docId ? entries.getDocument(docId) : EMPTY_ENTRIES, [ entries, docId ]));
|
|
476
|
-
return {
|
|
477
|
-
docId: docId,
|
|
478
|
-
entries: list
|
|
479
|
-
};
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
function useHeldWorkflowEntry(instanceId) {
|
|
483
|
-
const {entries: entries} = useWorkflowContext();
|
|
484
|
-
return useSyncExternalStore(entries.subscribe, useCallback(() => instanceId ? entries.getInstance(instanceId) : void 0, [ entries, instanceId ]));
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
function useWorkflowInstanceEntry(instanceId) {
|
|
488
|
-
const {requestInstance: requestInstance, releaseInstance: releaseInstance} = useWorkflowContext();
|
|
489
|
-
return useEffect(() => {
|
|
490
|
-
if (instanceId) return requestInstance(instanceId), () => releaseInstance(instanceId);
|
|
491
|
-
}, [ instanceId, requestInstance, releaseInstance ]), useHeldWorkflowEntry(instanceId);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
494
|
const isTodoDone = item => item.status === "done", toggledTodoStatus = item => isTodoDone(item) ? "open" : "done";
|
|
495
495
|
|
|
496
496
|
function isTodoOverdue(item, today = /* @__PURE__ */ new Date) {
|
|
@@ -566,7 +566,7 @@ function buildTickIndex(evaluation) {
|
|
|
566
566
|
function todoFieldEditability(args) {
|
|
567
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));
|
|
568
568
|
return match ? match.editable ? {
|
|
569
|
-
editTarget:
|
|
569
|
+
editTarget: editFieldTarget(match)
|
|
570
570
|
} : match.disabledReason === void 0 ? {} : {
|
|
571
571
|
editDisabledReason: match.disabledReason
|
|
572
572
|
} : {};
|
|
@@ -631,8 +631,8 @@ function assigneeMatches(member, who) {
|
|
|
631
631
|
return member.type === "user" ? member.id === who.userId : who.roles.includes(member.role);
|
|
632
632
|
}
|
|
633
633
|
|
|
634
|
-
function
|
|
635
|
-
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)));
|
|
636
636
|
}
|
|
637
637
|
|
|
638
638
|
function isAssigneeShape(value) {
|
|
@@ -761,13 +761,29 @@ function concludesHere(actionEval, activityName) {
|
|
|
761
761
|
return changesOwnStatus(actionEval.action, activityName) || actionEval.firing?.exitsStage === !0;
|
|
762
762
|
}
|
|
763
763
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
tone: "
|
|
764
|
+
const SEMANTIC_FACE = {
|
|
765
|
+
"decision.accept": {
|
|
766
|
+
tone: "positive",
|
|
767
|
+
icon: CheckmarkIcon
|
|
768
|
+
},
|
|
769
|
+
"decision.decline": {
|
|
770
|
+
tone: "caution",
|
|
771
|
+
icon: CloseIcon
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
|
|
775
|
+
function actionButtonFace(args) {
|
|
776
|
+
const mode = concludesHere(args.actionEval, args.activityName) ? "default" : "ghost";
|
|
777
|
+
if (actionAdvanceStatus(args.actionEval.action, args.activityName) === "failed") return {
|
|
778
|
+
mode: mode,
|
|
779
|
+
tone: "critical",
|
|
780
|
+
icon: void 0
|
|
781
|
+
};
|
|
782
|
+
const [semantic] = args.actionEval.semantics ?? [], face = semantic === void 0 ? void 0 : SEMANTIC_FACE[semantic];
|
|
783
|
+
return {
|
|
784
|
+
mode: mode,
|
|
785
|
+
tone: face?.tone ?? "default",
|
|
786
|
+
icon: face?.icon
|
|
771
787
|
};
|
|
772
788
|
}
|
|
773
789
|
|
|
@@ -991,6 +1007,112 @@ function deriveActivityDetail(args) {
|
|
|
991
1007
|
};
|
|
992
1008
|
}
|
|
993
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
|
+
|
|
994
1116
|
function isEmptyValue(value) {
|
|
995
1117
|
return value == null || value === "" || Array.isArray(value) && value.length === 0;
|
|
996
1118
|
}
|
|
@@ -1022,10 +1144,23 @@ function personActor(user) {
|
|
|
1022
1144
|
};
|
|
1023
1145
|
}
|
|
1024
1146
|
|
|
1147
|
+
const memberIndexes = /* @__PURE__ */ new WeakMap;
|
|
1148
|
+
|
|
1149
|
+
function memberIndex(members) {
|
|
1150
|
+
const cached = memberIndexes.get(members);
|
|
1151
|
+
if (cached) return cached;
|
|
1152
|
+
const created = new Map(members.map(member => [ member.id, member ]));
|
|
1153
|
+
return memberIndexes.set(members, created), created;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1025
1156
|
const selfUserFor = (id, me) => me != null && me.id === id ? me : void 0;
|
|
1026
1157
|
|
|
1158
|
+
function globalIdOf(users, projectScopedId) {
|
|
1159
|
+
return users.find(user => user.membership.id === projectScopedId)?.profile?.sanityUserId ?? projectScopedId;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1027
1162
|
function userDisplayFor(args) {
|
|
1028
|
-
const
|
|
1163
|
+
const matchId = args.matchId ?? args.id, member = memberIndex(args.members).get(matchId), self = selfUserFor(matchId, args.me);
|
|
1029
1164
|
return {
|
|
1030
1165
|
id: args.id,
|
|
1031
1166
|
name: member?.displayName ?? self?.name ?? args.id,
|
|
@@ -1034,42 +1169,69 @@ function userDisplayFor(args) {
|
|
|
1034
1169
|
}
|
|
1035
1170
|
|
|
1036
1171
|
function useUserDisplays(ids) {
|
|
1037
|
-
const {members: members} = useProjectMembers(),
|
|
1038
|
-
|
|
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 ]);
|
|
1176
|
+
return useMemo(() => ids.map(id => userDisplayFor({
|
|
1039
1177
|
id: id,
|
|
1040
1178
|
members: members,
|
|
1041
|
-
me: me
|
|
1042
|
-
|
|
1179
|
+
me: me,
|
|
1180
|
+
matchId: globalIdOf(users, id)
|
|
1181
|
+
})), [ ids, me, members, users ]);
|
|
1043
1182
|
}
|
|
1044
1183
|
|
|
1045
1184
|
function useUserDisplay(id) {
|
|
1046
|
-
const
|
|
1185
|
+
const ids = useMemo(() => [ id ], [ id ]), [display] = useUserDisplays(ids);
|
|
1047
1186
|
return display ?? {
|
|
1048
1187
|
name: id,
|
|
1049
1188
|
imageUrl: void 0
|
|
1050
1189
|
};
|
|
1051
1190
|
}
|
|
1052
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 {
|
|
1203
|
+
id: id,
|
|
1204
|
+
roles: me.roles ?? []
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
function useSelfActor() {
|
|
1209
|
+
const self = useBridgedSelf();
|
|
1210
|
+
return self === void 0 ? void 0 : personActor(self);
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1053
1213
|
function useAssignmentIdentity() {
|
|
1054
|
-
const
|
|
1055
|
-
if (
|
|
1056
|
-
userId:
|
|
1057
|
-
roles:
|
|
1214
|
+
const self = useBridgedSelf();
|
|
1215
|
+
if (self !== void 0) return {
|
|
1216
|
+
userId: self.id,
|
|
1217
|
+
roles: self.roles.map(r => r.name)
|
|
1058
1218
|
};
|
|
1059
1219
|
}
|
|
1060
1220
|
|
|
1221
|
+
const projectMembersByUsers = /* @__PURE__ */ new WeakMap;
|
|
1222
|
+
|
|
1061
1223
|
function projectMembersFrom(users) {
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
roles: (membership.roles ?? []).map(role => role.name)
|
|
1224
|
+
const cached = projectMembersByUsers.get(users);
|
|
1225
|
+
if (cached) return cached;
|
|
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
|
|
1072
1233
|
}));
|
|
1234
|
+
return projectMembersByUsers.set(users, members), members;
|
|
1073
1235
|
}
|
|
1074
1236
|
|
|
1075
1237
|
function useProjectMembers() {
|
|
@@ -1395,12 +1557,12 @@ function MemberPicker({selectedIds: selectedIds, onSelect: onSelect, unassignRow
|
|
|
1395
1557
|
});
|
|
1396
1558
|
}
|
|
1397
1559
|
|
|
1398
|
-
function AssigneePicker({value: value,
|
|
1560
|
+
function AssigneePicker({value: value, onChange: onChange}) {
|
|
1399
1561
|
const state = useProjectMembers();
|
|
1400
1562
|
/* @__PURE__ */
|
|
1401
1563
|
return jsx(AssigneePicker$1, {
|
|
1402
1564
|
...state,
|
|
1403
|
-
|
|
1565
|
+
onChange: onChange,
|
|
1404
1566
|
value: value
|
|
1405
1567
|
});
|
|
1406
1568
|
}
|
|
@@ -1511,7 +1673,7 @@ function DocPicker({value: value, onChange: onChange, types: types, readOnly: re
|
|
|
1511
1673
|
children: /* @__PURE__ */ jsx(Box, {
|
|
1512
1674
|
flex: 1,
|
|
1513
1675
|
children: /* @__PURE__ */ jsx(PreviewOrId, {
|
|
1514
|
-
id:
|
|
1676
|
+
id: toBareId(value.id),
|
|
1515
1677
|
type: value.type
|
|
1516
1678
|
})
|
|
1517
1679
|
})
|
|
@@ -1607,7 +1769,7 @@ function DocRefsInput({value: value, onChange: onChange, types: types}) {
|
|
|
1607
1769
|
/* @__PURE__ */ jsx(Box, {
|
|
1608
1770
|
flex: 1,
|
|
1609
1771
|
children: /* @__PURE__ */ jsx(PreviewOrId, {
|
|
1610
|
-
id:
|
|
1772
|
+
id: toBareId(ref.id),
|
|
1611
1773
|
type: ref.type
|
|
1612
1774
|
})
|
|
1613
1775
|
}),
|
|
@@ -1730,7 +1892,7 @@ function useActionClusterPending() {
|
|
|
1730
1892
|
}
|
|
1731
1893
|
|
|
1732
1894
|
function useFireAction(args) {
|
|
1733
|
-
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;
|
|
1734
1896
|
return {
|
|
1735
1897
|
fire: useCallback(async params => {
|
|
1736
1898
|
if (pending) return !1;
|
|
@@ -1745,6 +1907,11 @@ function useFireAction(args) {
|
|
|
1745
1907
|
}), toast.push({
|
|
1746
1908
|
status: "success",
|
|
1747
1909
|
title: `${label} done`
|
|
1910
|
+
}), telemetry.log(WorkflowActionControlUsed, {
|
|
1911
|
+
instanceId: instanceId,
|
|
1912
|
+
surface: surface,
|
|
1913
|
+
viaMenu: viaMenu,
|
|
1914
|
+
success: !0
|
|
1748
1915
|
}), !0;
|
|
1749
1916
|
} catch (err) {
|
|
1750
1917
|
return console.error(`[workflow-studio-plugin] firing "${action}" on "${activity}" failed:`, err),
|
|
@@ -1752,15 +1919,29 @@ function useFireAction(args) {
|
|
|
1752
1919
|
status: "error",
|
|
1753
1920
|
title: `${label} failed`,
|
|
1754
1921
|
description: describeError(err)
|
|
1922
|
+
}), telemetry.log(WorkflowActionControlUsed, {
|
|
1923
|
+
instanceId: instanceId,
|
|
1924
|
+
surface: surface,
|
|
1925
|
+
viaMenu: viaMenu,
|
|
1926
|
+
success: !1
|
|
1755
1927
|
}), !1;
|
|
1756
1928
|
} finally {
|
|
1757
1929
|
setLocalPending(!1), cluster?.onFireChange(!1);
|
|
1758
1930
|
}
|
|
1759
|
-
}, [ fireActionFor, instanceId, activity, action, label, pending, toast, cluster ]),
|
|
1931
|
+
}, [ fireActionFor, instanceId, activity, action, label, pending, toast, cluster, telemetry, surface, viaMenu ]),
|
|
1760
1932
|
pending: pending
|
|
1761
1933
|
};
|
|
1762
1934
|
}
|
|
1763
1935
|
|
|
1936
|
+
const ACTION_ICON_GAP = 2;
|
|
1937
|
+
|
|
1938
|
+
function actionIconProps(icon) {
|
|
1939
|
+
return icon ? {
|
|
1940
|
+
gap: ACTION_ICON_GAP,
|
|
1941
|
+
icon: icon
|
|
1942
|
+
} : {};
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1764
1945
|
function stopRowMouseDown(e) {
|
|
1765
1946
|
e.preventDefault(), e.stopPropagation();
|
|
1766
1947
|
}
|
|
@@ -1788,18 +1969,21 @@ function RowClickShield({active: active, children: children}) {
|
|
|
1788
1969
|
});
|
|
1789
1970
|
}
|
|
1790
1971
|
|
|
1791
|
-
function FireButton({instanceId: instanceId, activity: activity, action: action, label: label, mode: mode = "default", chrome: chrome, tone: tone = "default"}) {
|
|
1972
|
+
function FireButton({instanceId: instanceId, activity: activity, action: action, label: label, surface: surface, mode: mode = "default", chrome: chrome, tone: tone = "default", icon: icon}) {
|
|
1792
1973
|
const {fire: fire, pending: pending} = useFireAction({
|
|
1793
1974
|
instanceId: instanceId,
|
|
1794
1975
|
activity: activity,
|
|
1795
1976
|
action: action,
|
|
1796
|
-
label: label
|
|
1977
|
+
label: label,
|
|
1978
|
+
surface: surface,
|
|
1979
|
+
viaMenu: !1
|
|
1797
1980
|
}), handleClick = e => {
|
|
1798
1981
|
chrome?.inButtonCard === !0 && e.stopPropagation(), !pending && fire();
|
|
1799
1982
|
};
|
|
1800
1983
|
/* @__PURE__ */
|
|
1801
1984
|
return jsx(Button, {
|
|
1802
1985
|
fontSize: 1,
|
|
1986
|
+
...actionIconProps(icon),
|
|
1803
1987
|
loading: pending,
|
|
1804
1988
|
mode: chrome?.mode ?? mode,
|
|
1805
1989
|
onClick: handleClick,
|
|
@@ -1813,31 +1997,39 @@ function FireButton({instanceId: instanceId, activity: activity, action: action,
|
|
|
1813
1997
|
});
|
|
1814
1998
|
}
|
|
1815
1999
|
|
|
1816
|
-
function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
2000
|
+
function ActivityActionRow({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
1817
2001
|
const rowKind = actionRowKind(actionEval);
|
|
1818
2002
|
return rowKind.kind === "disabled" ? /* @__PURE__ */ jsx(DisabledActionButton, {
|
|
1819
2003
|
actionEval: actionEval,
|
|
2004
|
+
activity: activity,
|
|
1820
2005
|
chrome: chrome
|
|
1821
2006
|
}) : rowKind.kind === "plain" ? /* @__PURE__ */ jsx(PlainActionButton, {
|
|
1822
2007
|
actionEval: actionEval,
|
|
1823
2008
|
instanceId: instanceId,
|
|
1824
2009
|
activity: activity,
|
|
1825
|
-
chrome: chrome
|
|
2010
|
+
chrome: chrome,
|
|
2011
|
+
surface: surface
|
|
1826
2012
|
}) : /* @__PURE__ */ jsx(ParamsActionButton, {
|
|
1827
2013
|
actionEval: actionEval,
|
|
1828
2014
|
instanceId: instanceId,
|
|
1829
2015
|
activity: activity,
|
|
1830
|
-
chrome: chrome
|
|
2016
|
+
chrome: chrome,
|
|
2017
|
+
surface: surface
|
|
1831
2018
|
});
|
|
1832
2019
|
}
|
|
1833
2020
|
|
|
1834
|
-
function DisabledActionButton({actionEval: actionEval, chrome: chrome}) {
|
|
1835
|
-
const label = actionTriggerLabel(actionEval),
|
|
2021
|
+
function DisabledActionButton({actionEval: actionEval, activity: activity, chrome: chrome}) {
|
|
2022
|
+
const label = actionTriggerLabel(actionEval), {tone: tone, icon: icon} = actionButtonFace({
|
|
2023
|
+
actionEval: actionEval,
|
|
2024
|
+
activityName: activity
|
|
2025
|
+
}), button = /* @__PURE__ */ jsx(Button, {
|
|
1836
2026
|
fontSize: 1,
|
|
2027
|
+
...actionIconProps(icon),
|
|
1837
2028
|
mode: chrome?.mode ?? "ghost",
|
|
1838
2029
|
onClick: e => e.stopPropagation(),
|
|
1839
2030
|
padding: 2,
|
|
1840
2031
|
text: label,
|
|
2032
|
+
tone: tone,
|
|
1841
2033
|
...spanTriggerProps(chrome),
|
|
1842
2034
|
disabled: !0
|
|
1843
2035
|
});
|
|
@@ -1847,17 +2039,19 @@ function DisabledActionButton({actionEval: actionEval, chrome: chrome}) {
|
|
|
1847
2039
|
}) : button;
|
|
1848
2040
|
}
|
|
1849
2041
|
|
|
1850
|
-
function PlainActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
1851
|
-
const {action: action} = actionEval, label = actionLabel(action), btn =
|
|
2042
|
+
function PlainActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
2043
|
+
const {action: action} = actionEval, label = actionLabel(action), btn = actionButtonFace({
|
|
1852
2044
|
actionEval: actionEval,
|
|
1853
2045
|
activityName: activity
|
|
1854
2046
|
}), button = /* @__PURE__ */ jsx(FireButton, {
|
|
1855
2047
|
action: action.name,
|
|
2048
|
+
icon: btn.icon,
|
|
1856
2049
|
instanceId: instanceId,
|
|
1857
2050
|
label: label,
|
|
1858
2051
|
mode: btn.mode,
|
|
1859
2052
|
activity: activity,
|
|
1860
2053
|
chrome: chrome,
|
|
2054
|
+
surface: surface,
|
|
1861
2055
|
tone: btn.tone
|
|
1862
2056
|
});
|
|
1863
2057
|
return action.description ? /* @__PURE__ */ jsx(HoverHint, {
|
|
@@ -1866,12 +2060,14 @@ function PlainActionButton({actionEval: actionEval, instanceId: instanceId, acti
|
|
|
1866
2060
|
}) : button;
|
|
1867
2061
|
}
|
|
1868
2062
|
|
|
1869
|
-
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}) {
|
|
1870
2064
|
const {action: action} = actionEval, label = actionLabel(action), decls = action.params ?? [], [values, setValues] = useState({}), {fire: fire, pending: pending} = useFireAction({
|
|
1871
2065
|
instanceId: instanceId,
|
|
1872
2066
|
activity: activity,
|
|
1873
2067
|
action: action.name,
|
|
1874
|
-
label: label
|
|
2068
|
+
label: label,
|
|
2069
|
+
surface: surface,
|
|
2070
|
+
viaMenu: viaMenu
|
|
1875
2071
|
}), built = buildParams(decls, values), confirm = async () => {
|
|
1876
2072
|
await fire(built.params) && onClose();
|
|
1877
2073
|
};
|
|
@@ -1926,8 +2122,8 @@ function ParamsActionDialog({actionEval: actionEval, instanceId: instanceId, act
|
|
|
1926
2122
|
});
|
|
1927
2123
|
}
|
|
1928
2124
|
|
|
1929
|
-
function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, chrome: chrome}) {
|
|
1930
|
-
const [open, setOpen] = useState(!1), btn =
|
|
2125
|
+
function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, chrome: chrome}) {
|
|
2126
|
+
const [open, setOpen] = useState(!1), btn = actionButtonFace({
|
|
1931
2127
|
actionEval: actionEval,
|
|
1932
2128
|
activityName: activity
|
|
1933
2129
|
});
|
|
@@ -1936,6 +2132,7 @@ function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, act
|
|
|
1936
2132
|
children: [
|
|
1937
2133
|
/* @__PURE__ */ jsx(Button, {
|
|
1938
2134
|
fontSize: 1,
|
|
2135
|
+
...actionIconProps(btn.icon),
|
|
1939
2136
|
mode: chrome?.mode ?? btn.mode,
|
|
1940
2137
|
onClick: e => {
|
|
1941
2138
|
chrome?.inButtonCard === !0 && e.stopPropagation(), setOpen(!0);
|
|
@@ -1950,7 +2147,9 @@ function ParamsActionButton({actionEval: actionEval, instanceId: instanceId, act
|
|
|
1950
2147
|
actionEval: actionEval,
|
|
1951
2148
|
activity: activity,
|
|
1952
2149
|
instanceId: instanceId,
|
|
1953
|
-
onClose: () => setOpen(!1)
|
|
2150
|
+
onClose: () => setOpen(!1),
|
|
2151
|
+
surface: surface,
|
|
2152
|
+
viaMenu: !1
|
|
1954
2153
|
})
|
|
1955
2154
|
}) : null ]
|
|
1956
2155
|
});
|
|
@@ -2244,27 +2443,10 @@ function useLocalDocRef(gdr) {
|
|
|
2244
2443
|
}
|
|
2245
2444
|
|
|
2246
2445
|
function useActualDocType(bareId) {
|
|
2247
|
-
const
|
|
2248
|
-
apiVersion: WORKFLOW_API_VERSION
|
|
2249
|
-
}), [probe, setProbe] = useState();
|
|
2446
|
+
const {actualTypes: actualTypes} = useWorkflowContext();
|
|
2250
2447
|
return useEffect(() => {
|
|
2251
|
-
if (
|
|
2252
|
-
|
|
2253
|
-
return client.fetch("*[_id == $id || _id == $draft || _id in path($version)][0]._type", {
|
|
2254
|
-
id: bareId,
|
|
2255
|
-
draft: `drafts.${bareId}`,
|
|
2256
|
-
version: `versions.*.${bareId}`
|
|
2257
|
-
}, {
|
|
2258
|
-
perspective: "raw"
|
|
2259
|
-
}).then(result => {
|
|
2260
|
-
cancelled || setProbe({
|
|
2261
|
-
id: bareId,
|
|
2262
|
-
value: result
|
|
2263
|
-
});
|
|
2264
|
-
}).catch(() => {}), () => {
|
|
2265
|
-
cancelled = !0;
|
|
2266
|
-
};
|
|
2267
|
-
}, [ 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 ]));
|
|
2268
2450
|
}
|
|
2269
2451
|
|
|
2270
2452
|
function useDocLink(gdr) {
|
|
@@ -2761,7 +2943,7 @@ function ReadOnlyDocRefs({entry: entry}) {
|
|
|
2761
2943
|
padding: 2,
|
|
2762
2944
|
radius: 2,
|
|
2763
2945
|
children: /* @__PURE__ */ jsx(PreviewOrId, {
|
|
2764
|
-
id:
|
|
2946
|
+
id: toBareId(ref.id),
|
|
2765
2947
|
type: ref.type
|
|
2766
2948
|
})
|
|
2767
2949
|
}, ref.id))
|
|
@@ -2844,7 +3026,7 @@ function useFieldDraft(args) {
|
|
|
2844
3026
|
}
|
|
2845
3027
|
|
|
2846
3028
|
function EditableFieldControl({instanceId: instanceId, field: field}) {
|
|
2847
|
-
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);
|
|
2848
3030
|
/* @__PURE__ */
|
|
2849
3031
|
return jsx(EditableField, {
|
|
2850
3032
|
field: field,
|
|
@@ -2880,7 +3062,7 @@ function EditableFieldControl({instanceId: instanceId, field: field}) {
|
|
|
2880
3062
|
mode: "append",
|
|
2881
3063
|
value: noteRow({
|
|
2882
3064
|
body: body,
|
|
2883
|
-
actor:
|
|
3065
|
+
actor: selfActor,
|
|
2884
3066
|
at: /* @__PURE__ */ (new Date).toISOString()
|
|
2885
3067
|
})
|
|
2886
3068
|
}).then(() => {})
|
|
@@ -3015,7 +3197,10 @@ function AssigneeField({field: field, onSave: onSave, onUnset: onUnset}) {
|
|
|
3015
3197
|
align: "center",
|
|
3016
3198
|
children: /* @__PURE__ */ jsx(DismissablePopover, {
|
|
3017
3199
|
content: /* @__PURE__ */ jsx(AssigneePicker, {
|
|
3018
|
-
|
|
3200
|
+
onChange: next => {
|
|
3201
|
+
const changed = changedAssignee(cur ? [ cur ] : [], next);
|
|
3202
|
+
changed && pickAndClose(changed);
|
|
3203
|
+
},
|
|
3019
3204
|
value: cur ? [ cur ] : []
|
|
3020
3205
|
}),
|
|
3021
3206
|
onDismiss: () => setOpen(!1),
|
|
@@ -3540,11 +3725,11 @@ function AssignActivityControl({instanceId: instanceId, state: state, assigneeId
|
|
|
3540
3725
|
setBusy(!0);
|
|
3541
3726
|
try {
|
|
3542
3727
|
selectedIds.has(memberId) ? await editFieldFor(instanceId, {
|
|
3543
|
-
target:
|
|
3728
|
+
target: editFieldTarget(field),
|
|
3544
3729
|
mode: "set",
|
|
3545
3730
|
value: members.filter(m => !(m.type === "user" && m.id === memberId))
|
|
3546
3731
|
}) : await editFieldFor(instanceId, {
|
|
3547
|
-
target:
|
|
3732
|
+
target: editFieldTarget(field),
|
|
3548
3733
|
mode: "append",
|
|
3549
3734
|
value: {
|
|
3550
3735
|
type: "user",
|
|
@@ -3973,8 +4158,8 @@ function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle,
|
|
|
3973
4158
|
});
|
|
3974
4159
|
}
|
|
3975
4160
|
|
|
3976
|
-
function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter}) {
|
|
3977
|
-
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 => {
|
|
3978
4163
|
if (busy) return !1;
|
|
3979
4164
|
setBusy(!0);
|
|
3980
4165
|
try {
|
|
@@ -3999,15 +4184,35 @@ function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter}) {
|
|
|
3999
4184
|
mode: "set",
|
|
4000
4185
|
value: next
|
|
4001
4186
|
}));
|
|
4002
|
-
}, toggleRow = row => {
|
|
4003
|
-
if (
|
|
4004
|
-
|
|
4005
|
-
|
|
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
|
+
}
|
|
4006
4202
|
const tick = row.tick;
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
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
|
+
}
|
|
4011
4216
|
}, addItem = label => appendTarget ? run(() => editFieldFor(instance._id, {
|
|
4012
4217
|
target: appendTarget,
|
|
4013
4218
|
mode: "append",
|
|
@@ -4124,26 +4329,39 @@ const ACTIONS_MENU_TRIGGER = {
|
|
|
4124
4329
|
padding: 2
|
|
4125
4330
|
};
|
|
4126
4331
|
|
|
4127
|
-
function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activity: activity, onCollectParams: onCollectParams}) {
|
|
4128
|
-
const rowKind = actionRowKind(actionEval), label = actionTriggerLabel(actionEval), {
|
|
4332
|
+
function ActionMenuItem({actionEval: actionEval, instanceId: instanceId, activity: activity, surface: surface, onCollectParams: onCollectParams}) {
|
|
4333
|
+
const rowKind = actionRowKind(actionEval), label = actionTriggerLabel(actionEval), {tone: tone, icon: icon} = actionButtonFace({
|
|
4334
|
+
actionEval: actionEval,
|
|
4335
|
+
activityName: activity
|
|
4336
|
+
}), iconProp = icon ? {
|
|
4337
|
+
icon: icon
|
|
4338
|
+
} : {}, {fire: fire, pending: pending} = useFireAction({
|
|
4129
4339
|
instanceId: instanceId,
|
|
4130
4340
|
activity: activity,
|
|
4131
4341
|
action: actionEval.action.name,
|
|
4132
|
-
label: label
|
|
4342
|
+
label: label,
|
|
4343
|
+
surface: surface,
|
|
4344
|
+
viaMenu: !0
|
|
4133
4345
|
});
|
|
4134
4346
|
return rowKind.kind === "disabled" ? /* @__PURE__ */ jsx(MenuItem, {
|
|
4135
4347
|
disabled: !0,
|
|
4136
|
-
|
|
4348
|
+
...iconProp,
|
|
4349
|
+
text: label,
|
|
4350
|
+
tone: tone
|
|
4137
4351
|
}) : rowKind.kind === "plain" ? /* @__PURE__ */ jsx(MenuItem, {
|
|
4138
4352
|
disabled: pending,
|
|
4353
|
+
...iconProp,
|
|
4139
4354
|
onClick: () => {
|
|
4140
4355
|
fire();
|
|
4141
4356
|
},
|
|
4142
|
-
text: label
|
|
4357
|
+
text: label,
|
|
4358
|
+
tone: tone
|
|
4143
4359
|
}) : /* @__PURE__ */ jsx(MenuItem, {
|
|
4144
4360
|
disabled: pending,
|
|
4361
|
+
...iconProp,
|
|
4145
4362
|
onClick: onCollectParams,
|
|
4146
|
-
text: label
|
|
4363
|
+
text: label,
|
|
4364
|
+
tone: tone
|
|
4147
4365
|
});
|
|
4148
4366
|
}
|
|
4149
4367
|
|
|
@@ -4159,7 +4377,7 @@ function rowShield(menuButton) {
|
|
|
4159
4377
|
});
|
|
4160
4378
|
}
|
|
4161
4379
|
|
|
4162
|
-
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}) {
|
|
4163
4381
|
const [paramsAction, setParamsAction] = useState(void 0), clusterPending = useActionClusterPending(), menuId = useId(), menuButton = /* @__PURE__ */ jsx(MenuButton, {
|
|
4164
4382
|
button: /* @__PURE__ */ jsx(Button, {
|
|
4165
4383
|
...ACTIONS_MENU_TRIGGER,
|
|
@@ -4178,7 +4396,8 @@ function ActionsMenuButton({actions: actions, instanceId: instanceId, activity:
|
|
|
4178
4396
|
actionEval: a,
|
|
4179
4397
|
activity: activity,
|
|
4180
4398
|
instanceId: instanceId,
|
|
4181
|
-
onCollectParams: () => setParamsAction(a)
|
|
4399
|
+
onCollectParams: () => setParamsAction(a),
|
|
4400
|
+
surface: surface
|
|
4182
4401
|
}, a.action.name))
|
|
4183
4402
|
}),
|
|
4184
4403
|
popover: {
|
|
@@ -4194,7 +4413,9 @@ function ActionsMenuButton({actions: actions, instanceId: instanceId, activity:
|
|
|
4194
4413
|
actionEval: paramsAction,
|
|
4195
4414
|
activity: activity,
|
|
4196
4415
|
instanceId: instanceId,
|
|
4197
|
-
onClose: () => setParamsAction(void 0)
|
|
4416
|
+
onClose: () => setParamsAction(void 0),
|
|
4417
|
+
surface: surface,
|
|
4418
|
+
viaMenu: !0
|
|
4198
4419
|
})
|
|
4199
4420
|
}) : null ]
|
|
4200
4421
|
});
|
|
@@ -4210,7 +4431,8 @@ function TerminalFooter({actions: actions, activity: activity, instanceId: insta
|
|
|
4210
4431
|
children: /* @__PURE__ */ jsx(ActivityActionRow, {
|
|
4211
4432
|
actionEval: only,
|
|
4212
4433
|
activity: activity,
|
|
4213
|
-
instanceId: instanceId
|
|
4434
|
+
instanceId: instanceId,
|
|
4435
|
+
surface: "terminal-footer"
|
|
4214
4436
|
})
|
|
4215
4437
|
}) : /* @__PURE__ */ jsx(FittedActions, {
|
|
4216
4438
|
actions: actions,
|
|
@@ -4256,6 +4478,7 @@ function FittedActions({actions: actions, activity: activity, instanceId: instan
|
|
|
4256
4478
|
children: [
|
|
4257
4479
|
/* @__PURE__ */ jsx(MeasureRow, {
|
|
4258
4480
|
actions: actions,
|
|
4481
|
+
activity: activity,
|
|
4259
4482
|
onElement: setMeasureEl
|
|
4260
4483
|
}),
|
|
4261
4484
|
/* @__PURE__ */ jsxs(FooterRow, {
|
|
@@ -4263,19 +4486,21 @@ function FittedActions({actions: actions, activity: activity, instanceId: instan
|
|
|
4263
4486
|
children: [ inline === void 0 ? null : actions.slice(0, inline).map(a => /* @__PURE__ */ jsx(ActivityActionRow, {
|
|
4264
4487
|
actionEval: a,
|
|
4265
4488
|
activity: activity,
|
|
4266
|
-
instanceId: instanceId
|
|
4489
|
+
instanceId: instanceId,
|
|
4490
|
+
surface: "terminal-footer"
|
|
4267
4491
|
}, a.action.name)), overflow.length > 0 ? /* @__PURE__ */ jsx(ActionsMenuButton, {
|
|
4268
4492
|
actions: overflow,
|
|
4269
4493
|
activity: activity,
|
|
4270
4494
|
instanceId: instanceId,
|
|
4271
4495
|
label: MORE_ACTIONS_LABEL,
|
|
4272
|
-
mode: "default"
|
|
4496
|
+
mode: "default",
|
|
4497
|
+
surface: "terminal-footer"
|
|
4273
4498
|
}) : null ]
|
|
4274
4499
|
}) ]
|
|
4275
4500
|
});
|
|
4276
4501
|
}
|
|
4277
4502
|
|
|
4278
|
-
function MeasureRow({actions: actions, onElement: onElement}) {
|
|
4503
|
+
function MeasureRow({actions: actions, activity: activity, onElement: onElement}) {
|
|
4279
4504
|
/* @__PURE__ */
|
|
4280
4505
|
return jsx("div", {
|
|
4281
4506
|
"aria-hidden": !0,
|
|
@@ -4289,12 +4514,20 @@ function MeasureRow({actions: actions, onElement: onElement}) {
|
|
|
4289
4514
|
display: "inline-flex",
|
|
4290
4515
|
whiteSpace: "nowrap"
|
|
4291
4516
|
},
|
|
4292
|
-
children: [ actions.map(a =>
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4517
|
+
children: [ actions.map(a => {
|
|
4518
|
+
const {icon: icon} = actionButtonFace({
|
|
4519
|
+
actionEval: a,
|
|
4520
|
+
activityName: activity
|
|
4521
|
+
});
|
|
4522
|
+
/* @__PURE__ */
|
|
4523
|
+
return jsx(Button, {
|
|
4524
|
+
as: "span",
|
|
4525
|
+
fontSize: 1,
|
|
4526
|
+
...actionIconProps(icon),
|
|
4527
|
+
padding: 2,
|
|
4528
|
+
text: actionTriggerLabel(a)
|
|
4529
|
+
}, a.action.name);
|
|
4530
|
+
}),
|
|
4298
4531
|
/* @__PURE__ */ jsx(Button, {
|
|
4299
4532
|
...ACTIONS_MENU_TRIGGER,
|
|
4300
4533
|
as: "span",
|
|
@@ -4304,7 +4537,7 @@ function MeasureRow({actions: actions, onElement: onElement}) {
|
|
|
4304
4537
|
});
|
|
4305
4538
|
}
|
|
4306
4539
|
|
|
4307
|
-
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}) {
|
|
4308
4541
|
const detail = deriveActivityDetail({
|
|
4309
4542
|
entry: entry,
|
|
4310
4543
|
activityName: activityName
|
|
@@ -4326,6 +4559,13 @@ function ActivityDetailDialog({entry: entry, activityName: activityName, breadcr
|
|
|
4326
4559
|
onClose: onClose,
|
|
4327
4560
|
width: 1,
|
|
4328
4561
|
children: [
|
|
4562
|
+
/* @__PURE__ */ jsx(LogEventOnMount, {
|
|
4563
|
+
data: {
|
|
4564
|
+
instanceId: instanceId,
|
|
4565
|
+
source: source
|
|
4566
|
+
},
|
|
4567
|
+
event: WorkflowActivityDialogOpened
|
|
4568
|
+
}),
|
|
4329
4569
|
/* @__PURE__ */ jsx(Card, {
|
|
4330
4570
|
borderBottom: hasBody,
|
|
4331
4571
|
style: {
|
|
@@ -4433,7 +4673,8 @@ function TopActions({detail: detail, definition: definition, instanceId: instanc
|
|
|
4433
4673
|
children: [ p.actions.map(a => /* @__PURE__ */ jsx(ActivityActionRow, {
|
|
4434
4674
|
actionEval: a,
|
|
4435
4675
|
activity: activityName,
|
|
4436
|
-
instanceId: instanceId
|
|
4676
|
+
instanceId: instanceId,
|
|
4677
|
+
surface: "dialog-strip"
|
|
4437
4678
|
}, a.action.name)), p.manualTarget ? /* @__PURE__ */ jsx(Button, {
|
|
4438
4679
|
as: "a",
|
|
4439
4680
|
fontSize: 1,
|
|
@@ -4469,7 +4710,8 @@ function FieldRow({field: field, detail: detail, entry: entry, activityName: act
|
|
|
4469
4710
|
scope: "activity",
|
|
4470
4711
|
field: field.name,
|
|
4471
4712
|
activity: activityName
|
|
4472
|
-
}
|
|
4713
|
+
},
|
|
4714
|
+
surface: "activity-dialog"
|
|
4473
4715
|
}) ]
|
|
4474
4716
|
});
|
|
4475
4717
|
if (field._type === "assignees") {
|
|
@@ -4576,7 +4818,26 @@ function CountedLabel({count: count, label: label}) {
|
|
|
4576
4818
|
});
|
|
4577
4819
|
}
|
|
4578
4820
|
|
|
4579
|
-
function
|
|
4821
|
+
function SpinnerSlot({busy: busy, size: size}) {
|
|
4822
|
+
/* @__PURE__ */
|
|
4823
|
+
return jsx(Flex, {
|
|
4824
|
+
align: "center",
|
|
4825
|
+
flex: "none",
|
|
4826
|
+
justify: "center",
|
|
4827
|
+
style: {
|
|
4828
|
+
width: 19,
|
|
4829
|
+
height: 19
|
|
4830
|
+
},
|
|
4831
|
+
children: busy ? /* @__PURE__ */ jsx(Spinner, {
|
|
4832
|
+
muted: !0,
|
|
4833
|
+
...size !== void 0 ? {
|
|
4834
|
+
size: size
|
|
4835
|
+
} : {}
|
|
4836
|
+
}) : null
|
|
4837
|
+
});
|
|
4838
|
+
}
|
|
4839
|
+
|
|
4840
|
+
function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
4580
4841
|
/* @__PURE__ */
|
|
4581
4842
|
return jsxs(Flex, {
|
|
4582
4843
|
align: "center",
|
|
@@ -4591,6 +4852,9 @@ function GroupHeading({count: count, title: title, end: end}) {
|
|
|
4591
4852
|
weight: "semibold",
|
|
4592
4853
|
children: title
|
|
4593
4854
|
})
|
|
4855
|
+
}), busy === void 0 ? null : /* @__PURE__ */ jsx(SpinnerSlot, {
|
|
4856
|
+
busy: busy,
|
|
4857
|
+
size: 1
|
|
4594
4858
|
}), end === void 0 ? null : /* @__PURE__ */ jsxs(Fragment, {
|
|
4595
4859
|
children: [
|
|
4596
4860
|
/* @__PURE__ */ jsx(Flex, {
|
|
@@ -4600,29 +4864,7 @@ function GroupHeading({count: count, title: title, end: end}) {
|
|
|
4600
4864
|
});
|
|
4601
4865
|
}
|
|
4602
4866
|
|
|
4603
|
-
function
|
|
4604
|
-
const toast = useClosableToast();
|
|
4605
|
-
/* @__PURE__ */
|
|
4606
|
-
return jsx(Button, {
|
|
4607
|
-
fontSize: 1,
|
|
4608
|
-
mode: "ghost",
|
|
4609
|
-
onClick: () => {
|
|
4610
|
-
navigator.clipboard.writeText(unreadableDocsReport(unreadable)).then(() => toast.push({
|
|
4611
|
-
status: "success",
|
|
4612
|
-
title: "Details copied"
|
|
4613
|
-
}), () => toast.push({
|
|
4614
|
-
status: "error",
|
|
4615
|
-
title: "Could not copy the details"
|
|
4616
|
-
}));
|
|
4617
|
-
},
|
|
4618
|
-
padding: 2,
|
|
4619
|
-
text: "Copy details"
|
|
4620
|
-
});
|
|
4621
|
-
}
|
|
4622
|
-
|
|
4623
|
-
function UnreadableDocsNote({unreadable: unreadable}) {
|
|
4624
|
-
if (unreadable.length === 0) return null;
|
|
4625
|
-
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}) {
|
|
4626
4868
|
/* @__PURE__ */
|
|
4627
4869
|
return jsxs(Card, {
|
|
4628
4870
|
padding: 2,
|
|
@@ -4649,35 +4891,64 @@ function UnreadableDocsNote({unreadable: unreadable}) {
|
|
|
4649
4891
|
size: 1,
|
|
4650
4892
|
children: label
|
|
4651
4893
|
}) ]
|
|
4652
|
-
}),
|
|
4653
|
-
/* @__PURE__ */ jsx(CopyDetailsButton, {
|
|
4654
|
-
unreadable: unreadable
|
|
4655
|
-
}) ]
|
|
4894
|
+
}), action ]
|
|
4656
4895
|
});
|
|
4657
4896
|
}
|
|
4658
4897
|
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
"shape-violation": "Unreadable workflow document"
|
|
4662
|
-
};
|
|
4663
|
-
|
|
4664
|
-
function remediation(invalid) {
|
|
4665
|
-
return invalid.reason === "model-ahead" ? `"${invalid.documentId}" was created by a newer version of the workflow engine than this Studio can read. It needs a plugin update that supports the newer data model — share the details with your Studio maintainers.` : `This version of the Studio can't read "${invalid.documentId}" — it was likely created by a newer or different version of the workflow tooling. Share the details with your Studio maintainers.`;
|
|
4666
|
-
}
|
|
4667
|
-
|
|
4668
|
-
function InvalidDocNotice({invalid: invalid}) {
|
|
4898
|
+
function CopyDetailsButton({unreadable: unreadable}) {
|
|
4899
|
+
const toast = useClosableToast();
|
|
4669
4900
|
/* @__PURE__ */
|
|
4670
|
-
return jsx(
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
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, {
|
|
4924
|
+
unreadable: unreadable
|
|
4925
|
+
}),
|
|
4926
|
+
label: label
|
|
4927
|
+
});
|
|
4928
|
+
}
|
|
4929
|
+
|
|
4930
|
+
const HEADLINES = {
|
|
4931
|
+
"model-ahead": "Workflow needs a newer engine",
|
|
4932
|
+
"shape-violation": "Unreadable workflow document"
|
|
4933
|
+
};
|
|
4934
|
+
|
|
4935
|
+
function remediation(invalid) {
|
|
4936
|
+
return invalid.reason === "model-ahead" ? `"${invalid.documentId}" was created by a newer version of the workflow engine than this Studio can read. It needs a plugin update that supports the newer data model — share the details with your Studio maintainers.` : `This version of the Studio can't read "${invalid.documentId}" — it was likely created by a newer or different version of the workflow tooling. Share the details with your Studio maintainers.`;
|
|
4937
|
+
}
|
|
4938
|
+
|
|
4939
|
+
function InvalidDocNotice({invalid: invalid}) {
|
|
4940
|
+
/* @__PURE__ */
|
|
4941
|
+
return jsx(Card, {
|
|
4942
|
+
border: !0,
|
|
4943
|
+
padding: 3,
|
|
4944
|
+
radius: 2,
|
|
4945
|
+
tone: "caution",
|
|
4946
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
4947
|
+
space: 3,
|
|
4948
|
+
children: [
|
|
4949
|
+
/* @__PURE__ */ jsx(Text, {
|
|
4950
|
+
size: 1,
|
|
4951
|
+
weight: "medium",
|
|
4681
4952
|
children: HEADLINES[invalid.reason]
|
|
4682
4953
|
}),
|
|
4683
4954
|
/* @__PURE__ */ jsx(Text, {
|
|
@@ -4713,6 +4984,18 @@ function TabSwitch({ariaControls: ariaControls, idPrefix: idPrefix, options: opt
|
|
|
4713
4984
|
});
|
|
4714
4985
|
}
|
|
4715
4986
|
|
|
4987
|
+
function useDelayedFlag(active, delayMs) {
|
|
4988
|
+
const [held, setHeld] = useState(!1);
|
|
4989
|
+
return useEffect(() => {
|
|
4990
|
+
if (!active) {
|
|
4991
|
+
setHeld(!1);
|
|
4992
|
+
return;
|
|
4993
|
+
}
|
|
4994
|
+
const timer = setTimeout(() => setHeld(!0), delayMs);
|
|
4995
|
+
return () => clearTimeout(timer);
|
|
4996
|
+
}, [ active, delayMs ]), held && active;
|
|
4997
|
+
}
|
|
4998
|
+
|
|
4716
4999
|
function instanceTitle(instance, definition) {
|
|
4717
5000
|
return definition?.title ?? instance.definition;
|
|
4718
5001
|
}
|
|
@@ -4962,6 +5245,25 @@ function buildStartRequest(args) {
|
|
|
4962
5245
|
};
|
|
4963
5246
|
}
|
|
4964
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
|
+
|
|
4965
5267
|
function findResumeEntry(args) {
|
|
4966
5268
|
return args.entries.find(e => isUnprimed(e.instance) && e.instance.definition === args.definitionName && (args.heldInstanceId === void 0 || e.instance._id === args.heldInstanceId));
|
|
4967
5269
|
}
|
|
@@ -4977,7 +5279,8 @@ function classifyStartError(err) {
|
|
|
4977
5279
|
instance: err.instance,
|
|
4978
5280
|
description: describeError(err.cause)
|
|
4979
5281
|
} : err instanceof StartNotAllowedError ? {
|
|
4980
|
-
kind: "not-allowed"
|
|
5282
|
+
kind: "not-allowed",
|
|
5283
|
+
description: err.unmetRequirements.map(requirementCopy).join("; ")
|
|
4981
5284
|
} : {
|
|
4982
5285
|
kind: "failed",
|
|
4983
5286
|
description: describeError(err)
|
|
@@ -4990,22 +5293,30 @@ function boundReleaseId(mapping, selectedReleaseId) {
|
|
|
4990
5293
|
|
|
4991
5294
|
function startGate(args) {
|
|
4992
5295
|
const {mapping: mapping, mappingIssue: mappingIssue, selectedReleaseId: selectedReleaseId, releaseActive: releaseActive} = args;
|
|
4993
|
-
|
|
5296
|
+
if (mappingIssue !== void 0) return {
|
|
4994
5297
|
blocked: !0,
|
|
4995
5298
|
tooltip: mappingIssue
|
|
4996
|
-
}
|
|
5299
|
+
};
|
|
5300
|
+
if (mapping.perspectiveField?.required === !0 && selectedReleaseId === void 0) return {
|
|
4997
5301
|
blocked: !0,
|
|
4998
5302
|
tooltip: "Pick a release in the perspective dropdown first"
|
|
4999
|
-
}
|
|
5303
|
+
};
|
|
5304
|
+
if (mapping.perspectiveField !== void 0 && selectedReleaseId !== void 0 && !releaseActive) return {
|
|
5000
5305
|
blocked: !0,
|
|
5001
5306
|
tooltip: `Release "${selectedReleaseId}" is not active — only active releases can host new workflows`
|
|
5002
|
-
}
|
|
5307
|
+
};
|
|
5308
|
+
if (args.startFilterFailed === !0) return {
|
|
5003
5309
|
blocked: !0,
|
|
5004
5310
|
tooltip: `${mapping.label} can't start for this document right now — the workflow's start condition isn't met`
|
|
5005
|
-
}
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
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 {
|
|
5009
5320
|
blocked: !1,
|
|
5010
5321
|
tooltip: void 0
|
|
5011
5322
|
};
|
|
@@ -5028,10 +5339,10 @@ async function preflightFilter(args) {
|
|
|
5028
5339
|
});
|
|
5029
5340
|
}
|
|
5030
5341
|
|
|
5031
|
-
async function
|
|
5032
|
-
const {
|
|
5033
|
-
return
|
|
5034
|
-
|
|
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,
|
|
5035
5346
|
definition: {
|
|
5036
5347
|
name: mapping.definition
|
|
5037
5348
|
},
|
|
@@ -5040,6 +5351,25 @@ async function preflightAllowed(args) {
|
|
|
5040
5351
|
})).outcome === "unsatisfied";
|
|
5041
5352
|
}
|
|
5042
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
|
+
|
|
5043
5373
|
async function performStart(args) {
|
|
5044
5374
|
const {mapping: mapping, docId: docId, initialValue: initialValue, selectedReleaseId: selectedReleaseId} = args, releaseId = boundReleaseId(mapping, selectedReleaseId);
|
|
5045
5375
|
try {
|
|
@@ -5066,7 +5396,21 @@ async function performStart(args) {
|
|
|
5066
5396
|
}
|
|
5067
5397
|
|
|
5068
5398
|
function useStartVerdicts(args) {
|
|
5069
|
-
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));
|
|
5070
5414
|
return {
|
|
5071
5415
|
filterFailed: useFilterVerdict({
|
|
5072
5416
|
mapping: mapping,
|
|
@@ -5074,25 +5418,15 @@ function useStartVerdicts(args) {
|
|
|
5074
5418
|
docId: docId,
|
|
5075
5419
|
initialValue: initialValue,
|
|
5076
5420
|
selectedReleaseId: selectedReleaseId,
|
|
5077
|
-
skip: skip
|
|
5421
|
+
skip: skip,
|
|
5422
|
+
fetchDataset: fetchDataset
|
|
5078
5423
|
}),
|
|
5079
|
-
|
|
5080
|
-
mapping: mapping,
|
|
5081
|
-
allowed: start?.allowed,
|
|
5082
|
-
docId: docId,
|
|
5083
|
-
selectedReleaseId: selectedReleaseId,
|
|
5084
|
-
skip: skip
|
|
5085
|
-
})
|
|
5424
|
+
unmetRequirement: unmetRequirement
|
|
5086
5425
|
};
|
|
5087
5426
|
}
|
|
5088
5427
|
|
|
5089
5428
|
function preflightScope(args) {
|
|
5090
|
-
const {
|
|
5091
|
-
tag: tag,
|
|
5092
|
-
filter: {
|
|
5093
|
-
includeCompleted: !0
|
|
5094
|
-
}
|
|
5095
|
-
});
|
|
5429
|
+
const {tag: tag, mapping: mapping, contentResource: contentResource, docId: docId, fetchDataset: fetchDataset} = args;
|
|
5096
5430
|
return {
|
|
5097
5431
|
tag: tag,
|
|
5098
5432
|
now: /* @__PURE__ */ (new Date).toISOString(),
|
|
@@ -5101,15 +5435,12 @@ function preflightScope(args) {
|
|
|
5101
5435
|
contentResource: contentResource,
|
|
5102
5436
|
documentId: docId
|
|
5103
5437
|
}).id,
|
|
5104
|
-
fetchDataset:
|
|
5105
|
-
groq: query,
|
|
5106
|
-
params: params
|
|
5107
|
-
})).map(assertReadableModel)
|
|
5438
|
+
fetchDataset: fetchDataset
|
|
5108
5439
|
};
|
|
5109
5440
|
}
|
|
5110
5441
|
|
|
5111
5442
|
function useFilterVerdict(args) {
|
|
5112
|
-
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;
|
|
5113
5444
|
return useEffect(() => {
|
|
5114
5445
|
if (skip || filter === void 0 || docId === void 0) {
|
|
5115
5446
|
setFailed(!1);
|
|
@@ -5123,57 +5454,112 @@ function useFilterVerdict(args) {
|
|
|
5123
5454
|
candidateValue: candidateValue,
|
|
5124
5455
|
selectedReleaseId: selectedReleaseId,
|
|
5125
5456
|
scope: preflightScope({
|
|
5126
|
-
engine: engine,
|
|
5127
5457
|
tag: binding.tag,
|
|
5128
5458
|
mapping: mapping,
|
|
5129
5459
|
contentResource: binding.contentResource,
|
|
5130
|
-
docId: docId
|
|
5460
|
+
docId: docId,
|
|
5461
|
+
fetchDataset: fetchDataset
|
|
5131
5462
|
})
|
|
5132
5463
|
}).catch(showRowOnError("start.filter", mapping)).then(verdict => {
|
|
5133
5464
|
cancelled || setFailed(verdict);
|
|
5134
5465
|
}), () => {
|
|
5135
5466
|
cancelled = !0;
|
|
5136
5467
|
};
|
|
5137
|
-
}, [ filter, rootRead, skip, docId, selectedReleaseId, candidateValue, mapping,
|
|
5468
|
+
}, [ filter, rootRead, skip, docId, selectedReleaseId, candidateValue, mapping, binding, fetchDataset ]),
|
|
5138
5469
|
failed;
|
|
5139
5470
|
}
|
|
5140
5471
|
|
|
5141
|
-
function
|
|
5142
|
-
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([]);
|
|
5143
5489
|
return useEffect(() => {
|
|
5144
|
-
if (skip ||
|
|
5145
|
-
setRefused(
|
|
5490
|
+
if (skip || requirements.length === 0 || docId === void 0) {
|
|
5491
|
+
setRefused(current => current.length === 0 ? current : []);
|
|
5146
5492
|
return;
|
|
5147
5493
|
}
|
|
5148
5494
|
let cancelled = !1;
|
|
5149
|
-
const
|
|
5495
|
+
const fields = preflightSeedFields({
|
|
5150
5496
|
mapping: mapping,
|
|
5151
|
-
|
|
5497
|
+
docId: docId,
|
|
5152
5498
|
selectedReleaseId: selectedReleaseId,
|
|
5153
5499
|
contentResource: binding.contentResource,
|
|
5154
5500
|
declaredFields: mappingFields.get(mappingKey(mapping))
|
|
5155
|
-
},
|
|
5156
|
-
|
|
5157
|
-
initFields: [],
|
|
5158
|
-
values: {}
|
|
5159
|
-
}).map(field => [ field.name, field.value ]));
|
|
5160
|
-
return preflightAllowed({
|
|
5161
|
-
allowed: allowed,
|
|
5501
|
+
}), scope = preflightScope({
|
|
5502
|
+
tag: binding.tag,
|
|
5162
5503
|
mapping: mapping,
|
|
5163
|
-
|
|
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
|
+
}),
|
|
5164
5550
|
scope: preflightScope({
|
|
5165
|
-
engine: engine,
|
|
5166
5551
|
tag: binding.tag,
|
|
5167
5552
|
mapping: mapping,
|
|
5553
|
+
docId: docId,
|
|
5168
5554
|
contentResource: binding.contentResource,
|
|
5169
|
-
|
|
5555
|
+
fetchDataset: () => Promise.resolve(entries.map(({instance: instance}) => projectStartSliceRow(instance)))
|
|
5170
5556
|
})
|
|
5171
|
-
}).catch(showRowOnError("
|
|
5557
|
+
}).catch(showRowOnError("singleSubject requirement", mapping)).then(verdict => {
|
|
5172
5558
|
cancelled || setRefused(verdict);
|
|
5173
5559
|
}), () => {
|
|
5174
5560
|
cancelled = !0;
|
|
5175
5561
|
};
|
|
5176
|
-
}, [
|
|
5562
|
+
}, [ dedupe, start, skip, docId, selectedReleaseId, entries, mapping, binding, mappingFields ]),
|
|
5177
5563
|
refused;
|
|
5178
5564
|
}
|
|
5179
5565
|
|
|
@@ -5183,7 +5569,7 @@ function showRowOnError(key, mapping) {
|
|
|
5183
5569
|
}
|
|
5184
5570
|
|
|
5185
5571
|
function useStartWorkflow(args) {
|
|
5186
|
-
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({
|
|
5187
5573
|
engine: engine
|
|
5188
5574
|
}), [starting, setStarting] = useState(!1), {selectedReleaseId: selectedReleaseId} = usePerspective(), releaseActive = useIsReleaseActive(), startBlock = mappingStarts.get(mappingKey(mapping)), hidden = startKindOf({
|
|
5189
5575
|
start: startBlock
|
|
@@ -5191,12 +5577,13 @@ function useStartWorkflow(args) {
|
|
|
5191
5577
|
entries: entries,
|
|
5192
5578
|
definitionName: mapping.definition,
|
|
5193
5579
|
heldInstanceId: void 0
|
|
5194
|
-
}) !== void 0, {filterFailed: filterFailed,
|
|
5580
|
+
}) !== void 0, {filterFailed: filterFailed, unmetRequirement: unmetRequirement} = useStartVerdicts({
|
|
5195
5581
|
mapping: mapping,
|
|
5196
5582
|
start: startBlock,
|
|
5197
5583
|
docId: docId,
|
|
5198
5584
|
initialValue: initialValue,
|
|
5199
5585
|
selectedReleaseId: selectedReleaseId,
|
|
5586
|
+
entries: entries,
|
|
5200
5587
|
hidden: hidden,
|
|
5201
5588
|
resumable: resumable
|
|
5202
5589
|
}), {blocked: blocked, tooltip: tooltip} = startGate({
|
|
@@ -5205,7 +5592,9 @@ function useStartWorkflow(args) {
|
|
|
5205
5592
|
selectedReleaseId: selectedReleaseId,
|
|
5206
5593
|
releaseActive: releaseActive,
|
|
5207
5594
|
startFilterFailed: filterFailed,
|
|
5208
|
-
|
|
5595
|
+
...unmetRequirement !== void 0 ? {
|
|
5596
|
+
unmetRequirement: unmetRequirement
|
|
5597
|
+
} : {}
|
|
5209
5598
|
});
|
|
5210
5599
|
return {
|
|
5211
5600
|
blocked: blocked,
|
|
@@ -5227,7 +5616,10 @@ function useStartWorkflow(args) {
|
|
|
5227
5616
|
title: "Could not persist the document before starting",
|
|
5228
5617
|
description: describeError(err)
|
|
5229
5618
|
}),
|
|
5230
|
-
openStartDialog: openStartDialog
|
|
5619
|
+
openStartDialog: request => openStartDialog({
|
|
5620
|
+
...request,
|
|
5621
|
+
source: source
|
|
5622
|
+
})
|
|
5231
5623
|
});
|
|
5232
5624
|
} finally {
|
|
5233
5625
|
setStarting(!1);
|
|
@@ -5237,11 +5629,12 @@ function useStartWorkflow(args) {
|
|
|
5237
5629
|
};
|
|
5238
5630
|
}
|
|
5239
5631
|
|
|
5240
|
-
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"}) {
|
|
5241
5633
|
const {blocked: blocked, tooltip: tooltip, hidden: hidden, starting: starting, start: start} = useStartWorkflow({
|
|
5242
5634
|
mapping: mapping,
|
|
5243
5635
|
docId: docId,
|
|
5244
|
-
initialValue: initialValue
|
|
5636
|
+
initialValue: initialValue,
|
|
5637
|
+
source: source
|
|
5245
5638
|
});
|
|
5246
5639
|
if (hidden) return null;
|
|
5247
5640
|
const startLabel = label ?? `Start ${mapping.label}`, button = /* @__PURE__ */ jsx(Button, {
|
|
@@ -5274,7 +5667,7 @@ function useStartableMappings(mappings) {
|
|
|
5274
5667
|
}) !== "autonomous");
|
|
5275
5668
|
}
|
|
5276
5669
|
|
|
5277
|
-
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"}) {
|
|
5278
5671
|
const menuId = useId(), startable = useStartableMappings(mappings), [first] = startable;
|
|
5279
5672
|
if (first === void 0) return null;
|
|
5280
5673
|
if (startable.length === 1) /* @__PURE__ */
|
|
@@ -5287,6 +5680,7 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5287
5680
|
},
|
|
5288
5681
|
mapping: first,
|
|
5289
5682
|
mode: mode,
|
|
5683
|
+
source: source,
|
|
5290
5684
|
tone: tone
|
|
5291
5685
|
});
|
|
5292
5686
|
const menuLabel = label ?? "Start a workflow";
|
|
@@ -5312,7 +5706,8 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5312
5706
|
children: startable.map(mapping => /* @__PURE__ */ jsx(StartWorkflowMenuItem, {
|
|
5313
5707
|
docId: docId,
|
|
5314
5708
|
initialValue: initialValue,
|
|
5315
|
-
mapping: mapping
|
|
5709
|
+
mapping: mapping,
|
|
5710
|
+
source: source
|
|
5316
5711
|
}, mappingKey(mapping)))
|
|
5317
5712
|
}),
|
|
5318
5713
|
popover: {
|
|
@@ -5323,11 +5718,12 @@ function StartWorkflowControl({mappings: mappings, docId: docId, initialValue: i
|
|
|
5323
5718
|
});
|
|
5324
5719
|
}
|
|
5325
5720
|
|
|
5326
|
-
function StartWorkflowMenuItem({mapping: mapping, docId: docId, initialValue: initialValue}) {
|
|
5721
|
+
function StartWorkflowMenuItem({mapping: mapping, docId: docId, initialValue: initialValue, source: source}) {
|
|
5327
5722
|
const {blocked: blocked, tooltip: tooltip, starting: starting, start: start} = useStartWorkflow({
|
|
5328
5723
|
mapping: mapping,
|
|
5329
5724
|
docId: docId,
|
|
5330
|
-
initialValue: initialValue
|
|
5725
|
+
initialValue: initialValue,
|
|
5726
|
+
source: source
|
|
5331
5727
|
}), item = /* @__PURE__ */ jsx(MenuItem, {
|
|
5332
5728
|
disabled: blocked || starting || !docId,
|
|
5333
5729
|
onClick: () => {
|
|
@@ -5382,13 +5778,15 @@ function RowTerminalActions({actions: actions, activity: activity, instanceId: i
|
|
|
5382
5778
|
mode: "ghost",
|
|
5383
5779
|
inButtonCard: !0
|
|
5384
5780
|
},
|
|
5385
|
-
instanceId: instanceId
|
|
5781
|
+
instanceId: instanceId,
|
|
5782
|
+
surface: "inline-row"
|
|
5386
5783
|
}) : /* @__PURE__ */ jsx(ActionsMenuButton, {
|
|
5387
5784
|
actions: actions,
|
|
5388
5785
|
activity: activity,
|
|
5389
5786
|
inButtonCard: !0,
|
|
5390
5787
|
instanceId: instanceId,
|
|
5391
|
-
label: "Select action"
|
|
5788
|
+
label: "Select action",
|
|
5789
|
+
surface: "inline-row"
|
|
5392
5790
|
})
|
|
5393
5791
|
}) : null;
|
|
5394
5792
|
}
|
|
@@ -5486,7 +5884,8 @@ function ForMeList({entry: entry, work: work, identity: identity, onOpenActivity
|
|
|
5486
5884
|
filter: {
|
|
5487
5885
|
kind: "mine",
|
|
5488
5886
|
identity: identity
|
|
5489
|
-
}
|
|
5887
|
+
},
|
|
5888
|
+
surface: "document-view-for-me"
|
|
5490
5889
|
}) : null ]
|
|
5491
5890
|
})
|
|
5492
5891
|
});
|
|
@@ -5551,9 +5950,16 @@ function instanceNotice(entry) {
|
|
|
5551
5950
|
size: 1,
|
|
5552
5951
|
children: "This workflow didn’t finish starting — use Start workflow to continue it"
|
|
5553
5952
|
})
|
|
5554
|
-
}) : pending ? /* @__PURE__ */ jsx(
|
|
5555
|
-
|
|
5556
|
-
|
|
5953
|
+
}) : pending ? /* @__PURE__ */ jsx(WorkRow, {
|
|
5954
|
+
lead: /* @__PURE__ */ jsx(Spinner, {
|
|
5955
|
+
muted: !0,
|
|
5956
|
+
size: 1
|
|
5957
|
+
}),
|
|
5958
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
5959
|
+
muted: !0,
|
|
5960
|
+
size: 1,
|
|
5961
|
+
children: "Loading…"
|
|
5962
|
+
})
|
|
5557
5963
|
}) : null;
|
|
5558
5964
|
}
|
|
5559
5965
|
|
|
@@ -5688,7 +6094,8 @@ function TodoFieldDialog({entry: entry, scope: scope, field: field, title: title
|
|
|
5688
6094
|
kind: "field",
|
|
5689
6095
|
scope: scope,
|
|
5690
6096
|
field: field
|
|
5691
|
-
}
|
|
6097
|
+
},
|
|
6098
|
+
surface: "todo-field-dialog"
|
|
5692
6099
|
})
|
|
5693
6100
|
})
|
|
5694
6101
|
});
|
|
@@ -5901,7 +6308,7 @@ function PillButton({children: children, pill: pill, hintDisabled: hintDisabled
|
|
|
5901
6308
|
}
|
|
5902
6309
|
|
|
5903
6310
|
function useFieldCommit({entry: entry, editability: editability}) {
|
|
5904
|
-
const {editFieldFor: editFieldFor} = useWorkflowContext(), target =
|
|
6311
|
+
const {editFieldFor: editFieldFor} = useWorkflowContext(), target = editFieldTarget(editability);
|
|
5905
6312
|
return {
|
|
5906
6313
|
set: value => editFieldFor(entry.instance._id, {
|
|
5907
6314
|
target: target,
|
|
@@ -6117,8 +6524,9 @@ function AssigneePill({entry: entry, pill: pill, editability: editability}) {
|
|
|
6117
6524
|
/* @__PURE__ */
|
|
6118
6525
|
return jsx(PillPopover, {
|
|
6119
6526
|
content: /* @__PURE__ */ jsx(AssigneePicker, {
|
|
6120
|
-
|
|
6121
|
-
|
|
6527
|
+
onChange: next => {
|
|
6528
|
+
const changed = changedAssignee(current ? [ current ] : [], next);
|
|
6529
|
+
changed && (setOpen(!1), pick(changed));
|
|
6122
6530
|
},
|
|
6123
6531
|
value: current ? [ current ] : []
|
|
6124
6532
|
}),
|
|
@@ -6137,10 +6545,8 @@ function AssigneesPill({entry: entry, pill: pill, editability: editability}) {
|
|
|
6137
6545
|
/* @__PURE__ */
|
|
6138
6546
|
return jsx(PillPopover, {
|
|
6139
6547
|
content: /* @__PURE__ */ jsx(AssigneePicker, {
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
const next = current.some(a => sameAssignee(a, assignee)) ? current.filter(a => !sameAssignee(a, assignee)) : [ ...current, assignee ];
|
|
6143
|
-
save(() => set(next));
|
|
6548
|
+
onChange: next => {
|
|
6549
|
+
saving || save(() => set(next));
|
|
6144
6550
|
},
|
|
6145
6551
|
value: current
|
|
6146
6552
|
}),
|
|
@@ -6245,15 +6651,15 @@ function Hairline({weight: weight, style: style}) {
|
|
|
6245
6651
|
});
|
|
6246
6652
|
}
|
|
6247
6653
|
|
|
6248
|
-
function CollapsibleBand({header: header, children: children, background: background = !1, defaultOpen: defaultOpen = !0, sticky: sticky = !1, title: title}) {
|
|
6249
|
-
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";
|
|
6250
6656
|
/* @__PURE__ */
|
|
6251
6657
|
return jsxs(Stack, {
|
|
6252
6658
|
gap: 1,
|
|
6253
6659
|
children: [
|
|
6254
6660
|
/* @__PURE__ */ jsx(Card, {
|
|
6255
6661
|
onDoubleClick: event => {
|
|
6256
|
-
event.target instanceof Element && event.target.closest("a, button") ||
|
|
6662
|
+
event.target instanceof Element && event.target.closest("a, button") || toggle();
|
|
6257
6663
|
},
|
|
6258
6664
|
padding: 1,
|
|
6259
6665
|
radius: 3,
|
|
@@ -6274,7 +6680,7 @@ function CollapsibleBand({header: header, children: children, background: backgr
|
|
|
6274
6680
|
fontSize: 1,
|
|
6275
6681
|
icon: open ? ChevronDownIcon : ChevronRightIcon,
|
|
6276
6682
|
mode: "bleed",
|
|
6277
|
-
onClick:
|
|
6683
|
+
onClick: toggle,
|
|
6278
6684
|
padding: 2
|
|
6279
6685
|
}), header ]
|
|
6280
6686
|
})
|
|
@@ -6617,20 +7023,7 @@ function InstanceDebugMenu({entry: entry}) {
|
|
|
6617
7023
|
}
|
|
6618
7024
|
|
|
6619
7025
|
function InstanceAccordion({entry: entry, children: children, defaultOpen: defaultOpen}) {
|
|
6620
|
-
const definition = useDefinition(entry), {instance: instance
|
|
6621
|
-
align: "center",
|
|
6622
|
-
gap: 2,
|
|
6623
|
-
style: badgeTrim,
|
|
6624
|
-
children: [
|
|
6625
|
-
/* @__PURE__ */ jsx(AbortedBadge, {
|
|
6626
|
-
instance: instance
|
|
6627
|
-
}), settled ? null : /* @__PURE__ */ jsx(OlderDefinitionBadge, {
|
|
6628
|
-
instance: instance
|
|
6629
|
-
}), !ready && entry.invalid === void 0 ? /* @__PURE__ */ jsx(Spinner, {
|
|
6630
|
-
muted: !0,
|
|
6631
|
-
size: 1
|
|
6632
|
-
}) : null ]
|
|
6633
|
-
});
|
|
7026
|
+
const definition = useDefinition(entry), {instance: instance} = entry, settled = !isLiveEntry(entry), title = instanceTitle(instance, definition), badgeTrim = useBadgeCapTrim();
|
|
6634
7027
|
/* @__PURE__ */
|
|
6635
7028
|
return jsx(CollapsibleBand, {
|
|
6636
7029
|
defaultOpen: defaultOpen ?? !settled,
|
|
@@ -6653,7 +7046,18 @@ function InstanceAccordion({entry: entry, children: children, defaultOpen: defau
|
|
|
6653
7046
|
textOverflow: "ellipsis",
|
|
6654
7047
|
weight: "medium",
|
|
6655
7048
|
children: title
|
|
6656
|
-
}),
|
|
7049
|
+
}),
|
|
7050
|
+
/* @__PURE__ */ jsxs(Flex, {
|
|
7051
|
+
align: "center",
|
|
7052
|
+
gap: 2,
|
|
7053
|
+
style: badgeTrim,
|
|
7054
|
+
children: [
|
|
7055
|
+
/* @__PURE__ */ jsx(AbortedBadge, {
|
|
7056
|
+
instance: instance
|
|
7057
|
+
}), settled ? null : /* @__PURE__ */ jsx(OlderDefinitionBadge, {
|
|
7058
|
+
instance: instance
|
|
7059
|
+
}) ]
|
|
7060
|
+
}) ]
|
|
6657
7061
|
}),
|
|
6658
7062
|
/* @__PURE__ */ jsx(TrailingHairline, {}),
|
|
6659
7063
|
/* @__PURE__ */ jsx(InstanceDebugMenu, {
|
|
@@ -6671,7 +7075,7 @@ function InstanceAccordion({entry: entry, children: children, defaultOpen: defau
|
|
|
6671
7075
|
}
|
|
6672
7076
|
|
|
6673
7077
|
function PartOfBand({instance: instance}) {
|
|
6674
|
-
const parentRef = instance.ancestors.at(-1), parentId = parentRef ?
|
|
7078
|
+
const parentRef = instance.ancestors.at(-1), parentId = parentRef ? toBareId(parentRef.id) : null, parentEntry = useWorkflowInstanceEntry(parentId), parentDefinition = useDefinition(parentEntry);
|
|
6675
7079
|
if (!parentId) return null;
|
|
6676
7080
|
const title = parentEntry ? instanceTitle(parentEntry.instance, parentDefinition) : parentId;
|
|
6677
7081
|
/* @__PURE__ */
|
|
@@ -7187,7 +7591,12 @@ function StageSection({entry: entry, onOpenActivity: onOpenActivity}) {
|
|
|
7187
7591
|
}
|
|
7188
7592
|
|
|
7189
7593
|
const VIEW_TAB_CODEC = workflowsTabCodec([ "overview", "for-me" ]), WorkflowsView = props => {
|
|
7190
|
-
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);
|
|
7191
7600
|
if (entries.length === 0) return discoveryInvalid !== void 0 ? /* @__PURE__ */ jsx(Box, {
|
|
7192
7601
|
padding: 4,
|
|
7193
7602
|
children: /* @__PURE__ */ jsx(InvalidDocNotice, {
|
|
@@ -7228,11 +7637,9 @@ const VIEW_TAB_CODEC = workflowsTabCodec([ "overview", "for-me" ]), WorkflowsVie
|
|
|
7228
7637
|
};
|
|
7229
7638
|
|
|
7230
7639
|
function DiscoverySpinner() {
|
|
7231
|
-
const
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
return () => clearTimeout(timer);
|
|
7235
|
-
}, []), /* @__PURE__ */ jsx(Flex, {
|
|
7640
|
+
const visible = useDelayedFlag(!0, 1e3);
|
|
7641
|
+
/* @__PURE__ */
|
|
7642
|
+
return jsx(Flex, {
|
|
7236
7643
|
align: "center",
|
|
7237
7644
|
height: "fill",
|
|
7238
7645
|
justify: "center",
|
|
@@ -7242,7 +7649,7 @@ function DiscoverySpinner() {
|
|
|
7242
7649
|
});
|
|
7243
7650
|
}
|
|
7244
7651
|
|
|
7245
|
-
const GROUP_GAP = 1;
|
|
7652
|
+
const BOOT_CUE_DELAY_MS = 400, GROUP_GAP = 1;
|
|
7246
7653
|
|
|
7247
7654
|
function useWorkflowsTab() {
|
|
7248
7655
|
const {params: params, setParams: setParams} = usePaneRouter();
|
|
@@ -7267,7 +7674,7 @@ function useOpenActivity(entries) {
|
|
|
7267
7674
|
}
|
|
7268
7675
|
|
|
7269
7676
|
function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappings: docTypeMappings, initialValue: initialValue}) {
|
|
7270
|
-
const identity = useAssignmentIdentity(), panelId = useId(), {params: params} = usePaneRouter(), {view: view, setView: setView} = useWorkflowsTab(), {openActivity: openActivity, setOpenActivity: setOpenActivity, dialogEntry: dialogEntry} = useOpenActivity(entries), active = entries.filter(isLiveEntry), finished = entries.filter(e => !isLiveEntry(e)), forMe = forMeWorkOf(active, identity), [landing] = useState(() => focusedLanding(params?.[WORKFLOWS_FOCUS_PARAM], entries.map(e => e.instance._id))), assignedWorkUnknown = active.some(e => e.invalid !== void 0), sectionFor = e => /* @__PURE__ */ jsx(WorkflowInstanceSection, {
|
|
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, {
|
|
7271
7678
|
defaultOpen: landingDefaultOpen(landing, e.instance._id),
|
|
7272
7679
|
entry: e,
|
|
7273
7680
|
onOpenActivity: activityName => setOpenActivity({
|
|
@@ -7288,6 +7695,7 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7288
7695
|
padding: 3,
|
|
7289
7696
|
children: [
|
|
7290
7697
|
/* @__PURE__ */ jsx(GroupHeading, {
|
|
7698
|
+
busy: booting,
|
|
7291
7699
|
count: active.length,
|
|
7292
7700
|
end:
|
|
7293
7701
|
/* @__PURE__ */ jsx(Box, {
|
|
@@ -7300,6 +7708,7 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7300
7708
|
initialValue: initialValue,
|
|
7301
7709
|
mappings: docTypeMappings,
|
|
7302
7710
|
mode: "bleed",
|
|
7711
|
+
source: "document-view-header",
|
|
7303
7712
|
tone: "default"
|
|
7304
7713
|
})
|
|
7305
7714
|
}),
|
|
@@ -7308,7 +7717,12 @@ function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappin
|
|
|
7308
7717
|
/* @__PURE__ */ jsx(TabSwitch, {
|
|
7309
7718
|
ariaControls: `${panelId}-panel`,
|
|
7310
7719
|
idPrefix: panelId,
|
|
7311
|
-
onSelect:
|
|
7720
|
+
onSelect: next => {
|
|
7721
|
+
next !== view && telemetry.log(WorkflowDocumentViewOpened, {
|
|
7722
|
+
tab: next,
|
|
7723
|
+
via: "tab-switch"
|
|
7724
|
+
}), setView(next);
|
|
7725
|
+
},
|
|
7312
7726
|
options: [ {
|
|
7313
7727
|
value: "overview",
|
|
7314
7728
|
label: "Overview"
|
|
@@ -7382,6 +7796,7 @@ function OverviewEmptyState({mappings: mappings, docId: docId, initialValue: ini
|
|
|
7382
7796
|
label: "Start workflow",
|
|
7383
7797
|
mappings: mappings,
|
|
7384
7798
|
mode: "ghost",
|
|
7799
|
+
source: "document-view-empty-state",
|
|
7385
7800
|
tone: "default"
|
|
7386
7801
|
})
|
|
7387
7802
|
},
|
|
@@ -7415,7 +7830,8 @@ function SectionActivityDialog({entry: entry, activityName: activityName, onClos
|
|
|
7415
7830
|
breadcrumb: instanceBreadcrumb(instance, definition),
|
|
7416
7831
|
definition: definition,
|
|
7417
7832
|
entry: entry,
|
|
7418
|
-
onClose: onClose
|
|
7833
|
+
onClose: onClose,
|
|
7834
|
+
source: "document-view"
|
|
7419
7835
|
});
|
|
7420
7836
|
}
|
|
7421
7837
|
|
|
@@ -7423,10 +7839,8 @@ function workflowsView(S) {
|
|
|
7423
7839
|
return S.view.component(WorkflowsView).id(WORKFLOWS_VIEW_ID).title("Workflows");
|
|
7424
7840
|
}
|
|
7425
7841
|
|
|
7426
|
-
function workflowDefaultDocumentNode(
|
|
7427
|
-
return (S,
|
|
7428
|
-
if (mappingForDocType(options.mappings, ctx.schemaType)) return S.document().views([ S.view.form(), workflowsView(S) ]);
|
|
7429
|
-
};
|
|
7842
|
+
function workflowDefaultDocumentNode() {
|
|
7843
|
+
return S => S.document().views([ S.view.form(), workflowsView(S) ]);
|
|
7430
7844
|
}
|
|
7431
7845
|
|
|
7432
7846
|
function lockTitleFor(args) {
|
|
@@ -7439,26 +7853,12 @@ function lockTitleFor(args) {
|
|
|
7439
7853
|
return workflows.length === 1 ? `The ${workflowList} workflow is holding this document.` : `The ${workflowList} workflows are holding this document.`;
|
|
7440
7854
|
}
|
|
7441
7855
|
|
|
7442
|
-
const EMPTY = {
|
|
7443
|
-
byType: /* @__PURE__ */ new Map,
|
|
7444
|
-
definitions: /* @__PURE__ */ new Map,
|
|
7445
|
-
warnings: []
|
|
7446
|
-
};
|
|
7447
|
-
|
|
7448
7856
|
function resolveAutoStart(args) {
|
|
7449
|
-
const {autoStart: autoStart,
|
|
7450
|
-
|
|
7451
|
-
const evaluated = evaluateMap(autoStart, context);
|
|
7452
|
-
if ("warning" in evaluated) return {
|
|
7453
|
-
byType: /* @__PURE__ */ new Map,
|
|
7454
|
-
definitions: /* @__PURE__ */ new Map,
|
|
7455
|
-
warnings: [ evaluated.warning ]
|
|
7456
|
-
};
|
|
7457
|
-
const map = evaluated.map, latestByName = new Map(latestDeployedDefinitions(definitions).map(d => [ d.name, d ])), byType = /* @__PURE__ */ new Map, resolvedDefinitions = /* @__PURE__ */ new Map, warnings = [];
|
|
7458
|
-
for (const [docType, spec] of Object.entries(map)) {
|
|
7857
|
+
const {autoStart: autoStart, knownDocTypes: knownDocTypes, definitions: definitions} = args, latestByName = new Map(latestDeployedDefinitions(definitions).map(d => [ d.name, d ])), byType = /* @__PURE__ */ new Map, resolvedDefinitions = /* @__PURE__ */ new Map, warnings = [];
|
|
7858
|
+
for (const [docType, names] of Object.entries(autoStart)) {
|
|
7459
7859
|
const entry = resolveEntry({
|
|
7460
7860
|
docType: docType,
|
|
7461
|
-
|
|
7861
|
+
names: names,
|
|
7462
7862
|
knownDocTypes: knownDocTypes,
|
|
7463
7863
|
latestByName: latestByName
|
|
7464
7864
|
});
|
|
@@ -7474,35 +7874,15 @@ function resolveAutoStart(args) {
|
|
|
7474
7874
|
};
|
|
7475
7875
|
}
|
|
7476
7876
|
|
|
7477
|
-
function evaluateMap(autoStart, context) {
|
|
7478
|
-
let map;
|
|
7479
|
-
try {
|
|
7480
|
-
map = typeof autoStart == "function" ? autoStart(context) : autoStart;
|
|
7481
|
-
} catch (err) {
|
|
7482
|
-
return {
|
|
7483
|
-
warning: `autoStart: config function threw — ignoring it (${describeError(err)}).`
|
|
7484
|
-
};
|
|
7485
|
-
}
|
|
7486
|
-
return typeof map != "object" || map === null ? {
|
|
7487
|
-
warning: "autoStart: config did not resolve to an object — ignoring it."
|
|
7488
|
-
} : {
|
|
7489
|
-
map: map
|
|
7490
|
-
};
|
|
7491
|
-
}
|
|
7492
|
-
|
|
7493
|
-
function specNames(spec) {
|
|
7494
|
-
return typeof spec == "string" ? [ spec ] : Array.isArray(spec) ? spec : [];
|
|
7495
|
-
}
|
|
7496
|
-
|
|
7497
7877
|
function resolveEntry(args) {
|
|
7498
|
-
const {docType: docType,
|
|
7878
|
+
const {docType: docType, names: names, knownDocTypes: knownDocTypes, latestByName: latestByName} = args;
|
|
7499
7879
|
if (!knownDocTypes.has(docType)) return {
|
|
7500
7880
|
valid: [],
|
|
7501
7881
|
definitions: [],
|
|
7502
7882
|
warnings: [ `autoStart: no schema type "${docType}" — entry skipped.` ]
|
|
7503
7883
|
};
|
|
7504
7884
|
const valid = [], definitions = [], warnings = [];
|
|
7505
|
-
for (const name of
|
|
7885
|
+
for (const name of names) {
|
|
7506
7886
|
const definition = latestByName.get(name), issue = workflowIssue({
|
|
7507
7887
|
name: name,
|
|
7508
7888
|
docType: docType,
|
|
@@ -7528,11 +7908,57 @@ function workflowIssue(args) {
|
|
|
7528
7908
|
const {name: name, docType: docType, definition: definition} = args;
|
|
7529
7909
|
if (definition === void 0) return `autoStart: "${docType}" → workflow "${name}" is not deployed — skipped.`;
|
|
7530
7910
|
if (!isStartableDefinition(definition)) return `autoStart: "${docType}" → workflow "${name}" is spawn-only, not startable — skipped.`;
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7911
|
+
const subject = documentSubjectEntry(definition), acceptsType = subject?.types === void 0 || subject.types.includes(docType);
|
|
7912
|
+
if (subject === void 0 || !acceptsType) return `autoStart: "${docType}" → workflow "${name}" has no document subject accepting "${docType}" — skipped.`;
|
|
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.`;
|
|
7914
|
+
}
|
|
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
|
+
};
|
|
7536
7962
|
}
|
|
7537
7963
|
|
|
7538
7964
|
function contentDocumentTypes(schema) {
|
|
@@ -7541,7 +7967,7 @@ function contentDocumentTypes(schema) {
|
|
|
7541
7967
|
|
|
7542
7968
|
async function readDeployedDefinitions(engine) {
|
|
7543
7969
|
return (await engine.query({
|
|
7544
|
-
groq:
|
|
7970
|
+
groq: latestDefinitionsGroq()
|
|
7545
7971
|
})).map(assertReadableModel);
|
|
7546
7972
|
}
|
|
7547
7973
|
|
|
@@ -7552,20 +7978,31 @@ const EMPTY_SNAPSHOT = {
|
|
|
7552
7978
|
};
|
|
7553
7979
|
|
|
7554
7980
|
function useDiscoveryState(args) {
|
|
7555
|
-
const {
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
watching || (setLatest(EMPTY_SNAPSHOT), setResolved(EMPTY_SNAPSHOT));
|
|
7560
|
-
}, [ watching ]);
|
|
7561
|
-
const filter = useMemo(() => ({
|
|
7562
|
-
documents: registered.map(id => gdrFromResource(contentResource, id)),
|
|
7981
|
+
const {observed: observed, requested: requested, contentResource: contentResource} = args, documentWatching = observed.length > 0, requestedWatching = requested.length > 0, documents = useDiscoveryStream(documentWatching), explicit = useDiscoveryStream(requestedWatching), documentFilter = useMemo(() => documentWatching ? {
|
|
7982
|
+
documents: observed.map(id => gdrFromResource(contentResource, id)),
|
|
7983
|
+
includeCompleted: !0
|
|
7984
|
+
} : void 0, [ documentWatching, observed, contentResource ]), requestedFilter = useMemo(() => requestedWatching ? {
|
|
7563
7985
|
ids: requested,
|
|
7564
7986
|
includeCompleted: !0
|
|
7565
|
-
}
|
|
7987
|
+
} : void 0, [ requestedWatching, requested ]), resolved = useMemo(() => mergeResolved(documents.resolved, explicit.resolved), [ documents.resolved, explicit.resolved ]);
|
|
7566
7988
|
return {
|
|
7567
|
-
|
|
7568
|
-
|
|
7989
|
+
documentFilter: documentFilter,
|
|
7990
|
+
requestedFilter: requestedFilter,
|
|
7991
|
+
loading: documents.loading || explicit.loading,
|
|
7992
|
+
invalid: documents.invalid ?? explicit.invalid,
|
|
7993
|
+
resolved: resolved,
|
|
7994
|
+
onDocumentSnapshot: documents.onSnapshot,
|
|
7995
|
+
onRequestedSnapshot: explicit.onSnapshot
|
|
7996
|
+
};
|
|
7997
|
+
}
|
|
7998
|
+
|
|
7999
|
+
function useDiscoveryStream(watching) {
|
|
8000
|
+
const [latest, setLatest] = useState(EMPTY_SNAPSHOT), [resolved, setResolved] = useState(EMPTY_SNAPSHOT), onSnapshot = useCallback(snapshot => {
|
|
8001
|
+
setLatest(snapshot), snapshot.instances !== void 0 && setResolved(snapshot);
|
|
8002
|
+
}, []);
|
|
8003
|
+
return useEffect(() => {
|
|
8004
|
+
watching || (setLatest(EMPTY_SNAPSHOT), setResolved(EMPTY_SNAPSHOT));
|
|
8005
|
+
}, [ watching ]), {
|
|
7569
8006
|
loading: watching && latest.instances === void 0 && latest.invalid === void 0,
|
|
7570
8007
|
invalid: watching ? latest.invalid : void 0,
|
|
7571
8008
|
resolved: resolved,
|
|
@@ -7573,18 +8010,62 @@ function useDiscoveryState(args) {
|
|
|
7573
8010
|
};
|
|
7574
8011
|
}
|
|
7575
8012
|
|
|
7576
|
-
function
|
|
7577
|
-
const
|
|
7578
|
-
for (const
|
|
7579
|
-
const
|
|
7580
|
-
|
|
8013
|
+
function mergeResolved(documents, explicit) {
|
|
8014
|
+
const rows = [ ...documents.instances ?? [], ...explicit.instances ?? [] ], freshest = /* @__PURE__ */ new Map;
|
|
8015
|
+
for (const instance of rows) {
|
|
8016
|
+
const current = freshest.get(instance._id);
|
|
8017
|
+
(current === void 0 || Date.parse(instance.lastChangedAt) > Date.parse(current.lastChangedAt)) && freshest.set(instance._id, instance);
|
|
7581
8018
|
}
|
|
8019
|
+
return {
|
|
8020
|
+
instances: documents.instances === void 0 && explicit.instances === void 0 ? void 0 : [ ...freshest.values() ],
|
|
8021
|
+
invalid: documents.invalid ?? explicit.invalid,
|
|
8022
|
+
registered: documents.registered
|
|
8023
|
+
};
|
|
8024
|
+
}
|
|
8025
|
+
|
|
8026
|
+
function createDiscoveryIndexer(deriveWatchSet = subscriptionDocumentsForInstance) {
|
|
8027
|
+
const cached = /* @__PURE__ */ new Map;
|
|
8028
|
+
return {
|
|
8029
|
+
index(args) {
|
|
8030
|
+
const liveIds = new Set(args.instances.map(instance => instance._id));
|
|
8031
|
+
for (const id of cached.keys()) liveIds.has(id) || cached.delete(id);
|
|
8032
|
+
const watchedById = /* @__PURE__ */ new Map;
|
|
8033
|
+
for (const instance of args.instances) {
|
|
8034
|
+
let row = cached.get(instance._id);
|
|
8035
|
+
row?.source !== instance && (row = {
|
|
8036
|
+
source: instance,
|
|
8037
|
+
globalDocumentIds: [ ...new Set(deriveWatchSet(instance).documents.map(document => document.globalDocumentId)) ]
|
|
8038
|
+
}, cached.set(instance._id, row)), watchedById.set(instance._id, row.globalDocumentIds);
|
|
8039
|
+
}
|
|
8040
|
+
return buildDiscoveryIndex(args, watchedById);
|
|
8041
|
+
}
|
|
8042
|
+
};
|
|
8043
|
+
}
|
|
8044
|
+
|
|
8045
|
+
function buildDiscoveryIndex(args, watchedById) {
|
|
8046
|
+
const {instances: instances, registered: registered, contentResource: contentResource} = args, ordered = [ ...instances ].sort((a, b) => b.startedAt.localeCompare(a.startedAt)), index = /* @__PURE__ */ new Map, registeredByUri = new Map(registered.map(bareId => [ gdrFromResource(contentResource, bareId), bareId ]));
|
|
8047
|
+
for (const instance of ordered) appendInstanceWatches({
|
|
8048
|
+
index: index,
|
|
8049
|
+
registeredByUri: registeredByUri,
|
|
8050
|
+
instanceId: instance._id,
|
|
8051
|
+
watched: watchedById.get(instance._id) ?? []
|
|
8052
|
+
});
|
|
7582
8053
|
return {
|
|
7583
8054
|
instances: new Map(ordered.map(inst => [ inst._id, inst ])),
|
|
7584
8055
|
index: index
|
|
7585
8056
|
};
|
|
7586
8057
|
}
|
|
7587
8058
|
|
|
8059
|
+
function appendInstanceWatches(args) {
|
|
8060
|
+
const {index: index, registeredByUri: registeredByUri, instanceId: instanceId, watched: watched} = args;
|
|
8061
|
+
for (const uri of watched) {
|
|
8062
|
+
const bareId = registeredByUri.get(uri);
|
|
8063
|
+
if (bareId === void 0) continue;
|
|
8064
|
+
const ids = index.get(bareId);
|
|
8065
|
+
ids === void 0 ? index.set(bareId, [ instanceId ]) : ids.push(instanceId);
|
|
8066
|
+
}
|
|
8067
|
+
}
|
|
8068
|
+
|
|
7588
8069
|
function sameInstance(a, b) {
|
|
7589
8070
|
return a === b || a._id === b._id && a._rev === b._rev;
|
|
7590
8071
|
}
|
|
@@ -7608,7 +8089,7 @@ function entryOf(inst, report) {
|
|
|
7608
8089
|
instance: report?.evaluation?.instance ?? inst,
|
|
7609
8090
|
committed: inst,
|
|
7610
8091
|
evaluation: report?.evaluation,
|
|
7611
|
-
ready: report?.ready ??
|
|
8092
|
+
ready: report?.ready ?? terminalState(inst) !== "in-flight",
|
|
7612
8093
|
invalid: report?.invalid,
|
|
7613
8094
|
guards: report?.guards
|
|
7614
8095
|
};
|
|
@@ -7701,7 +8182,19 @@ function createEntriesStore() {
|
|
|
7701
8182
|
};
|
|
7702
8183
|
}
|
|
7703
8184
|
|
|
7704
|
-
|
|
8185
|
+
function sessionPlan(args) {
|
|
8186
|
+
const demandedIds = new Set(args.demanded), evaluated = [ ...args.discovered.values() ].filter(inst => demandedIds.has(inst._id));
|
|
8187
|
+
return {
|
|
8188
|
+
evaluated: evaluated,
|
|
8189
|
+
guardScope: evaluated.map(inst => inst._id).sort()
|
|
8190
|
+
};
|
|
8191
|
+
}
|
|
8192
|
+
|
|
8193
|
+
function useDefaultLayout(props) {
|
|
8194
|
+
return useMemo(() => props.renderDefault(props), [ props ]);
|
|
8195
|
+
}
|
|
8196
|
+
|
|
8197
|
+
const notReady = (..._args) => Promise.reject(new Error("workflow session not ready yet")), NO_REGISTERED_DOCUMENTS = [], DEMAND_RELEASE_GRACE_MS = 500;
|
|
7705
8198
|
|
|
7706
8199
|
function workspaceParts(config) {
|
|
7707
8200
|
if (!config.projectId || !config.dataset) throw new Error("workflow plugin requires a workspace with projectId and dataset");
|
|
@@ -7729,10 +8222,11 @@ class InstanceEvaluatorBoundary extends Component {
|
|
|
7729
8222
|
}
|
|
7730
8223
|
|
|
7731
8224
|
function InstanceEvaluator(props) {
|
|
7732
|
-
const {engine: engine, instanceId: instanceId, grantsFromPath: grantsFromPath, onReport: onReport} = props, {evaluation: evaluation, ready: ready, invalid: invalid, guards: guards, fireAction: fireAction, editField: editField, previewField: previewField, discardFieldPreview: discardFieldPreview} = useWorkflowSession({
|
|
8225
|
+
const {engine: engine, instanceId: instanceId, grantsFromPath: grantsFromPath, guardScope: guardScope, onReport: onReport} = props, {evaluation: evaluation, ready: ready, invalid: invalid, guards: guards, fireAction: fireAction, editField: editField, previewField: previewField, discardFieldPreview: discardFieldPreview} = useWorkflowSession({
|
|
7733
8226
|
engine: engine,
|
|
7734
8227
|
instanceId: instanceId,
|
|
7735
|
-
grantsFromPath: grantsFromPath
|
|
8228
|
+
grantsFromPath: grantsFromPath,
|
|
8229
|
+
guardScope: guardScope
|
|
7736
8230
|
});
|
|
7737
8231
|
return useEffect(() => {
|
|
7738
8232
|
onReport(instanceId, {
|
|
@@ -7775,9 +8269,9 @@ function engineOptionsFrom(config) {
|
|
|
7775
8269
|
}
|
|
7776
8270
|
|
|
7777
8271
|
function WorkflowProvider(props) {
|
|
7778
|
-
const {config: config} = props, studioClient = useClient({
|
|
8272
|
+
const {config: config} = props, defaultLayout = useDefaultLayout(props), studioClient = useClient({
|
|
7779
8273
|
apiVersion: WORKFLOW_API_VERSION
|
|
7780
|
-
}), schema = useSchema(), {
|
|
8274
|
+
}), schema = useSchema(), {projectId: projectId, dataset: contentDataset} = workspaceParts(studioClient.config()), workflowDataset = config.workflowDataset ?? contentDataset, binding = useMemo(() => ({
|
|
7781
8275
|
engineResource: {
|
|
7782
8276
|
type: "dataset",
|
|
7783
8277
|
id: `${projectId}.${workflowDataset}`
|
|
@@ -7795,11 +8289,19 @@ function WorkflowProvider(props) {
|
|
|
7795
8289
|
}), grantsFromPath = aclPathForResource({
|
|
7796
8290
|
type: "dataset",
|
|
7797
8291
|
id: `${projectId}.${workflowDataset}`
|
|
7798
|
-
}), {ids: registered, acquire:
|
|
8292
|
+
}), {ids: registered, acquire: registerActive, release: unregisterActive} = useRefcountedIds(), {ids: observed, acquire: retainRegistration, release: releaseRegistration} = useRefcountedIds({
|
|
8293
|
+
releaseDelayMs: DEMAND_RELEASE_GRACE_MS
|
|
8294
|
+
}), register = useCallback(id => {
|
|
8295
|
+
registerActive(id), retainRegistration(id);
|
|
8296
|
+
}, [ registerActive, retainRegistration ]), unregister = useCallback(id => {
|
|
8297
|
+
unregisterActive(id), releaseRegistration(id);
|
|
8298
|
+
}, [ unregisterActive, releaseRegistration ]), {ids: requested, acquire: requestInstance, release: releaseInstance} = useRefcountedIds(), {ids: evaluationDemand, acquire: requestEvaluation, release: releaseEvaluation} = useRefcountedIds({
|
|
8299
|
+
releaseDelayMs: DEMAND_RELEASE_GRACE_MS
|
|
8300
|
+
}), [seeded, setSeeded] = useState(/* @__PURE__ */ new Map), seedInstance = useCallback(instance => {
|
|
7799
8301
|
setSeeded(prev => new Map(prev).set(instance._id, instance));
|
|
7800
8302
|
}, []), [startRequest2, setStartRequest] = useState(void 0), openStartDialog = useCallback(r => setStartRequest(r), []), closeStartDialog = useCallback(() => setStartRequest(void 0), []), [entriesStore] = useState(createEntriesStore);
|
|
7801
8303
|
useEffect(() => () => entriesStore.dispose(), [ entriesStore ]);
|
|
7802
|
-
const onReport = useCallback((instanceId, report) => {
|
|
8304
|
+
const previewStore = useDocumentPreviewStore(), actualTypes = useMemo(() => createActualTypeProbeStore(previewStore), [ previewStore ]), onReport = useCallback((instanceId, report) => {
|
|
7803
8305
|
entriesStore.report(instanceId, report);
|
|
7804
8306
|
}, [ entriesStore ]), drainRef = useRef(void 0), drainCommitted = useCallback(async instanceId => {
|
|
7805
8307
|
try {
|
|
@@ -7846,15 +8348,18 @@ function WorkflowProvider(props) {
|
|
|
7846
8348
|
});
|
|
7847
8349
|
}, [ engine ]);
|
|
7848
8350
|
drainRef.current = drainEffectsFor;
|
|
7849
|
-
const {
|
|
7850
|
-
|
|
8351
|
+
const {documentFilter: documentFilter, requestedFilter: requestedFilter, loading: loading, invalid: discoveryInvalid, resolved: resolved, onDocumentSnapshot: onDocumentSnapshot, onRequestedSnapshot: onRequestedSnapshot} = useDiscoveryState({
|
|
8352
|
+
observed: observed,
|
|
7851
8353
|
requested: requested,
|
|
7852
8354
|
contentResource: binding.contentResource
|
|
7853
|
-
}), {instances: discovered, index: docIndex} = useMemo(() =>
|
|
8355
|
+
}), discoveryIndexer = useMemo(createDiscoveryIndexer, []), {instances: discovered, index: docIndex} = useMemo(() => discoveryIndexer.index({
|
|
7854
8356
|
instances: resolved.instances ?? [],
|
|
7855
8357
|
registered: resolved.registered,
|
|
7856
8358
|
contentResource: binding.contentResource
|
|
7857
|
-
}), [ resolved, binding.contentResource ]),
|
|
8359
|
+
}), [ discoveryIndexer, resolved, binding.contentResource ]), {evaluated: evaluated, guardScope: guardScope} = useMemo(() => sessionPlan({
|
|
8360
|
+
discovered: discovered,
|
|
8361
|
+
demanded: evaluationDemand
|
|
8362
|
+
}), [ discovered, evaluationDemand ]), resolvedDocs = useMemo(() => new Set(resolved.registered), [ resolved.registered ]);
|
|
7858
8363
|
useEffect(() => {
|
|
7859
8364
|
setSeeded(prev => {
|
|
7860
8365
|
const kept = [ ...prev ].filter(([id]) => !discovered.has(id));
|
|
@@ -7867,22 +8372,23 @@ function WorkflowProvider(props) {
|
|
|
7867
8372
|
docIndex: docIndex
|
|
7868
8373
|
});
|
|
7869
8374
|
}, [ entriesStore, seeded, discovered, docIndex ]);
|
|
7870
|
-
const isDocResolved = useCallback(docId => resolvedDocs.has(docId), [ resolvedDocs ]), schemaContentTypes = useMemo(() => new Set(contentDocumentTypes(schema)), [ schema ]), {issues: issues, starts: starts, fields: fields, latestVersions: latestVersions, autoStartByType: autoStartByType, autoStartDefinitions: autoStartDefinitions} = useDeployedDefinitions({
|
|
8375
|
+
const isDocResolved = useCallback(docId => resolvedDocs.has(docId), [ resolvedDocs ]), schemaContentTypes = useMemo(() => new Set(contentDocumentTypes(schema)), [ schema ]), {mappings: mappings, issues: issues, starts: starts, fields: fields, latestVersions: latestVersions, autoStartByType: autoStartByType, autoStartDefinitions: autoStartDefinitions} = useDeployedDefinitions({
|
|
7871
8376
|
engine: engine,
|
|
7872
|
-
|
|
8377
|
+
overrides: config.mappings,
|
|
7873
8378
|
contentResource: binding.contentResource,
|
|
7874
8379
|
schemaContentTypes: schemaContentTypes,
|
|
7875
8380
|
startRequest: startRequest2,
|
|
7876
|
-
|
|
7877
|
-
schema: schema,
|
|
7878
|
-
workspaceName: workspaceName
|
|
8381
|
+
schema: schema
|
|
7879
8382
|
}), value = useMemo(() => ({
|
|
7880
8383
|
register: register,
|
|
7881
8384
|
unregister: unregister,
|
|
7882
8385
|
isDocResolved: isDocResolved,
|
|
7883
8386
|
entries: entriesStore,
|
|
8387
|
+
actualTypes: actualTypes,
|
|
7884
8388
|
requestInstance: requestInstance,
|
|
7885
8389
|
releaseInstance: releaseInstance,
|
|
8390
|
+
requestEvaluation: requestEvaluation,
|
|
8391
|
+
releaseEvaluation: releaseEvaluation,
|
|
7886
8392
|
seedInstance: seedInstance,
|
|
7887
8393
|
openStartDialog: openStartDialog,
|
|
7888
8394
|
closeStartDialog: closeStartDialog,
|
|
@@ -7897,7 +8403,7 @@ function WorkflowProvider(props) {
|
|
|
7897
8403
|
completeEffectFor: completeEffectFor,
|
|
7898
8404
|
engine: engine,
|
|
7899
8405
|
binding: binding,
|
|
7900
|
-
mappings:
|
|
8406
|
+
mappings: mappings,
|
|
7901
8407
|
mappingIssues: issues,
|
|
7902
8408
|
mappingStarts: starts,
|
|
7903
8409
|
mappingFields: fields,
|
|
@@ -7905,24 +8411,30 @@ function WorkflowProvider(props) {
|
|
|
7905
8411
|
effectHandlers: engine.effectHandlers,
|
|
7906
8412
|
autoStartByType: autoStartByType,
|
|
7907
8413
|
autoStartDefinitions: autoStartDefinitions
|
|
7908
|
-
}), [ register, unregister, isDocResolved, entriesStore, requestInstance, releaseInstance, seedInstance, openStartDialog, closeStartDialog, startRequest2, loading, discoveryInvalid, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding,
|
|
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 ]);
|
|
7909
8415
|
/* @__PURE__ */
|
|
7910
8416
|
return jsxs(WorkflowContext.Provider, {
|
|
7911
8417
|
value: value,
|
|
7912
|
-
children: [
|
|
8418
|
+
children: [ documentFilter ? /* @__PURE__ */ jsx(DiscoverySubscription, {
|
|
7913
8419
|
engine: engine,
|
|
7914
|
-
filter:
|
|
7915
|
-
onSnapshot:
|
|
8420
|
+
filter: documentFilter,
|
|
8421
|
+
onSnapshot: onDocumentSnapshot,
|
|
7916
8422
|
registered: registered
|
|
7917
|
-
}) : null,
|
|
8423
|
+
}) : null, requestedFilter ? /* @__PURE__ */ jsx(DiscoverySubscription, {
|
|
8424
|
+
engine: engine,
|
|
8425
|
+
filter: requestedFilter,
|
|
8426
|
+
onSnapshot: onRequestedSnapshot,
|
|
8427
|
+
registered: NO_REGISTERED_DOCUMENTS
|
|
8428
|
+
}) : null, evaluated.map(inst => /* @__PURE__ */ jsx(InstanceEvaluatorBoundary, {
|
|
7918
8429
|
instanceId: inst._id,
|
|
7919
8430
|
children: /* @__PURE__ */ jsx(InstanceEvaluator, {
|
|
7920
8431
|
engine: engine,
|
|
7921
8432
|
grantsFromPath: grantsFromPath,
|
|
8433
|
+
guardScope: guardScope,
|
|
7922
8434
|
instanceId: inst._id,
|
|
7923
8435
|
onReport: onReport
|
|
7924
8436
|
})
|
|
7925
|
-
}, inst._id)),
|
|
8437
|
+
}, inst._id)), defaultLayout, props.overlay ]
|
|
7926
8438
|
});
|
|
7927
8439
|
}
|
|
7928
8440
|
|
|
@@ -7932,14 +8444,25 @@ function sameEntries(a, b) {
|
|
|
7932
8444
|
return !0;
|
|
7933
8445
|
}
|
|
7934
8446
|
|
|
8447
|
+
function sameMappings(a, b) {
|
|
8448
|
+
return a.length === b.length && a.every((mapping, index) => {
|
|
8449
|
+
const other = b[index];
|
|
8450
|
+
return other !== void 0 && mappingKey(mapping) === mappingKey(other) && mapping.label === other.label && mapping.autoStart === other.autoStart && mapping.initialStateBuilder === other.initialStateBuilder && mapping.contextBuilder === other.contextBuilder && mapping.perspectiveField === other.perspectiveField;
|
|
8451
|
+
});
|
|
8452
|
+
}
|
|
8453
|
+
|
|
7935
8454
|
function useDeployedDefinitions(args) {
|
|
7936
|
-
const {engine: engine,
|
|
8455
|
+
const {engine: engine, overrides: overrides, contentResource: contentResource, schemaContentTypes: schemaContentTypes, startRequest: startRequest2, schema: schema} = args, [mappings, setMappings] = useState([]), [issues, setIssues] = useState(/* @__PURE__ */ new Map), [starts, setStarts] = useState(/* @__PURE__ */ new Map), [fields, setFields] = useState(/* @__PURE__ */ new Map), [latestVersions, setLatestVersions] = useState(/* @__PURE__ */ new Map), [autoStartByType, setAutoStartByType] = useState(
|
|
7937
8456
|
/* @__PURE__ */ new Map), [autoStartDefinitions, setAutoStartDefinitions] = useState(/* @__PURE__ */ new Map), logged = useRef(/* @__PURE__ */ new Set);
|
|
7938
8457
|
return useEffect(() => {
|
|
7939
8458
|
let cancelled = !1;
|
|
7940
8459
|
return (async () => {
|
|
7941
|
-
const definitions = await readDeployedDefinitions(engine),
|
|
7942
|
-
|
|
8460
|
+
const definitions = await readDeployedDefinitions(engine), effectiveMappings = discoverWorkflowMappings({
|
|
8461
|
+
definitions: definitions,
|
|
8462
|
+
schemaContentTypes: schemaContentTypes,
|
|
8463
|
+
overrides: overrides
|
|
8464
|
+
}), found = mappingIssues({
|
|
8465
|
+
mappings: effectiveMappings,
|
|
7943
8466
|
definitions: definitions,
|
|
7944
8467
|
contentResource: contentResource,
|
|
7945
8468
|
schemaContentTypes: schemaContentTypes
|
|
@@ -7949,32 +8472,30 @@ function useDeployedDefinitions(args) {
|
|
|
7949
8472
|
logged.current.has(signature) || (logged.current.add(signature), console.error(`[workflow-studio-plugin] ${message}`));
|
|
7950
8473
|
}
|
|
7951
8474
|
const resolvedAutoStart = resolveAutoStart({
|
|
7952
|
-
autoStart:
|
|
7953
|
-
context: {
|
|
7954
|
-
workspaceName: workspaceName,
|
|
7955
|
-
schema: schema
|
|
7956
|
-
},
|
|
8475
|
+
autoStart: mappingAutoStartMap(effectiveMappings),
|
|
7957
8476
|
knownDocTypes: new Set(schema.getTypeNames()),
|
|
7958
8477
|
definitions: definitions
|
|
7959
8478
|
});
|
|
7960
8479
|
if (logOnce(resolvedAutoStart.warnings, logged.current), cancelled) return;
|
|
8480
|
+
setMappings(prev => sameMappings(prev, effectiveMappings) ? prev : effectiveMappings),
|
|
7961
8481
|
setIssues(prev => sameEntries(prev, found) ? prev : found), setStarts(mappingStartBlocks({
|
|
7962
|
-
mappings:
|
|
8482
|
+
mappings: effectiveMappings,
|
|
7963
8483
|
definitions: definitions
|
|
7964
8484
|
})), setFields(mappingDeclaredFields({
|
|
7965
|
-
mappings:
|
|
8485
|
+
mappings: effectiveMappings,
|
|
7966
8486
|
definitions: definitions
|
|
7967
8487
|
}));
|
|
7968
8488
|
const versions = new Map(latestDeployedDefinitions(definitions).map(d => [ d.name, d.version ]));
|
|
7969
8489
|
setLatestVersions(prev => sameEntries(prev, versions) ? prev : versions), setAutoStartByType(resolvedAutoStart.byType),
|
|
7970
8490
|
setAutoStartDefinitions(resolvedAutoStart.definitions);
|
|
7971
8491
|
})().catch(err => {
|
|
7972
|
-
console.error("[workflow-studio-plugin] mapping
|
|
8492
|
+
console.error("[workflow-studio-plugin] mapping discovery failed — keeping the last resolved workflow state:", err);
|
|
7973
8493
|
}), () => {
|
|
7974
8494
|
cancelled = !0;
|
|
7975
8495
|
};
|
|
7976
|
-
}, [ engine,
|
|
8496
|
+
}, [ engine, overrides, contentResource, schemaContentTypes, startRequest2, schema ]),
|
|
7977
8497
|
{
|
|
8498
|
+
mappings: mappings,
|
|
7978
8499
|
issues: issues,
|
|
7979
8500
|
starts: starts,
|
|
7980
8501
|
fields: fields,
|
|
@@ -8363,12 +8884,12 @@ function DocRefsFieldInput({entry: entry, mappedType: mappedType, value: value,
|
|
|
8363
8884
|
}
|
|
8364
8885
|
|
|
8365
8886
|
function NotesStartInput({onChange: onChange}) {
|
|
8366
|
-
const
|
|
8887
|
+
const selfActor = useSelfActor(), [body, setBody] = useState(""), update = next => {
|
|
8367
8888
|
setBody(next);
|
|
8368
8889
|
const trimmed = next.trim();
|
|
8369
8890
|
onChange(trimmed === "" ? [] : [ noteRow({
|
|
8370
8891
|
body: trimmed,
|
|
8371
|
-
actor:
|
|
8892
|
+
actor: selfActor,
|
|
8372
8893
|
at: /* @__PURE__ */ (new Date).toISOString()
|
|
8373
8894
|
}) ]);
|
|
8374
8895
|
};
|
|
@@ -8577,7 +9098,7 @@ function handleStartError(args) {
|
|
|
8577
9098
|
toast.push({
|
|
8578
9099
|
status: "warning",
|
|
8579
9100
|
title: `${label} can't be started right now`,
|
|
8580
|
-
description:
|
|
9101
|
+
description: outcome.description
|
|
8581
9102
|
});
|
|
8582
9103
|
return;
|
|
8583
9104
|
}
|
|
@@ -8589,7 +9110,7 @@ function handleStartError(args) {
|
|
|
8589
9110
|
}
|
|
8590
9111
|
|
|
8591
9112
|
function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
8592
|
-
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({
|
|
8593
9114
|
entries: entries,
|
|
8594
9115
|
definitionName: definitionName,
|
|
8595
9116
|
heldInstanceId: heldInstanceId,
|
|
@@ -8612,7 +9133,10 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
|
8612
9133
|
[name]: v
|
|
8613
9134
|
})), heldInstanceId !== void 0 && declineResume();
|
|
8614
9135
|
}, onStart = async () => {
|
|
8615
|
-
|
|
9136
|
+
telemetry.log(WorkflowStartDialogSubmitted, {
|
|
9137
|
+
source: request.source,
|
|
9138
|
+
resumed: resuming
|
|
9139
|
+
}), setAttempt({
|
|
8616
9140
|
resume: resumeEntry
|
|
8617
9141
|
});
|
|
8618
9142
|
const instanceId = resumeEntry?.instance._id ?? heldInstanceId ?? instanceDocId(binding.tag);
|
|
@@ -8692,8 +9216,9 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
|
8692
9216
|
}
|
|
8693
9217
|
|
|
8694
9218
|
function StartWorkflowDialog({request: request, onClose: onClose}) {
|
|
8695
|
-
|
|
8696
|
-
|
|
9219
|
+
return useLogEventOnMount(WorkflowStartDialogOpened, {
|
|
9220
|
+
source: request.source
|
|
9221
|
+
}), /* @__PURE__ */ jsx(Dialog, {
|
|
8697
9222
|
header: `Start ${request.label}`,
|
|
8698
9223
|
id: "start-workflow",
|
|
8699
9224
|
onClose: onClose,
|
|
@@ -8760,7 +9285,7 @@ function isFreshDocument(value) {
|
|
|
8760
9285
|
}
|
|
8761
9286
|
|
|
8762
9287
|
function subjectEntry(definition) {
|
|
8763
|
-
return (definition
|
|
9288
|
+
return documentSubjectEntry(definition);
|
|
8764
9289
|
}
|
|
8765
9290
|
|
|
8766
9291
|
function autoStartInputs(args) {
|
|
@@ -8787,11 +9312,11 @@ function pendingWorkflows(workflows, live) {
|
|
|
8787
9312
|
}
|
|
8788
9313
|
|
|
8789
9314
|
function extraRequiredInputs(definition) {
|
|
8790
|
-
const fields = definition.fields ?? [],
|
|
9315
|
+
const fields = definition.fields ?? [], subjectName = subjectEntry(definition)?.name, requiredNames = new Set(missingRequiredInputs({
|
|
8791
9316
|
entryDefs: fields,
|
|
8792
9317
|
initialFields: []
|
|
8793
9318
|
}).map(input => input.name));
|
|
8794
|
-
return fields.filter(entry => requiredNames.has(entry.name) &&
|
|
9319
|
+
return fields.filter(entry => requiredNames.has(entry.name) && entry.name !== subjectName);
|
|
8795
9320
|
}
|
|
8796
9321
|
|
|
8797
9322
|
function buildAutoStartRequests(args) {
|
|
@@ -8832,21 +9357,21 @@ function AutoStartGate(props) {
|
|
|
8832
9357
|
}
|
|
8833
9358
|
|
|
8834
9359
|
function AutoStartDriver(props) {
|
|
8835
|
-
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({
|
|
8836
9361
|
engine: engine
|
|
8837
9362
|
}), {selectedReleaseId: selectedReleaseId} = usePerspective(), {entries: entries} = useWorkflowsForDocument(rawDocId), docId = getPublishedId(rawDocId), valueRef = useRef(value);
|
|
8838
9363
|
valueRef.current = value;
|
|
8839
9364
|
const pending = useMemo(() => pendingWorkflows(workflows, new Set(entries.map(entry => entry.instance.definition))), [ workflows, entries ]), inputs = useMemo(() => autoStartInputs({
|
|
8840
9365
|
workflows: pending,
|
|
8841
9366
|
definitions: autoStartDefinitions
|
|
8842
|
-
}), [ pending, autoStartDefinitions ]), pendingRef = useRef(pending);
|
|
9367
|
+
}), [ pending, autoStartDefinitions ]), definitionsResolved = workflows.every(name => autoStartDefinitions.has(name)), pendingRef = useRef(pending);
|
|
8843
9368
|
pendingRef.current = pending;
|
|
8844
9369
|
const instanceIds = useRef(/* @__PURE__ */ new Map), instanceIdFor = useCallback(workflow => {
|
|
8845
9370
|
const held = instanceIds.current.get(workflow);
|
|
8846
9371
|
if (held !== void 0) return held;
|
|
8847
9372
|
const id = instanceDocId(binding.tag);
|
|
8848
9373
|
return instanceIds.current.set(workflow, id), id;
|
|
8849
|
-
}, [ 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) => {
|
|
8850
9375
|
if (!firedRef.current) {
|
|
8851
9376
|
firedRef.current = !0, setFired(!0);
|
|
8852
9377
|
try {
|
|
@@ -8858,20 +9383,25 @@ function AutoStartDriver(props) {
|
|
|
8858
9383
|
releaseId: selectedReleaseId
|
|
8859
9384
|
} : {}
|
|
8860
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
|
+
});
|
|
8861
9401
|
const {failure: failure2} = await runStarts({
|
|
8862
9402
|
engine: engine,
|
|
8863
9403
|
seed: seedInstance,
|
|
8864
|
-
requests:
|
|
8865
|
-
workflows: pendingRef.current,
|
|
8866
|
-
definitions: autoStartDefinitions,
|
|
8867
|
-
subject: {
|
|
8868
|
-
docId: docId,
|
|
8869
|
-
type: docType
|
|
8870
|
-
},
|
|
8871
|
-
contentResource: binding.contentResource,
|
|
8872
|
-
values: values,
|
|
8873
|
-
instanceIdFor: instanceIdFor
|
|
8874
|
-
})
|
|
9404
|
+
requests: requests
|
|
8875
9405
|
});
|
|
8876
9406
|
failure2 !== void 0 && setFailure(failure2);
|
|
8877
9407
|
} catch (err) {
|
|
@@ -8880,17 +9410,17 @@ function AutoStartDriver(props) {
|
|
|
8880
9410
|
setSettled(!0);
|
|
8881
9411
|
}
|
|
8882
9412
|
}
|
|
8883
|
-
}, [ autoStartDefinitions, docId, docType, binding, engine, observer, seedInstance, instanceIdFor, selectedReleaseId ]), retry = useCallback(() => {
|
|
9413
|
+
}, [ autoStartDefinitions, docId, docType, binding, engine, observer, seedInstance, instanceIdFor, selectedReleaseId, telemetry ]), retry = useCallback(() => {
|
|
8884
9414
|
firedRef.current = !1, setFired(!1), setSettled(!1), setFailure(void 0);
|
|
8885
9415
|
}, []), action = autoStartAction({
|
|
8886
|
-
resolved: isDocResolved(docId),
|
|
9416
|
+
resolved: definitionsResolved && isDocResolved(docId),
|
|
8887
9417
|
pendingCount: pending.length,
|
|
8888
9418
|
needsInput: inputs.length > 0,
|
|
8889
9419
|
fired: fired,
|
|
8890
9420
|
settled: settled
|
|
8891
9421
|
});
|
|
8892
9422
|
return useEffect(() => {
|
|
8893
|
-
action === "silent-start" && startAll({});
|
|
9423
|
+
action === "silent-start" && startAll({}, "silent");
|
|
8894
9424
|
}, [ action, startAll ]), failure !== void 0 ? /* @__PURE__ */ jsx(AutoStartFailure, {
|
|
8895
9425
|
message: failure,
|
|
8896
9426
|
onProceed: () => setFailure(void 0),
|
|
@@ -8902,7 +9432,7 @@ function AutoStartDriver(props) {
|
|
|
8902
9432
|
docType: docType,
|
|
8903
9433
|
inputs: inputs,
|
|
8904
9434
|
onStart: values => {
|
|
8905
|
-
startAll(values);
|
|
9435
|
+
startAll(values, "collect");
|
|
8906
9436
|
},
|
|
8907
9437
|
starting: fired,
|
|
8908
9438
|
workflowCount: pending.length
|
|
@@ -9124,7 +9654,9 @@ function finishedLinesOf(entries) {
|
|
|
9124
9654
|
}
|
|
9125
9655
|
|
|
9126
9656
|
function WorkflowFormStrip(props) {
|
|
9127
|
-
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);
|
|
9128
9660
|
/* @__PURE__ */
|
|
9129
9661
|
return jsxs(Stack, {
|
|
9130
9662
|
gap: 4,
|
|
@@ -9158,7 +9690,8 @@ function StripLines({active: active, docId: docId, finished: finished, initialVa
|
|
|
9158
9690
|
initialValue: initialValue,
|
|
9159
9691
|
label: "Start workflow",
|
|
9160
9692
|
mappings: mappings,
|
|
9161
|
-
mode: "bleed"
|
|
9693
|
+
mode: "bleed",
|
|
9694
|
+
source: "form-strip"
|
|
9162
9695
|
})
|
|
9163
9696
|
}) : null ]
|
|
9164
9697
|
});
|
|
@@ -9305,6 +9838,61 @@ function TaskCountSpinner({entry: entry}) {
|
|
|
9305
9838
|
});
|
|
9306
9839
|
}
|
|
9307
9840
|
|
|
9841
|
+
function stagePillState(instance) {
|
|
9842
|
+
const definition = definitionSnapshotOf(instance), stage = definition?.stages.find(candidate => candidate.name === instance.currentStage), state = terminalState(instance);
|
|
9843
|
+
return {
|
|
9844
|
+
title: stageTitle(definition, instance.currentStage),
|
|
9845
|
+
terminal: stage !== void 0 && isTerminalStage(stage) || state !== "in-flight",
|
|
9846
|
+
state: state,
|
|
9847
|
+
stageKnown: stage !== void 0
|
|
9848
|
+
};
|
|
9849
|
+
}
|
|
9850
|
+
|
|
9851
|
+
function WorkflowStagePreview(props) {
|
|
9852
|
+
const {mappings: mappings} = useWorkflowContext(), mapped = props.schemaType !== void 0 && mappingsForDocType(mappings, props.schemaType.name).length > 0, {entries: entries} = useCommittedWorkflowsForDocument(mapped ? props._id ?? null : null), lead = entries.find(isLiveEntry) ?? entries[0], extraLive = entries.filter(e => e !== lead && isLiveEntry(e)).length;
|
|
9853
|
+
return props.renderDefault({
|
|
9854
|
+
...props,
|
|
9855
|
+
status: lead ? /* @__PURE__ */ jsx(StagePill, {
|
|
9856
|
+
entry: lead,
|
|
9857
|
+
extraLive: extraLive
|
|
9858
|
+
}) : props.status
|
|
9859
|
+
});
|
|
9860
|
+
}
|
|
9861
|
+
|
|
9862
|
+
function StagePill({entry: entry, extraLive: extraLive}) {
|
|
9863
|
+
/* @__PURE__ */
|
|
9864
|
+
return jsxs(Flex, {
|
|
9865
|
+
align: "center",
|
|
9866
|
+
gap: 2,
|
|
9867
|
+
children: [
|
|
9868
|
+
/* @__PURE__ */ jsx(LeadBadge, {
|
|
9869
|
+
entry: entry
|
|
9870
|
+
}), extraLive > 0 ? /* @__PURE__ */ jsxs(Badge, {
|
|
9871
|
+
fontSize: 1,
|
|
9872
|
+
mode: "outline",
|
|
9873
|
+
tone: "default",
|
|
9874
|
+
children: [ "+", extraLive ]
|
|
9875
|
+
}) : null ]
|
|
9876
|
+
});
|
|
9877
|
+
}
|
|
9878
|
+
|
|
9879
|
+
function LeadBadge({entry: entry}) {
|
|
9880
|
+
const {instance: instance} = entry;
|
|
9881
|
+
if (isUnprimed(instance)) /* @__PURE__ */ return jsx(StartIncompleteBadge, {});
|
|
9882
|
+
const pill = stagePillState(instance);
|
|
9883
|
+
/* @__PURE__ */
|
|
9884
|
+
return jsxs(Badge, {
|
|
9885
|
+
fontSize: 1,
|
|
9886
|
+
mode: pill.terminal ? "default" : "outline",
|
|
9887
|
+
tone: pillTone(pill),
|
|
9888
|
+
children: [ pill.title, pill.state === "completed" ? " ✓" : "" ]
|
|
9889
|
+
});
|
|
9890
|
+
}
|
|
9891
|
+
|
|
9892
|
+
function pillTone(args) {
|
|
9893
|
+
return args.state === "aborted" ? "critical" : args.terminal ? "positive" : args.stageKnown ? "primary" : "default";
|
|
9894
|
+
}
|
|
9895
|
+
|
|
9308
9896
|
function StartWorkflowDialogHost() {
|
|
9309
9897
|
const {startRequest: startRequest2, closeStartDialog: closeStartDialog} = useWorkflowContext();
|
|
9310
9898
|
return startRequest2 ? /* @__PURE__ */ jsx(StartWorkflowDialog, {
|
|
@@ -9377,7 +9965,8 @@ function withWorkflowLock(Action, guardAction) {
|
|
|
9377
9965
|
Locked;
|
|
9378
9966
|
}
|
|
9379
9967
|
|
|
9380
|
-
const workflowStudioPlugin = definePlugin(config => (
|
|
9968
|
+
const workflowStudioPlugin = definePlugin(config => (assertUniqueWorkflowMappings(config.mappings ?? []),
|
|
9969
|
+
{
|
|
9381
9970
|
name: "workflow-studio-plugin",
|
|
9382
9971
|
tools: prev => [ ...prev, workflowsTool ],
|
|
9383
9972
|
studio: {
|
|
@@ -9391,82 +9980,35 @@ const workflowStudioPlugin = definePlugin(config => ({
|
|
|
9391
9980
|
},
|
|
9392
9981
|
form: {
|
|
9393
9982
|
components: {
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
mappings: docTypeMappings
|
|
9399
|
-
}) : props.renderDefault(props);
|
|
9400
|
-
/* @__PURE__ */
|
|
9401
|
-
return jsx(AutoStartGate, {
|
|
9402
|
-
...props,
|
|
9403
|
-
fallback: fallback
|
|
9404
|
-
});
|
|
9405
|
-
}
|
|
9406
|
-
return props.renderDefault(props);
|
|
9407
|
-
}
|
|
9983
|
+
preview: WorkflowStagePreview,
|
|
9984
|
+
input: props => props.id === "root" && isObjectInputProps(props) ? /* @__PURE__ */ jsx(WorkflowRootInput, {
|
|
9985
|
+
...props
|
|
9986
|
+
}) : props.renderDefault(props)
|
|
9408
9987
|
}
|
|
9409
9988
|
},
|
|
9410
9989
|
document: {
|
|
9411
9990
|
badges: (prev, ctx) => {
|
|
9412
|
-
if (!
|
|
9991
|
+
if (!ctx.documentId) return prev;
|
|
9413
9992
|
const docId = ctx.documentId;
|
|
9414
9993
|
return [ makeActiveWorkflowsBadge(docId), makePerspectiveBadge(docId), ...prev ];
|
|
9415
9994
|
},
|
|
9416
|
-
actions:
|
|
9995
|
+
actions: prev => prev.map(Action => {
|
|
9417
9996
|
const guardAction = Action.action ? LOCKABLE_ACTIONS.get(Action.action) : void 0;
|
|
9418
9997
|
return guardAction ? withWorkflowLock(Action, guardAction) : Action;
|
|
9419
|
-
})
|
|
9998
|
+
})
|
|
9420
9999
|
}
|
|
9421
10000
|
}));
|
|
9422
10001
|
|
|
9423
|
-
function
|
|
9424
|
-
const {
|
|
9425
|
-
return props.renderDefault({
|
|
10002
|
+
function WorkflowRootInput(props) {
|
|
10003
|
+
const {mappings: mappings} = useWorkflowContext(), docTypeMappings = mappingsForDocType(mappings, props.schemaType.name), fallback = docTypeMappings.length > 0 ? /* @__PURE__ */ jsx(WorkflowFormStrip, {
|
|
9426
10004
|
...props,
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
extraLive: extraLive
|
|
9430
|
-
}) : props.status
|
|
9431
|
-
});
|
|
9432
|
-
}
|
|
9433
|
-
|
|
9434
|
-
function StagePill({entry: entry, extraLive: extraLive}) {
|
|
10005
|
+
mappings: docTypeMappings
|
|
10006
|
+
}) : props.renderDefault(props);
|
|
9435
10007
|
/* @__PURE__ */
|
|
9436
|
-
return
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
children: [
|
|
9440
|
-
/* @__PURE__ */ jsx(LeadBadge, {
|
|
9441
|
-
entry: entry
|
|
9442
|
-
}), extraLive > 0 ? /* @__PURE__ */ jsxs(Badge, {
|
|
9443
|
-
fontSize: 1,
|
|
9444
|
-
mode: "outline",
|
|
9445
|
-
tone: "default",
|
|
9446
|
-
children: [ "+", extraLive ]
|
|
9447
|
-
}) : null ]
|
|
9448
|
-
});
|
|
9449
|
-
}
|
|
9450
|
-
|
|
9451
|
-
function LeadBadge({entry: entry}) {
|
|
9452
|
-
const {instance: instance, evaluation: evaluation} = entry;
|
|
9453
|
-
if (isUnprimed(instance)) /* @__PURE__ */ return jsx(StartIncompleteBadge, {});
|
|
9454
|
-
const stage = evaluation?.currentStage?.stage, title = stage?.title ?? stageTitle(definitionSnapshotOf(instance), instance.currentStage), state = terminalState(instance), isTerminal = (stage ? isTerminalStage(stage) : !1) || state !== "in-flight";
|
|
9455
|
-
/* @__PURE__ */
|
|
9456
|
-
return jsxs(Badge, {
|
|
9457
|
-
fontSize: 1,
|
|
9458
|
-
mode: isTerminal ? "default" : "outline",
|
|
9459
|
-
tone: pillTone({
|
|
9460
|
-
state: state,
|
|
9461
|
-
isTerminal: isTerminal,
|
|
9462
|
-
stageKnown: stage !== void 0
|
|
9463
|
-
}),
|
|
9464
|
-
children: [ title, state === "completed" ? " ✓" : "" ]
|
|
10008
|
+
return jsx(AutoStartGate, {
|
|
10009
|
+
...props,
|
|
10010
|
+
fallback: fallback
|
|
9465
10011
|
});
|
|
9466
10012
|
}
|
|
9467
10013
|
|
|
9468
|
-
|
|
9469
|
-
return args.state === "aborted" ? "critical" : args.isTerminal ? "positive" : args.stageKnown ? "primary" : "default";
|
|
9470
|
-
}
|
|
9471
|
-
|
|
9472
|
-
export { AbortedBadge, ActivitiesList, ActivityDetailDialog, ActivityRow, BreadcrumbTail, CollapsibleBand, DismissablePopover, DocPreviewLink, DocRefFace, GroupHeading, HoverHint, InvalidDocNotice, LinkChip, LoadingRow, StageChip, StageFace, StaleLock, TabSwitch, TodoItemsList, TrailingHairline, UnreadableDocsNote, WorkflowStagePreview, activityRowProps, assigneeUserIdsOf, committedRowFace, dateControlKind, dateControlValue, definitionSnapshotOf, describeError, editTargetOf, findActivity, findActivityNode, formatDate, gdrLocality, instanceBreadcrumb, instanceNotice, instanceTitle, isActivityAssignedTo, isEvaluationStale, isOpenActivityStatus, mappingForDocType, openActivityGone, parseDateFieldValue, parseStoredDateValue, readDeployedDefinitions, rowAssignControlState, rowDateControlState, serializeDateFieldValue, stageTitle, stateByActivity, stopRowClick, stopRowMouseDown, useAssignmentIdentity, useDefinition, useProjectMembers, useSaveField, useUserDisplays, useWorkflowContext, useWorkflowInstanceEntry, workflowDefaultDocumentNode, workflowDocTypes, workflowStudioPlugin, workflowsTabCodec, workflowsView };
|
|
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 };
|