@strapi/plugin-users-permissions 0.0.0-next.de5394e73076ccf7aca1e28dc68894e3c43f8b91 → 0.0.0-next.e037a7b2d1f48b7bd8bcd0d9400ca0f9ded8a982
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 +2 -4
- package/admin/src/{permissions.js → constants.js} +1 -3
- package/admin/src/index.js +12 -13
- package/admin/src/pages/AdvancedSettings/index.js +48 -35
- package/admin/src/pages/EmailTemplates/index.js +66 -55
- package/admin/src/pages/Providers/index.js +66 -64
- package/admin/src/{hooks → pages/Roles/hooks}/usePlugins.js +15 -8
- package/admin/src/pages/Roles/index.js +12 -9
- package/admin/src/pages/Roles/pages/CreatePage.js +190 -0
- package/admin/src/pages/Roles/pages/EditPage.js +211 -0
- package/admin/src/pages/Roles/{ListPage → pages/ListPage}/components/TableBody.js +44 -14
- package/admin/src/pages/Roles/{ListPage → pages/ListPage}/index.js +31 -32
- package/admin/src/pages/Roles/{ListPage → pages/ListPage}/utils/api.js +2 -4
- package/admin/src/translations/zh-Hans.json +80 -80
- package/admin/src/utils/index.js +0 -1
- package/documentation/content-api.yaml +1 -1
- package/jest.config.front.js +1 -1
- package/package.json +10 -10
- package/server/bootstrap/index.js +35 -0
- package/server/controllers/auth.js +46 -13
- package/server/controllers/user.js +12 -1
- package/server/middlewares/rateLimit.js +41 -21
- package/admin/src/hooks/index.js +0 -5
- package/admin/src/hooks/useFetchRole/index.js +0 -67
- package/admin/src/hooks/useFetchRole/reducer.js +0 -31
- package/admin/src/hooks/useForm/index.js +0 -70
- package/admin/src/hooks/useForm/reducer.js +0 -40
- package/admin/src/hooks/useRolesList/index.js +0 -65
- package/admin/src/hooks/useRolesList/init.js +0 -5
- package/admin/src/hooks/useRolesList/reducer.js +0 -31
- package/admin/src/pages/AdvancedSettings/utils/api.js +0 -18
- package/admin/src/pages/EmailTemplates/utils/api.js +0 -18
- package/admin/src/pages/Providers/reducer.js +0 -54
- package/admin/src/pages/Providers/utils/api.js +0 -26
- package/admin/src/pages/Providers/utils/createProvidersArray.js +0 -21
- package/admin/src/pages/Roles/CreatePage.js +0 -185
- package/admin/src/pages/Roles/EditPage.js +0 -197
- package/admin/src/pages/Roles/ProtectedCreatePage.js +0 -15
- package/admin/src/pages/Roles/ProtectedEditPage.js +0 -15
- package/admin/src/pages/Roles/ProtectedListPage.js +0 -17
- package/admin/src/utils/getRequestURL.js +0 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useReducer } from 'react';
|
|
2
2
|
|
|
3
|
-
import { Accordion, AccordionContent, AccordionToggle,
|
|
3
|
+
import { Accordion, AccordionContent, AccordionToggle, Flex } from '@strapi/design-system';
|
|
4
4
|
import { useIntl } from 'react-intl';
|
|
5
5
|
|
|
6
6
|
import { useUsersPermissions } from '../../contexts/UsersPermissionsContext';
|
|
@@ -44,9 +44,7 @@ const Permissions = () => {
|
|
|
44
44
|
variant={index % 2 ? 'primary' : 'secondary'}
|
|
45
45
|
/>
|
|
46
46
|
<AccordionContent>
|
|
47
|
-
<
|
|
48
|
-
<PermissionRow permissions={modifiedData[collapse.name]} name={collapse.name} />
|
|
49
|
-
</Box>
|
|
47
|
+
<PermissionRow permissions={modifiedData[collapse.name]} name={collapse.name} />
|
|
50
48
|
</AccordionContent>
|
|
51
49
|
</Accordion>
|
|
52
50
|
))}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
export const PERMISSIONS = {
|
|
2
2
|
// Roles
|
|
3
3
|
accessRoles: [
|
|
4
4
|
{ action: 'plugin::users-permissions.roles.create', subject: null },
|
|
@@ -27,5 +27,3 @@ const pluginPermissions = {
|
|
|
27
27
|
readProviders: [{ action: 'plugin::users-permissions.providers.read', subject: null }],
|
|
28
28
|
updateProviders: [{ action: 'plugin::users-permissions.providers.update', subject: null }],
|
|
29
29
|
};
|
|
30
|
-
|
|
31
|
-
export default pluginPermissions;
|
package/admin/src/index.js
CHANGED
|
@@ -8,8 +8,7 @@ import { prefixPluginTranslations } from '@strapi/helper-plugin';
|
|
|
8
8
|
|
|
9
9
|
import pluginPkg from '../../package.json';
|
|
10
10
|
|
|
11
|
-
import
|
|
12
|
-
import pluginId from './pluginId';
|
|
11
|
+
import { PERMISSIONS } from './constants';
|
|
13
12
|
import getTrad from './utils/getTrad';
|
|
14
13
|
|
|
15
14
|
const name = pluginPkg.strapi.name;
|
|
@@ -19,7 +18,7 @@ export default {
|
|
|
19
18
|
// Create the plugin's settings section
|
|
20
19
|
app.createSettingSection(
|
|
21
20
|
{
|
|
22
|
-
id:
|
|
21
|
+
id: 'users-permissions',
|
|
23
22
|
intlLabel: {
|
|
24
23
|
id: getTrad('Settings.section-label'),
|
|
25
24
|
defaultMessage: 'Users & Permissions plugin',
|
|
@@ -32,7 +31,7 @@ export default {
|
|
|
32
31
|
defaultMessage: 'Roles',
|
|
33
32
|
},
|
|
34
33
|
id: 'roles',
|
|
35
|
-
to: `/settings
|
|
34
|
+
to: `/settings/users-permissions/roles`,
|
|
36
35
|
async Component() {
|
|
37
36
|
const component = await import(
|
|
38
37
|
/* webpackChunkName: "users-roles-settings-page" */ './pages/Roles'
|
|
@@ -40,7 +39,7 @@ export default {
|
|
|
40
39
|
|
|
41
40
|
return component;
|
|
42
41
|
},
|
|
43
|
-
permissions:
|
|
42
|
+
permissions: PERMISSIONS.accessRoles,
|
|
44
43
|
},
|
|
45
44
|
{
|
|
46
45
|
intlLabel: {
|
|
@@ -48,7 +47,7 @@ export default {
|
|
|
48
47
|
defaultMessage: 'Providers',
|
|
49
48
|
},
|
|
50
49
|
id: 'providers',
|
|
51
|
-
to: `/settings
|
|
50
|
+
to: `/settings/users-permissions/providers`,
|
|
52
51
|
async Component() {
|
|
53
52
|
const component = await import(
|
|
54
53
|
/* webpackChunkName: "users-providers-settings-page" */ './pages/Providers'
|
|
@@ -56,7 +55,7 @@ export default {
|
|
|
56
55
|
|
|
57
56
|
return component;
|
|
58
57
|
},
|
|
59
|
-
permissions:
|
|
58
|
+
permissions: PERMISSIONS.readProviders,
|
|
60
59
|
},
|
|
61
60
|
{
|
|
62
61
|
intlLabel: {
|
|
@@ -64,7 +63,7 @@ export default {
|
|
|
64
63
|
defaultMessage: 'Email templates',
|
|
65
64
|
},
|
|
66
65
|
id: 'email-templates',
|
|
67
|
-
to: `/settings
|
|
66
|
+
to: `/settings/users-permissions/email-templates`,
|
|
68
67
|
async Component() {
|
|
69
68
|
const component = await import(
|
|
70
69
|
/* webpackChunkName: "users-email-settings-page" */ './pages/EmailTemplates'
|
|
@@ -72,7 +71,7 @@ export default {
|
|
|
72
71
|
|
|
73
72
|
return component;
|
|
74
73
|
},
|
|
75
|
-
permissions:
|
|
74
|
+
permissions: PERMISSIONS.readEmailTemplates,
|
|
76
75
|
},
|
|
77
76
|
{
|
|
78
77
|
intlLabel: {
|
|
@@ -80,7 +79,7 @@ export default {
|
|
|
80
79
|
defaultMessage: 'Advanced Settings',
|
|
81
80
|
},
|
|
82
81
|
id: 'advanced-settings',
|
|
83
|
-
to: `/settings
|
|
82
|
+
to: `/settings/users-permissions/advanced-settings`,
|
|
84
83
|
async Component() {
|
|
85
84
|
const component = await import(
|
|
86
85
|
/* webpackChunkName: "users-advanced-settings-page" */ './pages/AdvancedSettings'
|
|
@@ -88,13 +87,13 @@ export default {
|
|
|
88
87
|
|
|
89
88
|
return component;
|
|
90
89
|
},
|
|
91
|
-
permissions:
|
|
90
|
+
permissions: PERMISSIONS.readAdvancedSettings,
|
|
92
91
|
},
|
|
93
92
|
]
|
|
94
93
|
);
|
|
95
94
|
|
|
96
95
|
app.registerPlugin({
|
|
97
|
-
id:
|
|
96
|
+
id: 'users-permissions',
|
|
98
97
|
name,
|
|
99
98
|
});
|
|
100
99
|
},
|
|
@@ -107,7 +106,7 @@ export default {
|
|
|
107
106
|
)
|
|
108
107
|
.then(({ default: data }) => {
|
|
109
108
|
return {
|
|
110
|
-
data: prefixPluginTranslations(data,
|
|
109
|
+
data: prefixPluginTranslations(data, 'users-permissions'),
|
|
111
110
|
locale,
|
|
112
111
|
};
|
|
113
112
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
Box,
|
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
GenericInput,
|
|
21
21
|
LoadingIndicatorPage,
|
|
22
22
|
SettingsPageTitle,
|
|
23
|
+
useAPIErrorHandler,
|
|
24
|
+
useFetchClient,
|
|
23
25
|
useFocusWhenNavigate,
|
|
24
26
|
useNotification,
|
|
25
27
|
useOverlayBlocker,
|
|
@@ -30,15 +32,14 @@ import { Formik } from 'formik';
|
|
|
30
32
|
import { useIntl } from 'react-intl';
|
|
31
33
|
import { useMutation, useQuery, useQueryClient } from 'react-query';
|
|
32
34
|
|
|
33
|
-
import
|
|
35
|
+
import { PERMISSIONS } from '../../constants';
|
|
34
36
|
import { getTrad } from '../../utils';
|
|
35
37
|
|
|
36
|
-
import { fetchData, putAdvancedSettings } from './utils/api';
|
|
37
38
|
import layout from './utils/layout';
|
|
38
39
|
import schema from './utils/schema';
|
|
39
40
|
|
|
40
41
|
const ProtectedAdvancedSettingsPage = () => (
|
|
41
|
-
<CheckPagePermissions permissions={
|
|
42
|
+
<CheckPagePermissions permissions={PERMISSIONS.readAdvancedSettings}>
|
|
42
43
|
<AdvancedSettingsPage />
|
|
43
44
|
</CheckPagePermissions>
|
|
44
45
|
);
|
|
@@ -49,39 +50,47 @@ const AdvancedSettingsPage = () => {
|
|
|
49
50
|
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
50
51
|
const { notifyStatus } = useNotifyAT();
|
|
51
52
|
const queryClient = useQueryClient();
|
|
53
|
+
const { get, put } = useFetchClient();
|
|
54
|
+
const { formatAPIError } = useAPIErrorHandler();
|
|
55
|
+
|
|
52
56
|
useFocusWhenNavigate();
|
|
53
57
|
|
|
54
|
-
const updatePermissions = useMemo(
|
|
55
|
-
() => ({ update: pluginPermissions.updateAdvancedSettings }),
|
|
56
|
-
[]
|
|
57
|
-
);
|
|
58
58
|
const {
|
|
59
59
|
isLoading: isLoadingForPermissions,
|
|
60
60
|
allowedActions: { canUpdate },
|
|
61
|
-
} = useRBAC(
|
|
62
|
-
|
|
63
|
-
const {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
})
|
|
70
|
-
);
|
|
71
|
-
},
|
|
72
|
-
onError() {
|
|
73
|
-
toggleNotification({
|
|
74
|
-
type: 'warning',
|
|
75
|
-
message: { id: getTrad('notification.error'), defaultMessage: 'An error occured' },
|
|
76
|
-
});
|
|
61
|
+
} = useRBAC({ update: PERMISSIONS.updateAdvancedSettings });
|
|
62
|
+
|
|
63
|
+
const { isLoading: isLoadingData, data } = useQuery(
|
|
64
|
+
['users-permissions', 'advanced'],
|
|
65
|
+
async () => {
|
|
66
|
+
const { data } = await get('/users-permissions/advanced');
|
|
67
|
+
|
|
68
|
+
return data;
|
|
77
69
|
},
|
|
78
|
-
|
|
70
|
+
{
|
|
71
|
+
onSuccess() {
|
|
72
|
+
notifyStatus(
|
|
73
|
+
formatMessage({
|
|
74
|
+
id: getTrad('Form.advancedSettings.data.loaded'),
|
|
75
|
+
defaultMessage: 'Advanced settings data has been loaded',
|
|
76
|
+
})
|
|
77
|
+
);
|
|
78
|
+
},
|
|
79
|
+
onError() {
|
|
80
|
+
toggleNotification({
|
|
81
|
+
type: 'warning',
|
|
82
|
+
message: { id: getTrad('notification.error'), defaultMessage: 'An error occured' },
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
);
|
|
79
87
|
|
|
80
|
-
const isLoading = isLoadingForPermissions || isLoadingData
|
|
88
|
+
const isLoading = isLoadingForPermissions || isLoadingData;
|
|
81
89
|
|
|
82
|
-
const submitMutation = useMutation((body) =>
|
|
90
|
+
const submitMutation = useMutation((body) => put('/users-permissions/advanced', body), {
|
|
83
91
|
async onSuccess() {
|
|
84
|
-
await queryClient.invalidateQueries('advanced');
|
|
92
|
+
await queryClient.invalidateQueries(['users-permissions', 'advanced']);
|
|
93
|
+
|
|
85
94
|
toggleNotification({
|
|
86
95
|
type: 'success',
|
|
87
96
|
message: { id: getTrad('notification.success.saved'), defaultMessage: 'Saved' },
|
|
@@ -89,11 +98,12 @@ const AdvancedSettingsPage = () => {
|
|
|
89
98
|
|
|
90
99
|
unlockApp();
|
|
91
100
|
},
|
|
92
|
-
onError() {
|
|
101
|
+
onError(error) {
|
|
93
102
|
toggleNotification({
|
|
94
103
|
type: 'warning',
|
|
95
|
-
message:
|
|
104
|
+
message: formatAPIError(error),
|
|
96
105
|
});
|
|
106
|
+
|
|
97
107
|
unlockApp();
|
|
98
108
|
},
|
|
99
109
|
refetchActive: true,
|
|
@@ -104,9 +114,12 @@ const AdvancedSettingsPage = () => {
|
|
|
104
114
|
const handleSubmit = async (body) => {
|
|
105
115
|
lockApp();
|
|
106
116
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
submitMutation.mutate({
|
|
118
|
+
...body,
|
|
119
|
+
email_confirmation_redirection: body.email_confirmation
|
|
120
|
+
? body.email_confirmation_redirection
|
|
121
|
+
: '',
|
|
122
|
+
});
|
|
110
123
|
};
|
|
111
124
|
|
|
112
125
|
if (isLoading) {
|
|
@@ -146,7 +159,7 @@ const AdvancedSettingsPage = () => {
|
|
|
146
159
|
validationSchema={schema}
|
|
147
160
|
enableReinitialize
|
|
148
161
|
>
|
|
149
|
-
{({ errors, values, handleChange, isSubmitting }) => {
|
|
162
|
+
{({ errors, values, handleChange, isSubmitting, dirty }) => {
|
|
150
163
|
return (
|
|
151
164
|
<Form>
|
|
152
165
|
<HeaderLayout
|
|
@@ -158,7 +171,7 @@ const AdvancedSettingsPage = () => {
|
|
|
158
171
|
<Button
|
|
159
172
|
loading={isSubmitting}
|
|
160
173
|
type="submit"
|
|
161
|
-
disabled={!canUpdate}
|
|
174
|
+
disabled={canUpdate ? !dirty : !canUpdate}
|
|
162
175
|
startIcon={<Check />}
|
|
163
176
|
size="S"
|
|
164
177
|
>
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React 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,
|
|
8
10
|
useFocusWhenNavigate,
|
|
9
11
|
useNotification,
|
|
10
12
|
useOverlayBlocker,
|
|
@@ -14,15 +16,14 @@ import {
|
|
|
14
16
|
import { useIntl } from 'react-intl';
|
|
15
17
|
import { useMutation, useQuery, useQueryClient } from 'react-query';
|
|
16
18
|
|
|
17
|
-
import
|
|
19
|
+
import { PERMISSIONS } from '../../constants';
|
|
18
20
|
import { getTrad } from '../../utils';
|
|
19
21
|
|
|
20
22
|
import EmailForm from './components/EmailForm';
|
|
21
23
|
import EmailTable from './components/EmailTable';
|
|
22
|
-
import { fetchData, putEmailTemplate } from './utils/api';
|
|
23
24
|
|
|
24
25
|
const ProtectedEmailTemplatesPage = () => (
|
|
25
|
-
<CheckPagePermissions permissions={
|
|
26
|
+
<CheckPagePermissions permissions={PERMISSIONS.readEmailTemplates}>
|
|
26
27
|
<EmailTemplatesPage />
|
|
27
28
|
</CheckPagePermissions>
|
|
28
29
|
);
|
|
@@ -33,40 +34,46 @@ const EmailTemplatesPage = () => {
|
|
|
33
34
|
const { notifyStatus } = useNotifyAT();
|
|
34
35
|
const toggleNotification = useNotification();
|
|
35
36
|
const { lockApp, unlockApp } = useOverlayBlocker();
|
|
36
|
-
const trackUsageRef = useRef(trackUsage);
|
|
37
37
|
const queryClient = useQueryClient();
|
|
38
|
-
|
|
38
|
+
const { get, put } = useFetchClient();
|
|
39
|
+
const { formatAPIError } = useAPIErrorHandler();
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
const [templateToEdit, setTemplateToEdit] = useState(null);
|
|
41
|
+
useFocusWhenNavigate();
|
|
42
42
|
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
}, []);
|
|
43
|
+
const [isModalOpen, setIsModalOpen] = React.useState(false);
|
|
44
|
+
const [templateToEdit, setTemplateToEdit] = React.useState(null);
|
|
46
45
|
|
|
47
46
|
const {
|
|
48
47
|
isLoading: isLoadingForPermissions,
|
|
49
48
|
allowedActions: { canUpdate },
|
|
50
|
-
} = useRBAC(
|
|
51
|
-
|
|
52
|
-
const {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
})
|
|
59
|
-
);
|
|
60
|
-
},
|
|
61
|
-
onError() {
|
|
62
|
-
toggleNotification({
|
|
63
|
-
type: 'warning',
|
|
64
|
-
message: { id: 'notification.error', defaultMessage: 'An error occured' },
|
|
65
|
-
});
|
|
49
|
+
} = useRBAC({ update: PERMISSIONS.updateEmailTemplates });
|
|
50
|
+
|
|
51
|
+
const { isLoading: isLoadingData, data } = useQuery(
|
|
52
|
+
['users-permissions', 'email-templates'],
|
|
53
|
+
async () => {
|
|
54
|
+
const { data } = await get('/users-permissions/email-templates');
|
|
55
|
+
|
|
56
|
+
return data;
|
|
66
57
|
},
|
|
67
|
-
|
|
58
|
+
{
|
|
59
|
+
onSuccess() {
|
|
60
|
+
notifyStatus(
|
|
61
|
+
formatMessage({
|
|
62
|
+
id: getTrad('Email.template.data.loaded'),
|
|
63
|
+
defaultMessage: 'Email templates has been loaded',
|
|
64
|
+
})
|
|
65
|
+
);
|
|
66
|
+
},
|
|
67
|
+
onError(error) {
|
|
68
|
+
toggleNotification({
|
|
69
|
+
type: 'warning',
|
|
70
|
+
message: formatAPIError(error),
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
);
|
|
68
75
|
|
|
69
|
-
const isLoading = isLoadingForPermissions || isLoadingData
|
|
76
|
+
const isLoading = isLoadingForPermissions || isLoadingData;
|
|
70
77
|
|
|
71
78
|
const handleToggle = () => {
|
|
72
79
|
setIsModalOpen((prev) => !prev);
|
|
@@ -77,34 +84,38 @@ const EmailTemplatesPage = () => {
|
|
|
77
84
|
handleToggle();
|
|
78
85
|
};
|
|
79
86
|
|
|
80
|
-
const submitMutation = useMutation(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
87
|
+
const submitMutation = useMutation(
|
|
88
|
+
(body) => put('/users-permissions/email-templates', { 'email-templates': body }),
|
|
89
|
+
{
|
|
90
|
+
async onSuccess() {
|
|
91
|
+
await queryClient.invalidateQueries(['users-permissions', 'email-templates']);
|
|
92
|
+
|
|
93
|
+
toggleNotification({
|
|
94
|
+
type: 'success',
|
|
95
|
+
message: { id: 'notification.success.saved', defaultMessage: 'Saved' },
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
trackUsage('didEditEmailTemplates');
|
|
99
|
+
|
|
100
|
+
unlockApp();
|
|
101
|
+
handleToggle();
|
|
102
|
+
},
|
|
103
|
+
onError(error) {
|
|
104
|
+
toggleNotification({
|
|
105
|
+
type: 'warning',
|
|
106
|
+
message: formatAPIError(error),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
unlockApp();
|
|
110
|
+
},
|
|
111
|
+
refetchActive: true,
|
|
112
|
+
}
|
|
113
|
+
);
|
|
104
114
|
|
|
105
115
|
const handleSubmit = (body) => {
|
|
106
116
|
lockApp();
|
|
107
|
-
|
|
117
|
+
|
|
118
|
+
trackUsage('willEditEmailTemplates');
|
|
108
119
|
|
|
109
120
|
const editedTemplates = { ...data, [templateToEdit]: body };
|
|
110
121
|
submitMutation.mutate(editedTemplates);
|
|
@@ -133,7 +144,7 @@ const EmailTemplatesPage = () => {
|
|
|
133
144
|
}
|
|
134
145
|
|
|
135
146
|
return (
|
|
136
|
-
<Main aria-busy={
|
|
147
|
+
<Main aria-busy={submitMutation.isLoading}>
|
|
137
148
|
<SettingsPageTitle
|
|
138
149
|
name={formatMessage({
|
|
139
150
|
id: getTrad('HeaderNav.link.emailTemplates'),
|