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

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
- var _a;
703
- return toast.push({
704
- title: "Moved to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
702
+ }).commit().then(res => {
703
+ var _a, _b;
704
+ toast.push({
705
+ title: newState.id === document._metadata.state ? "Reordered in \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\"") : "Moved to \"".concat((_b = newState == null ? void 0 : newState.title) != null ? _b : 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,
@@ -1173,7 +1199,7 @@ function DocumentList(props) {
1173
1199
  states
1174
1200
  })
1175
1201
  })
1176
- }, documentId);
1202
+ }, virtualItem.key);
1177
1203
  })
1178
1204
  });
1179
1205
  }
@@ -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 => {
@@ -1377,6 +1403,40 @@ function StateTitle(props) {
1377
1403
  })
1378
1404
  });
1379
1405
  }
1406
+ function generateMiddleValue(ranks) {
1407
+ if (!ranks.some(rank => !rank)) {
1408
+ return ranks;
1409
+ }
1410
+ const firstUndefined = ranks.findIndex(rank => !rank);
1411
+ const firstDefinedAfter = ranks.findIndex((rank, index) => rank && index > firstUndefined);
1412
+ const firstDefinedBefore = ranks.findLastIndex((rank, index) => rank && index < firstUndefined);
1413
+ if (firstDefinedAfter === -1 || firstDefinedBefore === -1) {
1414
+ throw new Error("Unable to generate middle value between indexes ".concat(firstDefinedBefore, " and ").concat(firstDefinedAfter));
1415
+ }
1416
+ const beforeRank = ranks[firstDefinedBefore];
1417
+ const afterRank = ranks[firstDefinedAfter];
1418
+ if (!beforeRank || typeof beforeRank === "undefined" || !afterRank || typeof afterRank === "undefined") {
1419
+ throw new Error("Unable to generate middle value between indexes ".concat(firstDefinedBefore, " and ").concat(firstDefinedAfter));
1420
+ }
1421
+ const between = beforeRank.between(afterRank);
1422
+ const middle = Math.floor((firstDefinedAfter + firstDefinedBefore) / 2);
1423
+ if (ranks[middle]) {
1424
+ throw new Error("Should not have overwritten value at index ".concat(middle));
1425
+ }
1426
+ ranks[middle] = between;
1427
+ return ranks;
1428
+ }
1429
+ function generateMultipleOrderRanks(count, start, end) {
1430
+ let ranks = [...Array(count)];
1431
+ const rankStart = start != null ? start : lexorank.LexoRank.min().genNext().genNext();
1432
+ const rankEnd = end != null ? end : lexorank.LexoRank.max().genPrev().genPrev();
1433
+ ranks[0] = rankStart;
1434
+ ranks[count - 1] = rankEnd;
1435
+ for (let i = 0; i < count; i++) {
1436
+ ranks = generateMiddleValue(ranks);
1437
+ }
1438
+ return ranks.sort((a, b) => a.toString().localeCompare(b.toString()));
1439
+ }
1380
1440
  const StyledFloatingCard = styled__default.default(ui.Card)(() => styled.css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n position: fixed;\n bottom: 0;\n left: 0;\n z-index: 1000;\n "]))));
1381
1441
  function FloatingCard(_ref3) {
1382
1442
  let {
@@ -1426,7 +1486,7 @@ function Verify(props) {
1426
1486
  const stateExists = states.find(s => s.id === state);
1427
1487
  return !stateExists && documentId ? [...acc, documentId] : acc;
1428
1488
  }, []) : [];
1429
- const documentsWithInvalidUserIds = (data == null ? void 0 : data.length) ? data.reduce((acc, cur) => {
1489
+ const documentsWithInvalidUserIds = (data == null ? void 0 : data.length) && (userList == null ? void 0 : userList.length) ? data.reduce((acc, cur) => {
1430
1490
  var _a;
1431
1491
  const {
1432
1492
  documentId,
@@ -1501,19 +1561,42 @@ function Verify(props) {
1501
1561
  });
1502
1562
  }, [client, data, toast, userList]);
1503
1563
  const addOrderToDocuments = React__default.default.useCallback(async ids => {
1504
- var _a, _b;
1505
1564
  toast.push({
1506
1565
  title: "Adding ordering...",
1507
1566
  status: "info"
1508
1567
  });
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();
1568
+ const [firstOrder, secondOrder] = [...data].slice(0, 2).map(d => {
1569
+ var _a;
1570
+ return (_a = d._metadata) == null ? void 0 : _a.orderRank;
1571
+ });
1572
+ const minLexo = firstOrder ? lexorank.LexoRank.parse(firstOrder) : void 0;
1573
+ const maxLexo = secondOrder ? lexorank.LexoRank.parse(secondOrder) : void 0;
1574
+ const ranks = generateMultipleOrderRanks(ids.length, minLexo, maxLexo);
1511
1575
  const tx = client.transaction();
1512
1576
  for (let index = 0; index < ids.length; index += 1) {
1513
- newLexo = newLexo.genNext().genNext();
1514
1577
  tx.patch("workflow-metadata.".concat(ids[index]), {
1515
1578
  set: {
1516
- orderRank: newLexo.toString()
1579
+ orderRank: ranks[index].toString()
1580
+ }
1581
+ });
1582
+ }
1583
+ await tx.commit();
1584
+ toast.push({
1585
+ title: "Added order to ".concat(ids.length === 1 ? "1 Document" : "".concat(ids.length, " Documents")),
1586
+ status: "success"
1587
+ });
1588
+ }, [data, client, toast]);
1589
+ const resetOrderOfAllDocuments = React__default.default.useCallback(async ids => {
1590
+ toast.push({
1591
+ title: "Adding ordering...",
1592
+ status: "info"
1593
+ });
1594
+ const ranks = generateMultipleOrderRanks(ids.length);
1595
+ const tx = client.transaction();
1596
+ for (let index = 0; index < ids.length; index += 1) {
1597
+ tx.patch("workflow-metadata.".concat(ids[index]), {
1598
+ set: {
1599
+ orderRank: ranks[index].toString()
1517
1600
  }
1518
1601
  });
1519
1602
  }
@@ -1544,24 +1627,39 @@ function Verify(props) {
1544
1627
  return /* @__PURE__ */jsxRuntime.jsxs(FloatingCard, {
1545
1628
  children: [documentsWithoutValidMetadataIds.length > 0 ? /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1546
1629
  tone: "caution",
1630
+ mode: "ghost",
1547
1631
  onClick: () => correctDocuments(documentsWithoutValidMetadataIds),
1548
1632
  text: documentsWithoutValidMetadataIds.length === 1 ? "Correct 1 Document State" : "Correct ".concat(documentsWithoutValidMetadataIds.length, " Document States")
1549
1633
  }) : null, documentsWithInvalidUserIds.length > 0 ? /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1550
1634
  tone: "caution",
1635
+ mode: "ghost",
1551
1636
  onClick: () => removeUsersFromDocuments(documentsWithInvalidUserIds),
1552
1637
  text: documentsWithInvalidUserIds.length === 1 ? "Remove Invalid Users from 1 Document" : "Remove Invalid Users from ".concat(documentsWithInvalidUserIds.length, " Documents")
1553
1638
  }) : null, documentsWithoutOrderIds.length > 0 ? /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1554
1639
  tone: "caution",
1640
+ mode: "ghost",
1555
1641
  onClick: () => addOrderToDocuments(documentsWithoutOrderIds),
1556
1642
  text: documentsWithoutOrderIds.length === 1 ? "Set Order for 1 Document" : "Set Order for ".concat(documentsWithoutOrderIds.length, " Documents")
1557
- }) : null, documentsWithDuplicatedOrderIds.length > 0 ? /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1558
- tone: "caution",
1559
- onClick: () => addOrderToDocuments(documentsWithDuplicatedOrderIds),
1560
- text: documentsWithDuplicatedOrderIds.length === 1 ? "Set Unique Order for 1 Document" : "Set Unique Order for ".concat(documentsWithDuplicatedOrderIds.length, " Documents")
1643
+ }) : null, documentsWithDuplicatedOrderIds.length > 0 ? /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
1644
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1645
+ tone: "caution",
1646
+ mode: "ghost",
1647
+ onClick: () => addOrderToDocuments(documentsWithDuplicatedOrderIds),
1648
+ text: documentsWithDuplicatedOrderIds.length === 1 ? "Set Unique Order for 1 Document" : "Set Unique Order for ".concat(documentsWithDuplicatedOrderIds.length, " Documents")
1649
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1650
+ tone: "caution",
1651
+ mode: "ghost",
1652
+ onClick: () => resetOrderOfAllDocuments(data.map(doc => {
1653
+ var _a;
1654
+ return String((_a = doc._metadata) == null ? void 0 : _a.documentId);
1655
+ })),
1656
+ text: data.length === 1 ? "Reset Order for 1 Document" : "Reset Order for all ".concat(data.length, " Documents")
1657
+ })]
1561
1658
  }) : null, orphanedMetadataDocumentIds.length > 0 ? /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1562
