@sanity/workflow-studio-plugin 0.30.0 → 0.31.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 CHANGED
@@ -1,5 +1,50 @@
1
1
  # @sanity/workflow-studio-plugin
2
2
 
3
+ ## 0.31.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ae876ad: The Workflows tool Overview table and board cards now say how late a run is instead of only that it is late. A run with one overdue task shows a calendar glyph and a compact span in caution — `4d` — and a run with several shows the count instead (`3 tasks`). Hovering the mark opens the same stage-tasks panel the row's people open when a listed human task is late, and that panel now carries the same calendar and span beside each task title, so the row's figure can be traced to the task it counts. Lateness that sits on an automation has no row in that panel, even if other human tasks are still open, and keeps a sentence: `3 tasks overdue — the longest by 4d`.
8
+
9
+ A run that cannot continue now wears a critical disc rather than a bare outline glyph, and its hover text names the cause instead of restating that the document is blocked: a task sent back is quoted by title, an automation that reported a failure reads `Automation “Notify legal” failed`, and one that was claimed and never reported back reads `Automation “Notify legal” didn’t finish` — the two are no longer told as the same fault.
10
+
11
+ The Tasks column now fits as many assignee groups as the column is actually wide enough for, rather than always three, and keeps room for the `+N` counter. Previously a row whose tasks were held by several people pushed the counter past the column's edge, where it lost its number and left a stray `+` sitting against the next column; a wide window now also fills the column it was given instead of stopping at three groups.
12
+
13
+ **No upgrade action required.** Both marks are derived from the same committed instance state as before; no definition, stored field, or configuration changes.
14
+
15
+ **Docs impact:** Update the Workflows tool guide wherever it pictures or describes the Overview attention column and the board cards' marks — the overdue mark is now a calendar with a span rather than a warning triangle, it opens the stage-tasks panel, and the blocked mark names its cause.
16
+
17
+ - b593a51: The Workflows tool Overview Open runs table labels its people column **Tasks**, and each cell (and each board card) groups holders by the current stage's human activities instead of flattening them into one stack. Overlap means one task, a gap means the next, a dashed circle with a person glyph means nobody is holding that task, and hover lists every task in the stage. Inside a mixed group, role squares sit before people.
18
+
19
+ Automated activities are left out of the cell only when the deployed workflow the run is pinned to says so. A run pinned to an older version, or one whose workflow the catalog no longer carries, shows all of its open activities as tasks rather than risking a hidden one.
20
+
21
+ The run scope picker beside the workflow picker now rests on the surrounding surface — white in a light scheme, the panel colour in a dark one — instead of a filled grey chip, and keeps its outline and hover feedback.
22
+
23
+ **No upgrade action required.**
24
+
25
+ **Docs impact:** Update the Workflows tool guide wherever it names the Overview Assignees column or implies a run itself has assignees.
26
+
27
+ - 7832486: The Workflows tool Open runs header now keeps the applied filter chips and **Clear filters** at the right of the row, next to the **Add filter** button and the Table/Board toggle, instead of at the left beside the workflow and scope pickers. The workflow picker and the open/closed scope picker stay on the left. Applied filters grow leftward from the **Add filter** button, so adding a chip no longer moves that button, and a row too wide for the viewport wraps the filter group rather than pushing the pickers off the line.
28
+
29
+ **No upgrade action required.** Filter behaviour, the saved view, and the URL parameters that address a filtered view are unchanged.
30
+
31
+ **Docs impact:** Update any Workflows tool guide screenshot or prose that places the applied filters beside the workflow picker at the left of the Open runs header.
32
+
33
+ ### Patch Changes
34
+
35
+ - ff72ece: Reader-model errors and the Studio Workflows tool now link to the canonical `/docs/workflows` documentation routes.
36
+
37
+ **No upgrade action required.** Permanent redirects preserve the former `/docs/editorial-workflows` URLs.
38
+
39
+ **Docs impact:** Publish the Workflows documentation at `/docs/workflows` and retain permanent redirects from every previously published `/docs/editorial-workflows` route.
40
+
41
+ - Updated dependencies [ff72ece]
42
+ - @sanity/workflow-engine@0.31.0
43
+ - @sanity/workflow-components@0.31.0
44
+ - @sanity/workflow-diagram@0.31.0
45
+ - @sanity/workflow-react@0.31.0
46
+ - @sanity/workflow-studio@0.31.0
47
+
3
48
  ## 0.30.0
4
49
 
5
50
  ### Minor Changes
package/README.md CHANGED
@@ -377,7 +377,7 @@ into its workflows, so instances whose documents are gone stay in-flight
377
377
  until something settles them. A document-delete
