@strapi/admin 4.9.0-exp.90df253ba90fd6879eb56a720a1f80d04ff745b8 → 4.10.0-beta.0

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 (167) hide show
  1. package/admin/src/content-manager/components/DynamicTable/CellContent/PublicationState/PublicationState.js +26 -0
  2. package/admin/src/content-manager/components/DynamicTable/CellContent/PublicationState/index.js +1 -0
  3. package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/ReviewWorkflowsStage.js +15 -0
  4. package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/index.js +1 -0
  5. package/admin/src/content-manager/components/DynamicTable/index.js +43 -49
  6. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +2 -0
  7. package/admin/src/content-manager/components/DynamicZone/utils/select.js +1 -1
  8. package/admin/src/content-manager/components/FieldComponent/utils/select.js +2 -1
  9. package/admin/src/content-manager/components/Inputs/utils/getInputType.js +1 -1
  10. package/admin/src/content-manager/components/Inputs/utils/select.js +1 -1
  11. package/admin/src/content-manager/hooks/useContentTypeLayout/index.js +1 -2
  12. package/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js +4 -1
  13. package/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.js +1 -2
  14. package/admin/src/content-manager/pages/EditSettingsView/init.js +3 -1
  15. package/admin/src/content-manager/pages/EditSettingsView/utils/createPossibleMainFieldsForModelsAndComponents.js +2 -4
  16. package/admin/src/content-manager/pages/EditView/DeleteLink/utils/select.js +1 -1
  17. package/admin/src/content-manager/pages/EditView/Information/index.js +77 -53
  18. package/admin/src/content-manager/pages/EditView/InformationBox/InformationBoxCE.js +13 -0
  19. package/admin/src/content-manager/pages/EditView/InformationBox/index.js +3 -0
  20. package/admin/src/content-manager/pages/EditView/index.js +3 -4
  21. package/admin/src/content-manager/pages/EditView/utils/createAttributesLayout.js +2 -1
  22. package/admin/src/content-manager/pages/EditView/utils/getFieldsActionMatchingPermissions.js +2 -1
  23. package/admin/src/content-manager/pages/ListView/index.js +6 -9
  24. package/admin/src/content-manager/utils/checkIfAttributeIsDisplayable.js +1 -1
  25. package/admin/src/content-manager/utils/createDefaultForm.js +2 -2
  26. package/admin/src/content-manager/utils/formatLayoutToApi.js +2 -1
  27. package/admin/src/content-manager/utils/getFieldName.js +1 -1
  28. package/admin/src/content-manager/utils/mergeMetasWithSchema.js +1 -1
  29. package/admin/src/content-manager/utils/paths.js +1 -1
  30. package/admin/src/content-manager/utils/removePasswordFieldsFromData.js +1 -1
  31. package/admin/src/hooks/useRegenerate/index.js +1 -1
  32. package/admin/src/hooks/useSettingsForm/index.js +3 -3
  33. package/admin/src/hooks/useSettingsForm/reducer.js +3 -1
  34. package/admin/src/hooks/useSettingsMenu/reducer.js +1 -1
  35. package/admin/src/index.js +1 -0
  36. package/admin/src/pages/AuthPage/reducer.js +1 -1
  37. package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +5 -7
  38. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +1 -1
  39. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/reducer.js +1 -1
  40. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/transformPermissionsData.js +6 -8
  41. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/utils/createDefaultConditionsForm.js +1 -1
  42. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/utils/generateCheckboxesActions.js +2 -1
  43. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/ActionRow/utils/getRowLabelCheckboxeState.js +2 -1
  44. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/GlobalActions/utils/getRowLabelCheckboxesState.js +1 -1
  45. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/Permissions/reducer.js +6 -1
  46. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/Permissions/utils/createDefaultCTFormFromLayout.js +5 -1
  47. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/Permissions/utils/createDefaultPluginsFormFromLayout.js +1 -2
  48. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/Permissions/utils/formatContentTypesPermissionToAPI.js +2 -2
  49. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/Permissions/utils/updateConditionsToFalse.js +4 -1
  50. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/Permissions/utils/updateValues.js +1 -1
  51. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PluginsAndSettings/SubCategory/utils/formatActions.js +1 -1
  52. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/utils/createArrayOfValues.js +2 -1
  53. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/index.js +1 -1
  54. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +0 -41
  55. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +4 -6
  56. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +0 -1
  57. package/admin/src/pages/SettingsPage/pages/Users/ProtectedEditPage/index.js +2 -2
  58. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/utils/formatData.js +1 -7
  59. package/admin/src/permissions/index.js +1 -1
  60. package/admin/src/translations/en.json +6 -0
  61. package/admin/src/utils/getAttributesToDisplay.js +2 -4
  62. package/admin/src/utils/getExistingActions.js +1 -3
  63. package/admin/src/utils/sortLinks.js +1 -1
  64. package/build/{8580.b0dcf37c.chunk.js → 2263.4c5916f9.chunk.js} +61 -61
  65. package/build/4649.213b8a3b.chunk.js +30 -0
  66. package/build/6985.66cca29c.chunk.js +1 -0
  67. package/build/7259.aefb51e8.chunk.js +1 -0
  68. package/build/{7112.2bf13da3.chunk.js → 9505.dbe702ab.chunk.js} +6 -6
  69. package/build/{Admin-authenticatedApp.5aa08bf5.chunk.js → Admin-authenticatedApp.f50ad423.chunk.js} +3 -3
  70. package/build/{Admin_marketplace.0f6c8ee2.chunk.js → Admin_marketplace.02608d56.chunk.js} +1 -1
  71. package/build/{Admin_profilePage.d2a8f9ab.chunk.js → Admin_profilePage.76afeca0.chunk.js} +1 -1
  72. package/build/Admin_settingsPage.147755cd.chunk.js +9 -0
  73. package/build/admin-app.55dd7921.chunk.js +112 -0
  74. package/build/admin-edit-roles-page.cf543488.chunk.js +216 -0
  75. package/build/admin-edit-users.31c20712.chunk.js +10 -0
  76. package/build/admin-roles-list.489c501f.chunk.js +2 -0
  77. package/build/{admin-users.af8c3123.chunk.js → admin-users.3e111a7d.chunk.js} +1 -1
  78. package/build/{api-tokens-create-page.2a6e22bd.chunk.js → api-tokens-create-page.4328b852.chunk.js} +1 -1
  79. package/build/{api-tokens-edit-page.fa38cd63.chunk.js → api-tokens-edit-page.bce5050f.chunk.js} +1 -1
  80. package/build/content-manager.4480ae88.chunk.js +1137 -0
  81. package/build/content-type-builder-translation-en-json.7961593e.chunk.js +1 -0
  82. package/build/content-type-builder.af9abf1e.chunk.js +126 -0
  83. package/build/en-json.697b4bcf.chunk.js +1 -0
  84. package/build/index.html +1 -1
  85. package/build/main.af8c0f31.js +3790 -0
  86. package/build/review-workflows-settings.7a7dc773.chunk.js +57 -0
  87. package/build/runtime~main.5a95bee6.js +2 -0
  88. package/build/sso-settings-page.272b87c8.chunk.js +1 -0
  89. package/build/{upload-settings.0200561d.chunk.js → upload-settings.0875e973.chunk.js} +1 -1
  90. package/build/upload-translation-fr-json.baab9911.chunk.js +1 -0
  91. package/build/users-advanced-settings-page.1d3c14c7.chunk.js +1 -0
  92. package/build/{users-email-settings-page.a3c80419.chunk.js → users-email-settings-page.e8db68c4.chunk.js} +1 -1
  93. package/build/users-providers-settings-page.14cac425.chunk.js +1 -0
  94. package/build/users-roles-settings-page.2ea4de84.chunk.js +30 -0
  95. package/build/{webhook-edit-page.a2a2b7bb.chunk.js → webhook-edit-page.329141a5.chunk.js} +3 -3
  96. package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +92 -0
  97. package/ee/admin/content-manager/pages/EditView/InformationBox/index.js +3 -0
  98. package/ee/admin/hooks/useSettingsMenu/utils/customAdminLinks.js +12 -12
  99. package/ee/admin/hooks/useSettingsMenu/utils/customGlobalLinks.js +21 -13
  100. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +195 -0
  101. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/actions/index.js +42 -0
  102. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/AddStage.js +87 -0
  103. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/index.js +1 -0
  104. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +90 -0
  105. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/index.js +1 -0
  106. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +92 -0
  107. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/index.js +1 -0
  108. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +6 -0
  109. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows.js +35 -0
  110. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/index.js +3 -0
  111. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +121 -0
  112. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js +25 -0
  113. package/ee/admin/pages/SettingsPage/utils/customRoutes.js +16 -2
  114. package/ee/admin/permissions/customPermissions.js +3 -0
  115. package/ee/server/bootstrap.js +16 -0
  116. package/ee/server/config/admin-actions.js +10 -0
  117. package/ee/server/constants/default-stages.json +14 -0
  118. package/ee/server/constants/default-workflow.json +1 -0
  119. package/ee/server/constants/workflows.js +8 -0
  120. package/ee/server/content-types/index.js +9 -0
  121. package/ee/server/content-types/workflow/index.js +34 -0
  122. package/ee/server/content-types/workflow-stage/index.js +41 -0
  123. package/ee/server/controllers/index.js +2 -0
  124. package/ee/server/controllers/workflows/index.js +36 -0
  125. package/ee/server/controllers/workflows/stages/index.js +95 -0
  126. package/ee/server/index.js +1 -0
  127. package/ee/server/middlewares/review-workflows.js +40 -0
  128. package/ee/server/migrations/review-workflows.js +39 -0
  129. package/ee/server/register.js +7 -0
  130. package/ee/server/routes/index.js +104 -0
  131. package/ee/server/services/index.js +4 -0
  132. package/ee/server/services/review-workflows/entity-service-decorator.js +42 -0
  133. package/ee/server/services/review-workflows/review-workflows.js +175 -0
  134. package/ee/server/services/review-workflows/stages.js +148 -0
  135. package/ee/server/services/review-workflows/workflows.js +25 -0
  136. package/ee/server/utils/index.js +8 -0
  137. package/ee/server/utils/persisted-tables.js +49 -0
  138. package/ee/server/utils/review-workflows.js +25 -0
  139. package/ee/server/utils/test.js +11 -0
  140. package/ee/server/validation/review-workflows.js +24 -0
  141. package/package.json +13 -13
  142. package/server/controllers/transfer/runner.js +2 -4
  143. package/server/routes/transfer.js +4 -13
  144. package/server/services/constants.js +0 -4
  145. package/server/services/permission/permissions-manager/sanitize.js +2 -0
  146. package/server/services/transfer/permission.js +1 -1
  147. package/server/services/transfer/token.js +31 -33
  148. package/server/validation/transfer/token.js +2 -10
  149. package/build/2637.679b590b.chunk.js +0 -1
  150. package/build/5563.451e91ee.chunk.js +0 -30
  151. package/build/7259.7744297b.chunk.js +0 -1
  152. package/build/Admin_settingsPage.489ec4eb.chunk.js +0 -9
  153. package/build/admin-app.4b313104.chunk.js +0 -112
  154. package/build/admin-edit-roles-page.3b196317.chunk.js +0 -216
  155. package/build/admin-edit-users.af3b0f15.chunk.js +0 -10
  156. package/build/admin-roles-list.0ad504a7.chunk.js +0 -2
  157. package/build/content-manager.f530e141.chunk.js +0 -1139
  158. package/build/content-type-builder-translation-en-json.e577d595.chunk.js +0 -1
  159. package/build/content-type-builder.6ecd201d.chunk.js +0 -126
  160. package/build/en-json.01a88a30.chunk.js +0 -1
  161. package/build/main.43b93ff3.js +0 -3843
  162. package/build/runtime~main.a40b1b57.js +0 -2
  163. package/build/sso-settings-page.5a8588ef.chunk.js +0 -1
  164. package/build/upload-translation-fr-json.84429734.chunk.js +0 -1
  165. package/build/users-advanced-settings-page.c0cae03a.chunk.js +0 -1
  166. package/build/users-providers-settings-page.5f86e45c.chunk.js +0 -1
  167. package/build/users-roles-settings-page.b02986df.chunk.js +0 -30
