sanity-plugin-workflow 1.0.0-beta.4 → 1.0.0-beta.5

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
@@ -49,8 +49,8 @@ const DEFAULT_CONFIG = {
49
49
  title: "Approved",
50
50
  color: "success",
51
51
  roles: ["administrator"],
52
- requireAssignment: true,
53
- transitions: ["changesRequested"]
52
+ transitions: ["changesRequested"],
53
+ requireAssignment: true
54
54
  }])
55
55
  };
56
56
  function UserAssignment(props) {
@@ -304,11 +304,6 @@ function UpdateWorkflow(props, allStates, actionState) {
304
304
  id,
305
305
  type
306
306
  } = props;
307
- const {
308
- validation,
309
- isValidating
310
- } = sanity.useValidationStatus(id, type);
311
- const hasValidationErrors = !isValidating && (validation == null ? void 0 : validation.length) > 0 && validation.find(v => v.level === "error");
312
307
  const user = sanity.useCurrentUser();
313
308
  const client = sanity.useClient({
314
309
  apiVersion: API_VERSION
@@ -326,6 +321,11 @@ function UpdateWorkflow(props, allStates, actionState) {
326
321
  const {
327
322
  assignees = []
328
323
  } = (_a = data == null ? void 0 : data.metadata) != null ? _a : {};
324
+ const {
325
+ validation,
326
+ isValidating
327
+ } = sanity.useValidationStatus(id, type);
328
+ const hasValidationErrors = (currentState == null ? void 0 : currentState.requireValidation) && !isValidating && (validation == null ? void 0 : validation.length) > 0 && validation.find(v => v.level === "error");
329
329
  if (error) {
330
330
  console.error(error);
331
331
  }
@@ -355,40 +355,39 @@ function UpdateWorkflow(props, allStates, actionState) {
355
355
  const direction = actionStateIndex > currentStateIndex ? "promote" : "demote";
356
356
  const DirectionIcon = direction === "promote" ? icons.ArrowRightIcon : icons.ArrowLeftIcon;
357
357
  const directionLabel = direction === "promote" ? "Promote" : "Demote";
358
- let title = "".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
359
358
  const userRoleCanUpdateState = ((_b = user == null ? void 0 : user.roles) == null ? void 0 : _b.length) && ((_c = actionState == null ? void 0 : actionState.roles) == null ? void 0 : _c.length) ?
360
359
  // If the Action state is limited to specific roles
361
360
  // check that the current user has one of those roles
362
361
  arraysContainMatchingString(user.roles.map(r => r.name), actionState.roles) :
363
362
  // No roles specified on the next state, so anyone can update
364
363
  ((_d = actionState == null ? void 0 : actionState.roles) == null ? void 0 : _d.length) !== 0;
365
- if (!userRoleCanUpdateState) {
366
- title = "Your User role cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
367
- }
368
364
  const actionStateIsAValidTransition = (currentState == null ? void 0 : currentState.id) && currentState.transitions.length ?
369
365
  // If the Current State limits transitions to specific States
370
366
  // Check that the Action State is in Current State's transitions array
371
367
  currentState.transitions.includes(actionState.id) :
372
368
  // Otherwise this isn't a problem
373
369
  true;
374
- if (!actionStateIsAValidTransition) {
375
- title = "You cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\" from \"").concat(currentState == null ? void 0 : currentState.title, "\"");
376
- }
377
370
  const userAssignmentCanUpdateState = actionState.requireAssignment ?
378
371
  // If the Action State requires assigned users
379
372
  // Check the current user ID is in the assignees array
380
373
  currentUser && assignees.length && assignees.includes(currentUser.id) :
381
374
  // Otherwise this isn't a problem
382
375
  true;
383
- if (!userAssignmentCanUpdateState) {
376
+ let title = "".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
377
+ if (!userRoleCanUpdateState) {
378
+ title = "Your User role cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
379
+ } else if (!actionStateIsAValidTransition) {
380
+ title = "You cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\" from \"").concat(currentState == null ? void 0 : currentState.title, "\"");
381
+ } else if (!userAssignmentCanUpdateState) {
384
382
  title = "You must be assigned to the document to ".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
385
- }
386
- if (hasValidationErrors) {
383
+ } else if ((currentState == null ? void 0 : currentState.requireValidation) && isValidating) {
384
+ title = "Document is validating, cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
385
+ } else if (hasValidationErrors) {
387
386
  title = "Document has validation errors, cannot ".concat(directionLabel, " State to \"").concat(actionState.title, "\"");
388
387
  }
389
388
  return {
390
389
  icon: DirectionIcon,
391
- disabled: loading || error || isValidating || hasValidationErrors || !currentState || !userRoleCanUpdateState || !actionStateIsAValidTransition || !userAssignmentCanUpdateState,
390
+ disabled: loading || error || (currentState == null ? void 0 : currentState.requireValidation) && isValidating || hasValidationErrors || !currentState || !userRoleCanUpdateState || !actionStateIsAValidTransition || !userAssignmentCanUpdateState,
392
391
  title,
393
392
  label: actionState.title,
394
393
  onHandle: () => onHandle(id, actionState)
@@ -921,6 +920,24 @@ function PublishedStatus(props) {
921
920
  })
922
921
  });
923
922
  }
923
+ function Validate(props) {
924
+ const {
925
+ documentId,
926
+ type,
927
+ onChange
928
+ } = props;
929
+ const {
930
+ isValidating,
931
+ validation = []
932
+ } = sanity.useValidationStatus(documentId, type);
933
+ React.useEffect(() => {
934
+ onChange({
935
+ isValidating,
936
+ validation
937
+ });
938
+ }, [onChange, isValidating, validation]);
939
+ return null;
940
+ }
924
941
  function ValidationStatus(props) {
925
942
  const {
926
943
  validation = []
@@ -946,7 +963,7 @@ function ValidationStatus(props) {
946
963
  });
947
964
  }
948
965
  function DocumentCard(props) {
949
- var _a;
966
+ var _a, _b;
950
967
  const {
951
968
  isDragDisabled,
952
969
  userRoleCanDrop,
@@ -961,18 +978,29 @@ function DocumentCard(props) {
961
978
  documentId
962
979
  } = (_a = item._metadata) != null ? _a : {};
963
980
  const schema = sanity.useSchema();
981
+ const state = states.find(s => {
982
+ var _a2;
983
+ return s.id === ((_a2 = item._metadata) == null ? void 0 : _a2.state);
984
+ });
964
985
  const isDarkMode = ui.useTheme().sanity.color.dark;
965
986
  const defaultCardTone = isDarkMode ? "transparent" : "default";
987
+ const [optimisticValidation, setOptimisticValidation] = React.useState({
988
+ isValidating: (_b = state == null ? void 0 : state.requireValidation) != null ? _b : false,
989
+ validation: []
990
+ });
966
991
  const {
967
- validation = [],
968
- isValidating
969
- } = sanity.useValidationStatus(documentId != null ? documentId : "", item._type);
992
+ isValidating,
993
+ validation
994
+ } = optimisticValidation;
995
+ const handleValidation = React.useCallback(updates => {
996
+ setOptimisticValidation(updates);
997
+ }, []);
970
998
  const cardTone = React.useMemo(() => {
971
999
  let tone = defaultCardTone;
972
1000
  if (!userRoleCanDrop) return isDarkMode ? "default" : "transparent";
973
1001
  if (!documentId) return tone;
974
1002
  if (isDragging) tone = "positive";
975
- if (!isValidating && validation.length > 0) {
1003
+ if ((state == null ? void 0 : state.requireValidation) && !isValidating && validation.length > 0) {
976
1004
  if (validation.some(v => v.level === "error")) {
977
1005
  tone = "critical";
978
1006
  } else {
@@ -980,7 +1008,7 @@ function DocumentCard(props) {
980
1008
  }
981
1009
  }
982
1010
  return tone;
983
- }, [isDarkMode, userRoleCanDrop, defaultCardTone, documentId, isDragging, validation, isValidating]);
1011
+ }, [defaultCardTone, userRoleCanDrop, isDarkMode, documentId, isDragging, isValidating, validation, state == null ? void 0 : state.requireValidation]);
984
1012
  React.useEffect(() => {
985
1013
  if (!isValidating && validation.length > 0) {
986
1014
  if (validation.some(v => v.level === "error")) {
@@ -997,75 +1025,81 @@ function DocumentCard(props) {
997
1025
  var _a2;
998
1026
  return states[states.length - 1].id === ((_a2 = item._metadata) == null ? void 0 : _a2.state);
999
1027
  }, [states, item._metadata.state]);
1000
- return /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1001
- paddingBottom: 3,
1002
- paddingX: 3,
1003
- children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1004
- radius: 2,
1005
- shadow: isDragging ? 3 : 1,
1006
- tone: cardTone,
1007
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1008
- children: [/* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1009
- borderBottom: true,
1010
- radius: 2,
1011
- padding: 3,
1012
- paddingLeft: 2,
1013
- tone: cardTone,
1014
- style: {
1015
- pointerEvents: "none"
1016
- },
1017
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1018
- align: "center",
1019
- justify: "space-between",
1020
- gap: 1,
1021
- children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1022
- flex: 1,
1023
- children: /* @__PURE__ */jsxRuntime.jsx(sanity.Preview, {
1024
- layout: "default",
1025
- value: item,
1026
- schemaType: schema.get(item._type)
1027
- })
1028
- }), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1029
- style: {
1030
- flexShrink: 0
1031
- },
1032
- children: hasError || isDragDisabled ? null : /* @__PURE__ */jsxRuntime.jsx(icons.DragHandleIcon, {})
1033
- })]
1034
- })
1035
- }), /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1036
- padding: 2,
1037
- radius: 2,
1038
- tone: "inherit",
1039
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1040
- align: "center",
1041
- justify: "space-between",
1042
- gap: 3,
1043
- children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1044
- flex: 1,
1045
- children: documentId && /* @__PURE__ */jsxRuntime.jsx(UserDisplay, {
1046
- userList,
1047
- assignees,
1028
+ return /* @__PURE__ */jsxRuntime.jsxs(jsxRuntime.Fragment, {
1029
+ children: [(state == null ? void 0 : state.requireValidation) ? /* @__PURE__ */jsxRuntime.jsx(Validate, {
1030
+ documentId,
1031
+ type: item._type,
1032
+ onChange: handleValidation
1033
+ }) : null, /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1034
+ paddingBottom: 3,
1035
+ paddingX: 3,
1036
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1037
+ radius: 2,
1038
+ shadow: isDragging ? 3 : 1,
1039
+ tone: cardTone,
1040
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
1041
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1042
+ borderBottom: true,
1043
+ radius: 2,
1044
+ padding: 3,
1045
+ paddingLeft: 2,
1046
+ tone: cardTone,
1047
+ style: {
1048
+ pointerEvents: "none"
1049
+ },
1050
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1051
+ align: "center",
1052
+ justify: "space-between",
1053
+ gap: 1,
1054
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1055
+ flex: 1,
1056
+ children: /* @__PURE__ */jsxRuntime.jsx(sanity.Preview, {
1057
+ layout: "default",
1058
+ value: item,
1059
+ schemaType: schema.get(item._type)
1060
+ })
1061
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1062
+ style: {
1063
+ flexShrink: 0
1064
+ },
1065
+ children: hasError || isDragDisabled ? null : /* @__PURE__ */jsxRuntime.jsx(icons.DragHandleIcon, {})
1066
+ })]
1067
+ })
1068
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1069
+ padding: 2,
1070
+ radius: 2,
1071
+ tone: "inherit",
1072
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1073
+ align: "center",
1074
+ justify: "space-between",
1075
+ gap: 3,
1076
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1077
+ flex: 1,
1078
+ children: documentId && /* @__PURE__ */jsxRuntime.jsx(UserDisplay, {
1079
+ userList,
1080
+ assignees,
1081
+ documentId,
1082
+ disabled: !userRoleCanDrop
1083
+ })
1084
+ }), validation.length > 0 ? /* @__PURE__ */jsxRuntime.jsx(ValidationStatus, {
1085
+ validation
1086
+ }) : null, /* @__PURE__ */jsxRuntime.jsx(DraftStatus, {
1087
+ document: item
1088
+ }), /* @__PURE__ */jsxRuntime.jsx(PublishedStatus, {
1089
+ document: item
1090
+ }), /* @__PURE__ */jsxRuntime.jsx(EditButton, {
1091
+ id: item._id,
1092
+ type: item._type,
1093
+ disabled: !userRoleCanDrop
1094
+ }), isLastState ? /* @__PURE__ */jsxRuntime.jsx(CompleteButton, {
1048
1095
  documentId,
1049
1096
  disabled: !userRoleCanDrop
1050
- })
1051
- }), validation.length > 0 ? /* @__PURE__ */jsxRuntime.jsx(ValidationStatus, {
1052
- validation
1053
- }) : null, /* @__PURE__ */jsxRuntime.jsx(DraftStatus, {
1054
- document: item
1055
- }), /* @__PURE__ */jsxRuntime.jsx(PublishedStatus, {
1056
- document: item
1057
- }), /* @__PURE__ */jsxRuntime.jsx(EditButton, {
1058
- id: item._id,
1059
- type: item._type,
1060
- disabled: !userRoleCanDrop
1061
- }), isLastState ? /* @__PURE__ */jsxRuntime.jsx(CompleteButton, {
1062
- documentId,
1063
- disabled: !userRoleCanDrop
1064
- }) : null]
1065
- })
1066
- })]
1097
+ }) : null]
1098
+ })
1099
+ })]
1100
+ })
1067
1101
  })
