@strapi/admin 4.12.0-beta.3 → 4.12.0-beta.4
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/CollectionTypeFormWrapper/index.js +13 -35
- package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +304 -0
- package/admin/src/pages/AuthPage/components/Register/index.js +4 -0
- package/build/2379.0ca87a89.chunk.js +1 -0
- package/build/2395.df7a044a.chunk.js +26 -0
- package/build/2801.b1140c9b.chunk.js +1 -0
- package/build/{3100.21c343fa.chunk.js → 3100.2ba4df95.chunk.js} +1 -1
- package/build/{3483.ddd2d6df.chunk.js → 3483.e2ee2547.chunk.js} +1 -1
- package/build/3984.dda474f7.chunk.js +1 -0
- package/build/502.8ae8ef60.chunk.js +1 -0
- package/build/5483.6dd2e776.chunk.js +6 -0
- package/build/7065.99ca8ab1.chunk.js +112 -0
- package/build/7464.8a6c1e6c.chunk.js +1 -0
- package/build/8276.6c7b8e6e.chunk.js +26 -0
- package/build/{Admin-authenticatedApp.36b3826c.chunk.js → Admin-authenticatedApp.24998de8.chunk.js} +1 -1
- package/build/{admin-app.1c3f7fd6.chunk.js → admin-app.c2e4e128.chunk.js} +8 -8
- package/build/content-manager.8772445b.chunk.js +1103 -0
- package/build/index.html +1 -1
- package/build/{main.a12c4c0f.js → main.ef5fb1a8.js} +45 -45
- package/build/review-workflows-settings-create-view.d4b5dbb8.chunk.js +1 -0
- package/build/review-workflows-settings-edit-view.77299c63.chunk.js +1 -0
- package/build/review-workflows-settings-list-view.3ee9190d.chunk.js +56 -0
- package/build/{runtime~main.d197f488.js → runtime~main.c99f4c36.js} +2 -2
- package/build/sso-settings-page.3a1ed8c9.chunk.js +1 -0
- package/ee/admin/constants.js +3 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +12 -4
- package/ee/admin/hooks/index.js +1 -1
- package/ee/admin/hooks/useLicenseLimitNotification/index.js +1 -1
- package/ee/admin/hooks/useLicenseLimits/__mocks__/index.js +8 -0
- package/ee/admin/hooks/useLicenseLimits/index.js +1 -3
- package/ee/admin/hooks/useLicenseLimits/useLicenseLimits.js +3 -13
- package/ee/admin/pages/SettingsPage/pages/ApplicationInfosPage/components/AdminSeatInfo/index.js +19 -4
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +7 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +20 -16
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/WorkflowAttributes/WorkflowAttributes.js +38 -23
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +3 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/CreateView/CreateView.js +47 -27
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/CreateView/index.js +8 -3
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/EditView/EditView.js +68 -41
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/EditView/index.js +8 -3
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/ListView/ListView.js +72 -55
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/pages/ListView/index.js +8 -3
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +1 -7
- package/ee/admin/pages/SettingsPage/pages/SingleSignOn/utils/schema.js +8 -5
- package/ee/server/services/review-workflows/review-workflows.js +1 -1
- package/ee/server/services/review-workflows/validation.js +6 -4
- package/ee/server/services/review-workflows/workflows/content-types.js +28 -19
- package/ee/server/services/review-workflows/workflows/index.js +14 -2
- package/ee/server/validation/authentication.js +14 -8
- package/package.json +8 -8
- package/build/2379.d33a2e16.chunk.js +0 -1
- package/build/2395.b0419a54.chunk.js +0 -26
- package/build/2801.18f38baf.chunk.js +0 -1
- package/build/3984.ea7b8036.chunk.js +0 -1
- package/build/502.ccb38223.chunk.js +0 -1
- package/build/5483.ed2c7efa.chunk.js +0 -6
- package/build/7464.c6d0565c.chunk.js +0 -1
- package/build/8276.23e0763b.chunk.js +0 -26
- package/build/8298.fd253c9f.chunk.js +0 -117
- package/build/content-manager.b8d593d4.chunk.js +0 -1103
- package/build/review-workflows-settings-create-view.dfd87e1f.chunk.js +0 -1
- package/build/review-workflows-settings-edit-view.53c00afe.chunk.js +0 -1
- package/build/review-workflows-settings-list-view.a34be805.chunk.js +0 -56
- package/build/sso-settings-page.ed6f3f15.chunk.js +0 -1
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/ProtectedPage/ProtectedPage.js +0 -21
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/ProtectedPage/index.js +0 -1
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
3
|
import { Button, Flex, Loader } from '@strapi/design-system';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
useAPIErrorHandler,
|
|
6
|
+
useFetchClient,
|
|
7
|
+
useNotification,
|
|
8
|
+
useRBAC,
|
|
9
|
+
} from '@strapi/helper-plugin';
|
|
5
10
|
import { Check } from '@strapi/icons';
|
|
6
11
|
import { useFormik, Form, FormikProvider } from 'formik';
|
|
7
12
|
import set from 'lodash/set';
|
|
@@ -12,13 +17,18 @@ import { useHistory } from 'react-router-dom';
|
|
|
12
17
|
|
|
13
18
|
import { useContentTypes } from '../../../../../../../../admin/src/hooks/useContentTypes';
|
|
14
19
|
import { useInjectReducer } from '../../../../../../../../admin/src/hooks/useInjectReducer';
|
|
20
|
+
import { selectAdminPermissions } from '../../../../../../../../admin/src/pages/App/selectors';
|
|
15
21
|
import { useLicenseLimits } from '../../../../../../hooks';
|
|
16
|
-
import { resetWorkflow } from '../../actions';
|
|
22
|
+
import { addStage, resetWorkflow } from '../../actions';
|
|
17
23
|
import * as Layout from '../../components/Layout';
|
|
18
24
|
import * as LimitsModal from '../../components/LimitsModal';
|
|
19
25
|
import { Stages } from '../../components/Stages';
|
|
20
26
|
import { WorkflowAttributes } from '../../components/WorkflowAttributes';
|
|
21
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME,
|
|
29
|
+
CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME,
|
|
30
|
+
REDUX_NAMESPACE,
|
|
31
|
+
} from '../../constants';
|
|
22
32
|
import { useReviewWorkflows } from '../../hooks/useReviewWorkflows';
|
|
23
33
|
import { reducer, initialState } from '../../reducer';
|
|
24
34
|
import { validateWorkflow } from '../../utils/validateWorkflow';
|
|
@@ -29,6 +39,7 @@ export function ReviewWorkflowsCreateView() {
|
|
|
29
39
|
const { push } = useHistory();
|
|
30
40
|
const { formatAPIError } = useAPIErrorHandler();
|
|
31
41
|
const dispatch = useDispatch();
|
|
42
|
+
const permissions = useSelector(selectAdminPermissions);
|
|
32
43
|
const toggleNotification = useNotification();
|
|
33
44
|
const { collectionTypes, singleTypes, isLoading: isLoadingModels } = useContentTypes();
|
|
34
45
|
const {
|
|
@@ -36,6 +47,9 @@ export function ReviewWorkflowsCreateView() {
|
|
|
36
47
|
currentWorkflow: { data: currentWorkflow, isDirty: currentWorkflowIsDirty },
|
|
37
48
|
},
|
|
38
49
|
} = useSelector((state) => state?.[REDUX_NAMESPACE] ?? initialState);
|
|
50
|
+
const {
|
|
51
|
+
allowedActions: { canCreate },
|
|
52
|
+
} = useRBAC(permissions.settings['review-workflows']);
|
|
39
53
|
const [showLimitModal, setShowLimitModal] = React.useState(false);
|
|
40
54
|
const { isLoading: isLicenseLoading, getFeature } = useLicenseLimits();
|
|
41
55
|
const { meta, isLoading: isWorkflowLoading } = useReviewWorkflows();
|
|
@@ -72,20 +86,12 @@ export function ReviewWorkflowsCreateView() {
|
|
|
72
86
|
|
|
73
87
|
return workflow;
|
|
74
88
|
} catch (error) {
|
|
75
|
-
// TODO:
|
|
76
|
-
//
|
|
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`.
|
|
89
|
+
// TODO: this would benefit from a utility to get a formik error
|
|
90
|
+
// representation from an API error
|
|
80
91
|
if (
|
|
81
92
|
error.response.data?.error?.name === 'ValidationError' &&
|
|
82
93
|
error.response.data?.error?.details?.errors?.length > 0
|
|
83
94
|
) {
|
|
84
|
-
toggleNotification({
|
|
85
|
-
type: 'warning',
|
|
86
|
-
message: error.response.data.error.message,
|
|
87
|
-
});
|
|
88
|
-
|
|
89
95
|
setInitialErrors(
|
|
90
96
|
error.response.data?.error?.details?.errors.reduce((acc, error) => {
|
|
91
97
|
set(acc, error.path, error.message);
|
|
@@ -93,13 +99,13 @@ export function ReviewWorkflowsCreateView() {
|
|
|
93
99
|
return acc;
|
|
94
100
|
}, {})
|
|
95
101
|
);
|
|
96
|
-
} else {
|
|
97
|
-
toggleNotification({
|
|
98
|
-
type: 'warning',
|
|
99
|
-
message: formatAPIError(error),
|
|
100
|
-
});
|
|
101
102
|
}
|
|
102
103
|
|
|
104
|
+
toggleNotification({
|
|
105
|
+
type: 'warning',
|
|
106
|
+
message: formatAPIError(error),
|
|
107
|
+
});
|
|
108
|
+
|
|
103
109
|
return null;
|
|
104
110
|
}
|
|
105
111
|
};
|
|
@@ -117,7 +123,10 @@ export function ReviewWorkflowsCreateView() {
|
|
|
117
123
|
* update, because it would throw an API error.
|
|
118
124
|
*/
|
|
119
125
|
|
|
120
|
-
if (
|
|
126
|
+
if (
|
|
127
|
+
limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
128
|
+
meta?.workflowCount >= parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
129
|
+
) {
|
|
121
130
|
setShowLimitModal('workflow');
|
|
122
131
|
|
|
123
132
|
/**
|
|
@@ -126,8 +135,9 @@ export function ReviewWorkflowsCreateView() {
|
|
|
126
135
|
* update, because it would throw an API error.
|
|
127
136
|
*/
|
|
128
137
|
} else if (
|
|
129
|
-
limits?.
|
|
130
|
-
currentWorkflow.stages.length >=
|
|
138
|
+
limits?.[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
139
|
+
currentWorkflow.stages.length >=
|
|
140
|
+
parseInt(limits[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
131
141
|
) {
|
|
132
142
|
setShowLimitModal('stage');
|
|
133
143
|
} else {
|
|
@@ -143,6 +153,13 @@ export function ReviewWorkflowsCreateView() {
|
|
|
143
153
|
|
|
144
154
|
React.useEffect(() => {
|
|
145
155
|
dispatch(resetWorkflow());
|
|
156
|
+
|
|
157
|
+
// Create an empty default stage
|
|
158
|
+
dispatch(
|
|
159
|
+
addStage({
|
|
160
|
+
name: '',
|
|
161
|
+
})
|
|
162
|
+
);
|
|
146
163
|
}, [dispatch]);
|
|
147
164
|
|
|
148
165
|
/**
|
|
@@ -160,11 +177,15 @@ export function ReviewWorkflowsCreateView() {
|
|
|
160
177
|
|
|
161
178
|
React.useEffect(() => {
|
|
162
179
|
if (!isWorkflowLoading && !isLicenseLoading) {
|
|
163
|
-
if (
|
|
180
|
+
if (
|
|
181
|
+
limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
182
|
+
meta?.workflowsTotal >= parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
183
|
+
) {
|
|
164
184
|
setShowLimitModal('workflow');
|
|
165
185
|
} else if (
|
|
166
|
-
limits
|
|
167
|
-
currentWorkflow.stages.length >=
|
|
186
|
+
limits?.[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
187
|
+
currentWorkflow.stages.length >=
|
|
188
|
+
parseInt(limits[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
168
189
|
) {
|
|
169
190
|
setShowLimitModal('stage');
|
|
170
191
|
}
|
|
@@ -172,8 +193,7 @@ export function ReviewWorkflowsCreateView() {
|
|
|
172
193
|
}, [
|
|
173
194
|
isLicenseLoading,
|
|
174
195
|
isWorkflowLoading,
|
|
175
|
-
limits
|
|
176
|
-
limits?.workflows,
|
|
196
|
+
limits,
|
|
177
197
|
meta?.workflowsTotal,
|
|
178
198
|
currentWorkflow.stages.length,
|
|
179
199
|
]);
|
|
@@ -191,7 +211,7 @@ export function ReviewWorkflowsCreateView() {
|
|
|
191
211
|
startIcon={<Check />}
|
|
192
212
|
type="submit"
|
|
193
213
|
size="M"
|
|
194
|
-
disabled={!currentWorkflowIsDirty}
|
|
214
|
+
disabled={!currentWorkflowIsDirty || !canCreate}
|
|
195
215
|
isLoading={isLoading}
|
|
196
216
|
>
|
|
197
217
|
{formatMessage({
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
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
|
-
<
|
|
14
|
+
<CheckPagePermissions permissions={permissions.settings['review-workflows'].create}>
|
|
10
15
|
<ReviewWorkflowsCreateView />
|
|
11
|
-
</
|
|
16
|
+
</CheckPagePermissions>
|
|
12
17
|
);
|
|
13
18
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
useAPIErrorHandler,
|
|
7
7
|
useFetchClient,
|
|
8
8
|
useNotification,
|
|
9
|
+
useRBAC,
|
|
9
10
|
} from '@strapi/helper-plugin';
|
|
10
11
|
import { Check } from '@strapi/icons';
|
|
11
12
|
import { useFormik, Form, FormikProvider } from 'formik';
|
|
@@ -17,19 +18,25 @@ import { useParams } from 'react-router-dom';
|
|
|
17
18
|
|
|
18
19
|
import { useContentTypes } from '../../../../../../../../admin/src/hooks/useContentTypes';
|
|
19
20
|
import { useInjectReducer } from '../../../../../../../../admin/src/hooks/useInjectReducer';
|
|
21
|
+
import { selectAdminPermissions } from '../../../../../../../../admin/src/pages/App/selectors';
|
|
20
22
|
import { useLicenseLimits } from '../../../../../../hooks';
|
|
21
|
-
import { setWorkflow } from '../../actions';
|
|
23
|
+
import { resetWorkflow, setWorkflow } from '../../actions';
|
|
22
24
|
import * as Layout from '../../components/Layout';
|
|
23
25
|
import * as LimitsModal from '../../components/LimitsModal';
|
|
24
26
|
import { Stages } from '../../components/Stages';
|
|
25
27
|
import { WorkflowAttributes } from '../../components/WorkflowAttributes';
|
|
26
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME,
|
|
30
|
+
CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME,
|
|
31
|
+
REDUX_NAMESPACE,
|
|
32
|
+
} from '../../constants';
|
|
27
33
|
import { useReviewWorkflows } from '../../hooks/useReviewWorkflows';
|
|
28
34
|
import { reducer, initialState } from '../../reducer';
|
|
29
35
|
import { validateWorkflow } from '../../utils/validateWorkflow';
|
|
30
36
|
|
|
31
37
|
export function ReviewWorkflowsEditView() {
|
|
32
38
|
const { workflowId } = useParams();
|
|
39
|
+
const permissions = useSelector(selectAdminPermissions);
|
|
33
40
|
const { formatMessage } = useIntl();
|
|
34
41
|
const dispatch = useDispatch();
|
|
35
42
|
const { put } = useFetchClient();
|
|
@@ -53,6 +60,9 @@ export function ReviewWorkflowsEditView() {
|
|
|
53
60
|
},
|
|
54
61
|
},
|
|
55
62
|
} = useSelector((state) => state?.[REDUX_NAMESPACE] ?? initialState);
|
|
63
|
+
const {
|
|
64
|
+
allowedActions: { canDelete, canUpdate },
|
|
65
|
+
} = useRBAC(permissions.settings['review-workflows']);
|
|
56
66
|
const [isConfirmDeleteDialogOpen, setIsConfirmDeleteDialogOpen] = React.useState(false);
|
|
57
67
|
const { getFeature, isLoading: isLicenseLoading } = useLicenseLimits();
|
|
58
68
|
const [showLimitModal, setShowLimitModal] = React.useState(false);
|
|
@@ -87,20 +97,12 @@ export function ReviewWorkflowsEditView() {
|
|
|
87
97
|
|
|
88
98
|
return res;
|
|
89
99
|
} catch (error) {
|
|
90
|
-
// TODO:
|
|
91
|
-
//
|
|
92
|
-
// several times. What we want instead in these scenarios is to print only the error summary and
|
|
93
|
-
// display the individual error messages for each field. This is a workaround, until we change the
|
|
94
|
-
// implementation of `formatAPIError`.
|
|
100
|
+
// TODO: this would benefit from a utility to get a formik error
|
|
101
|
+
// representation from an API error
|
|
95
102
|
if (
|
|
96
103
|
error.response.data?.error?.name === 'ValidationError' &&
|
|
97
104
|
error.response.data?.error?.details?.errors?.length > 0
|
|
98
105
|
) {
|
|
99
|
-
toggleNotification({
|
|
100
|
-
type: 'warning',
|
|
101
|
-
message: error.response.data.error.message,
|
|
102
|
-
});
|
|
103
|
-
|
|
104
106
|
setInitialErrors(
|
|
105
107
|
error.response.data?.error?.details?.errors.reduce((acc, error) => {
|
|
106
108
|
set(acc, error.path, error.message);
|
|
@@ -108,13 +110,13 @@ export function ReviewWorkflowsEditView() {
|
|
|
108
110
|
return acc;
|
|
109
111
|
}, {})
|
|
110
112
|
);
|
|
111
|
-
} else {
|
|
112
|
-
toggleNotification({
|
|
113
|
-
type: 'warning',
|
|
114
|
-
message: formatAPIError(error),
|
|
115
|
-
});
|
|
116
113
|
}
|
|
117
114
|
|
|
115
|
+
toggleNotification({
|
|
116
|
+
type: 'warning',
|
|
117
|
+
message: formatAPIError(error),
|
|
118
|
+
});
|
|
119
|
+
|
|
118
120
|
return null;
|
|
119
121
|
}
|
|
120
122
|
};
|
|
@@ -141,7 +143,10 @@ export function ReviewWorkflowsEditView() {
|
|
|
141
143
|
async onSubmit() {
|
|
142
144
|
if (currentWorkflowHasDeletedServerStages) {
|
|
143
145
|
setIsConfirmDeleteDialogOpen(true);
|
|
144
|
-
} else if (
|
|
146
|
+
} else if (
|
|
147
|
+
limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
148
|
+
meta?.workflowCount > parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
149
|
+
) {
|
|
145
150
|
/**
|
|
146
151
|
* If the current license has a limit, check if the total count of workflows
|
|
147
152
|
* exceeds that limit and display the limits modal instead of sending the
|
|
@@ -155,8 +160,9 @@ export function ReviewWorkflowsEditView() {
|
|
|
155
160
|
* update, because it would throw an API error.
|
|
156
161
|
*/
|
|
157
162
|
} else if (
|
|
158
|
-
limits?.
|
|
159
|
-
currentWorkflow.stages.length >
|
|
163
|
+
limits?.[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
164
|
+
currentWorkflow.stages.length >
|
|
165
|
+
parseInt(limits[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
160
166
|
) {
|
|
161
167
|
setShowLimitModal('stage');
|
|
162
168
|
} else {
|
|
@@ -174,6 +180,12 @@ export function ReviewWorkflowsEditView() {
|
|
|
174
180
|
|
|
175
181
|
React.useEffect(() => {
|
|
176
182
|
dispatch(setWorkflow({ status: workflowStatus, data: workflow }));
|
|
183
|
+
|
|
184
|
+
// reset the state to the initial state to avoid flashes if a user
|
|
185
|
+
// navigates from an edit-view to a create-view
|
|
186
|
+
return () => {
|
|
187
|
+
dispatch(resetWorkflow());
|
|
188
|
+
};
|
|
177
189
|
}, [workflowStatus, workflow, dispatch]);
|
|
178
190
|
|
|
179
191
|
/**
|
|
@@ -191,11 +203,15 @@ export function ReviewWorkflowsEditView() {
|
|
|
191
203
|
|
|
192
204
|
React.useEffect(() => {
|
|
193
205
|
if (!isWorkflowLoading && !isLicenseLoading) {
|
|
194
|
-
if (
|
|
206
|
+
if (
|
|
207
|
+
limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
208
|
+
meta?.workflowCount > parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
209
|
+
) {
|
|
195
210
|
setShowLimitModal('workflow');
|
|
196
211
|
} else if (
|
|
197
|
-
limits?.
|
|
198
|
-
currentWorkflow.stages.length >
|
|
212
|
+
limits?.[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
213
|
+
currentWorkflow.stages.length >
|
|
214
|
+
parseInt(limits[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
199
215
|
) {
|
|
200
216
|
setShowLimitModal('stage');
|
|
201
217
|
}
|
|
@@ -204,8 +220,7 @@ export function ReviewWorkflowsEditView() {
|
|
|
204
220
|
currentWorkflow.stages.length,
|
|
205
221
|
isLicenseLoading,
|
|
206
222
|
isWorkflowLoading,
|
|
207
|
-
limits
|
|
208
|
-
limits.workflows,
|
|
223
|
+
limits,
|
|
209
224
|
meta?.workflowCount,
|
|
210
225
|
meta.workflowsTotal,
|
|
211
226
|
]);
|
|
@@ -225,7 +240,7 @@ export function ReviewWorkflowsEditView() {
|
|
|
225
240
|
startIcon={<Check />}
|
|
226
241
|
type="submit"
|
|
227
242
|
size="M"
|
|
228
|
-
disabled={!currentWorkflowIsDirty}
|
|
243
|
+
disabled={!currentWorkflowIsDirty || !canUpdate}
|
|
229
244
|
// if the confirm dialog is open the loading state is on
|
|
230
245
|
// the confirm button already
|
|
231
246
|
loading={!isConfirmDeleteDialogOpen && isLoading}
|
|
@@ -236,28 +251,40 @@ export function ReviewWorkflowsEditView() {
|
|
|
236
251
|
})}
|
|
237
252
|
</Button>
|
|
238
253
|
}
|
|
239
|
-
subtitle={
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
254
|
+
subtitle={
|
|
255
|
+
currentWorkflow.stages.length > 0 &&
|
|
256
|
+
formatMessage(
|
|
257
|
+
{
|
|
258
|
+
id: 'Settings.review-workflows.page.subtitle',
|
|
259
|
+
defaultMessage: '{count, plural, one {# stage} other {# stages}}',
|
|
260
|
+
},
|
|
261
|
+
{ count: currentWorkflow.stages.length }
|
|
262
|
+
)
|
|
263
|
+
}
|
|
246
264
|
title={currentWorkflow.name}
|
|
247
265
|
/>
|
|
248
266
|
|
|
249
267
|
<Layout.Root>
|
|
250
268
|
{isLoadingModels || status === 'loading' ? (
|
|
251
|
-
<
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
269
|
+
<Flex justifyContent="center">
|
|
270
|
+
<Loader>
|
|
271
|
+
{formatMessage({
|
|
272
|
+
id: 'Settings.review-workflows.page.isLoading',
|
|
273
|
+
defaultMessage: 'Workflow is loading',
|
|
274
|
+
})}
|
|
275
|
+
</Loader>
|
|
276
|
+
</Flex>
|
|
257
277
|
) : (
|
|
258
278
|
<Flex alignItems="stretch" direction="column" gap={7}>
|
|
259
|
-
<WorkflowAttributes
|
|
260
|
-
|
|
279
|
+
<WorkflowAttributes
|
|
280
|
+
canUpdate={canUpdate}
|
|
281
|
+
contentTypes={{ collectionTypes, singleTypes }}
|
|
282
|
+
/>
|
|
283
|
+
<Stages
|
|
284
|
+
canDelete={canDelete}
|
|
285
|
+
canUpdate={canUpdate}
|
|
286
|
+
stages={formik.values?.stages}
|
|
287
|
+
/>
|
|
261
288
|
</Flex>
|
|
262
289
|
)}
|
|
263
290
|
</Layout.Root>
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
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 { ReviewWorkflowsEditView } from './EditView';
|
|
6
9
|
|
|
7
10
|
export default function () {
|
|
11
|
+
const permissions = useSelector(selectAdminPermissions);
|
|
12
|
+
|
|
8
13
|
return (
|
|
9
|
-
<
|
|
14
|
+
<CheckPagePermissions permissions={permissions.settings['review-workflows'].main}>
|
|
10
15
|
<ReviewWorkflowsEditView />
|
|
11
|
-
</
|
|
16
|
+
</CheckPagePermissions>
|
|
12
17
|
);
|
|
13
18
|
}
|
|
@@ -23,18 +23,22 @@ import {
|
|
|
23
23
|
useAPIErrorHandler,
|
|
24
24
|
useFetchClient,
|
|
25
25
|
useNotification,
|
|
26
|
+
useRBAC,
|
|
26
27
|
useTracking,
|
|
27
28
|
} from '@strapi/helper-plugin';
|
|
28
29
|
import { Pencil, Plus, Trash } from '@strapi/icons';
|
|
29
30
|
import { useIntl } from 'react-intl';
|
|
30
31
|
import { useMutation } from 'react-query';
|
|
32
|
+
import { useSelector } from 'react-redux';
|
|
31
33
|
import { useHistory } from 'react-router-dom';
|
|
32
34
|
import styled from 'styled-components';
|
|
33
35
|
|
|
34
36
|
import { useContentTypes } from '../../../../../../../../admin/src/hooks/useContentTypes';
|
|
37
|
+
import { selectAdminPermissions } from '../../../../../../../../admin/src/pages/App/selectors';
|
|
35
38
|
import { useLicenseLimits } from '../../../../../../hooks';
|
|
36
39
|
import * as Layout from '../../components/Layout';
|
|
37
40
|
import * as LimitsModal from '../../components/LimitsModal';
|
|
41
|
+
import { CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME } from '../../constants';
|
|
38
42
|
import { useReviewWorkflows } from '../../hooks/useReviewWorkflows';
|
|
39
43
|
|
|
40
44
|
const ActionLink = styled(Link)`
|
|
@@ -76,6 +80,10 @@ export function ReviewWorkflowsListView() {
|
|
|
76
80
|
const toggleNotification = useNotification();
|
|
77
81
|
const { getFeature, isLoading: isLicenseLoading } = useLicenseLimits();
|
|
78
82
|
const { trackUsage } = useTracking();
|
|
83
|
+
const permissions = useSelector(selectAdminPermissions);
|
|
84
|
+
const {
|
|
85
|
+
allowedActions: { canCreate, canDelete },
|
|
86
|
+
} = useRBAC(permissions.settings['review-workflows']);
|
|
79
87
|
|
|
80
88
|
const limits = getFeature('review-workflows');
|
|
81
89
|
|
|
@@ -148,24 +156,21 @@ export function ReviewWorkflowsListView() {
|
|
|
148
156
|
|
|
149
157
|
React.useEffect(() => {
|
|
150
158
|
if (!isLoading && !isLicenseLoading) {
|
|
151
|
-
if (
|
|
159
|
+
if (
|
|
160
|
+
limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
161
|
+
meta?.workflowCount > parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
162
|
+
) {
|
|
152
163
|
setShowLimitModal(true);
|
|
153
164
|
}
|
|
154
165
|
}
|
|
155
|
-
}, [
|
|
156
|
-
isLicenseLoading,
|
|
157
|
-
isLoading,
|
|
158
|
-
limits.stagesPerWorkflow,
|
|
159
|
-
limits.workflows,
|
|
160
|
-
meta?.workflowCount,
|
|
161
|
-
meta.workflowsTotal,
|
|
162
|
-
]);
|
|
166
|
+
}, [isLicenseLoading, isLoading, limits, meta?.workflowCount, meta.workflowsTotal]);
|
|
163
167
|
|
|
164
168
|
return (
|
|
165
169
|
<>
|
|
166
170
|
<Layout.Header
|
|
167
171
|
primaryAction={
|
|
168
172
|
<LinkButton
|
|
173
|
+
disabled={!canCreate}
|
|
169
174
|
startIcon={<Plus />}
|
|
170
175
|
size="S"
|
|
171
176
|
to="/settings/review-workflows/create"
|
|
@@ -180,7 +185,10 @@ export function ReviewWorkflowsListView() {
|
|
|
180
185
|
* current hard-limit of 200 they will see an error thrown by the API.
|
|
181
186
|
*/
|
|
182
187
|
|
|
183
|
-
if (
|
|
188
|
+
if (
|
|
189
|
+
limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
190
|
+
meta?.workflowCount >= parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
191
|
+
) {
|
|
184
192
|
event.preventDefault();
|
|
185
193
|
setShowLimitModal(true);
|
|
186
194
|
} else {
|
|
@@ -207,42 +215,50 @@ export function ReviewWorkflowsListView() {
|
|
|
207
215
|
|
|
208
216
|
<Layout.Root>
|
|
209
217
|
{isLoading || isLoadingModels ? (
|
|
210
|
-
<
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
218
|
+
<Flex justifyContent="center">
|
|
219
|
+
<Loader>
|
|
220
|
+
{formatMessage({
|
|
221
|
+
id: 'Settings.review-workflows.page.list.isLoading',
|
|
222
|
+
defaultMessage: 'Workflows are loading',
|
|
223
|
+
})}
|
|
224
|
+
</Loader>
|
|
225
|
+
</Flex>
|
|
216
226
|
) : (
|
|
217
227
|
<Table
|
|
218
228
|
colCount={3}
|
|
219
229
|
footer={
|
|
220
230
|
// TODO: we should be able to use a link here instead of an (inaccessible onClick) handler
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
231
|
+
canCreate && (
|
|
232
|
+
<TFooter
|
|
233
|
+
icon={<Plus />}
|
|
234
|
+
onClick={() => {
|
|
235
|
+
/**
|
|
236
|
+
* If the current license has a workflow limit:
|
|
237
|
+
* check if the total count of workflows exceeds that limit
|
|
238
|
+
*
|
|
239
|
+
* If the current license does not have a limit (e.g. offline license):
|
|
240
|
+
* allow the user to navigate to the create-view. In case they exceed the
|
|
241
|
+
* current hard-limit of 200 they will see an error thrown by the API.
|
|
242
|
+
*/
|
|
232
243
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
if (
|
|
245
|
+
limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] &&
|
|
246
|
+
meta?.workflowCount >=
|
|
247
|
+
parseInt(limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME], 10)
|
|
248
|
+
) {
|
|
249
|
+
setShowLimitModal(true);
|
|
250
|
+
} else {
|
|
251
|
+
push('/settings/review-workflows/create');
|
|
252
|
+
trackUsage('willCreateWorkflow');
|
|
253
|
+
}
|
|
254
|
+
}}
|
|
255
|
+
>
|
|
256
|
+
{formatMessage({
|
|
257
|
+
id: 'Settings.review-workflows.list.page.create',
|
|
258
|
+
defaultMessage: 'Create new workflow',
|
|
259
|
+
})}
|
|
260
|
+
</TFooter>
|
|
261
|
+
)
|
|
246
262
|
}
|
|
247
263
|
rowCount={1}
|
|
248
264
|
>
|
|
@@ -326,21 +342,22 @@ export function ReviewWorkflowsListView() {
|
|
|
326
342
|
<Pencil />
|
|
327
343
|
</ActionLink>
|
|
328
344
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
{
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
345
|
+
{workflows.length > 1 && canDelete && (
|
|
346
|
+
<IconButton
|
|
347
|
+
aria-label={formatMessage(
|
|
348
|
+
{
|
|
349
|
+
id: 'Settings.review-workflows.list.page.list.column.actions.delete.label',
|
|
350
|
+
defaultMessage: 'Delete {name}',
|
|
351
|
+
},
|
|
352
|
+
{ name: 'Default workflow' }
|
|
353
|
+
)}
|
|
354
|
+
icon={<Trash />}
|
|
355
|
+
noBorder
|
|
356
|
+
onClick={() => {
|
|
357
|
+
handleDeleteWorkflow(workflow.id);
|
|
358
|
+
}}
|
|
359
|
+
/>
|
|
360
|
+
)}
|
|
344
361
|
</Flex>
|
|
345
362
|
</Td>
|
|
346
363
|
</Tr>
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
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 { ReviewWorkflowsListView } from './ListView';
|
|
6
9
|
|
|
7
10
|
export default function () {
|
|
11
|
+
const permissions = useSelector(selectAdminPermissions);
|
|
12
|
+
|
|
8
13
|
return (
|
|
9
|
-
<
|
|
14
|
+
<CheckPagePermissions permissions={permissions.settings['review-workflows'].main}>
|
|
10
15
|
<ReviewWorkflowsListView />
|
|
11
|
-
</
|
|
16
|
+
</CheckPagePermissions>
|
|
12
17
|
);
|
|
13
18
|
}
|