sanity-plugin-workflow 1.0.0-beta.6 → 1.0.0-beta.7

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/lib/index.js CHANGED
@@ -693,25 +693,28 @@ function useWorkflowDocuments(schemaTypes) {
693
693
  _type
694
694
  } = document;
695
695
  const {
696
- documentId
696
+ documentId,
697
+ _rev
697
698
  } = document._metadata || {};
698
- await client.patch("workflow-metadata.".concat(documentId)).set({
699
+ await client.patch("workflow-metadata.".concat(documentId)).ifRevisionId(_rev).set({
699
700
  state: newStateId,
700
701
  orderRank: newOrder
701
- }).commit().then(() => {
702
+ }).commit().then(res => {
702
703
  var _a;
703
- return toast.push({
704
+ toast.push({
704
705
  title: "Moved to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
705
706
  status: "success"
706
707
  });
708
+ return res;
707
709
  }).catch(err => {
708
710
  var _a;
709
711
  setLocalDocuments(currentLocalData);
710
- return toast.push({
712
+ toast.push({
711
713
  title: "Failed to move to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
712
714
  description: err.message,
713
715
  status: "error"
714
716
  });
717
+ return null;
715
718
  });
716
719
  return {
717
720
  _id,
@@ -825,31 +828,44 @@ function CompleteButton(props) {
825
828
  apiVersion: API_VERSION
826
829
  });
827
830
  const toast = ui.useToast();
828
- const handleComplete = React__default.default.useCallback(id => {
831
+ const handleComplete = React__default.default.useCallback(event => {
832
+ const id = event.currentTarget.value;
833
+ if (!id) {
834
+ return;
835
+ }
829
836
  client.delete("workflow-metadata.".concat(id)).then(() => {
830
837
  toast.push({
831
838
  status: "success",
832
- title: "Workflow completed",
833
- description: id
839
+ title: "Workflow completed"
834
840
  });
835
841
  }).catch(() => {
836
842
  toast.push({
837
843
  status: "error",
838
- title: "Could not complete Workflow",
839
- description: id
844
+ title: "Could not complete Workflow"
840
845
  });
841
846
  });
842
847
  }, [client, toast]);
843
- return /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
844
- onClick: () => handleComplete(documentId),
845
- text: "Complete",
846
- icon: icons.CheckmarkIcon,
847
- tone: "positive",
848
- mode: "ghost",
849
- fontSize: 1,
850
- padding: 2,
851
- tabIndex: -1,
852
- disabled
848
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Tooltip, {
849
+ portal: true,
850
+ content: /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
851
+ padding: 2,
852
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
853
+ size: 1,
854
+ children: "Remove this document from Workflow"
855
+ })
856
+ }),
857
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
858
+ value: documentId,
859
+ onClick: handleComplete,
860
+ text: "Complete",
861
+ icon: icons.CheckmarkIcon,
862
+ tone: "positive",
863
+ mode: "ghost",
864
+ fontSize: 1,
865
+ padding: 2,
866
+ tabIndex: -1,
867
+ disabled
868
+ })
853
869
  });
854
870
  }