1068
- })
1102
+ })]
1069
1103
  });
1070
1104
  }
1071
1105
  function DocumentList(props) {
@@ -1364,12 +1398,12 @@ function FloatingCard(_ref3) {
1364
1398
  }, "floater") : null
1365
1399
  });
1366
1400
  }
1367
- function Validators(_ref4) {
1368
- let {
1401
+ function Verify(props) {
1402
+ const {
1369
1403
  data,
1370
1404
  userList,
1371
1405
  states
1372
- } = _ref4;
1406
+ } = props;
1373
1407
  const client = sanity.useClient({
1374
1408
  apiVersion: API_VERSION
1375
1409
  });
@@ -1600,10 +1634,10 @@ function WorkflowTool(props) {
1600
1634
  } else {
1601
1635
  const itemBefore = destinationStateItems[destination.index - 1];
1602
1636
  const itemBeforeRank = (_e = itemBefore == null ? void 0 : itemBefore._metadata) == null ? void 0 : _e.orderRank;
1603
- const itemBeforeRankParsed = itemBefore._metadata.orderRank ? lexorank.LexoRank.parse(itemBeforeRank) : lexorank.LexoRank.min();
1637
+ const itemBeforeRankParsed = itemBeforeRank ? lexorank.LexoRank.parse(itemBeforeRank) : lexorank.LexoRank.min();
1604
1638
  const itemAfter = destinationStateItems[destination.index];
1605
1639
  const itemAfterRank = (_f = itemAfter == null ? void 0 : itemAfter._metadata) == null ? void 0 : _f.orderRank;
1606
- const itemAfterRankParsed = itemAfter._metadata.orderRank ? lexorank.LexoRank.parse(itemAfterRank) : lexorank.LexoRank.max();
1640
+ const itemAfterRankParsed = itemAfterRank ? lexorank.LexoRank.parse(itemAfterRank) : lexorank.LexoRank.max();
1607
1641
  newOrder = itemBeforeRankParsed.between(itemAfterRankParsed).toString();
1608
1642
  }
1609
1643
  move(draggableId, destination, states, newOrder);
@@ -1659,7 +1693,7 @@ function WorkflowTool(props) {
1659
1693
  direction: "column",
1660
1694
  height: "fill",
1661
1695
  overflow: "hidden",
1662
- children: [/* @__PURE__ */jsxRuntime.jsx(Validators, {
1696
+ children: [/* @__PURE__ */jsxRuntime.jsx(Verify, {
1663
1697
  data,
1664
1698
  userList,
1665
1699
  states