@strapi/plugin-users-permissions 0.0.0-next.f45143c5e2a8a9d85691d0abf79a3f42024a0c71 → 0.0.0-next.f5b09a8e61e059f02784478e27c310c6290be088

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/.eslintignore +1 -2
  2. package/.eslintrc +14 -0
  3. package/admin/src/components/BoundRoute/index.js +5 -3
  4. package/admin/src/components/FormModal/Input/index.js +6 -3
  5. package/admin/src/components/FormModal/index.js +13 -10
  6. package/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.js +1 -1
  7. package/admin/src/components/Permissions/PermissionRow/SubCategory.js +26 -5
  8. package/admin/src/components/Permissions/PermissionRow/index.js +4 -2
  9. package/admin/src/components/Permissions/index.js +6 -5
  10. package/admin/src/components/Policies/index.js +3 -2
  11. package/admin/src/components/UsersPermissions/index.js +8 -5
  12. package/admin/src/{permissions.js → constants.js} +1 -3
  13. package/admin/src/contexts/UsersPermissionsContext/index.js +1 -0
  14. package/admin/src/index.js +19 -28
  15. package/admin/src/pages/AdvancedSettings/index.js +68 -52
  16. package/admin/src/pages/AdvancedSettings/utils/schema.js +1 -1
  17. package/admin/src/pages/EmailTemplates/components/EmailForm.js +14 -13
  18. package/admin/src/pages/EmailTemplates/components/EmailTable.js +9 -7
  19. package/admin/src/pages/EmailTemplates/index.js +77 -63
  20. package/admin/src/pages/EmailTemplates/utils/schema.js +1 -1
  21. package/admin/src/pages/Providers/index.js +91 -86
  22. package/admin/src/pages/Providers/utils/forms.js +1 -1
  23. package/admin/src/pages/Roles/{CreatePage/utils/schema.js → constants.js} +2 -4
  24. package/admin/src/pages/Roles/hooks/usePlugins.js +78 -0
  25. package/admin/src/pages/Roles/index.js +17 -11
  26. package/admin/src/pages/Roles/pages/CreatePage.js +199 -0
  27. package/admin/src/pages/Roles/pages/EditPage.js +220 -0
  28. package/admin/src/pages/Roles/{ListPage → pages/ListPage}/components/TableBody.js +46 -15
  29. package/admin/src/pages/Roles/{ListPage → pages/ListPage}/index.js +48 -47
  30. package/admin/src/pages/Roles/{ListPage → pages/ListPage}/utils/api.js +3 -4
  31. package/admin/src/translations/ru.json +50 -26
  32. package/admin/src/translations/zh-Hans.json +80 -80
  33. package/admin/src/utils/index.js +1 -2
  34. package/documentation/content-api.yaml +23 -15
  35. package/jest.config.front.js +2 -0
  36. package/package.json +47 -30
  37. package/packup.config.ts +42 -0
  38. package/server/bootstrap/index.js +36 -0
  39. package/server/controllers/auth.js +51 -14
  40. package/server/controllers/user.js +12 -1
  41. package/server/middlewares/rateLimit.js +41 -21
  42. package/server/register.js +7 -1
  43. package/server/services/providers-registry.js +1 -1
  44. package/server/strategies/users-permissions.js +1 -8
  45. package/.eslintrc.js +0 -14
  46. package/admin/src/hooks/index.js +0 -5
  47. package/admin/src/hooks/useFetchRole/index.js +0 -64
  48. package/admin/src/hooks/useFetchRole/reducer.js +0 -31
  49. package/admin/src/hooks/useForm/index.js +0 -70
  50. package/admin/src/hooks/useForm/reducer.js +0 -40
  51. package/admin/src/hooks/usePlugins/index.js +0 -67
  52. package/admin/src/hooks/usePlugins/init.js +0 -5
  53. package/admin/src/hooks/usePlugins/reducer.js +0 -34
  54. package/admin/src/hooks/useRolesList/index.js +0 -63
  55. package/admin/src/hooks/useRolesList/init.js +0 -5
  56. package/admin/src/hooks/useRolesList/reducer.js +0 -31
  57. package/admin/src/pages/AdvancedSettings/utils/api.js +0 -17
  58. package/admin/src/pages/EmailTemplates/utils/api.js +0 -17
  59. package/admin/src/pages/Providers/reducer.js +0 -54
  60. package/admin/src/pages/Providers/utils/api.js +0 -25
  61. package/admin/src/pages/Providers/utils/createProvidersArray.js +0 -21
  62. package/admin/src/pages/Roles/CreatePage/index.js +0 -182
  63. package/admin/src/pages/Roles/EditPage/index.js +0 -194
  64. package/admin/src/pages/Roles/EditPage/utils/schema.js +0 -9
  65. package/admin/src/pages/Roles/ProtectedCreatePage/index.js +0 -12
  66. package/admin/src/pages/Roles/ProtectedEditPage/index.js +0 -12
  67. package/admin/src/pages/Roles/ProtectedListPage/index.js +0 -15
  68. package/admin/src/utils/getRequestURL.js +0 -5
  69. package/strapi-admin.js +0 -3