@@ -1,17 +1,17 @@
1
1
  import adminPermissions from '../../../../../admin/src/permissions';
2
2
 
3
- const auditLogsRoutes = strapi.features.isEnabled(strapi.features.AUDIT_LOGS)
4
- ? [
5
- {
6
- intlLabel: { id: 'global.auditLogs', defaultMessage: 'Audit Logs' },
7
- to: '/settings/audit-logs?pageSize=50&page=1&sort=date:DESC',
8
- id: 'auditLogs',
9
- isDisplayed: false,
10
- permissions: adminPermissions.settings.auditLogs.main,
11
- },
12
- ]
13
- : [];
3
+ const items = [];
14
4
 
15
- const customAdminLinks = [...auditLogsRoutes];
5
+ if (window.strapi.features.isEnabled(window.strapi.features.AUDIT_LOGS)) {
6
+ items.push({
7
+ intlLabel: { id: 'global.auditLogs', defaultMessage: 'Audit Logs' },
8
+ to: '/settings/audit-logs?pageSize=50&page=1&sort=date:DESC',
9
+ id: 'auditLogs',
10
+ isDisplayed: false,
11
+ permissions: adminPermissions.settings.auditLogs.main,
12
+ });
13
+ }
14
+
15
+ const customAdminLinks = items;
16
16
 
