@strapi/admin 4.12.0-beta.3 → 4.12.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +13 -35
  2. package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +304 -0
  3. package/admin/src/pages/AuthPage/components/Register/index.js +4 -0
  4. package/build/2379.0ca87a89.chunk.js +1 -0
  5. package/build/2395.df7a044a.chunk.js +26 -0
  6. package/build/2801.b1140c9b.chunk.js +1 -0
  7. package/build/{3100.21c343fa.chunk.js → 3100.2ba4df95.chunk.js} +1 -1
  8. package/build/{3483.ddd2d6df.chunk.js → 3483.e2ee2547.chunk.js} +1 -1
  9. package/build/3984.dda474f7.chunk.js +1 -0
  10. package/build/502.8ae8ef60.chunk.js +1 -0
  11. package/build/5483.6dd2e776.chunk.js +6 -0
  12. package/build/7065.ec811562.chunk.js +114 -0
  13. package/build/7464.8a6c1e6c.chunk.js +1 -0
  14. package/build/8276.6c7b8e6e.chunk.js +26 -0
  15. package/build/{9806.91360bb6.chunk.js → 9806.aa25371d.chunk.js} +10 -10
  16. package/build/{Admin-authenticatedApp.36b3826c.chunk.js → Admin-authenticatedApp.6b8dfa45.chunk.js} +1 -1
  17. package/build/{admin-app.1c3f7fd6.chunk.js → admin-app.c2e4e128.chunk.js} +8 -8
  18. package/build/content-manager.8772445b.chunk.js +1103 -0
  19. package/build/index.html +1 -1
  20. package/build/{main.a12c4c0f.js → main.af84ad9c.js} +281 -281
  21. package/build/review-workflows-settings-create-view.05758184.chunk.js +1 -0
  22. package/build/review-workflows-settings-edit-view.c33f7c58.chunk.js +1 -0
  23. package/build/review-workflows-settings-list-view.3ee9190d.chunk.js +56 -0
  24. package/build/{runtime~main.d197f488.js → runtime~main.a65ca6fb.js} +2 -2
  25. package/build/sso-settings-page.7c9b2fd9.chunk.js +1 -0
  26. package/ee/admin/constants.js +3 -0
  27. package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +12 -4
  28. package/ee/admin/hooks/index.js +1 -1
  29. package/ee/admin/hooks/useLicenseLimitNotification/index.js +1 -1
  30. package/ee/admin/hooks/useLicenseLimits/__mocks__/index.js +8 -0
  31. package/ee/admin/hooks/useLicenseLimits/index.js +1 -3
  32. package/ee/admin/hooks/useLicenseLimits/useLicenseLimits.js +3 -13
  33. package/ee/admin/pages/SettingsPage/pages/ApplicationInfosPage/components/AdminSeatInfo/index.js +19 -4
  34. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +7 -0
  35. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +20 -16
  36. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/WorkflowAttributes/WorkflowAttributes.js +120 -29
  37. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +3 -0
  38. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/CreateView/CreateView.js +108 -31
  39. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/CreateView/index.js +8 -3
  40. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/EditView/EditView.js +138 -61
  41. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/EditView/index.js +8 -3
  42. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/ListView/ListView.js +72 -55
  43. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/ListView/index.js +8 -3
  44. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +2 -8
  45. package/ee/admin/pages/SettingsPage/pages/SingleSignOn/index.js +2 -8
  46. package/ee/admin/pages/SettingsPage/pages/SingleSignOn/utils/schema.js +8 -5
  47. package/ee/server/services/review-workflows/review-workflows.js +1 -1
  48. package/ee/server/services/review-workflows/validation.js +6 -4
  49. package/ee/server/services/review-workflows/workflows/content-types.js +28 -19
  50. package/ee/server/services/review-workflows/workflows/index.js +14 -2
  51. package/ee/server/validation/authentication.js +20 -9
  52. package/package.json +9 -9
  53. package/build/2379.d33a2e16.chunk.js +0 -1
  54. package/build/2395.b0419a54.chunk.js +0 -26
  55. package/build/2801.18f38baf.chunk.js +0 -1
  56. package/build/3984.ea7b8036.chunk.js +0 -1
  57. package/build/502.ccb38223.chunk.js +0 -1
  58. package/build/5483.ed2c7efa.chunk.js +0 -6
  59. package/build/7464.c6d0565c.chunk.js +0 -1
  60. package/build/8276.23e0763b.chunk.js +0 -26
  61. package/build/8298.fd253c9f.chunk.js +0 -117
  62. package/build/content-manager.b8d593d4.chunk.js +0 -1103
  63. package/build/review-workflows-settings-create-view.dfd87e1f.chunk.js +0 -1
  64. package/build/review-workflows-settings-edit-view.53c00afe.chunk.js +0 -1
  65. package/build/review-workflows-settings-list-view.a34be805.chunk.js +0 -56
  66. package/build/sso-settings-page.ed6f3f15.chunk.js +0 -1
  67. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/ProtectedPage/ProtectedPage.js +0 -21
  68. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/ProtectedPage/index.js +0 -1
