sanity-plugin-workflow 1.0.0-beta.5 → 1.0.0-beta.6
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/README.md +9 -5
- package/lib/index.esm.js +34 -9
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +34 -9
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/DocumentCard/index.tsx +0 -39
- package/src/components/DocumentList.tsx +1 -1
- package/src/components/StateTitle/index.tsx +31 -26
- package/src/components/Verify.tsx +23 -0
- package/src/components/WorkflowTool.tsx +9 -2
- package/src/hooks/useWorkflowDocuments.tsx +8 -5
- package/src/types/index.ts +0 -3
package/README.md
CHANGED
|
@@ -12,6 +12,8 @@ With Sanity Studio you can [customize your content tools to support arbitrary wo
|
|
|
12
12
|
|
|
13
13
|
This plugin is distributed as a **reference implementation** of these customization APIs and is not considered to be a feature-complete implementation of what workflow management requires in production. It is a starting point intended to be forked and customized to the needs of your organization and content creators.
|
|
14
14
|
|
|
15
|
+
A key intention of this plugin is that it **does not influence or modify whether a document is in draft or published**. It only tracks the values of a separate "metadata" document. In this implementation, an "Approved" document could be a draft but will still need publishing. "Approving" the document simply removes it from the Workflow process. You will decide if Publishing the document happens in the Studio like normal, using the [Scheduled Publishing plugin](https://www.sanity.io/plugins/scheduled-publishing) or the [Scheduling API](https://www.sanity.io/docs/scheduling-api#fa3bb95f83ed).
|
|
16
|
+
|
|
15
17
|

|
|
16
18
|
|
|
17
19
|
## Features
|
|
@@ -51,7 +53,7 @@ Add it as a plugin in sanity.config.ts (or .js):
|
|
|
51
53
|
// schemaTypes: ['article', 'product'],
|
|
52
54
|
schemaTypes: [],
|
|
53
55
|
// Optional, see below
|
|
54
|
-
states: [],
|
|
56
|
+
// states: [],
|
|
55
57
|
})
|
|
56
58
|
]
|
|
57
59
|
})
|
|
@@ -101,10 +103,12 @@ Once the Workflow is complete, the metadata can be removed by using the "Complet
|
|
|
101
103
|
|
|
102
104
|
This plugin is largely based on the original Workflow Demo built into a Sanity Studio v2 project. The major differences are:
|
|
103
105
|
|
|
104
|
-
* This plugin
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
106
|
+
* This plugin is not concerned with nor will modify whether a document is in draft or published.
|
|
107
|
+
* This plugin can be more easily installed and configured, not just code examples built into a Studio project.
|
|
108
|
+
* Documents must "opt-in" to and be removed from the Workflow. In the previous version, all documents were in the workflow which would fill up the interface and negatively affect performance.
|
|
109
|
+
* Document validation status can be used as a way to prevent movement through the workflow.
|
|
110
|
+
* User Roles and Assignments can affect the Workflow. Set rules to enforce which States documents can move between and if being assigned to a document is required to move it to a new State.
|
|
111
|
+
* This plugin can filter Schema types and assigned Users.
|
|
108
112
|
|
|
109
113
|
## License
|
|
110
114
|
|
package/lib/index.esm.js
CHANGED
|
@@ -633,7 +633,7 @@ function useWorkflowDocuments(schemaTypes) {
|
|
|
633
633
|
setLocalDocuments(data);
|
|
634
634
|
}
|
|
635
635
|
}, [data]);
|
|
636
|
-
const move = React.useCallback((draggedId, destination, states, newOrder) => {
|
|
636
|
+
const move = React.useCallback(async (draggedId, destination, states, newOrder) => {
|
|
637
637
|
const currentLocalData = localDocuments;
|
|
638
638
|
const newLocalDocuments = localDocuments.map(item => {
|
|
639
639
|
var _a;
|
|
@@ -680,10 +680,9 @@ function useWorkflowDocuments(schemaTypes) {
|
|
|
680
680
|
_type
|
|
681
681
|
} = document;
|
|
682
682
|
const {
|
|
683
|
-
_rev,
|
|
684
683
|
documentId
|
|
685
684
|
} = document._metadata || {};
|
|
686
|
-
client.patch("workflow-metadata.".concat(documentId)).
|
|
685
|
+
await client.patch("workflow-metadata.".concat(documentId)).set({
|
|
687
686
|
state: newStateId,
|
|
688
687
|
orderRank: newOrder
|
|
689
688
|
}).commit().then(() => {
|
|
@@ -692,11 +691,12 @@ function useWorkflowDocuments(schemaTypes) {
|
|
|
692
691
|
title: "Moved to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
|
|
693
692
|
status: "success"
|
|
694
693
|
});
|
|
695
|
-
}).catch(
|
|
694
|
+
}).catch(err => {
|
|
696
695
|
var _a;
|
|
697
696
|
setLocalDocuments(currentLocalData);
|
|
698
697
|
return toast.push({
|
|
699
698
|
title: "Failed to move to \"".concat((_a = newState == null ? void 0 : newState.title) != null ? _a : newStateId, "\""),
|
|
699
|
+
description: err.message,
|
|
700
700
|
status: "error"
|
|
701
701
|
});
|
|
702
702
|
});
|
|
@@ -1114,7 +1114,7 @@ function DocumentList(props) {
|
|
|
1114
1114
|
return (_c = (_b = (_a = dataFiltered[index]) == null ? void 0 : _a._metadata) == null ? void 0 : _b.documentId) != null ? _c : index;
|
|
1115
1115
|
},
|
|
1116
1116
|
estimateSize: () => 113,
|
|
1117
|
-
overscan:
|
|
1117
|
+
overscan: 10
|
|
1118
1118
|
});
|
|
1119
1119
|
if (!data.length) {
|
|
1120
1120
|
return null;
|
|
@@ -1326,7 +1326,8 @@ function StateTitle(props) {
|
|
|
1326
1326
|
requireAssignment,
|
|
1327
1327
|
userRoleCanDrop,
|
|
1328
1328
|
isDropDisabled,
|
|
1329
|
-
draggingFrom
|
|
1329
|
+
draggingFrom,
|
|
1330
|
+
documentCount
|
|
1330
1331
|
} = props;
|
|
1331
1332
|
let tone = "default";
|
|
1332
1333
|
const isSource = draggingFrom === state.id;
|
|
@@ -1351,7 +1352,15 @@ function StateTitle(props) {
|
|
|
1351
1352
|
}), requireAssignment ? /* @__PURE__ */jsx(Status, {
|
|
1352
1353
|
text: "You must be assigned to the document to move documents to this State",
|
|
1353
1354
|
icon: UserIcon
|
|
1354
|
-
}) : null
|
|
1355
|
+
}) : null, /* @__PURE__ */jsx(Box, {
|
|
1356
|
+
flex: 1,
|
|
1357
|
+
children: documentCount > 0 ? /* @__PURE__ */jsx(Text, {
|
|
1358
|
+
weight: "semibold",
|
|
1359
|
+
align: "right",
|
|
1360
|
+
size: 1,
|
|
1361
|
+
children: documentCount
|
|
1362
|
+
}) : null
|
|
1363
|
+
})]
|
|
1355
1364
|
})
|
|
1356
1365
|
});
|
|
1357
1366
|
}
|
|
@@ -1421,6 +1430,17 @@ function Verify(props) {
|
|
|
1421
1430
|
} = (_a = cur._metadata) != null ? _a : {};
|
|
1422
1431
|
return !orderRank && documentId ? [...acc, documentId] : acc;
|
|
1423
1432
|
}, []) : [];
|
|
1433
|
+
const documentsWithDuplicatedOrderIds = (data == null ? void 0 : data.length) ? data.reduce((acc, cur) => {
|
|
1434
|
+
var _a;
|
|
1435
|
+
const {
|
|
1436
|
+
documentId,
|
|
1437
|
+
orderRank
|
|
1438
|
+
} = (_a = cur._metadata) != null ? _a : {};
|
|
1439
|
+
return orderRank && data.filter(d => {
|
|
1440
|
+
var _a2;
|
|
1441
|
+
return ((_a2 = d._metadata) == null ? void 0 : _a2.orderRank) === orderRank;
|
|
1442
|
+
}).length > 1 && documentId ? [...acc, documentId] : acc;
|
|
1443
|
+
}, []) : [];
|
|
1424
1444
|
const correctDocuments = React.useCallback(async ids => {
|
|
1425
1445
|
toast.push({
|
|
1426
1446
|
title: "Correcting...",
|
|
@@ -1521,6 +1541,10 @@ function Verify(props) {
|
|
|
1521
1541
|
tone: "caution",
|
|
1522
1542
|
onClick: () => addOrderToDocuments(documentsWithoutOrderIds),
|
|
1523
1543
|
text: documentsWithoutOrderIds.length === 1 ? "Set Order for 1 Document" : "Set Order for ".concat(documentsWithoutOrderIds.length, " Documents")
|
|
1544
|
+
}) : null, documentsWithDuplicatedOrderIds.length > 0 ? /* @__PURE__ */jsx(Button, {
|
|
1545
|
+
tone: "caution",
|
|
1546
|
+
onClick: () => addOrderToDocuments(documentsWithDuplicatedOrderIds),
|
|
1547
|
+
text: documentsWithDuplicatedOrderIds.length === 1 ? "Set Unique Order for 1 Document" : "Set Unique Order for ".concat(documentsWithDuplicatedOrderIds.length, " Documents")
|
|
1524
1548
|
}) : null, orphanedMetadataDocumentIds.length > 0 ? /* @__PURE__ */jsx(Button, {
|
|
1525
1549
|
text: "Cleanup orphaned metadata",
|
|
1526
1550
|
onClick: handleOrphans,
|
|
@@ -1592,7 +1616,7 @@ function WorkflowTool(props) {
|
|
|
1592
1616
|
setUndroppableStates(undroppableExceptSelf);
|
|
1593
1617
|
}
|
|
1594
1618
|
}, [data, states, user]);
|
|
1595
|
-
const handleDragEnd = React.useCallback(result => {
|
|
1619
|
+
const handleDragEnd = React.useCallback(async result => {
|
|
1596
1620
|
var _a2, _b2, _c2, _d, _e, _f;
|
|
1597
1621
|
setUndroppableStates([]);
|
|
1598
1622
|
setDraggingFrom("");
|
|
@@ -1713,7 +1737,8 @@ function WorkflowTool(props) {
|
|
|
1713
1737
|
requireAssignment: (_b2 = state.requireAssignment) != null ? _b2 : false,
|
|
1714
1738
|
userRoleCanDrop,
|
|
1715
1739
|
isDropDisabled,
|
|
1716
|
-
draggingFrom
|
|
1740
|
+
draggingFrom,
|
|
1741
|
+
documentCount: filterItemsAndSort(data, state.id, selectedUserIds, selectedSchemaTypes).length
|
|
1717
1742
|
}), /* @__PURE__ */jsx(Box, {
|
|
1718
1743
|
flex: 1,
|
|
1719
1744
|
children: /* @__PURE__ */jsx(Droppable, {
|