378
378
  function settles them the moment the deletion happens, on the robot token —
379
379
  see the cookbook recipe
380
- [Handle a deleted subject document](https://www.sanity.io/docs/editorial-workflows/cookbook-handle-deleted-subject).
380
+ [Handle a deleted subject document](https://www.sanity.io/docs/workflows/cookbook-handle-deleted-subject).
381
381
 
382
382
  ## Limitations
383
383
 
@@ -408,9 +408,12 @@ function formatShortAgo(value, now) {
408
408
  }
409
409
 
410
410
  function formatShortSpan(value, now) {
411
- const d = new Date(value);
412
- if (Number.isNaN(d.getTime())) return "—";
413
- const seconds = Math.floor((now.getTime() - d.getTime()) / 1e3);
411
+ return shortSpanOf(new Date(value), now);
412
+ }
413
+
414
+ function shortSpanOf(from, now) {
415
+ if (from === void 0 || Number.isNaN(from.getTime())) return "—";
416
+ const seconds = Math.floor((now.getTime() - from.getTime()) / 1e3);
414
417
  if (seconds < 60) return "now";
415
418
  const minutes = Math.floor(seconds / 60);
416
419
  if (minutes < 60) return `${minutes}m`;
@@ -725,6 +728,10 @@ function assigneesOf(entries) {
725
728
  return entries.flatMap(entry => entry._type === "assignees" ? entry.value : []);
726
729
  }
727
730
 
731
+ function userIdsOf(assignees) {
732
+ return assignees.flatMap(assignee => assignee.type === "user" ? [ assignee.id ] : []);
733
+ }
734
+
728
735
  function assigneeEdit(current, next) {
729
736
  const changed = changedAssignee(current, next);
730
737
  if (changed !== void 0) return next.some(item => workflowComponents.sameAssignee(item, changed)) ? {
@@ -904,8 +911,15 @@ const ACTIVITY_STATUS_LABEL = {
904
911
  skipped: "Skipped"
905
912
  };
906
913
 
914
+ function isHandsOff(args) {
915
+ return args.classification === "autonomous" && args.completesWithoutCaller === "yes";
916
+ }
917
+
907
918
  function showsAutomatedPill(activityEval) {
908
- return !workflowEngine.isTerminalActivityStatus(activityEval.status) && activityEval.classification === "autonomous" && activityEval.autonomy.completesWithoutCaller === "yes";
919
+ return !workflowEngine.isTerminalActivityStatus(activityEval.status) && isHandsOff({
920
+ classification: activityEval.classification,
921
+ completesWithoutCaller: activityEval.autonomy.completesWithoutCaller
922
+ });
909
923
  }
910
924
 
911
925
  function showsBlockedTag(activityEval) {
@@ -1318,6 +1332,10 @@ function disambiguatedNames(displays) {
1318
1332
  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
1333
  }
1320
1334
 
1335
+ function uniqueIds(ids) {
1336
+ return [ ...new Set(ids) ];
1337
+ }
1338
+
1321
1339
  function useUserDisplays(ids) {
1322
1340
  const {members: members} = useProjectMembers(), {users: users} = workflowStudio.useStudioProjectUsers(), meRaw = sanity.useCurrentUser(), me = react.useMemo(() => meRaw === null ? null : {
1323
1341
  ...meRaw,
@@ -4480,7 +4498,7 @@ function AvatarButton({avatar: avatar, onClick: onClick, onMouseDown: onMouseDow
4480
4498
  }
4481
4499
 
4482
4500
  function RowAssignees({assignees: assignees, hint: hint}) {
4483
- const ids = assignees.flatMap(item => item.type === "user" ? [ item.id ] : []), vocabulary = useProjectMembers(), roles = assignees.flatMap(item => item.type === "role" ? [ workflowComponents.memberRoleFor(vocabulary, item.role) ] : []), displays = useUserDisplays(ids);
4501
+ const ids = userIdsOf(assignees), vocabulary = useProjectMembers(), roles = assignees.flatMap(item => item.type === "role" ? [ workflowComponents.memberRoleFor(vocabulary, item.role) ] : []), displays = useUserDisplays(ids);
4484
4502
  if (ids.length === 0 && roles.length === 0) return null;
4485
4503
  const bothKinds = roles.length > 0 && displays.length > 0;
4486
4504
  /* @__PURE__ */
@@ -5737,6 +5755,13 @@ function GroupHeading({busy: busy, count: count, title: title, end: end}) {
5737
5755
 
5738
5756
  const EMPTY_METRIC_OPACITY = .5;
5739
5757
 
5758
+ function labelledImgProps(label) {
5759
+ return label === void 0 ? {} : {
5760
+ "aria-label": label,
5761
+ role: "img"
5762
+ };
5763
+ }
5764
+
5740
5765
  function MetricText({children: children, tone: tone}) {
5741
5766
  return tone === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
5742
5767
  muted: !0,
@@ -5749,33 +5774,41 @@ function MetricText({children: children, tone: tone}) {
5749
5774
  });
5750
5775
  }
5751
5776
 
5752
- function MetricPair({Icon: Icon, empty: empty, face: face, tone: tone, value: value}) {
5777
+ function MetricPair({face: face, ...lockup}) {
5753
5778
  /* @__PURE__ */
5754
5779
  return jsxRuntime.jsx(HoverHint, {
5755
5780
  ...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
- }) ]
5781
+ children: /* @__PURE__ */ jsxRuntime.jsx(MetricLockup, {
5782
+ ...lockup
5775
5783
  })
5776
5784
  });
5777
5785
  }
5778
5786
 
5787
+ function MetricLockup({Icon: Icon, empty: empty, label: label, tone: tone, value: value}) {
5788
+ /* @__PURE__ */
5789
+ return jsxRuntime.jsxs(ui.Flex, {
5790
+ align: "center",
5791
+ gap: 2,
5792
+ style: empty ? {
5793
+ opacity: EMPTY_METRIC_OPACITY
5794
+ } : void 0,
5795
+ ...labelledImgProps(label),
5796
+ children: [
5797
+ /* @__PURE__ */ jsxRuntime.jsx(MetricText, {
5798
+ tone: tone,
5799
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {
5800
+ style: {
5801
+ color: "inherit"
5802
+ }
5803
+ })
5804
+ }),
5805
+ /* @__PURE__ */ jsxRuntime.jsx(MetricText, {
5806
+ tone: tone,
5807
+ children: value
5808
+ }) ]
5809
+ });
5810
+ }
5811
+
5779
5812
  function AlertGlyph({Icon: Icon, hint: hint, label: label, tone: tone}) {
5780
5813
  /* @__PURE__ */
5781
5814
  return jsxRuntime.jsx(HoverHint, {
@@ -5784,10 +5817,7 @@ function AlertGlyph({Icon: Icon, hint: hint, label: label, tone: tone}) {
5784
5817
  size: 1,
5785
5818
  tone: tone,
5786
5819
  children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {
5787
- ...label === void 0 ? {} : {
5788
- "aria-label": label,
5789
- role: "img"
5790
- },
5820
+ ...labelledImgProps(label),
5791
5821
  style: {
5792
5822
  color: "inherit"
5793
5823
  }
@@ -5796,6 +5826,37 @@ function AlertGlyph({Icon: Icon, hint: hint, label: label, tone: tone}) {
5796
5826
  });
5797
5827
  }
5798
5828
 
5829
+ function AlertChip({Icon: Icon, hint: hint, label: label, tone: tone}) {
5830
+ const glyph = useTextIconSize(), disc = glyph + useSpaceToken(1) * 2;
5831
+ /* @__PURE__ */
5832
+ return jsxRuntime.jsx(HoverHint, {
5833
+ text: hint,
5834
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.Card, {
5835
+ radius: "full",
5836
+ style: {
5837
+ alignItems: "center",
5838
+ display: "flex",
5839
+ height: disc,
5840
+ justifyContent: "center",
5841
+ width: disc
5842
+ },
5843
+ tone: tone,
5844
+ children: /* @__PURE__ */ jsxRuntime.jsx(sanity.TextWithTone, {
5845
+ size: 1,
5846
+ tone: tone,
5847
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {
5848
+ ...labelledImgProps(label),
5849
+ style: {
5850
+ color: "inherit",
5851
+ height: glyph,
5852
+ width: glyph
5853
+ }
5854
+ })
5855
+ })
5856
+ })
5857
+ });
5858
+ }
5859
+
5799
5860
  function ActivityDateControl({instanceId: instanceId, state: state, surface: surface, dueDates: dueDates}) {
5800
5861
  const editField = useEditField(surface), {save: save} = useSaveField({
5801
5862
  instanceId: instanceId
@@ -6409,7 +6470,7 @@ function AvatarCapAligned({children: children}) {
6409
6470
  }
6410
6471
 
6411
6472
  function AssigneesFace({assignees: assignees}) {
6412
- const vocabulary = useProjectMembers(), userIds = assignees.flatMap(a => a.type === "user" ? [ a.id ] : []), roles = assignees.flatMap(a => a.type === "role" ? [ workflowComponents.roleLabelFor(vocabulary, a.role) ] : []);
6473
+ const vocabulary = useProjectMembers(), userIds = userIdsOf(assignees), roles = assignees.flatMap(a => a.type === "role" ? [ workflowComponents.roleLabelFor(vocabulary, a.role) ] : []);
6413
6474
  /* @__PURE__ */
6414
6475
  return jsxRuntime.jsxs(jsxRuntime.Fragment, {
6415
6476
  children: [ userIds.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(AvatarCapAligned, {
@@ -11580,6 +11641,8 @@ exports.ActivityLog = ActivityLog;
11580
11641
 
11581
11642
  exports.AgoStamp = AgoStamp;
11582
11643
 
11644
+ exports.AlertChip = AlertChip;
11645
+
11583
11646
  exports.AlertGlyph = AlertGlyph;
11584
11647
 
11585
11648
  exports.CodeChip = CodeChip;
@@ -11608,6 +11671,8 @@ exports.LogEventOnMount = LogEventOnMount;
11608
11671
 
11609
11672
  exports.MetaRow = MetaRow;
11610
11673
 
11674
+ exports.MetricLockup = MetricLockup;
11675
+
11611
11676
  exports.MetricPair = MetricPair;
11612
11677
 
11613
11678
  exports.NoteBanner = NoteBanner;
@@ -11616,8 +11681,6 @@ exports.RUN_SEARCH_PARAM = RUN_SEARCH_PARAM;
11616
11681
 
11617
11682
  exports.RoleAssignedNotice = RoleAssignedNotice;
11618
11683
 
11619
- exports.RowAssignees = RowAssignees;
11620
-
11621
11684
  exports.SpinnerSlot = SpinnerSlot;
11622
11685
 
11623
11686
  exports.TOOL_TABS = TOOL_TABS;
@@ -11638,6 +11701,8 @@ exports.WorkflowTitleSeedDrifted = WorkflowTitleSeedDrifted;
11638
11701
 
11639
11702
  exports.WorkflowToolOpened = WorkflowToolOpened;
11640
11703
 
11704
+ exports.activityLabel = activityLabel;
11705
+
11641
11706
  exports.assigneesOf = assigneesOf;
11642
11707
 
11643
11708
  exports.countBy = countBy;
@@ -11648,6 +11713,8 @@ exports.definitionsRouteOf = definitionsRouteOf;
11648
11713
 
11649
11714
  exports.describeError = describeError;
11650
11715
 
11716
+ exports.disambiguatedNames = disambiguatedNames;
11717
+
11651
11718
  exports.dueDatesOf = dueDatesOf;
11652
11719
 
11653
11720
  exports.findActivity = findActivity;
@@ -11668,6 +11735,8 @@ exports.isDueDatePast = isDueDatePast;
11668
11735
 
11669
11736
  exports.isEvaluationStale = isEvaluationStale;
11670
11737
 
11738
+ exports.isHandsOff = isHandsOff;
11739
+
11671
11740
  exports.isLiveEntry = isLiveEntry;
11672
11741
 
11673
11742
  exports.isOpenActivityStatus = isOpenActivityStatus;
@@ -11686,6 +11755,8 @@ exports.parseStoredDateValue = parseStoredDateValue;
11686
11755
 
11687
11756
  exports.readDeployedDefinitions = readDeployedDefinitions;
11688
11757
 
11758
+ exports.shortSpanOf = shortSpanOf;
11759
+
11689
11760
  exports.stageTitle = stageTitle;
11690
11761
 
11691
11762
  exports.tabSelectionNavigates = tabSelectionNavigates;
@@ -11694,6 +11765,8 @@ exports.toolRoute = toolRoute;
11694
11765
 
11695
11766
  exports.toolTabState = toolTabState;
11696
11767
 
11768
+ exports.uniqueIds = uniqueIds;
11769
+
11697
11770
  exports.useAssignmentIdentity = useAssignmentIdentity;
11698
11771
 
11699
11772
  exports.useAvatarSize = useAvatarSize;
@@ -11726,6 +11799,8 @@ exports.useWorkflowContext = useWorkflowContext;
11726
11799
 
11727
11800
  exports.useWorkflowInstanceEntry = useWorkflowInstanceEntry;
11728
11801
 
11802
+ exports.userIdsOf = userIdsOf;
11803
+
11729
11804
  exports.workflowDefaultDocumentNode = workflowDefaultDocumentNode;
11730
11805
 
11731
11806
  exports.workflowState = workflowState;