@strapi/review-workflows 0.0.0-next.f6dca5adf05ef6bed9605a1535999ab0bbbf063e → 0.0.0-next.fc9d26d995624dc886b29f563e1de655d47e6609

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.
Files changed (102) hide show
  1. package/dist/admin/chunks/Layout-B4l91S3p.js +290 -0
  2. package/dist/admin/chunks/Layout-B4l91S3p.js.map +1 -0
  3. package/dist/admin/chunks/Layout-CXRcBLOx.js +265 -0
  4. package/dist/admin/chunks/Layout-CXRcBLOx.js.map +1 -0
  5. package/dist/admin/chunks/en-BixG7IBu.js +14 -0
  6. package/dist/admin/chunks/en-BixG7IBu.js.map +1 -0
  7. package/dist/admin/chunks/en-C6SESe-Y.js +16 -0
  8. package/dist/admin/chunks/en-C6SESe-Y.js.map +1 -0
  9. package/dist/admin/chunks/id-DnRGfGvc.js +1442 -0
  10. package/dist/admin/chunks/id-DnRGfGvc.js.map +1 -0
  11. package/dist/admin/chunks/id-SiBUWtYE.js +1420 -0
  12. package/dist/admin/chunks/id-SiBUWtYE.js.map +1 -0
  13. package/dist/admin/chunks/index-C5IeISWp.js +960 -0
  14. package/dist/admin/chunks/index-C5IeISWp.js.map +1 -0
  15. package/dist/admin/chunks/index-D-2M8KV9.js +271 -0
  16. package/dist/admin/chunks/index-D-2M8KV9.js.map +1 -0
  17. package/dist/admin/chunks/index-DZpcSUvc.js +293 -0
  18. package/dist/admin/chunks/index-DZpcSUvc.js.map +1 -0
  19. package/dist/admin/chunks/index-Df6sZesT.js +926 -0
  20. package/dist/admin/chunks/index-Df6sZesT.js.map +1 -0
  21. package/dist/admin/chunks/purchase-review-workflows-CEP8kvxZ.js +53 -0
  22. package/dist/admin/chunks/purchase-review-workflows-CEP8kvxZ.js.map +1 -0
  23. package/dist/admin/chunks/purchase-review-workflows-Drlxm8yP.js +55 -0
  24. package/dist/admin/chunks/purchase-review-workflows-Drlxm8yP.js.map +1 -0
  25. package/dist/admin/chunks/router-C9Jpl4gL.js +28 -0
  26. package/dist/admin/chunks/router-C9Jpl4gL.js.map +1 -0
  27. package/dist/admin/chunks/router-CrN8UbpP.js +30 -0
  28. package/dist/admin/chunks/router-CrN8UbpP.js.map +1 -0
  29. package/dist/admin/index.js +17 -2
  30. package/dist/admin/index.js.map +1 -1
  31. package/dist/admin/index.mjs +12 -4
  32. package/dist/admin/index.mjs.map +1 -1
  33. package/dist/admin/src/services/settings.d.ts +7 -3
  34. package/dist/server/index.js +2112 -7996
  35. package/dist/server/index.js.map +1 -1
  36. package/dist/server/index.mjs +2118 -8005
  37. package/dist/server/index.mjs.map +1 -1
  38. package/dist/server/src/bootstrap.d.ts.map +1 -1
  39. package/dist/server/src/constants/workflows.d.ts +1 -0
  40. package/dist/server/src/constants/workflows.d.ts.map +1 -1
  41. package/dist/server/src/content-types/index.d.ts +6 -0
  42. package/dist/server/src/content-types/index.d.ts.map +1 -1
  43. package/dist/server/src/content-types/workflow/index.d.ts +6 -0
  44. package/dist/server/src/content-types/workflow/index.d.ts.map +1 -1
  45. package/dist/server/src/controllers/assignees.d.ts.map +1 -1
  46. package/dist/server/src/controllers/stages.d.ts.map +1 -1
  47. package/dist/server/src/index.d.ts +28 -6
  48. package/dist/server/src/index.d.ts.map +1 -1
  49. package/dist/server/src/register.d.ts.map +1 -1
  50. package/dist/server/src/services/assignees.d.ts +8 -4
  51. package/dist/server/src/services/assignees.d.ts.map +1 -1
  52. package/dist/server/src/services/document-service-middleware.d.ts +2 -1
  53. package/dist/server/src/services/document-service-middleware.d.ts.map +1 -1
  54. package/dist/server/src/services/index.d.ts +16 -6
  55. package/dist/server/src/services/index.d.ts.map +1 -1
  56. package/dist/server/src/services/metrics/index.d.ts +4 -4
  57. package/dist/server/src/services/metrics/index.d.ts.map +1 -1
  58. package/dist/server/src/services/stages.d.ts +6 -1
  59. package/dist/server/src/services/stages.d.ts.map +1 -1
  60. package/dist/server/src/services/workflows.d.ts.map +1 -1
  61. package/dist/server/src/validation/review-workflows.d.ts +4 -0
  62. package/dist/server/src/validation/review-workflows.d.ts.map +1 -1
  63. package/dist/shared/contracts/review-workflows.d.ts +8 -4
  64. package/dist/shared/contracts/review-workflows.d.ts.map +1 -1
  65. package/package.json +17 -15
  66. package/dist/_chunks/Layout-8i0EXRRs.js +0 -251
  67. package/dist/_chunks/Layout-8i0EXRRs.js.map +0 -1
  68. package/dist/_chunks/Layout-C9m07iTY.mjs +0 -233
  69. package/dist/_chunks/Layout-C9m07iTY.mjs.map +0 -1
  70. package/dist/_chunks/en-D9ZrQAV6.mjs +0 -12
  71. package/dist/_chunks/en-D9ZrQAV6.mjs.map +0 -1
  72. package/dist/_chunks/en-xcewH2pC.js +0 -12
  73. package/dist/_chunks/en-xcewH2pC.js.map +0 -1
  74. package/dist/_chunks/id-CmtaTf1x.js +0 -1237
  75. package/dist/_chunks/id-CmtaTf1x.js.map +0 -1
  76. package/dist/_chunks/id-DV0Ndeav.mjs +0 -1217
  77. package/dist/_chunks/id-DV0Ndeav.mjs.map +0 -1
  78. package/dist/_chunks/index-B8WmHbCU.js +0 -233
  79. package/dist/_chunks/index-B8WmHbCU.js.map +0 -1
  80. package/dist/_chunks/index-BCUO98DV.js +0 -830
  81. package/dist/_chunks/index-BCUO98DV.js.map +0 -1
  82. package/dist/_chunks/index-CA5Axcoc.mjs +0 -214
  83. package/dist/_chunks/index-CA5Axcoc.mjs.map +0 -1
  84. package/dist/_chunks/index-CqYVkW3E.mjs +0 -812
  85. package/dist/_chunks/index-CqYVkW3E.mjs.map +0 -1
  86. package/dist/_chunks/purchase-review-workflows-BN-5Ube7.mjs +0 -52
  87. package/dist/_chunks/purchase-review-workflows-BN-5Ube7.mjs.map +0 -1
  88. package/dist/_chunks/purchase-review-workflows-DlCDg0fD.js +0 -52
  89. package/dist/_chunks/purchase-review-workflows-DlCDg0fD.js.map +0 -1
  90. package/dist/_chunks/router-BOXlNnrU.js +0 -24
  91. package/dist/_chunks/router-BOXlNnrU.js.map +0 -1
  92. package/dist/_chunks/router-Jdt6SbIA.mjs +0 -24
  93. package/dist/_chunks/router-Jdt6SbIA.mjs.map +0 -1
  94. /package/dist/admin/src/routes/content-manager/{[model] → model}/components/AssigneeFilter.d.ts +0 -0
  95. /package/dist/admin/src/routes/content-manager/{[model] → model}/components/StageFilter.d.ts +0 -0
  96. /package/dist/admin/src/routes/content-manager/{[model] → model}/components/TableColumns.d.ts +0 -0
  97. /package/dist/admin/src/routes/content-manager/{[model] → model}/configure/constants.d.ts +0 -0
  98. /package/dist/admin/src/routes/content-manager/{[model] → model}/constants.d.ts +0 -0
  99. /package/dist/admin/src/routes/content-manager/{[model]/[id] → model/id}/components/AssigneeSelect.d.ts +0 -0
  100. /package/dist/admin/src/routes/content-manager/{[model]/[id] → model/id}/components/Panel.d.ts +0 -0
  101. /package/dist/admin/src/routes/content-manager/{[model]/[id] → model/id}/components/StageSelect.d.ts +0 -0
  102. /package/dist/admin/src/routes/content-manager/{[model]/[id] → model/id}/components/constants.d.ts +0 -0
