@strapi/admin 4.9.0 → 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.
- package/admin/src/content-manager/components/DynamicTable/CellContent/PublicationState/PublicationState.js +26 -0
- package/admin/src/content-manager/components/DynamicTable/CellContent/PublicationState/index.js +1 -0
- package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/ReviewWorkflowsStage.js +15 -0
- package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/index.js +1 -0
- package/admin/src/content-manager/components/DynamicTable/index.js +43 -49
- package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +2 -0
- package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +1 -3
- package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findAllAndReplace.js +3 -10
- package/admin/src/content-manager/components/InputUID/endActionStyle.js +13 -4
- package/admin/src/content-manager/components/InputUID/index.js +71 -94
- package/admin/src/content-manager/pages/EditView/Information/index.js +77 -53
- package/admin/src/content-manager/pages/EditView/InformationBox/InformationBoxCE.js +13 -0
- package/admin/src/content-manager/pages/EditView/InformationBox/index.js +3 -0
- package/admin/src/content-manager/pages/EditView/index.js +3 -4
- package/admin/src/content-manager/pages/ListView/index.js +6 -9
- package/admin/src/hooks/useRegenerate/index.js +7 -12
- package/admin/src/index.js +1 -0
- package/admin/src/pages/AuthPage/components/Register/index.js +38 -46
- package/admin/src/pages/SettingsPage/components/Tokens/FormHead/index.js +0 -4
- package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +3 -5
- package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +5 -7
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +0 -41
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +9 -53
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +0 -1
- package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +5 -27
- package/admin/src/translations/en.json +6 -1
- package/build/2263.4c5916f9.chunk.js +98 -0
- package/build/4049.64715f20.chunk.js +1 -0
- package/build/4649.213b8a3b.chunk.js +30 -0
- package/build/6985.66cca29c.chunk.js +1 -0
- package/build/7259.aefb51e8.chunk.js +1 -0
- package/build/8469.853c822b.chunk.js +1 -0
- package/build/9505.dbe702ab.chunk.js +14 -0
- package/build/9816.01ee964f.chunk.js +2 -0
- package/build/Admin-authenticatedApp.f50ad423.chunk.js +79 -0
- package/build/Admin_InternalErrorPage.4ad8b0df.chunk.js +1 -0
- package/build/Admin_homePage.1411fb7c.chunk.js +68 -0
- package/build/Admin_marketplace.02608d56.chunk.js +22 -0
- package/build/Admin_pluginsPage.15e3b0fd.chunk.js +1 -0
- package/build/Admin_profilePage.76afeca0.chunk.js +15 -0
- package/build/Admin_settingsPage.147755cd.chunk.js +9 -0
- package/build/Upload_ConfigureTheView.34dde278.chunk.js +1 -0
- package/build/admin-app.55dd7921.chunk.js +112 -0
- package/build/admin-edit-roles-page.cf543488.chunk.js +216 -0
- package/build/admin-edit-users.31c20712.chunk.js +10 -0
- package/build/admin-roles-list.489c501f.chunk.js +2 -0
- package/build/admin-users.3e111a7d.chunk.js +11 -0
- package/build/api-tokens-create-page.4328b852.chunk.js +1 -0
- package/build/api-tokens-edit-page.bce5050f.chunk.js +1 -0
- package/build/api-tokens-list-page.93f24348.chunk.js +16 -0
- package/build/audit-logs-settings-page.7be97e82.chunk.js +1 -0
- package/build/content-manager.4480ae88.chunk.js +1137 -0
- package/build/content-type-builder-list-view.cf38fe2f.chunk.js +191 -0
- package/build/content-type-builder-translation-en-json.7961593e.chunk.js +1 -0
- package/build/content-type-builder.af9abf1e.chunk.js +126 -0
- package/build/email-settings-page.4bdbef9a.chunk.js +3 -0
- package/build/en-json.697b4bcf.chunk.js +1 -0
- package/build/{highlight.js.28a1547e.chunk.js → highlight.js.26ef649f.chunk.js} +2 -2
- package/build/i18n-settings-page.2bb5be96.chunk.js +1 -0
- package/build/index.html +1 -1
- package/build/main.af8c0f31.js +3790 -0
- package/build/review-workflows-settings.7a7dc773.chunk.js +57 -0
- package/build/runtime~main.5a95bee6.js +2 -0
- package/build/sso-settings-page.272b87c8.chunk.js +1 -0
- package/build/transfer-tokens-create-page.a1f14bb1.chunk.js +1 -0
- package/build/transfer-tokens-edit-page.00ee1c74.chunk.js +1 -0
- package/build/transfer-tokens-list-page.ce37354b.chunk.js +16 -0
- package/build/upload-settings.0875e973.chunk.js +1 -0
- package/build/{upload-translation-th-json.98d35574.chunk.js → upload-translation-th-json.3847dae0.chunk.js} +1 -1
- package/build/upload.c7da1611.chunk.js +13 -0
- package/build/users-advanced-settings-page.1d3c14c7.chunk.js +1 -0
- package/build/users-email-settings-page.e8db68c4.chunk.js +1 -0
- package/build/users-providers-settings-page.14cac425.chunk.js +1 -0
- package/build/users-roles-settings-page.2ea4de84.chunk.js +30 -0
- package/build/webhook-edit-page.329141a5.chunk.js +23 -0
- package/build/webhook-list-page.029957a4.chunk.js +1 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +92 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/index.js +3 -0
- package/ee/admin/hooks/useSettingsMenu/utils/customAdminLinks.js +12 -12
- package/ee/admin/hooks/useSettingsMenu/utils/customGlobalLinks.js +21 -13
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +195 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/actions/index.js +42 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/AddStage.js +87 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/index.js +1 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +90 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/index.js +1 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +92 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/index.js +1 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +6 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows.js +35 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/index.js +3 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +121 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js +25 -0
- package/ee/admin/pages/SettingsPage/utils/customRoutes.js +16 -2
- package/ee/admin/permissions/customPermissions.js +3 -0
- package/ee/server/bootstrap.js +13 -0
- package/ee/server/config/admin-actions.js +10 -0
- package/ee/server/constants/default-stages.json +14 -0
- package/ee/server/constants/default-workflow.json +1 -0
- package/ee/server/constants/workflows.js +8 -0
- package/ee/server/content-types/index.js +9 -0
- package/ee/server/content-types/workflow/index.js +34 -0
- package/ee/server/content-types/workflow-stage/index.js +41 -0
- package/ee/server/controllers/index.js +2 -0
- package/ee/server/controllers/workflows/index.js +36 -0
- package/ee/server/controllers/workflows/stages/index.js +95 -0
- package/ee/server/index.js +1 -0
- package/ee/server/middlewares/review-workflows.js +40 -0
- package/ee/server/migrations/review-workflows.js +39 -0
- package/ee/server/register.js +9 -3
- package/ee/server/routes/index.js +104 -0
- package/ee/server/services/audit-logs.js +16 -75
- package/ee/server/services/index.js +4 -0
- package/ee/server/services/review-workflows/entity-service-decorator.js +42 -0
- package/ee/server/services/review-workflows/review-workflows.js +175 -0
- package/ee/server/services/review-workflows/stages.js +148 -0
- package/ee/server/services/review-workflows/workflows.js +25 -0
- package/ee/server/utils/index.js +8 -0
- package/ee/server/utils/review-workflows.js +25 -0
- package/ee/server/utils/test.js +11 -0
- package/ee/server/validation/review-workflows.js +24 -0
- package/jest.config.front.js +6 -1
- package/package.json +15 -17
- package/server/controllers/transfer/runner.js +2 -4
- package/server/middlewares/data-transfer.js +1 -4
- package/server/routes/transfer.js +4 -13
- package/server/services/constants.js +0 -4
- package/server/services/transfer/permission.js +1 -1
- package/server/services/transfer/token.js +31 -33
- package/server/validation/transfer/token.js +2 -10
- package/webpack.config.js +1 -1
- package/.eslintignore +0 -4
- package/.eslintrc.js +0 -14
- package/admin/src/components/LocalesProvider/__mocks__/useLocalesProvider.js +0 -7
- package/admin/src/hooks/useConfigurations/__mocks__/index.js +0 -7
- package/build/1387.84b454d3.chunk.js +0 -1
- package/build/1657.45231968.chunk.js +0 -168
- package/build/3081.bcf9a12f.chunk.js +0 -108
- package/build/462.8fff7f3b.chunk.js +0 -71
- package/build/4628.20631dd1.chunk.js +0 -1
- package/build/5542.b8240e3f.chunk.js +0 -70
- package/build/5563.905daa13.chunk.js +0 -79
- package/build/6404.68405699.chunk.js +0 -100
- package/build/7259.b7d00cea.chunk.js +0 -1
- package/build/8694.6522968d.chunk.js +0 -247
- package/build/9347.058ddb22.chunk.js +0 -1
- package/build/Admin-authenticatedApp.31bf88ef.chunk.js +0 -79
- package/build/Admin_InternalErrorPage.15c6bf07.chunk.js +0 -1
- package/build/Admin_homePage.da2181fe.chunk.js +0 -73
- package/build/Admin_marketplace.d99044eb.chunk.js +0 -31
- package/build/Admin_pluginsPage.f6b52ee9.chunk.js +0 -6
- package/build/Admin_profilePage.9112cffc.chunk.js +0 -15
- package/build/Admin_settingsPage.cb63220f.chunk.js +0 -79
- package/build/Upload_ConfigureTheView.eaaec495.chunk.js +0 -1
- package/build/admin-app.8cde5b22.chunk.js +0 -110
- package/build/admin-edit-roles-page.4f1858e9.chunk.js +0 -280
- package/build/admin-edit-users.7e14d85f.chunk.js +0 -10
- package/build/admin-roles-list.97e198f9.chunk.js +0 -31
- package/build/admin-users.d02de059.chunk.js +0 -34
- package/build/api-tokens-create-page.97595e12.chunk.js +0 -1
- package/build/api-tokens-edit-page.cd36e30e.chunk.js +0 -1
- package/build/api-tokens-list-page.6757c7b9.chunk.js +0 -16
- package/build/audit-logs-settings-page.ca9a3c46.chunk.js +0 -76
- package/build/content-manager.de0ee3e5.chunk.js +0 -1132
- package/build/content-type-builder-list-view.9c2c020c.chunk.js +0 -214
- package/build/content-type-builder-translation-en-json.e577d595.chunk.js +0 -1
- package/build/content-type-builder.ec5ac7ab.chunk.js +0 -126
- package/build/email-settings-page.1095e1ab.chunk.js +0 -10
- package/build/en-json.b052667a.chunk.js +0 -1
- package/build/i18n-settings-page.7d80aae0.chunk.js +0 -60
- package/build/main.d40f9ca1.js +0 -2280
- package/build/runtime~main.7cdc9956.js +0 -2
- package/build/sso-settings-page.1dd4886e.chunk.js +0 -1
- package/build/transfer-tokens-create-page.ec2ca215.chunk.js +0 -1
- package/build/transfer-tokens-edit-page.22bf28e5.chunk.js +0 -1
- package/build/transfer-tokens-list-page.cf8c77f2.chunk.js +0 -16
- package/build/upload-settings.945fdcfa.chunk.js +0 -13
- package/build/upload.a86b1054.chunk.js +0 -33
- package/build/users-advanced-settings-page.5b5a9baa.chunk.js +0 -8
- package/build/users-email-settings-page.e5506eb4.chunk.js +0 -23
- package/build/users-providers-settings-page.e32089c2.chunk.js +0 -28
- package/build/users-roles-settings-page.a5c5b0df.chunk.js +0 -30
- package/build/webhook-edit-page.213f0075.chunk.js +0 -75
- package/build/webhook-list-page.5beb2a5c.chunk.js +0 -71
|
@@ -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,121 @@
|
|
|
1
|
+
import { current, produce } from 'immer';
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
ACTION_SET_WORKFLOWS,
|
|
6
|
+
ACTION_DELETE_STAGE,
|
|
7
|
+
ACTION_ADD_STAGE,
|
|
8
|
+
ACTION_UPDATE_STAGE,
|
|
9
|
+
} from '../constants';
|
|
10
|
+
|
|
11
|
+
export const initialState = {
|
|
12
|
+
status: 'loading',
|
|
13
|
+
serverState: {
|
|
14
|
+
currentWorkflow: null,
|
|
15
|
+
workflows: [],
|
|
16
|
+
},
|
|
17
|
+
clientState: {
|
|
18
|
+
currentWorkflow: { data: null, isDirty: false, hasDeletedServerStages: false },
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function reducer(state = initialState, action) {
|
|
23
|
+
return produce(state, (draft) => {
|
|
24
|
+
const { payload } = action;
|
|
25
|
+
|
|
26
|
+
switch (action.type) {
|
|
27
|
+
case ACTION_SET_WORKFLOWS: {
|
|
28
|
+
const { status, workflows } = payload;
|
|
29
|
+
|
|
30
|
+
draft.status = status;
|
|
31
|
+
|
|
32
|
+
if (workflows) {
|
|
33
|
+
const defaultWorkflow = workflows[0];
|
|
34
|
+
|
|
35
|
+
draft.serverState.workflows = workflows;
|
|
36
|
+
draft.serverState.currentWorkflow = defaultWorkflow;
|
|
37
|
+
draft.clientState.currentWorkflow.data = defaultWorkflow;
|
|
38
|
+
}
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
case ACTION_DELETE_STAGE: {
|
|
43
|
+
const { stageId } = payload;
|
|
44
|
+
const { currentWorkflow } = state.clientState;
|
|
45
|
+
|
|
46
|
+
draft.clientState.currentWorkflow.data.stages = currentWorkflow.data.stages.filter(
|
|
47
|
+
(stage) => (stage?.id ?? stage.__temp_key__) !== stageId
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (!currentWorkflow.hasDeletedServerStages) {
|
|
51
|
+
draft.clientState.currentWorkflow.hasDeletedServerStages =
|
|
52
|
+
!!state.serverState.currentWorkflow.stages.find((stage) => stage.id === stageId);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
case ACTION_ADD_STAGE: {
|
|
59
|
+
const { currentWorkflow } = state.clientState;
|
|
60
|
+
|
|
61
|
+
if (!currentWorkflow.data) {
|
|
62
|
+
draft.clientState.currentWorkflow.data = {
|
|
63
|
+
stages: [],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const newTempKey = getMaxTempKey(draft.clientState.currentWorkflow.data.stages);
|
|
68
|
+
|
|
69
|
+
draft.clientState.currentWorkflow.data.stages.push({
|
|
70
|
+
...payload,
|
|
71
|
+
__temp_key__: newTempKey,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
case ACTION_UPDATE_STAGE: {
|
|
78
|
+
const { currentWorkflow } = state.clientState;
|
|
79
|
+
const { stageId, ...modified } = payload;
|
|
80
|
+
|
|
81
|
+
draft.clientState.currentWorkflow.data.stages = currentWorkflow.data.stages.map((stage) =>
|
|
82
|
+
(stage.id ?? stage.__temp_key__) === stageId
|
|
83
|
+
? {
|
|
84
|
+
...stage,
|
|
85
|
+
...modified,
|
|
86
|
+
}
|
|
87
|
+
: stage
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
default:
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (state.clientState.currentWorkflow.data) {
|
|
98
|
+
draft.clientState.currentWorkflow.isDirty = !isEqual(
|
|
99
|
+
current(draft.clientState.currentWorkflow).data,
|
|
100
|
+
state.serverState.currentWorkflow
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @type {(stages: Array<{id?: number; __temp_key__: number}>) => number}
|
|
108
|
+
*/
|
|
109
|
+
const getMaxTempKey = (stages = []) => {
|
|
110
|
+
/**
|
|
111
|
+
* We check if there are ids or __temp_key__ because you may add a stage to a list of stages
|
|
112
|
+
* already in the DB, alternatively you might add multiple new stages at once.
|
|
113
|
+
*/
|
|
114
|
+
const ids = stages.map((stage) => stage.id ?? stage.__temp_key__);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* If there are no ids it will return 0 as the max value
|
|
118
|
+
* because the max value is -1.
|
|
119
|
+
*/
|
|
120
|
+
return Math.max(...ids, -1) + 1;
|
|
121
|
+
};
|
package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as yup from 'yup';
|
|
2
|
+
|
|
3
|
+
export function getWorkflowValidationSchema({ formatMessage }) {
|
|
4
|
+
return yup.object({
|
|
5
|
+
stages: yup.array().of(
|
|
6
|
+
yup.object().shape({
|
|
7
|
+
name: yup
|
|
8
|
+
.string()
|
|
9
|
+
.required(
|
|
10
|
+
formatMessage({
|
|
11
|
+
id: 'Settings.review-workflows.validation.stage.name',
|
|
12
|
+
defaultMessage: 'Name is required',
|
|
13
|
+
})
|
|
14
|
+
)
|
|
15
|
+
.max(
|
|
16
|
+
255,
|
|
17
|
+
formatMessage({
|
|
18
|
+
id: 'Settings.review-workflows.validation.stage.max-length',
|
|
19
|
+
defaultMessage: 'Name can not be longer than 255 characters',
|
|
20
|
+
})
|
|
21
|
+
),
|
|
22
|
+
})
|
|
23
|
+
),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const routes = [];
|
|
2
2
|
|
|
3
|
-
if (strapi.features.isEnabled(strapi.features.SSO)) {
|
|
3
|
+
if (window.strapi.features.isEnabled(window.strapi.features.SSO)) {
|
|
4
4
|
routes.push({
|
|
5
5
|
async Component() {
|
|
6
6
|
const component = await import(
|
|
@@ -14,7 +14,21 @@ if (strapi.features.isEnabled(strapi.features.SSO)) {
|
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
if (strapi.features.isEnabled(strapi.features.
|
|
17
|
+
if (window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS)) {
|
|
18
|
+
routes.push({
|
|
19
|
+
async Component() {
|
|
20
|
+
const component = await import(
|
|
21
|
+
/* webpackChunkName: "review-workflows-settings" */ '../pages/ReviewWorkflows'
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return component;
|
|
25
|
+
},
|
|
26
|
+
to: '/settings/review-workflows',
|
|
27
|
+
exact: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (window.strapi.features.isEnabled(window.strapi.features.AUDIT_LOGS)) {
|
|
18
32
|
routes.push({
|
|
19
33
|
async Component() {
|
|
20
34
|
const component = await import(
|
|
@@ -4,6 +4,9 @@ const customPermissions = {
|
|
|
4
4
|
main: [{ action: 'admin::audit-logs.read', subject: null }],
|
|
5
5
|
read: [{ action: 'admin::audit-logs.read', subject: null }],
|
|
6
6
|
},
|
|
7
|
+
'review-workflows': {
|
|
8
|
+
main: [{ action: 'admin::review-workflows.read', subject: null }],
|
|
9
|
+
},
|
|
7
10
|
sso: {
|
|
8
11
|
main: [{ action: 'admin::provider-login.read', subject: null }],
|
|
9
12
|
read: [{ action: 'admin::provider-login.read', subject: null }],
|
package/ee/server/bootstrap.js
CHANGED
|
@@ -20,6 +20,19 @@ module.exports = async () => {
|
|
|
20
20
|
await actionProvider.registerMany(actions.auditLogs);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
if (features.isEnabled('review-workflows')) {
|
|
24
|
+
await persistTablesWithPrefix('strapi_workflows');
|
|
25
|
+
|
|
26
|
+
const { bootstrap: rwBootstrap } = getService('review-workflows');
|
|
27
|
+
|
|
28
|
+
await rwBootstrap();
|
|
29
|
+
await actionProvider.registerMany(actions.reviewWorkflows);
|
|
30
|
+
|
|
31
|
+
// Decorate the entity service with review workflow logic
|
|
32
|
+
const { decorator } = getService('review-workflows-decorator');
|
|
33
|
+
strapi.entityService.decorate(decorator);
|
|
34
|
+
}
|
|
35
|
+
|
|
23
36
|
await getService('seat-enforcement').seatEnforcementWorkflow();
|
|
24
37
|
|
|
25
38
|
await executeCEBootstrap();
|
|
@@ -29,4 +29,14 @@ module.exports = {
|
|
|
29
29
|
subCategory: 'options',
|
|
30
30
|
},
|
|
31
31
|
],
|
|
32
|
+
reviewWorkflows: [
|
|
33
|
+
{
|
|
34
|
+
uid: 'review-workflows.read',
|
|
35
|
+
displayName: 'Read',
|
|
36
|
+
pluginName: 'admin',
|
|
37
|
+
section: 'settings',
|
|
38
|
+
category: 'review workflows',
|
|
39
|
+
subCategory: 'options',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
32
42
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
schema: {
|
|
5
|
+
collectionName: 'strapi_workflows',
|
|
6
|
+
info: {
|
|
7
|
+
name: 'Workflow',
|
|
8
|
+
description: '',
|
|
9
|
+
singularName: 'workflow',
|
|
10
|
+
pluralName: 'workflows',
|
|
11
|
+
displayName: 'Workflow',
|
|
12
|
+
},
|
|
13
|
+
options: {},
|
|
14
|
+
pluginOptions: {
|
|
15
|
+
'content-manager': {
|
|
16
|
+
visible: false,
|
|
17
|
+
},
|
|
18
|
+
'content-type-builder': {
|
|
19
|
+
visible: false,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
attributes: {
|
|
23
|
+
uid: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
},
|
|
26
|
+
stages: {
|
|
27
|
+
type: 'relation',
|
|
28
|
+
target: 'admin::workflow-stage',
|
|
29
|
+
relation: 'oneToMany',
|
|
30
|
+
mappedBy: 'workflow',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
schema: {
|
|
5
|
+
collectionName: 'strapi_workflows_stages',
|
|
6
|
+
info: {
|
|
7
|
+
name: 'Workflow Stage',
|
|
8
|
+
description: '',
|
|
9
|
+
singularName: 'workflow-stage',
|
|
10
|
+
pluralName: 'workflow-stages',
|
|
11
|
+
displayName: 'Stages',
|
|
12
|
+
},
|
|
13
|
+
options: {},
|
|
14
|
+
pluginOptions: {
|
|
15
|
+
'content-manager': {
|
|
16
|
+
visible: false,
|
|
17
|
+
},
|
|
18
|
+
'content-type-builder': {
|
|
19
|
+
visible: false,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
attributes: {
|
|
23
|
+
name: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
configurable: false,
|
|
26
|
+
},
|
|
27
|
+
workflow: {
|
|
28
|
+
type: 'relation',
|
|
29
|
+
target: 'admin::workflow',
|
|
30
|
+
relation: 'manyToOne',
|
|
31
|
+
inversedBy: 'stages',
|
|
32
|
+
configurable: false,
|
|
33
|
+
},
|
|
34
|
+
related: {
|
|
35
|
+
type: 'relation',
|
|
36
|
+
relation: 'morphToMany',
|
|
37
|
+
configurable: false,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { getService } = require('../../utils');
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
/**
|
|
7
|
+
* List all workflows
|
|
8
|
+
* @param {import('koa').BaseContext} ctx - koa context
|
|
9
|
+
*/
|
|
10
|
+
async find(ctx) {
|
|
11
|
+
const { populate } = ctx.query;
|
|
12
|
+
const workflowService = getService('workflows');
|
|
13
|
+
const data = await workflowService.find({
|
|
14
|
+
populate,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
ctx.body = {
|
|
18
|
+
data,
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
/**
|
|
22
|
+
* Get one workflow based on its id contained in request parameters
|
|
23
|
+
* @param {import('koa').BaseContext} ctx - koa context
|
|
24
|
+
*/
|
|
25
|
+
async findById(ctx) {
|
|
26
|
+
const { id } = ctx.params;
|
|
27
|
+
const { populate } = ctx.query;
|
|
28
|
+
|
|
29
|
+
const workflowService = getService('workflows');
|
|
30
|
+
const data = await workflowService.findById(id, { populate });
|
|
31
|
+
|
|
32
|
+
ctx.body = {
|
|
33
|
+
data,
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { ApplicationError } = require('@strapi/utils/lib/errors');
|
|
4
|
+
const { getService } = require('../../../utils');
|
|
5
|
+
const { hasReviewWorkflow } = require('../../../utils/review-workflows');
|
|
6
|
+
const {
|
|
7
|
+
validateUpdateStages,
|
|
8
|
+
validateUpdateStageOnEntity,
|
|
9
|
+
} = require('../../../validation/review-workflows');
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
/**
|
|
13
|
+
* List all stages
|
|
14
|
+
* @param {import('koa').BaseContext} ctx - koa context
|
|
15
|
+
*/
|
|
16
|
+
async find(ctx) {
|
|
17
|
+
const { workflow_id: workflowId } = ctx.params;
|
|
18
|
+
const { populate } = ctx.query;
|
|
19
|
+
const stagesService = getService('stages');
|
|
20
|
+
|
|
21
|
+
const data = await stagesService.find({
|
|
22
|
+
workflowId,
|
|
23
|
+
populate,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
ctx.body = {
|
|
27
|
+
data,
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
/**
|
|
31
|
+
* Get one stage
|
|
32
|
+
* @param {import('koa').BaseContext} ctx - koa context
|
|
33
|
+
*/
|
|
34
|
+
async findById(ctx) {
|
|
35
|
+
const { id, workflow_id: workflowId } = ctx.params;
|
|
36
|
+
const { populate } = ctx.query;
|
|
37
|
+
const stagesService = getService('stages');
|
|
38
|
+
|
|
39
|
+
const data = await stagesService.findById(id, {
|
|
40
|
+
workflowId,
|
|
41
|
+
populate,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
ctx.body = {
|
|
45
|
+
data,
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
async replace(ctx) {
|
|
50
|
+
const { workflow_id: workflowId } = ctx.params;
|
|
51
|
+
const stagesService = getService('stages');
|
|
52
|
+
const {
|
|
53
|
+
body: { data: stages },
|
|
54
|
+
} = ctx.request;
|
|
55
|
+
|
|
56
|
+
const stagesValidated = await validateUpdateStages(stages);
|
|
57
|
+
|
|
58
|
+
const data = await stagesService.replaceWorkflowStages(workflowId, stagesValidated);
|
|
59
|
+
|
|
60
|
+
ctx.body = { data };
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Updates an entity's stage.
|
|
65
|
+
* @async
|
|
66
|
+
* @param {Object} ctx - The Koa context object.
|
|
67
|
+
* @param {Object} ctx.params - An object containing the parameters from the request URL.
|
|
68
|
+
* @param {string} ctx.params.model_uid - The model UID of the entity.
|
|
69
|
+
* @param {string} ctx.params.id - The ID of the entity to update.
|
|
70
|
+
* @param {Object} ctx.request.body.data - Optional data object containing the new stage ID for the entity.
|
|
71
|
+
* @param {string} ctx.request.body.data.id - The ID of the new stage for the entity.
|
|
72
|
+
* @throws {ApplicationError} If review workflows is not activated on the specified model UID.
|
|
73
|
+
* @throws {ValidationError} If the `data` object in the request body fails to pass validation.
|
|
74
|
+
* @returns {Promise<void>} A promise that resolves when the entity's stage has been updated.
|
|
75
|
+
*/
|
|
76
|
+
async updateEntity(ctx) {
|
|
77
|
+
const stagesService = getService('stages');
|
|
78
|
+
const { model_uid: modelUID, id: entityIdString } = ctx.params;
|
|
79
|
+
const entityId = Number(entityIdString);
|
|
80
|
+
|
|
81
|
+
const { id: stageId } = await validateUpdateStageOnEntity(
|
|
82
|
+
ctx.request?.body?.data,
|
|
83
|
+
'You should pass an id to the body of the put request.'
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
if (!hasReviewWorkflow({ strapi }, modelUID)) {
|
|
87
|
+
throw new ApplicationError(`Review workflows is not activated on ${modelUID}.`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// TODO When multiple workflows are possible, check if the stage is part of the right one
|
|
91
|
+
// Didn't need this today as their can only be one workflow
|
|
92
|
+
|
|
93
|
+
ctx.body = await stagesService.updateEntity({ id: entityId, modelUID }, stageId);
|
|
94
|
+
},
|
|
95
|
+
};
|
package/ee/server/index.js
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { set } = require('lodash/fp');
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
contentTypeMiddleware,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A Strapi middleware function that adds support for review workflows.
|
|
11
|
+
*
|
|
12
|
+
* Why is it needed ?
|
|
13
|
+
* For now, the admin panel cannot have anything but top-level attributes in the content-type for options.
|
|
14
|
+
* But we need the CE part to be agnostics from Review Workflow (which is an EE feature).
|
|
15
|
+
* CE handle the `options` object, that's why we move the reviewWorkflows boolean to the options object.
|
|
16
|
+
*
|
|
17
|
+
* @param {object} strapi - The Strapi instance.
|
|
18
|
+
*/
|
|
19
|
+
function contentTypeMiddleware(strapi) {
|
|
20
|
+
/**
|
|
21
|
+
* A middleware function that moves the `reviewWorkflows` attribute from the top level of
|
|
22
|
+
* the request body to the `options` object within the request body.
|
|
23
|
+
*
|
|
24
|
+
* @param {object} ctx - The Koa context object.
|
|
25
|
+
*/
|
|
26
|
+
const moveReviewWorkflowOption = (ctx) => {
|
|
27
|
+
// Move reviewWorkflows to options.reviewWorkflows
|
|
28
|
+
const { reviewWorkflows, ...contentType } = ctx.request.body.contentType;
|
|
29
|
+
|
|
30
|
+
if (typeof reviewWorkflows === 'boolean') {
|
|
31
|
+
ctx.request.body.contentType = set('options.reviewWorkflows', reviewWorkflows, contentType);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
strapi.server.router.use('/content-type-builder/content-types/:uid?', (ctx, next) => {
|
|
35
|
+
if (ctx.method === 'PUT' || ctx.method === 'POST') {
|
|
36
|
+
moveReviewWorkflowOption(ctx);
|
|
37
|
+
}
|
|
38
|
+
return next();
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { hasReviewWorkflow } = require('../utils/review-workflows');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Remove all stage information for all content types that have had review workflows disabled
|
|
7
|
+
*/
|
|
8
|
+
/* eslint-disable no-continue */
|
|
9
|
+
const disableOnContentTypes = async ({ oldContentTypes, contentTypes }) => {
|
|
10
|
+
const uidsToRemove = [];
|
|
11
|
+
for (const uid in contentTypes) {
|
|
12
|
+
if (!oldContentTypes || !oldContentTypes[uid]) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const oldContentType = oldContentTypes[uid];
|
|
17
|
+
const contentType = contentTypes?.[uid];
|
|
18
|
+
|
|
19
|
+
if (
|
|
20
|
+
hasReviewWorkflow({ strapi }, oldContentType) &&
|
|
21
|
+
!hasReviewWorkflow({ strapi }, contentType)
|
|
22
|
+
) {
|
|
23
|
+
// If review workflows has been turned off on a content type
|
|
24
|
+
// remove stage information from all entities within this CT
|
|
25
|
+
uidsToRemove.push(uid);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (uidsToRemove.length === 0) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await strapi.db
|
|
34
|
+
.connection('strapi_workflows_stages_related_morphs')
|
|
35
|
+
.whereIn('related_type', uidsToRemove)
|
|
36
|
+
.del();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
module.exports = { disableOnContentTypes };
|
package/ee/server/register.js
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { features } = require('@strapi/strapi/lib/utils/ee');
|
|
3
4
|
const executeCERegister = require('../../server/register');
|
|
4
5
|
const migrateAuditLogsTable = require('./migrations/audit-logs-table');
|
|
5
6
|
const createAuditLogsService = require('./services/audit-logs');
|
|
7
|
+
const reviewWorkflowsMiddlewares = require('./middlewares/review-workflows');
|
|
8
|
+
const { getService } = require('./utils');
|
|
6
9
|
|
|
7
10
|
module.exports = async ({ strapi }) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (auditLogsIsEnabled) {
|
|
11
|
+
if (features.isEnabled('audit-logs')) {
|
|
11
12
|
strapi.hook('strapi::content-types.beforeSync').register(migrateAuditLogsTable);
|
|
12
13
|
const auditLogsService = createAuditLogsService(strapi);
|
|
13
14
|
strapi.container.register('audit-logs', auditLogsService);
|
|
14
15
|
await auditLogsService.register();
|
|
15
16
|
}
|
|
17
|
+
if (features.isEnabled('review-workflows')) {
|
|
18
|
+
const reviewWorkflowService = getService('review-workflows');
|
|
16
19
|
|
|
20
|
+
reviewWorkflowsMiddlewares.contentTypeMiddleware(strapi);
|
|
21
|
+
await reviewWorkflowService.register();
|
|
22
|
+
}
|
|
17
23
|
await executeCERegister({ strapi });
|
|
18
24
|
};
|