@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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var jsxRuntime = require("react/jsx-runtime"), Timeline = require("@sanity/icons/Timeline"), ui = require("@sanity/ui"), workflowReact = require("@sanity/workflow-react"), react = require("react"), structure = require("sanity/structure"), workflowEngine = require("@sanity/workflow-engine"), Checkmark = require("@sanity/icons/Checkmark"), Close = require("@sanity/icons/Close"), formatDistanceToNow = require("date-fns/formatDistanceToNow"), workflowComponents = require("@sanity/workflow-components"), csm = require("@sanity/client/csm"), telemetry = require("@sanity/telemetry"), workflowStudio = require("@sanity/workflow-studio"), sanity = require("sanity"), Calendar = require("@sanity/icons/Calendar"), User = require("@sanity/icons/User"), Search = require("@sanity/icons/Search"), ChevronRight = require("@sanity/icons/ChevronRight"), Edit = require("@sanity/icons/Edit"), content = require("@sanity/util/content"), InfoOutline = require("@sanity/icons/InfoOutline"), Document = require("@sanity/icons/Document"), WarningOutline = require("@sanity/icons/WarningOutline"), router = require("sanity/router"), types = require("@sanity/types"), Launch = require("@sanity/icons/Launch"), Empty$1 = require("@sanity/icons/Empty"), ErrorFilled = require("@sanity/icons/ErrorFilled"), RemoveCircle = require("@sanity/icons/RemoveCircle"), Add = require("@sanity/icons/Add"), Ulist = require("@sanity/icons/Ulist"), CheckmarkCircle = require("@sanity/icons/CheckmarkCircle"), Bolt = require("@sanity/icons/Bolt"), ChevronDown = require("@sanity/icons/ChevronDown"), pluralize = require("pluralize-esm"), EllipsisHorizontal = require("@sanity/icons/EllipsisHorizontal"), Clock = require("@sanity/icons/Clock"), Cog = require("@sanity/icons/Cog"), ArrowUp = require("@sanity/icons/ArrowUp"),
|
|
3
|
+
var jsxRuntime = require("react/jsx-runtime"), Timeline = require("@sanity/icons/Timeline"), ui = require("@sanity/ui"), workflowReact = require("@sanity/workflow-react"), react = require("react"), structure = require("sanity/structure"), workflowEngine = require("@sanity/workflow-engine"), Checkmark = require("@sanity/icons/Checkmark"), Close = require("@sanity/icons/Close"), formatDistanceToNow = require("date-fns/formatDistanceToNow"), workflowComponents = require("@sanity/workflow-components"), csm = require("@sanity/client/csm"), telemetry = require("@sanity/telemetry"), workflowStudio = require("@sanity/workflow-studio"), sanity = require("sanity"), Calendar = require("@sanity/icons/Calendar"), User = require("@sanity/icons/User"), Search = require("@sanity/icons/Search"), ChevronRight = require("@sanity/icons/ChevronRight"), Edit = require("@sanity/icons/Edit"), content = require("@sanity/util/content"), InfoOutline = require("@sanity/icons/InfoOutline"), Document = require("@sanity/icons/Document"), WarningOutline = require("@sanity/icons/WarningOutline"), router = require("sanity/router"), types = require("@sanity/types"), Launch = require("@sanity/icons/Launch"), ErrorOutline = require("@sanity/icons/ErrorOutline"), Empty$1 = require("@sanity/icons/Empty"), ErrorFilled = require("@sanity/icons/ErrorFilled"), RemoveCircle = require("@sanity/icons/RemoveCircle"), Add = require("@sanity/icons/Add"), Ulist = require("@sanity/icons/Ulist"), CheckmarkCircle = require("@sanity/icons/CheckmarkCircle"), Bolt = require("@sanity/icons/Bolt"), ChevronDown = require("@sanity/icons/ChevronDown"), pluralize = require("pluralize-esm"), EllipsisHorizontal = require("@sanity/icons/EllipsisHorizontal"), Clock = require("@sanity/icons/Clock"), Cog = require("@sanity/icons/Cog"), ArrowUp = require("@sanity/icons/ArrowUp"), rxjs = require("rxjs"), operators = require("rxjs/operators"), Transfer = require("@sanity/icons/Transfer");
|
|
4
4
|
|
|
5
5
|
function _interopDefaultCompat(e) {
|
|
6
6
|
return e && typeof e == "object" && "default" in e ? e : {
|
|
@@ -291,7 +291,7 @@ function landingDefaultOpen(landing, instanceId) {
|
|
|
291
291
|
if (!(landing === void 0 || !landing.instanceIds.includes(instanceId))) return instanceId === landing.focusedId;
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
const WORKFLOWS_TOOL_NAME = "workflows", WORKFLOW_INTENT = "workflow";
|
|
294
|
+
const WORKFLOWS_TOOL_NAME = "workflows", WORKFLOW_INTENT = "workflow", RUN_SEARCH_PARAM = "run";
|
|
295
295
|
|
|
296
296
|
function pathSegmentName(args) {
|
|
297
297
|
return args.names.find(name => name === args.segment);
|
|
@@ -303,9 +303,10 @@ function handlesWorkflowIntent(intent, params) {
|
|
|
303
303
|
|
|
304
304
|
function workflowIntentState(intent, params) {
|
|
305
305
|
const instanceId = params.instanceId;
|
|
306
|
-
return intent
|
|
307
|
-
|
|
308
|
-
|
|
306
|
+
return intent !== WORKFLOW_INTENT || typeof instanceId != "string" ? null : {
|
|
307
|
+
workflowsTab: "overview",
|
|
308
|
+
_searchParams: [ [ RUN_SEARCH_PARAM, instanceId ] ]
|
|
309
|
+
};
|
|
309
310
|
}
|
|
310
311
|
|
|
311
312
|
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);
|
|
@@ -333,16 +334,25 @@ function parseLocalDate(value) {
|
|
|
333
334
|
return parsed2.getFullYear() === year && parsed2.getMonth() === (month ?? NaN) - 1 && parsed2.getDate() === day ? parsed2 : /* @__PURE__ */ new Date(NaN);
|
|
334
335
|
}
|
|
335
336
|
|
|
337
|
+
function storedDateKind(value) {
|
|
338
|
+
return /^\d{4}-\d{2}-\d{2}$/.test(value) ? "date" : "datetime";
|
|
339
|
+
}
|
|
340
|
+
|
|
336
341
|
function parseStoredDateValue(value) {
|
|
337
|
-
if (typeof value
|
|
338
|
-
const kind = /^\d{4}-\d{2}-\d{2}$/.test(value) ? "date" : "datetime";
|
|
339
|
-
return parseDateFieldValue(value, kind);
|
|
342
|
+
if (typeof value == "string") return parseDateFieldValue(value, storedDateKind(value));
|
|
340
343
|
}
|
|
341
344
|
|
|
342
345
|
function serializeDateFieldValue(date, kind) {
|
|
343
346
|
return hasTimeOfDay(kind) ? date.toISOString() : `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
|
|
344
347
|
}
|
|
345
348
|
|
|
349
|
+
function isDueDatePast(value, now) {
|
|
350
|
+
const kind = storedDateKind(value);
|
|
351
|
+
if (!hasTimeOfDay(kind)) return value < serializeDateFieldValue(now, kind);
|
|
352
|
+
const due = parseDateFieldValue(value, kind);
|
|
353
|
+
return due !== void 0 && due.getTime() < now.getTime();
|
|
354
|
+
}
|
|
355
|
+
|
|
346
356
|
class EffectsIncompleteError extends Error {
|
|
347
357
|
reason;
|
|
348
358
|
constructor(reason, options) {
|
|
@@ -393,14 +403,19 @@ function formatTimeAgo(value) {
|
|
|
393
403
|
}
|
|
394
404
|
|
|
395
405
|
function formatShortAgo(value, now) {
|
|
406
|
+
const span = formatShortSpan(value, now);
|
|
407
|
+
return span === "—" ? "—" : span === "now" ? "just now" : `${span} ago`;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function formatShortSpan(value, now) {
|
|
396
411
|
const d = new Date(value);
|
|
397
412
|
if (Number.isNaN(d.getTime())) return "—";
|
|
398
413
|
const seconds = Math.floor((now.getTime() - d.getTime()) / 1e3);
|
|
399
|
-
if (seconds < 60) return "
|
|
414
|
+
if (seconds < 60) return "now";
|
|
400
415
|
const minutes = Math.floor(seconds / 60);
|
|
401
|
-
if (minutes < 60) return `${minutes}m
|
|
416
|
+
if (minutes < 60) return `${minutes}m`;
|
|
402
417
|
const hours = Math.floor(minutes / 60);
|
|
403
|
-
return hours < 24 ? `${hours}h
|
|
418
|
+
return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;
|
|
404
419
|
}
|
|
405
420
|
|
|
406
421
|
function stampFace(verb, at) {
|
|
@@ -523,7 +538,7 @@ function isLiveEntry(entry) {
|
|
|
523
538
|
const isTodoDone = item => item.status === "done", toggledTodoStatus = item => isTodoDone(item) ? "open" : "done";
|
|
524
539
|
|
|
525
540
|
function isTodoOverdue(item, today = /* @__PURE__ */ new Date) {
|
|
526
|
-
return !item.dueDate || isTodoDone(item) ? !1 : item.dueDate
|
|
541
|
+
return !item.dueDate || isTodoDone(item) ? !1 : isDueDatePast(item.dueDate, today);
|
|
527
542
|
}
|
|
528
543
|
|
|
529
544
|
function todoEditKind(patch) {
|
|
@@ -624,7 +639,7 @@ function todoFieldEditability(args) {
|
|
|
624
639
|
}
|
|
625
640
|
|
|
626
641
|
function itemRow(args) {
|
|
627
|
-
const {item: item, items: items, field: field, source: source, ticks: ticks, editability: editability} = args, tick = ticks.get(tickKey(field.name, item._key));
|
|
642
|
+
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;
|
|
628
643
|
return {
|
|
629
644
|
item: item,
|
|
630
645
|
items: items,
|
|
@@ -639,6 +654,9 @@ function itemRow(args) {
|
|
|
639
654
|
...editability.editDisabledReason ? {
|
|
640
655
|
editDisabledReason: editability.editDisabledReason
|
|
641
656
|
} : {},
|
|
657
|
+
...eligibleAssigneeRoles === void 0 ? {} : {
|
|
658
|
+
eligibleAssigneeRoles: eligibleAssigneeRoles
|
|
659
|
+
},
|
|
642
660
|
...tick ? {
|
|
643
661
|
tick: tick
|
|
644
662
|
} : {}
|
|
@@ -844,7 +862,7 @@ function concludesHere(actionEval, activityName) {
|
|
|
844
862
|
return changesOwnStatus(actionEval.action, activityName) || actionEval.firing?.exitsStage === !0;
|
|
845
863
|
}
|
|
846
864
|
|
|
847
|
-
const
|
|
865
|
+
const DECISION_SEMANTIC_FACE = {
|
|
848
866
|
"decision.accept": {
|
|
849
867
|
tone: "positive",
|
|
850
868
|
icon: Checkmark.CheckmarkIcon
|
|
@@ -855,6 +873,15 @@ const SEMANTIC_FACE = {
|
|
|
855
873
|
}
|
|
856
874
|
};
|
|
857
875
|
|
|
876
|
+
function isDecisionSemantic(value) {
|
|
877
|
+
return Object.hasOwn(DECISION_SEMANTIC_FACE, value);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
function decisionSemanticFace(semantics) {
|
|
881
|
+
const semantic = semantics.find(isDecisionSemantic);
|
|
882
|
+
return semantic === void 0 ? void 0 : DECISION_SEMANTIC_FACE[semantic];
|
|
883
|
+
}
|
|
884
|
+
|
|
858
885
|
function actionButtonFace(args) {
|
|
859
886
|
const mode = concludesHere(args.actionEval, args.activityName) ? "default" : "ghost";
|
|
860
887
|
if (actionAdvanceStatus(args.actionEval.action, args.activityName) === "failed") return {
|
|
@@ -862,7 +889,7 @@ function actionButtonFace(args) {
|
|
|
862
889
|
tone: "critical",
|
|
863
890
|
icon: void 0
|
|
864
891
|
};
|
|
865
|
-
const
|
|
892
|
+
const face = decisionSemanticFace(args.actionEval.semantics ?? []);
|
|
866
893
|
return {
|
|
867
894
|
mode: mode,
|
|
868
895
|
tone: face?.tone ?? "default",
|
|
@@ -1029,24 +1056,10 @@ function dateValuesOf(state, matches) {
|
|
|
1029
1056
|
return state.filter(entry => matches(entry._type)).map(entry => entry.value).filter(value => typeof value == "string" && value !== "");
|
|
1030
1057
|
}
|
|
1031
1058
|
|
|
1032
|
-
function datesOf(state) {
|
|
1033
|
-
return dateValuesOf(state, isDateFieldKind);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
1059
|
function dueDatesOf(state) {
|
|
1037
1060
|
return dateValuesOf(state, isDueDateFieldKind);
|
|
1038
1061
|
}
|
|
1039
1062
|
|
|
1040
|
-
function committedRowFace(row) {
|
|
1041
|
-
return {
|
|
1042
|
-
activityName: row.activityName,
|
|
1043
|
-
title: row.title,
|
|
1044
|
-
status: row.status,
|
|
1045
|
-
automated: !1,
|
|
1046
|
-
blocked: !1
|
|
1047
|
-
};
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
1063
|
function activityRowProps(args) {
|
|
1051
1064
|
const {activityEval: activityEval, activityState: activityState, editableFields: editableFields} = args, state = activityState.get(activityEval.activity.name) ?? [], controlArgs = {
|
|
1052
1065
|
activity: activityEval.activity,
|
|
@@ -1145,15 +1158,15 @@ function useWorkflowInstanceEntry(instanceId, options = {}) {
|
|
|
1145
1158
|
}
|
|
1146
1159
|
|
|
1147
1160
|
const WorkflowToolOpened = telemetry.defineEvent({
|
|
1148
|
-
name: "
|
|
1149
|
-
version:
|
|
1161
|
+
name: "Workflows Studio Plugin Tool Opened",
|
|
1162
|
+
version: 3,
|
|
1150
1163
|
description: "The Workflows tool was opened or its tab was switched"
|
|
1151
1164
|
}), WorkflowDocumentViewOpened = telemetry.defineEvent({
|
|
1152
|
-
name: "
|
|
1165
|
+
name: "Workflows Studio Plugin Document View Opened",
|
|
1153
1166
|
version: 1,
|
|
1154
1167
|
description: "The Workflows document view was opened or its tab was switched"
|
|
1155
1168
|
}), WorkflowInstanceDetailViewed = telemetry.defineEvent({
|
|
1156
|
-
name: "
|
|
1169
|
+
name: "Workflows Studio Plugin Instance Detail Viewed",
|
|
1157
1170
|
version: 1,
|
|
1158
1171
|
description: "The Workflows tool's per-instance detail view was opened"
|
|
1159
1172
|
});
|
|
@@ -1166,67 +1179,63 @@ function definitionFingerprint(definition) {
|
|
|
1166
1179
|
}
|
|
1167
1180
|
|
|
1168
1181
|
const WorkflowDefinitionDetailViewed = telemetry.defineEvent({
|
|
1169
|
-
name: "
|
|
1182
|
+
name: "Workflows Studio Plugin Definition Detail Viewed",
|
|
1170
1183
|
version: 1,
|
|
1171
1184
|
description: "A workflow's definition page was opened in the Workflows tool"
|
|
1172
1185
|
}), WorkflowFormStripClicked = telemetry.defineEvent({
|
|
1173
|
-
name: "
|
|
1186
|
+
name: "Workflows Studio Plugin Form Strip Clicked",
|
|
1174
1187
|
version: 1,
|
|
1175
1188
|
description: "The form strip's instance line was clicked, opening the document view"
|
|
1176
1189
|
}), WorkflowDocumentLinkClicked = telemetry.defineEvent({
|
|
1177
|
-
name: "
|
|
1178
|
-
version:
|
|
1190
|
+
name: "Workflows Studio Plugin Document Link Clicked",
|
|
1191
|
+
version: 3,
|
|
1179
1192
|
description: "A document link was clicked, opening the referenced document's editor"
|
|
1180
1193
|
}), WorkflowStartDialogOpened = telemetry.defineEvent({
|
|
1181
|
-
name: "
|
|
1194
|
+
name: "Workflows Studio Plugin Start Dialog Opened",
|
|
1182
1195
|
version: 1,
|
|
1183
1196
|
description: "The start-workflow dialog was opened"
|
|
1184
1197
|
}), WorkflowStartDialogSubmitted = telemetry.defineEvent({
|
|
1185
|
-
name: "
|
|
1198
|
+
name: "Workflows Studio Plugin Start Dialog Submitted",
|
|
1186
1199
|
version: 1,
|
|
1187
1200
|
description: "The start-workflow dialog's confirm was pressed"
|
|
1188
1201
|
}), WorkflowAutoStartRan = telemetry.defineEvent({
|
|
1189
|
-
name: "
|
|
1202
|
+
name: "Workflows Studio Plugin Auto Start Ran",
|
|
1190
1203
|
version: 1,
|
|
1191
1204
|
description: "A fresh document's auto-start ran — one start request per configured workflow"
|
|
1192
1205
|
}), WorkflowActionControlUsed = telemetry.defineEvent({
|
|
1193
|
-
name: "
|
|
1194
|
-
version:
|
|
1206
|
+
name: "Workflows Studio Plugin Action Control Used",
|
|
1207
|
+
version: 3,
|
|
1195
1208
|
description: "An action-firing control was used, attributed to its UI surface"
|
|
1196
1209
|
}), WorkflowFieldControlUsed = telemetry.defineEvent({
|
|
1197
|
-
name: "
|
|
1198
|
-
version:
|
|
1210
|
+
name: "Workflows Studio Plugin Field Control Used",
|
|
1211
|
+
version: 2,
|
|
1199
1212
|
description: "A field-editing control committed an edit, attributed to its UI surface"
|
|
1200
1213
|
}), WorkflowActivityDialogOpened = telemetry.defineEvent({
|
|
1201
|
-
name: "
|
|
1202
|
-
version:
|
|
1214
|
+
name: "Workflows Studio Plugin Activity Dialog Opened",
|
|
1215
|
+
version: 2,
|
|
1203
1216
|
description: "The activity detail dialog was opened"
|
|
1204
|
-
}), WorkflowTaskFiltersApplied = telemetry.defineEvent({
|
|
1205
|
-
name: "Editorial Workflows Studio Plugin Task Filters Applied",
|
|
1206
|
-
version: 1,
|
|
1207
|
-
description: "The tool's task-filter menu closed with a changed selection"
|
|
1208
1217
|
}), WorkflowBoardWorkflowSelected = telemetry.defineEvent({
|
|
1209
|
-
name: "
|
|
1210
|
-
version:
|
|
1211
|
-
description: "The
|
|
1218
|
+
name: "Workflows Studio Plugin Board Workflow Selected",
|
|
1219
|
+
version: 3,
|
|
1220
|
+
description: "The Overview's board display settled on the workflow it's showing"
|
|
1212
1221
|
}), WorkflowTitleSeedDrifted = telemetry.defineEvent({
|
|
1213
|
-
name: "
|
|
1222
|
+
name: "Workflows Studio Plugin Title Seed Drifted",
|
|
1214
1223
|
version: 1,
|
|
1215
1224
|
description: "A cold-start seeded preview title diverged from the live preview pipeline"
|
|
1216
1225
|
}), WorkflowTodoToggled = telemetry.defineEvent({
|
|
1217
|
-
name: "
|
|
1226
|
+
name: "Workflows Studio Plugin Todo Toggled",
|
|
1218
1227
|
version: 1,
|
|
1219
1228
|
description: "A todo checkbox was toggled, attributed to its UI surface and write seam"
|
|
1220
1229
|
}), WorkflowTodoEdited = telemetry.defineEvent({
|
|
1221
|
-
name: "
|
|
1230
|
+
name: "Workflows Studio Plugin Todo Edited",
|
|
1222
1231
|
version: 1,
|
|
1223
1232
|
description: "A non-toggle todo-list write, attributed to its UI surface and gesture"
|
|
1224
1233
|
}), WorkflowAbortDialogOpened = telemetry.defineEvent({
|
|
1225
|
-
name: "
|
|
1234
|
+
name: "Workflows Studio Plugin Abort Dialog Opened",
|
|
1226
1235
|
version: 1,
|
|
1227
1236
|
description: "The abort-workflow confirm was opened"
|
|
1228
1237
|
}), WorkflowAbortDialogSubmitted = telemetry.defineEvent({
|
|
1229
|
-
name: "
|
|
1238
|
+
name: "Workflows Studio Plugin Abort Dialog Submitted",
|
|
1230
1239
|
version: 1,
|
|
1231
1240
|
description: "The abort-workflow confirm was submitted, carrying the attempt's outcome"
|
|
1232
1241
|
});
|
|
@@ -1262,6 +1271,12 @@ function scalarValidationIssue(args) {
|
|
|
1262
1271
|
return issues === void 0 ? void 0 : `${args.label}: ${issues.join("; ")}`;
|
|
1263
1272
|
}
|
|
1264
1273
|
|
|
1274
|
+
function countBy(rows, keysOf) {
|
|
1275
|
+
const counts = /* @__PURE__ */ new Map;
|
|
1276
|
+
for (const row of rows) for (const key of keysOf(row)) counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
1277
|
+
return counts;
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1265
1280
|
function personActor(user) {
|
|
1266
1281
|
const roles = user.roles.map(role => typeof role == "string" ? role : role.name);
|
|
1267
1282
|
return {
|
|
@@ -1293,10 +1308,16 @@ function userDisplayFor(args) {
|
|
|
1293
1308
|
return {
|
|
1294
1309
|
id: args.id,
|
|
1295
1310
|
name: member?.displayName ?? self?.name ?? args.id,
|
|
1296
|
-
imageUrl: member?.imageUrl ?? self?.profileImage ?? void 0
|
|
1311
|
+
imageUrl: member?.imageUrl ?? self?.profileImage ?? void 0,
|
|
1312
|
+
loginProvider: member?.loginProvider
|
|
1297
1313
|
};
|
|
1298
1314
|
}
|
|
1299
1315
|
|
|
1316
|
+
function disambiguatedNames(displays) {
|
|
1317
|
+
const counts = countBy(displays, display => [ display.name ]);
|
|
1318
|
+
return displays.map(display => (counts.get(display.name) ?? 0) < 2 || display.loginProvider === void 0 ? display.name : `${display.name} (${workflowComponents.providerTitle(display.loginProvider) ?? display.loginProvider})`);
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1300
1321
|
function useUserDisplays(ids) {
|
|
1301
1322
|
const {members: members} = useProjectMembers(), {users: users} = workflowStudio.useStudioProjectUsers(), meRaw = sanity.useCurrentUser(), me = react.useMemo(() => meRaw === null ? null : {
|
|
1302
1323
|
...meRaw,
|
|
@@ -1329,21 +1350,32 @@ function bridgedSelfId(users, meId) {
|
|
|
1329
1350
|
return users.find(user => user.membership.id === meId)?.profile?.sanityUserId ?? classified.globalId ?? (classified.namespace === "project" ? void 0 : meId);
|
|
1330
1351
|
}
|
|
1331
1352
|
|
|
1332
|
-
function
|
|
1353
|
+
function useSelfState() {
|
|
1333
1354
|
const me = sanity.useCurrentUser(), {users: users, loading: loading, error: error} = workflowStudio.useStudioProjectUsers();
|
|
1334
|
-
if (!me) return
|
|
1335
|
-
|
|
1336
|
-
if (id !== void 0) return {
|
|
1337
|
-
id: id,
|
|
1338
|
-
roles: me.roles ?? []
|
|
1355
|
+
if (!me) return {
|
|
1356
|
+
kind: "unavailable"
|
|
1339
1357
|
};
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1358
|
+
const id = bridgedSelfId(users, me.id);
|
|
1359
|
+
return id !== void 0 ? {
|
|
1360
|
+
kind: "resolved",
|
|
1361
|
+
self: {
|
|
1362
|
+
id: id,
|
|
1363
|
+
roles: me.roles ?? []
|
|
1344
1364
|
}
|
|
1345
|
-
|
|
1346
|
-
|
|
1365
|
+
} : loading ? {
|
|
1366
|
+
kind: "pending"
|
|
1367
|
+
} : error !== void 0 ? (warnSelfUnavailableOnce(`load:${me.id}`, `workflow: the project member directory failed to load ("${workflowEngine.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.`),
|
|
1368
|
+
{
|
|
1369
|
+
kind: "unavailable"
|
|
1370
|
+
}) : (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.`),
|
|
1371
|
+
{
|
|
1372
|
+
kind: "unavailable"
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
function useBridgedSelf() {
|
|
1377
|
+
const state = useSelfState();
|
|
1378
|
+
return state.kind === "resolved" ? state.self : void 0;
|
|
1347
1379
|
}
|
|
1348
1380
|
|
|
1349
1381
|
function useSelfActor() {
|
|
@@ -1352,13 +1384,26 @@ function useSelfActor() {
|
|
|
1352
1384
|
}
|
|
1353
1385
|
|
|
1354
1386
|
function useAssignmentIdentity() {
|
|
1355
|
-
const
|
|
1356
|
-
if (
|
|
1357
|
-
|
|
1358
|
-
|
|
1387
|
+
const state = useSelfState();
|
|
1388
|
+
if (state.kind !== "resolved") return state;
|
|
1389
|
+
const {id: id, roles: roles} = state.self;
|
|
1390
|
+
return {
|
|
1391
|
+
kind: "resolved",
|
|
1392
|
+
identity: {
|
|
1393
|
+
userId: id,
|
|
1394
|
+
roles: roles.map(r => r.name)
|
|
1395
|
+
}
|
|
1359
1396
|
};
|
|
1360
1397
|
}
|
|
1361
1398
|
|
|
1399
|
+
function identityOf(state) {
|
|
1400
|
+
return state.kind === "resolved" ? state.identity : void 0;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
function useCurrentUserId() {
|
|
1404
|
+
return identityOf(useAssignmentIdentity())?.userId;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1362
1407
|
const projectMembersByUsers = /* @__PURE__ */ new WeakMap;
|
|
1363
1408
|
|
|
1364
1409
|
function projectMembersFrom(users) {
|
|
@@ -1466,6 +1511,8 @@ function buildParams(decls, values) {
|
|
|
1466
1511
|
};
|
|
1467
1512
|
}
|
|
1468
1513
|
|
|
1514
|
+
const LOADING_CUE_DELAY_MS = 400;
|
|
1515
|
+
|
|
1469
1516
|
function useDelayedFlag(active, delayMs) {
|
|
1470
1517
|
const [held, setHeld] = react.useState(!1);
|
|
1471
1518
|
return react.useEffect(() => {
|
|
@@ -1747,23 +1794,27 @@ function MemberPicker({selectedIds: selectedIds, onSelect: onSelect, unassignRow
|
|
|
1747
1794
|
});
|
|
1748
1795
|
}
|
|
1749
1796
|
|
|
1750
|
-
function AssigneePicker({value: value, onChange: onChange}) {
|
|
1797
|
+
function AssigneePicker({value: value, onChange: onChange, eligibleRoles: eligibleRoles, roleAliases: roleAliases}) {
|
|
1751
1798
|
const state = useProjectMembers();
|
|
1752
1799
|
/* @__PURE__ */
|
|
1753
1800
|
return jsxRuntime.jsx(workflowComponents.AssigneePicker, {
|
|
1754
1801
|
...state,
|
|
1802
|
+
eligibleRoles: eligibleRoles,
|
|
1755
1803
|
onChange: onChange,
|
|
1804
|
+
roleAliases: roleAliases,
|
|
1756
1805
|
value: value
|
|
1757
1806
|
});
|
|
1758
1807
|
}
|
|
1759
1808
|
|
|
1760
|
-
function SingleAssigneePicker({current: current, onPick: onPick}) {
|
|
1809
|
+
function SingleAssigneePicker({current: current, onPick: onPick, eligibleRoles: eligibleRoles, roleAliases: roleAliases}) {
|
|
1761
1810
|
/* @__PURE__ */
|
|
1762
1811
|
return jsxRuntime.jsx(AssigneePicker, {
|
|
1812
|
+
eligibleRoles: eligibleRoles,
|
|
1763
1813
|
onChange: next => {
|
|
1764
1814
|
const picked = singleAssigneePick(current, next);
|
|
1765
1815
|
picked !== void 0 && onPick(picked);
|
|
1766
1816
|
},
|
|
1817
|
+
roleAliases: roleAliases,
|
|
1767
1818
|
value: current ? [ current ] : []
|
|
1768
1819
|
});
|
|
1769
1820
|
}
|
|
@@ -2076,7 +2127,6 @@ const TOAST_ID = {
|
|
|
2076
2127
|
effectResolve: "workflow-effect-resolve",
|
|
2077
2128
|
effectsDrain: "workflow-effects-drain",
|
|
2078
2129
|
effectsIncomplete: "workflow-effects-incomplete",
|
|
2079
|
-
orphanSettle: "workflow-orphan-settle",
|
|
2080
2130
|
start: "workflow-start"
|
|
2081
2131
|
};
|
|
2082
2132
|
|
|
@@ -2473,15 +2523,14 @@ function Separator() {
|
|
|
2473
2523
|
}
|
|
2474
2524
|
|
|
2475
2525
|
function stageTitle(definition, stageName) {
|
|
2476
|
-
return
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
return args.definition?.stages.find(s => s.name === args.stageName)?.activities?.find(a => a.name === args.activityName);
|
|
2526
|
+
return workflowEngine.findStageNode({
|
|
2527
|
+
definition: definition,
|
|
2528
|
+
stageName: stageName
|
|
2529
|
+
})?.title ?? stageName;
|
|
2481
2530
|
}
|
|
2482
2531
|
|
|
2483
2532
|
function findActivity(args) {
|
|
2484
|
-
const activity = findActivityNode(args);
|
|
2533
|
+
const activity = workflowEngine.findActivityNode(args);
|
|
2485
2534
|
return {
|
|
2486
2535
|
title: activity?.title ?? args.activityName,
|
|
2487
2536
|
description: activity?.description
|
|
@@ -2937,8 +2986,7 @@ function PendingDocFace({bareId: bareId, layout: layout}) {
|
|
|
2937
2986
|
children: id
|
|
2938
2987
|
});
|
|
2939
2988
|
}
|
|
2940
|
-
return compact ?
|
|
2941
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
2989
|
+
return compact ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
2942
2990
|
align: "center",
|
|
2943
2991
|
gap: 2,
|
|
2944
2992
|
children: [
|
|
@@ -3612,9 +3660,11 @@ function AssigneeField({field: field, instanceId: instanceId, onSave: onSave, on
|
|
|
3612
3660
|
children: /* @__PURE__ */ jsxRuntime.jsx(DismissablePopover, {
|
|
3613
3661
|
content: /* @__PURE__ */ jsxRuntime.jsx(SingleAssigneePicker, {
|
|
3614
3662
|
current: cur,
|
|
3663
|
+
eligibleRoles: field.roles,
|
|
3615
3664
|
onPick: picked => {
|
|
3616
3665
|
setOpen(!1), pick(picked);
|
|
3617
|
-
}
|
|
3666
|
+
},
|
|
3667
|
+
roleAliases: field.roleAliases
|
|
3618
3668
|
}),
|
|
3619
3669
|
onDismiss: () => setOpen(!1),
|
|
3620
3670
|
open: open,
|
|
@@ -3945,6 +3995,267 @@ function EditableField({field: field, entry: entry, description: description, in
|
|
|
3945
3995
|
});
|
|
3946
3996
|
}
|
|
3947
3997
|
|
|
3998
|
+
function useDrainEffects(instanceId) {
|
|
3999
|
+
const {drainEffectsFor: drainEffectsFor} = useWorkflowContext(), toast = useWorkflowToast(), [busy, setBusy] = react.useState(!1);
|
|
4000
|
+
return {
|
|
4001
|
+
busy: busy,
|
|
4002
|
+
run: async () => {
|
|
4003
|
+
setBusy(!0);
|
|
4004
|
+
try {
|
|
4005
|
+
await drainEffectsFor(instanceId), toast.push({
|
|
4006
|
+
id: TOAST_ID.effectsDrain,
|
|
4007
|
+
status: "info",
|
|
4008
|
+
title: "Ran the registered handlers"
|
|
4009
|
+
});
|
|
4010
|
+
} catch (err) {
|
|
4011
|
+
toast.push({
|
|
4012
|
+
id: TOAST_ID.effectsDrain,
|
|
4013
|
+
status: "error",
|
|
4014
|
+
title: "Failed to run pending effects",
|
|
4015
|
+
description: describeError(err)
|
|
4016
|
+
});
|
|
4017
|
+
} finally {
|
|
4018
|
+
setBusy(!1);
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
};
|
|
4022
|
+
}
|
|
4023
|
+
|
|
4024
|
+
function isRunnable(verb) {
|
|
4025
|
+
return verb === "drain-effects";
|
|
4026
|
+
}
|
|
4027
|
+
|
|
4028
|
+
function effectLabel(effect) {
|
|
4029
|
+
return effect.title ?? effect.name;
|
|
4030
|
+
}
|
|
4031
|
+
|
|
4032
|
+
const ACTION_LABEL = {
|
|
4033
|
+
"drain-effects": "Run the step again"
|
|
4034
|
+
}, REMEDY_TEXT = {
|
|
4035
|
+
"retry-effect": "The step has to run again before this workflow can continue.",
|
|
4036
|
+
"reset-activity": "Reset the task to try it again, or skip it.",
|
|
4037
|
+
"set-stage": "Move the workflow on to its next stage yourself."
|
|
4038
|
+
};
|
|
4039
|
+
|
|
4040
|
+
function detailOf(cause) {
|
|
4041
|
+
switch (cause.kind) {
|
|
4042
|
+
case "failed-effect":
|
|
4043
|
+
return `The step “${effectLabel(cause.effect)}” failed`;
|
|
4044
|
+
|
|
4045
|
+
case "hung-effect":
|
|
4046
|
+
return `The step “${effectLabel(cause.effect)}” didn’t finish`;
|
|
4047
|
+
|
|
4048
|
+
case "failed-activity":
|
|
4049
|
+
return "This task failed";
|
|
4050
|
+
|
|
4051
|
+
default:
|
|
4052
|
+
return summaryOf(cause);
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4055
|
+
|
|
4056
|
+
function summaryOf(cause) {
|
|
4057
|
+
switch (cause.kind) {
|
|
4058
|
+
case "failed-effect":
|
|
4059
|
+
return "An automated step failed";
|
|
4060
|
+
|
|
4061
|
+
case "hung-effect":
|
|
4062
|
+
return "An automated step didn’t finish";
|
|
4063
|
+
|
|
4064
|
+
case "failed-activity":
|
|
4065
|
+
return "A task failed";
|
|
4066
|
+
|
|
4067
|
+
case "no-transition-fires":
|
|
4068
|
+
return "Every task is done, but nothing moves this workflow on";
|
|
4069
|
+
|
|
4070
|
+
case "transition-unevaluable":
|
|
4071
|
+
return "This workflow is waiting on something it can’t read yet, and will move on by itself";
|
|
4072
|
+
}
|
|
4073
|
+
}
|
|
4074
|
+
|
|
4075
|
+
function activityDeclaringEffect(args) {
|
|
4076
|
+
return workflowEngine.findStageNode(args)?.activities?.find(activity => (activity.actions ?? []).some(action => (action.effects ?? []).some(effect => effect.name === args.effectName)))?.name;
|
|
4077
|
+
}
|
|
4078
|
+
|
|
4079
|
+
function faultingActivity(args) {
|
|
4080
|
+
const {cause: cause} = args;
|
|
4081
|
+
if (cause.kind === "failed-activity") return cause.activity;
|
|
4082
|
+
if (cause.kind === "failed-effect" || cause.kind === "hung-effect") return activityDeclaringEffect({
|
|
4083
|
+
definition: args.definition,
|
|
4084
|
+
effectName: cause.effect.name,
|
|
4085
|
+
stageName: args.stageName
|
|
4086
|
+
});
|
|
4087
|
+
}
|
|
4088
|
+
|
|
4089
|
+
function isRecoverable(cause) {
|
|
4090
|
+
return cause.kind === "transition-unevaluable";
|
|
4091
|
+
}
|
|
4092
|
+
|
|
4093
|
+
function diagnosisOf(args) {
|
|
4094
|
+
if (args.evaluation !== void 0) return workflowEngine.diagnoseInstance(workflowEngine.diagnoseInputFromEvaluation(args.evaluation));
|
|
4095
|
+
const cause = workflowEngine.documentStuckCause({
|
|
4096
|
+
instance: args.instance,
|
|
4097
|
+
definition: args.definition
|
|
4098
|
+
});
|
|
4099
|
+
return cause === void 0 ? void 0 : {
|
|
4100
|
+
state: "stuck",
|
|
4101
|
+
cause: cause
|
|
4102
|
+
};
|
|
4103
|
+
}
|
|
4104
|
+
|
|
4105
|
+
function instanceFault(args) {
|
|
4106
|
+
const diagnosis = diagnosisOf(args);
|
|
4107
|
+
if (diagnosis === void 0 || diagnosis.state !== "stuck") return;
|
|
4108
|
+
const verbs = workflowEngine.remediationsFor(diagnosis).map(remediation2 => remediation2.verb);
|
|
4109
|
+
return {
|
|
4110
|
+
activity: faultingActivity({
|
|
4111
|
+
cause: diagnosis.cause,
|
|
4112
|
+
definition: args.definition,
|
|
4113
|
+
stageName: args.instance.currentStage
|
|
4114
|
+
}),
|
|
4115
|
+
detail: detailOf(diagnosis.cause),
|
|
4116
|
+
summary: summaryOf(diagnosis.cause),
|
|
4117
|
+
remedies: verbs.flatMap(verb => REMEDY_TEXT[verb] ?? []),
|
|
4118
|
+
actions: verbs.flatMap(verb => isRunnable(verb) ? [ {
|
|
4119
|
+
verb: verb,
|
|
4120
|
+
label: ACTION_LABEL[verb]
|
|
4121
|
+
} ] : []),
|
|
4122
|
+
recoverable: isRecoverable(diagnosis.cause)
|
|
4123
|
+
};
|
|
4124
|
+
}
|
|
4125
|
+
|
|
4126
|
+
function looksLikeDefinition(value) {
|
|
4127
|
+
return typeof value == "object" && value !== null && Array.isArray(value.stages);
|
|
4128
|
+
}
|
|
4129
|
+
|
|
4130
|
+
const parsed = /* @__PURE__ */ new WeakMap;
|
|
4131
|
+
|
|
4132
|
+
function definitionSnapshotOf(instance) {
|
|
4133
|
+
if (parsed.has(instance)) return parsed.get(instance);
|
|
4134
|
+
let definition;
|
|
4135
|
+
try {
|
|
4136
|
+
const candidate = workflowEngine.parseDefinitionSnapshot(instance);
|
|
4137
|
+
if (!looksLikeDefinition(candidate)) throw new Error(`definitionSnapshot on "${instance._id}" parsed to a non-definition shape`);
|
|
4138
|
+
definition = candidate;
|
|
4139
|
+
} catch (err) {
|
|
4140
|
+
console.error("[workflow-studio-plugin] unreadable definitionSnapshot:", err), definition = void 0;
|
|
4141
|
+
}
|
|
4142
|
+
return parsed.set(instance, definition), definition;
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4145
|
+
function useDefinition(entry) {
|
|
4146
|
+
return react.useMemo(() => {
|
|
4147
|
+
if (entry) return entry.evaluation ? entry.evaluation.definition : definitionSnapshotOf(entry.instance);
|
|
4148
|
+
}, [ entry ]);
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4151
|
+
function AbortedBadge({instance: instance}) {
|
|
4152
|
+
return workflowEngine.terminalState(instance) !== "aborted" ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, {
|
|
4153
|
+
fontSize: 1,
|
|
4154
|
+
tone: "critical",
|
|
4155
|
+
children: "Aborted"
|
|
4156
|
+
});
|
|
4157
|
+
}
|
|
4158
|
+
|
|
4159
|
+
function OlderDefinitionBadge({instance: instance}) {
|
|
4160
|
+
const {latestDefinitionVersions: latestDefinitionVersions} = useWorkflowContext(), latest = latestDefinitionVersions.get(instance.definition);
|
|
4161
|
+
return latest === void 0 || latest <= instance.pinnedVersion ? null : /* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
4162
|
+
description: "Running workflows keep the version they started on",
|
|
4163
|
+
text: `Started on v${instance.pinnedVersion}, latest is now v${latest}`,
|
|
4164
|
+
textWeight: "medium",
|
|
4165
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, {
|
|
4166
|
+
fontSize: 1,
|
|
4167
|
+
tone: "caution",
|
|
4168
|
+
children: "Older version"
|
|
4169
|
+
})
|
|
4170
|
+
});
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
function useInstanceFault(entry) {
|
|
4174
|
+
return instanceFault({
|
|
4175
|
+
definition: useDefinition(entry),
|
|
4176
|
+
evaluation: entry.evaluation,
|
|
4177
|
+
instance: entry.instance
|
|
4178
|
+
});
|
|
4179
|
+
}
|
|
4180
|
+
|
|
4181
|
+
function InstanceFaultNote({entry: entry, scope: scope}) {
|
|
4182
|
+
const fault = useInstanceFault(entry);
|
|
4183
|
+
if (fault === void 0 || scope.kind === "task" && fault.activity !== scope.activityName) return null;
|
|
4184
|
+
const Icon = fault.recoverable ? WarningOutline.WarningOutlineIcon : ErrorOutline.ErrorOutlineIcon;
|
|
4185
|
+
/* @__PURE__ */
|
|
4186
|
+
return jsxRuntime.jsx(ui.Card, {
|
|
4187
|
+
padding: 3,
|
|
4188
|
+
radius: 3,
|
|
4189
|
+
tone: fault.recoverable ? "caution" : "critical",
|
|
4190
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
4191
|
+
align: "flex-start",
|
|
4192
|
+
gap: 3,
|
|
4193
|
+
children: [
|
|
4194
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
4195
|
+
size: 1,
|
|
4196
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {})
|
|
4197
|
+
}),
|
|
4198
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
4199
|
+
flex: 1,
|
|
4200
|
+
gap: 3,
|
|
4201
|
+
children: [
|
|
4202
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
4203
|
+
size: 1,
|
|
4204
|
+
weight: "medium",
|
|
4205
|
+
children: scope.kind === "run" ? fault.summary : fault.detail
|
|
4206
|
+
}), scope.kind === "run" ? /* @__PURE__ */ jsxRuntime.jsx(RunControl, {
|
|
4207
|
+
activity: fault.activity,
|
|
4208
|
+
onOpenActivity: scope.onOpenActivity
|
|
4209
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(TaskControls, {
|
|
4210
|
+
actions: fault.actions,
|
|
4211
|
+
instanceId: entry.instance._id,
|
|
4212
|
+
remedies: fault.remedies
|
|
4213
|
+
}) ]
|
|
4214
|
+
}) ]
|
|
4215
|
+
})
|
|
4216
|
+
});
|
|
4217
|
+
}
|
|
4218
|
+
|
|
4219
|
+
function RunControl({activity: activity, onOpenActivity: onOpenActivity}) {
|
|
4220
|
+
return activity === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
4221
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
4222
|
+
fontSize: 1,
|
|
4223
|
+
mode: "ghost",
|
|
4224
|
+
onClick: () => onOpenActivity(activity),
|
|
4225
|
+
padding: 2,
|
|
4226
|
+
text: "View task"
|
|
4227
|
+
})
|
|
4228
|
+
});
|
|
4229
|
+
}
|
|
4230
|
+
|
|
4231
|
+
const RUN_VERB = {
|
|
4232
|
+
"drain-effects": drain => drain.run()
|
|
4233
|
+
};
|
|
4234
|
+
|
|
4235
|
+
function TaskControls({actions: actions, instanceId: instanceId, remedies: remedies}) {
|
|
4236
|
+
const drain = useDrainEffects(instanceId);
|
|
4237
|
+
/* @__PURE__ */
|
|
4238
|
+
return jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
4239
|
+
children: [ remedies.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
4240
|
+
muted: !0,
|
|
4241
|
+
size: 1,
|
|
4242
|
+
children: remedies.join(" ")
|
|
4243
|
+
}), actions.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
4244
|
+
gap: 2,
|
|
4245
|
+
children: actions.map(action => /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
4246
|
+
disabled: drain.busy,
|
|
4247
|
+
fontSize: 1,
|
|
4248
|
+
mode: "ghost",
|
|
4249
|
+
onClick: () => {
|
|
4250
|
+
RUN_VERB[action.verb](drain);
|
|
4251
|
+
},
|
|
4252
|
+
padding: 2,
|
|
4253
|
+
text: action.label
|
|
4254
|
+
}, action.verb))
|
|
4255
|
+
}) ]
|
|
4256
|
+
});
|
|
4257
|
+
}
|
|
4258
|
+
|
|
3948
4259
|
function MetaRow({children: children, fillHeight: fillHeight, label: label}) {
|
|
3949
4260
|
/* @__PURE__ */
|
|
3950
4261
|
return jsxRuntime.jsxs(ui.Flex, {
|
|
@@ -4032,6 +4343,12 @@ function useSpaceToken(index) {
|
|
|
4032
4343
|
return value;
|
|
4033
4344
|
}
|
|
4034
4345
|
|
|
4346
|
+
function useRadiusToken(index) {
|
|
4347
|
+
const value = ui.useTheme_v2().radius[index];
|
|
4348
|
+
if (value === void 0) throw new Error(`theme is missing radius token ${index}`);
|
|
4349
|
+
return value;
|
|
4350
|
+
}
|
|
4351
|
+
|
|
4035
4352
|
function useContainerToken(index) {
|
|
4036
4353
|
const value = ui.useTheme_v2().container[index];
|
|
4037
4354
|
if (value === void 0) throw new Error(`theme is missing container token ${index}`);
|
|
@@ -4072,10 +4389,9 @@ function useBadgeCapTrim() {
|
|
|
4072
4389
|
};
|
|
4073
4390
|
}
|
|
4074
4391
|
|
|
4075
|
-
function SpinnerSlot({busy: busy}) {
|
|
4076
|
-
const size = useTextIconSize(), trim = useCapTrimFor(size);
|
|
4077
|
-
/* @__PURE__ */
|
|
4078
|
-
return jsxRuntime.jsx(ui.Flex, {
|
|
4392
|
+
function SpinnerSlot({busy: busy, reserve: reserve = !0}) {
|
|
4393
|
+
const size = useTextIconSize(), trim = useCapTrimFor(size), spinning = useDelayedFlag(busy, LOADING_CUE_DELAY_MS);
|
|
4394
|
+
return !spinning && !reserve ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
4079
4395
|
align: "center",
|
|
4080
4396
|
flex: "none",
|
|
4081
4397
|
justify: "center",
|
|
@@ -4085,7 +4401,7 @@ function SpinnerSlot({busy: busy}) {
|
|
|
4085
4401
|
marginTop: trim,
|
|
4086
4402
|
width: size
|
|
4087
4403
|
},
|
|
4088
|
-
children:
|
|
4404
|
+
children: spinning ? /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {
|
|
4089
4405
|
muted: !0,
|
|
4090
4406
|
size: 1
|
|
4091
4407
|
}) : null
|
|
@@ -4093,6 +4409,7 @@ function SpinnerSlot({busy: busy}) {
|
|
|
4093
4409
|
}
|
|
4094
4410
|
|
|
4095
4411
|
function LoadingRow({label: label, padding: padding}) {
|
|
4412
|
+
const announced = useDelayedFlag(!0, LOADING_CUE_DELAY_MS);
|
|
4096
4413
|
/* @__PURE__ */
|
|
4097
4414
|
return jsxRuntime.jsxs(ui.Flex, {
|
|
4098
4415
|
align: "center",
|
|
@@ -4103,12 +4420,11 @@ function LoadingRow({label: label, padding: padding}) {
|
|
|
4103
4420
|
children: [
|
|
4104
4421
|
/* @__PURE__ */ jsxRuntime.jsx(SpinnerSlot, {
|
|
4105
4422
|
busy: !0
|
|
4106
|
-
}),
|
|
4107
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
4423
|
+
}), announced ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
4108
4424
|
muted: !0,
|
|
4109
4425
|
size: 1,
|
|
4110
4426
|
children: label
|
|
4111
|
-
}) ]
|
|
4427
|
+
}) : null ]
|
|
4112
4428
|
});
|
|
4113
4429
|
}
|
|
4114
4430
|
|
|
@@ -4169,8 +4485,7 @@ function RowAssignees({assignees: assignees, hint: hint}) {
|
|
|
4169
4485
|
const bothKinds = roles.length > 0 && displays.length > 0;
|
|
4170
4486
|
/* @__PURE__ */
|
|
4171
4487
|
return jsxRuntime.jsx(HoverHint, {
|
|
4172
|
-
content:
|
|
4173
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
4488
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
4174
4489
|
gap: 3,
|
|
4175
4490
|
children: [ roles.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(HintSection, {
|
|
4176
4491
|
names: roles.map(workflowComponents.roleLabel),
|
|
@@ -4178,7 +4493,7 @@ function RowAssignees({assignees: assignees, hint: hint}) {
|
|
|
4178
4493
|
label: "Roles"
|
|
4179
4494
|
} : {}
|
|
4180
4495
|
}) : null, displays.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(HintSection, {
|
|
4181
|
-
names: displays
|
|
4496
|
+
names: disambiguatedNames(displays),
|
|
4182
4497
|
...bothKinds ? {
|
|
4183
4498
|
label: "Members"
|
|
4184
4499
|
} : {}
|
|
@@ -4257,8 +4572,7 @@ function AssignActivityControl({instanceId: instanceId, state: state, surface: s
|
|
|
4257
4572
|
}
|
|
4258
4573
|
}, handleClick = e => {
|
|
4259
4574
|
e.stopPropagation(), setOpen(v => !v);
|
|
4260
|
-
}, button = assignees.length > 0 ?
|
|
4261
|
-
/* @__PURE__ */ jsxRuntime.jsx(AvatarButton, {
|
|
4575
|
+
}, button = assignees.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(AvatarButton, {
|
|
4262
4576
|
"aria-label": "Assignees",
|
|
4263
4577
|
as: "span",
|
|
4264
4578
|
avatar: /* @__PURE__ */ jsxRuntime.jsx(RowAssignees, {
|
|
@@ -4288,9 +4602,11 @@ function AssignActivityControl({instanceId: instanceId, state: state, surface: s
|
|
|
4288
4602
|
label: "Loading…",
|
|
4289
4603
|
padding: 3
|
|
4290
4604
|
}) : /* @__PURE__ */ jsxRuntime.jsx(AssigneePicker, {
|
|
4605
|
+
eligibleRoles: state.field.roles,
|
|
4291
4606
|
onChange: next => {
|
|
4292
4607
|
change(next);
|
|
4293
4608
|
},
|
|
4609
|
+
roleAliases: state.field.roleAliases,
|
|
4294
4610
|
value: current
|
|
4295
4611
|
})
|
|
4296
4612
|
}),
|
|
@@ -4375,49 +4691,39 @@ function ForMeEmptyState() {
|
|
|
4375
4691
|
});
|
|
4376
4692
|
}
|
|
4377
4693
|
|
|
4378
|
-
|
|
4379
|
-
return typeof value == "object" && value !== null && Array.isArray(value.stages);
|
|
4380
|
-
}
|
|
4381
|
-
|
|
4382
|
-
const parsed = /* @__PURE__ */ new WeakMap;
|
|
4383
|
-
|
|
4384
|
-
function definitionSnapshotOf(instance) {
|
|
4385
|
-
if (parsed.has(instance)) return parsed.get(instance);
|
|
4386
|
-
let definition;
|
|
4387
|
-
try {
|
|
4388
|
-
const candidate = workflowEngine.parseDefinitionSnapshot(instance);
|
|
4389
|
-
if (!looksLikeDefinition(candidate)) throw new Error(`definitionSnapshot on "${instance._id}" parsed to a non-definition shape`);
|
|
4390
|
-
definition = candidate;
|
|
4391
|
-
} catch (err) {
|
|
4392
|
-
console.error("[workflow-studio-plugin] unreadable definitionSnapshot:", err), definition = void 0;
|
|
4393
|
-
}
|
|
4394
|
-
return parsed.set(instance, definition), definition;
|
|
4395
|
-
}
|
|
4694
|
+
const OVERDUE_HINT = "Now overdue";
|
|
4396
4695
|
|
|
4397
|
-
function
|
|
4398
|
-
return
|
|
4399
|
-
|
|
4400
|
-
}
|
|
4696
|
+
function hintFace(args) {
|
|
4697
|
+
return args.overdue ? args.reason === void 0 ? {
|
|
4698
|
+
text: OVERDUE_HINT
|
|
4699
|
+
} : {
|
|
4700
|
+
text: OVERDUE_HINT,
|
|
4701
|
+
description: args.reason
|
|
4702
|
+
} : args.reason === void 0 ? void 0 : {
|
|
4703
|
+
text: args.reason
|
|
4704
|
+
};
|
|
4401
4705
|
}
|
|
4402
4706
|
|
|
4403
|
-
function
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4707
|
+
function DueDate({dueDate: dueDate, hintDisabled: hintDisabled, overdue: overdue, reason: reason}) {
|
|
4708
|
+
const face = hintFace({
|
|
4709
|
+
overdue: overdue,
|
|
4710
|
+
reason: reason
|
|
4711
|
+
}), text = overdue ? /* @__PURE__ */ jsxRuntime.jsx(sanity.TextWithTone, {
|
|
4712
|
+
size: 1,
|
|
4713
|
+
tone: "caution",
|
|
4714
|
+
children: formatDate(dueDate)
|
|
4715
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
4716
|
+
muted: !0,
|
|
4717
|
+
size: 1,
|
|
4718
|
+
children: formatDate(dueDate)
|
|
4408
4719
|
});
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
textWeight: "medium",
|
|
4417
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, {
|
|
4418
|
-
fontSize: 1,
|
|
4419
|
-
tone: "caution",
|
|
4420
|
-
children: "Older version"
|
|
4720
|
+
return face === void 0 ? text :
|
|
4721
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
4722
|
+
align: "center",
|
|
4723
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
4724
|
+
...face,
|
|
4725
|
+
disabled: hintDisabled === !0,
|
|
4726
|
+
children: text
|
|
4421
4727
|
})
|
|
4422
4728
|
});
|
|
4423
4729
|
}
|
|
@@ -4457,18 +4763,6 @@ function CheckboxSlot({children: children}) {
|
|
|
4457
4763
|
});
|
|
4458
4764
|
}
|
|
4459
4765
|
|
|
4460
|
-
function DueDateText({dueDate: dueDate, overdue: overdue}) {
|
|
4461
|
-
return overdue ? /* @__PURE__ */ jsxRuntime.jsx(sanity.TextWithTone, {
|
|
4462
|
-
size: 1,
|
|
4463
|
-
tone: "caution",
|
|
4464
|
-
children: formatDate(dueDate)
|
|
4465
|
-
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
4466
|
-
muted: !0,
|
|
4467
|
-
size: 1,
|
|
4468
|
-
children: formatDate(dueDate)
|
|
4469
|
-
});
|
|
4470
|
-
}
|
|
4471
|
-
|
|
4472
4766
|
function DueDateEditor({dueDate: dueDate, onDone: onDone, onPatch: onPatch}) {
|
|
4473
4767
|
/* @__PURE__ */
|
|
4474
4768
|
return jsxRuntime.jsx(workflowComponents.ClearableDatePicker, {
|
|
@@ -4488,8 +4782,9 @@ function DueDateEditor({dueDate: dueDate, onDone: onDone, onPatch: onPatch}) {
|
|
|
4488
4782
|
}
|
|
4489
4783
|
|
|
4490
4784
|
function DueDateControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
4491
|
-
const [open, setOpen] = react.useState(!1), overdue = isTodoOverdue(item), display = item.dueDate ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4785
|
+
const [open, setOpen] = react.useState(!1), overdue = isTodoOverdue(item), display = item.dueDate ? /* @__PURE__ */ jsxRuntime.jsx(DueDate, {
|
|
4492
4786
|
dueDate: item.dueDate,
|
|
4787
|
+
hintDisabled: open,
|
|
4493
4788
|
overdue: overdue
|
|
4494
4789
|
}) : null;
|
|
4495
4790
|
return editable ? /* @__PURE__ */ jsxRuntime.jsx(DismissablePopover, {
|
|
@@ -4500,18 +4795,14 @@ function DueDateControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
|
4500
4795
|
}),
|
|
4501
4796
|
onDismiss: () => setOpen(!1),
|
|
4502
4797
|
open: open,
|
|
4503
|
-
children: display ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
padding: 2,
|
|
4512
|
-
tone: overdue ? "caution" : "default",
|
|
4513
|
-
children: display
|
|
4514
|
-
})
|
|
4798
|
+
children: display ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
4799
|
+
"aria-label": "Change due date",
|
|
4800
|
+
fontSize: 1,
|
|
4801
|
+
mode: "bleed",
|
|
4802
|
+
onClick: () => setOpen(v => !v),
|
|
4803
|
+
padding: 2,
|
|
4804
|
+
tone: overdue ? "caution" : "default",
|
|
4805
|
+
children: display
|
|
4515
4806
|
}) : /* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
4516
4807
|
disabled: open,
|
|
4517
4808
|
text: "Set due date",
|
|
@@ -4525,13 +4816,10 @@ function DueDateControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
|
4525
4816
|
radius: 2
|
|
4526
4817
|
})
|
|
4527
4818
|
})
|
|
4528
|
-
}) : display && overdue ? /* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
4529
|
-
text: "Now overdue",
|
|
4530
|
-
children: display
|
|
4531
4819
|
}) : display;
|
|
4532
4820
|
}
|
|
4533
4821
|
|
|
4534
|
-
function AssigneeControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
4822
|
+
function AssigneeControl({item: item, editable: editable, eligibleRoles: eligibleRoles, onPatch: onPatch, roleAliases: roleAliases}) {
|
|
4535
4823
|
const [open, setOpen] = react.useState(!1), current = item.assignee ?? null, chip = current ? /* @__PURE__ */ jsxRuntime.jsx(RowAssignees, {
|
|
4536
4824
|
assignees: [ current ]
|
|
4537
4825
|
}) : null;
|
|
@@ -4539,11 +4827,13 @@ function AssigneeControl({item: item, editable: editable, onPatch: onPatch}) {
|
|
|
4539
4827
|
content:
|
|
4540
4828
|
/* @__PURE__ */ jsxRuntime.jsx(SingleAssigneePicker, {
|
|
4541
4829
|
current: current,
|
|
4830
|
+
eligibleRoles: eligibleRoles,
|
|
4542
4831
|
onPick: picked => {
|
|
4543
4832
|
setOpen(!1), onPatch({
|
|
4544
4833
|
assignee: picked
|
|
4545
4834
|
});
|
|
4546
|
-
}
|
|
4835
|
+
},
|
|
4836
|
+
roleAliases: roleAliases
|
|
4547
4837
|
}),
|
|
4548
4838
|
onDismiss: () => setOpen(!1),
|
|
4549
4839
|
open: open,
|
|
@@ -4645,8 +4935,7 @@ function BreadcrumbTail({segments: segments, style: style}) {
|
|
|
4645
4935
|
}
|
|
4646
4936
|
|
|
4647
4937
|
function WorkRow({lead: lead, children: children, end: end, onOpen: onOpen}) {
|
|
4648
|
-
const frame =
|
|
4649
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
4938
|
+
const frame = /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
4650
4939
|
align: "center",
|
|
4651
4940
|
children: [
|
|
4652
4941
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
@@ -4680,8 +4969,7 @@ function WorkRow({lead: lead, children: children, end: end, onOpen: onOpen}) {
|
|
|
4680
4969
|
padding: 1,
|
|
4681
4970
|
radius: 3,
|
|
4682
4971
|
children: frame
|
|
4683
|
-
}) :
|
|
4684
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
4972
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
|
|
4685
4973
|
as: "button",
|
|
4686
4974
|
onClick: onOpen,
|
|
4687
4975
|
padding: 1,
|
|
@@ -4693,7 +4981,7 @@ function WorkRow({lead: lead, children: children, end: end, onOpen: onOpen}) {
|
|
|
4693
4981
|
});
|
|
4694
4982
|
}
|
|
4695
4983
|
|
|
4696
|
-
function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle, onPatch: onPatch, onRemove: onRemove}) {
|
|
4984
|
+
function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle, onPatch: onPatch, onRemove: onRemove, roleAliases: roleAliases}) {
|
|
4697
4985
|
const {canClick: canClick, hint: hint} = rowInteractivity(row), editable = row.editTarget !== void 0, checkbox = /* @__PURE__ */ jsxRuntime.jsx(TodoCheckbox, {
|
|
4698
4986
|
canClick: canClick,
|
|
4699
4987
|
checked: isTodoDone(row.item),
|
|
@@ -4710,8 +4998,10 @@ function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle,
|
|
|
4710
4998
|
}),
|
|
4711
4999
|
/* @__PURE__ */ jsxRuntime.jsx(AssigneeControl, {
|
|
4712
5000
|
editable: editable,
|
|
5001
|
+
eligibleRoles: row.eligibleAssigneeRoles,
|
|
4713
5002
|
item: row.item,
|
|
4714
|
-
onPatch: onPatch
|
|
5003
|
+
onPatch: onPatch,
|
|
5004
|
+
roleAliases: roleAliases
|
|
4715
5005
|
}), onRemove === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(RemoveItemButton, {
|
|
4716
5006
|
onClick: onRemove
|
|
4717
5007
|
}) ]
|
|
@@ -4888,6 +5178,7 @@ function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter, sh
|
|
|
4888
5178
|
onToggle: () => {
|
|
4889
5179
|
toggleRow(row);
|
|
4890
5180
|
},
|
|
5181
|
+
roleAliases: definition?.roleAliases,
|
|
4891
5182
|
row: row
|
|
4892
5183
|
}, rowKey(row)))
|
|
4893
5184
|
}), addControl === null ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
@@ -5180,9 +5471,15 @@ function ActivityDetailDialog({entry: entry, activityName: activityName, breadcr
|
|
|
5180
5471
|
const detail = deriveActivityDetail({
|
|
5181
5472
|
entry: entry,
|
|
5182
5473
|
activityName: activityName
|
|
5183
|
-
});
|
|
5474
|
+
}), faultingActivity2 = useInstanceFault(entry)?.activity;
|
|
5184
5475
|
if (!detail) return null;
|
|
5185
|
-
const instanceId = entry.instance._id, notice = blockedNotice(detail),
|
|
5476
|
+
const instanceId = entry.instance._id, notice = blockedNotice(detail), fault = /* @__PURE__ */ jsxRuntime.jsx(InstanceFaultNote, {
|
|
5477
|
+
entry: entry,
|
|
5478
|
+
scope: {
|
|
5479
|
+
kind: "task",
|
|
5480
|
+
activityName: activityName
|
|
5481
|
+
}
|
|
5482
|
+
}), faulted = faultingActivity2 === activityName, hasBody = detail.state.length > 0 || notice !== void 0 || faulted;
|
|
5186
5483
|
/* @__PURE__ */
|
|
5187
5484
|
return jsxRuntime.jsxs(ui.Dialog, {
|
|
5188
5485
|
footer: detail.presentation.terminalActions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(TerminalFooter, {
|
|
@@ -5223,7 +5520,7 @@ function ActivityDetailDialog({entry: entry, activityName: activityName, breadcr
|
|
|
5223
5520
|
padding: 4,
|
|
5224
5521
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, {
|
|
5225
5522
|
gap: 5,
|
|
5226
|
-
children: [ detail.state.map(field => /* @__PURE__ */ jsxRuntime.jsx(FieldRow, {
|
|
5523
|
+
children: [ fault, detail.state.map(field => /* @__PURE__ */ jsxRuntime.jsx(FieldRow, {
|
|
5227
5524
|
activityName: activityName,
|
|
5228
5525
|
detail: detail,
|
|
5229
5526
|
entry: entry,
|
|
@@ -5404,6 +5701,18 @@ function CountedLabel({count: count, label: label}) {
|
|
|
5404
5701
|
});
|
|
5405
5702
|
}
|
|
5406
5703
|
|
|
5704
|
+
function CountedHeading({count: count, title: title}) {
|
|
5705
|
+
/* @__PURE__ */
|
|
5706
|
+
return jsxRuntime.jsx(CountedLabel, {
|
|
5707
|
+
count: count,
|
|
5708
|
+
label: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
5709
|
+
size: 1,
|
|
5710
|
+
weight: "semibold",
|
|
5711
|
+
children: title
|
|
5712
|
+
})
|
|
5713
|
+
});
|
|
5714
|
+
}
|
|
5715
|
+
|
|
5407
5716
|
function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
5408
5717
|
/* @__PURE__ */
|
|
5409
5718
|
return jsxRuntime.jsxs(ui.Flex, {
|
|
@@ -5411,14 +5720,10 @@ function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
|
5411
5720
|
gap: 3,
|
|
5412
5721
|
paddingLeft: 2,
|
|
5413
5722
|
paddingY: end === void 0 ? 3 : 1,
|
|
5414
|
-
children: [
|
|
5415
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5416
|
-
count: count,
|
|
5417
|
-
|
|
5418
|
-
size: 1,
|
|
5419
|
-
weight: "semibold",
|
|
5420
|
-
children: title
|
|
5421
|
-
})
|
|
5723
|
+
children: [
|
|
5724
|
+
/* @__PURE__ */ jsxRuntime.jsx(CountedHeading, {
|
|
5725
|
+
count: count,
|
|
5726
|
+
title: title
|
|
5422
5727
|
}), busy === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(SpinnerSlot, {
|
|
5423
5728
|
busy: busy
|
|
5424
5729
|
}), end === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
@@ -5430,21 +5735,85 @@ function GroupHeading({busy: busy, count: count, title: title, end: end}) {
|
|
|
5430
5735
|
});
|
|
5431
5736
|
}
|
|
5432
5737
|
|
|
5738
|
+
const EMPTY_METRIC_OPACITY = .5;
|
|
5739
|
+
|
|
5740
|
+
function MetricText({children: children, tone: tone}) {
|
|
5741
|
+
return tone === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
5742
|
+
muted: !0,
|
|
5743
|
+
size: 1,
|
|
5744
|
+
children: children
|
|
5745
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx(sanity.TextWithTone, {
|
|
5746
|
+
size: 1,
|
|
5747
|
+
tone: tone,
|
|
5748
|
+
children: children
|
|
5749
|
+
});
|
|
5750
|
+
}
|
|
5751
|
+
|
|
5752
|
+
function MetricPair({Icon: Icon, empty: empty, face: face, tone: tone, value: value}) {
|
|
5753
|
+
/* @__PURE__ */
|
|
5754
|
+
return jsxRuntime.jsx(HoverHint, {
|
|
5755
|
+
...face,
|
|
5756
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, {
|
|
5757
|
+
align: "center",
|
|
5758
|
+
gap: 2,
|
|
5759
|
+
style: empty ? {
|
|
5760
|
+
opacity: EMPTY_METRIC_OPACITY
|
|
5761
|
+
} : void 0,
|
|
5762
|
+
children: [
|
|
5763
|
+
/* @__PURE__ */ jsxRuntime.jsx(MetricText, {
|
|
5764
|
+
tone: tone,
|
|
5765
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {
|
|
5766
|
+
style: {
|
|
5767
|
+
color: "inherit"
|
|
5768
|
+
}
|
|
5769
|
+
})
|
|
5770
|
+
}),
|
|
5771
|
+
/* @__PURE__ */ jsxRuntime.jsx(MetricText, {
|
|
5772
|
+
tone: tone,
|
|
5773
|
+
children: value
|
|
5774
|
+
}) ]
|
|
5775
|
+
})
|
|
5776
|
+
});
|
|
5777
|
+
}
|
|
5778
|
+
|
|
5779
|
+
function AlertGlyph({Icon: Icon, hint: hint, label: label, tone: tone}) {
|
|
5780
|
+
/* @__PURE__ */
|
|
5781
|
+
return jsxRuntime.jsx(HoverHint, {
|
|
5782
|
+
text: hint,
|
|
5783
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(sanity.TextWithTone, {
|
|
5784
|
+
size: 1,
|
|
5785
|
+
tone: tone,
|
|
5786
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {
|
|
5787
|
+
...label === void 0 ? {} : {
|
|
5788
|
+
"aria-label": label,
|
|
5789
|
+
role: "img"
|
|
5790
|
+
},
|
|
5791
|
+
style: {
|
|
5792
|
+
color: "inherit"
|
|
5793
|
+
}
|
|
5794
|
+
})
|
|
5795
|
+
})
|
|
5796
|
+
});
|
|
5797
|
+
}
|
|
5798
|
+
|
|
5433
5799
|
function ActivityDateControl({instanceId: instanceId, state: state, surface: surface, dueDates: dueDates}) {
|
|
5434
5800
|
const editField = useEditField(surface), {save: save} = useSaveField({
|
|
5435
5801
|
instanceId: instanceId
|
|
5436
5802
|
}), [open, setOpen] = react.useState(!1), raw = dateControlValue({
|
|
5437
5803
|
state: state,
|
|
5438
5804
|
dueDates: dueDates
|
|
5439
|
-
}),
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5805
|
+
}), overdue = raw !== void 0 && isDueDatePast(raw, /* @__PURE__ */ new Date), dueDate = reason => raw === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(DueDate, {
|
|
5806
|
+
dueDate: raw,
|
|
5807
|
+
hintDisabled: open,
|
|
5808
|
+
overdue: overdue,
|
|
5809
|
+
...reason === void 0 ? {} : {
|
|
5810
|
+
reason: reason
|
|
5811
|
+
}
|
|
5443
5812
|
});
|
|
5444
|
-
if (state.kind === "none") return
|
|
5445
|
-
if (state.kind === "closed")
|
|
5446
|
-
|
|
5447
|
-
|
|
5813
|
+
if (state.kind === "none") return dueDate();
|
|
5814
|
+
if (state.kind === "closed") {
|
|
5815
|
+
const display = dueDate(state.reason);
|
|
5816
|
+
return display === null ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
5448
5817
|
"aria-label": "Date",
|
|
5449
5818
|
as: "span",
|
|
5450
5819
|
fontSize: 1,
|
|
@@ -5453,8 +5822,8 @@ function ActivityDateControl({instanceId: instanceId, state: state, surface: sur
|
|
|
5453
5822
|
onMouseDown: stopRowMouseDown,
|
|
5454
5823
|
padding: 2,
|
|
5455
5824
|
children: display
|
|
5456
|
-
})
|
|
5457
|
-
}
|
|
5825
|
+
});
|
|
5826
|
+
}
|
|
5458
5827
|
const kind = dateControlKind(state), commit = (mode, value) => {
|
|
5459
5828
|
state.kind === "editable" && save(() => editField({
|
|
5460
5829
|
instanceId: instanceId,
|
|
@@ -5490,7 +5859,7 @@ function ActivityDateControl({instanceId: instanceId, state: state, surface: sur
|
|
|
5490
5859
|
}),
|
|
5491
5860
|
onDismiss: () => setOpen(!1),
|
|
5492
5861
|
open: open,
|
|
5493
|
-
children:
|
|
5862
|
+
children: raw !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
5494
5863
|
"aria-label": "Change date",
|
|
5495
5864
|
as: "span",
|
|
5496
5865
|
fontSize: 1,
|
|
@@ -5498,7 +5867,7 @@ function ActivityDateControl({instanceId: instanceId, state: state, surface: sur
|
|
|
5498
5867
|
onClick: handleClick,
|
|
5499
5868
|
onMouseDown: stopRowMouseDown,
|
|
5500
5869
|
padding: 2,
|
|
5501
|
-
children:
|
|
5870
|
+
children: dueDate()
|
|
5502
5871
|
}) : /* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
5503
5872
|
disabled: open,
|
|
5504
5873
|
text: "Set date",
|
|
@@ -5588,12 +5957,11 @@ function TitleTag({hint: hint, tone: tone, children: children}) {
|
|
|
5588
5957
|
});
|
|
5589
5958
|
}
|
|
5590
5959
|
|
|
5591
|
-
function ActivityRow({face: face, breadcrumb: breadcrumb, assignees: assignees, assignState: assignState, dateState: dateState, dueDates: dueDates, instanceId: instanceId, onOpen: onOpen, surface: surface, terminalActions: terminalActions = []}) {
|
|
5960
|
+
function ActivityRow({face: face, breadcrumb: breadcrumb, assignees: assignees, assignState: assignState, dateState: dateState, dueDates: dueDates, faultHint: faultHint, instanceId: instanceId, onOpen: onOpen, surface: surface, terminalActions: terminalActions = []}) {
|
|
5592
5961
|
const settled = workflowEngine.isTerminalActivityStatus(face.status), dimmed = settledDim(settled);
|
|
5593
5962
|
/* @__PURE__ */
|
|
5594
5963
|
return jsxRuntime.jsxs(WorkRow, {
|
|
5595
|
-
end:
|
|
5596
|
-
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
5964
|
+
end: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
5597
5965
|
children: [
|
|
5598
5966
|
/* @__PURE__ */ jsxRuntime.jsx(ActivityDateControl, {
|
|
5599
5967
|
dueDates: dueDates,
|
|
@@ -5621,6 +5989,10 @@ function ActivityRow({face: face, breadcrumb: breadcrumb, assignees: assignees,
|
|
|
5621
5989
|
/* @__PURE__ */ jsxRuntime.jsx(ActivityRowTitle, {
|
|
5622
5990
|
dimmed: dimmed,
|
|
5623
5991
|
children: face.title
|
|
5992
|
+
}), faultHint === void 0 || face.status === "failed" ? null : /* @__PURE__ */ jsxRuntime.jsx(AlertGlyph, {
|
|
5993
|
+
Icon: ErrorOutline.ErrorOutlineIcon,
|
|
5994
|
+
hint: faultHint,
|
|
5995
|
+
tone: "critical"
|
|
5624
5996
|
}), face.automated ? /* @__PURE__ */ jsxRuntime.jsx(TitleTag, {
|
|
5625
5997
|
hint: "Completes on its own — no user action is needed",
|
|
5626
5998
|
children: "Automated"
|
|
@@ -5636,9 +6008,8 @@ function ActivityRow({face: face, breadcrumb: breadcrumb, assignees: assignees,
|
|
|
5636
6008
|
}
|
|
5637
6009
|
|
|
5638
6010
|
function ActivitiesList({entry: entry, onOpenActivity: onOpenActivity, surface: surface}) {
|
|
5639
|
-
const activities = (entry.evaluation?.currentStage.activities ?? []).filter(t => !t.scopedOut), activityState = stateByActivity(entry.instance);
|
|
5640
|
-
return activities.length === 0 ?
|
|
5641
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
6011
|
+
const activities = (entry.evaluation?.currentStage.activities ?? []).filter(t => !t.scopedOut), activityState = stateByActivity(entry.instance), fault = useInstanceFault(entry);
|
|
6012
|
+
return activities.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, {
|
|
5642
6013
|
paddingX: 1,
|
|
5643
6014
|
paddingY: 3,
|
|
5644
6015
|
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
@@ -5654,6 +6025,9 @@ function ActivitiesList({entry: entry, onOpenActivity: onOpenActivity, surface:
|
|
|
5654
6025
|
activityState: activityState,
|
|
5655
6026
|
editableFields: entry.evaluation?.editableFields
|
|
5656
6027
|
}),
|
|
6028
|
+
...fault?.activity === t.activity.name ? {
|
|
6029
|
+
faultHint: fault.summary
|
|
6030
|
+
} : {},
|
|
5657
6031
|
instanceId: entry.instance._id,
|
|
5658
6032
|
onOpen: () => onOpenActivity(t.activity.name),
|
|
5659
6033
|
surface: surface
|
|
@@ -5663,8 +6037,7 @@ function ActivitiesList({entry: entry, onOpenActivity: onOpenActivity, surface:
|
|
|
5663
6037
|
|
|
5664
6038
|
function instanceNotice(entry) {
|
|
5665
6039
|
const {instance: instance, committed: committed, evaluation: evaluation} = entry, state = workflowEngine.terminalState(instance);
|
|
5666
|
-
if (state !== "in-flight")
|
|
5667
|
-
/* @__PURE__ */
|
|
6040
|
+
if (state !== "in-flight") /* @__PURE__ */
|
|
5668
6041
|
return jsxRuntime.jsx(ui.Box, {
|
|
5669
6042
|
paddingX: 1,
|
|
5670
6043
|
paddingY: 2,
|
|
@@ -5800,7 +6173,10 @@ function progressFillPercent(face) {
|
|
|
5800
6173
|
}
|
|
5801
6174
|
|
|
5802
6175
|
function deriveFieldPills(args) {
|
|
5803
|
-
const {scope: scope, definition: definition, instance: instance, committed: committed, evaluation: evaluation} = args, declared = scope === "workflow" ? definition?.fields ?? [] :
|
|
6176
|
+
const {scope: scope, definition: definition, instance: instance, committed: committed, evaluation: evaluation} = args, declared = scope === "workflow" ? definition?.fields ?? [] : workflowEngine.findStageNode({
|
|
6177
|
+
definition: definition,
|
|
6178
|
+
stageName: instance.currentStage
|
|
6179
|
+
})?.fields ?? [], entries = scope === "workflow" ? instance.fields : workflowEngine.findOpenStageEntry(instance)?.fields ?? [], entriesByName = new Map(entries.map(entry => [ entry.name, entry ])), editables = isEvaluationCurrent({
|
|
5804
6180
|
committed: committed,
|
|
5805
6181
|
evaluation: evaluation
|
|
5806
6182
|
}) ? editablesByName(evaluation, scope) : /* @__PURE__ */ new Map, declaredNames = new Set(declared.map(d => d.name));
|
|
@@ -5849,7 +6225,7 @@ function UserAvatar({id: id}) {
|
|
|
5849
6225
|
function UserAvatarGroup({ids: ids, hint: hint}) {
|
|
5850
6226
|
const displays = useUserDisplays(ids);
|
|
5851
6227
|
return displays.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
5852
|
-
text: displays
|
|
6228
|
+
text: disambiguatedNames(displays).join(", "),
|
|
5853
6229
|
...hint === void 0 ? {} : {
|
|
5854
6230
|
description: hint
|
|
5855
6231
|
},
|
|
@@ -5908,8 +6284,7 @@ function FieldPills({entry: entry, scope: scope, definition: definition, surface
|
|
|
5908
6284
|
pill: pill,
|
|
5909
6285
|
scope: scope,
|
|
5910
6286
|
surface: surface
|
|
5911
|
-
}, pill.name)), overflow > 0 ?
|
|
5912
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
6287
|
+
}, pill.name)), overflow > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
5913
6288
|
mode: "bleed",
|
|
5914
6289
|
onClick: () => setExpanded(v => !v),
|
|
5915
6290
|
padding: 2,
|
|
@@ -6348,9 +6723,11 @@ function AssigneePill({entry: entry, pill: pill, editability: editability, surfa
|
|
|
6348
6723
|
return jsxRuntime.jsx(PillPopover, {
|
|
6349
6724
|
content: /* @__PURE__ */ jsxRuntime.jsx(SingleAssigneePicker, {
|
|
6350
6725
|
current: current,
|
|
6726
|
+
eligibleRoles: editability.roles,
|
|
6351
6727
|
onPick: picked => {
|
|
6352
6728
|
setOpen(!1), pick(picked);
|
|
6353
|
-
}
|
|
6729
|
+
},
|
|
6730
|
+
roleAliases: editability.roleAliases
|
|
6354
6731
|
}),
|
|
6355
6732
|
onDismiss: () => setOpen(!1),
|
|
6356
6733
|
onToggle: () => setOpen(v => !v),
|
|
@@ -6364,13 +6741,15 @@ function AssigneesPill({entry: entry, pill: pill, editability: editability, surf
|
|
|
6364
6741
|
entry: entry,
|
|
6365
6742
|
editability: editability,
|
|
6366
6743
|
surface: surface
|
|
6367
|
-
}), current = pill.face.kind === "assignees" ? pill.face.assignees : []
|
|
6744
|
+
}), current = pill.face.kind === "assignees" ? pill.face.assignees : [], change = next => {
|
|
6745
|
+
saving || save(() => set(next));
|
|
6746
|
+
};
|
|
6368
6747
|
/* @__PURE__ */
|
|
6369
6748
|
return jsxRuntime.jsx(PillPopover, {
|
|
6370
6749
|
content: /* @__PURE__ */ jsxRuntime.jsx(AssigneePicker, {
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6750
|
+
eligibleRoles: editability.roles,
|
|
6751
|
+
onChange: change,
|
|
6752
|
+
roleAliases: editability.roleAliases,
|
|
6374
6753
|
value: current
|
|
6375
6754
|
}),
|
|
6376
6755
|
onDismiss: () => setOpen(!1),
|
|
@@ -6956,6 +7335,24 @@ function historyLine(h, titles) {
|
|
|
6956
7335
|
return historyLiner[h._type](h, titles);
|
|
6957
7336
|
}
|
|
6958
7337
|
|
|
7338
|
+
function AgoStamp({at: at, now: now}) {
|
|
7339
|
+
/* @__PURE__ */
|
|
7340
|
+
return jsxRuntime.jsx(ui.Flex, {
|
|
7341
|
+
align: "center",
|
|
7342
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(HoverHint, {
|
|
7343
|
+
text: formatShortDateTime(at),
|
|
7344
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
7345
|
+
muted: !0,
|
|
7346
|
+
size: 1,
|
|
7347
|
+
style: {
|
|
7348
|
+
whiteSpace: "nowrap"
|
|
7349
|
+
},
|
|
7350
|
+
children: formatShortAgo(at, now)
|
|
7351
|
+
})
|
|
7352
|
+
})
|
|
7353
|
+
});
|
|
7354
|
+
}
|
|
7355
|
+
|
|
6959
7356
|
function CodeChip({value: value}) {
|
|
6960
7357
|
/* @__PURE__ */
|
|
6961
7358
|
return jsxRuntime.jsx("code", {
|
|
@@ -6990,6 +7387,27 @@ function HintedMenuButton({hint: hint, ...menuButtonProps}) {
|
|
|
6990
7387
|
});
|
|
6991
7388
|
}
|
|
6992
7389
|
|
|
7390
|
+
function InlineEmphasis({children: children}) {
|
|
7391
|
+
const {font: font} = ui.useTheme_v2();
|
|
7392
|
+
/* @__PURE__ */
|
|
7393
|
+
return jsxRuntime.jsx("span", {
|
|
7394
|
+
style: {
|
|
7395
|
+
fontWeight: font.text.weights.medium
|
|
7396
|
+
},
|
|
7397
|
+
children: children
|
|
7398
|
+
});
|
|
7399
|
+
}
|
|
7400
|
+
|
|
7401
|
+
const MINUTE_MS = 6e4;
|
|
7402
|
+
|
|
7403
|
+
function useMinuteClock() {
|
|
7404
|
+
const [now, setNow] = react.useState(() => /* @__PURE__ */ new Date);
|
|
7405
|
+
return react.useEffect(() => {
|
|
7406
|
+
const timer = setInterval(() => setNow(/* @__PURE__ */ new Date), MINUTE_MS);
|
|
7407
|
+
return () => clearInterval(timer);
|
|
7408
|
+
}, []), now;
|
|
7409
|
+
}
|
|
7410
|
+
|
|
6993
7411
|
function historyWindow(args) {
|
|
6994
7412
|
const {entries: entries, expanded: expanded} = args;
|
|
6995
7413
|
return {
|
|
@@ -6999,28 +7417,10 @@ function historyWindow(args) {
|
|
|
6999
7417
|
}
|
|
7000
7418
|
|
|
7001
7419
|
function PendingEffectRows({instance: instance, now: now}) {
|
|
7002
|
-
const {
|
|
7420
|
+
const {completeEffectFor: completeEffectFor, effectHandlers: effectHandlers} = useWorkflowContext(), toast = useWorkflowToast(), drain = useDrainEffects(instance._id), [resolving, setResolving] = react.useState(!1), pending = instance.pendingEffects ?? [];
|
|
7003
7421
|
if (pending.length === 0) return null;
|
|
7004
|
-
const
|
|
7005
|
-
|
|
7006
|
-
try {
|
|
7007
|
-
await drainEffectsFor(instance._id), toast.push({
|
|
7008
|
-
id: TOAST_ID.effectsDrain,
|
|
7009
|
-
status: "info",
|
|
7010
|
-
title: "Ran the registered handlers"
|
|
7011
|
-
});
|
|
7012
|
-
} catch (err) {
|
|
7013
|
-
toast.push({
|
|
7014
|
-
id: TOAST_ID.effectsDrain,
|
|
7015
|
-
status: "error",
|
|
7016
|
-
title: "Failed to run pending effects",
|
|
7017
|
-
description: describeError(err)
|
|
7018
|
-
});
|
|
7019
|
-
} finally {
|
|
7020
|
-
setBusy(!1);
|
|
7021
|
-
}
|
|
7022
|
-
}, resolve = async (effectKey, status) => {
|
|
7023
|
-
setBusy(!0);
|
|
7422
|
+
const resolve = async (effectKey, status) => {
|
|
7423
|
+
setResolving(!0);
|
|
7024
7424
|
try {
|
|
7025
7425
|
await completeEffectFor(instance._id, {
|
|
7026
7426
|
effectKey: effectKey,
|
|
@@ -7039,18 +7439,20 @@ function PendingEffectRows({instance: instance, now: now}) {
|
|
|
7039
7439
|
description: describeError(err)
|
|
7040
7440
|
});
|
|
7041
7441
|
} finally {
|
|
7042
|
-
|
|
7442
|
+
setResolving(!1);
|
|
7043
7443
|
}
|
|
7044
7444
|
};
|
|
7045
7445
|
/* @__PURE__ */
|
|
7046
7446
|
return jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
7047
7447
|
children: pending.map(fx => /* @__PURE__ */ jsxRuntime.jsx(PendingEffectRow, {
|
|
7048
|
-
busy: busy,
|
|
7448
|
+
busy: drain.busy || resolving,
|
|
7049
7449
|
effect: fx,
|
|
7050
7450
|
instanceId: instance._id,
|
|
7051
7451
|
now: now,
|
|
7052
7452
|
onResolve: status => resolve(fx._key, status),
|
|
7053
|
-
onRunHandlers:
|
|
7453
|
+
onRunHandlers: () => {
|
|
7454
|
+
drain.run();
|
|
7455
|
+
},
|
|
7054
7456
|
registered: fx.name in effectHandlers
|
|
7055
7457
|
}, fx._key))
|
|
7056
7458
|
});
|
|
@@ -7134,12 +7536,7 @@ function PendingEffectRow({busy: busy, effect: effect, instanceId: instanceId, n
|
|
|
7134
7536
|
}
|
|
7135
7537
|
|
|
7136
7538
|
function ActivityLog({instance: instance, definition: definition, windowed: windowed = !0}) {
|
|
7137
|
-
const titles = react.useMemo(() => makeTitleResolver(definition), [ definition ]), entries = react.useMemo(() => instance.history.toReversed(), [ instance.history ]),
|
|
7138
|
-
react.useEffect(() => {
|
|
7139
|
-
const timer = setInterval(() => setNow(/* @__PURE__ */ new Date), 6e4);
|
|
7140
|
-
return () => clearInterval(timer);
|
|
7141
|
-
}, []);
|
|
7142
|
-
const history = historyWindow({
|
|
7539
|
+
const titles = react.useMemo(() => makeTitleResolver(definition), [ definition ]), entries = react.useMemo(() => instance.history.toReversed(), [ instance.history ]), now = useMinuteClock(), [expanded, setExpanded] = react.useState(!1), history = historyWindow({
|
|
7143
7540
|
entries: entries,
|
|
7144
7541
|
expanded: expanded || !windowed
|
|
7145
7542
|
});
|
|
@@ -7181,16 +7578,9 @@ function FeedStamp({at: at, now: now}) {
|
|
|
7181
7578
|
size: 1,
|
|
7182
7579
|
children: "·"
|
|
7183
7580
|
}),
|
|
7184
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
muted: !0,
|
|
7188
|
-
size: 1,
|
|
7189
|
-
style: {
|
|
7190
|
-
whiteSpace: "nowrap"
|
|
7191
|
-
},
|
|
7192
|
-
children: formatShortAgo(at, now)
|
|
7193
|
-
})
|
|
7581
|
+
/* @__PURE__ */ jsxRuntime.jsx(AgoStamp, {
|
|
7582
|
+
at: at,
|
|
7583
|
+
now: now
|
|
7194
7584
|
}) ]
|
|
7195
7585
|
});
|
|
7196
7586
|
}
|
|
@@ -7242,12 +7632,9 @@ function HistoryRow({entry: entry, now: now, titles: titles}) {
|
|
|
7242
7632
|
}
|
|
7243
7633
|
|
|
7244
7634
|
function ActorNameSpan({id: id}) {
|
|
7245
|
-
const {name: name} = useUserDisplay(id)
|
|
7635
|
+
const {name: name} = useUserDisplay(id);
|
|
7246
7636
|
/* @__PURE__ */
|
|
7247
|
-
return jsxRuntime.jsx(
|
|
7248
|
-
style: {
|
|
7249
|
-
fontWeight: font.text.weights.medium
|
|
7250
|
-
},
|
|
7637
|
+
return jsxRuntime.jsx(InlineEmphasis, {
|
|
7251
7638
|
children: name
|
|
7252
7639
|
});
|
|
7253
7640
|
}
|
|
@@ -7302,8 +7689,7 @@ function InstanceCardMenu({entry: entry, title: title}) {
|
|
|
7302
7689
|
return jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
7303
7690
|
children: [
|
|
7304
7691
|
/* @__PURE__ */ jsxRuntime.jsx(ui.MenuButton, {
|
|
7305
|
-
button:
|
|
7306
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
7692
|
+
button: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, {
|
|
7307
7693
|
"aria-label": `More options for ${title}`,
|
|
7308
7694
|
fontSize: 1,
|
|
7309
7695
|
icon: EllipsisHorizontal.EllipsisHorizontalIcon,
|
|
@@ -7624,8 +8010,7 @@ function StageOverviewCard({overview: overview}) {
|
|
|
7624
8010
|
size: 1,
|
|
7625
8011
|
weight: "medium",
|
|
7626
8012
|
children: overview.title
|
|
7627
|
-
}), overview.description === void 0 ? null :
|
|
7628
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
8013
|
+
}), overview.description === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
7629
8014
|
muted: !0,
|
|
7630
8015
|
size: 1,
|
|
7631
8016
|
style: {
|
|
@@ -7655,7 +8040,6 @@ function StageOverviewCard({overview: overview}) {
|
|
|
7655
8040
|
}
|
|
7656
8041
|
|
|
7657
8042
|
function AdvanceCard({advance: advance}) {
|
|
7658
|
-
const {font: font} = ui.useTheme_v2();
|
|
7659
8043
|
/* @__PURE__ */
|
|
7660
8044
|
return jsxRuntime.jsx(ui.Card, {
|
|
7661
8045
|
padding: 3,
|
|
@@ -7667,14 +8051,10 @@ function AdvanceCard({advance: advance}) {
|
|
|
7667
8051
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, {
|
|
7668
8052
|
size: 1,
|
|
7669
8053
|
children: [ "Advances to ",
|
|
7670
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7671
|
-
style: {
|
|
7672
|
-
fontWeight: font.text.weights.medium
|
|
7673
|
-
},
|
|
8054
|
+
/* @__PURE__ */ jsxRuntime.jsx(InlineEmphasis, {
|
|
7674
8055
|
children: advance.toTitle
|
|
7675
8056
|
}), ADVANCE_TAILS[advance.kind] ]
|
|
7676
|
-
}), advance.kind !== "conditions" ? null : advance.lines.map((line, index) =>
|
|
7677
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
8057
|
+
}), advance.kind !== "conditions" ? null : advance.lines.map((line, index) => /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
7678
8058
|
muted: !0,
|
|
7679
8059
|
size: 1,
|
|
7680
8060
|
style: {
|
|
@@ -8728,8 +9108,7 @@ const VIEW_TAB_CODEC = workflowsTabCodec([ "overview", "for-me" ]), WorkflowsVie
|
|
|
8728
9108
|
children: /* @__PURE__ */ jsxRuntime.jsx(InvalidDocNotice, {
|
|
8729
9109
|
invalid: discoveryInvalid
|
|
8730
9110
|
})
|
|
8731
|
-
}) : resolved ?
|
|
8732
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
9111
|
+
}) : resolved ? /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
8733
9112
|
direction: "column",
|
|
8734
9113
|
height: "fill",
|
|
8735
9114
|
padding: 4,
|
|
@@ -8778,7 +9157,7 @@ function DiscoverySpinner() {
|
|
|
8778
9157
|
});
|
|
8779
9158
|
}
|
|
8780
9159
|
|
|
8781
|
-
const
|
|
9160
|
+
const GROUP_GAP = 2;
|
|
8782
9161
|
|
|
8783
9162
|
function useWorkflowsTab() {
|
|
8784
9163
|
const {params: params, setParams: setParams} = structure.usePaneRouter();
|
|
@@ -8803,7 +9182,7 @@ function useOpenActivity(entries) {
|
|
|
8803
9182
|
}
|
|
8804
9183
|
|
|
8805
9184
|
function WorkflowsPanel({entries: entries, documentId: documentId, docTypeMappings: docTypeMappings, initialValue: initialValue}) {
|
|
8806
|
-
const identity = useAssignmentIdentity(), panelId = react.useId(), {params: params} = structure.usePaneRouter(), {view: view, setView: setView} = useWorkflowsTab(), telemetry2 = workflowReact.useWorkflowTelemetry(), {openActivity: openActivity, setOpenActivity: setOpenActivity, dialogEntry: dialogEntry} = useOpenActivity(entries), active = entries.filter(isLiveEntry), finished = entries.filter(e => !isLiveEntry(e)), forMe = forMeWorkOf(active, identity), [landing] = react.useState(() => focusedLanding(params?.[WORKFLOWS_FOCUS_PARAM], entries.map(e => e.instance._id))), assignedWorkUnknown = active.some(e => e.invalid !== void 0), booting =
|
|
9185
|
+
const identity = useAssignmentIdentity(), panelId = react.useId(), {params: params} = structure.usePaneRouter(), {view: view, setView: setView} = useWorkflowsTab(), telemetry2 = workflowReact.useWorkflowTelemetry(), {openActivity: openActivity, setOpenActivity: setOpenActivity, dialogEntry: dialogEntry} = useOpenActivity(entries), active = entries.filter(isLiveEntry), finished = entries.filter(e => !isLiveEntry(e)), forMe = forMeWorkOf(active, identityOf(identity)), [landing] = react.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__ */ jsxRuntime.jsx(WorkflowInstanceSection, {
|
|
8807
9186
|
defaultOpen: landingDefaultOpen(landing, e.instance._id),
|
|
8808
9187
|
entry: e,
|
|
8809
9188
|
onOpenActivity: activityName => setOpenActivity({
|
|
@@ -9031,7 +9410,10 @@ function resolveEntry(args) {
|
|
|
9031
9410
|
}
|
|
9032
9411
|
valid.push(name), definition && definitions.push({
|
|
9033
9412
|
name: name,
|
|
9034
|
-
fields: definition.fields
|
|
9413
|
+
fields: definition.fields,
|
|
9414
|
+
...definition.roleAliases === void 0 ? {} : {
|
|
9415
|
+
roleAliases: definition.roleAliases
|
|
9416
|
+
}
|
|
9035
9417
|
});
|
|
9036
9418
|
}
|
|
9037
9419
|
return {
|
|
@@ -9549,6 +9931,7 @@ function WorkflowProvider(props) {
|
|
|
9549
9931
|
engine: engine,
|
|
9550
9932
|
binding: binding,
|
|
9551
9933
|
mappings: mappings,
|
|
9934
|
+
previewHydration: config.previewHydration,
|
|
9552
9935
|
mappingIssues: issues,
|
|
9553
9936
|
mappingStarts: starts,
|
|
9554
9937
|
mappingFields: fields,
|
|
@@ -9556,7 +9939,7 @@ function WorkflowProvider(props) {
|
|
|
9556
9939
|
effectHandlers: engine.effectHandlers,
|
|
9557
9940
|
autoStartByType: autoStartByType,
|
|
9558
9941
|
autoStartDefinitions: autoStartDefinitions
|
|
9559
|
-
}), [ 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 ]);
|
|
9942
|
+
}), [ 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 ]);
|
|
9560
9943
|
/* @__PURE__ */
|
|
9561
9944
|
return jsxRuntime.jsxs(WorkflowContext.Provider, {
|
|
9562
9945
|
value: value,
|
|
@@ -9658,7 +10041,7 @@ function logOnce(messages, logged) {
|
|
|
9658
10041
|
for (const message of messages) logged.has(message) || (logged.add(message), console.warn(`[workflow-studio-plugin] ${message}`));
|
|
9659
10042
|
}
|
|
9660
10043
|
|
|
9661
|
-
function AssigneesInput({value: value, onChange: onChange}) {
|
|
10044
|
+
function AssigneesInput({value: value, onChange: onChange, eligibleRoles: eligibleRoles, roleAliases: roleAliases}) {
|
|
9662
10045
|
const [open, setOpen] = react.useState(!1), remove = index => onChange(value.filter((_, i) => i !== index));
|
|
9663
10046
|
/* @__PURE__ */
|
|
9664
10047
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
@@ -9692,7 +10075,9 @@ function AssigneesInput({value: value, onChange: onChange}) {
|
|
|
9692
10075
|
wrap: "wrap",
|
|
9693
10076
|
children: /* @__PURE__ */ jsxRuntime.jsx(DismissablePopover, {
|
|
9694
10077
|
content: /* @__PURE__ */ jsxRuntime.jsx(AssigneePicker, {
|
|
10078
|
+
eligibleRoles: eligibleRoles,
|
|
9695
10079
|
onChange: next => onChange([ ...next ]),
|
|
10080
|
+
roleAliases: roleAliases,
|
|
9696
10081
|
value: value
|
|
9697
10082
|
}),
|
|
9698
10083
|
onDismiss: () => setOpen(!1),
|
|
@@ -9761,11 +10146,29 @@ function ChecklistInput({value: value, onChange: onChange}) {
|
|
|
9761
10146
|
});
|
|
9762
10147
|
}
|
|
9763
10148
|
|
|
9764
|
-
function
|
|
9765
|
-
|
|
10149
|
+
function titleOf(release) {
|
|
10150
|
+
return release.metadata.title ?? release.name;
|
|
10151
|
+
}
|
|
10152
|
+
|
|
10153
|
+
function useReleaseTitles() {
|
|
10154
|
+
const {data: data} = sanity.useActiveReleases();
|
|
10155
|
+
return react.useMemo(() => new Map(data.map(release => [ release.name, titleOf(release) ])), [ data ]);
|
|
10156
|
+
}
|
|
10157
|
+
|
|
10158
|
+
function useActiveReleaseOptions() {
|
|
10159
|
+
const {data: data, loading: loading, error: error} = sanity.useActiveReleases(), releases = react.useMemo(() => data.filter(release => release.state === "active").map(release => ({
|
|
9766
10160
|
name: release.name,
|
|
9767
|
-
title: release
|
|
9768
|
-
})).toSorted((a, b) => a.title.localeCompare(b.title)), [ data ])
|
|
10161
|
+
title: titleOf(release)
|
|
10162
|
+
})).toSorted((a, b) => a.title.localeCompare(b.title)), [ data ]);
|
|
10163
|
+
return {
|
|
10164
|
+
error: error,
|
|
10165
|
+
loading: loading,
|
|
10166
|
+
releases: releases
|
|
10167
|
+
};
|
|
10168
|
+
}
|
|
10169
|
+
|
|
10170
|
+
function ReleasePicker({value: value, onChange: onChange}) {
|
|
10171
|
+
const {binding: binding} = useWorkflowContext(), {error: error, loading: loading, releases: releases} = useActiveReleaseOptions(), labelOf = react.useMemo(() => {
|
|
9769
10172
|
const m = new Map(releases.map(r => [ r.name, r.title ]));
|
|
9770
10173
|
return name => m.get(name) ?? name;
|
|
9771
10174
|
}, [ releases ]);
|
|
@@ -10033,8 +10436,10 @@ const docRefInput = ({entry: entry, docType: docType, releaseId: releaseId, valu
|
|
|
10033
10436
|
onChange: onChange,
|
|
10034
10437
|
value: value ?? []
|
|
10035
10438
|
}),
|
|
10036
|
-
assignees: ({value: value, onChange: onChange}) => /* @__PURE__ */ jsxRuntime.jsx(AssigneesInput, {
|
|
10439
|
+
assignees: ({entry: entry, roleAliases: roleAliases, value: value, onChange: onChange}) => /* @__PURE__ */ jsxRuntime.jsx(AssigneesInput, {
|
|
10440
|
+
eligibleRoles: entry.roles,
|
|
10037
10441
|
onChange: onChange,
|
|
10442
|
+
roleAliases: roleAliases,
|
|
10038
10443
|
value: value ?? []
|
|
10039
10444
|
}),
|
|
10040
10445
|
array: ({entry: entry, value: value, onChange: onChange}) => {
|
|
@@ -10076,7 +10481,7 @@ function FieldInput(props) {
|
|
|
10076
10481
|
});
|
|
10077
10482
|
}
|
|
10078
10483
|
|
|
10079
|
-
function InitFieldRow({entry: entry, docType: docType, releaseId: releaseId, value: value, onChange: onChange}) {
|
|
10484
|
+
function InitFieldRow({entry: entry, docType: docType, releaseId: releaseId, roleAliases: roleAliases, value: value, onChange: onChange}) {
|
|
10080
10485
|
const label = entry.title ?? entry.name;
|
|
10081
10486
|
/* @__PURE__ */
|
|
10082
10487
|
return jsxRuntime.jsxs(ui.Stack, {
|
|
@@ -10100,6 +10505,7 @@ function InitFieldRow({entry: entry, docType: docType, releaseId: releaseId, val
|
|
|
10100
10505
|
entry: entry,
|
|
10101
10506
|
onChange: onChange,
|
|
10102
10507
|
releaseId: releaseId,
|
|
10508
|
+
roleAliases: roleAliases,
|
|
10103
10509
|
value: value
|
|
10104
10510
|
}) ]
|
|
10105
10511
|
});
|
|
@@ -10149,7 +10555,7 @@ function StartFooter({canStart: canStart, starting: starting, startLabel: startL
|
|
|
10149
10555
|
});
|
|
10150
10556
|
}
|
|
10151
10557
|
|
|
10152
|
-
function StartInputList({initFields: initFields, mapping: mapping, releaseId: releaseId, values: values, onChange: onChange}) {
|
|
10558
|
+
function StartInputList({initFields: initFields, mapping: mapping, releaseId: releaseId, roleAliases: roleAliases, values: values, onChange: onChange}) {
|
|
10153
10559
|
return initFields.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
10154
10560
|
muted: !0,
|
|
10155
10561
|
size: 1,
|
|
@@ -10160,6 +10566,7 @@ function StartInputList({initFields: initFields, mapping: mapping, releaseId: re
|
|
|
10160
10566
|
entry: entry,
|
|
10161
10567
|
onChange: v => onChange(entry.name, v),
|
|
10162
10568
|
releaseId: releaseId,
|
|
10569
|
+
roleAliases: roleAliases,
|
|
10163
10570
|
value: values[entry.name] ?? null
|
|
10164
10571
|
}, entry.name))
|
|
10165
10572
|
});
|
|
@@ -10290,6 +10697,7 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
|
|
|
10290
10697
|
mapping: mapping,
|
|
10291
10698
|
onChange: setValue,
|
|
10292
10699
|
releaseId: releaseId,
|
|
10700
|
+
roleAliases: definition.roleAliases,
|
|
10293
10701
|
values: values
|
|
10294
10702
|
}),
|
|
10295
10703
|
/* @__PURE__ */ jsxRuntime.jsx(StartFooter, {
|
|
@@ -10344,11 +10752,12 @@ function AutoStartInputDialog(props) {
|
|
|
10344
10752
|
}),
|
|
10345
10753
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Stack, {
|
|
10346
10754
|
gap: 4,
|
|
10347
|
-
children: inputs.map(({entry: entry}) => /* @__PURE__ */ jsxRuntime.jsx(InitFieldRow, {
|
|
10755
|
+
children: inputs.map(({entry: entry, roleAliases: roleAliases}) => /* @__PURE__ */ jsxRuntime.jsx(InitFieldRow, {
|
|
10348
10756
|
docType: docType,
|
|
10349
10757
|
entry: entry,
|
|
10350
10758
|
onChange: value => setValue(entry.name, value),
|
|
10351
10759
|
releaseId: void 0,
|
|
10760
|
+
roleAliases: roleAliases,
|
|
10352
10761
|
value: values[entry.name] ?? null
|
|
10353
10762
|
}, entry.name))
|
|
10354
10763
|
}),
|
|
@@ -10377,23 +10786,65 @@ function subjectEntry(definition) {
|
|
|
10377
10786
|
return documentSubjectEntry(definition);
|
|
10378
10787
|
}
|
|
10379
10788
|
|
|
10380
|
-
function
|
|
10789
|
+
function autoStartInputPlan(args) {
|
|
10381
10790
|
const byName = /* @__PURE__ */ new Map;
|
|
10382
10791
|
for (const name of args.workflows) {
|
|
10383
10792
|
const definition = args.definitions.get(name);
|
|
10384
10793
|
if (definition !== void 0) for (const entry of extraRequiredInputs(definition)) {
|
|
10385
|
-
const
|
|
10386
|
-
existing === void 0 ? byName.set(entry.name, {
|
|
10794
|
+
const conflict = mergeAutoStartInput(byName, {
|
|
10387
10795
|
entry: entry,
|
|
10388
|
-
|
|
10389
|
-
|
|
10796
|
+
workflow: name,
|
|
10797
|
+
roleAliases: definition.roleAliases
|
|
10798
|
+
});
|
|
10799
|
+
if (conflict !== void 0) return {
|
|
10800
|
+
inputs: [],
|
|
10801
|
+
conflict: conflict
|
|
10802
|
+
};
|
|
10390
10803
|
}
|
|
10391
10804
|
}
|
|
10392
|
-
return
|
|
10805
|
+
return {
|
|
10806
|
+
inputs: [ ...byName.values() ]
|
|
10807
|
+
};
|
|
10808
|
+
}
|
|
10809
|
+
|
|
10810
|
+
function mergeAutoStartInput(byName, args) {
|
|
10811
|
+
const existing = byName.get(args.entry.name);
|
|
10812
|
+
if (existing === void 0) {
|
|
10813
|
+
byName.set(args.entry.name, {
|
|
10814
|
+
entry: args.entry,
|
|
10815
|
+
workflows: [ args.workflow ],
|
|
10816
|
+
...args.roleAliases === void 0 ? {} : {
|
|
10817
|
+
roleAliases: args.roleAliases
|
|
10818
|
+
}
|
|
10819
|
+
});
|
|
10820
|
+
return;
|
|
10821
|
+
}
|
|
10822
|
+
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`;
|
|
10823
|
+
existing.workflows.push(args.workflow), sameRoleAliases(existing.roleAliases, args.roleAliases) || delete existing.roleAliases;
|
|
10824
|
+
}
|
|
10825
|
+
|
|
10826
|
+
function sameRoleSet(left, right) {
|
|
10827
|
+
return roleSetKey(left) === roleSetKey(right);
|
|
10828
|
+
}
|
|
10829
|
+
|
|
10830
|
+
function roleSetKey(roles) {
|
|
10831
|
+
return roles === void 0 ? void 0 : JSON.stringify(sortedUnique(roles));
|
|
10832
|
+
}
|
|
10833
|
+
|
|
10834
|
+
function sameRoleAliases(left, right) {
|
|
10835
|
+
return roleAliasesKey(left) === roleAliasesKey(right);
|
|
10836
|
+
}
|
|
10837
|
+
|
|
10838
|
+
function roleAliasesKey(aliases) {
|
|
10839
|
+
if (aliases !== void 0) return JSON.stringify(Object.entries(aliases).map(([role, fulfillers]) => [ role, sortedUnique(fulfillers) ]).toSorted(([left], [right]) => left.localeCompare(right)));
|
|
10840
|
+
}
|
|
10841
|
+
|
|
10842
|
+
function sortedUnique(values) {
|
|
10843
|
+
return [ ...new Set(values) ].toSorted();
|
|
10393
10844
|
}
|
|
10394
10845
|
|
|
10395
10846
|
function autoStartAction(args) {
|
|
10396
|
-
return args.fired ? args.settled ? "reveal" : "starting" : args.pendingCount === 0 ? "reveal" : args.resolved ? args.needsInput ? "collect" : "silent-start" : "wait";
|
|
10847
|
+
return args.fired ? args.settled ? "reveal" : "starting" : args.blocked || args.pendingCount === 0 ? "reveal" : args.resolved ? args.needsInput ? "collect" : "silent-start" : "wait";
|
|
10397
10848
|
}
|
|
10398
10849
|
|
|
10399
10850
|
function pendingWorkflows(workflows, live) {
|
|
@@ -10450,10 +10901,14 @@ function AutoStartDriver(props) {
|
|
|
10450
10901
|
engine: engine
|
|
10451
10902
|
}), {selectedReleaseId: selectedReleaseId} = sanity.usePerspective(), {entries: entries} = useWorkflowsForDocument(rawDocId), docId = csm.getPublishedId(rawDocId), valueRef = react.useRef(value);
|
|
10452
10903
|
valueRef.current = value;
|
|
10453
|
-
const pending = react.useMemo(() => pendingWorkflows(workflows, new Set(entries.map(entry => entry.instance.definition))), [ workflows, entries ]),
|
|
10904
|
+
const pending = react.useMemo(() => pendingWorkflows(workflows, new Set(entries.map(entry => entry.instance.definition))), [ workflows, entries ]), inputPlan = react.useMemo(() => autoStartInputPlan({
|
|
10454
10905
|
workflows: pending,
|
|
10455
10906
|
definitions: autoStartDefinitions
|
|
10456
|
-
}), [ pending, autoStartDefinitions ]),
|
|
10907
|
+
}), [ pending, autoStartDefinitions ]), inputs = inputPlan.inputs;
|
|
10908
|
+
react.useEffect(() => {
|
|
10909
|
+
inputPlan.conflict !== void 0 && console.warn(`[Workflows] Auto-start skipped. ${inputPlan.conflict}`);
|
|
10910
|
+
}, [ inputPlan.conflict ]);
|
|
10911
|
+
const definitionsResolved = workflows.every(name => autoStartDefinitions.has(name)), pendingRef = react.useRef(pending);
|
|
10457
10912
|
pendingRef.current = pending;
|
|
10458
10913
|
const instanceIds = react.useRef(/* @__PURE__ */ new Map), instanceIdFor = react.useCallback(workflow => {
|
|
10459
10914
|
const held = instanceIds.current.get(workflow);
|
|
@@ -10505,6 +10960,7 @@ function AutoStartDriver(props) {
|
|
|
10505
10960
|
resolved: definitionsResolved && isDocResolved(docId),
|
|
10506
10961
|
pendingCount: pending.length,
|
|
10507
10962
|
needsInput: inputs.length > 0,
|
|
10963
|
+
blocked: inputPlan.conflict !== void 0,
|
|
10508
10964
|
fired: fired,
|
|
10509
10965
|
settled: settled
|
|
10510
10966
|
});
|
|
@@ -10747,6 +11203,28 @@ function unassignedLineHint(args) {
|
|
|
10747
11203
|
};
|
|
10748
11204
|
}
|
|
10749
11205
|
|
|
11206
|
+
function taskCountState(args) {
|
|
11207
|
+
const {entry: entry, identity: identity} = args, freshness = entry.invalid === void 0 ? evaluationFreshness({
|
|
11208
|
+
committed: entry.committed,
|
|
11209
|
+
evaluation: entry.evaluation
|
|
11210
|
+
}) : void 0;
|
|
11211
|
+
return identity.kind === "unavailable" ? {
|
|
11212
|
+
kind: "unknowable"
|
|
11213
|
+
} : identity.kind === "pending" || freshness === "pending" ? {
|
|
11214
|
+
kind: "pending"
|
|
11215
|
+
} : freshness === "stale" ? {
|
|
11216
|
+
kind: "stale"
|
|
11217
|
+
} : {
|
|
11218
|
+
kind: "ready",
|
|
11219
|
+
tasks: assignedTaskCount({
|
|
11220
|
+
instance: entry.instance,
|
|
11221
|
+
committed: entry.committed,
|
|
11222
|
+
evaluation: entry.evaluation,
|
|
11223
|
+
who: identity.identity
|
|
11224
|
+
})
|
|
11225
|
+
};
|
|
11226
|
+
}
|
|
11227
|
+
|
|
10750
11228
|
function WorkflowFormStrip(props) {
|
|
10751
11229
|
const {mappings: mappings} = props, {isDocResolved: isDocResolved, discoveryInvalid: discoveryInvalid} = useWorkflowContext(), {docId: docId, entries: entries} = useWorkflowsForDocument(props.value?._id ?? null), {params: params, setParams: setParams} = structure.usePaneRouter(), telemetry2 = workflowReact.useWorkflowTelemetry(), openWorkflowsView = focusId => {
|
|
10752
11230
|
telemetry2.log(WorkflowFormStripClicked), setParams(focusedViewParams(params, focusId));
|
|
@@ -10834,7 +11312,7 @@ function InstanceLine({entry: entry, onOpen: onOpen}) {
|
|
|
10834
11312
|
aside: unprimed ? void 0 : /* @__PURE__ */ jsxRuntime.jsx(TaskCountSpinner, {
|
|
10835
11313
|
entry: entry
|
|
10836
11314
|
}),
|
|
10837
|
-
hint: lineHint(entry, identity),
|
|
11315
|
+
hint: lineHint(entry, identityOf(identity)),
|
|
10838
11316
|
onOpen: onOpen,
|
|
10839
11317
|
children: [
|
|
10840
11318
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, {
|
|
@@ -10893,28 +11371,16 @@ function finishedHint(instance) {
|
|
|
10893
11371
|
}
|
|
10894
11372
|
|
|
10895
11373
|
function useTaskCountState(entry) {
|
|
10896
|
-
const identity = useAssignmentIdentity()
|
|
10897
|
-
|
|
10898
|
-
|
|
10899
|
-
|
|
10900
|
-
|
|
10901
|
-
kind: "pending"
|
|
10902
|
-
} : freshness === "stale" ? {
|
|
10903
|
-
kind: "stale"
|
|
10904
|
-
} : {
|
|
10905
|
-
kind: "ready",
|
|
10906
|
-
tasks: assignedTaskCount({
|
|
10907
|
-
instance: entry.instance,
|
|
10908
|
-
committed: entry.committed,
|
|
10909
|
-
evaluation: entry.evaluation,
|
|
10910
|
-
who: identity
|
|
10911
|
-
})
|
|
10912
|
-
};
|
|
11374
|
+
const identity = useAssignmentIdentity();
|
|
11375
|
+
return taskCountState({
|
|
11376
|
+
entry: entry,
|
|
11377
|
+
identity: identity
|
|
11378
|
+
});
|
|
10913
11379
|
}
|
|
10914
11380
|
|
|
10915
11381
|
function TaskCountText({entry: entry}) {
|
|
10916
11382
|
const state = useTaskCountState(entry);
|
|
10917
|
-
return state.kind === "pending" || state.kind === "ready" && state.tasks === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
11383
|
+
return state.kind === "pending" || state.kind === "unknowable" || state.kind === "ready" && state.tasks === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
10918
11384
|
muted: !0,
|
|
10919
11385
|
size: 1,
|
|
10920
11386
|
children: state.kind === "stale" ? "Updating…" : pluralize__default.default("assigned task", state.tasks, !0)
|
|
@@ -10940,19 +11406,13 @@ function StartWorkflowDialogHost() {
|
|
|
10940
11406
|
}
|
|
10941
11407
|
|
|
10942
11408
|
const TOOL_TAB_LABELS = {
|
|
10943
|
-
overview: "
|
|
10944
|
-
"
|
|
10945
|
-
|
|
11409
|
+
overview: "Overview",
|
|
11410
|
+
"for-me": "For me",
|
|
11411
|
+
definitions: "Definitions"
|
|
10946
11412
|
}, TOOL_TAB_VALUES = Object.keys(TOOL_TAB_LABELS), TOOL_TABS = TOOL_TAB_VALUES.map(value => ({
|
|
10947
11413
|
value: value,
|
|
10948
11414
|
label: TOOL_TAB_LABELS[value]
|
|
10949
|
-
})), LANDING_TAB = "overview",
|
|
10950
|
-
workflow: "Documents",
|
|
10951
|
-
definition: "Definition"
|
|
10952
|
-
}, 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 => ({
|
|
10953
|
-
value: value,
|
|
10954
|
-
label: WORKFLOW_PAGE_LABELS[value]
|
|
10955
|
-
})), toolRouter = router.route.create("/", [ router.route.create("/instance/:instanceId"), router.route.create(`/${LANDING_TAB}/:workflowName`, [ router.route.create("/:workflowPage") ]), router.route.create("/:workflowsTab") ]);
|
|
11415
|
+
})), LANDING_TAB = "overview", DEFINITIONS_TAB = "definitions", toolRouter = router.route.create("/", [ router.route.create(`/${DEFINITIONS_TAB}/:workflowName`), router.route.create("/:workflowsTab") ]);
|
|
10956
11416
|
|
|
10957
11417
|
function toolTabState(tab) {
|
|
10958
11418
|
return {
|
|
@@ -10970,39 +11430,17 @@ function workflowState(workflowName) {
|
|
|
10970
11430
|
};
|
|
10971
11431
|
}
|
|
10972
11432
|
|
|
10973
|
-
function instanceState(instanceId) {
|
|
10974
|
-
return {
|
|
10975
|
-
instanceId: instanceId
|
|
10976
|
-
};
|
|
10977
|
-
}
|
|
10978
|
-
|
|
10979
11433
|
function tabSelectionNavigates(current, tab) {
|
|
10980
11434
|
return !(current.kind === "home" && tab === current.tab);
|
|
10981
11435
|
}
|
|
10982
11436
|
|
|
10983
|
-
function toolTabLabel(tab) {
|
|
10984
|
-
return TOOL_TAB_LABELS[tab];
|
|
10985
|
-
}
|
|
10986
|
-
|
|
10987
|
-
function backToTabLabel(tab) {
|
|
10988
|
-
return `Back to ${toolTabLabel(tab)}`;
|
|
10989
|
-
}
|
|
10990
|
-
|
|
10991
|
-
function workflowPageState(page, workflowName) {
|
|
10992
|
-
return page === DEFAULT_WORKFLOW_PAGE ? workflowState(workflowName) : {
|
|
10993
|
-
...workflowState(workflowName),
|
|
10994
|
-
workflowPage: page
|
|
10995
|
-
};
|
|
10996
|
-
}
|
|
10997
|
-
|
|
10998
11437
|
function toolRoute(state) {
|
|
10999
|
-
const {
|
|
11000
|
-
if (typeof
|
|
11001
|
-
kind: "
|
|
11002
|
-
|
|
11003
|
-
tab:
|
|
11438
|
+
const {workflowName: workflowName} = state;
|
|
11439
|
+
if (typeof workflowName == "string") return {
|
|
11440
|
+
kind: "definition",
|
|
11441
|
+
workflowName: workflowName,
|
|
11442
|
+
tab: DEFINITIONS_TAB
|
|
11004
11443
|
};
|
|
11005
|
-
if (typeof workflowName == "string") return workflowRoute(workflowName, state.workflowPage);
|
|
11006
11444
|
const tab = pathSegmentName({
|
|
11007
11445
|
segment: state.workflowsTab,
|
|
11008
11446
|
names: TOOL_TAB_VALUES
|
|
@@ -11016,24 +11454,11 @@ function toolRoute(state) {
|
|
|
11016
11454
|
};
|
|
11017
11455
|
}
|
|
11018
11456
|
|
|
11019
|
-
function
|
|
11020
|
-
if (
|
|
11021
|
-
|
|
11022
|
-
workflowName: workflowName,
|
|
11023
|
-
tab: LANDING_TAB
|
|
11024
|
-
};
|
|
11025
|
-
const page = pathSegmentName({
|
|
11026
|
-
segment: pageSegment,
|
|
11027
|
-
names: WORKFLOW_PAGES
|
|
11028
|
-
});
|
|
11029
|
-
return page === void 0 ? {
|
|
11030
|
-
kind: "unnamed",
|
|
11031
|
-
tab: LANDING_TAB
|
|
11032
|
-
} : {
|
|
11033
|
-
kind: page,
|
|
11034
|
-
workflowName: workflowName,
|
|
11035
|
-
tab: LANDING_TAB
|
|
11457
|
+
function definitionsRouteOf(route2) {
|
|
11458
|
+
if (route2.kind === "definition") return {
|
|
11459
|
+
workflowName: route2.workflowName
|
|
11036
11460
|
};
|
|
11461
|
+
if (route2.kind === "home" && route2.tab === "definitions") return {};
|
|
11037
11462
|
}
|
|
11038
11463
|
|
|
11039
11464
|
const WorkflowsToolRoot = react.lazy(() => Promise.resolve().then(function() {
|
|
@@ -11153,13 +11578,13 @@ exports.ActivityDetailDialog = ActivityDetailDialog;
|
|
|
11153
11578
|
|
|
11154
11579
|
exports.ActivityLog = ActivityLog;
|
|
11155
11580
|
|
|
11156
|
-
exports.
|
|
11581
|
+
exports.AgoStamp = AgoStamp;
|
|
11157
11582
|
|
|
11158
|
-
exports.
|
|
11583
|
+
exports.AlertGlyph = AlertGlyph;
|
|
11159
11584
|
|
|
11160
11585
|
exports.CodeChip = CodeChip;
|
|
11161
11586
|
|
|
11162
|
-
exports.
|
|
11587
|
+
exports.CountedHeading = CountedHeading;
|
|
11163
11588
|
|
|
11164
11589
|
exports.DismissablePopover = DismissablePopover;
|
|
11165
11590
|
|
|
@@ -11169,35 +11594,31 @@ exports.DocRefFace = DocRefFace;
|
|
|
11169
11594
|
|
|
11170
11595
|
exports.EmptyState = EmptyState;
|
|
11171
11596
|
|
|
11172
|
-
exports.ForMeEmptyState = ForMeEmptyState;
|
|
11173
|
-
|
|
11174
|
-
exports.Hairline = Hairline;
|
|
11175
|
-
|
|
11176
11597
|
exports.HoverHint = HoverHint;
|
|
11177
11598
|
|
|
11599
|
+
exports.InstanceFaultNote = InstanceFaultNote;
|
|
11600
|
+
|
|
11178
11601
|
exports.InstanceSnapshotBody = InstanceSnapshotBody;
|
|
11179
11602
|
|
|
11180
11603
|
exports.InvalidDocNotice = InvalidDocNotice;
|
|
11181
11604
|
|
|
11182
|
-
exports.LinkChip = LinkChip;
|
|
11183
|
-
|
|
11184
11605
|
exports.LoadingRow = LoadingRow;
|
|
11185
11606
|
|
|
11186
11607
|
exports.LogEventOnMount = LogEventOnMount;
|
|
11187
11608
|
|
|
11188
11609
|
exports.MetaRow = MetaRow;
|
|
11189
11610
|
|
|
11190
|
-
exports.
|
|
11611
|
+
exports.MetricPair = MetricPair;
|
|
11191
11612
|
|
|
11192
|
-
exports.
|
|
11613
|
+
exports.NoteBanner = NoteBanner;
|
|
11193
11614
|
|
|
11194
|
-
exports.
|
|
11615
|
+
exports.RUN_SEARCH_PARAM = RUN_SEARCH_PARAM;
|
|
11195
11616
|
|
|
11196
|
-
exports.
|
|
11617
|
+
exports.RoleAssignedNotice = RoleAssignedNotice;
|
|
11197
11618
|
|
|
11198
|
-
exports.
|
|
11619
|
+
exports.RowAssignees = RowAssignees;
|
|
11199
11620
|
|
|
11200
|
-
exports.
|
|
11621
|
+
exports.SpinnerSlot = SpinnerSlot;
|
|
11201
11622
|
|
|
11202
11623
|
exports.TOOL_TABS = TOOL_TABS;
|
|
11203
11624
|
|
|
@@ -11207,35 +11628,23 @@ exports.UnreadableDocsNote = UnreadableDocsNote;
|
|
|
11207
11628
|
|
|
11208
11629
|
exports.WORKFLOW_API_VERSION = WORKFLOW_API_VERSION;
|
|
11209
11630
|
|
|
11210
|
-
exports.WORKFLOW_PAGE_TABS = WORKFLOW_PAGE_TABS;
|
|
11211
|
-
|
|
11212
11631
|
exports.WorkflowBoardWorkflowSelected = WorkflowBoardWorkflowSelected;
|
|
11213
11632
|
|
|
11214
11633
|
exports.WorkflowDefinitionDetailViewed = WorkflowDefinitionDetailViewed;
|
|
11215
11634
|
|
|
11216
11635
|
exports.WorkflowInstanceDetailViewed = WorkflowInstanceDetailViewed;
|
|
11217
11636
|
|
|
11218
|
-
exports.WorkflowTaskFiltersApplied = WorkflowTaskFiltersApplied;
|
|
11219
|
-
|
|
11220
11637
|
exports.WorkflowTitleSeedDrifted = WorkflowTitleSeedDrifted;
|
|
11221
11638
|
|
|
11222
11639
|
exports.WorkflowToolOpened = WorkflowToolOpened;
|
|
11223
11640
|
|
|
11224
|
-
exports.activityRowProps = activityRowProps;
|
|
11225
|
-
|
|
11226
11641
|
exports.assigneesOf = assigneesOf;
|
|
11227
11642
|
|
|
11228
|
-
exports.
|
|
11229
|
-
|
|
11230
|
-
exports.committedRowFace = committedRowFace;
|
|
11231
|
-
|
|
11232
|
-
exports.createSubscribers = createSubscribers;
|
|
11233
|
-
|
|
11234
|
-
exports.datesOf = datesOf;
|
|
11643
|
+
exports.countBy = countBy;
|
|
11235
11644
|
|
|
11236
11645
|
exports.definitionFingerprint = definitionFingerprint;
|
|
11237
11646
|
|
|
11238
|
-
exports.
|
|
11647
|
+
exports.definitionsRouteOf = definitionsRouteOf;
|
|
11239
11648
|
|
|
11240
11649
|
exports.describeError = describeError;
|
|
11241
11650
|
|
|
@@ -11243,23 +11652,19 @@ exports.dueDatesOf = dueDatesOf;
|
|
|
11243
11652
|
|
|
11244
11653
|
exports.findActivity = findActivity;
|
|
11245
11654
|
|
|
11246
|
-
exports.findActivityNode = findActivityNode;
|
|
11247
|
-
|
|
11248
|
-
exports.formatDate = formatDate;
|
|
11249
|
-
|
|
11250
11655
|
exports.formatShortDateTime = formatShortDateTime;
|
|
11251
11656
|
|
|
11252
11657
|
exports.formatTimeAgo = formatTimeAgo;
|
|
11253
11658
|
|
|
11254
11659
|
exports.gdrLocality = gdrLocality;
|
|
11255
11660
|
|
|
11256
|
-
exports.
|
|
11661
|
+
exports.identityOf = identityOf;
|
|
11257
11662
|
|
|
11258
|
-
exports.
|
|
11663
|
+
exports.instanceBreadcrumb = instanceBreadcrumb;
|
|
11259
11664
|
|
|
11260
11665
|
exports.instanceTitle = instanceTitle;
|
|
11261
11666
|
|
|
11262
|
-
exports.
|
|
11667
|
+
exports.isDueDatePast = isDueDatePast;
|
|
11263
11668
|
|
|
11264
11669
|
exports.isEvaluationStale = isEvaluationStale;
|
|
11265
11670
|
|
|
@@ -11267,8 +11672,6 @@ exports.isLiveEntry = isLiveEntry;
|
|
|
11267
11672
|
|
|
11268
11673
|
exports.isOpenActivityStatus = isOpenActivityStatus;
|
|
11269
11674
|
|
|
11270
|
-
exports.isRoleAssignedTo = isRoleAssignedTo;
|
|
11271
|
-
|
|
11272
11675
|
exports.landingState = landingState;
|
|
11273
11676
|
|
|
11274
11677
|
exports.mappingIssueDetail = mappingIssueDetail;
|
|
@@ -11283,14 +11686,8 @@ exports.parseStoredDateValue = parseStoredDateValue;
|
|
|
11283
11686
|
|
|
11284
11687
|
exports.readDeployedDefinitions = readDeployedDefinitions;
|
|
11285
11688
|
|
|
11286
|
-
exports.rowAssignControlState = rowAssignControlState;
|
|
11287
|
-
|
|
11288
|
-
exports.rowDateControlState = rowDateControlState;
|
|
11289
|
-
|
|
11290
11689
|
exports.stageTitle = stageTitle;
|
|
11291
11690
|
|
|
11292
|
-
exports.stateByActivity = stateByActivity;
|
|
11293
|
-
|
|
11294
11691
|
exports.tabSelectionNavigates = tabSelectionNavigates;
|
|
11295
11692
|
|
|
11296
11693
|
exports.toolRoute = toolRoute;
|
|
@@ -11299,32 +11696,38 @@ exports.toolTabState = toolTabState;
|
|
|
11299
11696
|
|
|
11300
11697
|
exports.useAssignmentIdentity = useAssignmentIdentity;
|
|
11301
11698
|
|
|
11302
|
-
exports.
|
|
11699
|
+
exports.useAvatarSize = useAvatarSize;
|
|
11700
|
+
|
|
11701
|
+
exports.useCapTrimFor = useCapTrimFor;
|
|
11303
11702
|
|
|
11304
11703
|
exports.useContainerToken = useContainerToken;
|
|
11305
11704
|
|
|
11306
|
-
exports.
|
|
11705
|
+
exports.useCurrentUserId = useCurrentUserId;
|
|
11307
11706
|
|
|
11308
|
-
exports.
|
|
11707
|
+
exports.useDefinition = useDefinition;
|
|
11309
11708
|
|
|
11310
11709
|
exports.useLogEventOnMount = useLogEventOnMount;
|
|
11311
11710
|
|
|
11711
|
+
exports.useMinuteClock = useMinuteClock;
|
|
11712
|
+
|
|
11312
11713
|
exports.useProjectMembers = useProjectMembers;
|
|
11313
11714
|
|
|
11715
|
+
exports.useRadiusToken = useRadiusToken;
|
|
11716
|
+
|
|
11717
|
+
exports.useReleaseTitles = useReleaseTitles;
|
|
11718
|
+
|
|
11314
11719
|
exports.useSpaceToken = useSpaceToken;
|
|
11315
11720
|
|
|
11721
|
+
exports.useTextIconSize = useTextIconSize;
|
|
11722
|
+
|
|
11316
11723
|
exports.useUserDisplays = useUserDisplays;
|
|
11317
11724
|
|
|
11318
11725
|
exports.useWorkflowContext = useWorkflowContext;
|
|
11319
11726
|
|
|
11320
11727
|
exports.useWorkflowInstanceEntry = useWorkflowInstanceEntry;
|
|
11321
11728
|
|
|
11322
|
-
exports.useWorkflowToast = useWorkflowToast;
|
|
11323
|
-
|
|
11324
11729
|
exports.workflowDefaultDocumentNode = workflowDefaultDocumentNode;
|
|
11325
11730
|
|
|
11326
|
-
exports.workflowPageState = workflowPageState;
|
|
11327
|
-
|
|
11328
11731
|
exports.workflowState = workflowState;
|
|
11329
11732
|
|
|
11330
11733
|
exports.workflowStudioPlugin = workflowStudioPlugin;
|