@strapi/review-workflows 0.0.0-next.ea6e3b80ab37f554da4f8bde08dbfe9b57400d31 → 0.0.0-next.eb48c73c86cbc452c1ba8d727106f9ed9da0c834

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