@sanity/workflow-studio-plugin 0.29.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.
@@ -18,7 +18,7 @@ import { CloseIcon } from "@sanity/icons/Close";
18
18
 
19
19
  import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
20
20
 
21
- import { sameAssignee, projectMemberRow, ClearableDatePicker, AssigneePicker as AssigneePicker$1, MemberPicker as MemberPicker$1, MemberAvatar, AssigneeBadges as AssigneeBadges$1, AssigneeBadge as AssigneeBadge$1, ProgressBar, memberRoleFor, AssigneeStack, roleLabel, clampProgress, MemberAvatarGroup, progressCaption, DatePicker, roleLabelFor, roleListLabel } from "@sanity/workflow-components";
21
+ import { sameAssignee, projectMemberRow, providerTitle, ClearableDatePicker, AssigneePicker as AssigneePicker$1, MemberPicker as MemberPicker$1, MemberAvatar, AssigneeBadges as AssigneeBadges$1, AssigneeBadge as AssigneeBadge$1, ProgressBar, memberRoleFor, AssigneeStack, roleLabel, clampProgress, MemberAvatarGroup, progressCaption, DatePicker, roleLabelFor, roleListLabel } from "@sanity/workflow-components";
22
22
 
23
23
  import { getPublishedId, getDraftId } from "@sanity/client/csm";
24
24
 
@@ -26,7 +26,7 @@ import { defineEvent } from "@sanity/telemetry";
26
26
 
27
27
  import { useStudioProjectUsers, useStudioObserver, useWorkflowEngine, useWorkflowInstances, useWorkflowSession } from "@sanity/workflow-studio";
28
28
 
29
- import { useCurrentUser, Preview, SanityDefaultPreview, useValuePreview, useClient, useSchema, useWorkspace, TextWithTone, usePerspective, useIsReleaseActive, useDocumentPreviewStore, useActiveReleases, useTemplates, useInitialValueResolverContext, resolveInitialValue, definePlugin, isObjectInputProps } from "sanity";
29
+ import { useCurrentUser, Preview, useValuePreview, SanityDefaultPreview, useClient, useSchema, useWorkspace, TextWithTone, usePerspective, useIsReleaseActive, useDocumentPreviewStore, useActiveReleases, useTemplates, useInitialValueResolverContext, resolveInitialValue, definePlugin, isObjectInputProps } from "sanity";
30
30
 
31
31
  import { CalendarIcon } from "@sanity/icons/Calendar";
32
32
 
@@ -367,7 +367,7 @@ function landingDefaultOpen(landing, instanceId) {
367
367
  if (!(landing === void 0 || !landing.instanceIds.includes(instanceId))) return instanceId === landing.focusedId;
368
368
  }
369
369
 
370
- const WORKFLOWS_TOOL_NAME = "workflows", WORKFLOW_INTENT = "workflow";
370
+ const WORKFLOWS_TOOL_NAME = "workflows", WORKFLOW_INTENT = "workflow", RUN_SEARCH_PARAM = "run";
371
371
 