package/.eslintignore CHANGED
@@ -1,2 +1 @@
1
- node_modules/
2
- .eslintrc.js
1
+ dist
package/.eslintrc ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "root": true,
3
+ "overrides": [
4
+ {
5
+ "files": ["admin/**/*"],
6
+ "extends": ["custom/front"]
7
+ },
8
+ {
9
+ "files": ["**/*"],
10
+ "excludedFiles": ["admin/**/*"],
11
+ "extends": ["custom/back"]
12
+ }
13
+ ]
14
+ }
@@ -1,10 +1,12 @@
1
1
  import React from 'react';
2
- import styled from 'styled-components';
3
- import { Flex, Box, Typography } from '@strapi/design-system';
2
+
3
+ import { Box, Flex, Typography } from '@strapi/design-system';
4
4
  import map from 'lodash/map';
5
5
  import tail from 'lodash/tail';
6
- import { useIntl } from 'react-intl';
7
6
  import PropTypes from 'prop-types';
7
+ import { useIntl } from 'react-intl';
8
+ import styled from 'styled-components';
9
+
8
10
  import getMethodColor from './getMethodColor';
9
11
 
10
12
  const MethodBox = styled(Box)`
@@ -5,9 +5,10 @@
5
5
  */
6
6
 
7
7
  import React from 'react';
8
- import { useIntl } from 'react-intl';
9
- import { ToggleInput, TextInput } from '@strapi/design-system';
8
+
9
+ import { TextInput, ToggleInput } from '@strapi/design-system';
10
10
  import PropTypes from 'prop-types';
11
+ import { useIntl } from 'react-intl';
11
12
 
12
13
  const Input = ({
13
14
  description,
@@ -23,7 +24,9 @@ const Input = ({
23
24
  }) => {
24
25
  const { formatMessage } = useIntl();
25
26
  const inputValue =
26
- name === 'noName' ? `${strapi.backendURL}/api/connect/${providerToEditName}/callback` : value;
27
+ name === 'noName'
28
+ ? `${window.strapi.backendURL}/api/connect/${providerToEditName}/callback`
29
+ : value;
27
30
 
28
31
  const label = formatMessage(
29
32
  { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
@@ -5,22 +5,23 @@
5
5
  */
6
6
 
7
7
  import React from 'react';
8
- import { useIntl } from 'react-intl';
8
+
9
9
  import {
10
10
  Button,
11
11
  Flex,
12
- Breadcrumbs,
13
- Crumb,
14
12
  Grid,
15
13
  GridItem,
16
- ModalLayout,
17
- ModalHeader,
18
- ModalFooter,
19
14
  ModalBody,
15
+ ModalFooter,
16
+ ModalHeader,
17
+ ModalLayout,
20
18
  } from '@strapi/design-system';
21
- import PropTypes from 'prop-types';
22
- import { Formik } from 'formik';
19
+ import { Breadcrumbs, Crumb } from '@strapi/design-system/v2';
23
20
  import { Form } from '@strapi/helper-plugin';
21
+ import { Formik } from 'formik';
22
+ import PropTypes from 'prop-types';
23
+ import { useIntl } from 'react-intl';
24
+
24
25
  import Input from './Input';
25
26
 
26
27
  const FormModal = ({
@@ -43,8 +44,10 @@ const FormModal = ({
43
44
  <ModalLayout onClose={onToggle} labelledBy="title">
44
45
  <ModalHeader>
45
46
  <Breadcrumbs label={headerBreadcrumbs.join(', ')}>
46
- {headerBreadcrumbs.map((crumb) => (
47
- <Crumb key={crumb}>{crumb}</Crumb>
47
+ {headerBreadcrumbs.map((crumb, index, arr) => (
48
+ <Crumb isCurrent={index === arr.length - 1} key={crumb}>
49
+ {crumb}
50
+ </Crumb>
48
51
  ))}
49
52
  </Breadcrumbs>
50
53
  </ModalHeader>
@@ -1,5 +1,5 @@
1
- import styled, { css } from 'styled-components';
2
1
  import { Box } from '@strapi/design-system';
2
+ import styled, { css } from 'styled-components';
3
3
 
4
4
  const activeCheckboxWrapperStyles = css`