@@ -1,1237 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const jsxRuntime = require("react/jsx-runtime");
4
- const React = require("react");
5
- const strapiAdmin = require("@strapi/admin/strapi-admin");
6
- const ee = require("@strapi/admin/strapi-admin/ee");
7
- const designSystem = require("@strapi/design-system");
8
- const icons = require("@strapi/icons");
9
- const fractionalIndexing = require("fractional-indexing");
10
- const reactIntl = require("react-intl");
11
- const reactRouterDom = require("react-router-dom");
12
- const yup = require("yup");
13
- const index = require("./index-BCUO98DV.js");
14
- const Layout = require("./Layout-8i0EXRRs.js");
15
- const reactDndHtml5Backend = require("react-dnd-html5-backend");
16
- const styledComponents = require("styled-components");
17
- const reactDnd = require("react-dnd");
18
- function _interopNamespace(e) {
19
- if (e && e.__esModule)
20
- return e;
21
- const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
22
- if (e) {
23
- for (const k in e) {
24
- if (k !== "default") {
25
- const d = Object.getOwnPropertyDescriptor(e, k);
26
- Object.defineProperty(n, k, d.get ? d : {
27
- enumerable: true,
28
- get: () => e[k]
29
- });
30
- }
31
- }
32
- }
33
- n.default = e;
34
- return Object.freeze(n);
35
- }
36
- const React__namespace = /* @__PURE__ */ _interopNamespace(React);
37
- const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
38
- const adminApi = index.reviewWorkflowsApi.injectEndpoints({
39
- endpoints(builder) {
40
- return {
41
- getAdminRoles: builder.query({
42
- query: () => ({
43
- url: `/admin/roles`,
44
- method: "GET"
45
- }),
46
- transformResponse: (res) => {
47
- return res.data;
48
- }
49
- })
50
- };
51
- }
52
- });
53
- const { useGetAdminRolesQuery } = adminApi;
54
- const useKeyboardDragAndDrop = (active, index2, { onCancel, onDropItem, onGrabItem, onMoveItem }) => {
55
- const [isSelected, setIsSelected] = React__namespace.useState(false);
56
- const handleMove = (movement) => {
57
- if (!isSelected) {
58
- return;
59
- }
60
- if (typeof index2 === "number" && onMoveItem) {
61
- if (movement === "UP") {
62
- onMoveItem(index2 - 1, index2);
63
- } else if (movement === "DOWN") {
64
- onMoveItem(index2 + 1, index2);
65
- }
66
- }
67
- };
68
- const handleDragClick = () => {
69
- if (isSelected) {
70
- if (onDropItem) {
71
- onDropItem(index2);
72
- }
73
- setIsSelected(false);
74
- } else {
75
- if (onGrabItem) {
76
- onGrabItem(index2);
77
- }
78
- setIsSelected(true);
79
- }
80
- };
81
- const handleCancel = () => {
82
- if (isSelected) {
83
- setIsSelected(false);
84
- if (onCancel) {
85
- onCancel(index2);
86
- }
87
- }
88
- };
89
- const handleKeyDown = (e) => {
90
- if (!active) {
91
- return;
92
- }
93
- if (e.key === "Tab" && !isSelected) {
94
- return;
95
- }
96
- e.preventDefault();
97
- switch (e.key) {
98
- case " ":
99
- case "Enter":
100
- handleDragClick();
101
- break;
102
- case "Escape":
103
- handleCancel();
104
- break;
105
- case "ArrowDown":
106
- case "ArrowRight":
107
- handleMove("DOWN");
108
- break;
109
- case "ArrowUp":
110
- case "ArrowLeft":
111
- handleMove("UP");
112
- break;
113
- }
114
- };
115
- return handleKeyDown;
116
- };
117
- const DIRECTIONS = {
118
- UPWARD: "upward",
119
- DOWNWARD: "downward"
120
- };
121
- const DROP_SENSITIVITY = {
122
- REGULAR: "regular",
123
- IMMEDIATE: "immediate"
124
- };
125
- const useDragAndDrop = (active, {
126
- type = "STRAPI_DND",
127
- index: index2,
128
- item,
129
- onStart,
130
- onEnd,
131
- onGrabItem,
132
- onDropItem,
133
- onCancel,
134
- onMoveItem,
135
- dropSensitivity = DROP_SENSITIVITY.REGULAR
136
- }) => {
137
- const objectRef = React__namespace.useRef(null);
138
- const [{ handlerId, isOver }, dropRef] = reactDnd.useDrop({
139
- accept: type,
140
- collect(monitor) {
141
- return {
142
- handlerId: monitor.getHandlerId(),
143
- isOver: monitor.isOver({ shallow: true })
144
- };
145
- },
146
- drop(item2) {
147
- const draggedIndex = item2.index;
148
- const newIndex = index2;
149
- if (isOver && onDropItem) {
150
- onDropItem(draggedIndex, newIndex);
151
- }
152
- },
153
- hover(item2, monitor) {
154
- if (!objectRef.current || !onMoveItem) {
155
- return;
156
- }
157
- const dragIndex = item2.index;
158
- const newIndex = index2;
159
- const hoverBoundingRect = objectRef.current?.getBoundingClientRect();
160
- const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
161
- const clientOffset = monitor.getClientOffset();
162
- if (!clientOffset)
163
- return;
164
- const hoverClientY = clientOffset && clientOffset.y - hoverBoundingRect.top;
165
- if (typeof dragIndex === "number" && typeof newIndex === "number") {
166
- if (dragIndex === newIndex) {
167
- return;
168
- }
169
- if (dropSensitivity === DROP_SENSITIVITY.REGULAR) {
170
- if (dragIndex < newIndex && hoverClientY < hoverMiddleY) {
171
- return;
172
- }
173
- if (dragIndex > newIndex && hoverClientY > hoverMiddleY) {
174
- return;
175
- }
176
- }
177
- onMoveItem(newIndex, dragIndex);
178
- item2.index = newIndex;
179
- } else {
180
- if (Array.isArray(dragIndex) && Array.isArray(newIndex)) {
181
- const minLength = Math.min(dragIndex.length, newIndex.length);
182
- let areEqual = true;
183
- let isLessThan = false;
184
- let isGreaterThan = false;
185
- for (let i = 0; i < minLength; i++) {
186
- if (dragIndex[i] < newIndex[i]) {
187
- isLessThan = true;
188
- areEqual = false;
189
- break;
190
- } else if (dragIndex[i] > newIndex[i]) {
191
- isGreaterThan = true;
192
- areEqual = false;
193
- break;
194
- }
195
- }
196
- if (areEqual && dragIndex.length === newIndex.length) {
197
- return;
198
- }
199
- if (dropSensitivity === DROP_SENSITIVITY.REGULAR) {
200
- if (isLessThan && !isGreaterThan && hoverClientY < hoverMiddleY) {
201
- return;
202
- }
203
- if (isGreaterThan && !isLessThan && hoverClientY > hoverMiddleY) {
204
- return;
205
- }
206
- }
207
- }
208
- onMoveItem(newIndex, dragIndex);
209
- item2.index = newIndex;
210
- }
211
- }
212
- });
213
- const getDragDirection = (monitor) => {
214
- if (monitor && monitor.isDragging() && !monitor.didDrop() && monitor.getInitialClientOffset() && monitor.getClientOffset()) {
215
- const deltaY = monitor.getInitialClientOffset().y - monitor.getClientOffset().y;
216
- if (deltaY > 0)
217
- return DIRECTIONS.UPWARD;
218
- if (deltaY < 0)
219
- return DIRECTIONS.DOWNWARD;
220
- return null;
221
- }
222
- return null;
223
- };
224
- const [{ isDragging, direction }, dragRef, dragPreviewRef] = reactDnd.useDrag({
225
- type,
226
- item() {
227
- if (onStart) {
228
- onStart();
229
- }
230
- const { width } = objectRef.current?.getBoundingClientRect() ?? {};
231
- return { index: index2, width, ...item };
232
- },
233
- end() {
234
- if (onEnd) {
235
- onEnd();
236
- }
237
- },
238
- canDrag: active,
239
- /**
240
- * This is useful when the item is in a virtualized list.
241
- * However, if we don't have an ID then we want the libraries
242
- * defaults to take care of this.
243
- */
244
- isDragging: item?.id ? (monitor) => {
245
- return item.id === monitor.getItem().id;
246
- } : void 0,
247
- collect: (monitor) => ({
248
- isDragging: monitor.isDragging(),
249
- initialOffset: monitor.getInitialClientOffset(),
250
- currentOffset: monitor.getClientOffset(),
251
- direction: getDragDirection(monitor)
252
- })
253
- });
254
- const handleKeyDown = useKeyboardDragAndDrop(active, index2, {
255
- onGrabItem,
256
- onDropItem,
257
- onCancel,
258
- onMoveItem
259
- });
260
- return [
261
- { handlerId, isDragging, handleKeyDown, isOverDropTarget: isOver, direction },
262
- objectRef,
263
- dropRef,
264
- dragRef,
265
- dragPreviewRef
266
- ];
267
- };
268
- const AddStage = ({ children, ...props }) => {
269
- return /* @__PURE__ */ jsxRuntime.jsx(
270
- StyledButton,
271
- {
272
- tag: "button",
273
- background: "neutral0",
274
- borderColor: "neutral150",
275
- paddingBottom: 3,
276
- paddingLeft: 4,
277
- paddingRight: 4,
278
- paddingTop: 3,
279
- shadow: "filterShadow",
280
- ...props,
281
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { tag: "span", gap: 2, children: [
282
- /* @__PURE__ */ jsxRuntime.jsx(icons.PlusCircle, { width: "2.4rem", height: "2.4rem", "aria-hidden": true }),
283
- children
284
- ] }) })
285
- }
286
- );
287
- };
288
- const StyledButton = styledComponents.styled(designSystem.Box)`
289
- border-radius: 26px;
290
- color: ${({ theme }) => theme.colors.neutral500};
291
-
292
- &:hover {
293
- color: ${({ theme }) => theme.colors.primary600};
294
- }
295
-
296
- &:active {
297
- color: ${({ theme }) => theme.colors.primary600};
298
- }
299
- `;
300
- const Stages = ({ canDelete = true, canUpdate = true, isCreating }) => {
301
- const { formatMessage } = reactIntl.useIntl();
302
- const { trackUsage } = strapiAdmin.useTracking();
303
- const addFieldRow = strapiAdmin.useForm("Stages", (state) => state.addFieldRow);
304
- const { value: stages = [] } = strapiAdmin.useField("stages");
305
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 6, width: "100%", children: [
306
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { position: "relative", width: "100%", children: [
307
- /* @__PURE__ */ jsxRuntime.jsx(
308
- Background,
309
- {
310
- background: "neutral200",
311
- height: "100%",
312
- left: "50%",
313
- position: "absolute",
314
- top: "0",
315
- width: 2
316
- }
317
- ),
318
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 6, position: "relative", tag: "ol", children: stages.map((stage, index2) => {
319
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "li", children: /* @__PURE__ */ jsxRuntime.jsx(
320
- Stage,
321
- {
322
- index: index2,
323
- canDelete: stages.length > 1 && canDelete,
324
- canReorder: stages.length > 1,
325
- canUpdate,
326
- stagesCount: stages.length,
327
- defaultOpen: isCreating,
328
- ...stage
329
- }
330
- ) }, stage.__temp_key__);
331
- }) })
332
- ] }),
333
- canUpdate && /* @__PURE__ */ jsxRuntime.jsx(
334
- AddStage,
335
- {
336
- type: "button",
337
- onClick: () => {
338
- addFieldRow("stages", { name: "" });
339
- trackUsage("willCreateStage");
340
- },
341
- children: formatMessage({
342
- id: "Settings.review-workflows.stage.add",
343
- defaultMessage: "Add new stage"
344
- })
345
- }
346
- )
347
- ] });
348
- };
349
- const Background = styledComponents.styled(designSystem.Box)`
350
- transform: translateX(-50%);
351
- `;
352
- const Stage = ({
353
- index: index2,
354
- canDelete = false,
355
- canReorder = false,
356
- canUpdate = false,
357
- stagesCount,
358
- name,
359
- permissions,
360
- color,
361
- defaultOpen
362
- }) => {
363
- const [liveText, setLiveText] = React__namespace.useState();
364
- const { formatMessage } = reactIntl.useIntl();
365
- const { trackUsage } = strapiAdmin.useTracking();
366
- const stageErrors = strapiAdmin.useForm("Stages", (state) => state.errors.stages);
367
- const error = stageErrors?.[index2];
368
- const addFieldRow = strapiAdmin.useForm("Stage", (state) => state.addFieldRow);
369
- const moveFieldRow = strapiAdmin.useForm("Stage", (state) => state.moveFieldRow);
370
- const removeFieldRow = strapiAdmin.useForm("Stage", (state) => state.removeFieldRow);
371
- const getItemPos = (index22) => `${index22 + 1} of ${stagesCount}`;
372
- const handleGrabStage = (index22) => {
373
- setLiveText(
374
- formatMessage(
375
- {
376
- id: "dnd.grab-item",
377
- defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
378
- },
379
- {
380
- item: name,
381
- position: getItemPos(index22)
382
- }
383
- )
384
- );
385
- };
386
- const handleDropStage = (index22) => {
387
- setLiveText(
388
- formatMessage(
389
- {
390
- id: "dnd.drop-item",
391
- defaultMessage: `{item}, dropped. Final position in list: {position}.`
392
- },
393
- {
394
- item: name,
395
- position: getItemPos(index22)
396
- }
397
- )
398
- );
399
- };
400
- const handleCancelDragStage = () => {
401
- setLiveText(
402
- formatMessage(
403
- {
404
- id: "dnd.cancel-item",
405
- defaultMessage: "{item}, dropped. Re-order cancelled."
406
- },
407
- {
408
- item: name
409
- }
410
- )
411
- );
412
- };
413
- const handleMoveStage = (newIndex, oldIndex) => {
414
- setLiveText(
415
- formatMessage(
416
- {
417
- id: "dnd.reorder",
418
- defaultMessage: "{item}, moved. New position in list: {position}."
419
- },
420
- {
421
- item: name,
422
- position: getItemPos(newIndex)
423
- }
424
- )
425
- );
426
- moveFieldRow("stages", oldIndex, newIndex);
427
- };
428
- const [{ handlerId, isDragging, handleKeyDown }, stageRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(canReorder, {
429
- index: index2,
430
- item: {
431
- index: index2,
432
- name
433
- },
434
- onGrabItem: handleGrabStage,
435
- onDropItem: handleDropStage,
436
- onMoveItem: handleMoveStage,
437
- onCancel: handleCancelDragStage,
438
- type: Layout.DRAG_DROP_TYPES.STAGE
439
- });
440
- const composedRef = designSystem.useComposedRefs(stageRef, dropRef);
441
- React__namespace.useEffect(() => {
442
- dragPreviewRef(reactDndHtml5Backend.getEmptyImage(), { captureDraggingState: false });
443
- }, [dragPreviewRef, index2]);
444
- const handleCloneClick = () => {
445
- addFieldRow("stages", { name, color, permissions });
446
- };
447
- const id = React__namespace.useId();
448
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { ref: composedRef, shadow: "tableShadow", children: [
449
- liveText && /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { "aria-live": "assertive", children: liveText }),
450
- isDragging ? /* @__PURE__ */ jsxRuntime.jsx(
451
- designSystem.Box,
452
- {
453
- background: "primary100",
454
- borderStyle: "dashed",
455
- borderColor: "primary600",
456
- borderWidth: "1px",
457
- display: "block",
458
- hasRadius: true,
459
- padding: 6
460
- }
461
- ) : /* @__PURE__ */ jsxRuntime.jsx(
462
- AccordionRoot,
463
- {
464
- onValueChange: (value) => {
465
- if (value) {
466
- trackUsage("willEditStage");
467
- }
468
- },
469
- defaultValue: defaultOpen ? id : void 0,
470
- $error: Object.values(error ?? {}).length > 0,
471
- children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Item, { value: id, children: [
472
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Header, { children: [
473
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Trigger, { children: name }),
474
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Actions, { children: canDelete || canUpdate ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
475
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { children: [
476
- /* @__PURE__ */ jsxRuntime.jsxs(ContextMenuTrigger, { size: "S", endIcon: null, paddingLeft: 2, paddingRight: 2, children: [
477
- /* @__PURE__ */ jsxRuntime.jsx(icons.More, { "aria-hidden": true, focusable: false }),
478
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: formatMessage({
479
- id: "[tbdb].components.DynamicZone.more-actions",
480
- defaultMessage: "More actions"
481
- }) })
482
- ] }),
483
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Menu.Content, { popoverPlacement: "bottom-end", zIndex: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.SubRoot, { children: [
484
- canUpdate && /* @__PURE__ */ jsxRuntime.jsx(designSystem.MenuItem, { onClick: handleCloneClick, children: formatMessage({
485
- id: "Settings.review-workflows.stage.delete",
486
- defaultMessage: "Duplicate stage"
487
- }) }),
488
- canDelete && /* @__PURE__ */ jsxRuntime.jsx(DeleteMenuItem, { onClick: () => removeFieldRow("stages", index2), children: formatMessage({
489
- id: "Settings.review-workflows.stage.delete",
490
- defaultMessage: "Delete"
491
- }) })
492
- ] }) })
493
- ] }),
494
- canUpdate && /* @__PURE__ */ jsxRuntime.jsx(
495
- designSystem.IconButton,
496
- {
497
- background: "transparent",
498
- hasRadius: true,
499
- variant: "ghost",
500
- "data-handler-id": handlerId,
501
- ref: dragRef,
502
- label: formatMessage({
503
- id: "Settings.review-workflows.stage.drag",
504
- defaultMessage: "Drag"
505
- }),
506
- onClick: (e) => e.stopPropagation(),
507
- onKeyDown: handleKeyDown,
508
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.Drag, {})
509
- }
510
- )
511
- ] }) : null })
512
- ] }),
513
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { gap: 4, padding: 6, children: [
514
- {
515
- disabled: !canUpdate,
516
- label: formatMessage({
517
- id: "Settings.review-workflows.stage.name.label",
518
- defaultMessage: "Stage name"
519
- }),
520
- name: `stages.${index2}.name`,
521
- required: true,
522
- size: 6,
523
- type: "string"
524
- },
525
- {
526
- disabled: !canUpdate,
527
- label: formatMessage({
528
- id: "content-manager.reviewWorkflows.stage.color",
529
- defaultMessage: "Color"
530
- }),
531
- name: `stages.${index2}.color`,
532
- required: true,
533
- size: 6,
534
- type: "color"
535
- },
536
- {
537
- disabled: !canUpdate,
538
- label: formatMessage({
539
- id: "Settings.review-workflows.stage.permissions.label",
540
- defaultMessage: "Roles that can change this stage"
541
- }),
542
- name: `stages.${index2}.permissions`,
543
- placeholder: formatMessage({
544
- id: "Settings.review-workflows.stage.permissions.placeholder",
545
- defaultMessage: "Select a role"
546
- }),
547
- required: true,
548
- size: 6,
549
- type: "permissions"
550
- }
551
- ].map(({ size, ...field }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: size, direction: "column", alignItems: "stretch", children: /* @__PURE__ */ jsxRuntime.jsx(InputRenderer, { ...field }) }, field.name)) }) })
552
- ] })
553
- }
554
- )
555
- ] });
556
- };
557
- const AccordionRoot = styledComponents.styled(designSystem.Accordion.Root)`
558
- border: 1px solid
559
- ${({ theme, $error }) => $error ? theme.colors.danger600 : theme.colors.neutral200};
560
- `;
561
- const DeleteMenuItem = styledComponents.styled(designSystem.MenuItem)`
562
- color: ${({ theme }) => theme.colors.danger600};
563
- `;
564
- const ContextMenuTrigger = styledComponents.styled(designSystem.Menu.Trigger)`
565
- :hover,
566
- :focus {
567
- background-color: ${({ theme }) => theme.colors.neutral100};
568
- }
569
-
570
- > span {
571
- font-size: 0;
572
- }
573
- `;
574
- const InputRenderer = (props) => {
575
- switch (props.type) {
576
- case "color":
577
- return /* @__PURE__ */ jsxRuntime.jsx(ColorSelector, { ...props });
578
- case "permissions":
579
- return /* @__PURE__ */ jsxRuntime.jsx(PermissionsField, { ...props });
580
- default:
581
- return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.InputRenderer, { ...props });
582
- }
583
- };
584
- const ColorSelector = ({ disabled, label, name, required }) => {
585
- const { formatMessage } = reactIntl.useIntl();
586
- const { value, error, onChange } = strapiAdmin.useField(name);
587
- const colorOptions = index.AVAILABLE_COLORS.map(({ hex, name: name2 }) => ({
588
- value: hex,
589
- label: formatMessage(
590
- {
591
- id: "Settings.review-workflows.stage.color.name",
592
- defaultMessage: "{name}"
593
- },
594
- { name: name2 }
595
- ),
596
- color: hex
597
- }));
598
- const { themeColorName } = index.getStageColorByHex(value) ?? {};
599
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { error, name, required, children: [
600
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: label }),
601
- /* @__PURE__ */ jsxRuntime.jsx(
602
- designSystem.SingleSelect,
603
- {
604
- disabled,
605
- onChange: (v) => {
606
- onChange(name, v.toString());
607
- },
608
- value: value?.toUpperCase(),
609
- startIcon: /* @__PURE__ */ jsxRuntime.jsx(
610
- designSystem.Flex,
611
- {
612
- tag: "span",
613
- height: 2,
614
- background: value,
615
- borderColor: themeColorName === "neutral0" ? "neutral150" : "transparent",
616
- hasRadius: true,
617
- shrink: 0,
618
- width: 2
619
- }
620
- ),
621
- children: colorOptions.map(({ value: value2, label: label2, color }) => {
622
- const { themeColorName: themeColorName2 } = index.getStageColorByHex(color) || {};
623
- return /* @__PURE__ */ jsxRuntime.jsx(
624
- designSystem.SingleSelectOption,
625
- {
626
- value: value2,
627
- startIcon: /* @__PURE__ */ jsxRuntime.jsx(
628
- designSystem.Flex,
629
- {
630
- tag: "span",
631
- height: 2,
632
- background: color,
633
- borderColor: themeColorName2 === "neutral0" ? "neutral150" : "transparent",
634
- hasRadius: true,
635
- shrink: 0,
636
- width: 2
637
- }
638
- ),
639
- children: label2
640
- },
641
- value2
642
- );
643
- })
644
- }
645
- ),
646
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
647
- ] });
648
- };
649
- const PermissionsField = ({ disabled, name, placeholder, required }) => {
650
- const { formatMessage } = reactIntl.useIntl();
651
- const { toggleNotification } = strapiAdmin.useNotification();
652
- const [isApplyAllConfirmationOpen, setIsApplyAllConfirmationOpen] = React__namespace.useState(false);
653
- const { value = [], error, onChange } = strapiAdmin.useField(name);
654
- const allStages = strapiAdmin.useForm("PermissionsField", (state) => state.values.stages);
655
- const onFormValueChange = strapiAdmin.useForm("PermissionsField", (state) => state.onChange);
656
- const rolesErrorCount = React__namespace.useRef(0);
657
- const { data: roles = [], isLoading, error: getRolesError } = useGetAdminRolesQuery();
658
- const filteredRoles = roles?.filter((role) => role.code !== "strapi-super-admin") ?? [];
659
- React__namespace.useEffect(() => {
660
- if (!isLoading && getRolesError && "status" in getRolesError && getRolesError.status == 403 && rolesErrorCount.current === 0) {
661
- rolesErrorCount.current = 1;
662
- toggleNotification({
663
- blockTransition: true,
664
- type: "danger",
665
- message: formatMessage({
666
- id: "review-workflows.stage.permissions.noPermissions.description",
667
- defaultMessage: "You don’t have the permission to see roles. Contact your administrator."
668
- })
669
- });
670
- }
671
- }, [formatMessage, isLoading, roles, toggleNotification, getRolesError]);
672
- if (!isLoading && filteredRoles.length === 0) {
673
- return /* @__PURE__ */ jsxRuntime.jsxs(
674
- designSystem.Field.Root,
675
- {
676
- name,
677
- hint: formatMessage({
678
- id: "Settings.review-workflows.stage.permissions.noPermissions.description",
679
- defaultMessage: "You don’t have the permission to see roles"
680
- }),
681
- required,
682
- children: [
683
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
684
- id: "Settings.review-workflows.stage.permissions.label",
685
- defaultMessage: "Roles that can change this stage"
686
- }) }),
687
- /* @__PURE__ */ jsxRuntime.jsx(
688
- designSystem.TextInput,
689
- {
690
- disabled: true,
691
- placeholder: formatMessage({
692
- id: "components.NotAllowedInput.text",
693
- defaultMessage: "No permissions to see this field"
694
- }),
695
- startAction: /* @__PURE__ */ jsxRuntime.jsx(icons.EyeStriked, { fill: "neutral600" }),
696
- type: "text",
697
- value: ""
698
- }
699
- ),
700
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
701
- ]
702
- }
703
- );
704
- }
705
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-end", gap: 3, children: [
706
- /* @__PURE__ */ jsxRuntime.jsx(PermissionWrapper, { grow: 1, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { error, name, required: true, children: [
707
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
708
- id: "Settings.review-workflows.stage.permissions.label",
709
- defaultMessage: "Roles that can change this stage"
710
- }) }),
711
- /* @__PURE__ */ jsxRuntime.jsx(
712
- designSystem.MultiSelect,
713
- {
714
- disabled,
715
- onChange: (values) => {
716
- const permissions = values.map((value2) => ({
717
- role: parseInt(value2, 10),
718
- action: "admin::review-workflows.stage.transition"
719
- }));
720
- onChange(name, permissions);
721
- },
722
- placeholder,
723
- value: value.map((permission) => `${permission.role}`),
724
- withTags: true,
725
- children: /* @__PURE__ */ jsxRuntime.jsx(
726
- designSystem.MultiSelectGroup,
727
- {
728
- label: formatMessage({
729
- id: "Settings.review-workflows.stage.permissions.allRoles.label",
730
- defaultMessage: "All roles"
731
- }),
732
- values: filteredRoles.map((r) => `${r.id}`),
733
- children: filteredRoles.map((role) => {
734
- return /* @__PURE__ */ jsxRuntime.jsx(NestedOption$1, { value: `${role.id}`, children: role.name }, role.id);
735
- })
736
- }
737
- )
738
- }
739
- ),
740
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
741
- ] }) }),
742
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Root, { open: isApplyAllConfirmationOpen, onOpenChange: setIsApplyAllConfirmationOpen, children: [
743
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(
744
- designSystem.IconButton,
745
- {
746
- disabled,
747
- label: formatMessage({
748
- id: "Settings.review-workflows.stage.permissions.apply.label",
749
- defaultMessage: "Apply to all stages"
750
- }),
751
- size: "L",
752
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.Duplicate, {})
753
- }
754
- ) }),
755
- /* @__PURE__ */ jsxRuntime.jsx(
756
- strapiAdmin.ConfirmDialog,
757
- {
758
- onConfirm: () => {
759
- onFormValueChange(
760
- "stages",
761
- allStages.map((stage) => ({
762
- ...stage,
763
- permissions: value
764
- }))
765
- );
766
- setIsApplyAllConfirmationOpen(false);
767
- toggleNotification({
768
- type: "success",
769
- message: formatMessage({
770
- id: "Settings.review-workflows.page.edit.confirm.stages.permissions.copy.success",
771
- defaultMessage: "Applied roles to all other stages of the workflow"
772
- })
773
- });
774
- },
775
- variant: "default",
776
- children: formatMessage({
777
- id: "Settings.review-workflows.page.edit.confirm.stages.permissions.copy",
778
- defaultMessage: "Roles that can change that stage will be applied to all the other stages."
779
- })
780
- }
781
- )
782
- ] })
783
- ] }) });
784
- };
785
- const NestedOption$1 = styledComponents.styled(designSystem.MultiSelectOption)`
786
- padding-left: ${({ theme }) => theme.spaces[7]};
787
- `;
788
- const PermissionWrapper = styledComponents.styled(designSystem.Flex)`
789
- > * {
790
- flex-grow: 1;
791
- }
792
- `;
793
- const WorkflowAttributes = ({ canUpdate = true }) => {
794
- const { formatMessage } = reactIntl.useIntl();
795
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { background: "neutral0", hasRadius: true, gap: 4, padding: 6, shadow: "tableShadow", children: [
796
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, direction: "column", alignItems: "stretch", children: /* @__PURE__ */ jsxRuntime.jsx(
797
- strapiAdmin.InputRenderer,
798
- {
799
- disabled: !canUpdate,
800
- label: formatMessage({
801
- id: "Settings.review-workflows.workflow.name.label",
802
- defaultMessage: "Workflow Name"
803
- }),
804
- name: "name",
805
- required: true,
806
- type: "string"
807
- }
808
- ) }),
809
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, direction: "column", alignItems: "stretch", children: /* @__PURE__ */ jsxRuntime.jsx(ContentTypesSelector, { disabled: !canUpdate }) })
810
- ] });
811
- };
812
- const ContentTypesSelector = ({ disabled }) => {
813
- const { formatMessage, locale } = reactIntl.useIntl();
814
- const { data: contentTypes, isLoading } = index.useGetContentTypesQuery();
815
- const { workflows } = Layout.useReviewWorkflows();
816
- const currentWorkflow = strapiAdmin.useForm("ContentTypesSelector", (state) => state.values);
817
- const { error, value, onChange } = strapiAdmin.useField("contentTypes");
818
- const formatter = designSystem.useCollator(locale, {
819
- sensitivity: "base"
820
- });
821
- const isDisabled = disabled || isLoading || !contentTypes || contentTypes.collectionType.length === 0 && contentTypes.singleType.length === 0;
822
- const collectionTypes = (contentTypes?.collectionType ?? []).toSorted((a, b) => formatter.compare(a.info.displayName, b.info.displayName)).map((contentType) => ({
823
- label: contentType.info.displayName,
824
- value: contentType.uid
825
- }));
826
- const singleTypes = (contentTypes?.singleType ?? []).map((contentType) => ({
827
- label: contentType.info.displayName,
828
- value: contentType.uid
829
- }));
830
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { error, name: "contentTypes", children: [
831
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
832
- id: "Settings.review-workflows.workflow.contentTypes.label",
833
- defaultMessage: "Associated to"
834
- }) }),
835
- /* @__PURE__ */ jsxRuntime.jsx(
836
- designSystem.MultiSelect,
837
- {
838
- customizeContent: (value2) => formatMessage(
839
- {
840
- id: "Settings.review-workflows.workflow.contentTypes.displayValue",
841
- defaultMessage: "{count} {count, plural, one {content type} other {content types}} selected"
842
- },
843
- { count: value2?.length }
844
- ),
845
- disabled: isDisabled,
846
- onChange: (values) => {
847
- onChange("contentTypes", values);
848
- },
849
- value,
850
- placeholder: formatMessage({
851
- id: "Settings.review-workflows.workflow.contentTypes.placeholder",
852
- defaultMessage: "Select"
853
- }),
854
- children: [
855
- ...collectionTypes.length > 0 ? [
856
- {
857
- label: formatMessage({
858
- id: "Settings.review-workflows.workflow.contentTypes.collectionTypes.label",
859
- defaultMessage: "Collection Types"
860
- }),
861
- children: collectionTypes
862
- }
863
- ] : [],
864
- ...singleTypes.length > 0 ? [
865
- {
866
- label: formatMessage({
867
- id: "Settings.review-workflows.workflow.contentTypes.singleTypes.label",
868
- defaultMessage: "Single Types"
869
- }),
870
- children: singleTypes
871
- }
872
- ] : []
873
- ].map((opt) => {
874
- return /* @__PURE__ */ jsxRuntime.jsx(
875
- designSystem.MultiSelectGroup,
876
- {
877
- label: opt.label,
878
- values: opt.children.map((child) => child.value.toString()),
879
- children: opt.children.map((child) => {
880
- const { name: assignedWorkflowName } = workflows?.find(
881
- (workflow) => (currentWorkflow && workflow.id !== currentWorkflow.id || !currentWorkflow) && workflow.contentTypes.includes(child.value)
882
- ) ?? {};
883
- return /* @__PURE__ */ jsxRuntime.jsx(NestedOption, { value: child.value, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
884
- // @ts-expect-error - formatMessage options doesn't expect to be a React component but that's what we need actually for the <i> and <em> components
885
- children: formatMessage(
886
- {
887
- id: "Settings.review-workflows.workflow.contentTypes.assigned.notice",
888
- defaultMessage: "{label} {name, select, undefined {} other {<i>(assigned to <em>{name}</em> workflow)</i>}}"
889
- },
890
- {
891
- label: child.label,
892
- name: assignedWorkflowName,
893
- em: (...children) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "em", fontWeight: "bold", children }),
894
- i: (...children) => /* @__PURE__ */ jsxRuntime.jsx(ContentTypeTakeNotice, { children })
895
- }
896
- )
897
- }) }, child.value);
898
- })
899
- },
900
- opt.label
901
- );
902
- })
903
- }
904
- )
905
- ] });
906
- };
907
- const NestedOption = styledComponents.styled(designSystem.MultiSelectOption)`
908
- padding-left: ${({ theme }) => theme.spaces[7]};
909
- `;
910
- const ContentTypeTakeNotice = styledComponents.styled(designSystem.Typography)`
911
- font-style: italic;
912
- `;
913
- const WORKFLOW_SCHEMA = yup__namespace.object({
914
- contentTypes: yup__namespace.array().of(yup__namespace.string()),
915
- name: yup__namespace.string().max(255, {
916
- id: "review-workflows.validation.name.max-length",
917
- defaultMessage: "Name can not be longer than 255 characters"
918
- }).required().nullable(),
919
- stages: yup__namespace.array().of(
920
- yup__namespace.object().shape({
921
- name: yup__namespace.string().nullable().required({
922
- id: "review-workflows.validation.stage.name",
923
- defaultMessage: "Name is required"
924
- }).max(255, {
925
- id: "review-workflows.validation.stage.max-length",
926
- defaultMessage: "Name can not be longer than 255 characters"
927
- }).test(
928
- "unique-name",
929
- {
930
- id: "review-workflows.validation.stage.duplicate",
931
- defaultMessage: "Stage name must be unique"
932
- },
933
- (stageName, context) => {
934
- const { stages } = context.from[1].value;
935
- return stages.filter((stage) => stage.name === stageName).length === 1;
936
- }
937
- ),
938
- color: yup__namespace.string().nullable().required({
939
- id: "review-workflows.validation.stage.color",
940
- defaultMessage: "Color is required"
941
- }).matches(/^#(?:[0-9a-fA-F]{3}){1,2}$/i),
942
- permissions: yup__namespace.array(
943
- yup__namespace.object({
944
- role: yup__namespace.number().strict().typeError({
945
- id: "review-workflows.validation.stage.permissions.role.number",
946
- defaultMessage: "Role must be of type number"
947
- }).required(),
948
- action: yup__namespace.string().required({
949
- id: "review-workflows.validation.stage.permissions.action.required",
950
- defaultMessage: "Action is a required argument"
951
- })
952
- })
953
- ).strict()
954
- })
955
- ).min(1)
956
- });
957
- const EditPage = () => {
958
- const { id = "" } = reactRouterDom.useParams();
959
- const isCreatingWorkflow = id === "create";
960
- const { formatMessage } = reactIntl.useIntl();
961
- const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
962
- const navigate = reactRouterDom.useNavigate();
963
- const { toggleNotification } = strapiAdmin.useNotification();
964
- const {
965
- isLoading: isLoadingWorkflow,
966
- meta,
967
- workflows,
968
- error,
969
- update,
970
- create
971
- } = Layout.useReviewWorkflows();
972
- const permissions = index.useTypedSelector(
973
- (state) => state.admin_app.permissions["settings"]?.["review-workflows"]
974
- );
975
- const {
976
- allowedActions: { canDelete, canUpdate, canCreate }
977
- } = strapiAdmin.useRBAC(permissions);
978
- const [savePrompts, setSavePrompts] = React__namespace.useState({});
979
- const { getFeature, isLoading: isLicenseLoading } = ee.useLicenseLimits();
980
- const [showLimitModal, setShowLimitModal] = React__namespace.useState(null);
981
- const currentWorkflow = workflows?.find((workflow) => workflow.id === parseInt(id, 10));
982
- const contentTypesFromOtherWorkflows = workflows?.filter((workflow) => workflow.id !== parseInt(id, 10)).flatMap((workflow) => workflow.contentTypes);
983
- const limits = getFeature("review-workflows");
984
- const numberOfWorkflows = limits?.[index.CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME];
985
- const stagesPerWorkflow = limits?.[index.CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME];
986
- const submitForm = async (data, helpers) => {
987
- try {
988
- if (!isCreatingWorkflow) {
989
- const res = await update(id, {
990
- ...data,
991
- // compare permissions of stages and only submit them if at least one has
992
- // changed; this enables partial updates e.g. for users who don't have
993
- // permissions to see roles
994
- stages: data.stages.map((stage) => {
995
- let hasUpdatedPermissions = true;
996
- const serverStage = currentWorkflow?.stages?.find(
997
- (serverStage2) => serverStage2.id === stage?.id
998
- );
999
- if (serverStage) {
1000
- hasUpdatedPermissions = serverStage.permissions?.length !== stage.permissions?.length || !serverStage.permissions?.every(
1001
- (serverPermission) => !!stage.permissions?.find(
1002
- (permission) => permission.role === serverPermission.role
1003
- )
1004
- );
1005
- }
1006
- return {
1007
- ...stage,
1008
- permissions: hasUpdatedPermissions ? stage.permissions : void 0
1009
- };
1010
- })
1011
- });
1012
- if ("error" in res && index.isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1013
- helpers.setErrors(formatValidationErrors(res.error));
1014
- }
1015
- } else {
1016
- const res = await create(data);
1017
- if ("error" in res && index.isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1018
- helpers.setErrors(formatValidationErrors(res.error));
1019
- } else if ("data" in res) {
1020
- navigate(`../${res.data.id}`, { replace: true });
1021
- }
1022
- }
1023
- } catch (error2) {
1024
- toggleNotification({
1025
- type: "danger",
1026
- message: formatMessage({
1027
- id: "notification.error",
1028
- defaultMessage: "An error occurred"
1029
- })
1030
- });
1031
- }
1032
- setSavePrompts({});
1033
- };
1034
- const handleConfirmDeleteDialog = (data, helpers) => async () => {
1035
- await submitForm(data, helpers);
1036
- };
1037
- const handleConfirmClose = () => {
1038
- setSavePrompts({});
1039
- };
1040
- const handleSubmit = async (data, helpers) => {
1041
- const isContentTypeReassignment = data.contentTypes.some(
1042
- (contentType) => contentTypesFromOtherWorkflows?.includes(contentType)
1043
- );
1044
- const hasDeletedServerStages = !isCreatingWorkflow && !currentWorkflow?.stages.every(
1045
- (stage) => data.stages.some((newStage) => newStage.id === stage.id)
1046
- );
1047
- if (meta && numberOfWorkflows && meta?.workflowCount > parseInt(numberOfWorkflows, 10)) {
1048
- setShowLimitModal("workflow");
1049
- } else if (data.stages && stagesPerWorkflow && data.stages.length > parseInt(stagesPerWorkflow, 10)) {
1050
- setShowLimitModal("stage");
1051
- } else if (hasDeletedServerStages || isContentTypeReassignment) {
1052
- if (hasDeletedServerStages) {
1053
- setSavePrompts((prev) => ({ ...prev, hasDeletedServerStages: true }));
1054
- }
1055
- if (isContentTypeReassignment) {
1056
- setSavePrompts((prev) => ({ ...prev, hasReassignedContentTypes: true }));
1057
- }
1058
- } else {
1059
- await submitForm(data, helpers);
1060
- }
1061
- };
1062
- React__namespace.useEffect(() => {
1063
- if (!isLoadingWorkflow && !isLicenseLoading) {
1064
- if (meta && numberOfWorkflows && meta?.workflowCount > parseInt(numberOfWorkflows, 10)) {
1065
- setShowLimitModal("workflow");
1066
- } else if (currentWorkflow && currentWorkflow.stages && stagesPerWorkflow && currentWorkflow.stages.length > parseInt(stagesPerWorkflow, 10)) {
1067
- setShowLimitModal("stage");
1068
- }
1069
- }
1070
- }, [
1071
- currentWorkflow,
1072
- isLicenseLoading,
1073
- isLoadingWorkflow,
1074
- limits,
1075
- meta,
1076
- numberOfWorkflows,
1077
- stagesPerWorkflow
1078
- ]);
1079
- const initialValues = React__namespace.useMemo(() => {
1080
- if (isCreatingWorkflow || !currentWorkflow) {
1081
- return {
1082
- name: "",
1083
- stages: [],
1084
- contentTypes: []
1085
- };
1086
- } else {
1087
- return {
1088
- name: currentWorkflow.name,
1089
- stages: addTmpKeysToStages(currentWorkflow.stages),
1090
- contentTypes: currentWorkflow.contentTypes
1091
- };
1092
- }
1093
- }, [currentWorkflow, isCreatingWorkflow]);
1094
- if (isLoadingWorkflow) {
1095
- return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Page.Loading, {});
1096
- }
1097
- if (error) {
1098
- return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Page.Error, {});
1099
- }
1100
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1101
- /* @__PURE__ */ jsxRuntime.jsx(Layout.DragLayerRendered, {}),
1102
- /* @__PURE__ */ jsxRuntime.jsx(
1103
- strapiAdmin.Form,
1104
- {
1105
- method: isCreatingWorkflow ? "POST" : "PUT",
1106
- initialValues,
1107
- validationSchema: WORKFLOW_SCHEMA,
1108
- onSubmit: handleSubmit,
1109
- children: ({ modified, isSubmitting, values, setErrors }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1110
- /* @__PURE__ */ jsxRuntime.jsx(
1111
- Layout.Header,
1112
- {
1113
- navigationAction: /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
1114
- primaryAction: canUpdate || canCreate ? /* @__PURE__ */ jsxRuntime.jsx(
1115
- designSystem.Button,
1116
- {
1117
- startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}),
1118
- type: "submit",
1119
- disabled: !modified || isSubmitting || values.stages.length === 0,
1120
- loading: !Boolean(Object.keys(savePrompts).length > 0) && isSubmitting,
1121
- children: formatMessage({
1122
- id: "global.save",
1123
- defaultMessage: "Save"
1124
- })
1125
- }
1126
- ) : null,
1127
- subtitle: formatMessage(
1128
- {
1129
- id: "review-workflows.page.subtitle",
1130
- defaultMessage: "{count, plural, one {# stage} other {# stages}}"
1131
- },
1132
- { count: currentWorkflow?.stages?.length ?? 0 }
1133
- ),
1134
- title: currentWorkflow?.name || formatMessage({
1135
- id: "Settings.review-workflows.create.page.title",
1136
- defaultMessage: "Create Review Workflow"
1137
- })
1138
- }
1139
- ),
1140
- /* @__PURE__ */ jsxRuntime.jsx(Layout.Root, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "stretch", direction: "column", gap: 7, children: [
1141
- /* @__PURE__ */ jsxRuntime.jsx(WorkflowAttributes, { canUpdate: canUpdate || canCreate }),
1142
- /* @__PURE__ */ jsxRuntime.jsx(
1143
- Stages,
1144
- {
1145
- canDelete,
1146
- canUpdate: canUpdate || canCreate,
1147
- isCreating: isCreatingWorkflow
1148
- }
1149
- )
1150
- ] }) }),
1151
- /* @__PURE__ */ jsxRuntime.jsx(
1152
- designSystem.Dialog.Root,
1153
- {
1154
- open: Object.keys(savePrompts).length > 0,
1155
- onOpenChange: handleConfirmClose,
1156
- children: /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.ConfirmDialog, { onConfirm: handleConfirmDeleteDialog(values, { setErrors }), children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 5, children: [
1157
- savePrompts.hasDeletedServerStages && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textAlign: "center", variant: "omega", children: formatMessage({
1158
- id: "review-workflows.page.delete.confirm.stages.body",
1159
- defaultMessage: "All entries assigned to deleted stages will be moved to the previous stage."
1160
- }) }),
1161
- savePrompts.hasReassignedContentTypes && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textAlign: "center", variant: "omega", children: formatMessage(
1162
- {
1163
- id: "review-workflows.page.delete.confirm.contentType.body",
1164
- defaultMessage: "{count} {count, plural, one {content-type} other {content-types}} {count, plural, one {is} other {are}} already mapped to {count, plural, one {another workflow} other {other workflows}}. If you save changes, {count, plural, one {this} other {these}} {count, plural, one {content-type} other {{count} content-types}} will no more be mapped to the {count, plural, one {another workflow} other {other workflows}} and all corresponding information will be removed."
1165
- },
1166
- {
1167
- count: contentTypesFromOtherWorkflows?.filter(
1168
- (contentType) => values.contentTypes.includes(contentType)
1169
- ).length ?? 0
1170
- }
1171
- ) }),
1172
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textAlign: "center", variant: "omega", children: formatMessage({
1173
- id: "review-workflows.page.delete.confirm.confirm",
1174
- defaultMessage: "Are you sure you want to save?"
1175
- }) })
1176
- ] }) })
1177
- }
1178
- )
1179
- ] })
1180
- }
1181
- ),
1182
- /* @__PURE__ */ jsxRuntime.jsxs(
1183
- index.LimitsModal.Root,
1184
- {
1185
- open: showLimitModal === "workflow",
1186
- onOpenChange: () => setShowLimitModal(null),
1187
- children: [
1188
- /* @__PURE__ */ jsxRuntime.jsx(index.LimitsModal.Title, { children: formatMessage({
1189
- id: "review-workflows.edit.page.workflows.limit.title",
1190
- defaultMessage: "You’ve reached the limit of workflows in your plan"
1191
- }) }),
1192
- /* @__PURE__ */ jsxRuntime.jsx(index.LimitsModal.Body, { children: formatMessage({
1193
- id: "review-workflows.edit.page.workflows.limit.body",
1194
- defaultMessage: "Delete a workflow or contact Sales to enable more workflows."
1195
- }) })
1196
- ]
1197
- }
1198
- ),
1199
- /* @__PURE__ */ jsxRuntime.jsxs(
1200
- index.LimitsModal.Root,
1201
- {
1202
- open: showLimitModal === "stage",
1203
- onOpenChange: () => setShowLimitModal(null),
1204
- children: [
1205
- /* @__PURE__ */ jsxRuntime.jsx(index.LimitsModal.Title, { children: formatMessage({
1206
- id: "review-workflows.edit.page.stages.limit.title",
1207
- defaultMessage: "You have reached the limit of stages for this workflow in your plan"
1208
- }) }),
1209
- /* @__PURE__ */ jsxRuntime.jsx(index.LimitsModal.Body, { children: formatMessage({
1210
- id: "review-workflows.edit.page.stages.limit.body",
1211
- defaultMessage: "Try deleting some stages or contact Sales to enable more stages."
1212
- }) })
1213
- ]
1214
- }
1215
- )
1216
- ] });
1217
- };
1218
- const addTmpKeysToStages = (data) => {
1219
- const keys = fractionalIndexing.generateNKeysBetween(void 0, void 0, data.length);
1220
- return data.map((datum, index2) => ({
1221
- ...datum,
1222
- __temp_key__: keys[index2]
1223
- }));
1224
- };
1225
- const ProtectedEditPage = () => {
1226
- const permissions = index.useTypedSelector((state) => {
1227
- const {
1228
- create = [],
1229
- update = [],
1230
- read = []
1231
- } = state.admin_app.permissions.settings?.["review-workflows"] ?? {};
1232
- return [...create, ...update, ...read];
1233
- });
1234
- return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Page.Protect, { permissions, children: /* @__PURE__ */ jsxRuntime.jsx(EditPage, {}) });
1235
- };
1236
- exports.ProtectedEditPage = ProtectedEditPage;
1237
- //# sourceMappingURL=id-CmtaTf1x.js.map