@strapi/plugin-users-permissions 4.12.6 → 4.12.7
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/components/Permissions/index.js +4 -2
- package/admin/src/hooks/index.js +5 -0
- package/admin/src/hooks/useFetchRole/index.js +67 -0
- package/admin/src/hooks/useFetchRole/reducer.js +31 -0
- package/admin/src/hooks/useForm/index.js +68 -0
- package/admin/src/hooks/useForm/reducer.js +40 -0
- package/admin/src/{pages/Roles/hooks → hooks}/usePlugins.js +8 -15
- package/admin/src/hooks/useRolesList/index.js +65 -0
- package/admin/src/hooks/useRolesList/init.js +5 -0
- package/admin/src/hooks/useRolesList/reducer.js +31 -0
- package/admin/src/index.js +8 -7
- package/admin/src/pages/AdvancedSettings/index.js +24 -41
- package/admin/src/pages/AdvancedSettings/utils/api.js +16 -0
- package/admin/src/pages/EmailTemplates/index.js +47 -62
- package/admin/src/pages/EmailTemplates/utils/api.js +16 -0
- package/admin/src/pages/Providers/index.js +58 -64
- package/admin/src/pages/Providers/reducer.js +54 -0
- package/admin/src/pages/Providers/utils/api.js +24 -0
- package/admin/src/pages/Providers/utils/createProvidersArray.js +21 -0
- package/admin/src/pages/Roles/CreatePage.js +185 -0
- package/admin/src/pages/Roles/EditPage.js +197 -0
- package/admin/src/pages/Roles/{pages/ListPage → ListPage}/components/TableBody.js +11 -41
- package/admin/src/pages/Roles/{pages/ListPage → ListPage}/index.js +15 -19
- package/admin/src/pages/Roles/ProtectedCreatePage.js +15 -0
- package/admin/src/pages/Roles/ProtectedEditPage.js +15 -0
- package/admin/src/pages/Roles/ProtectedListPage.js +17 -0
- package/admin/src/pages/Roles/index.js +7 -10
- package/jest.config.front.js +1 -1
- package/package.json +4 -4
- package/admin/src/pages/Roles/pages/CreatePage.js +0 -190
- package/admin/src/pages/Roles/pages/EditPage.js +0 -211
- /package/admin/src/pages/Roles/{pages/ListPage → ListPage}/utils/api.js +0 -0
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import { ContentLayout, HeaderLayout, Main, useNotifyAT } from '@strapi/design-system';
|
|
4
4
|
import {
|
|
5
5
|
CheckPagePermissions,
|
|
6
6
|
LoadingIndicatorPage,
|
|
7
7
|
SettingsPageTitle,
|
|
8
|
-
useAPIErrorHandler,
|
|
9
|
-
useFetchClient,
|
|
10
8
|
useFocusWhenNavigate,
|
|
11
9
|
useNotification,
|
|
12
10
|
useOverlayBlocker,
|
|
@@ -21,6 +19,7 @@ import { getTrad } from '../../utils';
|
|
|
21
19
|
|
|
22
20
|
import EmailForm from './components/EmailForm';
|
|
23
21
|
import EmailTable from './components/EmailTable';
|
|
22
|
+
import { fetchData, putEmailTemplate } from './utils/api';
|
|
24
23
|
|
|
25
24
|
const ProtectedEmailTemplatesPage = () => (
|
|
26
25
|
<CheckPagePermissions permissions={PERMISSIONS.readEmailTemplates}>
|
|
@@ -34,46 +33,36 @@ const EmailTemplatesPage = () => {
|
|
|
34
33
|
const { notifyStatus } = useNotifyAT();
|
|
35
34
|
const toggleNotification = useNotification();
|
|
36
35
|
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
36
|
+
const trackUsageRef = useRef(trackUsage);
|
|
37
37
|
const queryClient = useQueryClient();
|
|
38
|
-
const { get, put } = useFetchClient();
|
|
39
|
-
const { formatAPIError } = useAPIErrorHandler();
|
|
40
|
-
|
|
41
38
|
useFocusWhenNavigate();
|
|
42
39
|
|
|
43
|
-
const [isModalOpen, setIsModalOpen] =
|
|
44
|
-
const [templateToEdit, setTemplateToEdit] =
|
|
40
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
41
|
+
const [templateToEdit, setTemplateToEdit] = useState(null);
|
|
45
42
|
|
|
46
43
|
const {
|
|
47
44
|
isLoading: isLoadingForPermissions,
|
|
48
45
|
allowedActions: { canUpdate },
|
|
49
46
|
} = useRBAC({ update: PERMISSIONS.updateEmailTemplates });
|
|
50
47
|
|
|
51
|
-
const {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
const { status: isLoadingData, data } = useQuery('email-templates', () => fetchData(), {
|
|
49
|
+
onSuccess() {
|
|
50
|
+
notifyStatus(
|
|
51
|
+
formatMessage({
|
|
52
|
+
id: getTrad('Email.template.data.loaded'),
|
|
53
|
+
defaultMessage: 'Email templates has been loaded',
|
|
54
|
+
})
|
|
55
|
+
);
|
|
57
56
|
},
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
);
|
|
66
|
-
},
|
|
67
|
-
onError(error) {
|
|
68
|
-
toggleNotification({
|
|
69
|
-
type: 'warning',
|
|
70
|
-
message: formatAPIError(error),
|
|
71
|
-
});
|
|
72
|
-
},
|
|
73
|
-
}
|
|
74
|
-
);
|
|
57
|
+
onError() {
|
|
58
|
+
toggleNotification({
|
|
59
|
+
type: 'warning',
|
|
60
|
+
message: { id: 'notification.error', defaultMessage: 'An error occured' },
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
});
|
|
75
64
|
|
|
76
|
-
const isLoading = isLoadingForPermissions || isLoadingData;
|
|
65
|
+
const isLoading = isLoadingForPermissions || isLoadingData !== 'success';
|
|
77
66
|
|
|
78
67
|
const handleToggle = () => {
|
|
79
68
|
setIsModalOpen((prev) => !prev);
|
|
@@ -84,38 +73,34 @@ const EmailTemplatesPage = () => {
|
|
|
84
73
|
handleToggle();
|
|
85
74
|
};
|
|
86
75
|
|
|
87
|
-
const submitMutation = useMutation(
|
|
88
|
-
(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
refetchActive: true,
|
|
112
|
-
}
|
|
113
|
-
);
|
|
76
|
+
const submitMutation = useMutation((body) => putEmailTemplate({ 'email-templates': body }), {
|
|
77
|
+
async onSuccess() {
|
|
78
|
+
await queryClient.invalidateQueries('email-templates');
|
|
79
|
+
|
|
80
|
+
toggleNotification({
|
|
81
|
+
type: 'success',
|
|
82
|
+
message: { id: 'notification.success.saved', defaultMessage: 'Saved' },
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
trackUsageRef.current('didEditEmailTemplates');
|
|
86
|
+
|
|
87
|
+
unlockApp();
|
|
88
|
+
handleToggle();
|
|
89
|
+
},
|
|
90
|
+
onError() {
|
|
91
|
+
toggleNotification({
|
|
92
|
+
type: 'warning',
|
|
93
|
+
message: { id: 'notification.error', defaultMessage: 'An error occured' },
|
|
94
|
+
});
|
|
95
|
+
unlockApp();
|
|
96
|
+
},
|
|
97
|
+
refetchActive: true,
|
|
98
|
+
});
|
|
99
|
+
const { isLoading: isSubmittingForm } = submitMutation;
|
|
114
100
|
|
|
115
101
|
const handleSubmit = (body) => {
|
|
116
102
|
lockApp();
|
|
117
|
-
|
|
118
|
-
trackUsage('willEditEmailTemplates');
|
|
103
|
+
trackUsageRef.current('willEditEmailTemplates');
|
|
119
104
|
|
|
120
105
|
const editedTemplates = { ...data, [templateToEdit]: body };
|
|
121
106
|
submitMutation.mutate(editedTemplates);
|
|
@@ -144,7 +129,7 @@ const EmailTemplatesPage = () => {
|
|
|
144
129
|
}
|
|
145
130
|
|
|
146
131
|
return (
|
|
147
|
-
<Main aria-busy={
|
|
132
|
+
<Main aria-busy={isSubmittingForm}>
|
|
148
133
|
<SettingsPageTitle
|
|
149
134
|
name={formatMessage({
|
|
150
135
|
id: getTrad('HeaderNav.link.emailTemplates'),
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getFetchClient } from '@strapi/helper-plugin';
|
|
2
|
+
|
|
3
|
+
const fetchData = async () => {
|
|
4
|
+
const { get } = getFetchClient();
|
|
5
|
+
const { data } = await get('/users-permissions/email-templates');
|
|
6
|
+
|
|
7
|
+
return data;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const putEmailTemplate = (body) => {
|
|
11
|
+
const { put } = getFetchClient();
|
|
12
|
+
|
|
13
|
+
return put('/users-permissions/email-templates', body);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { fetchData, putEmailTemplate };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React, { useMemo, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
ContentLayout,
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
Thead,
|
|
14
14
|
Tr,
|
|
15
15
|
Typography,
|
|
16
|
+
useNotifyAT,
|
|
16
17
|
VisuallyHidden,
|
|
17
18
|
} from '@strapi/design-system';
|
|
18
19
|
import {
|
|
@@ -21,9 +22,6 @@ import {
|
|
|
21
22
|
onRowClick,
|
|
22
23
|
SettingsPageTitle,
|
|
23
24
|
stopPropagation,
|
|
24
|
-
useAPIErrorHandler,
|
|
25
|
-
useCollator,
|
|
26
|
-
useFetchClient,
|
|
27
25
|
useFocusWhenNavigate,
|
|
28
26
|
useNotification,
|
|
29
27
|
useOverlayBlocker,
|
|
@@ -31,6 +29,7 @@ import {
|
|
|
31
29
|
useTracking,
|
|
32
30
|
} from '@strapi/helper-plugin';
|
|
33
31
|
import { Pencil } from '@strapi/icons';
|
|
32
|
+
import has from 'lodash/has';
|
|
34
33
|
import upperFirst from 'lodash/upperFirst';
|
|
35
34
|
import { useIntl } from 'react-intl';
|
|
36
35
|
import { useMutation, useQuery, useQueryClient } from 'react-query';
|
|
@@ -39,94 +38,90 @@ import FormModal from '../../components/FormModal';
|
|
|
39
38
|
import { PERMISSIONS } from '../../constants';
|
|
40
39
|
import { getTrad } from '../../utils';
|
|
41
40
|
|
|
41
|
+
import { fetchData, putProvider } from './utils/api';
|
|
42
|
+
import createProvidersArray from './utils/createProvidersArray';
|
|
42
43
|
import forms from './utils/forms';
|
|
43
44
|
|
|
44
45
|
export const ProvidersPage = () => {
|
|
45
|
-
const { formatMessage
|
|
46
|
+
const { formatMessage } = useIntl();
|
|
47
|
+
useFocusWhenNavigate();
|
|
48
|
+
const { notifyStatus } = useNotifyAT();
|
|
46
49
|
const queryClient = useQueryClient();
|
|
47
50
|
const { trackUsage } = useTracking();
|
|
48
|
-
const
|
|
49
|
-
const [
|
|
51
|
+
const trackUsageRef = useRef(trackUsage);
|
|
52
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
53
|
+
const [isSubmiting, setIsSubmiting] = useState(false);
|
|
54
|
+
const [providerToEditName, setProviderToEditName] = useState(null);
|
|
50
55
|
const toggleNotification = useNotification();
|
|
51
56
|
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
52
|
-
const { get, put } = useFetchClient();
|
|
53
|
-
const { formatAPIError } = useAPIErrorHandler();
|
|
54
|
-
const formatter = useCollator(locale, {
|
|
55
|
-
sensitivity: 'base',
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
useFocusWhenNavigate();
|
|
59
57
|
|
|
60
58
|
const {
|
|
61
|
-
isLoading:
|
|
59
|
+
isLoading: isLoadingForPermissions,
|
|
62
60
|
allowedActions: { canUpdate },
|
|
63
61
|
} = useRBAC({ update: PERMISSIONS.updateProviders });
|
|
64
62
|
|
|
65
|
-
const {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
const {
|
|
64
|
+
isLoading: isLoadingForData,
|
|
65
|
+
data: modifiedData,
|
|
66
|
+
isFetching,
|
|
67
|
+
} = useQuery('get-providers', () => fetchData(toggleNotification), {
|
|
68
|
+
onSuccess() {
|
|
69
|
+
notifyStatus(
|
|
70
|
+
formatMessage({
|
|
71
|
+
id: getTrad('Providers.data.loaded'),
|
|
72
|
+
defaultMessage: 'Providers have been loaded',
|
|
73
|
+
})
|
|
74
|
+
);
|
|
71
75
|
},
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
+
initialData: {},
|
|
77
|
+
});
|
|
76
78
|
|
|
77
|
-
const
|
|
78
|
-
async onSuccess() {
|
|
79
|
-
await queryClient.invalidateQueries(['users-permissions', 'providers']);
|
|
79
|
+
const isLoading = isLoadingForData || isFetching;
|
|
80
80
|
|
|
81
|
+
const submitMutation = useMutation(putProvider, {
|
|
82
|
+
async onSuccess() {
|
|
83
|
+
await queryClient.invalidateQueries('get-providers');
|
|
81
84
|
toggleNotification({
|
|
82
|
-
type: '
|
|
85
|
+
type: 'info',
|
|
83
86
|
message: { id: getTrad('notification.success.submit') },
|
|
84
87
|
});
|
|
85
88
|
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
trackUsageRef.current('didEditAuthenticationProvider');
|
|
90
|
+
setIsSubmiting(false);
|
|
88
91
|
handleToggleModal();
|
|
89
92
|
unlockApp();
|
|
90
93
|
},
|
|
91
|
-
onError(
|
|
94
|
+
onError() {
|
|
92
95
|
toggleNotification({
|
|
93
96
|
type: 'warning',
|
|
94
|
-
message:
|
|
97
|
+
message: { id: 'notification.error' },
|
|
95
98
|
});
|
|
96
|
-
|
|
97
99
|
unlockApp();
|
|
100
|
+
setIsSubmiting(false);
|
|
98
101
|
},
|
|
99
102
|
refetchActive: false,
|
|
100
103
|
});
|
|
101
104
|
|
|
102
|
-
const providers =
|
|
103
|
-
.reduce((acc, [name, provider]) => {
|
|
104
|
-
const { icon, enabled, subdomain } = provider;
|
|
105
|
-
|
|
106
|
-
acc.push({
|
|
107
|
-
name,
|
|
108
|
-
icon: icon === 'envelope' ? ['fas', 'envelope'] : ['fab', icon],
|
|
109
|
-
enabled,
|
|
110
|
-
subdomain,
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
return acc;
|
|
114
|
-
}, [])
|
|
115
|
-
.sort((a, b) => formatter.compare(a.name, b.name));
|
|
105
|
+
const providers = useMemo(() => createProvidersArray(modifiedData), [modifiedData]);
|
|
116
106
|
|
|
117
|
-
const
|
|
107
|
+
const rowCount = providers.length;
|
|
118
108
|
|
|
119
|
-
const isProviderWithSubdomain =
|
|
109
|
+
const isProviderWithSubdomain = useMemo(() => {
|
|
120
110
|
if (!providerToEditName) {
|
|
121
111
|
return false;
|
|
122
112
|
}
|
|
123
113
|
|
|
124
114
|
const providerToEdit = providers.find((obj) => obj.name === providerToEditName);
|
|
125
115
|
|
|
126
|
-
return
|
|
116
|
+
return has(providerToEdit, 'subdomain');
|
|
127
117
|
}, [providers, providerToEditName]);
|
|
128
118
|
|
|
129
|
-
const
|
|
119
|
+
const pageTitle = formatMessage({
|
|
120
|
+
id: getTrad('HeaderNav.link.providers'),
|
|
121
|
+
defaultMessage: 'Providers',
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const layoutToRender = useMemo(() => {
|
|
130
125
|
if (providerToEditName === 'email') {
|
|
131
126
|
return forms.email;
|
|
132
127
|
}
|
|
@@ -150,21 +145,20 @@ export const ProvidersPage = () => {
|
|
|
150
145
|
};
|
|
151
146
|
|
|
152
147
|
const handleSubmit = async (values) => {
|
|
148
|
+
setIsSubmiting(true);
|
|
149
|
+
|
|
153
150
|
lockApp();
|
|
154
151
|
|
|
155
|
-
|
|
152
|
+
trackUsageRef.current('willEditAuthenticationProvider');
|
|
156
153
|
|
|
157
|
-
|
|
154
|
+
const body = { ...modifiedData, [providerToEditName]: values };
|
|
155
|
+
|
|
156
|
+
submitMutation.mutate({ providers: body });
|
|
158
157
|
};
|
|
159
158
|
|
|
160
159
|
return (
|
|
161
160
|
<Layout>
|
|
162
|
-
<SettingsPageTitle
|
|
163
|
-
name={formatMessage({
|
|
164
|
-
id: getTrad('HeaderNav.link.providers'),
|
|
165
|
-
defaultMessage: 'Providers',
|
|
166
|
-
})}
|
|
167
|
-
/>
|
|
161
|
+
<SettingsPageTitle name={pageTitle} />
|
|
168
162
|
<Main>
|
|
169
163
|
<HeaderLayout
|
|
170
164
|
title={formatMessage({
|
|
@@ -172,11 +166,11 @@ export const ProvidersPage = () => {
|
|
|
172
166
|
defaultMessage: 'Providers',
|
|
173
167
|
})}
|
|
174
168
|
/>
|
|
175
|
-
{isLoading ? (
|
|
169
|
+
{isLoading || isLoadingForPermissions ? (
|
|
176
170
|
<LoadingIndicatorPage />
|
|
177
171
|
) : (
|
|
178
172
|
<ContentLayout>
|
|
179
|
-
<Table colCount={3} rowCount={
|
|
173
|
+
<Table colCount={3} rowCount={rowCount + 1}>
|
|
180
174
|
<Thead>
|
|
181
175
|
<Tr>
|
|
182
176
|
<Th>
|
|
@@ -249,9 +243,9 @@ export const ProvidersPage = () => {
|
|
|
249
243
|
)}
|
|
250
244
|
</Main>
|
|
251
245
|
<FormModal
|
|
252
|
-
initialData={
|
|
246
|
+
initialData={modifiedData[providerToEditName]}
|
|
253
247
|
isOpen={isOpen}
|
|
254
|
-
isSubmiting={
|
|
248
|
+
isSubmiting={isSubmiting}
|
|
255
249
|
layout={layoutToRender}
|
|
256
250
|
headerBreadcrumbs={[
|
|
257
251
|
formatMessage({
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import produce from 'immer';
|
|
2
|
+
import set from 'lodash/set';
|
|
3
|
+
|
|
4
|
+
const initialState = {
|
|
5
|
+
formErrors: {},
|
|
6
|
+
isLoading: true,
|
|
7
|
+
initialData: {},
|
|
8
|
+
modifiedData: {},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const reducer = (state, action) =>
|
|
12
|
+
// eslint-disable-next-line consistent-return
|
|
13
|
+
produce(state, (draftState) => {
|
|
14
|
+
switch (action.type) {
|
|
15
|
+
case 'GET_DATA': {
|
|
16
|
+
draftState.isLoading = true;
|
|
17
|
+
draftState.initialData = {};
|
|
18
|
+
draftState.modifiedData = {};
|
|
19
|
+
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
case 'GET_DATA_SUCCEEDED': {
|
|
24
|
+
draftState.isLoading = false;
|
|
25
|
+
draftState.initialData = action.data;
|
|
26
|
+
draftState.modifiedData = action.data;
|
|
27
|
+
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
case 'GET_DATA_ERROR': {
|
|
31
|
+
draftState.isLoading = true;
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
case 'ON_CHANGE': {
|
|
35
|
+
set(draftState, ['modifiedData', ...action.keys.split('.')], action.value);
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
case 'RESET_FORM': {
|
|
39
|
+
draftState.modifiedData = state.initialData;
|
|
40
|
+
draftState.formErrors = {};
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
case 'SET_ERRORS': {
|
|
44
|
+
draftState.formErrors = action.errors;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
default: {
|
|
48
|
+
return draftState;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export default reducer;
|
|
54
|
+
export { initialState };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getFetchClient } from '@strapi/helper-plugin';
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line import/prefer-default-export
|
|
4
|
+
export const fetchData = async (toggleNotification) => {
|
|
5
|
+
try {
|
|
6
|
+
const { get } = getFetchClient();
|
|
7
|
+
const { data } = await get('/users-permissions/providers');
|
|
8
|
+
|
|
9
|
+
return data;
|
|
10
|
+
} catch (err) {
|
|
11
|
+
toggleNotification({
|
|
12
|
+
type: 'warning',
|
|
13
|
+
message: { id: 'notification.error' },
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
throw new Error('error');
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const putProvider = (body) => {
|
|
21
|
+
const { put } = getFetchClient();
|
|
22
|
+
|
|
23
|
+
return put('/users-permissions/providers', body);
|
|
24
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import sortBy from 'lodash/sortBy';
|
|
2
|
+
|
|
3
|
+
const createProvidersArray = (data) => {
|
|
4
|
+
return sortBy(
|
|
5
|
+
Object.keys(data).reduce((acc, current) => {
|
|
6
|
+
const { icon: iconName, enabled, subdomain } = data[current];
|
|
7
|
+
const icon = iconName === 'envelope' ? ['fas', 'envelope'] : ['fab', iconName];
|
|
8
|
+
|
|
9
|
+
if (subdomain !== undefined) {
|
|
10
|
+
acc.push({ name: current, icon, enabled, subdomain });
|
|
11
|
+
} else {
|
|
12
|
+
acc.push({ name: current, icon, enabled });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return acc;
|
|
16
|
+
}, []),
|
|
17
|
+
'name'
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default createProvidersArray;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Box,
|
|
5
|
+
Button,
|
|
6
|
+
ContentLayout,
|
|
7
|
+
Flex,
|
|
8
|
+
Grid,
|
|
9
|
+
GridItem,
|
|
10
|
+
HeaderLayout,
|
|
11
|
+
Main,
|
|
12
|
+
Textarea,
|
|
13
|
+
TextInput,
|
|
14
|
+
Typography,
|
|
15
|
+
} from '@strapi/design-system';
|
|
16
|
+
import {
|
|
17
|
+
Form,
|
|
18
|
+
SettingsPageTitle,
|
|
19
|
+
useFetchClient,
|
|
20
|
+
useNotification,
|
|
21
|
+
useOverlayBlocker,
|
|
22
|
+
useTracking,
|
|
23
|
+
} from '@strapi/helper-plugin';
|
|
24
|
+
import { Check } from '@strapi/icons';
|
|
25
|
+
import { Formik } from 'formik';
|
|
26
|
+
import { useIntl } from 'react-intl';
|
|
27
|
+
import { useHistory } from 'react-router-dom';
|
|
28
|
+
|
|
29
|
+
import UsersPermissions from '../../components/UsersPermissions';
|
|
30
|
+
import { usePlugins } from '../../hooks';
|
|
31
|
+
import pluginId from '../../pluginId';
|
|
32
|
+
import getTrad from '../../utils/getTrad';
|
|
33
|
+
|
|
34
|
+
import { createRoleSchema } from './constants';
|
|
35
|
+
|
|
36
|
+
const CreatePage = () => {
|
|
37
|
+
const { formatMessage } = useIntl();
|
|
38
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
39
|
+
const toggleNotification = useNotification();
|
|
40
|
+
const { goBack } = useHistory();
|
|
41
|
+
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
42
|
+
const { isLoading: isLoadingPlugins, permissions, routes } = usePlugins();
|
|
43
|
+
const { trackUsage } = useTracking();
|
|
44
|
+
const permissionsRef = useRef();
|
|
45
|
+
const { post } = useFetchClient();
|
|
46
|
+
|
|
47
|
+
const handleCreateRoleSubmit = async (data) => {
|
|
48
|
+
// Set loading state
|
|
49
|
+
lockApp();
|
|
50
|
+
setIsSubmitting(true);
|
|
51
|
+
try {
|
|
52
|
+
const permissions = permissionsRef.current.getPermissions();
|
|
53
|
+
// Update role in Strapi
|
|
54
|
+
await post(`/${pluginId}/roles`, { ...data, ...permissions, users: [] });
|
|
55
|
+
// Notify success
|
|
56
|
+
trackUsage('didCreateRole');
|
|
57
|
+
toggleNotification({
|
|
58
|
+
type: 'success',
|
|
59
|
+
message: {
|
|
60
|
+
id: getTrad('Settings.roles.created'),
|
|
61
|
+
defaultMessage: 'Role created',
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
// Forcing redirecting since we don't have the id in the response
|
|
65
|
+
goBack();
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error(err);
|
|
68
|
+
toggleNotification({
|
|
69
|
+
type: 'warning',
|
|
70
|
+
message: {
|
|
71
|
+
id: 'notification.error',
|
|
72
|
+
defaultMessage: 'An error occurred',
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// Unset loading state
|
|
77
|
+
setIsSubmitting(false);
|
|
78
|
+
unlockApp();
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<Main>
|
|
83
|
+
<SettingsPageTitle name="Roles" />
|
|
84
|
+
<Formik
|
|
85
|
+
enableReinitialize
|
|
86
|
+
initialValues={{ name: '', description: '' }}
|
|
87
|
+
onSubmit={handleCreateRoleSubmit}
|
|
88
|
+
validationSchema={createRoleSchema}
|
|
89
|
+
>
|
|
90
|
+
{({ handleSubmit, values, handleChange, errors }) => (
|
|
91
|
+
<Form noValidate onSubmit={handleSubmit}>
|
|
92
|
+
<HeaderLayout
|
|
93
|
+
primaryAction={
|
|
94
|
+
!isLoadingPlugins && (
|
|
95
|
+
<Button type="submit" loading={isSubmitting} startIcon={<Check />}>
|
|
96
|
+
{formatMessage({
|
|
97
|
+
id: 'global.save',
|
|
98
|
+
defaultMessage: 'Save',
|
|
99
|
+
})}
|
|
100
|
+
</Button>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
title={formatMessage({
|
|
104
|
+
id: 'Settings.roles.create.title',
|
|
105
|
+
defaultMessage: 'Create a role',
|
|
106
|
+
})}
|
|
107
|
+
subtitle={formatMessage({
|
|
108
|
+
id: 'Settings.roles.create.description',
|
|
109
|
+
defaultMessage: 'Define the rights given to the role',
|
|
110
|
+
})}
|
|
111
|
+
/>
|
|
112
|
+
<ContentLayout>
|
|
113
|
+
<Flex direction="column" alignItems="stretch" gap={7}>
|
|
114
|
+
<Box
|
|
115
|
+
background="neutral0"
|
|
116
|
+
hasRadius
|
|
117
|
+
shadow="filterShadow"
|
|
118
|
+
paddingTop={6}
|
|
119
|
+
paddingBottom={6}
|
|
120
|
+
paddingLeft={7}
|
|
121
|
+
paddingRight={7}
|
|
122
|
+
>
|
|
123
|
+
<Flex direction="column" alignItems="stretch" gap={4}>
|
|
124
|
+
<Typography variant="delta" as="h2">
|
|
125
|
+
{formatMessage({
|
|
126
|
+
id: getTrad('EditPage.form.roles'),
|
|
127
|
+
defaultMessage: 'Role details',
|
|
128
|
+
})}
|
|
129
|
+
</Typography>
|
|
130
|
+
<Grid gap={4}>
|
|
131
|
+
<GridItem col={6}>
|
|
132
|
+
<TextInput
|
|
133
|
+
name="name"
|
|
134
|
+
value={values.name || ''}
|
|
135
|
+
onChange={handleChange}
|
|
136
|
+
label={formatMessage({
|
|
137
|
+
id: 'global.name',
|
|
138
|
+
defaultMessage: 'Name',
|
|
139
|
+
})}
|
|
140
|
+
error={
|
|
141
|
+
errors.name
|
|
142
|
+
? formatMessage({ id: errors.name, defaultMessage: 'Invalid value' })
|
|
143
|
+
: null
|
|
144
|
+
}
|
|
145
|
+
/>
|
|
146
|
+
</GridItem>
|
|
147
|
+
<GridItem col={6}>
|
|
148
|
+
<Textarea
|
|
149
|
+
id="description"
|
|
150
|
+
value={values.description || ''}
|
|
151
|
+
onChange={handleChange}
|
|
152
|
+
label={formatMessage({
|
|
153
|
+
id: 'global.description',
|
|
154
|
+
defaultMessage: 'Description',
|
|
155
|
+
})}
|
|
156
|
+
error={
|
|
157
|
+
errors.description
|
|
158
|
+
? formatMessage({
|
|
159
|
+
id: errors.description,
|
|
160
|
+
defaultMessage: 'Invalid value',
|
|
161
|
+
})
|
|
162
|
+
: null
|
|
163
|
+
}
|
|
164
|
+
/>
|
|
165
|
+
</GridItem>
|
|
166
|
+
</Grid>
|
|
167
|
+
</Flex>
|
|
168
|
+
</Box>
|
|
169
|
+
{!isLoadingPlugins && (
|
|
170
|
+
<UsersPermissions
|
|
171
|
+
ref={permissionsRef}
|
|
172
|
+
permissions={permissions}
|
|
173
|
+
routes={routes}
|
|
174
|
+
/>
|
|
175
|
+
)}
|
|
176
|
+
</Flex>
|
|
177
|
+
</ContentLayout>
|
|
178
|
+
</Form>
|
|
179
|
+
)}
|
|
180
|
+
</Formik>
|
|
181
|
+
</Main>
|
|
182
|
+
);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export default CreatePage;
|