17
17
  export default customAdminLinks;
@@ -1,17 +1,25 @@
1
1
  import adminPermissions from '../../../../../admin/src/permissions';
2
2
 
3
- const ssoGlobalRoutes = strapi.features.isEnabled(strapi.features.SSO)
4
- ? [
5
- {
6
- intlLabel: { id: 'Settings.sso.title', defaultMessage: 'Single Sign-On' },
7
- to: '/settings/single-sign-on',
8
- id: 'sso',
9
- isDisplayed: false,
10
- permissions: adminPermissions.settings.sso.main,
11
- },
12
- ]
13
- : [];
3
+ const items = [];
14
4
 
15
- const customGlobalLinks = [...ssoGlobalRoutes];
5
+ if (window.strapi.features.isEnabled(window.strapi.features.SSO)) {
6
+ items.push({
7
+ intlLabel: { id: 'Settings.sso.title', defaultMessage: 'Single Sign-On' },
8
+ to: '/settings/single-sign-on',
9
+ id: 'sso',
10
+ isDisplayed: false,
11
+ permissions: adminPermissions.settings.sso.main,
12
+ });
13
+ }
16
14
 
17
- export default customGlobalLinks;
15
+ if (window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS)) {
16
+ items.push({
17
+ intlLabel: { id: 'Settings.review-workflows.page.title', defaultMessage: 'Review Workflows' },
18
+ to: '/settings/review-workflows',
19
+ id: 'review-workflows',
20
+ isDisplayed: false,
21
+ permissions: adminPermissions.settings['review-workflows'].main,
22
+ });
23
+ }
24
+
25
+ export default items;
@@ -0,0 +1,195 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { FormikProvider, useFormik, Form } from 'formik';
3
+ import { useIntl } from 'react-intl';
4
+ import { useSelector, useDispatch } from 'react-redux';
5
+ import { useMutation } from 'react-query';
6
+
7
+ import {
8
+ CheckPagePermissions,
9
+ ConfirmDialog,
10
+ SettingsPageTitle,
11
+ useAPIErrorHandler,
12
+ useFetchClient,
13
+ useNotification,
14
+ useTracking,
15
+ } from '@strapi/helper-plugin';
16
+ import { Button, ContentLayout, HeaderLayout, Layout, Loader, Main } from '@strapi/design-system';
17
+ import { Check } from '@strapi/icons';
18
+
19
+ import { Stages } from './components/Stages';
20
+ import { reducer, initialState } from './reducer';
21
+ import { REDUX_NAMESPACE } from './constants';
22
+ import { useInjectReducer } from '../../../../../../admin/src/hooks/useInjectReducer';
23
+ import { useReviewWorkflows } from './hooks/useReviewWorkflows';
24
+ import { setWorkflows } from './actions';
25
+ import { getWorkflowValidationSchema } from './utils/getWorkflowValidationSchema';
26
+ import adminPermissions from '../../../../../../admin/src/permissions';
27
+
28
+ export function ReviewWorkflowsPage() {
29
+ const { trackUsage } = useTracking();
30
+ const { formatMessage } = useIntl();
31
+ const dispatch = useDispatch();
32
+ const { put } = useFetchClient();
33
+ const { formatAPIError } = useAPIErrorHandler();
34
+ const toggleNotification = useNotification();
35
+ const { workflows: workflowsData, refetchWorkflow } = useReviewWorkflows();
36
+ const {
37
+ status,
38
+ clientState: {
39
+ currentWorkflow: {
40
+ data: currentWorkflow,
41
+ isDirty: currentWorkflowIsDirty,
42
+ hasDeletedServerStages: currentWorkflowHasDeletedServerStages,
43
+ },
44
+ },
45
+ } = useSelector((state) => state?.[REDUX_NAMESPACE] ?? initialState);
46
+ const [isConfirmDeleteDialogOpen, setIsConfirmDeleteDialogOpen] = useState(false);
47
+
48
+ const { mutateAsync, isLoading } = useMutation(
49
+ async ({ workflowId, stages }) => {
50
+ try {
51
+ const {
52
+ data: { data },
53
+ } = await put(`/admin/review-workflows/workflows/${workflowId}/stages`, {
54
+ data: stages,
55
+ });
56
+
57
+ return data;
58
+ } catch (error) {
59
+ toggleNotification({
60
+ type: 'warning',
61
+ message: formatAPIError(error),
62
+ });
63
+ }
64
+
65
+ return null;
66
+ },
67
+ {
68
+ onError(error) {
69
+ toggleNotification({
70
+ type: 'warning',
71
+ message: formatAPIError(error),
72
+ });
73
+ },
74
+
75
+ onSuccess() {
76
+ toggleNotification({
77
+ type: 'success',
78
+ message: { id: 'notification.success.saved', defaultMessage: 'Saved' },
79
+ });
80
+ },
81
+ }
82
+ );
83
+
84
+ const updateWorkflowStages = (workflowId, stages) => {
85
+ return mutateAsync({ workflowId, stages });
86
+ };
87
+
88
+ const submitForm = async () => {
89
+ setIsConfirmDeleteDialogOpen(false);
90
+
91
+ await updateWorkflowStages(currentWorkflow.id, currentWorkflow.stages);
92
+ refetchWorkflow();
93
+ };
94
+
95
+ const handleConfirmDeleteDialog = async () => {
96
+ await submitForm();
97
+ };
98
+
99
+ const toggleConfirmDeleteDialog = () => {
100
+ setIsConfirmDeleteDialogOpen((prev) => !prev);
101
+ };
102
+
103
+ const formik = useFormik({
104
+ enableReinitialize: true,
105
+ initialValues: currentWorkflow,
106
+ async onSubmit() {
107
+ if (currentWorkflowHasDeletedServerStages) {
108
+ setIsConfirmDeleteDialogOpen(true);
109
+ } else {
110
+ submitForm();
111
+ }
112
+ },
113
+ validationSchema: getWorkflowValidationSchema({ formatMessage }),
114
+ validateOnChange: false,
115
+ });
116
+
117
+ useInjectReducer(REDUX_NAMESPACE, reducer);
118
+
119
+ useEffect(() => {
120
+ dispatch(setWorkflows({ status: workflowsData.status, data: workflowsData.data }));
121
+ }, [workflowsData.status, workflowsData.data, dispatch]);
122
+
123
+ useEffect(() => {
124
+ trackUsage('didViewWorkflow');
125
+ }, [trackUsage]);
126
+
127
+ return (
128
+ <CheckPagePermissions permissions={adminPermissions.settings['review-workflows'].main}>
129
+ <Layout>
130
+ <SettingsPageTitle
131
+ name={formatMessage({
132
+ id: 'Settings.review-workflows.page.title',
133
+ defaultMessage: 'Review Workflows',
134
+ })}
135
+ />
136
+ <Main tabIndex={-1}>
137
+ <FormikProvider value={formik}>
138
+ <Form onSubmit={formik.handleSubmit}>
139
+ <HeaderLayout
140
+ primaryAction={
141
+ <Button
142
+ startIcon={<Check />}
143
+ type="submit"
144
+ size="M"
145
+ disabled={!currentWorkflowIsDirty}
146
+ >
147
+ {formatMessage({
148
+ id: 'global.save',
149
+ defaultMessage: 'Save',
150
+ })}
151
+ </Button>
152
+ }
153
+ title={formatMessage({
154
+ id: 'Settings.review-workflows.page.title',
155
+ defaultMessage: 'Review Workflows',
156
+ })}
157
+ subtitle={formatMessage(
158
+ {
159
+ id: 'Settings.review-workflows.page.subtitle',
160
+ defaultMessage: '{count, plural, one {# stage} other {# stages}}',
161
+ },
162
+ { count: currentWorkflow?.stages?.length ?? 0 }
163
+ )}
164
+ />
165
+ <ContentLayout>
166
+ {status === 'loading' && (
167
+ <Loader>
168
+ {formatMessage({
169
+ id: 'Settings.review-workflows.page.isLoading',
170
+ defaultMessage: 'Workflow is loading',
171
+ })}
172
+ </Loader>
173
+ )}
174
+
175
+ <Stages stages={formik.values?.stages} />
176
+ </ContentLayout>
177
+ </Form>
178
+ </FormikProvider>
179
+
180
+ <ConfirmDialog
181
+ bodyText={{
182
+ id: 'Settings.review-workflows.page.delete.confirm.body',
183
+ defaultMessage:
184
+ 'All entries assigned to deleted stages will be moved to the first stage. Are you sure you want to save this?',
185
+ }}
186
+ isConfirmButtonLoading={isLoading}
187
+ isOpen={isConfirmDeleteDialogOpen}
188
+ onToggleDialog={toggleConfirmDeleteDialog}
189
+ onConfirm={handleConfirmDeleteDialog}
190
+ />
191
+ </Main>
192
+ </Layout>
193
+ </CheckPagePermissions>
194
+ );
195
+ }
@@ -0,0 +1,42 @@
1
+ import {
2
+ ACTION_SET_WORKFLOWS,
3
+ ACTION_DELETE_STAGE,
4
+ ACTION_ADD_STAGE,
5
+ ACTION_UPDATE_STAGE,
6
+ } from '../constants';
7
+
8
+ export function setWorkflows({ status, data }) {
9
+ return {
10
+ type: ACTION_SET_WORKFLOWS,
11
+ payload: {
12
+ status,
13
+ workflows: data,
14
+ },
15
+ };
16
+ }
17
+
18
+ export function deleteStage(stageId) {
19
+ return {
20
+ type: ACTION_DELETE_STAGE,
21
+ payload: {
22
+ stageId,
23
+ },
24
+ };
25
+ }
26
+
27
+ export function addStage(stage = {}) {
28
+ return {
29
+ type: ACTION_ADD_STAGE,
30
+ payload: stage,
31
+ };
32
+ }
33
+
34
+ export function updateStage(stageId, payload) {
35
+ return {
36
+ type: ACTION_UPDATE_STAGE,
37
+ payload: {
38
+ stageId,
39
+ ...payload,
40
+ },
41
+ };
42
+ }
@@ -0,0 +1,87 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+
5
+ import { Box, Flex, Typography } from '@strapi/design-system';
6
+ import { PlusCircle } from '@strapi/icons';
7
+
8
+ const StyledAddIcon = styled(PlusCircle)`
9
+ > circle {
10
+ fill: ${({ theme }) => theme.colors.neutral150};
11
+ }
12
+ > path {
13
+ fill: ${({ theme }) => theme.colors.neutral600};
14
+ }
15
+ `;
16
+
17
+ const StyledButton = styled(Box)`
18
+ border-radius: 26px;
19
+
20
+ svg {
21
+ height: ${({ theme }) => theme.spaces[6]};
22
+ width: ${({ theme }) => theme.spaces[6]};
23
+
24
+ > path {
25
+ fill: ${({ theme }) => theme.colors.neutral600};
26
+ }
27
+ }
28
+
29
+ &:hover {
30
+ color: ${({ theme }) => theme.colors.primary600} !important;
31
+ ${Typography} {
32
+ color: ${({ theme }) => theme.colors.primary600} !important;
33
+ }
34
+
35
+ ${StyledAddIcon} {
36
+ > circle {
37
+ fill: ${({ theme }) => theme.colors.primary600};
38
+ }
39
+ > path {
40
+ fill: ${({ theme }) => theme.colors.neutral100};
41
+ }
42
+ }
43
+ }
44
+
45
+ &:active {
46
+ ${Typography} {
47
+ color: ${({ theme }) => theme.colors.primary600};
48
+ }
49
+
50
+ ${StyledAddIcon} {
51
+ > circle {
52
+ fill: ${({ theme }) => theme.colors.primary600};
53
+ }
54
+ > path {
55
+ fill: ${({ theme }) => theme.colors.neutral100};
56
+ }
57
+ }
58
+ }
59
+ `;
60
+
61
+ export function AddStage({ children, ...props }) {
62
+ return (
63
+ <StyledButton
64
+ as="button"
65
+ background="neutral0"
66
+ border="neutral150"
67
+ paddingBottom={3}
68
+ paddingLeft={4}
69
+ paddingRight={4}
70
+ paddingTop={3}
71
+ shadow="filterShadow"
72
+ {...props}
73
+ >
74
+ <Flex gap={2}>
75
+ <StyledAddIcon aria-hidden />
76
+
77
+ <Typography variant="pi" fontWeight="bold" textColor="neutral500">
78
+ {children}
79
+ </Typography>
80
+ </Flex>
81
+ </StyledButton>
82
+ );
83
+ }
84
+
85
+ AddStage.propTypes = {
86
+ children: PropTypes.node.isRequired,
87
+ };
@@ -0,0 +1,90 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useField } from 'formik';
4
+ import { useIntl } from 'react-intl';
5
+ import { useDispatch } from 'react-redux';
6
+ import {
7
+ Accordion,
8
+ AccordionToggle,
9
+ AccordionContent,
10
+ Grid,
11
+ GridItem,
12
+ IconButton,
13
+ TextInput,
14
+ } from '@strapi/design-system';
15
+ import { useTracking } from '@strapi/helper-plugin';
16
+ import { Trash } from '@strapi/icons';
17
+
18
+ import { deleteStage, updateStage } from '../../../actions';
19
+
20
+ function Stage({ id, name, index, canDelete, isOpen: isOpenDefault = false }) {
21
+ const { formatMessage } = useIntl();
22
+ const { trackUsage } = useTracking();
23
+ const [isOpen, setIsOpen] = useState(isOpenDefault);
24
+ const fieldIdentifier = `stages.${index}.name`;
25
+ const [field, meta] = useField(fieldIdentifier);
26
+ const dispatch = useDispatch();
27
+
28
+ return (
29
+ <Accordion
30
+ size="S"
31
+ variant="primary"
32
+ onToggle={() => {
33
+ setIsOpen(!isOpen);
34
+
35
+ if (!isOpen) {
36
+ trackUsage('willEditStage');
37
+ }
38
+ }}
39
+ expanded={isOpen}
40
+ shadow="tableShadow"
41
+ >
42
+ <AccordionToggle
43
+ title={name}
44
+ togglePosition="left"
45
+ action={
46
+ canDelete ? (
47
+ <IconButton
48
+ backgroundColor="transparent"
49
+ noBorder
50
+ onClick={() => dispatch(deleteStage(id))}
51
+ label={formatMessage({
52
+ id: 'Settings.review-workflows.stage.delete',
53
+ defaultMessage: 'Delete stage',
54
+ })}
55
+ icon={<Trash />}
56
+ />
57
+ ) : null
58
+ }
59
+ />
60
+ <AccordionContent padding={6} background="neutral0">
61
+ <Grid gap={4}>
62
+ <GridItem col={6}>
63
+ <TextInput
64
+ {...field}
65
+ id={fieldIdentifier}
66
+ value={name}
67
+ label={formatMessage({
68
+ id: 'Settings.review-workflows.stage.name.label',
69
+ defaultMessage: 'Stage name',
70
+ })}
71
+ error={meta.error ?? false}
72
+ onChange={(event) => {
73
+ field.onChange(event);
74
+ dispatch(updateStage(id, { name: event.target.value }));
75
+ }}
76
+ />
77
+ </GridItem>
78
+ </Grid>
79
+ </AccordionContent>
80
+ </Accordion>
81
+ );
82
+ }
83
+
84
+ export { Stage };
85
+
86
+ Stage.propTypes = PropTypes.shape({
87
+ id: PropTypes.number.isRequired,
88
+ name: PropTypes.string.isRequired,
89
+ canDelete: PropTypes.bool.isRequired,
90
+ }).isRequired;
@@ -0,0 +1,92 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+ import { useIntl } from 'react-intl';
5
+ import { useDispatch } from 'react-redux';
6
+ import { Box, Flex } from '@strapi/design-system';
7
+ import { useTracking } from '@strapi/helper-plugin';
8
+
9
+ import { addStage } from '../../actions';
10
+ import { AddStage } from '../AddStage';
11
+ import { Stage } from './Stage';
12
+
13
+ const StagesContainer = styled(Box)`
14
+ position: relative;
15
+ `;
16
+
17
+ const Background = styled(Box)`
18
+ left: 50%;
19
+ position: absolute;
20
+ top: 0;
21
+ transform: translateX(-50%);
22
+ `;
23
+
24
+ function Stages({ stages }) {
25
+ const { formatMessage } = useIntl();
26
+ const dispatch = useDispatch();
27
+ const { trackUsage } = useTracking();
28
+
29
+ return (
30
+ <Flex direction="column" gap={6} width="100%">
31
+ <StagesContainer spacing={4} width="100%">
32
+ <Background background="neutral200" height="100%" width={2} zIndex={1} />
33
+
34
+ <Flex
35
+ direction="column"
36
+ alignItems="stretch"
37
+ gap={6}
38
+ zIndex={2}
39
+ position="relative"
40
+ as="ol"
41
+ >
42
+ {stages.map((stage, index) => {
43
+ const id = stage?.id ?? stage.__temp_key__;
44
+
45
+ return (
46
+ <Box key={`stage-${id}`} as="li">
47
+ <Stage
48
+ {...stage}
49
+ id={id}
50
+ index={index}
51
+ canDelete={stages.length > 1}
52
+ isOpen={!stage.id}
53
+ />
54
+ </Box>
55
+ );
56
+ })}
57
+ </Flex>
58
+ </StagesContainer>
59
+
60
+ <Flex direction="column" gap={6}>
61
+ <AddStage
62
+ type="button"
63
+ onClick={() => {
64
+ dispatch(addStage({ name: '' }));
65
+ trackUsage('willCreateStage');
66
+ }}
67
+ >
68
+ {formatMessage({
69
+ id: 'Settings.review-workflows.stage.add',
70
+ defaultMessage: 'Add new stage',
71
+ })}
72
+ </AddStage>
73
+ </Flex>
74
+ </Flex>
75
+ );
76
+ }
77
+
78
+ export { Stages };
79
+
80
+ Stages.defaultProps = {
81
+ stages: [],
82
+ };
83
+
84
+ Stages.propTypes = {
85
+ stages: PropTypes.arrayOf(
86
+ PropTypes.shape({
87
+ id: PropTypes.number,
88
+ __temp_key__: PropTypes.number,
89
+ name: PropTypes.string.isRequired,
90
+ })
91
+ ),
92
+ };
@@ -0,0 +1,6 @@
1
+ export const REDUX_NAMESPACE = 'settings_review-workflows';
2
+
3
+ export const ACTION_SET_WORKFLOWS = `Settings/Review_Workflows/SET_WORKFLOWS`;
4
+ export const ACTION_DELETE_STAGE = `Settings/Review_Workflows/WORKFLOW_DELETE_STAGE`;
5
+ export const ACTION_ADD_STAGE = `Settings/Review_Workflows/WORKFLOW_ADD_STAGE`;
6
+ export const ACTION_UPDATE_STAGE = `Settings/Review_Workflows/WORKFLOW_UPDATE_STAGE`;
@@ -0,0 +1,35 @@
1
+ import { useQuery, useQueryClient } from 'react-query';
2
+ import { useFetchClient } from '@strapi/helper-plugin';
3
+
4
+ const QUERY_BASE_KEY = 'review-workflows';
5
+ const API_BASE_URL = '/admin/review-workflows';
6
+
7
+ export function useReviewWorkflows(workflowId) {
8
+ const { get } = useFetchClient();
9
+ const client = useQueryClient();
10
+ const workflowQueryKey = [QUERY_BASE_KEY, workflowId ?? 'default'];
11
+
12
+ async function fetchWorkflows({ params = { populate: 'stages' } }) {
13
+ try {
14
+ const {
15
+ data: { data },
16
+ } = await get(`${API_BASE_URL}/workflows/${workflowId ?? ''}`, { params });
17
+
18
+ return data;
19
+ } catch (err) {
20
+ // silence
21
+ return null;
22
+ }
23
+ }
24
+
25
+ function refetchWorkflow() {
26
+ client.refetchQueries(workflowQueryKey);
27
+ }
28
+
29
+ const workflows = useQuery(workflowQueryKey, fetchWorkflows);
30
+
31
+ return {
32
+ workflows,
33
+ refetchWorkflow,
34
+ };
35
+ }
@@ -0,0 +1,3 @@
1
+ import { ReviewWorkflowsPage } from './ReviewWorkflows';
2
+
3
+ export default ReviewWorkflowsPage;