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.esm.js CHANGED
@@ -680,25 +680,28 @@ function useWorkflowDocuments(schemaTypes) {
680
680
  _type
681
681
  } = document;
682
682
  const {
683
- documentId
683
+ documentId,
684
+ _rev
684
685
  } = document._metadata || {};
685
- await client.patch("workflow-metadata.".concat(documentId)).set({
686
+ await client.patch("workflow-metadata.".concat(documentId)).ifRevisionId(_rev).set({
686
687
  state: newStateId,
687
688
  orderRank: newOrder
688
- }).commit().then(() => {
689
+ }).commit().then(res => {
689
690
  var _a;
690
- return toast.push({
691
+ toast.push({
691
692
  title: "Moved to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
692
693
  status: "success"
693
694
  });
695
+ return res;
694
696
  }).catch(err => {
695
697
  var _a;
696
698
  setLocalDocuments(currentLocalData);
697
- return toast.push({
699
+ toast.push({
698
700
  title: "Failed to move to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
699
701
  description: err.message,
700
702
  status: "error"
701
703
  });
704
+ return null;
702
705
  });
703
706
  return {
704
707
  _id,
@@ -812,31 +815,44 @@ function CompleteButton(props) {
812
815
  apiVersion: API_VERSION
813
816
  });
814
817
  const toast = useToast();
815
- const handleComplete = React.useCallback(id => {
818
+ const handleComplete = React.useCallback(event => {
819
+ const id = event.currentTarget.value;
820
+ if (!id) {
821
+ return;
822
+ }
816
823
  client.delete("workflow-metadata.".concat(id)).then(() => {
817
824
  toast.push({
818
825
  status: "success",
819
- title: "Workflow completed",
820
- description: id
826
+ title: "Workflow completed"
821
827
  });
822
828
  }).catch(() => {
823
829
  toast.push({
824
830
  status: "error",
825
- title: "Could not complete Workflow",
826
- description: id
831
+ title: "Could not complete Workflow"
827
832
  });
828
833
  });
829
834
  }, [client, toast]);
830
- return /* @__PURE__ */jsx(Button, {
831
- onClick: () => handleComplete(documentId),
832
- text: "Complete",
833
- icon: CheckmarkIcon,
834
- tone: "positive",
835
- mode: "ghost",
836
- fontSize: 1,
837
- padding: 2,
838
- tabIndex: -1,
839
- disabled
835
+ return /* @__PURE__ */jsx(Tooltip, {
836
+ portal: true,
837
+ content: /* @__PURE__ */jsx(Box, {
838
+ padding: 2,
839
+ children: /* @__PURE__ */jsx(Text, {
840
+ size: 1,
841
+ children: "Remove this document from Workflow"
842
+ })
843
+ }),
844
+ children: /* @__PURE__ */jsx(Button, {
845
+ value: documentId,
846
+ onClick: handleComplete,
847
+ text: "Complete",
848
+ icon: CheckmarkIcon,
849
+ tone: "positive",
850
+ mode: "ghost",
851
+ fontSize: 1,
852
+ padding: 2,
853
+ tabIndex: -1,
854
+ disabled
855
+ })
840
856
  });
841
857
  }
842
858
  function TimeAgo(_ref2) {
@@ -953,6 +969,7 @@ function DocumentCard(props) {
953
969
  var _a, _b;
954
970
  const {
955
971
  isDragDisabled,
972
+ isPatching,
956
973
  userRoleCanDrop,
957
974
  isDragging,
958
975
  item,
@@ -986,6 +1003,7 @@ function DocumentCard(props) {
986
1003
  let tone = defaultCardTone;
987
1004
  if (!userRoleCanDrop) return isDarkMode ? "default" : "transparent";
988
1005
  if (!documentId) return tone;
1006
+ if (isPatching) tone = isDarkMode ? "default" : "transparent";
989
1007
  if (isDragging) tone = "positive";
990
1008
  if ((state == null ? void 0 : state.requireValidation) && !isValidating && validation.length > 0) {
991
1009
  if (validation.some(v => v.level === "error")) {
@@ -995,7 +1013,7 @@ function DocumentCard(props) {
995
1013
  }
996
1014
  }
997
1015
  return tone;
998
- }, [defaultCardTone, userRoleCanDrop, isDarkMode, documentId, isDragging, isValidating, validation, state == null ? void 0 : state.requireValidation]);
1016
+ }, [defaultCardTone, userRoleCanDrop, isPatching, isDarkMode, documentId, isDragging, isValidating, validation, state == null ? void 0 : state.requireValidation]);
999
1017
  useEffect(() => {
1000
1018
  if (!isValidating && validation.length > 0) {
1001
1019
  if (validation.some(v => v.level === "error")) {
@@ -1041,7 +1059,7 @@ function DocumentCard(props) {
1041
1059
  children: [/* @__PURE__ */jsx(Box, {
1042
1060
  flex: 1,
1043
1061
  children: /* @__PURE__ */jsx(Preview, {
1044
- layout: "default",
1062
+ layout: "block",
1045
1063
  value: item,
1046
1064
  schemaType: schema.get(item._type)
1047
1065
  })
@@ -1049,14 +1067,14 @@ function DocumentCard(props) {
1049
1067
  style: {
1050
1068
  flexShrink: 0
1051
1069
  },
1052
- children: hasError || isDragDisabled ? null : /* @__PURE__ */jsx(DragHandleIcon, {})
1070
+ children: hasError || isDragDisabled || isPatching ? null : /* @__PURE__ */jsx(DragHandleIcon, {})
1053
1071
  })]
1054
1072
  })
1055
- }), /* @__PURE__ */jsx(Card, {
1073
+ }), /* @__PURE__ */jsxs(Card, {
1056
1074
  padding: 2,
1057
1075
  radius: 2,
1058
1076
  tone: "inherit",
1059
- children: /* @__PURE__ */jsxs(Flex, {
1077
+ children: [/* @__PURE__ */jsxs(Flex, {
1060
1078
  align: "center",
1061
1079
  justify: "space-between",
1062
1080
  gap: 3,
@@ -1078,11 +1096,17 @@ function DocumentCard(props) {
1078
1096
  id: item._id,
1079
1097
  type: item._type,
1080
1098
  disabled: !userRoleCanDrop
1081
- }), isLastState ? /* @__PURE__ */jsx(CompleteButton, {
1099
+ }), isLastState && states.length <= 3 ? /* @__PURE__ */jsx(CompleteButton, {
1082
1100
  documentId,
1083
1101
  disabled: !userRoleCanDrop
1084
1102
  }) : null]
1085
- })
1103
+ }), isLastState && states.length > 3 ? /* @__PURE__ */jsx(Stack, {
1104
+ paddingTop: 2,
1105
+ children: /* @__PURE__ */jsx(CompleteButton, {
1106
+ documentId,
1107
+ disabled: !userRoleCanDrop
1108
+ })
1109
+ }) : null]
1086
1110
  })]
1087
1111
  })
1088
1112
  })
@@ -1093,6 +1117,7 @@ function DocumentList(props) {
1093
1117
  const {
1094
1118
  data = [],
1095
1119
  invalidDocumentIds,
1120
+ patchingIds,
1096
1121
  selectedSchemaTypes,
1097
1122
  selectedUserIds,
1098
1123
  state,
@@ -1141,7 +1166,7 @@ function DocumentList(props) {
1141
1166
  }
1142
1167
  const isInvalid = invalidDocumentIds.includes(documentId);
1143
1168
  const meInAssignees = (user == null ? void 0 : user.id) ? assignees == null ? void 0 : assignees.includes(user.id) : false;
1144
- const isDragDisabled = !userRoleCanDrop || isInvalid || !(state.requireAssignment ? state.requireAssignment && meInAssignees : true);
1169
+ const isDragDisabled = patchingIds.includes(documentId) || !userRoleCanDrop || isInvalid || !(state.requireAssignment ? state.requireAssignment && meInAssignees : true);
1145
1170
  return /* @__PURE__ */jsx(Draggable, {
1146
1171
  draggableId: documentId,
1147
1172
  index: virtualItem.index,
@@ -1153,6 +1178,7 @@ function DocumentList(props) {
1153
1178
  children: /* @__PURE__ */jsx(DocumentCard, {
1154
1179
  userRoleCanDrop,
1155
1180
  isDragDisabled,
1181
+ isPatching: patchingIds.includes(documentId),
1156
1182
  isDragging: draggableSnapshot.isDragging,
1157
1183
  item,
1158
1184
  toggleInvalidDocumentId,
@@ -1278,7 +1304,7 @@ function Filters(props) {
1278
1304
  icon: ResetIcon
1279
1305
  }) : null]
1280
1306
  })
1281
- }), schemaTypes.length > 0 ? /* @__PURE__ */jsx(Flex, {
1307
+ }), schemaTypes.length > 1 ? /* @__PURE__ */jsx(Flex, {
1282
1308
  align: "center",
1283
1309
  gap: 1,
1284
1310
  children: schemaTypes.map(typeName => {
@@ -1488,16 +1514,21 @@ function Verify(props) {
1488
1514
  });
1489
1515
  }, [client, data, toast, userList]);
1490
1516
  const addOrderToDocuments = React.useCallback(async ids => {
1491
- var _a, _b;
1492
1517
  toast.push({
1493
1518
  title: "Adding ordering...",
1494
1519
  status: "info"
1495
1520
  });
1496
- const firstOrder = (_b = (_a = data[0]) == null ? void 0 : _a._metadata) == null ? void 0 : _b.orderRank;
1497
- let newLexo = firstOrder && data.length !== ids.length ? LexoRank.parse(firstOrder) : LexoRank.min();
1521
+ const [firstOrder, secondOrder] = [...data].slice(0, 2).map(d => {
1522
+ var _a;
1523
+ return (_a = d._metadata) == null ? void 0 : _a.orderRank;
1524
+ });
1525
+ const minLexo = firstOrder && data.length !== ids.length ? LexoRank.parse(firstOrder) : LexoRank.min();
1526
+ const maxLexo = secondOrder && data.length !== ids.length ? LexoRank.parse(secondOrder) : LexoRank.max();
1527
+ let newLexo = minLexo.between(maxLexo);
1528
+ const lastLexo = maxLexo;
1498
1529
  const tx = client.transaction();
1499
1530
  for (let index = 0; index < ids.length; index += 1) {
1500
- newLexo = newLexo.genNext().genNext();
1531
+ newLexo = newLexo.between(lastLexo);
1501
1532
  tx.patch("workflow-metadata.".concat(ids[index]), {
1502
1533
  set: {
1503
1534
  orderRank: newLexo.toString()
@@ -1560,6 +1591,7 @@ function WorkflowTool(props) {
1560
1591
  } = (_b = (_a = props == null ? void 0 : props.tool) == null ? void 0 : _a.options) != null ? _b : {};
1561
1592
  const isDarkMode = useTheme().sanity.color.dark;
1562
1593
  const defaultCardTone = isDarkMode ? "default" : "transparent";
1594
+ const toast = useToast();
1563
1595
  const userList = useProjectUsers({
1564
1596
  apiVersion: API_VERSION
1565
1597
  });
@@ -1569,6 +1601,7 @@ function WorkflowTool(props) {
1569
1601
  workflowData,
1570
1602
  operations
1571
1603
  } = useWorkflowDocuments(schemaTypes);
1604
+ const [patchingIds, setPatchingIds] = React.useState([]);
1572
1605
  const {
1573
1606
  data,
1574
1607
  loading,
@@ -1633,26 +1666,65 @@ function WorkflowTool(props) {
1633
1666
  return;
1634
1667
  }
1635
1668
  const destinationStateItems = [...filterItemsAndSort(data, destination.droppableId, [], null)];
1669
+ const destinationStateIndex = states.findIndex(s => s.id === destination.droppableId);
1670
+ const globalStateMinimumRank = data[0]._metadata.orderRank;
1671
+ const globalStateMaximumRank = data[data.length - 1]._metadata.orderRank;
1636
1672
  let newOrder;
1637
1673
  if (!destinationStateItems.length) {
1638
- newOrder = LexoRank.min().toString();
1674
+ if (destinationStateIndex === 0) {
1675
+ newOrder = LexoRank.min().toString();
1676
+ } else {
1677
+ newOrder = LexoRank.parse(globalStateMinimumRank).between(LexoRank.min()).toString();
1678
+ }
1639
1679
  } else if (destination.index === 0) {
1640
1680
  const firstItemOrderRank = (_b2 = (_a2 = [...destinationStateItems].shift()) == null ? void 0 : _a2._metadata) == null ? void 0 : _b2.orderRank;
1641
- newOrder = firstItemOrderRank && typeof firstItemOrderRank === "string" ? LexoRank.parse(firstItemOrderRank).genPrev().toString() : LexoRank.min().toString();
1681
+ if (firstItemOrderRank && typeof firstItemOrderRank === "string") {
1682
+ newOrder = LexoRank.parse(firstItemOrderRank).genPrev().toString();
1683
+ } else if (destinationStateIndex === 0) {
1684
+ newOrder = LexoRank.min().toString();
1685
+ } else {
1686
+ newOrder = LexoRank.parse(globalStateMinimumRank).between(LexoRank.min()).toString();
1687
+ }
1642
1688
  } else if (destination.index + 1 === destinationStateItems.length) {
1643
1689
  const lastItemOrderRank = (_d = (_c2 = [...destinationStateItems].pop()) == null ? void 0 : _c2._metadata) == null ? void 0 : _d.orderRank;
1644
- newOrder = lastItemOrderRank && typeof lastItemOrderRank === "string" ? LexoRank.parse(lastItemOrderRank).genNext().toString() : LexoRank.min().toString();
1690
+ if (lastItemOrderRank && typeof lastItemOrderRank === "string") {
1691
+ newOrder = LexoRank.parse(lastItemOrderRank).genNext().toString();
1692
+ } else if (destinationStateIndex === states.length - 1) {
1693
+ newOrder = LexoRank.max().toString();
1694
+ } else {
1695
+ newOrder = LexoRank.parse(globalStateMaximumRank).between(LexoRank.min()).toString();
1696
+ }
1645
1697
  } else {
1646
1698
  const itemBefore = destinationStateItems[destination.index - 1];
1647
1699
  const itemBeforeRank = (_e = itemBefore == null ? void 0 : itemBefore._metadata) == null ? void 0 : _e.orderRank;
1648
- const itemBeforeRankParsed = itemBeforeRank ? LexoRank.parse(itemBeforeRank) : LexoRank.min();
1700
+ let itemBeforeRankParsed;
1701
+ if (itemBeforeRank) {
1702
+ itemBeforeRankParsed = LexoRank.parse(itemBeforeRank);
1703
+ } else if (destinationStateIndex === 0) {
1704
+ itemBeforeRankParsed = LexoRank.min();
1705
+ } else {
1706
+ itemBeforeRankParsed = LexoRank.parse(globalStateMinimumRank);
1707
+ }
1649
1708
  const itemAfter = destinationStateItems[destination.index];
1650
1709
  const itemAfterRank = (_f = itemAfter == null ? void 0 : itemAfter._metadata) == null ? void 0 : _f.orderRank;
1651
- const itemAfterRankParsed = itemAfterRank ? LexoRank.parse(itemAfterRank) : LexoRank.max();
1710
+ let itemAfterRankParsed;
1711
+ if (itemAfterRank) {
1712
+ itemAfterRankParsed = LexoRank.parse(itemAfterRank);
1713
+ } else if (destinationStateIndex === states.length - 1) {
1714
+ itemAfterRankParsed = LexoRank.max();
1715
+ } else {
1716
+ itemAfterRankParsed = LexoRank.parse(globalStateMaximumRank);
1717
+ }
1652
1718
  newOrder = itemBeforeRankParsed.between(itemAfterRankParsed).toString();
1653
1719
  }
1654
- move(draggableId, destination, states, newOrder);
1655
- }, [data, move, states]);
1720
+ setPatchingIds([...patchingIds, draggableId]);
1721
+ toast.push({
1722
+ status: "info",
1723
+ title: "Updating document state..."
1724
+ });
1725
+ await move(draggableId, destination, states, newOrder);
1726
+ setPatchingIds(ids => ids.filter(id => id !== draggableId));
1727
+ }, [data, patchingIds, toast, move, states]);
1656
1728
  const uniqueAssignedUsers = React.useMemo(() => {
1657
1729
  const uniqueUserIds = data.reduce((acc, item) => {
1658
1730
  var _a2;
@@ -1679,6 +1751,30 @@ function WorkflowTool(props) {
1679
1751
  const toggleInvalidDocumentId = React.useCallback((docId, action) => {
1680
1752
  setInvalidDocumentIds(prev => action === "ADD" ? [...prev, docId] : prev.filter(id => id !== docId));
1681
1753
  }, []);
1754
+ const Clone = React.useCallback((provided, snapshot, rubric) => {
1755
+ const item = data.find(doc => {
1756
+ var _a2;
1757
+ return ((_a2 = doc == null ? void 0 : doc._metadata) == null ? void 0 : _a2.documentId) === rubric.draggableId;
1758
+ });
1759
+ return /* @__PURE__ */jsx("div", {
1760
+ ...provided.draggableProps,
1761
+ ...provided.dragHandleProps,
1762
+ ref: provided.innerRef,
1763
+ children: item ? /* @__PURE__ */jsx(DocumentCard, {
1764
+ isDragDisabled: false,
1765
+ isPatching: false,
1766
+ userRoleCanDrop: true,
1767
+ isDragging: snapshot.isDragging,
1768
+ item,
1769
+ states,
1770
+ toggleInvalidDocumentId,
1771
+ userList
1772
+ }) : /* @__PURE__ */jsx(Feedback, {
1773
+ title: "Item not found",
1774
+ tone: "caution"
1775
+ })
1776
+ });
1777
+ }, [data, states, toggleInvalidDocumentId, userList]);
1682
1778
  if (!(states == null ? void 0 : states.length)) {
1683
1779
  return /* @__PURE__ */jsx(Container, {
1684
1780
  width: 1,
@@ -1745,29 +1841,7 @@ function WorkflowTool(props) {
1745
1841
  droppableId: state.id,
1746
1842
  isDropDisabled,
1747
1843
  mode: "virtual",
1748
- renderClone: (provided, snapshot, rubric) => {
1749
- const item = data.find(doc => {
1750
- var _a3;
1751
- return ((_a3 = doc == null ? void 0 : doc._metadata) == null ? void 0 : _a3.documentId) === rubric.draggableId;
1752
- });
1753
- return /* @__PURE__ */jsx("div", {
1754
- ...provided.draggableProps,
1755
- ...provided.dragHandleProps,
1756
- ref: provided.innerRef,
1757
- children: item ? /* @__PURE__ */jsx(DocumentCard, {
1758
- isDragDisabled: false,
1759
- userRoleCanDrop,
1760
- isDragging: snapshot.isDragging,
1761
- item,
1762
- states,
1763
- toggleInvalidDocumentId,
1764
- userList
1765
- }) : /* @__PURE__ */jsx(Feedback, {
1766
- title: "Item not found",
1767
- tone: "caution"
1768
- })
1769
- });
1770
- },
1844
+ renderClone: Clone,
1771
1845
  children: (provided, snapshot) => /* @__PURE__ */jsxs(Card, {
1772
1846
  ref: provided.innerRef,
1773
1847
  tone: snapshot.isDraggingOver ? "primary" : defaultCardTone,
@@ -1783,6 +1857,7 @@ function WorkflowTool(props) {
1783
1857
  }) : null, /* @__PURE__ */jsx(DocumentList, {
1784
1858
  data,
1785
1859
  invalidDocumentIds,
1860
+ patchingIds,
1786
1861
  selectedSchemaTypes,
1787
1862
  selectedUserIds,
1788
1863
  state,