372
372
  function pathSegmentName(args) {
373
373
  return args.names.find(name => name === args.segment);
@@ -379,9 +379,10 @@ function handlesWorkflowIntent(intent, params) {
379
379
 
380
380
  function workflowIntentState(intent, params) {
381
381
  const instanceId = params.instanceId;
382
- return intent === WORKFLOW_INTENT && typeof instanceId == "string" ? {
383
- instanceId: instanceId
384
- } : null;
382
+ return intent !== WORKFLOW_INTENT || typeof instanceId != "string" ? null : {
383
+ workflowsTab: "overview",
384
+ _searchParams: [ [ RUN_SEARCH_PARAM, instanceId ] ]
385
+ };
385
386
  }
386
387
 
387
388
  const pad2 = n => String(n).padStart(2, "0"), DUE_DATE_FIELD_KINDS = [ "dueDate", "dueDatetime" ], DATE_FIELD_KINDS = [ "date", "datetime", ...DUE_DATE_FIELD_KINDS ], DATE_FIELD_KIND_SET = new Set(DATE_FIELD_KINDS), DUE_DATE_FIELD_KIND_SET = new Set(DUE_DATE_FIELD_KINDS);
@@ -478,14 +479,19 @@ function formatTimeAgo(value) {
478
479
  }
479
480
 
480
481
  function formatShortAgo(value, now) {
482
+ const span = formatShortSpan(value, now);
483
+ return span === "—" ? "—" : span === "now" ? "just now" : `${span} ago`;
484
+ }
485
+
486
+ function formatShortSpan(value, now) {
481
487
  const d = new Date(value);
482
488
  if (Number.isNaN(d.getTime())) return "—";
483
489
  const seconds = Math.floor((now.getTime() - d.getTime()) / 1e3);
484
- if (seconds < 60) return "just now";
490
+ if (seconds < 60) return "now";
485
491
  const minutes = Math.floor(seconds / 60);
486
- if (minutes < 60) return `${minutes}m ago`;
492
+ if (minutes < 60) return `${minutes}m`;
487
493
  const hours = Math.floor(minutes / 60);
488
- return hours < 24 ? `${hours}h ago` : `${Math.floor(hours / 24)}d ago`;
494
+ return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;
489
495
  }
490
496
 
491
497
  function stampFace(verb, at) {
@@ -709,7 +715,7 @@ function todoFieldEditability(args) {
709
715
  }
710
716
 
711
717
  function itemRow(args) {
712
- const {item: item, items: items, field: field, source: source, ticks: ticks, editability: editability} = args, tick = ticks.get(tickKey(field.name, item._key));
718
+ const {item: item, items: items, field: field, source: source, ticks: ticks, editability: editability} = args, tick = ticks.get(tickKey(field.name, item._key)), eligibleAssigneeRoles = field.of.find(column => column.name === "assignee" && column.type === "assignee")?.roles;
713
719
  return {
714
720
  item: item,
715
721
  items: items,
@@ -724,6 +730,9 @@ function itemRow(args) {
724
730
  ...editability.editDisabledReason ? {
725
731
  editDisabledReason: editability.editDisabledReason
726
732
  } : {},
733
+ ...eligibleAssigneeRoles === void 0 ? {} : {
734
+ eligibleAssigneeRoles: eligibleAssigneeRoles
735
+ },
727
736
  ...tick ? {
728
737
  tick: tick
729
738
  } : {}
@@ -1123,24 +1132,10 @@ function dateValuesOf(state, matches) {
1123
1132
  return state.filter(entry => matches(entry._type)).map(entry => entry.value).filter(value => typeof value == "string" && value !== "");
1124
1133
  }
1125
1134
 
1126
- function datesOf(state) {
1127
- return dateValuesOf(state, isDateFieldKind);
1128
- }
1129
-
1130
1135
  function dueDatesOf(state) {
1131
1136
  return dateValuesOf(state, isDueDateFieldKind);
1132
1137
  }
1133
1138
 
1134
- function committedRowFace(row) {
1135
- return {
1136
- activityName: row.activityName,
1137
- title: row.title,
1138
- status: row.status,
1139
- automated: !1,
1140
- blocked: !1
1141
- };
1142
- }
1143
-
1144
1139
  function activityRowProps(args) {
1145
1140
  const {activityEval: activityEval, activityState: activityState, editableFields: editableFields} = args, state = activityState.get(activityEval.activity.name) ?? [], controlArgs = {
1146
1141
  activity: activityEval.activity,
@@ -1239,15 +1234,15 @@ function useWorkflowInstanceEntry(instanceId, options = {}) {
1239
1234
  }
1240
1235
 
1241
1236
  const WorkflowToolOpened = defineEvent({
1242
- name: "Editorial Workflows Studio Plugin Tool Opened",
1243
- version: 2,
1237
+ name: "Workflows Studio Plugin Tool Opened",
1238
+ version: 3,
1244
1239
  description: "The Workflows tool was opened or its tab was switched"
1245
1240
  }), WorkflowDocumentViewOpened = defineEvent({
1246
- name: "Editorial Workflows Studio Plugin Document View Opened",
1241
+ name: "Workflows Studio Plugin Document View Opened",
1247
1242
  version: 1,
1248
1243
  description: "The Workflows document view was opened or its tab was switched"
1249
1244
  }), WorkflowInstanceDetailViewed = defineEvent({
1250
- name: "Editorial Workflows Studio Plugin Instance Detail Viewed",
1245
+ name: "Workflows Studio Plugin Instance Detail Viewed",
1251
1246
  version: 1,
1252
1247
  description: "The Workflows tool's per-instance detail view was opened"
1253
1248
  });
@@ -1260,67 +1255,63 @@ function definitionFingerprint(definition) {
1260
1255
  }
1261
1256
 
1262
1257
  const WorkflowDefinitionDetailViewed = defineEvent({
1263
- name: "Editorial Workflows Studio Plugin Definition Detail Viewed",
1258
+ name: "Workflows Studio Plugin Definition Detail Viewed",
1264
1259
  version: 1,
1265
1260
  description: "A workflow's definition page was opened in the Workflows tool"
1266
1261
  }), WorkflowFormStripClicked = defineEvent({
1267
- name: "Editorial Workflows Studio Plugin Form Strip Clicked",
1262
+ name: "Workflows Studio Plugin Form Strip Clicked",
1268
1263
  version: 1,
1269
1264
  description: "The form strip's instance line was clicked, opening the document view"
1270
1265
  }), WorkflowDocumentLinkClicked = defineEvent({
1271
- name: "Editorial Workflows Studio Plugin Document Link Clicked",
1272
- version: 2,
1266
+ name: "Workflows Studio Plugin Document Link Clicked",
1267
+ version: 3,
1273
1268
  description: "A document link was clicked, opening the referenced document's editor"
1274
1269
  }), WorkflowStartDialogOpened = defineEvent({
1275
- name: "Editorial Workflows Studio Plugin Start Dialog Opened",
1270
+ name: "Workflows Studio Plugin Start Dialog Opened",
1276
1271
  version: 1,
1277
1272
  description: "The start-workflow dialog was opened"
1278
1273
  }), WorkflowStartDialogSubmitted = defineEvent({
1279
- name: "Editorial Workflows Studio Plugin Start Dialog Submitted",
1274
+ name: "Workflows Studio Plugin Start Dialog Submitted",
1280
1275
  version: 1,
1281
1276
  description: "The start-workflow dialog's confirm was pressed"
1282
1277
  }), WorkflowAutoStartRan = defineEvent({
1283
- name: "Editorial Workflows Studio Plugin Auto Start Ran",
1278
+ name: "Workflows Studio Plugin Auto Start Ran",
1284
1279
  version: 1,
1285
1280
  description: "A fresh document's auto-start ran — one start request per configured workflow"
1286
1281
  }), WorkflowActionControlUsed = defineEvent({
1287
- name: "Editorial Workflows Studio Plugin Action Control Used",
1288
- version: 2,
1282
+ name: "Workflows Studio Plugin Action Control Used",
1283
+ version: 3,
1289
1284
  description: "An action-firing control was used, attributed to its UI surface"
1290
1285
  }), WorkflowFieldControlUsed = defineEvent({
1291
- name: "Editorial Workflows Studio Plugin Field Control Used",
1292
- version: 1,
1286
+ name: "Workflows Studio Plugin Field Control Used",
1287
+ version: 2,
1293
1288
  description: "A field-editing control committed an edit, attributed to its UI surface"
1294
1289
  }), WorkflowActivityDialogOpened = defineEvent({
1295
- name: "Editorial Workflows Studio Plugin Activity Dialog Opened",
1296
- version: 1,
1290
+ name: "Workflows Studio Plugin Activity Dialog Opened",
1291
+ version: 2,
1297
1292
  description: "The activity detail dialog was opened"
1298
- }), WorkflowTaskFiltersApplied = defineEvent({
1299
- name: "Editorial Workflows Studio Plugin Task Filters Applied",
1300
- version: 1,
1301
- description: "The tool's task-filter menu closed with a changed selection"
1302
1293
  }), WorkflowBoardWorkflowSelected = defineEvent({
1303
- name: "Editorial Workflows Studio Plugin Board Workflow Selected",
1304
- version: 2,
1305
- description: "The workflow documents page settled on the workflow it's showing"
1294
+ name: "Workflows Studio Plugin Board Workflow Selected",
1295
+ version: 3,
1296
+ description: "The Overview's board display settled on the workflow it's showing"
1306
1297
  }), WorkflowTitleSeedDrifted = defineEvent({
1307
- name: "Editorial Workflows Studio Plugin Title Seed Drifted",
1298
+ name: "Workflows Studio Plugin Title Seed Drifted",
1308
1299
  version: 1,
1309
1300
  description: "A cold-start seeded preview title diverged from the live preview pipeline"
1310
1301
  }), WorkflowTodoToggled = defineEvent({
1311
- name: "Editorial Workflows Studio Plugin Todo Toggled",
1302
+ name: "Workflows Studio Plugin Todo Toggled",
1312
1303
  version: 1,
1313
1304
  description: "A todo checkbox was toggled, attributed to its UI surface and write seam"
1314
1305
  }), WorkflowTodoEdited = defineEvent({
1315
- name: "Editorial Workflows Studio Plugin Todo Edited",
1306
+ name: "Workflows Studio Plugin Todo Edited",
1316
1307
  version: 1,
1317
1308
  description: "A non-toggle todo-list write, attributed to its UI surface and gesture"
1318
1309
  }), WorkflowAbortDialogOpened = defineEvent({
1319
- name: "Editorial Workflows Studio Plugin Abort Dialog Opened",
1310
+ name: "Workflows Studio Plugin Abort Dialog Opened",
1320
1311
  version: 1,
1321
1312
  description: "The abort-workflow confirm was opened"
1322
1313
  }), WorkflowAbortDialogSubmitted = defineEvent({
1323
- name: "Editorial Workflows Studio Plugin Abort Dialog Submitted",
1314
+ name: "Workflows Studio Plugin Abort Dialog Submitted",
1324
1315
  version: 1,
1325
1316
  description: "The abort-workflow confirm was submitted, carrying the attempt's outcome"
1326
1317
  });
@@ -1356,6 +1347,12 @@ function scalarValidationIssue(args) {
1356
1347
  return issues === void 0 ? void 0 : `${args.label}: ${issues.join("; ")}`;
1357
1348
  }
1358
1349
 
1350
+ function countBy(rows, keysOf) {
1351
+ const counts = /* @__PURE__ */ new Map;
1352
+ for (const row of rows) for (const key of keysOf(row)) counts.set(key, (counts.get(key) ?? 0) + 1);
1353
+ return counts;
1354
+ }
1355
+
1359
1356
  function personActor(user) {
1360
1357
  const roles = user.roles.map(role => typeof role == "string" ? role : role.name);
1361
1358
  return {
@@ -1387,10 +1384,16 @@ function userDisplayFor(args) {
1387
1384
  return {
1388
1385
  id: args.id,
1389
1386
  name: member?.displayName ?? self?.name ?? args.id,
1390
- imageUrl: member?.imageUrl ?? self?.profileImage ?? void 0
1387
+ imageUrl: member?.imageUrl ?? self?.profileImage ?? void 0,
1388
+ loginProvider: member?.loginProvider
1391
1389
  };
1392
1390
  }
1393
1391
 
1392
+ function disambiguatedNames(displays) {
1393
+ const counts = countBy(displays, display => [ display.name ]);
1394
+ return displays.map(display => (counts.get(display.name) ?? 0) < 2 || display.loginProvider === void 0 ? display.name : `${display.name} (${providerTitle(display.loginProvider) ?? display.loginProvider})`);
1395
+ }
1396
+
1394
1397
  function useUserDisplays(ids) {
1395
1398
  const {members: members} = useProjectMembers(), {users: users} = useStudioProjectUsers(), meRaw = useCurrentUser(), me = useMemo(() => meRaw === null ? null : {
1396
1399
  ...meRaw,
@@ -1473,6 +1476,10 @@ function identityOf(state) {
1473
1476
  return state.kind === "resolved" ? state.identity : void 0;
1474
1477
  }
1475
1478
 
1479
+ function useCurrentUserId() {
1480
+ return identityOf(useAssignmentIdentity())?.userId;
1481
+ }
1482
+
1476
1483
  const projectMembersByUsers = /* @__PURE__ */ new WeakMap;
1477
1484
 
1478
1485
  function projectMembersFrom(users) {
@@ -1863,23 +1870,27 @@ function MemberPicker({selectedIds: selectedIds, onSelect: onSelect, unassignRow
1863
1870
  });
1864
1871
  }
1865
1872
 
1866
- function AssigneePicker({value: value, onChange: onChange}) {
1873
+ function AssigneePicker({value: value, onChange: onChange, eligibleRoles: eligibleRoles, roleAliases: roleAliases}) {
1867
1874
  const state = useProjectMembers();
1868
1875
  /* @__PURE__ */
1869
1876
  return jsx(AssigneePicker$1, {
1870
1877
  ...state,
1878
+ eligibleRoles: eligibleRoles,
1871
1879
  onChange: onChange,
1880
+ roleAliases: roleAliases,
1872
1881
  value: value
1873
1882
  });
1874
1883
  }
1875
1884
 
1876
- function SingleAssigneePicker({current: current, onPick: onPick}) {
1885
+ function SingleAssigneePicker({current: current, onPick: onPick, eligibleRoles: eligibleRoles, roleAliases: roleAliases}) {
1877
1886
  /* @__PURE__ */
1878
1887
  return jsx(AssigneePicker, {
1888
+ eligibleRoles: eligibleRoles,
1879
1889
  onChange: next => {
1880
1890
  const picked = singleAssigneePick(current, next);
1881
1891
  picked !== void 0 && onPick(picked);
1882
1892
  },
1893
+ roleAliases: roleAliases,
1883
1894
  value: current ? [ current ] : []
1884
1895
  });
1885
1896
  }
@@ -2192,7 +2203,6 @@ const TOAST_ID = {
2192
2203
  effectResolve: "workflow-effect-resolve",
2193
2204
  effectsDrain: "workflow-effects-drain",
2194
2205
  effectsIncomplete: "workflow-effects-incomplete",
2195
- orphanSettle: "workflow-orphan-settle",
2196
2206
  start: "workflow-start"
2197
2207
  };
2198
2208
 
@@ -3052,8 +3062,7 @@ function PendingDocFace({bareId: bareId, layout: layout}) {
3052
3062
  children: id
3053
3063
  });
3054
3064
  }
3055
- return compact ?
3056
- /* @__PURE__ */ jsxs(Flex, {
3065
+ return compact ? /* @__PURE__ */ jsxs(Flex, {
3057
3066
  align: "center",
3058
3067
  gap: 2,
3059
3068
  children: [
@@ -3727,9 +3736,11 @@ function AssigneeField({field: field, instanceId: instanceId, onSave: onSave, on
3727
3736
  children: /* @__PURE__ */ jsx(DismissablePopover, {
3728
3737
  content: /* @__PURE__ */ jsx(SingleAssigneePicker, {
3729
3738
  current: cur,
3739
+ eligibleRoles: field.roles,
3730
3740
  onPick: picked => {
3731
3741
  setOpen(!1), pick(picked);
3732
- }
3742
+ },
3743
+ roleAliases: field.roleAliases
3733
3744
  }),
3734
3745
  onDismiss: () => setOpen(!1),
3735
3746
  open: open,
@@ -4408,6 +4419,12 @@ function useSpaceToken(index) {
4408
4419
  return value;
4409
4420
  }
4410
4421
 
4422
+ function useRadiusToken(index) {
4423
+ const value = useTheme_v2().radius[index];
4424
+ if (value === void 0) throw new Error(`theme is missing radius token ${index}`);
4425
+ return value;
4426
+ }
4427
+
4411
4428
  function useContainerToken(index) {
4412
4429
  const value = useTheme_v2().container[index];
4413
4430
  if (value === void 0) throw new Error(`theme is missing container token ${index}`);
@@ -4448,10 +4465,9 @@ function useBadgeCapTrim() {
4448
4465
  };
4449
4466
  }
4450
4467
 
4451
- function SpinnerSlot({busy: busy}) {
4468
+ function SpinnerSlot({busy: busy, reserve: reserve = !0}) {
4452
4469
  const size = useTextIconSize(), trim = useCapTrimFor(size), spinning = useDelayedFlag(busy, LOADING_CUE_DELAY_MS);
4453
- /* @__PURE__ */
4454
- return jsx(Flex, {
4470
+ return !spinning && !reserve ? null : /* @__PURE__ */ jsx(Flex, {
4455
4471
  align: "center",
4456
4472
  flex: "none",
4457
4473
  justify: "center",
@@ -4545,8 +4561,7 @@ function RowAssignees({assignees: assignees, hint: hint}) {
4545
4561
  const bothKinds = roles.length > 0 && displays.length > 0;
4546
4562
  /* @__PURE__ */
4547
4563
  return jsx(HoverHint, {
4548
- content:
4549
- /* @__PURE__ */ jsxs(Stack, {
4564
+ content: /* @__PURE__ */ jsxs(Stack, {
4550
4565
  gap: 3,
4551
4566
  children: [ roles.length > 0 ? /* @__PURE__ */ jsx(HintSection, {
4552
4567
  names: roles.map(roleLabel),
@@ -4554,7 +4569,7 @@ function RowAssignees({assignees: assignees, hint: hint}) {
4554
4569
  label: "Roles"
4555
4570
  } : {}
4556
4571
  }) : null, displays.length > 0 ? /* @__PURE__ */ jsx(HintSection, {
4557
- names: displays.map(display => display.name),
4572
+ names: disambiguatedNames(displays),
4558
4573
  ...bothKinds ? {
4559
4574
  label: "Members"
4560
4575
  } : {}
@@ -4633,8 +4648,7 @@ function AssignActivityControl({instanceId: instanceId, state: state, surface: s
4633
4648
  }
4634
4649
  }, handleClick = e => {
4635
4650
  e.stopPropagation(), setOpen(v => !v);
4636
- }, button = assignees.length > 0 ?
4637
- /* @__PURE__ */ jsx(AvatarButton, {
4651
+ }, button = assignees.length > 0 ? /* @__PURE__ */ jsx(AvatarButton, {
4638
4652
  "aria-label": "Assignees",
4639
4653
  as: "span",
4640
4654
  avatar: /* @__PURE__ */ jsx(RowAssignees, {
@@ -4664,9 +4678,11 @@ function AssignActivityControl({instanceId: instanceId, state: state, surface: s
4664
4678
  label: "Loading…",
4665
4679
  padding: 3
4666
4680
  }) : /* @__PURE__ */ jsx(AssigneePicker, {
4681
+ eligibleRoles: state.field.roles,
4667
4682
  onChange: next => {
4668
4683
  change(next);
4669
4684
  },
4685
+ roleAliases: state.field.roleAliases,
4670
4686
  value: current
4671
4687
  })
4672
4688
  }),
@@ -4768,8 +4784,7 @@ function DueDate({dueDate: dueDate, hintDisabled: hintDisabled, overdue: overdue
4768
4784
  const face = hintFace({
4769
4785
  overdue: overdue,
4770
4786
  reason: reason
4771
- }), text = overdue ?
4772
- /* @__PURE__ */ jsx(TextWithTone, {
4787
+ }), text = overdue ? /* @__PURE__ */ jsx(TextWithTone, {
4773
4788
  size: 1,
4774
4789
  tone: "caution",
4775
4790
  children: formatDate(dueDate)
@@ -4880,7 +4895,7 @@ function DueDateControl({item: item, editable: editable, onPatch: onPatch}) {
4880
4895
  }) : display;
4881
4896
  }
4882
4897
 
4883
- function AssigneeControl({item: item, editable: editable, onPatch: onPatch}) {
4898
+ function AssigneeControl({item: item, editable: editable, eligibleRoles: eligibleRoles, onPatch: onPatch, roleAliases: roleAliases}) {
4884
4899
  const [open, setOpen] = useState(!1), current = item.assignee ?? null, chip = current ? /* @__PURE__ */ jsx(RowAssignees, {
4885
4900
  assignees: [ current ]
4886
4901
  }) : null;
@@ -4888,11 +4903,13 @@ function AssigneeControl({item: item, editable: editable, onPatch: onPatch}) {
4888
4903
  content:
4889
4904
  /* @__PURE__ */ jsx(SingleAssigneePicker, {
4890
4905
  current: current,
4906
+ eligibleRoles: eligibleRoles,
4891
4907
  onPick: picked => {
4892
4908
  setOpen(!1), onPatch({
4893
4909
  assignee: picked
4894
4910
  });
4895
- }
4911
+ },
4912
+ roleAliases: roleAliases
4896
4913
  }),
4897
4914
  onDismiss: () => setOpen(!1),
4898
4915
  open: open,
@@ -4994,8 +5011,7 @@ function BreadcrumbTail({segments: segments, style: style}) {
4994
5011
  }
4995
5012
 
4996
5013
  function WorkRow({lead: lead, children: children, end: end, onOpen: onOpen}) {
4997
- const frame =
4998
- /* @__PURE__ */ jsxs(Flex, {
5014
+ const frame = /* @__PURE__ */ jsxs(Flex, {
4999
5015
  align: "center",
5000
5016
  children: [
5001
5017
  /* @__PURE__ */ jsx(Flex, {
@@ -5029,8 +5045,7 @@ function WorkRow({lead: lead, children: children, end: end, onOpen: onOpen}) {
5029
5045
  padding: 1,
5030
5046
  radius: 3,
5031
5047
  children: frame
5032
- }) :
5033
- /* @__PURE__ */ jsx(Card, {
5048
+ }) : /* @__PURE__ */ jsx(Card, {
5034
5049
  as: "button",
5035
5050
  onClick: onOpen,
5036
5051
  padding: 1,
@@ -5042,7 +5057,7 @@ function WorkRow({lead: lead, children: children, end: end, onOpen: onOpen}) {
5042
5057
  });
5043
5058
  }
5044
5059
 
5045
- function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle, onPatch: onPatch, onRemove: onRemove}) {
5060
+ function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle, onPatch: onPatch, onRemove: onRemove, roleAliases: roleAliases}) {
5046
5061
  const {canClick: canClick, hint: hint} = rowInteractivity(row), editable = row.editTarget !== void 0, checkbox = /* @__PURE__ */ jsx(TodoCheckbox, {
5047
5062
  canClick: canClick,
5048
5063
  checked: isTodoDone(row.item),
@@ -5059,8 +5074,10 @@ function TodoItemRowView({breadcrumb: breadcrumb, row: row, onToggle: onToggle,
5059
5074
  }),
5060
5075
  /* @__PURE__ */ jsx(AssigneeControl, {
5061
5076
  editable: editable,
5077
+ eligibleRoles: row.eligibleAssigneeRoles,
5062
5078
  item: row.item,
5063
- onPatch: onPatch
5079
+ onPatch: onPatch,
5080
+ roleAliases: roleAliases
5064
5081
  }), onRemove === void 0 ? null : /* @__PURE__ */ jsx(RemoveItemButton, {
5065
5082
  onClick: onRemove
5066
5083
  }) ]
@@ -5237,6 +5254,7 @@ function TodoItemsList({breadcrumb: breadcrumb, entry: entry, filter: filter, sh
5237
5254
  onToggle: () => {
5238
5255
  toggleRow(row);
5239
5256
  },
5257
+ roleAliases: definition?.roleAliases,
5240
5258
  row: row
5241
5259
  }, rowKey(row)))
5242
5260
  }), addControl === null ? null : /* @__PURE__ */ jsx(Flex, {
@@ -5834,7 +5852,7 @@ function MetricPair({Icon: Icon, empty: empty, face: face, tone: tone, value: va
5834
5852
  });
5835
5853
  }
5836
5854
 
5837
- function AlertGlyph({Icon: Icon, hint: hint, tone: tone}) {
5855
+ function AlertGlyph({Icon: Icon, hint: hint, label: label, tone: tone}) {
5838
5856
  /* @__PURE__ */
5839
5857
  return jsx(HoverHint, {
5840
5858
  text: hint,
@@ -5842,6 +5860,10 @@ function AlertGlyph({Icon: Icon, hint: hint, tone: tone}) {
5842
5860
  size: 1,
5843
5861
  tone: tone,
5844
5862
  children: /* @__PURE__ */ jsx(Icon, {
5863
+ ...label === void 0 ? {} : {
5864
+ "aria-label": label,
5865
+ role: "img"
5866
+ },
5845
5867
  style: {
5846
5868
  color: "inherit"
5847
5869
  }
@@ -6015,8 +6037,7 @@ function ActivityRow({face: face, breadcrumb: breadcrumb, assignees: assignees,
6015
6037
  const settled = isTerminalActivityStatus(face.status), dimmed = settledDim(settled);
6016
6038
  /* @__PURE__ */
6017
6039
  return jsxs(WorkRow, {
6018
- end:
6019
- /* @__PURE__ */ jsxs(Fragment, {
6040
+ end: /* @__PURE__ */ jsxs(Fragment, {
6020
6041
  children: [
6021
6042
  /* @__PURE__ */ jsx(ActivityDateControl, {
6022
6043
  dueDates: dueDates,
@@ -6064,8 +6085,7 @@ function ActivityRow({face: face, breadcrumb: breadcrumb, assignees: assignees,
6064
6085
 
6065
6086
  function ActivitiesList({entry: entry, onOpenActivity: onOpenActivity, surface: surface}) {
6066
6087
  const activities = (entry.evaluation?.currentStage.activities ?? []).filter(t => !t.scopedOut), activityState = stateByActivity(entry.instance), fault = useInstanceFault(entry);
6067
- return activities.length === 0 ?
6068
- /* @__PURE__ */ jsx(Box, {
6088
+ return activities.length === 0 ? /* @__PURE__ */ jsx(Box, {
6069
6089
  paddingX: 1,
6070
6090
  paddingY: 3,
6071
6091
  children: /* @__PURE__ */ jsx(Text, {
@@ -6093,8 +6113,7 @@ function ActivitiesList({entry: entry, onOpenActivity: onOpenActivity, surface:
6093
6113
 
6094
6114
  function instanceNotice(entry) {
6095
6115
  const {instance: instance, committed: committed, evaluation: evaluation} = entry, state = terminalState(instance);
6096
- if (state !== "in-flight")
6097
- /* @__PURE__ */
6116
+ if (state !== "in-flight") /* @__PURE__ */
6098
6117
  return jsx(Box, {
6099
6118
  paddingX: 1,
6100
6119
  paddingY: 2,
@@ -6282,7 +6301,7 @@ function UserAvatar({id: id}) {
6282
6301
  function UserAvatarGroup({ids: ids, hint: hint}) {
6283
6302
  const displays = useUserDisplays(ids);
6284
6303
  return displays.length === 0 ? null : /* @__PURE__ */ jsx(HoverHint, {
6285
- text: displays.map(d => d.name).join(", "),
6304
+ text: disambiguatedNames(displays).join(", "),
6286
6305
  ...hint === void 0 ? {} : {
6287
6306
  description: hint
6288
6307
  },
@@ -6341,8 +6360,7 @@ function FieldPills({entry: entry, scope: scope, definition: definition, surface
6341
6360
  pill: pill,
6342
6361
  scope: scope,
6343
6362
  surface: surface
6344
- }, pill.name)), overflow > 0 ?
6345
- /* @__PURE__ */ jsx(Button, {
6363
+ }, pill.name)), overflow > 0 ? /* @__PURE__ */ jsx(Button, {
6346
6364
  mode: "bleed",
6347
6365
  onClick: () => setExpanded(v => !v),
6348
6366
  padding: 2,
@@ -6781,9 +6799,11 @@ function AssigneePill({entry: entry, pill: pill, editability: editability, surfa
6781
6799
  return jsx(PillPopover, {
6782
6800
  content: /* @__PURE__ */ jsx(SingleAssigneePicker, {
6783
6801
  current: current,
6802
+ eligibleRoles: editability.roles,
6784
6803
  onPick: picked => {
6785
6804
  setOpen(!1), pick(picked);
6786
- }
6805
+ },
6806
+ roleAliases: editability.roleAliases
6787
6807
  }),
6788
6808
  onDismiss: () => setOpen(!1),
6789
6809
  onToggle: () => setOpen(v => !v),
@@ -6797,13 +6817,15 @@ function AssigneesPill({entry: entry, pill: pill, editability: editability, surf
6797
6817
  entry: entry,
6798
6818
  editability: editability,
6799
6819
  surface: surface
6800
- }), current = pill.face.kind === "assignees" ? pill.face.assignees : [];
6820
+ }), current = pill.face.kind === "assignees" ? pill.face.assignees : [], change = next => {
6821
+ saving || save(() => set(next));
6822
+ };
6801
6823
  /* @__PURE__ */
6802
6824
  return jsx(PillPopover, {
6803
6825
  content: /* @__PURE__ */ jsx(AssigneePicker, {
6804
- onChange: next => {
6805
- saving || save(() => set(next));
6806
- },
6826
+ eligibleRoles: editability.roles,
6827
+ onChange: change,
6828
+ roleAliases: editability.roleAliases,
6807
6829
  value: current
6808
6830
  }),
6809
6831
  onDismiss: () => setOpen(!1),
@@ -7389,6 +7411,24 @@ function historyLine(h, titles) {
7389
7411
  return historyLiner[h._type](h, titles);
7390
7412
  }
7391
7413
 
7414
+ function AgoStamp({at: at, now: now}) {
7415
+ /* @__PURE__ */
7416
+ return jsx(Flex, {
7417
+ align: "center",
7418
+ children: /* @__PURE__ */ jsx(HoverHint, {
7419
+ text: formatShortDateTime(at),
7420
+ children: /* @__PURE__ */ jsx(Text, {
7421
+ muted: !0,
7422
+ size: 1,
7423
+ style: {
7424
+ whiteSpace: "nowrap"
7425
+ },
7426
+ children: formatShortAgo(at, now)
7427
+ })
7428
+ })
7429
+ });
7430
+ }
7431
+
7392
7432
  function CodeChip({value: value}) {
7393
7433
  /* @__PURE__ */
7394
7434
  return jsx("code", {
@@ -7614,16 +7654,9 @@ function FeedStamp({at: at, now: now}) {
7614
7654
  size: 1,
7615
7655
  children: "·"
7616
7656
  }),
7617
- /* @__PURE__ */ jsx(HoverHint, {
7618
- text: formatDateTime(at),
7619
- children: /* @__PURE__ */ jsx(Text, {
7620
- muted: !0,
7621
- size: 1,
7622
- style: {
7623
- whiteSpace: "nowrap"
7624
- },
7625
- children: formatShortAgo(at, now)
7626
- })
7657
+ /* @__PURE__ */ jsx(AgoStamp, {
7658
+ at: at,
7659
+ now: now
7627
7660
  }) ]
7628
7661
  });
7629
7662
  }
@@ -7732,8 +7765,7 @@ function InstanceCardMenu({entry: entry, title: title}) {
7732
7765
  return jsxs(Fragment, {
7733
7766
  children: [
7734
7767
  /* @__PURE__ */ jsx(MenuButton, {
7735
- button:
7736
- /* @__PURE__ */ jsx(Button, {
7768
+ button: /* @__PURE__ */ jsx(Button, {
7737
7769
  "aria-label": `More options for ${title}`,
7738
7770
  fontSize: 1,
7739
7771
  icon: EllipsisHorizontalIcon,
@@ -8054,8 +8086,7 @@ function StageOverviewCard({overview: overview}) {
8054
8086
  size: 1,
8055
8087
  weight: "medium",
8056
8088
  children: overview.title
8057
- }), overview.description === void 0 ? null :
8058
- /* @__PURE__ */ jsx(Text, {
8089
+ }), overview.description === void 0 ? null : /* @__PURE__ */ jsx(Text, {
8059
8090
  muted: !0,
8060
8091
  size: 1,
8061
8092
  style: {
@@ -8099,8 +8130,7 @@ function AdvanceCard({advance: advance}) {
8099
8130
  /* @__PURE__ */ jsx(InlineEmphasis, {
8100
8131
  children: advance.toTitle
8101
8132
  }), ADVANCE_TAILS[advance.kind] ]
8102
- }), advance.kind !== "conditions" ? null : advance.lines.map((line, index) =>
8103
- /* @__PURE__ */ jsx(Text, {
8133
+ }), advance.kind !== "conditions" ? null : advance.lines.map((line, index) => /* @__PURE__ */ jsx(Text, {
8104
8134
  muted: !0,
8105
8135
  size: 1,
8106
8136
  style: {
@@ -9154,8 +9184,7 @@ const VIEW_TAB_CODEC = workflowsTabCodec([ "overview", "for-me" ]), WorkflowsVie
9154
9184
  children: /* @__PURE__ */ jsx(InvalidDocNotice, {
9155
9185
  invalid: discoveryInvalid
9156
9186
  })
9157
- }) : resolved ?
9158
- /* @__PURE__ */ jsx(Flex, {
9187
+ }) : resolved ? /* @__PURE__ */ jsx(Flex, {
9159
9188
  direction: "column",
9160
9189
  height: "fill",
9161
9190
  padding: 4,
@@ -9457,7 +9486,10 @@ function resolveEntry(args) {
9457
9486
  }
9458
9487
  valid.push(name), definition && definitions.push({
9459
9488
  name: name,
9460
- fields: definition.fields
9489
+ fields: definition.fields,
9490
+ ...definition.roleAliases === void 0 ? {} : {
9491
+ roleAliases: definition.roleAliases
9492
+ }
9461
9493
  });
9462
9494
  }
9463
9495
  return {
@@ -9974,6 +10006,7 @@ function WorkflowProvider(props) {
9974
10006
  engine: engine,
9975
10007
  binding: binding,
9976
10008
  mappings: mappings,
10009
+ previewHydration: config.previewHydration,
9977
10010
  mappingIssues: issues,
9978
10011
  mappingStarts: starts,
9979
10012
  mappingFields: fields,
@@ -9981,7 +10014,7 @@ function WorkflowProvider(props) {
9981
10014
  effectHandlers: engine.effectHandlers,
9982
10015
  autoStartByType: autoStartByType,
9983
10016
  autoStartDefinitions: autoStartDefinitions
9984
- }), [ register, unregister, isDocResolved, entriesStore, actualTypes, requestInstance, releaseInstance, requestEvaluation, releaseEvaluation, seedInstance, openStartDialog, closeStartDialog, startRequest2, loading, discoveryInvalid, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding, mappings, issues, starts, fields, latestVersions, autoStartByType, autoStartDefinitions ]);
10017
+ }), [ register, unregister, isDocResolved, entriesStore, actualTypes, requestInstance, releaseInstance, requestEvaluation, releaseEvaluation, seedInstance, openStartDialog, closeStartDialog, startRequest2, loading, discoveryInvalid, fireActionFor, editFieldFor, previewFieldFor, discardFieldPreviewFor, drainEffectsFor, completeEffectFor, engine, binding, mappings, config.previewHydration, issues, starts, fields, latestVersions, autoStartByType, autoStartDefinitions ]);
9985
10018
  /* @__PURE__ */
9986
10019
  return jsxs(WorkflowContext.Provider, {
9987
10020
  value: value,
@@ -10083,7 +10116,7 @@ function logOnce(messages, logged) {
10083
10116
  for (const message of messages) logged.has(message) || (logged.add(message), console.warn(`[workflow-studio-plugin] ${message}`));
10084
10117
  }
10085
10118
 
10086
- function AssigneesInput({value: value, onChange: onChange}) {
10119
+ function AssigneesInput({value: value, onChange: onChange, eligibleRoles: eligibleRoles, roleAliases: roleAliases}) {
10087
10120
  const [open, setOpen] = useState(!1), remove = index => onChange(value.filter((_, i) => i !== index));
10088
10121
  /* @__PURE__ */
10089
10122
  return jsxs(Stack, {
@@ -10117,7 +10150,9 @@ function AssigneesInput({value: value, onChange: onChange}) {
10117
10150
  wrap: "wrap",
10118
10151
  children: /* @__PURE__ */ jsx(DismissablePopover, {
10119
10152
  content: /* @__PURE__ */ jsx(AssigneePicker, {
10153
+ eligibleRoles: eligibleRoles,
10120
10154
  onChange: next => onChange([ ...next ]),
10155
+ roleAliases: roleAliases,
10121
10156
  value: value
10122
10157
  }),
10123
10158
  onDismiss: () => setOpen(!1),
@@ -10186,11 +10221,29 @@ function ChecklistInput({value: value, onChange: onChange}) {
10186
10221
  });
10187
10222
  }
10188
10223
 
10189
- function ReleasePicker({value: value, onChange: onChange}) {
10190
- const {binding: binding} = useWorkflowContext(), {data: data, loading: loading, error: error} = useActiveReleases(), releases = useMemo(() => data.filter(release => release.state === "active").map(release => ({
10224
+ function titleOf(release) {
10225
+ return release.metadata.title ?? release.name;
10226
+ }
10227
+
10228
+ function useReleaseTitles() {
10229
+ const {data: data} = useActiveReleases();
10230
+ return useMemo(() => new Map(data.map(release => [ release.name, titleOf(release) ])), [ data ]);
10231
+ }
10232
+
10233
+ function useActiveReleaseOptions() {
10234
+ const {data: data, loading: loading, error: error} = useActiveReleases(), releases = useMemo(() => data.filter(release => release.state === "active").map(release => ({
10191
10235
  name: release.name,
10192
- title: release.metadata.title ?? release.name
10193
- })).toSorted((a, b) => a.title.localeCompare(b.title)), [ data ]), labelOf = useMemo(() => {
10236
+ title: titleOf(release)
10237
+ })).toSorted((a, b) => a.title.localeCompare(b.title)), [ data ]);
10238
+ return {
10239
+ error: error,
10240
+ loading: loading,
10241
+ releases: releases
10242
+ };
10243
+ }
10244
+
10245
+ function ReleasePicker({value: value, onChange: onChange}) {
10246
+ const {binding: binding} = useWorkflowContext(), {error: error, loading: loading, releases: releases} = useActiveReleaseOptions(), labelOf = useMemo(() => {
10194
10247
  const m = new Map(releases.map(r => [ r.name, r.title ]));
10195
10248
  return name => m.get(name) ?? name;
10196
10249
  }, [ releases ]);
@@ -10458,8 +10511,10 @@ const docRefInput = ({entry: entry, docType: docType, releaseId: releaseId, valu
10458
10511
  onChange: onChange,
10459
10512
  value: value ?? []
10460
10513
  }),
10461
- assignees: ({value: value, onChange: onChange}) => /* @__PURE__ */ jsx(AssigneesInput, {
10514
+ assignees: ({entry: entry, roleAliases: roleAliases, value: value, onChange: onChange}) => /* @__PURE__ */ jsx(AssigneesInput, {
10515
+ eligibleRoles: entry.roles,
10462
10516
  onChange: onChange,
10517
+ roleAliases: roleAliases,
10463
10518
  value: value ?? []
10464
10519
  }),
10465
10520
  array: ({entry: entry, value: value, onChange: onChange}) => {
@@ -10501,7 +10556,7 @@ function FieldInput(props) {
10501
10556
  });
10502
10557
  }
10503
10558
 
10504
- function InitFieldRow({entry: entry, docType: docType, releaseId: releaseId, value: value, onChange: onChange}) {
10559
+ function InitFieldRow({entry: entry, docType: docType, releaseId: releaseId, roleAliases: roleAliases, value: value, onChange: onChange}) {
10505
10560
  const label = entry.title ?? entry.name;
10506
10561
  /* @__PURE__ */
10507
10562
  return jsxs(Stack, {
@@ -10525,6 +10580,7 @@ function InitFieldRow({entry: entry, docType: docType, releaseId: releaseId, val
10525
10580
  entry: entry,
10526
10581
  onChange: onChange,
10527
10582
  releaseId: releaseId,
10583
+ roleAliases: roleAliases,
10528
10584
  value: value
10529
10585
  }) ]
10530
10586
  });
@@ -10574,7 +10630,7 @@ function StartFooter({canStart: canStart, starting: starting, startLabel: startL
10574
10630
  });
10575
10631
  }
10576
10632
 
10577
- function StartInputList({initFields: initFields, mapping: mapping, releaseId: releaseId, values: values, onChange: onChange}) {
10633
+ function StartInputList({initFields: initFields, mapping: mapping, releaseId: releaseId, roleAliases: roleAliases, values: values, onChange: onChange}) {
10578
10634
  return initFields.length === 0 ? /* @__PURE__ */ jsx(Text, {
10579
10635
  muted: !0,
10580
10636
  size: 1,
@@ -10585,6 +10641,7 @@ function StartInputList({initFields: initFields, mapping: mapping, releaseId: re
10585
10641
  entry: entry,
10586
10642
  onChange: v => onChange(entry.name, v),
10587
10643
  releaseId: releaseId,
10644
+ roleAliases: roleAliases,
10588
10645
  value: values[entry.name] ?? null
10589
10646
  }, entry.name))
10590
10647
  });
@@ -10715,6 +10772,7 @@ function StartWorkflowForm({request: request, onClose: onClose}) {
10715
10772
  mapping: mapping,
10716
10773
  onChange: setValue,
10717
10774
  releaseId: releaseId,
10775
+ roleAliases: definition.roleAliases,
10718
10776
  values: values
10719
10777
  }),
10720
10778
  /* @__PURE__ */ jsx(StartFooter, {
@@ -10769,11 +10827,12 @@ function AutoStartInputDialog(props) {
10769
10827
  }),
10770
10828
  /* @__PURE__ */ jsx(Stack, {
10771
10829
  gap: 4,
10772
- children: inputs.map(({entry: entry}) => /* @__PURE__ */ jsx(InitFieldRow, {
10830
+ children: inputs.map(({entry: entry, roleAliases: roleAliases}) => /* @__PURE__ */ jsx(InitFieldRow, {
10773
10831
  docType: docType,
10774
10832
  entry: entry,
10775
10833
  onChange: value => setValue(entry.name, value),
10776
10834
  releaseId: void 0,
10835
+ roleAliases: roleAliases,
10777
10836
  value: values[entry.name] ?? null
10778
10837
  }, entry.name))
10779
10838
  }),
@@ -10802,23 +10861,65 @@ function subjectEntry(definition) {
10802
10861
  return documentSubjectEntry(definition);
10803
10862
  }
10804
10863
 
10805
- function autoStartInputs(args) {
10864
+ function autoStartInputPlan(args) {
10806
10865
  const byName = /* @__PURE__ */ new Map;
10807
10866
  for (const name of args.workflows) {
10808
10867
  const definition = args.definitions.get(name);
10809
10868
  if (definition !== void 0) for (const entry of extraRequiredInputs(definition)) {
10810
- const existing = byName.get(entry.name);
10811
- existing === void 0 ? byName.set(entry.name, {
10869
+ const conflict = mergeAutoStartInput(byName, {
10812
10870
  entry: entry,
10813
- workflows: [ name ]
10814
- }) : existing.workflows.push(name);
10871
+ workflow: name,
10872
+ roleAliases: definition.roleAliases
10873
+ });
10874
+ if (conflict !== void 0) return {
10875
+ inputs: [],
10876
+ conflict: conflict
10877
+ };
10815
10878
  }
10816
10879
  }
10817
- return [ ...byName.values() ];
10880
+ return {
10881
+ inputs: [ ...byName.values() ]
10882
+ };
10883
+ }
10884
+
10885
+ function mergeAutoStartInput(byName, args) {
10886
+ const existing = byName.get(args.entry.name);
10887
+ if (existing === void 0) {
10888
+ byName.set(args.entry.name, {
10889
+ entry: args.entry,
10890
+ workflows: [ args.workflow ],
10891
+ ...args.roleAliases === void 0 ? {} : {
10892
+ roleAliases: args.roleAliases
10893
+ }
10894
+ });
10895
+ return;
10896
+ }
10897
+ if (!sameRoleSet(existing.entry.roles, args.entry.roles)) return `Auto-start input "${args.entry.name}" is shared by workflows "${existing.workflows.join('", "')}" and "${args.workflow}" with different role constraints`;
10898
+ existing.workflows.push(args.workflow), sameRoleAliases(existing.roleAliases, args.roleAliases) || delete existing.roleAliases;
10899
+ }
10900
+
10901
+ function sameRoleSet(left, right) {
10902
+ return roleSetKey(left) === roleSetKey(right);
10903
+ }
10904
+
10905
+ function roleSetKey(roles) {
10906
+ return roles === void 0 ? void 0 : JSON.stringify(sortedUnique(roles));
10907
+ }
10908
+
10909
+ function sameRoleAliases(left, right) {
10910
+ return roleAliasesKey(left) === roleAliasesKey(right);
10911
+ }
10912
+
10913
+ function roleAliasesKey(aliases) {
10914
+ if (aliases !== void 0) return JSON.stringify(Object.entries(aliases).map(([role, fulfillers]) => [ role, sortedUnique(fulfillers) ]).toSorted(([left], [right]) => left.localeCompare(right)));
10915
+ }
10916
+
10917
+ function sortedUnique(values) {
10918
+ return [ ...new Set(values) ].toSorted();
10818
10919
  }
10819
10920
 
10820
10921
  function autoStartAction(args) {
10821
- return args.fired ? args.settled ? "reveal" : "starting" : args.pendingCount === 0 ? "reveal" : args.resolved ? args.needsInput ? "collect" : "silent-start" : "wait";
10922
+ return args.fired ? args.settled ? "reveal" : "starting" : args.blocked || args.pendingCount === 0 ? "reveal" : args.resolved ? args.needsInput ? "collect" : "silent-start" : "wait";
10822
10923
  }
10823
10924
 
10824
10925
  function pendingWorkflows(workflows, live) {
@@ -10875,10 +10976,14 @@ function AutoStartDriver(props) {
10875
10976
  engine: engine
10876
10977
  }), {selectedReleaseId: selectedReleaseId} = usePerspective(), {entries: entries} = useWorkflowsForDocument(rawDocId), docId = getPublishedId(rawDocId), valueRef = useRef(value);
10877
10978
  valueRef.current = value;
10878
- const pending = useMemo(() => pendingWorkflows(workflows, new Set(entries.map(entry => entry.instance.definition))), [ workflows, entries ]), inputs = useMemo(() => autoStartInputs({
10979
+ const pending = useMemo(() => pendingWorkflows(workflows, new Set(entries.map(entry => entry.instance.definition))), [ workflows, entries ]), inputPlan = useMemo(() => autoStartInputPlan({
10879
10980
  workflows: pending,
10880
10981
  definitions: autoStartDefinitions
10881
- }), [ pending, autoStartDefinitions ]), definitionsResolved = workflows.every(name => autoStartDefinitions.has(name)), pendingRef = useRef(pending);
10982
+ }), [ pending, autoStartDefinitions ]), inputs = inputPlan.inputs;
10983
+ useEffect(() => {
10984
+ inputPlan.conflict !== void 0 && console.warn(`[Workflows] Auto-start skipped. ${inputPlan.conflict}`);
10985
+ }, [ inputPlan.conflict ]);
10986
+ const definitionsResolved = workflows.every(name => autoStartDefinitions.has(name)), pendingRef = useRef(pending);
10882
10987
  pendingRef.current = pending;
10883
10988
  const instanceIds = useRef(/* @__PURE__ */ new Map), instanceIdFor = useCallback(workflow => {
10884
10989
  const held = instanceIds.current.get(workflow);
@@ -10930,6 +11035,7 @@ function AutoStartDriver(props) {
10930
11035
  resolved: definitionsResolved && isDocResolved(docId),
10931
11036
  pendingCount: pending.length,
10932
11037
  needsInput: inputs.length > 0,
11038
+ blocked: inputPlan.conflict !== void 0,
10933
11039
  fired: fired,
10934
11040
  settled: settled
10935
11041
  });
@@ -11375,19 +11481,13 @@ function StartWorkflowDialogHost() {
11375
11481
  }
11376
11482
 
11377
11483
  const TOOL_TAB_LABELS = {
11378
- overview: "Workflows",
11379
- "all-documents": "All documents",
11380
- "for-me": "For me"
11484
+ overview: "Overview",
11485
+ "for-me": "For me",
11486
+ definitions: "Definitions"
11381
11487
  }, TOOL_TAB_VALUES = Object.keys(TOOL_TAB_LABELS), TOOL_TABS = TOOL_TAB_VALUES.map(value => ({
11382
11488
  value: value,
11383
11489
  label: TOOL_TAB_LABELS[value]
11384
- })), LANDING_TAB = "overview", TASKS_TAB = "all-documents", WORKFLOW_PAGE_LABELS = {
11385
- workflow: "Documents",
11386
- definition: "Definition"
11387
- }, 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 => ({
11388
- value: value,
11389
- label: WORKFLOW_PAGE_LABELS[value]
11390
- })), toolRouter = route.create("/", [ route.create("/instance/:instanceId"), route.create(`/${LANDING_TAB}/:workflowName`, [ route.create("/:workflowPage") ]), route.create("/:workflowsTab") ]);
11490
+ })), LANDING_TAB = "overview", DEFINITIONS_TAB = "definitions", toolRouter = route.create("/", [ route.create(`/${DEFINITIONS_TAB}/:workflowName`), route.create("/:workflowsTab") ]);
11391
11491
 
11392
11492
  function toolTabState(tab) {
11393
11493
  return {
@@ -11405,39 +11505,17 @@ function workflowState(workflowName) {
11405
11505
  };
11406
11506
  }
11407
11507
 
11408
- function instanceState(instanceId) {
11409
- return {
11410
- instanceId: instanceId
11411
- };
11412
- }
11413
-
11414
11508
  function tabSelectionNavigates(current, tab) {
11415
11509
  return !(current.kind === "home" && tab === current.tab);
11416
11510
  }
11417
11511
 
11418
- function toolTabLabel(tab) {
11419
- return TOOL_TAB_LABELS[tab];
11420
- }
11421
-
11422
- function backToTabLabel(tab) {
11423
- return `Back to ${toolTabLabel(tab)}`;
11424
- }
11425
-
11426
- function workflowPageState(page, workflowName) {
11427
- return page === DEFAULT_WORKFLOW_PAGE ? workflowState(workflowName) : {
11428
- ...workflowState(workflowName),
11429
- workflowPage: page
11430
- };
11431
- }
11432
-
11433
11512
  function toolRoute(state) {
11434
- const {instanceId: instanceId, workflowName: workflowName} = state;
11435
- if (typeof instanceId == "string") return {
11436
- kind: "instance",
11437
- instanceId: instanceId,
11438
- tab: TASKS_TAB
11513
+ const {workflowName: workflowName} = state;
11514
+ if (typeof workflowName == "string") return {
11515
+ kind: "definition",
11516
+ workflowName: workflowName,
11517
+ tab: DEFINITIONS_TAB
11439
11518
  };
11440
- if (typeof workflowName == "string") return workflowRoute(workflowName, state.workflowPage);
11441
11519
  const tab = pathSegmentName({
11442
11520
  segment: state.workflowsTab,
11443
11521
  names: TOOL_TAB_VALUES
@@ -11451,24 +11529,11 @@ function toolRoute(state) {
11451
11529
  };
11452
11530
  }
11453
11531
 
11454
- function workflowRoute(workflowName, pageSegment) {
11455
- if (pageSegment === void 0) return {
11456
- kind: "workflow",
11457
- workflowName: workflowName,
11458
- tab: LANDING_TAB
11459
- };
11460
- const page = pathSegmentName({
11461
- segment: pageSegment,
11462
- names: WORKFLOW_PAGES
11463
- });
11464
- return page === void 0 ? {
11465
- kind: "unnamed",
11466
- tab: LANDING_TAB
11467
- } : {
11468
- kind: page,
11469
- workflowName: workflowName,
11470
- tab: LANDING_TAB
11532
+ function definitionsRouteOf(route2) {
11533
+ if (route2.kind === "definition") return {
11534
+ workflowName: route2.workflowName
11471
11535
  };
11536
+ if (route2.kind === "home" && route2.tab === "definitions") return {};
11472
11537
  }
11473
11538
 
11474
11539
  const WorkflowsToolRoot = lazy(() => import("./workflows-tool-root.js"));
@@ -11580,4 +11645,4 @@ function WorkflowRootInput(props) {
11580
11645
  });
11581
11646
  }
11582
11647
 
11583
- export { AbortWorkflowDialog, ActivityDetailDialog, ActivityLog, ActivityRow, AlertGlyph, BreadcrumbTail, CodeChip, CountedHeading, DismissablePopover, DocPreviewLink, DocRefFace, EmptyState, ForMeEmptyState, Hairline, HoverHint, InlineEmphasis, InstanceFaultNote, InstanceSnapshotBody, InvalidDocNotice, LinkChip, LoadingRow, LogEventOnMount, MetaRow, MetricPair, NoteBanner, RoleAssignedNotice, SpinnerSlot, StageFace, StaleLock, TOAST_ID, TOOL_TABS, TabSwitch, UnreadableDocsNote, WORKFLOW_API_VERSION, WORKFLOW_PAGE_TABS, WorkflowBoardWorkflowSelected, WorkflowDefinitionDetailViewed, WorkflowInstanceDetailViewed, WorkflowTaskFiltersApplied, WorkflowTitleSeedDrifted, WorkflowToolOpened, activityRowProps, assigneesOf, backToTabLabel, committedRowFace, createSubscribers, datesOf, definitionFingerprint, definitionSnapshotOf, describeError, dueDatesOf, findActivity, formatDate, formatShortAgo, formatShortDateTime, formatTimeAgo, gdrLocality, identityOf, instanceBreadcrumb, instanceState, instanceTitle, isActivityAssignedTo, isDueDatePast, isEvaluationStale, isLiveEntry, isOpenActivityStatus, isRoleAssignedTo, landingState, mappingIssueDetail, namesNoDeployedDefinition, openActivityGone, openableSchemaType, parseStoredDateValue, readDeployedDefinitions, rowAssignControlState, rowDateControlState, stageTitle, stateByActivity, tabSelectionNavigates, toolRoute, toolTabState, useAssignmentIdentity, useContainerToken, useDefinition, useLogEventOnMount, useMinuteClock, useProjectMembers, useSpaceToken, useUserDisplays, useWorkflowContext, useWorkflowInstanceEntry, useWorkflowToast, workflowDefaultDocumentNode, workflowPageState, workflowState, workflowStudioPlugin, workflowsView };
11648
+ export { AbortWorkflowDialog, ActivityDetailDialog, ActivityLog, AgoStamp, AlertGlyph, CodeChip, CountedHeading, DismissablePopover, DocPreviewLink, DocRefFace, EmptyState, HoverHint, InstanceFaultNote, InstanceSnapshotBody, InvalidDocNotice, LoadingRow, LogEventOnMount, MetaRow, MetricPair, NoteBanner, RUN_SEARCH_PARAM, RoleAssignedNotice, RowAssignees, SpinnerSlot, TOOL_TABS, TabSwitch, UnreadableDocsNote, WORKFLOW_API_VERSION, WorkflowBoardWorkflowSelected, WorkflowDefinitionDetailViewed, WorkflowInstanceDetailViewed, WorkflowTitleSeedDrifted, WorkflowToolOpened, assigneesOf, countBy, definitionFingerprint, definitionsRouteOf, describeError, dueDatesOf, findActivity, formatShortDateTime, formatTimeAgo, gdrLocality, identityOf, instanceBreadcrumb, instanceTitle, isDueDatePast, isEvaluationStale, isLiveEntry, isOpenActivityStatus, landingState, mappingIssueDetail, namesNoDeployedDefinition, openActivityGone, openableSchemaType, parseStoredDateValue, readDeployedDefinitions, stageTitle, tabSelectionNavigates, toolRoute, toolTabState, useAssignmentIdentity, useAvatarSize, useCapTrimFor, useContainerToken, useCurrentUserId, useDefinition, useLogEventOnMount, useMinuteClock, useProjectMembers, useRadiusToken, useReleaseTitles, useSpaceToken, useTextIconSize, useUserDisplays, useWorkflowContext, useWorkflowInstanceEntry, workflowDefaultDocumentNode, workflowState, workflowStudioPlugin, workflowsView };