855
871
  function TimeAgo(_ref2) {
@@ -966,6 +982,7 @@ function DocumentCard(props) {
966
982
  var _a, _b;
967
983
  const {
968
984
  isDragDisabled,
985
+ isPatching,
969
986
  userRoleCanDrop,
970
987
  isDragging,
971
988
  item,
@@ -999,6 +1016,7 @@ function DocumentCard(props) {
999
1016
  let tone = defaultCardTone;
1000
1017
  if (!userRoleCanDrop) return isDarkMode ? "default" : "transparent";
1001
1018
  if (!documentId) return tone;
1019
+ if (isPatching) tone = isDarkMode ? "default" : "transparent";
1002
1020
  if (isDragging) tone = "positive";
1003
1021
  if ((state == null ? void 0 : state.requireValidation) && !isValidating && validation.length > 0) {
1004
1022
  if (validation.some(v => v.level === "error")) {
@@ -1008,7 +1026,7 @@ function DocumentCard(props) {
1008
1026
  }
1009
1027
  }
1010
1028
  return tone;
1011
- }, [defaultCardTone, userRoleCanDrop, isDarkMode, documentId, isDragging, isValidating, validation, state == null ? void 0 : state.requireValidation]);
1029
+ }, [defaultCardTone, userRoleCanDrop, isPatching, isDarkMode, documentId, isDragging, isValidating, validation, state == null ? void 0 : state.requireValidation]);
1012
1030
  React.useEffect(() => {
1013
1031
  if (!isValidating && validation.length > 0) {
1014
1032
  if (validation.some(v => v.level === "error")) {
@@ -1054,7 +1072,7 @@ function DocumentCard(props) {
1054
1072
  children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1055
1073
  flex: 1,
1056
1074
  children: /* @__PURE__ */jsxRuntime.jsx(sanity.Preview, {
1057
- layout: "default",
1075
+ layout: "block",
1058
1076
  value: item,
1059
1077
  schemaType: schema.get(item._type)
1060
1078
  })
@@ -1062,14 +1080,14 @@ function DocumentCard(props) {
1062
1080
  style: {
1063
1081
  flexShrink: 0
1064
1082
  },
1065
- children: hasError || isDragDisabled ? null : /* @__PURE__ */jsxRuntime.jsx(icons.DragHandleIcon, {})
1083
+ children: hasError || isDragDisabled || isPatching ? null : /* @__PURE__ */jsxRuntime.jsx(icons.DragHandleIcon, {})
1066
1084
  })]
1067
1085
  })
1068
- }), /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1086
+ }), /* @__PURE__ */jsxRuntime.jsxs(ui.Card, {
1069
1087
  padding: 2,
1070
1088
  radius: 2,
1071
1089
  tone: "inherit",
1072
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1090
+ children: [/* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1073
1091
  align: "center",
1074
1092
  justify: "space-between",
1075
1093
  gap: 3,
@@ -1091,11 +1109,17 @@ function DocumentCard(props) {
1091
1109
  id: item._id,
1092
1110
  type: item._type,
1093
1111
  disabled: !userRoleCanDrop
1094
- }), isLastState ? /* @__PURE__ */jsxRuntime.jsx(CompleteButton, {
1112
+ }), isLastState && states.length <= 3 ? /* @__PURE__ */jsxRuntime.jsx(CompleteButton, {
1095
1113
  documentId,
1096
1114
  disabled: !userRoleCanDrop
1097
1115
  }) : null]
1098
- })
1116
+ }), isLastState && states.length > 3 ? /* @__PURE__ */jsxRuntime.jsx(ui.Stack, {
1117
+ paddingTop: 2,
1118
+ children: /* @__PURE__ */jsxRuntime.jsx(CompleteButton, {
1119
+ documentId,
1120
+ disabled: !userRoleCanDrop
1121
+ })
1122
+ }) : null]
1099
1123
  })]
1100
1124
  })
1101
1125
  })
@@ -1106,6 +1130,7 @@ function DocumentList(props) {
1106
1130
  const {
1107
1131
  data = [],
1108
1132
  invalidDocumentIds,
1133
+ patchingIds,
1109
1134
  selectedSchemaTypes,
1110
1135
  selectedUserIds,
1111
1136
  state,
@@ -1154,7 +1179,7 @@ function DocumentList(props) {
1154
1179
  }
1155
1180
  const isInvalid = invalidDocumentIds.includes(documentId);
1156
1181
  const meInAssignees = (user == null ? void 0 : user.id) ? assignees == null ? void 0 : assignees.includes(user.id) : false;
1157
- const isDragDisabled = !userRoleCanDrop || isInvalid || !(state.requireAssignment ? state.requireAssignment && meInAssignees : true);
1182
+ const isDragDisabled = patchingIds.includes(documentId) || !userRoleCanDrop || isInvalid || !(state.requireAssignment ? state.requireAssignment && meInAssignees : true);
1158
1183
  return /* @__PURE__ */jsxRuntime.jsx(dnd.Draggable, {
1159
1184
  draggableId: documentId,
1160
1185
  index: virtualItem.index,
@@ -1166,6 +1191,7 @@ function DocumentList(props) {
1166
1191
  children: /* @__PURE__ */jsxRuntime.jsx(DocumentCard, {
1167
1192
  userRoleCanDrop,
1168
1193
  isDragDisabled,
1194
+ isPatching: patchingIds.includes(documentId),
1169
1195
  isDragging: draggableSnapshot.isDragging,
1170
1196
  item,
1171
1197
  toggleInvalidDocumentId,
@@ -1291,7 +1317,7 @@ function Filters(props) {
1291
1317
  icon: icons.ResetIcon
1292
1318
  }) : null]
1293
1319
  })
1294
- }), schemaTypes.length > 0 ? /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
1320
+ }), schemaTypes.length > 1 ? /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
1295
1321
  align: "center",