@@ -1,15 +1,37 @@
1
1
  import * as React from 'react';
2
2
 
3
- import { Grid, GridItem, MultiSelectNested, TextInput } from '@strapi/design-system';
3
+ import {
4
+ Grid,
5
+ GridItem,
6
+ MultiSelect,
7
+ MultiSelectGroup,
8
+ MultiSelectOption,
9
+ TextInput,
10
+ Typography,
11
+ } from '@strapi/design-system';
4
12
  import { useCollator } from '@strapi/helper-plugin';
5
13
  import { useField } from 'formik';
6
14
  import PropTypes from 'prop-types';
7
15
  import { useIntl } from 'react-intl';
8
16
  import { useDispatch } from 'react-redux';
17
+ import styled from 'styled-components';
9
18
 
10
19
  import { updateWorkflow } from '../../actions';
11
20
 
12
- export function WorkflowAttributes({ contentTypes: { collectionTypes, singleTypes } }) {
21
+ const NestedOption = styled(MultiSelectOption)`
22
+ padding-left: ${({ theme }) => theme.spaces[7]};
23
+ `;
24
+
25
+ const ContentTypeTakeNotice = styled(Typography)`
26
+ font-style: italic;
27
+ `;
28
+
29
+ export function WorkflowAttributes({
30
+ canUpdate,
31
+ contentTypes: { collectionTypes, singleTypes },
32
+ currentWorkflow,
33
+ workflows,
34
+ }) {
13
35
  const { formatMessage, locale } = useIntl();
14
36
  const dispatch = useDispatch();
15
37
  const [nameField, nameMeta, nameHelper] = useField('name');
@@ -24,6 +46,7 @@ export function WorkflowAttributes({ contentTypes: { collectionTypes, singleType
24
46
  <TextInput
25
47
  {...nameField}
26
48
  id={nameField.name}
49
+ disabled={!canUpdate}
27
50
  label={formatMessage({
28
51
  id: 'Settings.review-workflows.workflow.name.label',
29
52
  defaultMessage: 'Workflow Name',
@@ -38,7 +61,7 @@ export function WorkflowAttributes({ contentTypes: { collectionTypes, singleType
38
61
  </GridItem>
39
62
 
40
63
  <GridItem col={6}>
41
- <MultiSelectNested
64
+ <MultiSelect
42
65
  {...contentTypesField}
43
66
  customizeContent={(value) =>
44
67
  formatMessage(
@@ -50,6 +73,7 @@ export function WorkflowAttributes({ contentTypes: { collectionTypes, singleType
50
73
  { count: value.length }
51
74
  )
52
75
  }
76
+ disabled={!canUpdate}
53
77
  error={contentTypesMeta.error ?? false}
54
78
  id={contentTypesField.name}
55
79
  label={formatMessage({
@@ -60,36 +84,95 @@ export function WorkflowAttributes({ contentTypes: { collectionTypes, singleType
60
84
  dispatch(updateWorkflow({ contentTypes: values }));
61
85
  contentTypesHelper.setValue(values);
62
86
  }}
63
- options={[
64
- {
65
- label: formatMessage({
66
- id: 'Settings.review-workflows.workflow.contentTypes.collectionTypes.label',
67
- defaultMessage: 'Collection Types',
68
- }),
69
- children: collectionTypes
70
- .sort((a, b) => formatter.compare(a.info.displayName, b.info.displayName))
71
- .map((contentType) => ({
72
- label: contentType.info.displayName,
73
- value: contentType.uid,
74
- })),
75
- },
76
-
77
- {
78
- label: formatMessage({
79
- id: 'Settings.review-workflows.workflow.contentTypes.singleTypes.label',
80
- defaultMessage: 'Single Types',
81
- }),
82
- children: singleTypes.map((contentType) => ({
83
- label: contentType.info.displayName,
84
- value: contentType.uid,
85
- })),
86
- },
87
- ]}
88
87
  placeholder={formatMessage({
89
88
  id: 'Settings.review-workflows.workflow.contentTypes.placeholder',
90
89
  defaultMessage: 'Select',
91
90
  })}
92
- />
91
+ >
92
+ {[
93
+ ...(collectionTypes.length > 0
94
+ ? [
95
+ {
96
+ label: formatMessage({
97
+ id: 'Settings.review-workflows.workflow.contentTypes.collectionTypes.label',
98
+ defaultMessage: 'Collection Types',
99
+ }),
100
+ children: collectionTypes
101
+ .sort((a, b) => formatter.compare(a.info.displayName, b.info.displayName))
102
+ .map((contentType) => ({
103
+ label: contentType.info.displayName,
104
+ value: contentType.uid,
105
+ })),
106
+ },
107
+ ]
108
+ : []),
109
+
110
+ ...(singleTypes.length > 0
111
+ ? [
112
+ {
113
+ label: formatMessage({
114
+ id: 'Settings.review-workflows.workflow.contentTypes.singleTypes.label',
115
+ defaultMessage: 'Single Types',
116
+ }),
117
+ children: singleTypes.map((contentType) => ({
118
+ label: contentType.info.displayName,
119
+ value: contentType.uid,
120
+ })),
121
+ },
122
+ ]
123
+ : []),
124
+ ].map((opt) => {
125
+ if ('children' in opt) {
126
+ return (
127
+ <MultiSelectGroup
128
+ key={opt.label}
129
+ label={opt.label}
130
+ values={opt.children.map((child) => child.value.toString())}
131
+ >
132
+ {opt.children.map((child) => {
133
+ const { name: assignedWorkflowName } =
134
+ workflows.find(
135
+ (workflow) =>
136
+ ((currentWorkflow && workflow.id !== currentWorkflow.id) ||
137
+ !currentWorkflow) &&
138
+ workflow.contentTypes.includes(child.value)
139
+ ) ?? {};
140
+
141
+ return (
142
+ <NestedOption key={child.value} value={child.value}>
143
+ {formatMessage(
144
+ {
145
+ id: 'Settings.review-workflows.workflow.contentTypes.assigned.notice',
146
+ defaultMessage:
147
+ '{label} {name, select, undefined {} other {<i>(assigned to <em>{name}</em> workflow)</i>}}',
148
+ },
149
+ {
150
+ label: child.label,
151
+ name: assignedWorkflowName,
152
+ em: (...children) => (
153
+ <Typography as="em" fontWeight="bold">
154
+ {children}
155
+ </Typography>
156
+ ),
157
+ i: (...children) => (
158
+ <ContentTypeTakeNotice>{children}</ContentTypeTakeNotice>
159
+ ),
160
+ }
161
+ )}
162
+ </NestedOption>
163
+ );
164
+ })}
165
+ </MultiSelectGroup>
166
+ );
167
+ }
168
+
169
+ return (
170
+ <MultiSelectOption key={opt.value} value={opt.value}>
171
+ {opt.label}
172
+ </MultiSelectOption>
173
+ );
174
+ })}
175
+ </MultiSelect>
93
176
  </GridItem>
94
177
  </Grid>
95
178
  );
@@ -102,9 +185,17 @@ const ContentTypeType = PropTypes.shape({
102
185
  }).isRequired,
103
186
  });
104
187
 
188
+ WorkflowAttributes.defaultProps = {
189
+ canUpdate: true,
190
+ currentWorkflow: undefined,
191
+ };
192
+
105
193
  WorkflowAttributes.propTypes = {
194
+ canUpdate: PropTypes.bool,
106
195
  contentTypes: PropTypes.shape({
107
196
  collectionTypes: PropTypes.arrayOf(ContentTypeType).isRequired,
108
197
  singleTypes: PropTypes.arrayOf(ContentTypeType).isRequired,
109
198
  }).isRequired,
199
+ currentWorkflow: PropTypes.object,
200
+ workflows: PropTypes.array.isRequired,
110
201
  };
@@ -32,3 +32,6 @@ export const STAGE_COLOR_DEFAULT = lightTheme.colors.primary600;
32
32
  export const DRAG_DROP_TYPES = {
33
33
  STAGE: 'stage',
34
34
  };
35
+
36
+ export const CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME = 'numberOfWorkflows';
37
+ export const CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME = 'stagesPerWorkflow';
@@ -1,7 +1,13 @@
1
1
  import * as React from 'react';
2
2
 
3
- import { Button, Flex, Loader } from '@strapi/design-system';
4
- import { useAPIErrorHandler, useFetchClient, useNotification } from '@strapi/helper-plugin';
3
+ import { Button, Flex, Loader, Typography } from '@strapi/design-system';
4
+ import {
5
+ ConfirmDialog,
6
+ useAPIErrorHandler,
7
+ useFetchClient,
8
+ useNotification,
9
+ useRBAC,
10
+ } from '@strapi/helper-plugin';
5
11
  import { Check } from '@strapi/icons';
6
12
  import { useFormik, Form, FormikProvider } from 'formik';
7
13
  import set from 'lodash/set';
@@ -12,13 +18,18 @@ import { useHistory } from 'react-router-dom';
12
18
 
13
19
  import { useContentTypes } from '../../../../../../../../admin/src/hooks/useContentTypes';
14
20
  import { useInjectReducer } from '../../../../../../../../admin/src/hooks/useInjectReducer';
21
+ import { selectAdminPermissions } from '../../../../../../../../admin/src/pages/App/selectors';
15
22
  import { useLicenseLimits } from '../../../../../../hooks';
16
- import { resetWorkflow } from '../../actions';
23
+ import { addStage, resetWorkflow } from '../../actions';
17
24
  import * as Layout from '../../components/Layout';
18
25
  import * as LimitsModal from '../../components/LimitsModal';
19
26
  import { Stages } from '../../components/Stages';
20
27
  import { WorkflowAttributes } from '../../components/WorkflowAttributes';
21
- import { REDUX_NAMESPACE } from '../../constants';
28
+ import {
29
+ CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME,
30
+ CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME,
31
+ REDUX_NAMESPACE,
32
+ } from '../../constants';
22
33
  import { useReviewWorkflows } from '../../hooks/useReviewWorkflows';
23
34
  import { reducer, initialState } from '../../reducer';
24
35
  import { validateWorkflow } from '../../utils/validateWorkflow';
@@ -29,17 +40,25 @@ export function ReviewWorkflowsCreateView() {
29
40
  const { push } = useHistory();
30
41
  const { formatAPIError } = useAPIErrorHandler();
31
42
  const dispatch = useDispatch();
43
+ const permissions = useSelector(selectAdminPermissions);
32
44
  const toggleNotification = useNotification();
33
45
  const { collectionTypes, singleTypes, isLoading: isLoadingModels } = useContentTypes();
46
+ const { isLoading: isWorkflowLoading, meta, workflows } = useReviewWorkflows();
34
47
  const {
35
48
  clientState: {
36
49
  currentWorkflow: { data: currentWorkflow, isDirty: currentWorkflowIsDirty },
37
50
  },
38
51
  } = useSelector((state) => state?.[REDUX_NAMESPACE] ?? initialState);
52
+ const {
53
+ allowedActions: { canCreate },
54
+ } = useRBAC(permissions.settings['review-workflows']);
39
55
  const [showLimitModal, setShowLimitModal] = React.useState(false);
40
56
  const { isLoading: isLicenseLoading, getFeature } = useLicenseLimits();
41
- const { meta, isLoading: isWorkflowLoading } = useReviewWorkflows();
42
57
  const [initialErrors, setInitialErrors] = React.useState(null);
58
+ const [savePrompts, setSavePrompts] = React.useState({});
59
+
60
+ const limits = getFeature('review-workflows');
61
+ const contentTypesFromOtherWorkflows = workflows.flatMap((workflow) => workflow.contentTypes);
43
62
 
44
63
  const { mutateAsync, isLoading } = useMutation(
45
64
  async ({ workflow }) => {
@@ -65,6 +84,8 @@ export function ReviewWorkflowsCreateView() {
65
84
  );
66
85
 
67
86
  const submitForm = async () => {
87
+ setSavePrompts({});
88
+
68
89
  try {
69
90
  const workflow = await mutateAsync({ workflow: currentWorkflow });
70
91
 
@@ -72,20 +93,12 @@ export function ReviewWorkflowsCreateView() {
72
93
 
73
94
  return workflow;
74
95
  } catch (error) {
75
- // TODO: the current implementation of `formatAPIError` prints all error messages of all details,
76
- // which get's hairy when we have duplicated-name errors, because the same error message is printed
77
- // several times. What we want instead in these scenarios is to print only the error summary and
78
- // display the individual error messages for each field. This is a workaround, until we change the
79
- // implementation of `formatAPIError`.
96
+ // TODO: this would benefit from a utility to get a formik error
97
+ // representation from an API error
80
98
  if (
81
99
  error.response.data?.error?.name === 'ValidationError' &&
82
100
  error.response.data?.error?.details?.errors?.length > 0
83
101
  ) {
84
- toggleNotification({
85
- type: 'warning',
86
- message: error.response.data.error.message,
87
- });
88
-
89
102
  setInitialErrors(
90
103
  error.response.data?.error?.details?.errors.reduce((acc, error) => {
91
104
  set(acc, error.path, error.message);
@@ -93,31 +106,44 @@ export function ReviewWorkflowsCreateView() {
93
106
  return acc;
94
107
  }, {})
95
108
  );
96
- } else {
97
- toggleNotification({
98
- type: 'warning',
99
- message: formatAPIError(error),
100
- });
101
109
  }
102
110
 
111
+ toggleNotification({
112
+ type: 'warning',
113
+ message: formatAPIError(error),
114
+ });
115
+
103
116
  return null;
104
117
  }
105
118
  };
106
119
 
107
- const limits = getFeature('review-workflows');
120
+ const handleConfirmDeleteDialog = async () => {
121
+ await submitForm();
122
+ };
123
+
124
+ const handleConfirmClose = () => {
125
+ setSavePrompts({});
126
+ };
108
127
 
109
128
  const formik = useFormik({
110
129
  enableReinitialize: true,
111
130
  initialErrors,
112
131
  initialValues: currentWorkflow,
113
132
  async onSubmit() {
133
+ const isContentTypeReassignment = currentWorkflow.contentTypes.some((contentType) =>
134
+ contentTypesFromOtherWorkflows.includes(contentType)
135
+ );
136
+
114
137
  /**
115
138
  * If the current license has a limit, check if the total count of workflows
116
139
  * exceeds that limit and display the limits modal instead of sending the
117
140
  * update, because it would throw an API error.
118
141
  */
119
142
 
120
- if (limits?.workflows && meta?.workflowCount >= parseInt(limits.workflows, 10)) {
143
+ if (
144
+ limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
145
+ meta?.workflowCount >= parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
146
+ ) {
121
147
  setShowLimitModal('workflow');
122
148
 
123
149
  /**
@@ -126,10 +152,13 @@ export function ReviewWorkflowsCreateView() {
126
152
  * update, because it would throw an API error.
127
153
  */
128
154
  } else if (
129
- limits?.stagesPerWorkflow &&
130
- currentWorkflow.stages.length >= parseInt(limits.stagesPerWorkflow, 10)
155
+ limits?.[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME] &&
156
+ currentWorkflow.stages.length >=
157
+ parseInt(limits[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME], 10)
131
158
  ) {
132
159
  setShowLimitModal('stage');
160
+ } else if (isContentTypeReassignment) {
161
+ setSavePrompts((prev) => ({ ...prev, hasReassignedContentTypes: true }));
133
162
  } else {
134
163
  submitForm();
135
164
  }
@@ -143,6 +172,13 @@ export function ReviewWorkflowsCreateView() {
143
172
 
144
173
  React.useEffect(() => {
145
174
  dispatch(resetWorkflow());
175
+
176
+ // Create an empty default stage
177
+ dispatch(
178
+ addStage({
179
+ name: '',
180
+ })
181
+ );
146
182
  }, [dispatch]);
147
183
 
148
184
  /**
@@ -160,11 +196,15 @@ export function ReviewWorkflowsCreateView() {
160
196
 
161
197
  React.useEffect(() => {
162
198
  if (!isWorkflowLoading && !isLicenseLoading) {
163
- if (limits.workflows && meta?.workflowsTotal >= parseInt(limits.workflows, 10)) {
199
+ if (
200
+ limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
201
+ meta?.workflowsTotal >= parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
202
+ ) {
164
203
  setShowLimitModal('workflow');
165
204
  } else if (
166
- limits.stagesPerWorkflow &&
167
- currentWorkflow.stages.length >= parseInt(limits.stagesPerWorkflow, 10)
205
+ limits?.[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME] &&
206
+ currentWorkflow.stages.length >=
207
+ parseInt(limits[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME], 10)
168
208
  ) {
169
209
  setShowLimitModal('stage');
170
210
  }
@@ -172,8 +212,7 @@ export function ReviewWorkflowsCreateView() {
172
212
  }, [
173
213
  isLicenseLoading,
174
214
  isWorkflowLoading,
175
- limits.stagesPerWorkflow,
176
- limits?.workflows,
215
+ limits,
177
216
  meta?.workflowsTotal,
178
217
  currentWorkflow.stages.length,
179
218
  ]);
@@ -191,7 +230,7 @@ export function ReviewWorkflowsCreateView() {
191
230
  startIcon={<Check />}
192
231
  type="submit"
193
232
  size="M"
194
- disabled={!currentWorkflowIsDirty}
233
+ disabled={!currentWorkflowIsDirty || !canCreate}
195
234
  isLoading={isLoading}
196
235
  >
197
236
  {formatMessage({
@@ -223,7 +262,10 @@ export function ReviewWorkflowsCreateView() {
223
262
  </Loader>
224
263
  ) : (
225
264
  <Flex alignItems="stretch" direction="column" gap={7}>
226
- <WorkflowAttributes contentTypes={{ collectionTypes, singleTypes }} />
265
+ <WorkflowAttributes
266
+ contentTypes={{ collectionTypes, singleTypes }}
267
+ workflows={workflows}
268
+ />
227
269
  <Stages stages={formik.values?.stages} />
228
270
  </Flex>
229
271
  )}
@@ -232,6 +274,41 @@ export function ReviewWorkflowsCreateView() {
232
274
  </Form>
233
275
  </FormikProvider>
234
276
 
277
+ <ConfirmDialog.Root
278
+ isConfirmButtonLoading={isLoading}
279
+ isOpen={Object.keys(savePrompts).length > 0}
280
+ onToggleDialog={handleConfirmClose}
281
+ onConfirm={handleConfirmDeleteDialog}
282
+ >
283
+ <ConfirmDialog.Body>
284
+ <Flex direction="column" gap={5}>
285
+ {savePrompts.hasReassignedContentTypes && (
286
+ <Typography textAlign="center" variant="omega">
287
+ {formatMessage(
288
+ {
289
+ id: 'Settings.review-workflows.page.delete.confirm.contentType.body',
290
+ defaultMessage:
291
+ '{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.',
292
+ },
293
+ {
294
+ count: contentTypesFromOtherWorkflows.filter((contentType) =>
295
+ currentWorkflow.contentTypes.includes(contentType)
296
+ ).length,
297
+ }
298
+ )}
299
+ </Typography>
300
+ )}
301
+
302
+ <Typography textAlign="center" variant="omega">
303
+ {formatMessage({
304
+ id: 'Settings.review-workflows.page.delete.confirm.confirm',
305
+ defaultMessage: 'Are you sure you want to save?',
306
+ })}
307
+ </Typography>
308
+ </Flex>
309
+ </ConfirmDialog.Body>
310
+ </ConfirmDialog.Root>
311
+
235
312
  <LimitsModal.Root
236
313
  isOpen={showLimitModal === 'workflow'}
237
314
  onClose={() => setShowLimitModal(false)}
@@ -1,13 +1,18 @@
1
1
  import React from 'react';
2
2
 
3
- import { ProtectedPage } from '../../components/ProtectedPage';
3
+ import { CheckPagePermissions } from '@strapi/helper-plugin';
4
+ import { useSelector } from 'react-redux';
5
+
6
+ import { selectAdminPermissions } from '../../../../../../../../admin/src/pages/App/selectors';
4
7
 
5
8
  import { ReviewWorkflowsCreateView } from './CreateView';
6
9
 
7
10
  export default function () {
11
+ const permissions = useSelector(selectAdminPermissions);
12
+
8
13
  return (
9
- <ProtectedPage>
14
+ <CheckPagePermissions permissions={permissions.settings['review-workflows'].create}>
10
15
  <ReviewWorkflowsCreateView />
11
- </ProtectedPage>
16
+ </CheckPagePermissions>
12
17
  );
13
18
  }