1659
  text: "Cleanup orphaned metadata",
1563
1660
  onClick: handleOrphans,
1564
- tone: "caution"
1661
+ tone: "caution",
1662
+ mode: "ghost"
1565
1663
  }) : null]
1566
1664
  });
1567
1665
  }
@@ -1573,6 +1671,7 @@ function WorkflowTool(props) {
1573
1671
  } = (_b = (_a = props == null ? void 0 : props.tool) == null ? void 0 : _a.options) != null ? _b : {};
1574
1672
  const isDarkMode = ui.useTheme().sanity.color.dark;
1575
1673
  const defaultCardTone = isDarkMode ? "default" : "transparent";
1674
+ const toast = ui.useToast();
1576
1675
  const userList = sanityPluginUtils.useProjectUsers({
1577
1676
  apiVersion: API_VERSION
1578
1677
  });
@@ -1582,6 +1681,7 @@ function WorkflowTool(props) {
1582
1681
  workflowData,
1583
1682
  operations
1584
1683
  } = useWorkflowDocuments(schemaTypes);
1684
+ const [patchingIds, setPatchingIds] = React__default.default.useState([]);
1585
1685
  const {
1586
1686
  data,
1587
1687
  loading,
@@ -1646,26 +1746,65 @@ function WorkflowTool(props) {
1646
1746
  return;
1647
1747
  }
1648
1748
  const destinationStateItems = [...filterItemsAndSort(data, destination.droppableId, [], null)];
1749
+ const destinationStateIndex = states.findIndex(s => s.id === destination.droppableId);
1750
+ const globalStateMinimumRank = data[0]._metadata.orderRank;
1751
+ const globalStateMaximumRank = data[data.length - 1]._metadata.orderRank;
1649
1752
  let newOrder;
1650
1753
  if (!destinationStateItems.length) {
1651
- newOrder = lexorank.LexoRank.min().toString();
1754
+ if (destinationStateIndex === 0) {
1755
+ newOrder = lexorank.LexoRank.min().toString();
1756
+ } else {
1757
+ newOrder = lexorank.LexoRank.parse(globalStateMinimumRank).between(lexorank.LexoRank.min()).toString();
1758
+ }
1652
1759
  } else if (destination.index === 0) {
1653
1760
  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();
1761
+ if (firstItemOrderRank && typeof firstItemOrderRank === "string") {
1762
+ newOrder = lexorank.LexoRank.parse(firstItemOrderRank).genPrev().toString();
1763
+ } else if (destinationStateIndex === 0) {
1764
+ newOrder = lexorank.LexoRank.min().toString();
1765
+ } else {
1766
+ newOrder = lexorank.LexoRank.parse(globalStateMinimumRank).between(lexorank.LexoRank.min()).toString();
1767
+ }
1655
1768
  } else if (destination.index + 1 === destinationStateItems.length) {
1656
1769
  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();
1770
+ if (lastItemOrderRank && typeof lastItemOrderRank === "string") {
1771
+ newOrder = lexorank.LexoRank.parse(lastItemOrderRank).genNext().toString();
1772
+ } else if (destinationStateIndex === states.length - 1) {
1773
+ newOrder = lexorank.LexoRank.max().toString();
1774
+ } else {
1775
+ newOrder = lexorank.LexoRank.parse(globalStateMaximumRank).between(lexorank.LexoRank.min()).toString();
1776
+ }
1658
1777
  } else {
1659
1778
  const itemBefore = destinationStateItems[destination.index - 1];
1660
1779
  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();
1780
+ let itemBeforeRankParsed;
1781
+ if (itemBeforeRank) {
1782
+ itemBeforeRankParsed = lexorank.LexoRank.parse(itemBeforeRank);
1783
+ } else if (destinationStateIndex === 0) {
1784
+ itemBeforeRankParsed = lexorank.LexoRank.min();
1785
+ } else {
1786
+ itemBeforeRankParsed = lexorank.LexoRank.parse(globalStateMinimumRank);
1787
+ }
1662
1788
  const itemAfter = destinationStateItems[destination.index];
1663
1789
  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();
1790
+ let itemAfterRankParsed;
1791
+ if (itemAfterRank) {
1792
+ itemAfterRankParsed = lexorank.LexoRank.parse(itemAfterRank);
1793
+ } else if (destinationStateIndex === states.length - 1) {
1794
+ itemAfterRankParsed = lexorank.LexoRank.max();
1795
+ } else {
1796
+ itemAfterRankParsed = lexorank.LexoRank.parse(globalStateMaximumRank);
1797
+ }
1665
1798
  newOrder = itemBeforeRankParsed.between(itemAfterRankParsed).toString();
1666
1799
  }
1667
- move(draggableId, destination, states, newOrder);
1668
- }, [data, move, states]);
1800
+ setPatchingIds([...patchingIds, draggableId]);
1801
+ toast.push({
1802
+ status: "info",
1803
+ title: "Updating document state..."
1804
+ });
1805
+ await move(draggableId, destination, states, newOrder);
1806
+ setPatchingIds(ids => ids.filter(id => id !== draggableId));
1807
+ }, [data, patchingIds, toast, move, states]);
1669
1808
  const uniqueAssignedUsers = React__default.default.useMemo(() => {
1670
1809
  const uniqueUserIds = data.reduce((acc, item) => {
1671
1810
  var _a2;
@@ -1692,6 +1831,30 @@ function WorkflowTool(props) {
1692
1831
  const toggleInvalidDocumentId = React__default.default.useCallback((docId, action) => {
1693
1832
  setInvalidDocumentIds(prev => action === "ADD" ? [...prev, docId] : prev.filter(id => id !== docId));
1694
1833
  }, []);
1834
+ const Clone = React__default.default.useCallback((provided, snapshot, rubric) => {
1835
+ const item = data.find(doc => {
1836
+ var _a2;
1837
+ return ((_a2 = doc == null ? void 0 : doc._metadata) == null ? void 0 : _a2.documentId) === rubric.draggableId;
1838
+ });
1839
+ return /* @__PURE__ */jsxRuntime.jsx("div", {
1840
+ ...provided.draggableProps,
1841
+ ...provided.dragHandleProps,
1842
+ ref: provided.innerRef,
1843
+ children: item ? /* @__PURE__ */jsxRuntime.jsx(DocumentCard, {
1844
+ isDragDisabled: false,
1845
+ isPatching: false,
1846
+ userRoleCanDrop: true,
1847
+ isDragging: snapshot.isDragging,
1848
+ item,
1849
+ states,
1850
+ toggleInvalidDocumentId,
1851
+ userList
1852
+ }) : /* @__PURE__ */jsxRuntime.jsx(sanityPluginUtils.Feedback, {
1853
+ title: "Item not found",
1854
+ tone: "caution"
1855
+ })
1856
+ });
1857
+ }, [data, states, toggleInvalidDocumentId, userList]);
1695
1858
  if (!(states == null ? void 0 : states.length)) {
1696
1859
  return /* @__PURE__ */jsxRuntime.jsx(ui.Container, {
1697
1860
  width: 1,
@@ -1758,29 +1921,7 @@ function WorkflowTool(props) {
1758
1921
  droppableId: state.id,
1759
1922
  isDropDisabled,
1760
1923
  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
- },
1924
+ renderClone: Clone,
1784
1925
  children: (provided, snapshot) => /* @__PURE__ */jsxRuntime.jsxs(ui.Card, {
1785
1926
  ref: provided.innerRef,
1786
1927
  tone: snapshot.isDraggingOver ? "primary" : defaultCardTone,
@@ -1796,6 +1937,7 @@ function WorkflowTool(props) {
1796
1937
  }) : null, /* @__PURE__ */jsxRuntime.jsx(DocumentList, {
1797
1938
  data,
1798
1939
  invalidDocumentIds,
1940
+ patchingIds,
1799
1941
  selectedSchemaTypes,
1800
1942
  selectedUserIds,
1801
1943
  state,