1296
1322
  gap: 1,
1297
1323
  children: schemaTypes.map(typeName => {
@@ -1501,16 +1527,21 @@ function Verify(props) {
1501
1527
  });
1502
1528
  }, [client, data, toast, userList]);
1503
1529
  const addOrderToDocuments = React__default.default.useCallback(async ids => {
1504
- var _a, _b;
1505
1530
  toast.push({
1506
1531
  title: "Adding ordering...",
1507
1532
  status: "info"
1508
1533
  });
1509
- const firstOrder = (_b = (_a = data[0]) == null ? void 0 : _a._metadata) == null ? void 0 : _b.orderRank;
1510
- let newLexo = firstOrder && data.length !== ids.length ? lexorank.LexoRank.parse(firstOrder) : lexorank.LexoRank.min();
1534
+ const [firstOrder, secondOrder] = [...data].slice(0, 2).map(d => {
1535
+ var _a;
1536
+ return (_a = d._metadata) == null ? void 0 : _a.orderRank;
1537
+ });
1538
+ const minLexo = firstOrder && data.length !== ids.length ? lexorank.LexoRank.parse(firstOrder) : lexorank.LexoRank.min();
1539
+ const maxLexo = secondOrder && data.length !== ids.length ? lexorank.LexoRank.parse(secondOrder) : lexorank.LexoRank.max();
1540
+ let newLexo = minLexo.between(maxLexo);
1541
+ const lastLexo = maxLexo;
1511
1542
  const tx = client.transaction();
1512
1543
  for (let index = 0; index < ids.length; index += 1) {
1513
- newLexo = newLexo.genNext().genNext();
1544
+ newLexo = newLexo.between(lastLexo);
1514
1545
  tx.patch("workflow-metadata.".concat(ids[index]), {
1515
1546
  set: {
1516
1547
  orderRank: newLexo.toString()
@@ -1573,6 +1604,7 @@ function WorkflowTool(props) {
1573
1604
  } = (_b = (_a = props == null ? void 0 : props.tool) == null ? void 0 : _a.options) != null ? _b : {};
1574
1605
  const isDarkMode = ui.useTheme().sanity.color.dark;
1575
1606
  const defaultCardTone = isDarkMode ? "default" : "transparent";
1607
+ const toast = ui.useToast();
1576
1608
  const userList = sanityPluginUtils.useProjectUsers({
1577
1609
  apiVersion: API_VERSION
1578
1610
  });
@@ -1582,6 +1614,7 @@ function WorkflowTool(props) {
1582
1614
  workflowData,
1583
1615
  operations
1584
1616
  } = useWorkflowDocuments(schemaTypes);
1617
+ const [patchingIds, setPatchingIds] = React__default.default.useState([]);
1585
1618
  const {
1586
1619
  data,
1587
1620
  loading,
@@ -1646,26 +1679,65 @@ function WorkflowTool(props) {
1646
1679
  return;
1647
1680
  }
1648
1681
  const destinationStateItems = [...filterItemsAndSort(data, destination.droppableId, [], null)];
1682
+ const destinationStateIndex = states.findIndex(s => s.id === destination.droppableId);
1683
+ const globalStateMinimumRank = data[0]._metadata.orderRank;
1684
+ const globalStateMaximumRank = data[data.length - 1]._metadata.orderRank;
1649
1685
  let newOrder;
1650
1686
  if (!destinationStateItems.length) {
1651
- newOrder = lexorank.LexoRank.min().toString();
1687
+ if (destinationStateIndex === 0) {
1688
+ newOrder = lexorank.LexoRank.min().toString();
1689
+ } else {
1690
+ newOrder = lexorank.LexoRank.parse(globalStateMinimumRank).between(lexorank.LexoRank.min()).toString();
1691
+ }
1652
1692
  } else if (destination.index === 0) {
1653
1693
  const firstItemOrderRank = (_b2 = (_a2 = [...destinationStateItems].shift()) == null ? void 0 : _a2._metadata) == null ? void 0 : _b2.orderRank;
1654
- newOrder = firstItemOrderRank && typeof firstItemOrderRank === "string" ? lexorank.LexoRank.parse(firstItemOrderRank).genPrev().toString() : lexorank.LexoRank.min().toString();
1694
+ if (firstItemOrderRank && typeof firstItemOrderRank === "string") {
1695
+ newOrder = lexorank.LexoRank.parse(firstItemOrderRank).genPrev().toString();
1696
+ } else if (destinationStateIndex === 0) {
1697
+ newOrder = lexorank.LexoRank.min().toString();
1698
+ } else {
1699
+ newOrder = lexorank.LexoRank.parse(globalStateMinimumRank).between(lexorank.LexoRank.min()).toString();
1700
+ }
1655
1701
  } else if (destination.index + 1 === destinationStateItems.length) {
1656
1702
  const lastItemOrderRank = (_d = (_c2 = [...destinationStateItems].pop()) == null ? void 0 : _c2._metadata) == null ? void 0 : _d.orderRank;
1657
- newOrder = lastItemOrderRank && typeof lastItemOrderRank === "string" ? lexorank.LexoRank.parse(lastItemOrderRank).genNext().toString() : lexorank.LexoRank.min().toString();
1703
+ if (lastItemOrderRank && typeof lastItemOrderRank === "string") {
1704
+ newOrder = lexorank.LexoRank.parse(lastItemOrderRank).genNext().toString();
1705
+ } else if (destinationStateIndex === states.length - 1) {
1706
+ newOrder = lexorank.LexoRank.max().toString();
1707
+ } else {
1708
+ newOrder = lexorank.LexoRank.parse(globalStateMaximumRank).between(lexorank.LexoRank.min()).toString();
1709
+ }
1658
1710
  } else {
1659
1711
  const itemBefore = destinationStateItems[destination.index - 1];
1660
1712
  const itemBeforeRank = (_e = itemBefore == null ? void 0 : itemBefore._metadata) == null ? void 0 : _e.orderRank;
1661
- const itemBeforeRankParsed = itemBeforeRank ? lexorank.LexoRank.parse(itemBeforeRank) : lexorank.LexoRank.min();
1713
+ let itemBeforeRankParsed;
1714
+ if (itemBeforeRank) {
1715
+ itemBeforeRankParsed = lexorank.LexoRank.parse(itemBeforeRank);
1716
+ } else if (destinationStateIndex === 0) {
1717
+ itemBeforeRankParsed = lexorank.LexoRank.min();
1718
+ } else {
1719
+ itemBeforeRankParsed = lexorank.LexoRank.parse(globalStateMinimumRank);
1720
+ }
1662
1721
  const itemAfter = destinationStateItems[destination.index];
1663
1722
  const itemAfterRank = (_f = itemAfter == null ? void 0 : itemAfter._metadata) == null ? void 0 : _f.orderRank;
1664
- const itemAfterRankParsed = itemAfterRank ? lexorank.LexoRank.parse(itemAfterRank) : lexorank.LexoRank.max();
1723
+ let itemAfterRankParsed;
1724
+ if (itemAfterRank) {
1725
+ itemAfterRankParsed = lexorank.LexoRank.parse(itemAfterRank);
1726
+ } else if (destinationStateIndex === states.length - 1) {
1727
+ itemAfterRankParsed = lexorank.LexoRank.max();
1728
+ } else {
1729
+ itemAfterRankParsed = lexorank.LexoRank.parse(globalStateMaximumRank);
1730
+ }
1665
1731
  newOrder = itemBeforeRankParsed.between(itemAfterRankParsed).toString();
1666
1732
  }
1667
- move(draggableId, destination, states, newOrder);
1668
- }, [data, move, states]);
1733
+ setPatchingIds([...patchingIds, draggableId]);
1734
+ toast.push({
1735
+ status: "info",
1736
+ title: "Updating document state..."
1737
+ });
1738
+ await move(draggableId, destination, states, newOrder);
1739
+ setPatchingIds(ids => ids.filter(id => id !== draggableId));
1740
+ }, [data, patchingIds, toast, move, states]);
1669
1741
  const uniqueAssignedUsers = React__default.default.useMemo(() => {
1670
1742
  const uniqueUserIds = data.reduce((acc, item) => {
1671
1743
  var _a2;
@@ -1692,6 +1764,30 @@ function WorkflowTool(props) {
1692
1764
  const toggleInvalidDocumentId = React__default.default.useCallback((docId, action) => {
1693
1765
  setInvalidDocumentIds(prev => action === "ADD" ? [...prev, docId] : prev.filter(id => id !== docId));
1694
1766
  }, []);
1767
+ const Clone = React__default.default.useCallback((provided, snapshot, rubric) => {
1768
+ const item = data.find(doc => {
1769
+ var _a2;
1770
+ return ((_a2 = doc == null ? void 0 : doc._metadata) == null ? void 0 : _a2.documentId) === rubric.draggableId;
1771
+ });
1772
+ return /* @__PURE__ */jsxRuntime.jsx("div", {
1773
+ ...provided.draggableProps,
1774
+ ...provided.dragHandleProps,
1775
+ ref: provided.innerRef,
1776
+ children: item ? /* @__PURE__ */jsxRuntime.jsx(DocumentCard, {
1777
+ isDragDisabled: false,
1778
+ isPatching: false,
1779
+ userRoleCanDrop: true,
1780
+ isDragging: snapshot.isDragging,
1781
+ item,
1782
+ states,
1783
+ toggleInvalidDocumentId,
1784
+ userList
1785
+ }) : /* @__PURE__ */jsxRuntime.jsx(sanityPluginUtils.Feedback, {
1786
+ title: "Item not found",
1787
+ tone: "caution"
1788
+ })
1789
+ });
1790
+ }, [data, states, toggleInvalidDocumentId, userList]);
1695
1791
  if (!(states == null ? void 0 : states.length)) {
1696
1792
  return /* @__PURE__ */jsxRuntime.jsx(ui.Container, {
1697
1793
  width: 1,
@@ -1758,29 +1854,7 @@ function WorkflowTool(props) {
1758
1854
  droppableId: state.id,
1759
1855
  isDropDisabled,
1760
1856
  mode: "virtual",
1761
- renderClone: (provided, snapshot, rubric) => {
1762
- const item = data.find(doc => {
1763
- var _a3;
1764
- return ((_a3 = doc == null ? void 0 : doc._metadata) == null ? void 0 : _a3.documentId) === rubric.draggableId;
1765
- });
1766
- return /* @__PURE__ */jsxRuntime.jsx("div", {
1767
- ...provided.draggableProps,
1768
- ...provided.dragHandleProps,
1769
- ref: provided.innerRef,
1770
- children: item ? /* @__PURE__ */jsxRuntime.jsx(DocumentCard, {
1771
- isDragDisabled: false,
1772
- userRoleCanDrop,
1773
- isDragging: snapshot.isDragging,
1774
- item,
1775
- states,
1776
- toggleInvalidDocumentId,
1777
- userList
1778
- }) : /* @__PURE__ */jsxRuntime.jsx(sanityPluginUtils.Feedback, {
1779
- title: "Item not found",
1780
- tone: "caution"
1781
- })
1782
- });
1783
- },
1857
+ renderClone: Clone,
1784
1858
  children: (provided, snapshot) => /* @__PURE__ */jsxRuntime.jsxs(ui.Card, {
1785
1859
  ref: provided.innerRef,
1786
1860
  tone: snapshot.isDraggingOver ? "primary" : defaultCardTone,
@@ -1796,6 +1870,7 @@ function WorkflowTool(props) {
1796
1870
  }) : null, /* @__PURE__ */jsxRuntime.jsx(DocumentList, {
1797
1871
  data,
1798
1872
  invalidDocumentIds,
1873
+ patchingIds,
1799
1874
  selectedSchemaTypes,
1800
1875
  selectedUserIds,
1801
1876
  state,