@sanity/workflow-studio-plugin 0.28.0 → 0.30.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 +374 -0
- package/README.md +13 -13
- package/dist/_chunks-cjs/index.cjs +822 -419
- package/dist/_chunks-cjs/workflows-tool-root.cjs +4443 -3172
- package/dist/_chunks-es/index.js +802 -377
- package/dist/_chunks-es/workflows-tool-root.js +4578 -3297
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/package.json +13 -12
package/dist/_chunks-es/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
|
2
2
|
|
|
3
3
|
import { TimelineIcon } from "@sanity/icons/Timeline";
|
|
4
4
|
|
|
5
|
-
import { Popover, Tooltip, Box, Stack, Text, useClickOutsideEvent, Flex, TextInput, Button, Select, Checkbox, Autocomplete, Card, TextArea, useToast, Dialog, Switch, TextSkeleton, Code, useTheme_v2, Spinner,
|
|
5
|
+
import { Popover, Tooltip, Box, Stack, Text, useClickOutsideEvent, Flex, TextInput, Button, Select, Checkbox, Autocomplete, Card, TextArea, useToast, Dialog, Switch, TextSkeleton, Code, Badge, useTheme_v2, Spinner, MenuButton, Menu, MenuItem, useElementSize, MenuDivider, TabList, Tab, TabPanel } from "@sanity/ui";
|
|
6
6
|
|
|
7
7
|
import { editFieldTarget, useWorkflowTelemetry, useRefcountedIds } from "@sanity/workflow-react";
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@ import { createContext, useContext, useEffect, useSyncExternalStore, useCallback
|
|
|
10
10
|
|
|
11
11
|
import { usePaneRouter } from "sanity/structure";
|
|
12
12
|
|
|
13
|
-
import { WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE, tryParseGdr, resourceFromParsed, latestDeployedDefinitions, isStartableDefinition, isSubjectEntry, isInputSourced, acceptsDocumentType, initialFieldIssues, gdrRef, releaseRef, refKindAcceptsTypes, rejectedRefTypes, ActionDisabledError, MutationGuardDeniedError, EditFieldDeniedError, errorMessage, terminalState, findOpenStageEntry, actionRendering, isTodoListEntry, isTodoListItem, isTerminalActivityStatus, describeCondition, sentenceCase, checklistLines, findCurrentActivityEntry, ENGINE_API_VERSION, scalarValidationIssues, classifyPrincipalId, userLoginProvider, toBareId, isSingleDocRefEntry, isGdr, resolveFieldEntry, isSingleDocRefKind, isNotesEntry, parseDefinitionSnapshot, isUnprimed, isTerminalStage, DEFAULT_TRANSITION_WHEN, instancesQuery, assertReadableModel, projectStartSliceRow, StartNotSettledError, StartNotAllowedError, isRevisionConflict, humanize, unboundRequirementReads, explainStartRequirement, singleSubjectRequirementRefused, evaluateStartFilter, startKindOf, hasSingleSubjectRequirement, readsRootDocument, latestDefinitionsGroq, gdrFromResource, subscriptionDocumentsForInstance, aclPathForResource, definitionLookupGroq, instanceDocId, missingRequiredInputs, documentActionDenials } from "@sanity/workflow-engine";
|
|
13
|
+
import { WORKFLOW_INSTANCE_TYPE, WORKFLOW_DEFINITION_TYPE, GUARD_DOC_TYPE, tryParseGdr, resourceFromParsed, latestDeployedDefinitions, isStartableDefinition, isSubjectEntry, isInputSourced, acceptsDocumentType, initialFieldIssues, gdrRef, releaseRef, refKindAcceptsTypes, rejectedRefTypes, ActionDisabledError, MutationGuardDeniedError, EditFieldDeniedError, errorMessage, terminalState, findOpenStageEntry, actionRendering, isTodoListEntry, isTodoListItem, isTerminalActivityStatus, describeCondition, sentenceCase, checklistLines, findCurrentActivityEntry, ENGINE_API_VERSION, scalarValidationIssues, classifyPrincipalId, userLoginProvider, toBareId, findStageNode, findActivityNode, isSingleDocRefEntry, isGdr, resolveFieldEntry, isSingleDocRefKind, isNotesEntry, remediationsFor, diagnoseInstance, diagnoseInputFromEvaluation, documentStuckCause, parseDefinitionSnapshot, isUnprimed, isTerminalStage, DEFAULT_TRANSITION_WHEN, instancesQuery, assertReadableModel, projectStartSliceRow, StartNotSettledError, StartNotAllowedError, isRevisionConflict, humanize, unboundRequirementReads, explainStartRequirement, singleSubjectRequirementRefused, evaluateStartFilter, startKindOf, hasSingleSubjectRequirement, readsRootDocument, latestDefinitionsGroq, gdrFromResource, subscriptionDocumentsForInstance, aclPathForResource, definitionLookupGroq, instanceDocId, missingRequiredInputs, documentActionDenials } from "@sanity/workflow-engine";
|
|
14
14
|
|
|
15
15
|
import { CheckmarkIcon } from "@sanity/icons/Checkmark";
|
|
16
16
|
|
|
@@ -18,7 +18,7 @@ import { CloseIcon } from "@sanity/icons/Close";
|
|
|
18
18
|
|
|
19
19
|
import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
|
|
20
20
|
|
|
21
|
-
import { sameAssignee, projectMemberRow, ClearableDatePicker, AssigneePicker as AssigneePicker$1, MemberPicker as MemberPicker$1, MemberAvatar, AssigneeBadges as AssigneeBadges$1, AssigneeBadge as AssigneeBadge$1, ProgressBar, memberRoleFor, AssigneeStack, roleLabel, clampProgress, MemberAvatarGroup, progressCaption, DatePicker, roleLabelFor, roleListLabel } from "@sanity/workflow-components";
|
|
21
|
+
import { sameAssignee, projectMemberRow, providerTitle, ClearableDatePicker, AssigneePicker as AssigneePicker$1, MemberPicker as MemberPicker$1, MemberAvatar, AssigneeBadges as AssigneeBadges$1, AssigneeBadge as AssigneeBadge$1, ProgressBar, memberRoleFor, AssigneeStack, roleLabel, clampProgress, MemberAvatarGroup, progressCaption, DatePicker, roleLabelFor, roleListLabel } from "@sanity/workflow-components";
|
|
22
22
|
|
|
23
23
|
import { getPublishedId, getDraftId } from "@sanity/client/csm";
|
|
24
24
|
|
|
@@ -26,7 +26,7 @@ import { defineEvent } from "@sanity/telemetry";
|
|
|
26
26
|
|
|
27
27
|
import { useStudioProjectUsers, useStudioObserver, useWorkflowEngine, useWorkflowInstances, useWorkflowSession } from "@sanity/workflow-studio";
|
|
28
28
|
|
|
29
|
-
import { useCurrentUser, Preview,
|
|
29
|
+
import { useCurrentUser, Preview, useValuePreview, SanityDefaultPreview, useClient, useSchema, useWorkspace, TextWithTone, usePerspective, useIsReleaseActive, useDocumentPreviewStore, useActiveReleases, useTemplates, useInitialValueResolverContext, resolveInitialValue, definePlugin, isObjectInputProps } from "sanity";
|
|
30
30
|
|
|
31
31
|
import { CalendarIcon } from "@sanity/icons/Calendar";
|
|
32
32
|
|
|
@@ -52,6 +52,8 @@ import { isDocumentSchemaType } from "@sanity/types";
|
|
|
52
52
|
|
|
53
53
|
import { LaunchIcon } from "@sanity/icons/Launch";
|
|
54
54
|
|
|
55
|
+
import { ErrorOutlineIcon } from "@sanity/icons/ErrorOutline";
|
|
56
|
+
|
|
55
57
|
import { EmptyIcon } from "@sanity/icons/Empty";
|
|
56
58
|
|
|
57
59
|
import { ErrorFilledIcon } from "@sanity/icons/ErrorFilled";
|
|
@@ -78,8 +80,6 @@ import { CogIcon } from "@sanity/icons/Cog";
|
|
|
78
80
|
|
|
79
81
|
import { ArrowUpIcon } from "@sanity/icons/ArrowUp";
|
|
80
82
|
|
|
81
|
-
import { ErrorOutlineIcon } from "@sanity/icons/ErrorOutline";
|
|
82
|
-
|
|
83
83
|
import { of } from "rxjs";
|
|
84
84
|
|
|
85
85
|
import { switchMap, distinctUntilChanged } from "rxjs/operators";
|
|
@@ -367,7 +367,7 @@ function landingDefaultOpen(landing, instanceId) {
|
|
|
367
367
|
if (!(landing === void 0 || !landing.instanceIds.includes(instanceId))) return instanceId === landing.focusedId;
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
-
const WORKFLOWS_TOOL_NAME = "workflows", WORKFLOW_INTENT = "workflow";
|
|
370
|
+
const WORKFLOWS_TOOL_NAME = "workflows", WORKFLOW_INTENT = "workflow", RUN_SEARCH_PARAM = "run";
|
|
371
371
|
|
|
372
372
|
function pathSegmentName(args) {
|
|
373
373
|
return args.names.find(name => name === args.segment);
|
|
@@ -379,9 +379,10 @@ function handlesWorkflowIntent(intent, params) {
|
|
|
379
379
|
|
|
380
380
|
function workflowIntentState(intent, params) {
|
|
381
381
|
const instanceId = params.instanceId;
|
|
382
|
-
return intent
|
|
383
|
-
|
|
384
|
-
|
|
382
|
+
return intent !== WORKFLOW_INTENT || typeof instanceId != "string" ? null : {
|
|
383
|
+
workflowsTab: "overview",
|
|
384
|
+
_searchParams: [ [ RUN_SEARCH_PARAM, instanceId ] ]
|
|
385
|
+
};
|
|
385
386
|
}
|
|
386
387
|
|
|
387
388
|
const pad2 = n => String(n).padStart(2, "0"), DUE_DATE_FIELD_KINDS = [ "dueDate", "dueDatetime" ], DATE_FIELD_KINDS = [ "date", "datetime", ...DUE_DATE_FIELD_KINDS ], DATE_FIELD_KIND_SET = new Set(DATE_FIELD_KINDS), DUE_DATE_FIELD_KIND_SET = new Set(DUE_DATE_FIELD_KINDS);
|
|
@@ -409,16 +410,25 @@ function parseLocalDate(value) {
|
|
|
409
410
|
return parsed2.getFullYear() === year && parsed2.getMonth() === (month ?? NaN) - 1 && parsed2.getDate() === day ? parsed2 : /* @__PURE__ */ new Date(NaN);
|
|
410
411
|
}
|
|
411
412
|
|
|
413
|
+
function storedDateKind(value) {
|
|
414
|
+
return /^\d{4}-\d{2}-\d{2}$/.test(value) ? "date" : "datetime";
|
|
415
|
+
}
|
|
416
|
+
|
|
412
417
|
function parseStoredDateValue(value) {
|
|
413
|
-
if (typeof value
|
|
414
|
-
const kind = /^\d{4}-\d{2}-\d{2}$/.test(value) ? "date" : "datetime";
|
|
415
|
-
return parseDateFieldValue(value, kind);
|
|
418
|
+
if (typeof value == "string") return parseDateFieldValue(value, storedDateKind(value));
|
|
416
419
|
}
|
|
417
420
|
|
|
418
421
|
function serializeDateFieldValue(date, kind) {
|
|
419
422
|
return hasTimeOfDay(kind) ? date.toISOString() : `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
|
|
420
423
|
}
|
|
421
424
|
|
|
425
|
+
function isDueDatePast(value, now) {
|
|
426
|
+
const kind = storedDateKind(value);
|
|
427
|
+
if (!hasTimeOfDay(kind)) return value < serializeDateFieldValue(now, kind);
|
|
428
|
+
const due = parseDateFieldValue(value, kind);
|
|
429
|
+
return due !== void 0 && due.getTime() < now.getTime();
|
|
430
|
+
}
|
|
431
|
+
|
|
422
432
|
class EffectsIncompleteError extends Error {
|
|
423
433
|
reason;
|
|
424
434
|
constructor(reason, options) {
|
|
@@ -469,14 +479,19 @@ function formatTimeAgo(value) {
|
|
|
469
479
|
}
|
|
470
480
|
|
|
471
481
|
function formatShortAgo(value, now) {
|
|
482
|
+
const span = formatShortSpan(value, now);
|
|
483
|
+
return span === "—" ? "—" : span === "now" ? "just now" : `${span} ago`;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function formatShortSpan(value, now) {
|
|
472
487
|
const d = new Date(value);
|
|
473
488
|
if (Number.isNaN(d.getTime())) return "—";
|
|
474
489
|
const seconds = Math.floor((now.getTime() - d.getTime()) / 1e3);
|
|
475
|
-
if (seconds < 60) return "
|
|
490
|
+
if (seconds < 60) return "now";
|
|
476
491
|
const minutes = Math.floor(seconds / 60);
|
|
477
|
-
if (minutes < 60) return `${minutes}m
|
|
492
|
+
if (minutes < 60) return `${minutes}m`;
|
|
478
493
|
const hours = Math.floor(minutes / 60);
|
|
479
|
-
return hours < 24 ? `${hours}h
|
|
494
|
+
return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;
|
|
480
495
|
}
|
|
481
496
|
|
|
482
497
|
function stampFace(verb, at) {
|
|
@@ -599,7 +614,7 @@ function isLiveEntry(entry) {
|
|
|
599
614
|
const isTodoDone = item => item.status === "done", toggledTodoStatus = item => isTodoDone(item) ? "open" : "done";
|
|
600
615
|
|
|
601
616
|
function isTodoOverdue(item, today = /* @__PURE__ */ new Date) {
|
|
602
|
-
return !item.dueDate || isTodoDone(item) ? !1 : item.dueDate
|
|
617
|
+
return !item.dueDate || isTodoDone(item) ? !1 : isDueDatePast(item.dueDate, today);
|
|
603
618
|
}
|
|
604
619
|
|
|
605
620
|
function todoEditKind(patch) {
|
|
@@ -700,7 +715,7 @@ function todoFieldEditability(args) {
|
|
|
700
715
|
}
|
|
701
716
|
|
|
702
717
|
function itemRow(args) {
|
|
703
|
-
const {item: item, items: items, field: field, source: source, ticks: ticks, editability: editability} = args, tick = ticks.get(tickKey(field.name, item._key));
|
|
718
|
+
const {item: item, items: items, field: field, source: source, ticks: ticks, editability: editability} = args, tick = ticks.get(tickKey(field.name, item._key)), eligibleAssigneeRoles = field.of.find(column => column.name === "assignee" && column.type === "assignee")?.roles;
|
|
704
719
|
return {
|
|
705
720
|
item: item,
|
|
706
721
|
items: items,
|
|
@@ -715,6 +730,9 @@ function itemRow(args) {
|
|
|
715
730
|
...editability.editDisabledReason ? {
|
|
716
731
|
editDisabledReason: editability.editDisabledReason
|
|
717
732
|
} : {},
|
|
733
|
+
...eligibleAssigneeRoles === void 0 ? {} : {
|
|
734
|
+
eligibleAssigneeRoles: eligibleAssigneeRoles
|
|
735
|
+
},
|
|
718
736
|
...tick ? {
|
|
719
737
|
tick: tick
|
|
720
738
|
} : {}
|
|
@@ -920,7 +938,7 @@ function concludesHere(actionEval, activityName) {
|
|
|
920
938
|
return changesOwnStatus(actionEval.action, activityName) || actionEval.firing?.exitsStage === !0;
|
|
921
939
|
}
|
|
922
940
|
|
|
923
|
-
const
|
|
941
|
+
const DECISION_SEMANTIC_FACE = {
|
|
924
942
|
"decision.accept": {
|
|
925
943
|
tone: "positive",
|
|
926
944
|
icon: CheckmarkIcon
|
|
@@ -931,6 +949,15 @@ const SEMANTIC_FACE = {
|
|
|
931
949
|
}
|
|
932
950
|
};
|
|
933
951
|
|
|
952
|
+
function isDecisionSemantic(value) {
|
|
953
|
+
return Object.hasOwn(DECISION_SEMANTIC_FACE, value);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
function decisionSemanticFace(semantics) {
|
|
957
|
+
const semantic = semantics.find(isDecisionSemantic);
|
|
958
|
+
return semantic === void 0 ? void 0 : DECISION_SEMANTIC_FACE[semantic];
|
|
959
|
+
}
|
|
960
|
+
|
|
934
961
|
function actionButtonFace(args) {
|
|
935
962
|
const mode = concludesHere(args.actionEval, args.activityName) ? "default" : "ghost";
|
|
936
963
|
if (actionAdvanceStatus(args.actionEval.action, args.activityName) === "failed") return {
|
|
@@ -938,7 +965,7 @@ function actionButtonFace(args) {
|
|
|
938
965
|
tone: "critical",
|
|
939
966
|
icon: void 0
|
|
940
967
|
};
|
|
941
|
-
const
|
|
968
|
+
const face = decisionSemanticFace(args.actionEval.semantics ?? []);
|
|
942
969
|
return {
|
|
943
970
|
mode: mode,
|
|
944
971
|
tone: face?.tone ?? "default",
|
|
@@ -1105,24 +1132,10 @@ function dateValuesOf(state, matches) {
|
|
|
1105
1132
|
return state.filter(entry => matches(entry._type)).map(entry => entry.value).filter(value => typeof value == "string" && value !== "");
|
|
1106
1133
|
}
|
|
1107
1134
|
|
|
1108
|
-
function datesOf(state) {
|
|
1109
|
-
return dateValuesOf(state, isDateFieldKind);
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
1135
|
function dueDatesOf(state) {
|
|
1113
1136
|
return dateValuesOf(state, isDueDateFieldKind);
|
|
1114
1137
|
}
|
|
1115
1138
|
|
|
1116
|
-
function committedRowFace(row) {
|
|
1117
|
-
return {
|
|
1118
|
-
activityName: row.activityName,
|
|
1119
|
-
title: row.title,
|
|
1120
|
-
status: row.status,
|
|
1121
|
-
automated: !1,
|
|
1122
|
-
blocked: !1
|
|
1123
|
-
};
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
1139
|
function activityRowProps(args) {
|
|
1127
1140
|
const {activityEval: activityEval, activityState: activityState, editableFields: editableFields} = args, state = activityState.get(activityEval.activity.name) ?? [], controlArgs = {
|
|
1128
1141
|
activity: activityEval.activity,
|
|
@@ -1221,15 +1234,15 @@ function useWorkflowInstanceEntry(instanceId, options = {}) {
|
|
|
1221
1234
|
}
|
|
1222
1235
|
|
|
1223
1236
|
const WorkflowToolOpened = defineEvent({
|
|
1224
|
-
name: "
|
|
1225
|
-
version:
|
|
1237
|
+
name: "Workflows Studio Plugin Tool Opened",
|
|
1238
|
+
version: 3,
|
|
1226
1239
|
description: "The Workflows tool was opened or its tab was switched"
|
|
1227
1240
|
}), WorkflowDocumentViewOpened = defineEvent({
|
|
1228
|
-
name: "
|
|
1241
|
+
name: "Workflows Studio Plugin Document View Opened",
|
|
1229
1242
|
version: 1,
|
|
1230
1243
|
description: "The Workflows document view was opened or its tab was switched"
|
|
1231
1244
|
}), WorkflowInstanceDetailViewed = defineEvent({
|
|
1232
|
-
name: "
|
|
1245
|
+
name: "Workflows Studio Plugin Instance Detail Viewed",
|
|
1233
1246
|
version: 1,
|
|
1234
1247
|
description: "The Workflows tool's per-instance detail view was opened"
|
|
1235
1248
|
});
|
|
@@ -1242,67 +1255,63 @@ function definitionFingerprint(definition) {
|
|
|
1242
1255
|
}
|
|
1243
1256
|
|
|
1244
1257
|
const WorkflowDefinitionDetailViewed = defineEvent({
|
|
1245
|
-
name: "
|
|
1258
|
+
name: "Workflows Studio Plugin Definition Detail Viewed",
|
|
1246
1259
|
version: 1,
|
|
1247
1260
|
description: "A workflow's definition page was opened in the Workflows tool"
|
|
1248
1261
|
}), WorkflowFormStripClicked = defineEvent({
|
|
1249
|
-
name: "
|
|
1262
|
+
name: "Workflows Studio Plugin Form Strip Clicked",
|
|
1250
1263
|
version: 1,
|
|
1251
1264
|
description: "The form strip's instance line was clicked, opening the document view"
|
|
1252
1265
|
}), WorkflowDocumentLinkClicked = defineEvent({
|
|
1253
|
-
name: "
|
|
1254
|
-
version:
|
|
1266
|
+
name: "Workflows Studio Plugin Document Link Clicked",
|
|
1267
|
+
version: 3,
|
|
1255
1268
|
description: "A document link was clicked, opening the referenced document's editor"
|
|
1256
1269
|
}), WorkflowStartDialogOpened = defineEvent({
|
|
1257
|
-
name: "
|
|
1270
|
+
name: "Workflows Studio Plugin Start Dialog Opened",
|
|
1258
1271
|
version: 1,
|
|
1259
1272
|
description: "The start-workflow dialog was opened"
|
|
1260
1273
|
}), WorkflowStartDialogSubmitted = defineEvent({
|
|
1261
|
-
name: "
|
|
1274
|
+
name: "Workflows Studio Plugin Start Dialog Submitted",
|
|
1262
1275
|
version: 1,
|
|
1263
1276
|
description: "The start-workflow dialog's confirm was pressed"
|
|
1264
1277
|
}), WorkflowAutoStartRan = defineEvent({
|
|
1265
|
-
name: "
|
|
1278
|
+
name: "Workflows Studio Plugin Auto Start Ran",
|
|
1266
1279
|
version: 1,
|
|
1267
1280
|
description: "A fresh document's auto-start ran — one start request per configured workflow"
|
|
1268
1281
|
}), WorkflowActionControlUsed = defineEvent({
|
|
1269
|
-
name: "
|
|
1270
|
-
version:
|
|
1282
|
+
name: "Workflows Studio Plugin Action Control Used",
|
|
1283
|
+
version: 3,
|
|
1271
1284
|
description: "An action-firing control was used, attributed to its UI surface"
|
|
1272
1285
|
}), WorkflowFieldControlUsed = defineEvent({
|
|
1273
|
-
name: "
|
|
1274
|
-
version:
|
|
1286
|
+
name: "Workflows Studio Plugin Field Control Used",
|
|
1287
|
+
version: 2,
|
|
1275
1288
|
description: "A field-editing control committed an edit, attributed to its UI surface"
|
|
1276
1289
|
}), WorkflowActivityDialogOpened = defineEvent({
|
|
1277
|
-
name: "
|
|
1278
|
-
version:
|
|
1290
|
+
name: "Workflows Studio Plugin Activity Dialog Opened",
|
|
1291
|
+
version: 2,
|
|
1279
1292
|
description: "The activity detail dialog was opened"
|
|
1280
|
-
}), WorkflowTaskFiltersApplied = defineEvent({
|
|
1281
|
-
name: "Editorial Workflows Studio Plugin Task Filters Applied",
|
|
1282
|
-
version: 1,
|
|
1283
|
-
description: "The tool's task-filter menu closed with a changed selection"
|
|
1284
1293
|
}), WorkflowBoardWorkflowSelected = defineEvent({
|
|
1285
|
-
name: "
|
|
1286
|
-
version:
|
|
1287
|
-
description: "The
|
|
1294
|
+
name: "Workflows Studio Plugin Board Workflow Selected",
|
|
1295
|
+
version: 3,
|
|
1296
|
+
description: "The Overview's board display settled on the workflow it's showing"
|
|
1288
1297
|
}), WorkflowTitleSeedDrifted = defineEvent({
|
|
1289
|
-
name: "
|
|
1298
|
+
name: "Workflows Studio Plugin Title Seed Drifted",
|
|
1290
1299
|
version: 1,
|
|
1291
1300
|
description: "A cold-start seeded preview title diverged from the live preview pipeline"
|
|
1292
1301
|
}), WorkflowTodoToggled = defineEvent({
|
|
1293
|
-
name: "
|
|
1302
|
+
name: "Workflows Studio Plugin Todo Toggled",
|
|
1294
1303
|
version: 1,
|
|
1295
1304
|
description: "A todo checkbox was toggled, attributed to its UI surface and write seam"
|
|
1296
1305
|
}), WorkflowTodoEdited = defineEvent({
|
|
1297
|
-
name: "
|
|
1306
|
+
name: "Workflows Studio Plugin Todo Edited",
|
|
1298
1307
|
version: 1,
|
|
1299
1308
|
description: "A non-toggle todo-list write, attributed to its UI surface and gesture"
|
|
1300
1309
|
}), WorkflowAbortDialogOpened = defineEvent({
|
|
1301
|
-
name: "
|
|
1310
|
+
name: "Workflows Studio Plugin Abort Dialog Opened",
|
|
1302
1311
|
version: 1,
|
|
1303
1312
|
description: "The abort-workflow confirm was opened"
|
|
1304
1313
|
}), WorkflowAbortDialogSubmitted = defineEvent({
|
|
1305
|
-
name: "
|
|
1314
|
+
name: "Workflows Studio Plugin Abort Dialog Submitted",
|
|
1306
1315
|
version: 1,
|
|
1307
1316
|
description: "The abort-workflow confirm was submitted, carrying the attempt's outcome"
|
|
1308
1317
|
});
|
|
@@ -1338,6 +1347,12 @@ function scalarValidationIssue(args) {
|
|
|
1338
1347
|
return issues === void 0 ? void 0 : `${args.label}: ${issues.join("; ")}`;
|
|
1339
1348
|
}
|
|
1340
1349
|
|
|
1350
|
+
function countBy(rows, keysOf) {
|
|
1351
|
+
const counts = /* @__PURE__ */ new Map;
|
|
1352
|
+
for (const row of rows) for (const key of keysOf(row)) counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
1353
|
+
return counts;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1341
1356
|
function personActor(user) {
|
|
1342
1357
|
const roles = user.roles.map(role => typeof role == "string" ? role : role.name);
|
|
1343
1358
|
return {
|
|
@@ -1369,10 +1384,16 @@ function userDisplayFor(args) {
|
|
|
1369
1384
|
return {
|
|
1370
1385
|
id: args.id,
|
|
1371
1386
|
name: member?.displayName ?? self?.name ?? args.id,
|
|
1372
|
-
imageUrl: member?.imageUrl ?? self?.profileImage ?? void 0
|
|
1387
|
+
imageUrl: member?.imageUrl ?? self?.profileImage ?? void 0,
|
|
1388
|
+
loginProvider: member?.loginProvider
|
|
1373
1389
|
};
|
|
1374
1390
|
}
|
|
1375
1391
|
|
|
1392
|
+
function disambiguatedNames(displays) {
|
|
1393
|
+
const counts = countBy(displays, display => [ display.name ]);
|
|
1394
|
+
return displays.map(display => (counts.get(display.name) ?? 0) < 2 || display.loginProvider === void 0 ? display.name : `${display.name} (${providerTitle(display.loginProvider) ?? display.loginProvider})`);
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1376
1397
|
function useUserDisplays(ids) {
|
|
1377
1398
|
const {members: members} = useProjectMembers(), {users: users} = useStudioProjectUsers(), meRaw = useCurrentUser(), me = useMemo(() => meRaw === null ? null : {
|
|
1378
1399
|
...meRaw,
|
|
@@ -1405,21 +1426,32 @@ function bridgedSelfId(users, meId) {
|
|
|
1405
1426
|
return users.find(user => user.membership.id === meId)?.profile?.sanityUserId ?? classified.globalId ?? (classified.namespace === "project" ? void 0 : meId);
|
|
1406
1427
|
}
|
|
1407
1428
|
|
|
1408
|
-
function
|
|
1429
|
+
function useSelfState() {
|
|
1409
1430
|
const me = useCurrentUser(), {users: users, loading: loading, error: error} = useStudioProjectUsers();
|
|
1410
|
-
if (!me) return
|
|
1411
|
-
|
|
1412
|
-
if (id !== void 0) return {
|
|
1413
|
-
id: id,
|
|
1414
|
-
roles: me.roles ?? []
|
|
1431
|
+
if (!me) return {
|
|
1432
|
+
kind: "unavailable"
|
|
1415
1433
|
};
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1434
|
+
const id = bridgedSelfId(users, me.id);
|
|
1435
|
+
return id !== void 0 ? {
|
|
1436
|
+
kind: "resolved",
|
|
1437
|
+
self: {
|
|
1438
|
+
id: id,
|
|
1439
|
+
roles: me.roles ?? []
|
|
1420
1440
|
}
|
|
1421
|
-
|
|
1422
|
-
|
|
1441
|
+
} : loading ? {
|
|
1442
|
+
kind: "pending"
|
|
1443
|
+
} : error !== void 0 ? (warnSelfUnavailableOnce(`load:${me.id}`, `workflow: the project member directory failed to load ("${errorMessage(error)}") — the logged-in user ("${me.id}") is project-scoped, and only that directory maps it to the account-global identity the engine stores, so workflow assignment and authoring controls stay disabled. A mounted view does not retry on its own; the next consumer to ask reloads the directory once its backoff has passed.`),
|
|
1444
|
+
{
|
|
1445
|
+
kind: "unavailable"
|
|
1446
|
+
}) : (warnSelfUnavailableOnce(`unresolved:${me.id}`, `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.`),
|
|
1447
|
+
{
|
|
1448
|
+
kind: "unavailable"
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
function useBridgedSelf() {
|
|
1453
|
+
const state = useSelfState();
|
|
1454
|
+
return state.kind === "resolved" ? state.self : void 0;
|
|
1423
1455
|
}
|
|
1424
1456
|
|
|
1425
1457
|
function useSelfActor() {
|
|
@@ -1428,13 +1460,26 @@ function useSelfActor() {
|
|
|
1428
1460
|
}
|
|
1429
1461
|
|
|
1430
1462
|
function useAssignmentIdentity() {
|
|
1431
|
-
const
|
|
1432
|
-
if (
|
|
1433
|
-
|
|
1434
|
-
|
|
1463
|
+
const state = useSelfState();
|
|
1464
|
+
if (state.kind !== "resolved") return state;
|
|
1465
|
+
const {id: id, roles: roles} = state.self;
|
|
1466
|
+
return {
|
|
1467
|
+
kind: "resolved",
|
|
1468
|
+
identity: {
|
|
1469
|
+
userId: id,
|
|
1470
|
+
roles: roles.map(r => r.name)
|
|
1471
|
+
}
|
|
1435
1472
|
};
|
|
1436
1473
|
}
|
|
1437
1474
|
|
|
1475
|
+
function identityOf(state) {
|
|
1476
|
+
return state.kind === "resolved" ? state.identity : void 0;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
function useCurrentUserId() {
|
|
1480
|
+
return identityOf(useAssignmentIdentity())?.userId;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1438
1483
|
const projectMembersByUsers = /* @__PURE__ */ new WeakMap;
|
|
1439
1484
|
|
|
1440
1485
|
function projectMembersFrom(users) {
|
|
@@ -1542,6 +1587,8 @@ function buildParams(decls, values) {
|
|
|
1542
1587
|
};
|
|
1543
1588
|
}
|
|
1544
1589
|
|
|
1590
|
+
const LOADING_CUE_DELAY_MS = 400;
|
|
1591
|
+
|
|
1545
1592
|
function useDelayedFlag(active, delayMs) {
|
|
1546
1593
|
const [held, setHeld] = useState(!1);
|
|
1547
1594
|
return useEffect(() => {
|
|
@@ -1823,23 +1870,27 @@ function MemberPicker({selectedIds: selectedIds, onSelect: onSelect, unassignRow
|
|
|
1823
1870
|
});
|
|
1824
1871
|
}
|
|
1825
1872
|
|
|
1826
|
-
function AssigneePicker({value: value, onChange: onChange}) {
|
|
1873
|
+
function AssigneePicker({value: value, onChange: onChange, eligibleRoles: eligibleRoles, roleAliases: roleAliases}) {
|
|
1827
1874
|
const state = useProjectMembers();
|
|
1828
1875
|
/* @__PURE__ */
|
|
1829
1876
|
return jsx(AssigneePicker$1, {
|
|
1830
1877
|
...state,
|
|
1878
|
+
eligibleRoles: eligibleRoles,
|
|
1831
1879
|
onChange: onChange,
|
|
1880
|
+
roleAliases: roleAliases,
|
|
1832
1881
|
value: value
|
|
1833
1882
|
});
|
|
1834
1883
|
}
|
|
1835
1884
|
|
|
1836
|
-
function SingleAssigneePicker({current: current, onPick: onPick}) {
|
|
1885
|
+
function SingleAssigneePicker({current: current, onPick: onPick, eligibleRoles: eligibleRoles, roleAliases: roleAliases}) {
|
|
1837
1886
|
/* @__PURE__ */
|
|
1838
1887
|
return jsx(AssigneePicker, {
|
|
1888
|
+
eligibleRoles: eligibleRoles,
|
|
1839
1889
|
onChange: next => {
|
|
1840
1890
|
const picked = singleAssigneePick(current, next);
|
|
1841
1891
|
picked !== void 0 && onPick(picked);
|
|
1842
1892
|
},
|
|
1893
|
+
roleAliases: roleAliases,
|
|
1843
1894
|
value: current ? [ current ] : []
|
|
1844
1895
|
});
|
|
1845
1896
|
}
|
|
@@ -2152,7 +2203,6 @@ const TOAST_ID = {
|
|
|
2152
2203
|
effectResolve: "workflow-effect-resolve",
|
|
2153
2204
|
effectsDrain: "workflow-effects-drain",
|
|
2154
2205
|
effectsIncomplete: "workflow-effects-incomplete",
|
|
2155
|
-
orphanSettle: "workflow-orphan-settle",
|
|
2156
2206
|
start: "workflow-start"
|
|
2157
2207
|
};
|
|
2158
2208
|
|
|
@@ -2549,11 +2599,10 @@ function Separator() {
|
|
|
2549
2599
|
}
|
|
2550
2600
|
|
|
2551
2601
|
function stageTitle(definition, stageName) {
|
|
2552
|
-
return
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
return args.definition?.stages.find(s => s.name === args.stageName)?.activities?.find(a => a.name === args.activityName);
|
|
2602
|
+
return findStageNode({
|
|
2603
|
+
definition: definition,
|
|
2604
|
+
stageName: stageName
|
|
2605
|
+
})?.title ?? stageName;
|
|
2557
2606
|
}
|
|
2558
2607
|
|
|
2559
2608
|
function findActivity(args) {
|
|
@@ -3013,8 +3062,7 @@ function PendingDocFace({bareId: bareId, layout: layout}) {
|
|
|
3013
3062
|
children: id
|
|
3014
3063
|
});
|
|
3015
3064
|
}
|
|
3016
|
-
return compact ?
|
|
3017
|
-
/* @__PURE__ */ jsxs(Flex, {
|
|
3065
|
+
return compact ? /* @__PURE__ */ jsxs(Flex, {
|
|
3018
3066
|
align: "center",
|
|
3019
3067
|
gap: 2,
|
|
3020
3068
|
children: [
|
|
@@ -3688,9 +3736,11 @@ function AssigneeField({field: field, instanceId: instanceId, onSave: onSave, on
|
|
|
3688
3736
|
children: /* @__PURE__ */ jsx(DismissablePopover, {
|
|
3689
3737
|
content: /* @__PURE__ */ jsx(SingleAssigneePicker, {
|
|
3690
3738
|
current: cur,
|
|
3739
|
+
eligibleRoles: field.roles,
|
|
3691
3740
|
onPick: picked => {
|
|
3692
3741
|
setOpen(!1), pick(picked);
|
|
3693
|
-
}
|
|
3742
|
+
},
|
|
3743
|
+
roleAliases: field.roleAliases
|
|
3694
3744
|
}),
|
|
3695
3745
|
onDismiss: () => setOpen(!1),
|
|
3696
3746
|
open: open,
|
|
@@ -4021,6 +4071,267 @@ function EditableField({field: field, entry: entry, description: description, in
|
|
|
4021
4071
|
});
|
|
4022
4072
|
}
|
|
4023
4073
|
|
|
4074
|
+
function useDrainEffects(instanceId) {
|
|
4075
|
+
const {drainEffectsFor: drainEffectsFor} = useWorkflowContext(), toast = useWorkflowToast(), [busy, setBusy] = useState(!1);
|
|
4076
|
+
return {
|
|
4077
|
+
busy: busy,
|
|
4078
|
+
run: async () => {
|
|
4079
|
+
setBusy(!0);
|
|
4080
|
+
try {
|
|
4081
|
+
await drainEffectsFor(instanceId), toast.push({
|
|
4082
|
+
id: TOAST_ID.effectsDrain,
|
|
4083
|
+
status: "info",
|
|
4084
|
+
title: "Ran the registered handlers"
|
|
4085
|
+
});
|
|
4086
|
+
} catch (err) {
|
|
4087
|
+
toast.push({
|
|
4088
|
+
id: TOAST_ID.effectsDrain,
|
|
4089
|
+
status: "error",
|
|
4090
|
+
title: "Failed to run pending effects",
|
|
4091
|
+
description: describeError(err)
|
|
4092
|
+
});
|
|
4093
|
+
} finally {
|
|
4094
|
+
setBusy(!1);
|
|
4095
|
+
}
|
|
4096
|
+
}
|
|
4097
|
+
};
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4100
|
+
function isRunnable(verb) {
|
|
4101
|
+
return verb === "drain-effects";
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
function effectLabel(effect) {
|
|
4105
|
+
return effect.title ?? effect.name;
|
|
4106
|
+
}
|
|
4107
|
+
|
|
4108
|
+
const ACTION_LABEL = {
|
|
4109
|
+
"drain-effects": "Run the step again"
|
|
4110
|
+
}, REMEDY_TEXT = {
|
|
4111
|
+
"retry-effect": "The step has to run again before this workflow can continue.",
|
|
4112
|
+
"reset-activity": "Reset the task to try it again, or skip it.",
|
|
4113
|
+
"set-stage": "Move the workflow on to its next stage yourself."
|
|
4114
|
+
};
|
|
4115
|
+
|
|
4116
|
+
function detailOf(cause) {
|
|
4117
|
+
switch (cause.kind) {
|
|
4118
|
+
case "failed-effect":
|
|
4119
|
+
return `The step “${effectLabel(cause.effect)}” failed`;
|
|
4120
|
+
|
|
4121
|
+
case "hung-effect":
|
|
4122
|
+
return `The step “${effectLabel(cause.effect)}” didn’t finish`;
|
|
4123
|
+
|
|
4124
|
+
case "failed-activity":
|
|
4125
|
+
return "This task failed";
|
|
4126
|
+
|
|
4127
|
+
default:
|
|
4128
|
+
return summaryOf(cause);
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
|
|
4132
|
+
function summaryOf(cause) {
|
|
4133
|
+
switch (cause.kind) {
|
|
4134
|
+
case "failed-effect":
|
|
4135
|
+
return "An automated step failed";
|
|
4136
|
+
|
|
4137
|
+
case "hung-effect":
|
|
4138
|
+
return "An automated step didn’t finish";
|
|
4139
|
+
|
|
4140
|
+
case "failed-activity":
|
|
4141
|
+
return "A task failed";
|
|
4142
|
+
|
|
4143
|
+
case "no-transition-fires":
|
|
4144
|
+
return "Every task is done, but nothing moves this workflow on";
|
|
4145
|
+
|
|
4146
|
+
case "transition-unevaluable":
|
|
4147
|
+
return "This workflow is waiting on something it can’t read yet, and will move on by itself";
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4151
|
+
function activityDeclaringEffect(args) {
|
|
4152
|
+
return findStageNode(args)?.activities?.find(activity => (activity.actions ?? []).some(action => (action.effects ?? []).some(effect => effect.name === args.effectName)))?.name;
|
|
4153
|
+
}
|
|
4154
|
+
|
|
4155
|
+
function faultingActivity(args) {
|
|
4156
|
+
const {cause: cause} = args;
|
|
4157
|
+
if (cause.kind === "failed-activity") return cause.activity;
|
|
4158
|
+
if (cause.kind === "failed-effect" || cause.kind === "hung-effect") return activityDeclaringEffect({
|
|
4159
|
+
definition: args.definition,
|
|
4160
|
+
effectName: cause.effect.name,
|
|
4161
|
+
stageName: args.stageName
|
|
4162
|
+
});
|
|
4163
|
+
}
|
|
4164
|
+
|
|
4165
|
+
function isRecoverable(cause) {
|
|
4166
|
+
return cause.kind === "transition-unevaluable";
|
|
4167
|
+
}
|
|
4168
|
+
|
|
4169
|
+
function diagnosisOf(args) {
|
|
4170
|
+
if (args.evaluation !== void 0) return diagnoseInstance(diagnoseInputFromEvaluation(args.evaluation));
|
|
4171
|
+
const cause = documentStuckCause({
|
|
4172
|
+
instance: args.instance,
|
|
4173
|
+
definition: args.definition
|
|
4174
|
+
});
|
|
4175
|
+
return cause === void 0 ? void 0 : {
|
|
4176
|
+
state: "stuck",
|
|
4177
|
+
cause: cause
|
|
4178
|
+
};
|
|
4179
|
+
}
|
|
4180
|
+
|
|
4181
|
+
function instanceFault(args) {
|
|
4182
|
+
const diagnosis = diagnosisOf(args);
|
|
4183
|
+
if (diagnosis === void 0 || diagnosis.state !== "stuck") return;
|
|
4184
|
+
const verbs = remediationsFor(diagnosis).map(remediation2 => remediation2.verb);
|
|
4185
|
+
return {
|
|
4186
|
+
activity: faultingActivity({
|
|
4187
|
+
cause: diagnosis.cause,
|
|
4188
|
+
definition: args.definition,
|
|
4189
|
+
stageName: args.instance.currentStage
|
|
4190
|
+
}),
|
|
4191
|
+
detail: detailOf(diagnosis.cause),
|
|
4192
|
+
summary: summaryOf(diagnosis.cause),
|
|
4193
|
+
remedies: verbs.flatMap(verb => REMEDY_TEXT[verb] ?? []),
|
|
4194
|
+
actions: verbs.flatMap(verb => isRunnable(verb) ? [ {
|
|
4195
|
+
verb: verb,
|
|
4196
|
+
label: ACTION_LABEL[verb]
|
|
4197
|
+
} ] : []),
|
|
4198
|
+
recoverable: isRecoverable(diagnosis.cause)
|
|
4199
|
+
};
|
|
4200
|
+
}
|
|
4201
|
+
|
|
4202
|
+
function looksLikeDefinition(value) {
|
|
4203
|
+
return typeof value == "object" && value !== null && Array.isArray(value.stages);
|
|
4204
|
+
}
|
|
4205
|
+
|
|
4206
|
+
const parsed = /* @__PURE__ */ new WeakMap;
|
|
4207
|
+
|
|
4208
|
+
function definitionSnapshotOf(instance) {
|
|
4209
|
+
if (parsed.has(instance)) return parsed.get(instance);
|
|
4210
|
+
let definition;
|
|
4211
|
+
try {
|
|
4212
|
+
const candidate = parseDefinitionSnapshot(instance);
|
|
4213
|
+
if (!looksLikeDefinition(candidate)) throw new Error(`definitionSnapshot on "${instance._id}" parsed to a non-definition shape`);
|
|
4214
|
+
definition = candidate;
|
|
4215
|
+
} catch (err) {
|
|
4216
|
+
console.error("[workflow-studio-plugin] unreadable definitionSnapshot:", err), definition = void 0;
|
|
4217
|
+
}
|
|
4218
|
+
return parsed.set(instance, definition), definition;
|
|
4219
|
+
}
|
|
4220
|
+
|
|
4221
|
+
function useDefinition(entry) {
|
|
4222
|
+
return useMemo(() => {
|
|
4223
|
+
if (entry) return entry.evaluation ? entry.evaluation.definition : definitionSnapshotOf(entry.instance);
|
|
4224
|
+
}, [ entry ]);
|
|
4225
|
+
}
|
|
4226
|
+
|
|
4227
|
+
function AbortedBadge({instance: instance}) {
|
|
4228
|
+
return terminalState(instance) !== "aborted" ? null : /* @__PURE__ */ jsx(Badge, {
|
|
4229
|
+
fontSize: 1,
|
|
4230
|
+
tone: "critical",
|
|
4231
|
+
children: "Aborted"
|
|
4232
|
+
});
|
|
4233
|
+
}
|
|
4234
|
+
|
|
4235
|
+
function OlderDefinitionBadge({instance: instance}) {
|
|
4236
|
+
const {latestDefinitionVersions: latestDefinitionVersions} = useWorkflowContext(), latest = latestDefinitionVersions.get(instance.definition);
|
|
4237
|
+
return latest === void 0 || latest <= instance.pinnedVersion ? null : /* @__PURE__ */ jsx(HoverHint, {
|
|
4238
|
+
description: "Running workflows keep the version they started on",
|
|
4239
|
+
text: `Started on v${instance.pinnedVersion}, latest is now v${latest}`,
|
|
4240
|
+
textWeight: "medium",
|
|
4241
|
+
children: /* @__PURE__ */ jsx(Badge, {
|
|
4242
|
+
fontSize: 1,
|
|
4243
|
+
tone: "caution",
|
|
4244
|
+
children: "Older version"
|
|
4245
|
+
})
|
|
4246
|
+
});
|
|
4247
|
+
}
|
|
4248
|
+
|
|
4249
|
+
function useInstanceFault(entry) {
|
|
4250
|
+
return instanceFault({
|
|
4251
|
+
definition: useDefinition(entry),
|
|
4252
|
+
evaluation: entry.evaluation,
|
|
4253
|
+
instance: entry.instance
|
|
4254
|
+
});
|
|
4255
|
+
}
|
|
4256
|
+
|
|
4257
|
+
function InstanceFaultNote({entry: entry, scope: scope}) {
|
|
4258
|
+
const fault = useInstanceFault(entry);
|
|
4259
|
+
if (fault === void 0 || scope.kind === "task" && fault.activity !== scope.activityName) return null;
|
|
4260
|
+
const Icon = fault.recoverable ? WarningOutlineIcon : ErrorOutlineIcon;
|
|
4261
|
+
/* @__PURE__ */
|
|
4262
|
+
return jsx(Card, {
|
|
4263
|
+
padding: 3,
|
|
4264
|
+
radius: 3,
|
|
4265
|
+
tone: fault.recoverable ? "caution" : "critical",
|
|
4266
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
4267
|
+
align: "flex-start",
|
|
4268
|
+
gap: 3,
|
|
4269
|
+
children: [
|
|
4270
|
+
/* @__PURE__ */ jsx(Text, {
|
|
4271
|
+
size: 1,
|
|
4272
|
+
children: /* @__PURE__ */ jsx(Icon, {})
|
|
4273
|
+
}),
|
|
4274
|
+
/* @__PURE__ */ jsxs(Stack, {
|
|
4275
|
+
flex: 1,
|
|
4276
|
+
gap: 3,
|
|
4277
|
+
children: [
|
|
4278
|
+
/* @__PURE__ */ jsx(Text, {
|
|
4279
|
+
size: 1,
|
|
4280
|
+
weight: "medium",
|
|
4281
|
+
children: scope.kind === "run" ? fault.summary : fault.detail
|
|
4282
|
+
}), scope.kind === "run" ? /* @__PURE__ */ jsx(RunControl, {
|
|
4283
|
+
activity: fault.activity,
|
|
4284
|
+
onOpenActivity: scope.onOpenActivity
|
|
4285
|
+
}) : /* @__PURE__ */ jsx(TaskControls, {
|
|
4286
|
+
actions: fault.actions,
|
|
4287
|
+
instanceId: entry.instance._id,
|
|
4288
|
+
remedies: fault.remedies
|
|
4289
|
+
}) ]
|
|
4290
|
+
}) ]
|
|
4291
|
+
})
|
|
4292
|
+
});
|
|
4293
|
+
}
|
|
4294
|
+
|
|
4295
|
+
function RunControl({activity: activity, onOpenActivity: onOpenActivity}) {
|
|
4296
|
+
return activity === void 0 ? null : /* @__PURE__ */ jsx(Flex, {
|
|
4297
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
4298
|
+
fontSize: 1,
|
|
4299
|
+
mode: "ghost",
|
|
4300
|
+
onClick: () => onOpenActivity(activity),
|
|
4301
|
+
padding: 2,
|
|
4302
|
+
text: "View task"
|
|
4303
|
+
})
|
|
4304
|
+
});
|
|
4305
|
+
}
|
|
4306
|
+
|
|
4307
|
+
const RUN_VERB = {
|
|
4308
|
+
"drain-effects": drain => drain.run()
|
|
4309
|
+
};
|
|
4310
|
+
|
|
4311
|
+
function TaskControls({actions: actions, instanceId: instanceId, remedies: remedies}) {
|
|
4312
|
+
const drain = useDrainEffects(instanceId);
|
|
4313
|
+
/* @__PURE__ */
|
|
4314
|
+
return jsxs(Fragment, {
|
|
4315
|
+
children: [ remedies.length === 0 ? null : /* @__PURE__ */ jsx(Text, {
|
|
4316
|
+
muted: !0,
|
|
4317
|
+
size: 1,
|
|
4318
|
+
children: remedies.join(" ")
|
|
4319
|
+
}), actions.length === 0 ? null : /* @__PURE__ */ jsx(Flex, {
|
|
4320
|
+
gap: 2,
|
|
4321
|
+
children: actions.map(action => /* @__PURE__ */ jsx(Button, {
|
|
4322
|
+
disabled: drain.busy,
|
|
4323
|
+
fontSize: 1,
|
|
4324
|
+
mode: "ghost",
|
|
4325
|
+
onClick: () => {
|
|
4326
|
+
RUN_VERB[action.verb](drain);
|
|
4327
|
+
},
|
|
4328
|
+
padding: 2,
|
|
4329
|
+
text: action.label
|
|
4330
|
+
}, action.verb))
|
|
4331
|
+
}) ]
|
|
4332
|
+
});
|
|
4333
|
+
}
|
|
4334
|
+
|
|
4024
4335
|
function MetaRow({children: children, fillHeight: fillHeight, label: label}) {
|
|
4025
4336
|
/* @__PURE__ */
|
|
4026
4337
|
return jsxs(Flex, {
|
|
@@ -4108,6 +4419,12 @@ function useSpaceToken(index) {
|
|
|
4108
4419
|
return value;
|
|
4109
4420
|
}
|
|
4110
4421
|
|
|
4422
|
+
function useRadiusToken(index) {
|
|
4423
|
+
const value = useTheme_v2().radius[index];
|
|
4424
|
+
if (value === void 0) throw new Error(`theme is missing radius token ${index}`);
|
|
4425
|
+
return value;
|
|
4426
|
+
}
|
|
4427
|
+
|
|
4111
4428
|
function useContainerToken(index) {
|
|
4112
4429
|
const value = useTheme_v2().container[index];
|
|
4113
4430
|
if (value === void 0) throw new Error(`theme is missing container token ${index}`);
|
|
@@ -4148,10 +4465,9 @@ function useBadgeCapTrim() {
|
|
|
4148
4465
|
};
|
|
4149
4466
|
}
|
|
4150
4467
|
|
|
4151
|
-
function SpinnerSlot({busy: busy}) {
|
|
4152
|
-
const size = useTextIconSize(), trim = useCapTrimFor(size);
|
|
4153
|
-
/* @__PURE__ */
|
|
4154
|
-
return jsx(Flex, {
|
|
4468
|
+
function SpinnerSlot({busy: busy, reserve: reserve = !0}) {
|
|
4469
|
+
const size = useTextIconSize(), trim = useCapTrimFor(size), spinning = useDelayedFlag(busy, LOADING_CUE_DELAY_MS);
|
|
4470
|
+
return !spinning && !reserve ? null : /* @__PURE__ */ jsx(Flex, {
|
|
4155
4471
|
align: "center",
|
|
4156
4472
|
flex: "none",
|
|
4157
4473
|
justify: "center",
|
|
@@ -4161,7 +4477,7 @@ function SpinnerSlot({busy: busy}) {
|
|
|
4161
4477
|
marginTop: trim,
|
|
4162
4478
|
width: size
|
|
4163
4479
|
},
|
|
4164
|
-
children:
|
|
4480
|
+
children: spinning ? /* @__PURE__ */ jsx(Spinner, {
|
|
4165
4481
|
muted: !0,
|
|
4166
4482
|
size: 1
|
|
4167
4483
|
}) : null
|
|
@@ -4169,6 +4485,7 @@ function SpinnerSlot({busy: busy}) {
|
|
|
4169
4485
|
}
|
|
4170
4486
|
|
|
4171
4487
|
function LoadingRow({label: label, padding: padding}) {
|
|
4488
|
+
const announced = useDelayedFlag(!0, LOADING_CUE_DELAY_MS);
|
|
4172
4489
|
/* @__PURE__ */
|
|
4173
4490
|
return jsxs(Flex, {
|
|
4174
4491
|
align: "center",
|
|
@@ -4179,12 +4496,11 @@ function LoadingRow({label: label, padding: padding}) {
|
|
|
4179
4496
|
children: [
|
|
4180
4497
|
/* @__PURE__ */ jsx(SpinnerSlot, {
|
|
4181
4498
|
busy: !0
|
|
4182
|
-
}),
|
|
4183
|
-
/* @__PURE__ */ jsx(Text, {
|
|
4499
|
+
}), announced ? /* @__PURE__ */ jsx(Text, {
|
|
4184
4500
|
muted: !0,
|
|
4185
4501
|
size: 1,
|
|
4186
4502
|
children: label
|
|
4187
|
-
}) ]
|
|
4503
|
+
}) : null ]
|
|
4188
4504
|
});
|
|
4189
4505
|
}
|
|
4190
4506
|
|
|
@@ -4245,8 +4561,7 @@ function RowAssignees({assignees: assignees, hint: hint}) {
|
|
|
4245
4561
|
const bothKinds = roles.length > 0 && displays.length > 0;
|
|
4246
4562
|
/* @__PURE__ */
|
|
4247
4563
|
return jsx(HoverHint, {
|
|
4248
|
-
content:
|
|
4249
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
4564
|
+
content: /* @__PURE__ */ jsxs(Stack, {
|
|
4250
4565
|
gap: 3,
|
|
4251
4566
|
children: [ roles.length > 0 ? /* @__PURE__ */ jsx(HintSection, {
|
|
4252
4567
|
names: roles.map(roleLabel),
|
|
@@ -4254,7 +4569,7 @@ function RowAssignees({assignees: assignees, hint: hint}) {
|
|
|
4254
4569
|
label: "Roles"
|
|
4255
4570
|
} : {}
|
|
4256
4571
|
}) : null, displays.length > 0 ? /* @__PURE__ */ jsx(HintSection, {
|
|
4257
|
-
names: displays
|
|
4572
|
+
names: disambiguatedNames(displays),
|
|
4258
4573
|
...bothKinds ? {
|
|
4259
4574
|
label: "Members"
|
|
4260
4575
|
} : {}
|
|
@@ -4333,8 +4648,7 @@ function AssignActivityControl({instanceId: instanceId, state: state, surface: s
|
|
|
4333
4648
|
}
|
|
4334
4649
|
}, handleClick = e => {
|
|
4335
4650
|
e.stopPropagation(), setOpen(v => !v);
|
|
4336
|
-
}, button = assignees.length > 0 ?
|
|
4337
|
-
/* @__PURE__ */ jsx(AvatarButton, {
|
|
4651
|
+
}, button = assignees.length > 0 ? /* @__PURE__ */ jsx(AvatarButton, {
|
|
4338
4652
|
"aria-label": "Assignees",
|
|
4339
4653
|
as: "span",
|
|
4340
4654
|
avatar: /* @__PURE__ */ jsx(RowAssignees, {
|
|
@@ -4364,9 +4678,11 @@ function AssignActivityControl({instanceId: instanceId, state: state, surface: s
|
|
|
4364
4678
|
label: "Loading…",
|
|
4365
4679
|
padding: 3
|
|
4366
4680
|
}) : /* @__PURE__ */ jsx(AssigneePicker, {
|
|
4681
|
+
eligibleRoles: state.field.roles,
|
|
4367
4682
|
onChange: next => {
|
|
4368
4683
|
change(next);
|
|
4369
4684
|
},
|
|
4685
|
+
roleAliases: state.field.roleAliases,
|
|
4370
4686
|
value: current
|
|
4371
4687
|
})
|
|
4372
4688
|
}),
|
|
@@ -4451,49 +4767,39 @@ function ForMeEmptyState() {
|
|
|
4451
4767
|
});
|
|
4452
4768
|
}
|
|
4453
4769
|
|
|
4454
|
-
|
|
4455
|
-
return typeof value == "object" && value !== null && Array.isArray(value.stages);
|
|
4456
|
-
}
|
|
4457
|
-
|
|
4458
|
-
const parsed = /* @__PURE__ */ new WeakMap;
|
|
4459
|
-
|
|
4460
|
-
function definitionSnapshotOf(instance) {
|
|
4461
|
-
if (parsed.has(instance)) return parsed.get(instance);
|
|
4462
|
-
let definition;
|
|
4463
|
-
try {
|
|
4464
|
-
const candidate = parseDefinitionSnapshot(instance);
|
|
4465
|
-
if (!looksLikeDefinition(candidate)) throw new Error(`definitionSnapshot on "${instance._id}" parsed to a non-definition shape`);
|
|
4466
|
-
definition = candidate;
|
|
4467
|
-
} catch (err) {
|
|
4468
|
-
console.error("[workflow-studio-plugin] unreadable definitionSnapshot:", err), definition = void 0;
|
|
4469
|
-
}
|
|
4470
|
-
return parsed.set(instance, definition), definition;
|
|
4471
|
-
}
|
|
4770
|
+
const OVERDUE_HINT = "Now overdue";
|
|
4472
4771
|
|
|
4473
|
-
function
|
|
4474
|
-
return
|
|
4475
|
-
|
|
4476
|
-
}
|
|
4772
|
+
function hintFace(args) {
|
|
4773
|
+
return args.overdue ? args.reason === void 0 ? {
|
|
4774
|
+
text: OVERDUE_HINT
|
|
4775
|
+
} : {
|
|
4776
|
+
text: OVERDUE_HINT,
|
|
4777
|
+
description: args.reason
|
|
4778
|
+
} : args.reason === void 0 ? void 0 : {
|
|
4779
|
+
text: args.reason
|
|
4780
|
+
};
|
|
4477
4781
|
}
|
|
4478
4782
|
|
|
4479
|
-
function
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4783
|
+
function DueDate({dueDate: dueDate, hintDisabled: hintDisabled, overdue: overdue, reason: reason}) {
|
|
4784
|
+
const face = hintFace({
|
|
4785
|
+
overdue: overdue,
|
|
4786
|
+
reason: reason
|
|
4787
|
+
}), text = overdue ? /* @__PURE__ */ jsx(TextWithTone, {
|
|
4788
|
+
size: 1,
|
|
4789
|
+
tone: "caution",
|
|
4790
|
+
children: formatDate(dueDate)
|
|
4791
|
+
}) : /* @__PURE__ */ jsx(Text, {
|
|
4792
|
+
muted: !0,
|
|
4793
|
+
size: 1,
|
|
4794
|
+
children: formatDate(dueDate)
|
|
4484
4795
|
});
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
textWeight: "medium",
|
|
4493
|
-
children: /* @__PURE__ */ jsx(Badge, {
|
|
4494
|
-
fontSize: 1,
|
|
4495
|
-
tone: "caution",
|
|
4496
|
-
children: "Older version"
|
|
4796
|
+
return face === void 0 ? text :
|
|
4797
|
+
/* @__PURE__ */ jsx(Flex, {
|
|
4798
|
+
align: "center",
|
|
4799
|
+
children: /* @__PURE__ */ jsx(HoverHint, {
|
|
4800
|
+
...face,
|
|
4801
|
+
disabled: hintDisabled === !0,
|
|
4802
|
+
children: text
|
|
4497
4803
|
})
|
|
4498
4804
|
});
|
|
4499
4805
|
}
|
|
@@ -4524,24 +4830,12 @@ function CheckboxSlot({children: children}) {
|
|
|
4524
4830
|
/* @__PURE__ */
|
|
4525
4831
|
return jsx(Flex, {
|
|
4526
4832
|
align: "center",
|
|
4527
|
-
justify: "center",
|
|
4528
|
-
style: {
|
|
4529
|
-
lineHeight: 0,
|
|
4530
|
-
margin: trim
|
|
4531
|
-
},
|
|
4532
|
-
children: children
|
|
4533
|
-
});
|
|
4534
|
-
}
|
|
4535
|
-
|
|
4536
|
-
function DueDateText({dueDate: dueDate, overdue: overdue}) {
|
|
4537
|
-
return overdue ? /* @__PURE__ */ jsx(TextWithTone, {
|
|
4538
|
-
size: 1,
|
|
4539
|
-
tone: "caution",
|
|
4540
|
-
children: formatDate(dueDate)
|
|
4541
|
-
}) : /* @__PURE__ */ jsx(Text, {
|
|
4542
|
-
muted: !0,
|
|
4543
|
-
size: 1,
|
|
4544
|
-
children: formatDate(dueDate)
|
|
4833
|
+
justify: "center",
|
|
4834
|
+
style: {
|
|
4835
|
+
lineHeight: 0,
|
|
4836
|
+
margin: trim
|
|
4837
|
+
},
|
|
4838
|
+
children: children
|
|
4545
4839
|
});
|
|
4546
4840
|
}
|
|
4547
4841
|
|
|
@@ -4564,8 +4858,9 @@ function DueDateEditor({dueDate: dueDate, onDone: onDone, onPatch: onPatch}) {
|
|
|
4564
4858
|
}
|
|
4565
4859
|
|
|
4566
4860
|
function DueDateControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
4567
|
-
const [open, setOpen] = useState(!1), overdue = isTodoOverdue(item), display = item.dueDate ? /* @__PURE__ */ jsx(
|
|
4861
|
+
const [open, setOpen] = useState(!1), overdue = isTodoOverdue(item), display = item.dueDate ? /* @__PURE__ */ jsx(DueDate, {
|
|
4568
4862
|
dueDate: item.dueDate,
|
|
4863
|
+
hintDisabled: open,
|
|
4569
4864
|
overdue: overdue
|
|
4570
4865
|
}) : null;
|
|
4571
4866
|
return editable ? /* @__PURE__ */ jsx(DismissablePopover, {
|
|
@@ -4576,18 +4871,14 @@ function DueDateControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
|
4576
4871
|
}),
|
|
4577
4872
|
onDismiss: () => setOpen(!1),
|
|
4578
4873
|
open: open,
|
|
4579
|
-
children: display ? /* @__PURE__ */ jsx(
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
padding: 2,
|
|
4588
|
-
tone: overdue ? "caution" : "default",
|
|
4589
|
-
children: display
|
|
4590
|
-
})
|
|
4874
|
+
children: display ? /* @__PURE__ */ jsx(Button, {
|
|
4875
|
+
"aria-label": "Change due date",
|
|
4876
|
+
fontSize: 1,
|
|
4877
|
+
mode: "bleed",
|
|
4878
|
+
onClick: () => setOpen(v => !v),
|
|
4879
|
+
padding: 2,
|
|
4880
|
+
tone: overdue ? "caution" : "default",
|
|
4881
|
+
children: display
|
|
4591
4882
|
}) : /* @__PURE__ */ jsx(HoverHint, {
|
|
4592
4883
|
disabled: open,
|
|
4593
4884
|
text: "Set due date",
|
|
@@ -4601,13 +4892,10 @@ function DueDateControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
|
4601
4892
|
radius: 2
|
|
4602
4893
|
})
|
|
4603
4894
|
})
|
|
4604
|
-
}) : display && overdue ? /* @__PURE__ */ jsx(HoverHint, {
|
|
4605
|
-
text: "Now overdue",
|
|
4606
|
-
children: display
|
|
4607
4895
|
}) : display;
|
|
4608
4896
|
}
|
|
4609
4897
|
|
|
4610
|
-
function AssigneeControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
4898
|
+
function AssigneeControl({item: item, editable: editable, eligibleRoles: eligibleRoles, onPatch: onPatch, roleAliases: roleAliases}) {
|
|
4611
4899
|
const [open, setOpen] = useState(!1), current = item.assignee ?? null, chip = current ? /* @__PURE__ */ jsx(RowAssignees, {
|
|
4612
4900
|
assignees: [ current ]
|
|
4613
4901
|
}) : null;
|
|
@@ -4615,11 +4903,13 @@ function AssigneeControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
|
4615
4903
|
content:
|
|
4616
4904
|
/* @__PURE__ */ jsx(SingleAssigneePicker, {
|
|
4617
4905
|
current: current,
|
|
4906
|
+
eligibleRoles: eligibleRoles,
|
|
4618
4907
|
onPick: picked => {
|
|
4619
4908
|
setOpen(!1), onPatch({
|
|
4620
4909
|
assignee: picked
|
|
4621
4910
|
});
|
|
4622
|
-
}
|
|
4911
|
+
},
|
|
4912
|
+
roleAliases: roleAliases
|
|
4623
4913
|
}),
|
|
4624
4914
|
onDismiss: () => setOpen(!1),
|
|
4625
4915
|
open: open,
|
|
@@ -4721,8 +5011,7 @@ function BreadcrumbTail({segments: segments, style: style}) {
|
|
|
4721
5011
|
}
|
|
4722
5012
|
|
|
4723
5013
|
function WorkRow({lead: lead, children: children, end: end, onOpen: onOpen}) {
|
|
4724
|
-
const frame =
|
|
4725
|
-
/* @__PURE__ */ jsxs(Flex, {
|
|
5014
|
+
const frame = /* @__PURE__ */ jsxs(Flex, {
|
|
4726
5015
|
align: "center",
|
|
4727
5016
|
children: [
|
|
4728
5017
|
/* @__PURE__ */ jsx(Flex, {
|
|
@@ -4756,8 +5045,7 @@ function WorkRow({lead: lead, children: children, end: end, onOpen: onOpen}) {
|
|
|
4756
5045
|
padding: 1,
|
|
4757
5046
|
radius: 3,
|
|
4758
5047
|
children: frame
|
|
4759
|
-
}) :
|
|
4760
|
-
/* @__PURE__ */ jsx(Card, {
|
|
5048
|
+
}) : /* @__PURE__ */ jsx(Card, {
|
|
4761
5049
|
as: "button",
|
|
4762
5050
|
onClick: onOpen,
|
|
4763
5051
|
padding: 1,
|
|
@@ -4769,7 +5057,7 @@ function WorkRow({lead: lead, children: children, end: end, onOpen: onOpen}) {
|
|
|
4769
5057
|
});
|
|
4770
5058
|
}
|
|
4771
5059
|
|
|
4772
|
-
function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle, onPatch: onPatch, onRemove: onRemove}) {
|
|
5060
|
+
function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle, onPatch: onPatch, onRemove: onRemove, roleAliases: roleAliases}) {
|
|
4773
5061
|
const {canClick: canClick, hint: hint} = rowInteractivity(row), editable = row.editTarget !== void 0, checkbox = /* @__PURE__ */ jsx(TodoCheckbox, {
|
|
4774
5062
|
canClick: canClick,
|
|
4775
5063
|
checked: isTodoDone(row.item),
|
|
@@ -4786,8 +5074,10 @@ function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle,
|
|
|
4786
5074
|
}),
|
|
4787
5075
|
/* @__PURE__ */ jsx(AssigneeControl, {
|
|
4788
5076
|
editable: editable,
|
|
5077
|
+
eligibleRoles: row.eligibleAssigneeRoles,
|
|
4789
5078
|
item: row.item,
|
|
4790
|
-
onPatch: onPatch
|
|
5079
|
+
onPatch: onPatch,
|
|
5080
|
+
roleAliases: roleAliases
|
|
4791
5081
|
}), onRemove === void 0 ? null : /* @__PURE__ */ jsx(RemoveItemButton, {
|
|
4792
5082
|
onClick: onRemove
|
|
4793
5083
|
}) ]
|
|
@@ -4964,6 +5254,7 @@ function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter, sh
|
|
|
4964
5254
|
onToggle: () => {
|
|
4965
5255
|
toggleRow(row);
|
|
4966
5256
|
},
|
|
5257
|
+
roleAliases: definition?.roleAliases,
|
|
4967
5258
|
row: row
|
|
4968
5259
|
}, rowKey(row)))
|
|
4969
5260
|
}), addControl === null ? null : /* @__PURE__ */ jsx(Flex, {
|
|
@@ -5256,9 +5547,15 @@ function ActivityDetailDialog({entry: entry, activityName: activityName, breadcr
|
|
|
5256
5547
|
const detail = deriveActivityDetail({
|
|
5257
5548
|
entry: entry,
|
|
5258
5549
|
activityName: activityName
|
|
5259
|
-
});
|
|
5550
|
+
}), faultingActivity2 = useInstanceFault(entry)?.activity;
|
|
5260
5551
|
if (!detail) return null;
|
|
5261
|
-
const instanceId = entry.instance._id, notice = blockedNotice(detail),
|
|
5552
|
+
const instanceId = entry.instance._id, notice = blockedNotice(detail), fault = /* @__PURE__ */ jsx(InstanceFaultNote, {
|
|
5553
|
+
entry: entry,
|
|
5554
|
+
scope: {
|
|
5555
|
+
kind: "task",
|
|
5556
|
+
activityName: activityName
|
|
5557
|
+
}
|
|
5558
|
+
}), faulted = faultingActivity2 === activityName, hasBody = detail.state.length > 0 || notice !== void 0 || faulted;
|
|
5262
5559
|
/* @__PURE__ */
|
|
5263
5560
|
return jsxs(Dialog, {
|
|
5264
5561
|
footer: detail.presentation.terminalActions.length > 0 ? /* @__PURE__ */ jsx(TerminalFooter, {
|
|
@@ -5299,7 +5596,7 @@ function ActivityDetailDialog({entry: entry, activityName: activityName, breadcr
|
|
|
5299
5596
|
padding: 4,
|
|
5300
5597
|
children: /* @__PURE__ */ jsxs(Stack, {
|
|
5301
5598
|
gap: 5,
|
|
5302
|
-
children: [ detail.state.map(field => /* @__PURE__ */ jsx(FieldRow, {
|
|
5599
|
+
children: [ fault, detail.state.map(field => /* @__PURE__ */ jsx(FieldRow, {
|
|
5303
5600
|
activityName: activityName,
|
|
5304
5601
|
detail: detail,
|
|
5305
5602
|
entry: entry,
|
|
@@ -5480,6 +5777,18 @@ function CountedLabel({count: count, label: label}) {
|
|
|
5480
5777
|
});
|
|
5481
5778
|
}
|
|
5482
5779
|
|
|
5780
|
+
function CountedHeading({count: count, title: title}) {
|
|
5781
|
+
/* @__PURE__ */
|
|
5782
|
+
return jsx(CountedLabel, {
|
|
5783
|
+
count: count,
|
|
5784
|
+
label: /* @__PURE__ */ jsx(Text, {
|
|
5785
|
+
size: 1,
|
|
5786
|
+
weight: "semibold",
|
|
5787
|
+
children: title
|
|
5788
|
+
})
|
|
5789
|
+
});
|
|
5790
|
+
}
|
|
5791
|
+
|
|
5483
5792
|
function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
5484
5793
|
/* @__PURE__ */
|
|
5485
5794
|
return jsxs(Flex, {
|
|
@@ -5488,13 +5797,9 @@ function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
|
5488
5797
|
paddingLeft: 2,
|
|
5489
5798
|
paddingY: end === void 0 ? 3 : 1,
|
|
5490
5799
|
children: [
|
|
5491
|
-
/* @__PURE__ */ jsx(
|
|
5800
|
+
/* @__PURE__ */ jsx(CountedHeading, {
|
|
5492
5801
|
count: count,
|
|
5493
|
-
|
|
5494
|
-
size: 1,
|
|
5495
|
-
weight: "semibold",
|
|
5496
|
-
children: title
|
|
5497
|
-
})
|
|
5802
|
+
title: title
|
|
5498
5803
|
}), busy === void 0 ? null : /* @__PURE__ */ jsx(SpinnerSlot, {
|
|
5499
5804
|
busy: busy
|
|
5500
5805
|
}), end === void 0 ? null : /* @__PURE__ */ jsxs(Fragment, {
|
|
@@ -5506,21 +5811,85 @@ function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
|
5506
5811
|
});
|
|
5507
5812
|
}
|
|
5508
5813
|
|
|
5814
|
+
const EMPTY_METRIC_OPACITY = .5;
|
|
5815
|
+
|
|
5816
|
+
function MetricText({children: children, tone: tone}) {
|
|
5817
|
+
return tone === void 0 ? /* @__PURE__ */ jsx(Text, {
|
|
5818
|
+
muted: !0,
|
|
5819
|
+
size: 1,
|
|
5820
|
+
children: children
|
|
5821
|
+
}) : /* @__PURE__ */ jsx(TextWithTone, {
|
|
5822
|
+
size: 1,
|
|
5823
|
+
tone: tone,
|
|
5824
|
+
children: children
|
|
5825
|
+
});
|
|
5826
|
+
}
|
|
5827
|
+
|
|
5828
|
+
function MetricPair({Icon: Icon, empty: empty, face: face, tone: tone, value: value}) {
|
|
5829
|
+
/* @__PURE__ */
|
|
5830
|
+
return jsx(HoverHint, {
|
|
5831
|
+
...face,
|
|
5832
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
5833
|
+
align: "center",
|
|
5834
|
+
gap: 2,
|
|
5835
|
+
style: empty ? {
|
|
5836
|
+
opacity: EMPTY_METRIC_OPACITY
|
|
5837
|
+
} : void 0,
|
|
5838
|
+
children: [
|
|
5839
|
+
/* @__PURE__ */ jsx(MetricText, {
|
|
5840
|
+
tone: tone,
|
|
5841
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
5842
|
+
style: {
|
|
5843
|
+
color: "inherit"
|
|
5844
|
+
}
|
|
5845
|
+
})
|
|
5846
|
+
}),
|
|
5847
|
+
/* @__PURE__ */ jsx(MetricText, {
|
|
5848
|
+
tone: tone,
|
|
5849
|
+
children: value
|
|
5850
|
+
}) ]
|
|
5851
|
+
})
|
|
5852
|
+
});
|
|
5853
|
+
}
|
|
5854
|
+
|
|
5855
|
+
function AlertGlyph({Icon: Icon, hint: hint, label: label, tone: tone}) {
|
|
5856
|
+
/* @__PURE__ */
|
|
5857
|
+
return jsx(HoverHint, {
|
|
5858
|
+
text: hint,
|
|
5859
|
+
children: /* @__PURE__ */ jsx(TextWithTone, {
|
|
5860
|
+
size: 1,
|
|
5861
|
+
tone: tone,
|
|
5862
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
5863
|
+
...label === void 0 ? {} : {
|
|
5864
|
+
"aria-label": label,
|
|
5865
|
+
role: "img"
|
|
5866
|
+
},
|
|
5867
|
+
style: {
|
|
5868
|
+
color: "inherit"
|
|
5869
|
+
}
|
|
5870
|
+
})
|
|
5871
|
+
})
|
|
5872
|
+
});
|
|
5873
|
+
}
|
|
5874
|
+
|
|
5509
5875
|
function ActivityDateControl({instanceId: instanceId, state: state, surface: surface, dueDates: dueDates}) {
|
|
5510
5876
|
const editField = useEditField(surface), {save: save} = useSaveField({
|
|
5511
5877
|
instanceId: instanceId
|
|
5512
5878
|
}), [open, setOpen] = useState(!1), raw = dateControlValue({
|
|
5513
5879
|
state: state,
|
|
5514
5880
|
dueDates: dueDates
|
|
5515
|
-
}),
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5881
|
+
}), overdue = raw !== void 0 && isDueDatePast(raw, /* @__PURE__ */ new Date), dueDate = reason => raw === void 0 ? null : /* @__PURE__ */ jsx(DueDate, {
|
|
5882
|
+
dueDate: raw,
|
|
5883
|
+
hintDisabled: open,
|
|
5884
|
+
overdue: overdue,
|
|
5885
|
+
...reason === void 0 ? {} : {
|
|
5886
|
+
reason: reason
|
|
5887
|
+
}
|
|
5519
5888
|
});
|
|
5520
|
-
if (state.kind === "none") return
|
|
5521
|
-
if (state.kind === "closed")
|
|
5522
|
-
|
|
5523
|
-
|
|
5889
|
+
if (state.kind === "none") return dueDate();
|
|
5890
|
+
if (state.kind === "closed") {
|
|
5891
|
+
const display = dueDate(state.reason);
|
|
5892
|
+
return display === null ? null : /* @__PURE__ */ jsx(Button, {
|
|
5524
5893
|
"aria-label": "Date",
|
|
5525
5894
|
as: "span",
|
|
5526
5895
|
fontSize: 1,
|
|
@@ -5529,8 +5898,8 @@ function ActivityDateControl({instanceId: instanceId, state: state, surface: sur
|
|
|
5529
5898
|
onMouseDown: stopRowMouseDown,
|
|
5530
5899
|
padding: 2,
|
|
5531
5900
|
children: display
|
|
5532
|
-
})
|
|
5533
|
-
}
|
|
5901
|
+
});
|
|
5902
|
+
}
|
|
5534
5903
|
const kind = dateControlKind(state), commit = (mode, value) => {
|
|
5535
5904
|
state.kind === "editable" && save(() => editField({
|
|
5536
5905
|
instanceId: instanceId,
|
|
@@ -5566,7 +5935,7 @@ function ActivityDateControl({instanceId: instanceId, state: state, surface: sur
|
|
|
5566
5935
|
}),
|
|
5567
5936
|
onDismiss: () => setOpen(!1),
|
|
5568
5937
|
open: open,
|
|
5569
|
-
children:
|
|
5938
|
+
children: raw !== void 0 ? /* @__PURE__ */ jsx(Button, {
|
|
5570
5939
|
"aria-label": "Change date",
|
|
5571
5940
|
as: "span",
|
|
5572
5941
|
fontSize: 1,
|
|
@@ -5574,7 +5943,7 @@ function ActivityDateControl({instanceId: instanceId, state: state, surface: sur
|
|
|
5574
5943
|
onClick: handleClick,
|
|
5575
5944
|
onMouseDown: stopRowMouseDown,
|
|
5576
5945
|
padding: 2,
|
|
5577
|
-
children:
|
|
5946
|
+
children: dueDate()
|
|
5578
5947
|
}) : /* @__PURE__ */ jsx(HoverHint, {
|
|
5579
5948
|
disabled: open,
|
|
5580
5949
|
text: "Set date",
|
|
@@ -5664,12 +6033,11 @@ function TitleTag({hint: hint, tone: tone, children: children}) {
|
|
|
5664
6033
|
});
|
|
5665
6034
|
}
|
|
5666
6035
|
|
|
5667
|
-
function ActivityRow({face: face, breadcrumb: breadcrumb, assignees: assignees, assignState: assignState, dateState: dateState, dueDates: dueDates, instanceId: instanceId, onOpen: onOpen, surface: surface, terminalActions: terminalActions = []}) {
|
|
6036
|
+
function ActivityRow({face: face, breadcrumb: breadcrumb, assignees: assignees, assignState: assignState, dateState: dateState, dueDates: dueDates, faultHint: faultHint, instanceId: instanceId, onOpen: onOpen, surface: surface, terminalActions: terminalActions = []}) {
|
|
5668
6037
|
const settled = isTerminalActivityStatus(face.status), dimmed = settledDim(settled);
|
|
5669
6038
|
/* @__PURE__ */
|
|
5670
6039
|
return jsxs(WorkRow, {
|
|
5671
|
-
end:
|
|
5672
|
-
/* @__PURE__ */ jsxs(Fragment, {
|
|
6040
|
+
end: /* @__PURE__ */ jsxs(Fragment, {
|
|
5673
6041
|
children: [
|
|
5674
6042
|
/* @__PURE__ */ jsx(ActivityDateControl, {
|
|
5675
6043
|
dueDates: dueDates,
|
|
@@ -5697,6 +6065,10 @@ function ActivityRow({face: face, breadcrumb: breadcrumb, assignees: assignees,
|
|
|
5697
6065
|
/* @__PURE__ */ jsx(ActivityRowTitle, {
|
|
5698
6066
|
dimmed: dimmed,
|
|
5699
6067
|
children: face.title
|
|
6068
|
+
}), faultHint === void 0 || face.status === "failed" ? null : /* @__PURE__ */ jsx(AlertGlyph, {
|
|
6069
|
+
Icon: ErrorOutlineIcon,
|
|
6070
|
+
hint: faultHint,
|
|
6071
|
+
tone: "critical"
|
|
5700
6072
|
}), face.automated ? /* @__PURE__ */ jsx(TitleTag, {
|
|
5701
6073
|
hint: "Completes on its own — no user action is needed",
|
|
5702
6074
|
children: "Automated"
|
|
@@ -5712,9 +6084,8 @@ function ActivityRow({face: face, breadcrumb: breadcrumb, assignees: assignees,
|
|
|
5712
6084
|
}
|
|
5713
6085
|
|
|
5714
6086
|
function ActivitiesList({entry: entry, onOpenActivity: onOpenActivity, surface: surface}) {
|
|
5715
|
-
const activities = (entry.evaluation?.currentStage.activities ?? []).filter(t => !t.scopedOut), activityState = stateByActivity(entry.instance);
|
|
5716
|
-
return activities.length === 0 ?
|
|
5717
|
-
/* @__PURE__ */ jsx(Box, {
|
|
6087
|
+
const activities = (entry.evaluation?.currentStage.activities ?? []).filter(t => !t.scopedOut), activityState = stateByActivity(entry.instance), fault = useInstanceFault(entry);
|
|
6088
|
+
return activities.length === 0 ? /* @__PURE__ */ jsx(Box, {
|
|
5718
6089
|
paddingX: 1,
|
|
5719
6090
|
paddingY: 3,
|
|
5720
6091
|
children: /* @__PURE__ */ jsx(Text, {
|
|
@@ -5730,6 +6101,9 @@ function ActivitiesList({entry: entry, onOpenActivity: onOpenActivity, surface:
|
|
|
5730
6101
|
activityState: activityState,
|
|
5731
6102
|
editableFields: entry.evaluation?.editableFields
|
|
5732
6103
|
}),
|
|
6104
|
+
...fault?.activity === t.activity.name ? {
|
|
6105
|
+
faultHint: fault.summary
|
|
6106
|
+
} : {},
|
|
5733
6107
|
instanceId: entry.instance._id,
|
|
5734
6108
|
onOpen: () => onOpenActivity(t.activity.name),
|
|
5735
6109
|
surface: surface
|
|
@@ -5739,8 +6113,7 @@ function ActivitiesList({entry: entry, onOpenActivity: onOpenActivity, surface:
|
|
|
5739
6113
|
|
|
5740
6114
|
function instanceNotice(entry) {
|
|
5741
6115
|
const {instance: instance, committed: committed, evaluation: evaluation} = entry, state = terminalState(instance);
|
|
5742
|
-
if (state !== "in-flight")
|
|
5743
|
-
/* @__PURE__ */
|
|
6116
|
+
if (state !== "in-flight") /* @__PURE__ */
|
|
5744
6117
|
return jsx(Box, {
|
|
5745
6118
|
paddingX: 1,
|
|
5746
6119
|
paddingY: 2,
|
|
@@ -5876,7 +6249,10 @@ function progressFillPercent(face) {
|
|
|
5876
6249
|
}
|
|
5877
6250
|
|
|
5878
6251
|
function deriveFieldPills(args) {
|
|
5879
|
-
const {scope: scope, definition: definition, instance: instance, committed: committed, evaluation: evaluation} = args, declared = scope === "workflow" ? definition?.fields ?? [] :
|
|
6252
|
+
const {scope: scope, definition: definition, instance: instance, committed: committed, evaluation: evaluation} = args, declared = scope === "workflow" ? definition?.fields ?? [] : findStageNode({
|
|
6253
|
+
definition: definition,
|
|
6254
|
+
stageName: instance.currentStage
|
|
6255
|
+
})?.fields ?? [], entries = scope === "workflow" ? instance.fields : findOpenStageEntry(instance)?.fields ?? [], entriesByName = new Map(entries.map(entry => [ entry.name, entry ])), editables = isEvaluationCurrent({
|
|
5880
6256
|
committed: committed,
|
|
5881
6257
|
evaluation: evaluation
|
|
5882
6258
|
}) ? editablesByName(evaluation, scope) : /* @__PURE__ */ new Map, declaredNames = new Set(declared.map(d => d.name));
|
|
@@ -5925,7 +6301,7 @@ function UserAvatar({id: id}) {
|
|
|
5925
6301
|
function UserAvatarGroup({ids: ids, hint: hint}) {
|
|
5926
6302
|
const displays = useUserDisplays(ids);
|
|
5927
6303
|
return displays.length === 0 ? null : /* @__PURE__ */ jsx(HoverHint, {
|
|
5928
|
-
text: displays
|
|
6304
|
+
text: disambiguatedNames(displays).join(", "),
|
|
5929
6305
|
...hint === void 0 ? {} : {
|
|
5930
6306
|
description: hint
|
|
5931
6307
|
},
|
|
@@ -5984,8 +6360,7 @@ function FieldPills({entry: entry, scope: scope, definition: definition, surface
|
|
|
5984
6360
|
pill: pill,
|
|
5985
6361
|
scope: scope,
|
|
5986
6362
|
surface: surface
|
|
5987
|
-
}, pill.name)), overflow > 0 ?
|
|
5988
|
-
/* @__PURE__ */ jsx(Button, {
|
|
6363
|
+
}, pill.name)), overflow > 0 ? /* @__PURE__ */ jsx(Button, {
|
|
5989
6364
|
mode: "bleed",
|
|
5990
6365
|
onClick: () => setExpanded(v => !v),
|
|
5991
6366
|
padding: 2,
|
|
@@ -6424,9 +6799,11 @@ function AssigneePill({entry: entry, pill: pill, editability: editability, surfa
|
|
|
6424
6799
|
return jsx(PillPopover, {
|
|
6425
6800
|
content: /* @__PURE__ */ jsx(SingleAssigneePicker, {
|
|
6426
6801
|
current: current,
|
|
6802
|
+
eligibleRoles: editability.roles,
|
|
6427
6803
|
onPick: picked => {
|
|
6428
6804
|
setOpen(!1), pick(picked);
|
|
6429
|
-
}
|
|
6805
|
+
},
|
|
6806
|
+
roleAliases: editability.roleAliases
|
|
6430
6807
|
}),
|
|
6431
6808
|
onDismiss: () => setOpen(!1),
|
|
6432
6809
|
onToggle: () => setOpen(v => !v),
|
|
@@ -6440,13 +6817,15 @@ function AssigneesPill({entry: entry, pill: pill, editability: editability, surf
|
|
|
6440
6817
|
entry: entry,
|
|
6441
6818
|
editability: editability,
|
|
6442
6819
|
surface: surface
|
|
6443
|
-
}), current = pill.face.kind === "assignees" ? pill.face.assignees : []
|
|
6820
|
+
}), current = pill.face.kind === "assignees" ? pill.face.assignees : [], change = next => {
|
|
6821
|
+
saving || save(() => set(next));
|
|
6822
|
+
};
|
|
6444
6823
|
/* @__PURE__ */
|
|
6445
6824
|
return jsx(PillPopover, {
|
|
6446
6825
|
content: /* @__PURE__ */ jsx(AssigneePicker, {
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6826
|
+
eligibleRoles: editability.roles,
|
|
6827
|
+
onChange: change,
|
|
6828
|
+
roleAliases: editability.roleAliases,
|
|
6450
6829
|
value: current
|
|
6451
6830
|
}),
|
|
6452
6831
|
onDismiss: () => setOpen(!1),
|
|
@@ -7032,6 +7411,24 @@ function historyLine(h, titles) {
|
|
|
7032
7411
|
return historyLiner[h._type](h, titles);
|
|
7033
7412
|
}
|
|
7034
7413
|
|
|
7414
|
+
function AgoStamp({at: at, now: now}) {
|
|
7415
|
+
/* @__PURE__ */
|
|
7416
|
+
return jsx(Flex, {
|
|
7417
|
+
align: "center",
|
|
7418
|
+
children: /* @__PURE__ */ jsx(HoverHint, {
|
|
7419
|
+
text: formatShortDateTime(at),
|
|
7420
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
7421
|
+
muted: !0,
|
|
7422
|
+
size: 1,
|
|
7423
|
+
style: {
|
|
7424
|
+
whiteSpace: "nowrap"
|
|
7425
|
+
},
|
|
7426
|
+
children: formatShortAgo(at, now)
|
|
7427
|
+
})
|
|
7428
|
+
})
|
|
7429
|
+
});
|
|
7430
|
+
}
|
|
7431
|
+
|
|
7035
7432
|
function CodeChip({value: value}) {
|
|
7036
7433
|
/* @__PURE__ */
|
|
7037
7434
|
return jsx("code", {
|
|
@@ -7066,6 +7463,27 @@ function HintedMenuButton({hint: hint, ...menuButtonProps}) {
|
|
|
7066
7463
|
});
|
|
7067
7464
|
}
|
|
7068
7465
|
|
|
7466
|
+
function InlineEmphasis({children: children}) {
|
|
7467
|
+
const {font: font} = useTheme_v2();
|
|
7468
|
+
/* @__PURE__ */
|
|
7469
|
+
return jsx("span", {
|
|
7470
|
+
style: {
|
|
7471
|
+
fontWeight: font.text.weights.medium
|
|
7472
|
+
},
|
|
7473
|
+
children: children
|
|
7474
|
+
});
|
|
7475
|
+
}
|
|
7476
|
+
|
|
7477
|
+
const MINUTE_MS = 6e4;
|
|
7478
|
+
|
|
7479
|
+
function useMinuteClock() {
|
|
7480
|
+
const [now, setNow] = useState(() => /* @__PURE__ */ new Date);
|
|
7481
|
+
return useEffect(() => {
|
|
7482
|
+
const timer = setInterval(() => setNow(/* @__PURE__ */ new Date), MINUTE_MS);
|
|
7483
|
+
return () => clearInterval(timer);
|
|
7484
|
+
}, []), now;
|
|
7485
|
+
}
|
|
7486
|
+
|
|
7069
7487
|
function historyWindow(args) {
|
|
7070
7488
|
const {entries: entries, expanded: expanded} = args;
|
|
7071
7489
|
return {
|
|
@@ -7075,28 +7493,10 @@ function historyWindow(args) {
|
|
|
7075
7493
|
}
|
|
7076
7494
|
|
|
7077
7495
|
function PendingEffectRows({instance: instance, now: now}) {
|
|
7078
|
-
const {
|
|
7496
|
+
const {completeEffectFor: completeEffectFor, effectHandlers: effectHandlers} = useWorkflowContext(), toast = useWorkflowToast(), drain = useDrainEffects(instance._id), [resolving, setResolving] = useState(!1), pending = instance.pendingEffects ?? [];
|
|
7079
7497
|
if (pending.length === 0) return null;
|
|
7080
|
-
const
|
|
7081
|
-
|
|
7082
|
-
try {
|
|
7083
|
-
await drainEffectsFor(instance._id), toast.push({
|
|
7084
|
-
id: TOAST_ID.effectsDrain,
|
|
7085
|
-
status: "info",
|
|
7086
|
-
title: "Ran the registered handlers"
|
|
7087
|
-
});
|
|
7088
|
-
} catch (err) {
|
|
7089
|
-
toast.push({
|
|
7090
|
-
id: TOAST_ID.effectsDrain,
|
|
7091
|
-
status: "error",
|
|
7092
|
-
title: "Failed to run pending effects",
|
|
7093
|
-
description: describeError(err)
|
|
7094
|
-
});
|
|
7095
|
-
} finally {
|
|
7096
|
-
setBusy(!1);
|
|
7097
|
-
}
|
|
7098
|
-
}, resolve = async (effectKey, status) => {
|
|
7099
|
-
setBusy(!0);
|
|
7498
|
+
const resolve = async (effectKey, status) => {
|
|
7499
|
+
setResolving(!0);
|
|
7100
7500
|
try {
|
|
7101
7501
|
await completeEffectFor(instance._id, {
|
|
7102
7502
|
effectKey: effectKey,
|
|
@@ -7115,18 +7515,20 @@ function PendingEffectRows({instance: instance, now: now}) {
|
|
|
7115
7515
|
description: describeError(err)
|
|
7116
7516
|
});
|
|
7117
7517
|
} finally {
|
|
7118
|
-
|
|
7518
|
+
setResolving(!1);
|
|
7119
7519
|
}
|
|
7120
7520
|
};
|
|
7121
7521
|
/* @__PURE__ */
|
|
7122
7522
|
return jsx(Fragment, {
|
|
7123
7523
|
children: pending.map(fx => /* @__PURE__ */ jsx(PendingEffectRow, {
|
|
7124
|
-
busy: busy,
|
|
7524
|
+
busy: drain.busy || resolving,
|
|
7125
7525
|
effect: fx,
|
|
7126
7526
|
instanceId: instance._id,
|
|
7127
7527
|
now: now,
|
|
7128
7528
|
onResolve: status => resolve(fx._key, status),
|
|
7129
|
-
onRunHandlers:
|
|
7529
|
+
onRunHandlers: () => {
|
|
7530
|
+
drain.run();
|
|
7531
|
+
},
|
|
7130
7532
|
registered: fx.name in effectHandlers
|
|
7131
7533
|
}, fx._key))
|
|
7132
7534
|
});
|
|
@@ -7210,12 +7612,7 @@ function PendingEffectRow({busy: busy, effect: effect, instanceId: instanceId, n
|
|
|
7210
7612
|
}
|
|
7211
7613
|
|
|
7212
7614
|
function ActivityLog({instance: instance, definition: definition, windowed: windowed = !0}) {
|
|
7213
|
-
const titles = useMemo(() => makeTitleResolver(definition), [ definition ]), entries = useMemo(() => instance.history.toReversed(), [ instance.history ]),
|
|
7214
|
-
useEffect(() => {
|
|
7215
|
-
const timer = setInterval(() => setNow(/* @__PURE__ */ new Date), 6e4);
|
|
7216
|
-
return () => clearInterval(timer);
|
|
7217
|
-
}, []);
|
|
7218
|
-
const history = historyWindow({
|
|
7615
|
+
const titles = useMemo(() => makeTitleResolver(definition), [ definition ]), entries = useMemo(() => instance.history.toReversed(), [ instance.history ]), now = useMinuteClock(), [expanded, setExpanded] = useState(!1), history = historyWindow({
|
|
7219
7616
|
entries: entries,
|
|
7220
7617
|
expanded: expanded || !windowed
|
|
7221
7618
|
});
|
|
@@ -7257,16 +7654,9 @@ function FeedStamp({at: at, now: now}) {
|
|
|
7257
7654
|
size: 1,
|
|
7258
7655
|
children: "·"
|
|
7259
7656
|
}),
|
|
7260
|
-
/* @__PURE__ */ jsx(
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
muted: !0,
|
|
7264
|
-
size: 1,
|
|
7265
|
-
style: {
|
|
7266
|
-
whiteSpace: "nowrap"
|
|
7267
|
-
},
|
|
7268
|
-
children: formatShortAgo(at, now)
|
|
7269
|
-
})
|
|
7657
|
+
/* @__PURE__ */ jsx(AgoStamp, {
|
|
7658
|
+
at: at,
|
|
7659
|
+
now: now
|
|
7270
7660
|
}) ]
|
|
7271
7661
|
});
|
|
7272
7662
|
}
|
|
@@ -7318,12 +7708,9 @@ function HistoryRow({entry: entry, now: now, titles: titles}) {
|
|
|
7318
7708
|
}
|
|
7319
7709
|
|
|
7320
7710
|
function ActorNameSpan({id: id}) {
|
|
7321
|
-
const {name: name} = useUserDisplay(id)
|
|
7711
|
+
const {name: name} = useUserDisplay(id);
|
|
7322
7712
|
/* @__PURE__ */
|
|
7323
|
-
return jsx(
|
|
7324
|
-
style: {
|
|
7325
|
-
fontWeight: font.text.weights.medium
|
|
7326
|
-
},
|
|
7713
|
+
return jsx(InlineEmphasis, {
|
|
7327
7714
|
children: name
|
|
7328
7715
|
});
|
|
7329
7716
|
}
|
|
@@ -7378,8 +7765,7 @@ function InstanceCardMenu({entry: entry, title: title}) {
|
|
|
7378
7765
|
return jsxs(Fragment, {
|
|
7379
7766
|
children: [
|
|
7380
7767
|
/* @__PURE__ */ jsx(MenuButton, {
|
|
7381
|
-
button:
|
|
7382
|
-
/* @__PURE__ */ jsx(Button, {
|
|
7768
|
+
button: /* @__PURE__ */ jsx(Button, {
|
|
7383
7769
|
"aria-label": `More options for ${title}`,
|
|
7384
7770
|
fontSize: 1,
|
|
7385
7771
|
icon: EllipsisHorizontalIcon,
|
|
@@ -7700,8 +8086,7 @@ function StageOverviewCard({overview: overview}) {
|
|
|
7700
8086
|
size: 1,
|
|
7701
8087
|
weight: "medium",
|
|
7702
8088
|
children: overview.title
|
|
7703
|
-
}), overview.description === void 0 ? null :
|
|
7704
|
-
/* @__PURE__ */ jsx(Text, {
|
|
8089
|
+
}), overview.description === void 0 ? null : /* @__PURE__ */ jsx(Text, {
|
|
7705
8090
|
muted: !0,
|
|
7706
8091
|
size: 1,
|
|
7707
8092
|
style: {
|
|
@@ -7731,7 +8116,6 @@ function StageOverviewCard({overview: overview}) {
|
|
|
7731
8116
|
}
|
|
7732
8117
|
|
|
7733
8118
|
function AdvanceCard({advance: advance}) {
|
|
7734
|
-
const {font: font} = useTheme_v2();
|
|
7735
8119
|
/* @__PURE__ */
|
|
7736
8120
|
return jsx(Card, {
|
|
7737
8121
|
padding: 3,
|
|
@@ -7743,14 +8127,10 @@ function AdvanceCard({advance: advance}) {
|
|
|
7743
8127
|
/* @__PURE__ */ jsxs(Text, {
|
|
7744
8128
|
size: 1,
|
|
7745
8129
|
children: [ "Advances to ",
|
|
7746
|
-
/* @__PURE__ */ jsx(
|
|
7747
|
-
style: {
|
|
7748
|
-
fontWeight: font.text.weights.medium
|
|
7749
|
-
},
|
|
8130
|
+
/* @__PURE__ */ jsx(InlineEmphasis, {
|
|
7750
8131
|
children: advance.toTitle
|
|
7751
8132
|
}), ADVANCE_TAILS[advance.kind] ]
|
|
7752
|
-
}), advance.kind !== "conditions" ? null : advance.lines.map((line, index) =>
|
|
7753
|
-
/* @__PURE__ */ jsx(Text, {
|
|
8133
|
+
}), advance.kind !== "conditions" ? null : advance.lines.map((line, index) => /* @__PURE__ */ jsx(Text, {
|
|
7754
8134
|
muted: !0,
|
|
7755
8135
|
size: 1,
|
|
7756
8136
|
style: {
|
|
@@ -8804,8 +9184,7 @@ const VIEW_TAB_CODEC = workflowsTabCodec([ "overview", "for-me" ]), WorkflowsVie
|
|
|
8804
9184
|
children: /* @__PURE__ */ jsx(InvalidDocNotice, {
|
|
8805
9185
|
invalid: discoveryInvalid
|
|
8806
9186
|
})
|
|
8807
|
-
}) : resolved ?
|
|
8808
|
-
/* @__PURE__ */ jsx(Flex, {
|
|
9187
|
+
}) : resolved ? /* @__PURE__ */ jsx(Flex, {
|
|
8809
9188
|
direction: "column",
|
|
8810
9189
|
height: "fill",
|
|
8811
9190
|
padding: 4,
|
|
@@ -8854,7 +9233,7 @@ function DiscoverySpinner() {
|
|
|
8854
9233
|
});
|
|
8855
9234
|
}
|
|
8856
9235
|
|
|
8857
|
-
const
|
|
9236
|
+
const GROUP_GAP = 2;
|
|
8858
9237
|
|
|
8859
9238
|
function useWorkflowsTab() {
|
|
8860
9239
|
const {params: params, setParams: setParams} = usePaneRouter();
|
|
@@ -8879,7 +9258,7 @@ function useOpenActivity(entries) {
|
|
|
8879
9258
|
}
|
|
8880
9259
|
|
|
8881
9260
|
function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappings: docTypeMappings, initialValue: initialValue}) {
|
|
8882
|
-
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 =
|
|
9261
|
+
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, identityOf(identity)), [landing] = useState(() => focusedLanding(params?.[WORKFLOWS_FOCUS_PARAM], entries.map(e => e.instance._id))), assignedWorkUnknown = active.some(e => e.invalid !== void 0), booting = active.some(e => !e.ready && e.invalid === void 0), sectionFor = e => /* @__PURE__ */ jsx(WorkflowInstanceSection, {
|
|
8883
9262
|
defaultOpen: landingDefaultOpen(landing, e.instance._id),
|
|
8884
9263
|
entry: e,
|
|
8885
9264
|
onOpenActivity: activityName => setOpenActivity({
|
|
@@ -9107,7 +9486,10 @@ function resolveEntry(args) {
|
|
|
9107
9486
|
}
|
|
9108
9487
|
valid.push(name), definition && definitions.push({
|
|
9109
9488
|
name: name,
|
|
9110
|
-
fields: definition.fields
|
|
9489
|
+
fields: definition.fields,
|
|
9490
|
+
...definition.roleAliases === void 0 ? {} : {
|
|
9491
|
+
roleAliases: definition.roleAliases
|
|
9492
|
+
}
|
|
9111
9493
|
});
|
|
9112
9494
|
}
|
|
9113
9495
|
return {
|
|
@@ -9624,6 +10006,7 @@ function WorkflowProvider(props) {
|
|
|
9624
10006
|
engine: engine,
|
|
9625
10007
|
binding: binding,
|
|
9626
10008
|
mappings: mappings,
|
|
10009
|
+
previewHydration: config.previewHydration,
|
|
9627
10010
|
mappingIssues: issues,
|
|
9628
10011
|
mappingStarts: starts,
|
|
9629
10012
|
mappingFields: fields,
|
|
@@ -9631,7 +10014,7 @@ function WorkflowProvider(props) {
|
|
|
9631
10014
|
effectHandlers: engine.effectHandlers,
|
|
9632
10015
|
autoStartByType: autoStartByType,
|
|
9633
10016
|
autoStartDefinitions: autoStartDefinitions
|
|
9634
|
-
}), [ 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 ]);
|
|
10017
|
+
}), [ register, unregister, isDocResolved, entriesStore, actualTypes, requestInstance, releaseInstance, requestEvaluation, releaseEvaluation, seedInstance, openStartDialog, closeStartDialog, startRequest2, loading, discoveryInvalid, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding, mappings, config.previewHydration, issues, starts, fields, latestVersions, autoStartByType, autoStartDefinitions ]);
|
|
9635
10018
|
/* @__PURE__ */
|
|
9636
10019
|
return jsxs(WorkflowContext.Provider, {
|
|
9637
10020
|
value: value,
|
|
@@ -9733,7 +10116,7 @@ function logOnce(messages, logged) {
|
|
|
9733
10116
|
for (const message of messages) logged.has(message) || (logged.add(message), console.warn(`[workflow-studio-plugin] ${message}`));
|
|
9734
10117
|
}
|
|
9735
10118
|
|
|
9736
|
-
function AssigneesInput({value: value, onChange: onChange}) {
|
|
10119
|
+
function AssigneesInput({value: value, onChange: onChange, eligibleRoles: eligibleRoles, roleAliases: roleAliases}) {
|
|
9737
10120
|
const [open, setOpen] = useState(!1), remove = index => onChange(value.filter((_, i) => i !== index));
|
|
9738
10121
|
/* @__PURE__ */
|
|
9739
10122
|
return jsxs(Stack, {
|
|
@@ -9767,7 +10150,9 @@ function AssigneesInput({value: value, onChange: onChange}) {
|
|
|
9767
10150
|
wrap: "wrap",
|
|
9768
10151
|
children: /* @__PURE__ */ jsx(DismissablePopover, {
|
|
9769
10152
|
content: /* @__PURE__ */ jsx(AssigneePicker, {
|
|
10153
|
+
eligibleRoles: eligibleRoles,
|
|
9770
10154
|
onChange: next => onChange([ ...next ]),
|
|
10155
|
+
roleAliases: roleAliases,
|
|
9771
10156
|
value: value
|
|
9772
10157
|
}),
|
|
9773
10158
|
onDismiss: () => setOpen(!1),
|
|
@@ -9836,11 +10221,29 @@ function ChecklistInput({value: value, onChange: onChange}) {
|
|
|
9836
10221
|
});
|
|
9837
10222
|
}
|
|
9838
10223
|
|
|
9839
|
-
function
|
|
9840
|
-
|
|
10224
|
+
function titleOf(release) {
|
|
10225
|
+
return release.metadata.title ?? release.name;
|
|
10226
|
+
}
|
|
10227
|
+
|
|
10228
|
+
function useReleaseTitles() {
|
|
10229
|
+
const {data: data} = useActiveReleases();
|
|
10230
|
+
return useMemo(() => new Map(data.map(release => [ release.name, titleOf(release) ])), [ data ]);
|
|
10231
|
+
}
|
|
10232
|
+
|
|
10233
|
+
function useActiveReleaseOptions() {
|
|
10234
|
+
const {data: data, loading: loading, error: error} = useActiveReleases(), releases = useMemo(() => data.filter(release => release.state === "active").map(release => ({
|
|
9841
10235
|
name: release.name,
|
|
9842
|
-
title: release
|
|
9843
|
-
})).toSorted((a, b) => a.title.localeCompare(b.title)), [ data ])
|
|
10236
|
+
title: titleOf(release)
|
|
10237
|
+
})).toSorted((a, b) => a.title.localeCompare(b.title)), [ data ]);
|
|
10238
|
+
return {
|
|
10239
|
+
error: error,
|
|
10240
|
+
loading: loading,
|
|
10241
|
+
releases: releases
|
|
10242
|
+
};
|
|
10243
|
+
}
|
|
10244
|
+
|
|
10245
|
+
function ReleasePicker({value: value, onChange: onChange}) {
|
|
10246
|
+
const {binding: binding} = useWorkflowContext(), {error: error, loading: loading, releases: releases} = useActiveReleaseOptions(), labelOf = useMemo(() => {
|
|
9844
10247
|
const m = new Map(releases.map(r => [ r.name, r.title ]));
|
|
9845
10248
|
return name => m.get(name) ?? name;
|
|
9846
10249
|
}, [ releases ]);
|
|
@@ -10108,8 +10511,10 @@ const docRefInput = ({entry: entry, docType: docType, releaseId: releaseId, valu
|
|
|
10108
10511
|
onChange: onChange,
|
|
10109
10512
|
value: value ?? []
|
|
10110
10513
|
}),
|
|
10111
|
-
assignees: ({value: value, onChange: onChange}) => /* @__PURE__ */ jsx(AssigneesInput, {
|
|
10514
|
+
assignees: ({entry: entry, roleAliases: roleAliases, value: value, onChange: onChange}) => /* @__PURE__ */ jsx(AssigneesInput, {
|
|
10515
|
+
eligibleRoles: entry.roles,
|
|
10112
10516
|
onChange: onChange,
|
|
10517
|
+
roleAliases: roleAliases,
|
|
10113
10518
|
value: value ?? []
|
|
10114
10519
|
}),
|
|
10115
10520
|
array: ({entry: entry, value: value, onChange: onChange}) => {
|
|
@@ -10151,7 +10556,7 @@ function FieldInput(props) {
|
|
|
10151
10556
|
});
|
|
10152
10557
|
}
|
|
10153
10558
|
|
|
10154
|
-
function InitFieldRow({entry: entry, docType: docType, releaseId: releaseId, value: value, onChange: onChange}) {
|
|
10559
|
+
function InitFieldRow({entry: entry, docType: docType, releaseId: releaseId, roleAliases: roleAliases, value: value, onChange: onChange}) {
|
|
10155
10560
|
const label = entry.title ?? entry.name;
|
|
10156
10561
|
/* @__PURE__ */
|
|
10157
10562
|
return jsxs(Stack, {
|
|
@@ -10175,6 +10580,7 @@ function InitFieldRow({entry: entry, docType: docType, releaseId: releaseId, val
|
|
|
10175
10580
|
entry: entry,
|
|
10176
10581
|
onChange: onChange,
|
|
10177
10582
|
releaseId: releaseId,
|
|
10583
|
+
roleAliases: roleAliases,
|
|
10178
10584
|
value: value
|
|
10179
10585
|
}) ]
|
|
10180
10586
|
});
|
|
@@ -10224,7 +10630,7 @@ function StartFooter({canStart: canStart, starting: starting, startLabel: startL
|
|
|
10224
10630
|
});
|
|
10225
10631
|
}
|
|
10226
10632
|
|
|
10227
|
-
function StartInputList({initFields: initFields, mapping: mapping, releaseId: releaseId, values: values, onChange: onChange}) {
|
|
10633
|
+
function StartInputList({initFields: initFields, mapping: mapping, releaseId: releaseId, roleAliases: roleAliases, values: values, onChange: onChange}) {
|
|
10228
10634
|
return initFields.length === 0 ? /* @__PURE__ */ jsx(Text, {
|
|
10229
10635
|
muted: !0,
|
|
10230
10636
|
size: 1,
|
|
@@ -10235,6 +10641,7 @@ function StartInputList({initFields: initFields, mapping: mapping, releaseId: re
|
|
|
10235
10641
|
entry: entry,
|
|
10236
10642
|
onChange: v => onChange(entry.name, v),
|
|
10237
10643
|
releaseId: releaseId,
|
|
10644
|
+
roleAliases: roleAliases,
|
|
10238
10645
|
value: values[entry.name] ?? null
|
|
10239
10646
|
}, entry.name))
|
|
10240
10647
|
});
|
|
@@ -10365,6 +10772,7 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
|
10365
10772
|
mapping: mapping,
|
|
10366
10773
|
onChange: setValue,
|
|
10367
10774
|
releaseId: releaseId,
|
|
10775
|
+
roleAliases: definition.roleAliases,
|
|
10368
10776
|
values: values
|
|
10369
10777
|
}),
|
|
10370
10778
|
/* @__PURE__ */ jsx(StartFooter, {
|
|
@@ -10419,11 +10827,12 @@ function AutoStartInputDialog(props) {
|
|
|
10419
10827
|
}),
|
|
10420
10828
|
/* @__PURE__ */ jsx(Stack, {
|
|
10421
10829
|
gap: 4,
|
|
10422
|
-
children: inputs.map(({entry: entry}) => /* @__PURE__ */ jsx(InitFieldRow, {
|
|
10830
|
+
children: inputs.map(({entry: entry, roleAliases: roleAliases}) => /* @__PURE__ */ jsx(InitFieldRow, {
|
|
10423
10831
|
docType: docType,
|
|
10424
10832
|
entry: entry,
|
|
10425
10833
|
onChange: value => setValue(entry.name, value),
|
|
10426
10834
|
releaseId: void 0,
|
|
10835
|
+
roleAliases: roleAliases,
|
|
10427
10836
|
value: values[entry.name] ?? null
|
|
10428
10837
|
}, entry.name))
|
|
10429
10838
|
}),
|
|
@@ -10452,23 +10861,65 @@ function subjectEntry(definition) {
|
|
|
10452
10861
|
return documentSubjectEntry(definition);
|
|
10453
10862
|
}
|
|
10454
10863
|
|
|
10455
|
-
function
|
|
10864
|
+
function autoStartInputPlan(args) {
|
|
10456
10865
|
const byName = /* @__PURE__ */ new Map;
|
|
10457
10866
|
for (const name of args.workflows) {
|
|
10458
10867
|
const definition = args.definitions.get(name);
|
|
10459
10868
|
if (definition !== void 0) for (const entry of extraRequiredInputs(definition)) {
|
|
10460
|
-
const
|
|
10461
|
-
existing === void 0 ? byName.set(entry.name, {
|
|
10869
|
+
const conflict = mergeAutoStartInput(byName, {
|
|
10462
10870
|
entry: entry,
|
|
10463
|
-
|
|
10464
|
-
|
|
10871
|
+
workflow: name,
|
|
10872
|
+
roleAliases: definition.roleAliases
|
|
10873
|
+
});
|
|
10874
|
+
if (conflict !== void 0) return {
|
|
10875
|
+
inputs: [],
|
|
10876
|
+
conflict: conflict
|
|
10877
|
+
};
|
|
10465
10878
|
}
|
|
10466
10879
|
}
|
|
10467
|
-
return
|
|
10880
|
+
return {
|
|
10881
|
+
inputs: [ ...byName.values() ]
|
|
10882
|
+
};
|
|
10883
|
+
}
|
|
10884
|
+
|
|
10885
|
+
function mergeAutoStartInput(byName, args) {
|
|
10886
|
+
const existing = byName.get(args.entry.name);
|
|
10887
|
+
if (existing === void 0) {
|
|
10888
|
+
byName.set(args.entry.name, {
|
|
10889
|
+
entry: args.entry,
|
|
10890
|
+
workflows: [ args.workflow ],
|
|
10891
|
+
...args.roleAliases === void 0 ? {} : {
|
|
10892
|
+
roleAliases: args.roleAliases
|
|
10893
|
+
}
|
|
10894
|
+
});
|
|
10895
|
+
return;
|
|
10896
|
+
}
|
|
10897
|
+
if (!sameRoleSet(existing.entry.roles, args.entry.roles)) return `Auto-start input "${args.entry.name}" is shared by workflows "${existing.workflows.join('", "')}" and "${args.workflow}" with different role constraints`;
|
|
10898
|
+
existing.workflows.push(args.workflow), sameRoleAliases(existing.roleAliases, args.roleAliases) || delete existing.roleAliases;
|
|
10899
|
+
}
|
|
10900
|
+
|
|
10901
|
+
function sameRoleSet(left, right) {
|
|
10902
|
+
return roleSetKey(left) === roleSetKey(right);
|
|
10903
|
+
}
|
|
10904
|
+
|
|
10905
|
+
function roleSetKey(roles) {
|
|
10906
|
+
return roles === void 0 ? void 0 : JSON.stringify(sortedUnique(roles));
|
|
10907
|
+
}
|
|
10908
|
+
|
|
10909
|
+
function sameRoleAliases(left, right) {
|
|
10910
|
+
return roleAliasesKey(left) === roleAliasesKey(right);
|
|
10911
|
+
}
|
|
10912
|
+
|
|
10913
|
+
function roleAliasesKey(aliases) {
|
|
10914
|
+
if (aliases !== void 0) return JSON.stringify(Object.entries(aliases).map(([role, fulfillers]) => [ role, sortedUnique(fulfillers) ]).toSorted(([left], [right]) => left.localeCompare(right)));
|
|
10915
|
+
}
|
|
10916
|
+
|
|
10917
|
+
function sortedUnique(values) {
|
|
10918
|
+
return [ ...new Set(values) ].toSorted();
|
|
10468
10919
|
}
|
|
10469
10920
|
|
|
10470
10921
|
function autoStartAction(args) {
|
|
10471
|
-
return args.fired ? args.settled ? "reveal" : "starting" : args.pendingCount === 0 ? "reveal" : args.resolved ? args.needsInput ? "collect" : "silent-start" : "wait";
|
|
10922
|
+
return args.fired ? args.settled ? "reveal" : "starting" : args.blocked || args.pendingCount === 0 ? "reveal" : args.resolved ? args.needsInput ? "collect" : "silent-start" : "wait";
|
|
10472
10923
|
}
|
|
10473
10924
|
|
|
10474
10925
|
function pendingWorkflows(workflows, live) {
|
|
@@ -10525,10 +10976,14 @@ function AutoStartDriver(props) {
|
|
|
10525
10976
|
engine: engine
|
|
10526
10977
|
}), {selectedReleaseId: selectedReleaseId} = usePerspective(), {entries: entries} = useWorkflowsForDocument(rawDocId), docId = getPublishedId(rawDocId), valueRef = useRef(value);
|
|
10527
10978
|
valueRef.current = value;
|
|
10528
|
-
const pending = useMemo(() => pendingWorkflows(workflows, new Set(entries.map(entry => entry.instance.definition))), [ workflows, entries ]),
|
|
10979
|
+
const pending = useMemo(() => pendingWorkflows(workflows, new Set(entries.map(entry => entry.instance.definition))), [ workflows, entries ]), inputPlan = useMemo(() => autoStartInputPlan({
|
|
10529
10980
|
workflows: pending,
|
|
10530
10981
|
definitions: autoStartDefinitions
|
|
10531
|
-
}), [ pending, autoStartDefinitions ]),
|
|
10982
|
+
}), [ pending, autoStartDefinitions ]), inputs = inputPlan.inputs;
|
|
10983
|
+
useEffect(() => {
|
|
10984
|
+
inputPlan.conflict !== void 0 && console.warn(`[Workflows] Auto-start skipped. ${inputPlan.conflict}`);
|
|
10985
|
+
}, [ inputPlan.conflict ]);
|
|
10986
|
+
const definitionsResolved = workflows.every(name => autoStartDefinitions.has(name)), pendingRef = useRef(pending);
|
|
10532
10987
|
pendingRef.current = pending;
|
|
10533
10988
|
const instanceIds = useRef(/* @__PURE__ */ new Map), instanceIdFor = useCallback(workflow => {
|
|
10534
10989
|
const held = instanceIds.current.get(workflow);
|
|
@@ -10580,6 +11035,7 @@ function AutoStartDriver(props) {
|
|
|
10580
11035
|
resolved: definitionsResolved && isDocResolved(docId),
|
|
10581
11036
|
pendingCount: pending.length,
|
|
10582
11037
|
needsInput: inputs.length > 0,
|
|
11038
|
+
blocked: inputPlan.conflict !== void 0,
|
|
10583
11039
|
fired: fired,
|
|
10584
11040
|
settled: settled
|
|
10585
11041
|
});
|
|
@@ -10822,6 +11278,28 @@ function unassignedLineHint(args) {
|
|
|
10822
11278
|
};
|
|
10823
11279
|
}
|
|
10824
11280
|
|
|
11281
|
+
function taskCountState(args) {
|
|
11282
|
+
const {entry: entry, identity: identity} = args, freshness = entry.invalid === void 0 ? evaluationFreshness({
|
|
11283
|
+
committed: entry.committed,
|
|
11284
|
+
evaluation: entry.evaluation
|
|
11285
|
+
}) : void 0;
|
|
11286
|
+
return identity.kind === "unavailable" ? {
|
|
11287
|
+
kind: "unknowable"
|
|
11288
|
+
} : identity.kind === "pending" || freshness === "pending" ? {
|
|
11289
|
+
kind: "pending"
|
|
11290
|
+
} : freshness === "stale" ? {
|
|
11291
|
+
kind: "stale"
|
|
11292
|
+
} : {
|
|
11293
|
+
kind: "ready",
|
|
11294
|
+
tasks: assignedTaskCount({
|
|
11295
|
+
instance: entry.instance,
|
|
11296
|
+
committed: entry.committed,
|
|
11297
|
+
evaluation: entry.evaluation,
|
|
11298
|
+
who: identity.identity
|
|
11299
|
+
})
|
|
11300
|
+
};
|
|
11301
|
+
}
|
|
11302
|
+
|
|
10825
11303
|
function WorkflowFormStrip(props) {
|
|
10826
11304
|
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 => {
|
|
10827
11305
|
telemetry.log(WorkflowFormStripClicked), setParams(focusedViewParams(params, focusId));
|
|
@@ -10909,7 +11387,7 @@ function InstanceLine({entry: entry, onOpen: onOpen}) {
|
|
|
10909
11387
|
aside: unprimed ? void 0 : /* @__PURE__ */ jsx(TaskCountSpinner, {
|
|
10910
11388
|
entry: entry
|
|
10911
11389
|
}),
|
|
10912
|
-
hint: lineHint(entry, identity),
|
|
11390
|
+
hint: lineHint(entry, identityOf(identity)),
|
|
10913
11391
|
onOpen: onOpen,
|
|
10914
11392
|
children: [
|
|
10915
11393
|
/* @__PURE__ */ jsx(Flex, {
|
|
@@ -10968,28 +11446,16 @@ function finishedHint(instance) {
|
|
|
10968
11446
|
}
|
|
10969
11447
|
|
|
10970
11448
|
function useTaskCountState(entry) {
|
|
10971
|
-
const identity = useAssignmentIdentity()
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
kind: "pending"
|
|
10977
|
-
} : freshness === "stale" ? {
|
|
10978
|
-
kind: "stale"
|
|
10979
|
-
} : {
|
|
10980
|
-
kind: "ready",
|
|
10981
|
-
tasks: assignedTaskCount({
|
|
10982
|
-
instance: entry.instance,
|
|
10983
|
-
committed: entry.committed,
|
|
10984
|
-
evaluation: entry.evaluation,
|
|
10985
|
-
who: identity
|
|
10986
|
-
})
|
|
10987
|
-
};
|
|
11449
|
+
const identity = useAssignmentIdentity();
|
|
11450
|
+
return taskCountState({
|
|
11451
|
+
entry: entry,
|
|
11452
|
+
identity: identity
|
|
11453
|
+
});
|
|
10988
11454
|
}
|
|
10989
11455
|
|
|
10990
11456
|
function TaskCountText({entry: entry}) {
|
|
10991
11457
|
const state = useTaskCountState(entry);
|
|
10992
|
-
return state.kind === "pending" || state.kind === "ready" && state.tasks === 0 ? null : /* @__PURE__ */ jsx(Text, {
|
|
11458
|
+
return state.kind === "pending" || state.kind === "unknowable" || state.kind === "ready" && state.tasks === 0 ? null : /* @__PURE__ */ jsx(Text, {
|
|
10993
11459
|
muted: !0,
|
|
10994
11460
|
size: 1,
|
|
10995
11461
|
children: state.kind === "stale" ? "Updating…" : pluralize("assigned task", state.tasks, !0)
|
|
@@ -11015,19 +11481,13 @@ function StartWorkflowDialogHost() {
|
|
|
11015
11481
|
}
|
|
11016
11482
|
|
|
11017
11483
|
const TOOL_TAB_LABELS = {
|
|
11018
|
-
overview: "
|
|
11019
|
-
"
|
|
11020
|
-
|
|
11484
|
+
overview: "Overview",
|
|
11485
|
+
"for-me": "For me",
|
|
11486
|
+
definitions: "Definitions"
|
|
11021
11487
|
}, TOOL_TAB_VALUES = Object.keys(TOOL_TAB_LABELS), TOOL_TABS = TOOL_TAB_VALUES.map(value => ({
|
|
11022
11488
|
value: value,
|
|
11023
11489
|
label: TOOL_TAB_LABELS[value]
|
|
11024
|
-
})), LANDING_TAB = "overview",
|
|
11025
|
-
workflow: "Documents",
|
|
11026
|
-
definition: "Definition"
|
|
11027
|
-
}, WORKFLOW_PAGE_VALUES = Object.keys(WORKFLOW_PAGE_LABELS), DEFAULT_WORKFLOW_PAGE = "workflow", WORKFLOW_PAGES = WORKFLOW_PAGE_VALUES.filter(page => page !== DEFAULT_WORKFLOW_PAGE), WORKFLOW_PAGE_TABS = WORKFLOW_PAGE_VALUES.map(value => ({
|
|
11028
|
-
value: value,
|
|
11029
|
-
label: WORKFLOW_PAGE_LABELS[value]
|
|
11030
|
-
})), toolRouter = route.create("/", [ route.create("/instance/:instanceId"), route.create(`/${LANDING_TAB}/:workflowName`, [ route.create("/:workflowPage") ]), route.create("/:workflowsTab") ]);
|
|
11490
|
+
})), LANDING_TAB = "overview", DEFINITIONS_TAB = "definitions", toolRouter = route.create("/", [ route.create(`/${DEFINITIONS_TAB}/:workflowName`), route.create("/:workflowsTab") ]);
|
|
11031
11491
|
|
|
11032
11492
|
function toolTabState(tab) {
|
|
11033
11493
|
return {
|
|
@@ -11045,39 +11505,17 @@ function workflowState(workflowName) {
|
|
|
11045
11505
|
};
|
|
11046
11506
|
}
|
|
11047
11507
|
|
|
11048
|
-
function instanceState(instanceId) {
|
|
11049
|
-
return {
|
|
11050
|
-
instanceId: instanceId
|
|
11051
|
-
};
|
|
11052
|
-
}
|
|
11053
|
-
|
|
11054
11508
|
function tabSelectionNavigates(current, tab) {
|
|
11055
11509
|
return !(current.kind === "home" && tab === current.tab);
|
|
11056
11510
|
}
|
|
11057
11511
|
|
|
11058
|
-
function toolTabLabel(tab) {
|
|
11059
|
-
return TOOL_TAB_LABELS[tab];
|
|
11060
|
-
}
|
|
11061
|
-
|
|
11062
|
-
function backToTabLabel(tab) {
|
|
11063
|
-
return `Back to ${toolTabLabel(tab)}`;
|
|
11064
|
-
}
|
|
11065
|
-
|
|
11066
|
-
function workflowPageState(page, workflowName) {
|
|
11067
|
-
return page === DEFAULT_WORKFLOW_PAGE ? workflowState(workflowName) : {
|
|
11068
|
-
...workflowState(workflowName),
|
|
11069
|
-
workflowPage: page
|
|
11070
|
-
};
|
|
11071
|
-
}
|
|
11072
|
-
|
|
11073
11512
|
function toolRoute(state) {
|
|
11074
|
-
const {
|
|
11075
|
-
if (typeof
|
|
11076
|
-
kind: "
|
|
11077
|
-
|
|
11078
|
-
tab:
|
|
11513
|
+
const {workflowName: workflowName} = state;
|
|
11514
|
+
if (typeof workflowName == "string") return {
|
|
11515
|
+
kind: "definition",
|
|
11516
|
+
workflowName: workflowName,
|
|
11517
|
+
tab: DEFINITIONS_TAB
|
|
11079
11518
|
};
|
|
11080
|
-
if (typeof workflowName == "string") return workflowRoute(workflowName, state.workflowPage);
|
|
11081
11519
|
const tab = pathSegmentName({
|
|
11082
11520
|
segment: state.workflowsTab,
|
|
11083
11521
|
names: TOOL_TAB_VALUES
|
|
@@ -11091,24 +11529,11 @@ function toolRoute(state) {
|
|
|
11091
11529
|
};
|
|
11092
11530
|
}
|
|
11093
11531
|
|
|
11094
|
-
function
|
|
11095
|
-
if (
|
|
11096
|
-
|
|
11097
|
-
workflowName: workflowName,
|
|
11098
|
-
tab: LANDING_TAB
|
|
11099
|
-
};
|
|
11100
|
-
const page = pathSegmentName({
|
|
11101
|
-
segment: pageSegment,
|
|
11102
|
-
names: WORKFLOW_PAGES
|
|
11103
|
-
});
|
|
11104
|
-
return page === void 0 ? {
|
|
11105
|
-
kind: "unnamed",
|
|
11106
|
-
tab: LANDING_TAB
|
|
11107
|
-
} : {
|
|
11108
|
-
kind: page,
|
|
11109
|
-
workflowName: workflowName,
|
|
11110
|
-
tab: LANDING_TAB
|
|
11532
|
+
function definitionsRouteOf(route2) {
|
|
11533
|
+
if (route2.kind === "definition") return {
|
|
11534
|
+
workflowName: route2.workflowName
|
|
11111
11535
|
};
|
|
11536
|
+
if (route2.kind === "home" && route2.tab === "definitions") return {};
|
|
11112
11537
|
}
|
|
11113
11538
|
|
|
11114
11539
|
const WorkflowsToolRoot = lazy(() => import("./workflows-tool-root.js"));
|
|
@@ -11220,4 +11645,4 @@ function WorkflowRootInput(props) {
|
|
|
11220
11645
|
});
|
|
11221
11646
|
}
|
|
11222
11647
|
|
|
11223
|
-
export { AbortWorkflowDialog, ActivityDetailDialog, ActivityLog,
|
|
11648
|
+
export { AbortWorkflowDialog, ActivityDetailDialog, ActivityLog, AgoStamp, AlertGlyph, CodeChip, CountedHeading, DismissablePopover, DocPreviewLink, DocRefFace, EmptyState, HoverHint, InstanceFaultNote, InstanceSnapshotBody, InvalidDocNotice, LoadingRow, LogEventOnMount, MetaRow, MetricPair, NoteBanner, RUN_SEARCH_PARAM, RoleAssignedNotice, RowAssignees, SpinnerSlot, TOOL_TABS, TabSwitch, UnreadableDocsNote, WORKFLOW_API_VERSION, WorkflowBoardWorkflowSelected, WorkflowDefinitionDetailViewed, WorkflowInstanceDetailViewed, WorkflowTitleSeedDrifted, WorkflowToolOpened, assigneesOf, countBy, definitionFingerprint, definitionsRouteOf, describeError, dueDatesOf, findActivity, formatShortDateTime, formatTimeAgo, gdrLocality, identityOf, instanceBreadcrumb, instanceTitle, isDueDatePast, isEvaluationStale, isLiveEntry, isOpenActivityStatus, landingState, mappingIssueDetail, namesNoDeployedDefinition, openActivityGone, openableSchemaType, parseStoredDateValue, readDeployedDefinitions, stageTitle, tabSelectionNavigates, toolRoute, toolTabState, useAssignmentIdentity, useAvatarSize, useCapTrimFor, useContainerToken, useCurrentUserId, useDefinition, useLogEventOnMount, useMinuteClock, useProjectMembers, useRadiusToken, useReleaseTitles, useSpaceToken, useTextIconSize, useUserDisplays, useWorkflowContext, useWorkflowInstanceEntry, workflowDefaultDocumentNode, workflowState, workflowStudioPlugin, workflowsView };
|