@strapi/review-workflows 0.0.0-experimental.74c69aeafc770d59d5b3d5d37cd249934ef395ba → 0.0.0-experimental.a65a85fdea97faae8679d3ffc5f9d79af61abd26

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