5
5
  background: ${(props) => props.theme.colors.primary100};
@@ -1,13 +1,24 @@
1
1
  import React, { useCallback, useMemo } from 'react';
2
+
3
+ import {
4
+ Box,
5
+ Checkbox,
6
+ Flex,
7
+ Typography,
8
+ Grid,
9
+ GridItem,
10
+ VisuallyHidden,
11
+ } from '@strapi/design-system';
12
+ import { Cog as CogIcon } from '@strapi/icons';
2
13
  import get from 'lodash/get';
3
- import styled from 'styled-components';
4
14
  import PropTypes from 'prop-types';
5
- import { Box, Checkbox, Flex, Typography, Grid, GridItem } from '@strapi/design-system';
6
- import { Cog as CogIcon } from '@strapi/icons';
7
15
  import { useIntl } from 'react-intl';
8
- import CheckboxWrapper from './CheckboxWrapper';
16
+ import styled from 'styled-components';
17
+
9
18
  import { useUsersPermissions } from '../../../contexts/UsersPermissionsContext';
10
19
 
20
+ import CheckboxWrapper from './CheckboxWrapper';
21
+
11
22
  const Border = styled.div`
12
23
  flex: 1;
13
24
  align-self: center;
@@ -87,10 +98,20 @@ const SubCategory = ({ subCategory }) => {
87
98
  </Checkbox>
88
99
  <button
89
100
  type="button"
90
- data-testid="action-cog"
91
101
  onClick={() => onSelectedAction(action.name)}
92
102
  style={{ display: 'inline-flex', alignItems: 'center' }}
93
103
  >
104
+ <VisuallyHidden as="span">
105
+ {formatMessage(
106
+ {
107
+ id: 'app.utils.show-bound-route',
108
+ defaultMessage: 'Show bound route for {route}',
109
+ },
110
+ {
111
+ route: action.name,
112
+ }
113
+ )}
114
+ </VisuallyHidden>
94
115
  <CogIcon />
95
116
  </button>
96
117
  </CheckboxWrapper>
@@ -1,7 +1,9 @@
1
1
  import React, { useMemo } from 'react';
2
- import PropTypes from 'prop-types';
3
- import sortBy from 'lodash/sortBy';
2
+
4
3
  import { Box } from '@strapi/design-system';
4
+ import sortBy from 'lodash/sortBy';
5
+ import PropTypes from 'prop-types';
6
+
5
7
  import SubCategory from './SubCategory';
6
8
 
7
9
  const PermissionRow = ({ name, permissions }) => {
@@ -1,10 +1,13 @@
1
1
  import React, { useReducer } from 'react';
2
- import { Accordion, AccordionToggle, AccordionContent, Box, Flex } from '@strapi/design-system';
2
+
3
+ import { Accordion, AccordionContent, AccordionToggle, Flex } from '@strapi/design-system';
3
4
  import { useIntl } from 'react-intl';
5
+
4
6
  import { useUsersPermissions } from '../../contexts/UsersPermissionsContext';
5
7
  import formatPluginName from '../../utils/formatPluginName';
6
- import PermissionRow from './PermissionRow';
8
+
7
9
  import init from './init';
10
+ import PermissionRow from './PermissionRow';
8
11
  import { initialState, reducer } from './reducer';
9
12
 
10
13
  const Permissions = () => {
@@ -41,9 +44,7 @@ const Permissions = () => {
41
44
  variant={index % 2 ? 'primary' : 'secondary'}
42
45
  />
43
46
  <AccordionContent>
44
- <Box>
45
- <PermissionRow permissions={modifiedData[collapse.name]} name={collapse.name} />
46
- </Box>
47
+ <PermissionRow permissions={modifiedData[collapse.name]} name={collapse.name} />
47
48
  </AccordionContent>
48
49
  </Accordion>
49
50
  ))}
@@ -1,9 +1,10 @@
1
1
  import React from 'react';
2
- import { useIntl } from 'react-intl';
3
- import { Typography, Flex, GridItem } from '@strapi/design-system';
2
+
3
+ import { Flex, GridItem, Typography } from '@strapi/design-system';
4
4
  import get from 'lodash/get';
5
5
  import isEmpty from 'lodash/isEmpty';
6
6
  import without from 'lodash/without';
7
+ import { useIntl } from 'react-intl';
7
8
 
8
9
  import { useUsersPermissions } from '../../contexts/UsersPermissionsContext';
9
10
  import BoundRoute from '../BoundRoute';
@@ -1,13 +1,16 @@
1
- import React, { memo, useReducer, forwardRef, useImperativeHandle } from 'react';
1
+ import React, { forwardRef, memo, useImperativeHandle, useReducer } from 'react';
2
+
3
+ import { Flex, Grid, GridItem, Typography } from '@strapi/design-system';
2
4
  import PropTypes from 'prop-types';
3
- import { Typography, Flex, Grid, GridItem } from '@strapi/design-system';
4
5
  import { useIntl } from 'react-intl';
6
+
7
+ import { UsersPermissionsProvider } from '../../contexts/UsersPermissionsContext';
5
8
  import getTrad from '../../utils/getTrad';
6
- import Policies from '../Policies';
7
9
  import Permissions from '../Permissions';
8
- import reducer, { initialState } from './reducer';
9
- import { UsersPermissionsProvider } from '../../contexts/UsersPermissionsContext';
10
+ import Policies from '../Policies';
11
+
10
12
  import init from './init';
13
+ import reducer, { initialState } from './reducer';
11
14
 
12
15
  const UsersPermissions = forwardRef(({ permissions, routes }, ref) => {
13
16
  const { formatMessage } = useIntl();
@@ -1,4 +1,4 @@
1
- const pluginPermissions = {
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;
@@ -1,4 +1,5 @@
1
1
  import React, { createContext, useContext } from 'react';
2
+
2
3
  import PropTypes from 'prop-types';
3
4
 
4
5
  const UsersPermissions = createContext({});
@@ -5,9 +5,10 @@
5
5
  // Also the strapi-generate-plugins/files/admin/src/index.js needs to be updated
6
6
  // IF THE DOC IS NOT UPDATED THE PULL REQUEST WILL NOT BE MERGED
7
7
  import { prefixPluginTranslations } from '@strapi/helper-plugin';
8
+
8
9
  import pluginPkg from '../../package.json';
9
- import pluginPermissions from './permissions';
10
- import pluginId from './pluginId';
10
+
11
+ import { PERMISSIONS } from './constants';
11
12
  import getTrad from './utils/getTrad';
12
13
 
13
14
  const name = pluginPkg.strapi.name;
@@ -17,7 +18,7 @@ export default {
17
18
  // Create the plugin's settings section
18
19
  app.createSettingSection(
19
20
  {
20
- id: pluginId,
21
+ id: 'users-permissions',
21
22
  intlLabel: {
22
23
  id: getTrad('Settings.section-label'),
23
24
  defaultMessage: 'Users & Permissions plugin',
@@ -30,15 +31,13 @@ export default {
30
31
  defaultMessage: 'Roles',
31
32
  },
32
33
  id: 'roles',
33
- to: `/settings/${pluginId}/roles`,
34
+ to: `/settings/users-permissions/roles`,
34
35
  async Component() {
35
- const component = await import(
36
- /* webpackChunkName: "users-roles-settings-page" */ './pages/Roles'
37
- );
36
+ const component = await import('./pages/Roles');
38
37
 
39
38
  return component;
40
39
  },
41
- permissions: pluginPermissions.accessRoles,
40
+ permissions: PERMISSIONS.accessRoles,
42
41
  },
43
42
  {
44
43
  intlLabel: {
@@ -46,15 +45,13 @@ export default {
46
45
  defaultMessage: 'Providers',
47
46
  },
48
47
  id: 'providers',
49
- to: `/settings/${pluginId}/providers`,
48
+ to: `/settings/users-permissions/providers`,
50
49
  async Component() {
51
- const component = await import(
52
- /* webpackChunkName: "users-providers-settings-page" */ './pages/Providers'
53
- );
50
+ const component = await import('./pages/Providers');
54
51
 
55
52
  return component;
56
53
  },
57
- permissions: pluginPermissions.readProviders,
54
+ permissions: PERMISSIONS.readProviders,
58
55
  },
59
56
  {
60
57
  intlLabel: {
@@ -62,15 +59,13 @@ export default {
62
59
  defaultMessage: 'Email templates',
63
60
  },
64
61
  id: 'email-templates',
65
- to: `/settings/${pluginId}/email-templates`,
62
+ to: `/settings/users-permissions/email-templates`,
66
63
  async Component() {
67
- const component = await import(
68
- /* webpackChunkName: "users-email-settings-page" */ './pages/EmailTemplates'
69
- );
64
+ const component = await import('./pages/EmailTemplates');
70
65
 
71
66
  return component;
72
67
  },
73
- permissions: pluginPermissions.readEmailTemplates,
68
+ permissions: PERMISSIONS.readEmailTemplates,
74
69
  },
75
70
  {
76
71
  intlLabel: {
@@ -78,21 +73,19 @@ export default {
78
73
  defaultMessage: 'Advanced Settings',
79
74
  },
80
75
  id: 'advanced-settings',
81
- to: `/settings/${pluginId}/advanced-settings`,
76
+ to: `/settings/users-permissions/advanced-settings`,
82
77
  async Component() {
83
- const component = await import(
84
- /* webpackChunkName: "users-advanced-settings-page" */ './pages/AdvancedSettings'
85
- );
78
+ const component = await import('./pages/AdvancedSettings');
86
79
 
87
80
  return component;
88
81
  },
89
- permissions: pluginPermissions.readAdvancedSettings,
82
+ permissions: PERMISSIONS.readAdvancedSettings,
90
83
  },
91
84
  ]
92
85
  );
93
86
 
94
87
  app.registerPlugin({
95
- id: pluginId,
88
+ id: 'users-permissions',
96
89
  name,
97
90
  });
98
91
  },
@@ -100,12 +93,10 @@ export default {
100
93
  async registerTrads({ locales }) {
101
94
  const importedTrads = await Promise.all(
102
95
  locales.map((locale) => {
103
- return import(
104
- /* webpackChunkName: "users-permissions-translation-[request]" */ `./translations/${locale}.json`
105
- )
96
+ return import(`./translations/${locale}.json`)
106
97
  .then(({ default: data }) => {
107
98
  return {
108
- data: prefixPluginTranslations(data, pluginId),
99
+ data: prefixPluginTranslations(data, 'users-permissions'),
109
100
  locale,
110
101
  };
111
102
  })
@@ -1,41 +1,45 @@
1
- import React, { useMemo } from 'react';
2
- import { useQuery, useMutation, useQueryClient } from 'react-query';
3
- import { useIntl } from 'react-intl';
4
- import { Formik } from 'formik';
1
+ import React from 'react';
2
+
3
+ import {
4
+ Box,
5
+ Button,
6
+ ContentLayout,
7
+ Flex,
8
+ Grid,
9
+ GridItem,
10
+ HeaderLayout,
11
+ Main,
12
+ Option,
13
+ Select,
14
+ Typography,
15
+ useNotifyAT,
16
+ } from '@strapi/design-system';
5
17
  import {
6
18
  CheckPagePermissions,
7
19
  Form,
8
20
  GenericInput,
9
21
  LoadingIndicatorPage,
10
22
  SettingsPageTitle,
23
+ useAPIErrorHandler,
24
+ useFetchClient,
11
25
  useFocusWhenNavigate,
12
26
  useNotification,
13
27
  useOverlayBlocker,
14
28
  useRBAC,
15
29
  } from '@strapi/helper-plugin';
16
- import {
17
- useNotifyAT,
18
- Main,
19
- HeaderLayout,
20
- ContentLayout,
21
- Button,
22
- Box,
23
- Flex,
24
- Select,
25
- Option,
26
- Typography,
27
- Grid,
28
- GridItem,
29
- } from '@strapi/design-system';
30
30
  import { Check } from '@strapi/icons';
31
- import pluginPermissions from '../../permissions';
31
+ import { Formik } from 'formik';
32
+ import { useIntl } from 'react-intl';
33
+ import { useMutation, useQuery, useQueryClient } from 'react-query';
34
+
35
+ import { PERMISSIONS } from '../../constants';
32
36
  import { getTrad } from '../../utils';
37
+
33
38
  import layout from './utils/layout';
34
39
  import schema from './utils/schema';
35
- import { fetchData, putAdvancedSettings } from './utils/api';
36
40
 
37
41
  const ProtectedAdvancedSettingsPage = () => (
38
- <CheckPagePermissions permissions={pluginPermissions.readAdvancedSettings}>
42
+ <CheckPagePermissions permissions={PERMISSIONS.readAdvancedSettings}>
39
43
  <AdvancedSettingsPage />
40
44
  </CheckPagePermissions>
41
45
  );
@@ -46,39 +50,47 @@ const AdvancedSettingsPage = () => {
46
50
  const { lockApp, unlockApp } = useOverlayBlocker();
47
51
  const { notifyStatus } = useNotifyAT();
48
52
  const queryClient = useQueryClient();
53
+ const { get, put } = useFetchClient();
54
+ const { formatAPIError } = useAPIErrorHandler();
55
+
49
56
  useFocusWhenNavigate();
50
57
 
51
- const updatePermissions = useMemo(
52
- () => ({ update: pluginPermissions.updateAdvancedSettings }),
53
- []
54
- );
55
58
  const {
56
59
  isLoading: isLoadingForPermissions,
57
60
  allowedActions: { canUpdate },
58
- } = useRBAC(updatePermissions);
59
-
60
- const { status: isLoadingData, data } = useQuery('advanced', () => fetchData(), {
61
- onSuccess() {
62
- notifyStatus(
63
- formatMessage({
64
- id: getTrad('Form.advancedSettings.data.loaded'),
65
- defaultMessage: 'Advanced settings data has been loaded',
66
- })
67
- );
68
- },
69
- onError() {
70
- toggleNotification({
71
- type: 'warning',
72
- message: { id: getTrad('notification.error'), defaultMessage: 'An error occured' },
73
- });
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;
74
69
  },
75
- });
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
+ );
76
87
 
77
- const isLoading = isLoadingForPermissions || isLoadingData !== 'success';
88
+ const isLoading = isLoadingForPermissions || isLoadingData;
78
89
 
79
- const submitMutation = useMutation((body) => putAdvancedSettings(body), {
90
+ const submitMutation = useMutation((body) => put('/users-permissions/advanced', body), {
80
91
  async onSuccess() {
81
- await queryClient.invalidateQueries('advanced');
92
+ await queryClient.invalidateQueries(['users-permissions', 'advanced']);
93
+
82
94
  toggleNotification({
83
95
  type: 'success',
84
96
  message: { id: getTrad('notification.success.saved'), defaultMessage: 'Saved' },
@@ -86,11 +98,12 @@ const AdvancedSettingsPage = () => {
86
98
 
87
99
  unlockApp();
88
100
  },
89
- onError() {
101
+ onError(error) {
90
102
  toggleNotification({
91
103
  type: 'warning',
92
- message: { id: getTrad('notification.error'), defaultMessage: 'An error occured' },
104
+ message: formatAPIError(error),
93
105
  });
106
+
94
107
  unlockApp();
95
108
  },
96
109
  refetchActive: true,
@@ -101,9 +114,12 @@ const AdvancedSettingsPage = () => {
101
114
  const handleSubmit = async (body) => {
102
115
  lockApp();
103
116
 
104
- const urlConfirmation = body.email_confirmation ? body.email_confirmation_redirection : '';
105
-
106
- await submitMutation.mutateAsync({ ...body, email_confirmation_redirection: urlConfirmation });
117
+ submitMutation.mutate({
118
+ ...body,
119
+ email_confirmation_redirection: body.email_confirmation
120
+ ? body.email_confirmation_redirection
121
+ : '',
122
+ });
107
123
  };
108
124
 
109
125
  if (isLoading) {
@@ -143,7 +159,7 @@ const AdvancedSettingsPage = () => {
143
159
  validationSchema={schema}
144
160
  enableReinitialize
145
161
  >
146
- {({ errors, values, handleChange, isSubmitting }) => {
162
+ {({ errors, values, handleChange, isSubmitting, dirty }) => {
147
163
  return (
148
164
  <Form>
149
165
  <HeaderLayout
@@ -155,7 +171,7 @@ const AdvancedSettingsPage = () => {
155
171
  <Button
156
172
  loading={isSubmitting}
157
173
  type="submit"
158
- disabled={!canUpdate}
174
+ disabled={canUpdate ? !dirty : !canUpdate}
159
175
  startIcon={<Check />}
160
176
  size="S"
161
177
  >
@@ -1,5 +1,5 @@
1
- import * as yup from 'yup';
2
1
  import { translatedErrors } from '@strapi/helper-plugin';
2
+ import * as yup from 'yup';
3
3
 
4
4
  // eslint-disable-next-line prefer-regex-literals
5
5
  const URL_REGEX = new RegExp('(^$)|((.+:\\/\\/.*)(d*)\\/?(.*))');
@@ -1,20 +1,21 @@
1
1
  import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { useIntl } from 'react-intl';
4
- import { Form, GenericInput } from '@strapi/helper-plugin';
5
- import { Formik } from 'formik';
2
+
6
3
  import {
7
- ModalLayout,
8
- ModalHeader,
9
- ModalFooter,
10
- ModalBody,
4
+ Button,
11
5
  Grid,
12
6
  GridItem,
13
- Button,
14
- Breadcrumbs,
15
- Crumb,
7
+ ModalBody,
8
+ ModalFooter,
9
+ ModalHeader,
10
+ ModalLayout,
16
11
  Textarea,
17
12
  } from '@strapi/design-system';
13
+ import { Breadcrumbs, Crumb } from '@strapi/design-system/v2';
14
+ import { Form, GenericInput } from '@strapi/helper-plugin';
15
+ import { Formik } from 'formik';
16
+ import PropTypes from 'prop-types';
17
+ import { useIntl } from 'react-intl';
18
+
18
19
  import { getTrad } from '../../../utils';
19
20
  import schema from '../utils/schema';
20
21
 
@@ -45,7 +46,7 @@ const EmailForm = ({ template, onToggle, onSubmit }) => {
45
46
  defaultMessage: 'Edit email template',
46
47
  })}
47
48
  </Crumb>
48
- <Crumb>
49
+ <Crumb isCurrent>
49
50
  {formatMessage({ id: getTrad(template.display), defaultMessage: template.display })}
50
51
  </Crumb>
51
52
  </Breadcrumbs>
@@ -120,7 +121,7 @@ const EmailForm = ({ template, onToggle, onSubmit }) => {
120
121
  id: getTrad('PopUpForm.Email.options.message.label'),
121
122
  defaultMessage: 'Message',
122
123
  })}
123
- name="options.message"
124
+ id="options.message"
124
125
  onChange={handleChange}
125
126
  value={values.options.message}
126
127
  error={
@@ -1,20 +1,22 @@
1
1
  import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { useIntl } from 'react-intl';
2
+
4
3
  import {
4
+ Icon,
5
+ IconButton,
5
6
  Table,
6
- Thead,
7
7
  Tbody,
8
- Tr,
9
8
  Td,
10
9
  Th,
10
+ Thead,
11
+ Tr,
11
12
  Typography,
12
- IconButton,
13
- Icon,
14
13
  VisuallyHidden,
15
14
  } from '@strapi/design-system';
16
- import { Pencil, Refresh, Check } from '@strapi/icons';
17
15
  import { onRowClick, stopPropagation } from '@strapi/helper-plugin';
16
+ import { Check, Pencil, Refresh } from '@strapi/icons';
17
+ import PropTypes from 'prop-types';
18
+ import { useIntl } from 'react-intl';
19
+
18
20
  import { getTrad } from '../../../utils';
19
21
 
20
22
  const EmailTable = ({ canUpdate, onEditClick }) => {