@strapi/admin 4.7.0-exp.3d6a31eb083e9d44afcf98f68c107fb7567e5720 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/admin/src/components/Notifications/Notification/index.js +8 -1
  2. package/admin/src/hooks/index.js +2 -0
  3. package/admin/src/hooks/useLicenseLimitNotification/index.js +5 -0
  4. package/admin/src/hooks/useLicenseLimits/index.js +3 -0
  5. package/admin/src/pages/HomePage/index.js +2 -0
  6. package/admin/src/pages/SettingsPage/components/Tokens/LifeSpanInput/index.js +1 -1
  7. package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +5 -5
  8. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +1 -1
  9. package/admin/src/pages/SettingsPage/components/Tokens/TokenBox/index.js +1 -1
  10. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +4 -4
  11. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +5 -5
  12. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +2 -2
  13. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/AdminSeatInfo/index.js +5 -0
  14. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +2 -0
  15. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/utils/tableHeaders.js +4 -4
  16. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +1 -4
  17. package/admin/src/pages/SettingsPage/pages/Users/ListPage/CreateAction/index.js +24 -0
  18. package/admin/src/pages/SettingsPage/pages/Users/ListPage/ModalForm/index.js +4 -1
  19. package/admin/src/pages/SettingsPage/pages/Users/ListPage/index.js +25 -31
  20. package/admin/src/translations/ca.json +6 -6
  21. package/admin/src/translations/de.json +6 -6
  22. package/admin/src/translations/dk.json +6 -6
  23. package/admin/src/translations/en.json +209 -184
  24. package/admin/src/translations/es.json +6 -6
  25. package/admin/src/translations/eu.json +19 -19
  26. package/admin/src/translations/fr.json +6 -6
  27. package/admin/src/translations/hi.json +6 -6
  28. package/admin/src/translations/hu.json +19 -19
  29. package/admin/src/translations/ja.json +6 -6
  30. package/admin/src/translations/ko.json +6 -6
  31. package/admin/src/translations/ml.json +6 -6
  32. package/admin/src/translations/nl.json +19 -19
  33. package/admin/src/translations/pl.json +6 -6
  34. package/admin/src/translations/pt-BR.json +6 -6
  35. package/admin/src/translations/ru.json +865 -785
  36. package/admin/src/translations/sa.json +6 -6
  37. package/admin/src/translations/sk.json +2 -2
  38. package/admin/src/translations/sv.json +19 -19
  39. package/admin/src/translations/tr.json +19 -19
  40. package/admin/src/translations/zh-Hans.json +6 -6
  41. package/admin/src/translations/zh.json +19 -19
  42. package/build/4649.ffa2f59a.chunk.js +30 -0
  43. package/build/7259.cd2f7bad.chunk.js +1 -0
  44. package/build/{Admin-authenticatedApp.368164a1.chunk.js → Admin-authenticatedApp.bce108cd.chunk.js} +6 -6
  45. package/build/Admin_homePage.cec3f510.chunk.js +70 -0
  46. package/build/Admin_settingsPage.f6d02df6.chunk.js +178 -0
  47. package/build/admin-app.d3b3237b.chunk.js +112 -0
  48. package/build/admin-edit-users.f06c4a53.chunk.js +10 -0
  49. package/build/admin-users.8c9bfda4.chunk.js +11 -0
  50. package/build/audit-logs-settings-page.7be97e82.chunk.js +1 -0
  51. package/build/ca-json.59c4502c.chunk.js +1 -0
  52. package/build/de-json.dbc2cf1b.chunk.js +1 -0
  53. package/build/dk-json.52f67b15.chunk.js +1 -0
  54. package/build/en-json.e688dfe2.chunk.js +1 -0
  55. package/build/es-json.c40c57dd.chunk.js +1 -0
  56. package/build/eu-json.6702a0d2.chunk.js +1 -0
  57. package/build/fr-json.ea9ec573.chunk.js +1 -0
  58. package/build/hi-json.14a17920.chunk.js +1 -0
  59. package/build/hu-json.33172d09.chunk.js +1 -0
  60. package/build/index.html +1 -1
  61. package/build/ja-json.3008b720.chunk.js +1 -0
  62. package/build/ko-json.7d2f95b1.chunk.js +1 -0
  63. package/build/ml-json.3e69969b.chunk.js +1 -0
  64. package/build/nl-json.641782d5.chunk.js +1 -0
  65. package/build/pl-json.05814145.chunk.js +1 -0
  66. package/build/pt-BR-json.d72350de.chunk.js +1 -0
  67. package/build/ru-json.c4a4f50b.chunk.js +1 -0
  68. package/build/{runtime~main.725b20df.js → runtime~main.bc7de2d8.js} +2 -2
  69. package/build/sa-json.e5e7ccaf.chunk.js +1 -0
  70. package/build/{sk-json.7bbeb0af.chunk.js → sk-json.3529b8aa.chunk.js} +1 -1
  71. package/build/sv-json.207afc0d.chunk.js +1 -0
  72. package/build/tr-json.f1a0d19d.chunk.js +1 -0
  73. package/build/{transfer-tokens-list-page.1e15926d.chunk.js → transfer-tokens-list-page.c6f8039a.chunk.js} +1 -1
  74. package/build/zh-Hans-json.6e26e359.chunk.js +1 -0
  75. package/build/zh-json.085a34f4.chunk.js +1 -0
  76. package/ee/admin/hooks/index.js +2 -0
  77. package/ee/admin/hooks/useLicenseLimitNotification/index.js +87 -0
  78. package/ee/admin/hooks/useLicenseLimits/index.js +31 -0
  79. package/ee/admin/pages/SettingsPage/pages/ApplicationInfosPage/components/AdminSeatInfo/index.js +88 -0
  80. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/Modal/ActionBody.js +1 -1
  81. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/utils/getDisplayedFilters.js +21 -10
  82. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/utils/tableHeaders.js +1 -1
  83. package/ee/admin/pages/SettingsPage/pages/Users/ListPage/CreateAction/index.js +51 -0
  84. package/ee/server/bootstrap.js +1 -1
  85. package/ee/server/controllers/admin.js +48 -0
  86. package/ee/server/controllers/index.js +1 -0
  87. package/ee/server/controllers/user.js +95 -3
  88. package/ee/server/routes/index.js +23 -0
  89. package/ee/server/services/audit-logs.js +15 -5
  90. package/ee/server/services/index.js +2 -0
  91. package/ee/server/services/seat-enforcement.js +114 -0
  92. package/ee/server/services/user.js +234 -0
  93. package/package.json +9 -9
  94. package/server/middlewares/data-transfer.js +26 -0
  95. package/server/middlewares/index.js +1 -0
  96. package/server/routes/transfer.js +7 -9
  97. package/server/services/transfer/index.js +1 -0
  98. package/server/services/transfer/token.js +18 -3
  99. package/server/services/transfer/utils.js +38 -0
  100. package/admin/src/pages/SettingsPage/components/Tokens/FormiTokenContainer/LifeSpanInput.js +0 -95
  101. package/build/4649.b7e84a29.chunk.js +0 -30
  102. package/build/7259.3f04094f.chunk.js +0 -1
  103. package/build/Admin_homePage.1f10437f.chunk.js +0 -78
  104. package/build/Admin_settingsPage.5a329b58.chunk.js +0 -178
  105. package/build/admin-app.df9adf93.chunk.js +0 -112
  106. package/build/admin-edit-users.08a60ea2.chunk.js +0 -10
  107. package/build/admin-users.74f5629d.chunk.js +0 -11
  108. package/build/audit-logs-settings-page.bc1784fe.chunk.js +0 -1
  109. package/build/ca-json.4d999055.chunk.js +0 -1
  110. package/build/de-json.866f8a28.chunk.js +0 -1
  111. package/build/dk-json.10f7b1d1.chunk.js +0 -1
  112. package/build/en-json.8e5451b1.chunk.js +0 -1
  113. package/build/es-json.ea15c957.chunk.js +0 -1
  114. package/build/eu-json.3bc24d60.chunk.js +0 -1
  115. package/build/fr-json.e88fbdfd.chunk.js +0 -1
  116. package/build/hi-json.df3a7be2.chunk.js +0 -1
  117. package/build/hu-json.680e6eef.chunk.js +0 -1
  118. package/build/ja-json.97ee41ba.chunk.js +0 -1
  119. package/build/ko-json.4cbbf4f2.chunk.js +0 -1
  120. package/build/ml-json.e3747091.chunk.js +0 -1
  121. package/build/nl-json.371a15ee.chunk.js +0 -1
  122. package/build/pl-json.e535cbce.chunk.js +0 -1
  123. package/build/pt-BR-json.e5fafa46.chunk.js +0 -1
  124. package/build/ru-json.866f0ff1.chunk.js +0 -1
  125. package/build/sa-json.7efeb257.chunk.js +0 -1
  126. package/build/sv-json.dc40951f.chunk.js +0 -1
  127. package/build/tr-json.b79eae31.chunk.js +0 -1
  128. package/build/zh-Hans-json.30a18940.chunk.js +0 -1
  129. package/build/zh-json.49d84433.chunk.js +0 -1
@@ -67,7 +67,14 @@ const Notification = ({ dispatch, notification }) => {
67
67
  }
68
68
 
69
69
  if (title) {
70
- alertTitle = typeof title === 'string' ? title : formatMessage(title);
70
+ alertTitle =
71
+ typeof title === 'string'
72
+ ? title
73
+ : formattedMessage({
74
+ id: title?.id || title,
75
+ defaultMessage: title?.defaultMessage || title?.id || title,
76
+ values: title?.values,
77
+ });
71
78
  }
72
79
 
73
80
  return (
@@ -10,3 +10,5 @@ export { default as usePermissionsDataManager } from './usePermissionsDataManage
10
10
  export { default as useReleaseNotification } from './useReleaseNotification';
11
11
  export { default as useThemeToggle } from './useThemeToggle';
12
12
  export { default as useRegenerate } from './useRegenerate';
13
+ export { default as useLicenseLimit } from './useLicenseLimits';
14
+ export { default as useLicenseLimitNotification } from './useLicenseLimitNotification';
@@ -0,0 +1,5 @@
1
+ const useLicenseLimitNotification = () => {
2
+ return null;
3
+ };
4
+
5
+ export default useLicenseLimitNotification;
@@ -0,0 +1,3 @@
1
+ const useLicenseLimits = () => {};
2
+
3
+ export default useLicenseLimits;
@@ -10,6 +10,7 @@ import { Helmet } from 'react-helmet';
10
10
  import { useHistory } from 'react-router-dom';
11
11
  import { LoadingIndicatorPage, useGuidedTour } from '@strapi/helper-plugin';
12
12
  import { Layout, Main, Box, Grid, GridItem } from '@strapi/design-system';
13
+ import useLicenseLimitNotification from 'ee_else_ce/hooks/useLicenseLimitNotification';
13
14
  import cornerOrnamentPath from './assets/corner-ornament.svg';
14
15
  import { useModels } from '../../hooks';
15
16
  import isGuidedTourCompleted from '../../components/GuidedTour/utils/isGuidedTourCompleted';
@@ -32,6 +33,7 @@ const HomePage = () => {
32
33
  // Temporary until we develop the menu API
33
34
  const { collectionTypes, singleTypes, isLoading: isLoadingForModels } = useModels();
34
35
  const { guidedTourState, isGuidedTourVisible, isSkipped } = useGuidedTour();
36
+ useLicenseLimitNotification();
35
37
 
36
38
  const showGuidedTour =
37
39
  !isGuidedTourCompleted(guidedTourState) && isGuidedTourVisible && !isSkipped;
@@ -12,7 +12,7 @@ const LifeSpanInput = ({ token, errors, values, onChange, isCreating }) => {
12
12
  <Select
13
13
  name="lifespan"
14
14
  label={formatMessage({
15
- id: 'Settings.apiTokens.form.duration',
15
+ id: 'Settings.tokens.form.duration',
16
16
  defaultMessage: 'Token duration',
17
17
  })}
18
18
  value={values.lifespan !== null ? values.lifespan : '0'}
@@ -30,14 +30,14 @@ export const Regenerate = ({ onRegenerate, idToRegenerate, backUrl }) => {
30
30
  name="regenerate"
31
31
  >
32
32
  {formatMessage({
33
- id: 'Settings.apiTokens.regenerate',
33
+ id: 'Settings.tokens.regenerate',
34
34
  defaultMessage: 'Regenerate',
35
35
  })}
36
36
  </Button>
37
37
 
38
38
  <ConfirmDialog
39
39
  bodyText={{
40
- id: 'Settings.apiTokens.popUpWarning.message',
40
+ id: 'Settings.tokens.popUpWarning.message',
41
41
  defaultMessage: 'Are you sure you want to regenerate this token?',
42
42
  }}
43
43
  iconRightButton={<Refresh />}
@@ -46,15 +46,15 @@ export const Regenerate = ({ onRegenerate, idToRegenerate, backUrl }) => {
46
46
  onToggleDialog={() => setShowConfirmDialog(false)}
47
47
  onConfirm={handleConfirmRegeneration}
48
48
  leftButtonText={{
49
- id: 'Settings.apiTokens.Button.cancel',
49
+ id: 'Settings.tokens.Button.cancel',
50
50
  defaultMessage: 'Cancel',
51
51
  }}
52
52
  rightButtonText={{
53
- id: 'Settings.apiTokens.Button.regenerate',
53
+ id: 'Settings.tokens.Button.regenerate',
54
54
  defaultMessage: 'Regenerate',
55
55
  }}
56
56
  title={{
57
- id: 'Settings.apiTokens.RegenerateDialog.title',
57
+ id: 'Settings.tokens.RegenerateDialog.title',
58
58
  defaultMessage: 'Regenerate token',
59
59
  }}
60
60
  />
@@ -31,7 +31,7 @@ const Table = ({
31
31
  push,
32
32
  location: { pathname },
33
33
  } = useHistory();
34
- const { trackUsage } = useTracking(); // TODO: Track different types of tokens
34
+ const { trackUsage } = useTracking();
35
35
 
36
36
  const sortedTokens = tokens.sort((a, b) => {
37
37
  const comparison = a.name.localeCompare(b.name);
@@ -9,7 +9,7 @@ import { CopyToClipboard } from 'react-copy-to-clipboard';
9
9
  const TokenBox = ({ token, tokenType }) => {
10
10
  const { formatMessage } = useIntl();
11
11
  const toggleNotification = useNotification();
12
- const { trackUsage } = useTracking(); // TODO: Track different types of tokens
12
+ const { trackUsage } = useTracking();
13
13
  const trackUsageRef = useRef(trackUsage);
14
14
 
15
15
  return (
@@ -38,21 +38,21 @@ const FormApiTokenContainer = ({
38
38
  {
39
39
  value: 'read-only',
40
40
  label: {
41
- id: 'Settings.apiTokens.types.read-only',
41
+ id: 'Settings.tokens.types.read-only',
42
42
  defaultMessage: 'Read-only',
43
43
  },
44
44
  },
45
45
  {
46
46
  value: 'full-access',
47
47
  label: {
48
- id: 'Settings.apiTokens.types.full-access',
48
+ id: 'Settings.tokens.types.full-access',
49
49
  defaultMessage: 'Full access',
50
50
  },
51
51
  },
52
52
  {
53
53
  value: 'custom',
54
54
  label: {
55
- id: 'Settings.apiTokens.types.custom',
55
+ id: 'Settings.tokens.types.custom',
56
56
  defaultMessage: 'Custom',
57
57
  },
58
58
  },
@@ -107,7 +107,7 @@ const FormApiTokenContainer = ({
107
107
  values={values}
108
108
  errors={errors}
109
109
  label={{
110
- id: 'Settings.apiTokens.form.type',
110
+ id: 'Settings.tokens.form.type',
111
111
  defaultMessage: 'Token type',
112
112
  }}
113
113
  onChange={(value) => {
@@ -30,14 +30,14 @@ export const Regenerate = ({ onRegenerate, idToRegenerate }) => {
30
30
  name="regenerate"
31
31
  >
32
32
  {formatMessage({
33
- id: 'Settings.apiTokens.regenerate',
33
+ id: 'Settings.tokens.regenerate',
34
34
  defaultMessage: 'Regenerate',
35
35
  })}
36
36
  </Button>
37
37
 
38
38
  <ConfirmDialog
39
39
  bodyText={{
40
- id: 'Settings.apiTokens.popUpWarning.message',
40
+ id: 'Settings.tokens.popUpWarning.message',
41
41
  defaultMessage: 'Are you sure you want to regenerate this token?',
42
42
  }}
43
43
  iconRightButton={<Refresh />}
@@ -46,15 +46,15 @@ export const Regenerate = ({ onRegenerate, idToRegenerate }) => {
46
46
  onToggleDialog={() => setShowConfirmDialog(false)}
47
47
  onConfirm={handleConfirmRegeneration}
48
48
  leftButtonText={{
49
- id: 'Settings.apiTokens.Button.cancel',
49
+ id: 'Settings.tokens.Button.cancel',
50
50
  defaultMessage: 'Cancel',
51
51
  }}
52
52
  rightButtonText={{
53
- id: 'Settings.apiTokens.Button.regenerate',
53
+ id: 'Settings.tokens.Button.regenerate',
54
54
  defaultMessage: 'Regenerate',
55
55
  }}
56
56
  title={{
57
- id: 'Settings.apiTokens.RegenerateDialog.title',
57
+ id: 'Settings.tokens.RegenerateDialog.title',
58
58
  defaultMessage: 'Regenerate token',
59
59
  }}
60
60
  />
@@ -193,11 +193,11 @@ const ApiTokenCreateView = () => {
193
193
  type: 'success',
194
194
  message: isCreating
195
195
  ? formatMessage({
196
- id: 'notification.success.tokencreated',
196
+ id: 'notification.success.apitokencreated',
197
197
  defaultMessage: 'API Token successfully created',
198
198
  })
199
199
  : formatMessage({
200
- id: 'notification.success.tokenedited',
200
+ id: 'notification.success.apitokenedited',
201
201
  defaultMessage: 'API Token successfully edited',
202
202
  }),
203
203
  });
@@ -0,0 +1,5 @@
1
+ const AdminSeatInfo = () => {
2
+ return null;
3
+ };
4
+
5
+ export default AdminSeatInfo;
@@ -23,6 +23,7 @@ import {
23
23
  Typography,
24
24
  } from '@strapi/design-system';
25
25
  import { ExternalLink, Check } from '@strapi/icons';
26
+ import AdminSeatInfo from 'ee_else_ce/pages/SettingsPage/pages/ApplicationInfosPage/components/AdminSeatInfo';
26
27
 
27
28
  import adminPermissions from '../../../../permissions';
28
29
  import { useConfigurations } from '../../../../hooks';
@@ -195,6 +196,7 @@ const ApplicationInfosPage = () => {
195
196
  </Typography>
196
197
  <Typography as="dd">{appInfos.nodeVersion}</Typography>
197
198
  </GridItem>
199
+ <AdminSeatInfo />
198
200
  </Grid>
199
201
  </Stack>
200
202
  {canRead && data && (
@@ -4,7 +4,7 @@ const tableHeaders = [
4
4
  key: 'name',
5
5
  metadatas: {
6
6
  label: {
7
- id: 'Settings.transferTokens.ListView.headers.name',
7
+ id: 'Settings.tokens.ListView.headers.name',
8
8
  defaultMessage: 'Name',
9
9
  },
10
10
  sortable: true,
@@ -15,7 +15,7 @@ const tableHeaders = [
15
15
  key: 'description',
16
16
  metadatas: {
17
17
  label: {
18
- id: 'Settings.transferTokens.ListView.headers.description',
18
+ id: 'Settings.tokens.ListView.headers.description',
19
19
  defaultMessage: 'Description',
20
20
  },
21
21
  sortable: false,
@@ -26,7 +26,7 @@ const tableHeaders = [
26
26
  key: 'createdAt',
27
27
  metadatas: {
28
28
  label: {
29
- id: 'Settings.transferTokens.ListView.headers.createdAt',
29
+ id: 'Settings.tokens.ListView.headers.createdAt',
30
30
  defaultMessage: 'Created at',
31
31
  },
32
32
  sortable: false,
@@ -37,7 +37,7 @@ const tableHeaders = [
37
37
  key: 'lastUsedAt',
38
38
  metadatas: {
39
39
  label: {
40
- id: 'Settings.transferTokens.ListView.headers.lastUsedAt',
40
+ id: 'Settings.tokens.ListView.headers.lastUsedAt',
41
41
  defaultMessage: 'Last used',
42
42
  },
43
43
  sortable: false,
@@ -47,15 +47,12 @@ const EditPage = ({ canUpdate }) => {
47
47
  } = useRouteMatch('/settings/users/:id');
48
48
  const { push } = useHistory();
49
49
  const { setUserDisplayName } = useAppInfos();
50
-
51
50
  const toggleNotification = useNotification();
52
51
  const { lockApp, unlockApp } = useOverlayBlocker();
53
52
  useFocusWhenNavigate();
54
53
 
55
54
  const { status, data } = useQuery(['user', id], () => fetchUser(id), {
56
55
  retry: false,
57
- keepPreviousData: false,
58
- staleTime: 1000 * 20,
59
56
  onError(err) {
60
57
  const status = err.response.status;
61
58
 
@@ -109,7 +106,7 @@ const EditPage = ({ canUpdate }) => {
109
106
  actions.setErrors(fieldsErrors);
110
107
  toggleNotification({
111
108
  type: 'warning',
112
- message: get(err, 'response.data.message', 'notification.error'),
109
+ message: get(err, 'response.data.error.message', 'notification.error'),
113
110
  });
114
111
  }
115
112
 
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import PropTypes from 'prop-types';
4
+ import { Button } from '@strapi/design-system';
5
+ import { Envelop } from '@strapi/icons';
6
+
7
+ const CreateAction = ({ onClick }) => {
8
+ const { formatMessage } = useIntl();
9
+
10
+ return (
11
+ <Button onClick={onClick} startIcon={<Envelop />} size="S">
12
+ {formatMessage({
13
+ id: 'Settings.permissions.users.create',
14
+ defaultMessage: 'Invite new user',
15
+ })}
16
+ </Button>
17
+ );
18
+ };
19
+
20
+ CreateAction.propTypes = {
21
+ onClick: PropTypes.func.isRequired,
22
+ };
23
+
24
+ export default CreateAction;
@@ -49,7 +49,10 @@ const ModalForm = ({ queryName, onToggle }) => {
49
49
  {
50
50
  async onSuccess({ data }) {
51
51
  setRegistrationToken(data.data.registrationToken);
52
- await queryClient.invalidateQueries(queryName);
52
+
53
+ await queryClient.refetchQueries(queryName);
54
+ await queryClient.refetchQueries(['ee', 'license-limit-info']);
55
+
53
56
  goNext();
54
57
  setIsSubmitting(false);
55
58
  },
@@ -7,19 +7,20 @@ import {
7
7
  useNotification,
8
8
  useFocusWhenNavigate,
9
9
  NoPermissions,
10
+ useAPIErrorHandler,
10
11
  } from '@strapi/helper-plugin';
11
12
  import {
12
13
  ActionLayout,
13
14
  ContentLayout,
14
15
  HeaderLayout,
15
- Button,
16
16
  Main,
17
17
  useNotifyAT,
18
18
  } from '@strapi/design-system';
19
- import { Envelop } from '@strapi/icons';
20
19
  import { useLocation } from 'react-router-dom';
21
20
  import { useIntl } from 'react-intl';
22
21
  import { useMutation, useQuery, useQueryClient } from 'react-query';
22
+ import CreateAction from 'ee_else_ce/pages/SettingsPage/pages/Users/ListPage/CreateAction';
23
+ import useLicenseLimitNotification from 'ee_else_ce/hooks/useLicenseLimitNotification';
23
24
  import adminPermissions from '../../../../../permissions';
24
25
  import TableRows from './DynamicTable/TableRows';
25
26
  import Filters from '../../../components/Filters';
@@ -30,6 +31,7 @@ import displayedFilters from './utils/displayedFilters';
30
31
  import tableHeaders from './utils/tableHeaders';
31
32
 
32
33
  const ListPage = () => {
34
+ const { formatAPIError } = useAPIErrorHandler();
33
35
  const [isModalOpened, setIsModalOpen] = useState(false);
34
36
  const {
35
37
  allowedActions: { canCreate, canDelete, canRead },
@@ -39,6 +41,7 @@ const ListPage = () => {
39
41
  const { formatMessage } = useIntl();
40
42
  const { search } = useLocation();
41
43
  useFocusWhenNavigate();
44
+ useLicenseLimitNotification();
42
45
  const { notifyStatus } = useNotifyAT();
43
46
  const queryName = ['users', search];
44
47
 
@@ -69,13 +72,15 @@ const ListPage = () => {
69
72
 
70
73
  const { status, data, isFetching } = useQuery(queryName, () => fetchData(search, notifyLoad), {
71
74
  enabled: canRead,
72
- keepPreviousData: true,
73
75
  retry: false,
74
- staleTime: 1000 * 20,
75
- onError() {
76
+ onError(error) {
76
77
  toggleNotification({
77
78
  type: 'warning',
78
- message: { id: 'notification.error', defaultMessage: 'An error occured' },
79
+ message: {
80
+ id: 'notification.error',
81
+ message: formatAPIError(error),
82
+ defaultMessage: 'An error occured',
83
+ },
79
84
  });
80
85
  },
81
86
  });
@@ -86,17 +91,20 @@ const ListPage = () => {
86
91
 
87
92
  const deleteAllMutation = useMutation((ids) => deleteData(ids), {
88
93
  async onSuccess() {
89
- await queryClient.invalidateQueries(queryName);
94
+ await queryClient.refetchQueries(queryName);
95
+
96
+ // Toggle enabled/ disabled state on the invite button
97
+ await queryClient.refetchQueries(['ee', 'license-limit-info']);
90
98
  },
91
- onError(err) {
92
- if (err?.response?.data?.data) {
93
- toggleNotification({ type: 'warning', message: err.response.data.data });
94
- } else {
95
- toggleNotification({
96
- type: 'warning',
97
- message: { id: 'notification.error', defaultMessage: 'An error occured' },
98
- });
99
- }
99
+ onError(error) {
100
+ toggleNotification({
101
+ type: 'warning',
102
+ message: {
103
+ id: 'notification.error',
104
+ message: formatAPIError(error),
105
+ defaultMessage: 'An error occured',
106
+ },
107
+ });
100
108
  },
101
109
  });
102
110
 
@@ -104,25 +112,11 @@ const ListPage = () => {
104
112
  const isLoading =
105
113
  (status !== 'success' && status !== 'error') || (status === 'success' && isFetching);
106
114
 
107
- const createAction = canCreate ? (
108
- <Button
109
- data-testid="create-user-button"
110
- onClick={handleToggle}
111
- startIcon={<Envelop />}
112
- size="S"
113
- >
114
- {formatMessage({
115
- id: 'Settings.permissions.users.create',
116
- defaultMessage: 'Invite new user',
117
- })}
118
- </Button>
119
- ) : undefined;
120
-
121
115
  return (
122
116
  <Main aria-busy={isLoading}>
123
117
  <SettingsPageTitle name="Users" />
124
118
  <HeaderLayout
125
- primaryAction={createAction}
119
+ primaryAction={canCreate && <CreateAction onClick={handleToggle} />}
126
120
  title={title}
127
121
  subtitle={formatMessage({
128
122
  id: 'Settings.permissions.users.listview.header.subtitle',
@@ -80,16 +80,16 @@
80
80
  "Settings.PageTitle": "Configuració - {name}",
81
81
  "Settings.apiTokens.addFirstToken": "Afegeix el teu primer token d'API",
82
82
  "Settings.apiTokens.addNewToken": "Afegir nou token d'API",
83
- "Settings.apiTokens.copy.editMessage": "Per raons de seguretat, només podeu veure el seu token una vegada.",
84
- "Settings.apiTokens.copy.editTitle": "Aquest token ja no és accessible.",
85
- "Settings.apiTokens.copy.lastWarning": "Assegureu-vos de copiar aquest token, no podreu tornar-lo a veure!",
83
+ "Settings.tokens.copy.editMessage": "Per raons de seguretat, només podeu veure el seu token una vegada.",
84
+ "Settings.tokens.copy.editTitle": "Aquest token ja no és accessible.",
85
+ "Settings.tokens.copy.lastWarning": "Assegureu-vos de copiar aquest token, no podreu tornar-lo a veure!",
86
86
  "Settings.apiTokens.create": "Afegir entrada",
87
87
  "Settings.apiTokens.description": "Llista de tokens generats per consumir l'API",
88
88
  "Settings.apiTokens.emptyStateLayout": "Encara no tens cap contingut...",
89
- "Settings.apiTokens.notification.copied": "Token copiat al porta-retalls.",
89
+ "Settings.tokens.notification.copied": "Token copiat al porta-retalls.",
90
90
  "Settings.apiTokens.title": "Tokens d'API",
91
- "Settings.apiTokens.types.full-access": "Accés complet",
92
- "Settings.apiTokens.types.read-only": "Només lectura",
91
+ "Settings.tokens.types.full-access": "Accés complet",
92
+ "Settings.tokens.types.read-only": "Només lectura",
93
93
  "Settings.application.Strapi-version": "versió de Strapi",
94
94
  "Settings.application.StrapiVersion": "versió de Strapi",
95
95
  "Settings.application.description": "Informació global del panell d'administració",
@@ -80,16 +80,16 @@
80
80
  "Settings.PageTitle": "Einstellungen - {name}",
81
81
  "Settings.apiTokens.addFirstToken": "Deinen ersten API-Token hinzufügen",
82
82
  "Settings.apiTokens.addNewToken": "Neuen API-Token hinzufügen",
83
- "Settings.apiTokens.copy.editMessage": "Aus Sicherheitsgründen kannst du deinen Token nur einmal sehen.",
84
- "Settings.apiTokens.copy.editTitle": "Auf diesen Token kann nicht mehr zugegriffen werden.",
85
- "Settings.apiTokens.copy.lastWarning": "Stell sicher, dass dieser Token kopiert wurde, da du ihn nicht noch einmal sehen können wirst!",
83
+ "Settings.tokens.copy.editMessage": "Aus Sicherheitsgründen kannst du deinen Token nur einmal sehen.",
84
+ "Settings.tokens.copy.editTitle": "Auf diesen Token kann nicht mehr zugegriffen werden.",
85
+ "Settings.tokens.copy.lastWarning": "Stell sicher, dass dieser Token kopiert wurde, da du ihn nicht noch einmal sehen können wirst!",
86
86
  "Settings.apiTokens.create": "Neuen API-Token erstellen",
87
87
  "Settings.apiTokens.description": "Liste der generierten Tokens mit Zugriff auf die API",
88
88
  "Settings.apiTokens.emptyStateLayout": "Du hast noch keinen Inhalt...",
89
- "Settings.apiTokens.notification.copied": "Token wurde in die Zwischenablage kopiert.",
89
+ "Settings.tokens.notification.copied": "Token wurde in die Zwischenablage kopiert.",
90
90
  "Settings.apiTokens.title": "API-Tokens",
91
- "Settings.apiTokens.types.full-access": "Voller Zugriff",
92
- "Settings.apiTokens.types.read-only": "Nur Lesezugriff",
91
+ "Settings.tokens.types.full-access": "Voller Zugriff",
92
+ "Settings.tokens.types.read-only": "Nur Lesezugriff",
93
93
  "Settings.application.description": "Globale Informationen über die Administrationsoberfläche",
94
94
  "Settings.application.edition-title": "Aktuelle Version",
95
95
  "Settings.application.get-help": "Hilfe",
@@ -78,16 +78,16 @@
78
78
  "Settings.PageTitle": "Indstillinger - {name}",
79
79
  "Settings.apiTokens.addFirstToken": "Tilføj dit første API token",
80
80
  "Settings.apiTokens.addNewToken": "Tilføj nyt API token",
81
- "Settings.apiTokens.copy.editMessage": "Af sikkerhedsmæssige årsager, kan du kun se dit token én gang.",
82
- "Settings.apiTokens.copy.editTitle": "Dette token er ikke længere tilgængeligt.",
83
- "Settings.apiTokens.copy.lastWarning": "Kopiér dette token, du kommer ikke til at se det igen!",
81
+ "Settings.tokens.copy.editMessage": "Af sikkerhedsmæssige årsager, kan du kun se dit token én gang.",
82
+ "Settings.tokens.copy.editTitle": "Dette token er ikke længere tilgængeligt.",
83
+ "Settings.tokens.copy.lastWarning": "Kopiér dette token, du kommer ikke til at se det igen!",
84
84
  "Settings.apiTokens.create": "Tilføj element",
85
85
  "Settings.apiTokens.description": "Liste over genererede tokens til at bruge API'et",
86
86
  "Settings.apiTokens.emptyStateLayout": "Du har endnu ikke noget indhold...",
87
- "Settings.apiTokens.notification.copied": "Token er kopieret til klippebordet.",
87
+ "Settings.tokens.notification.copied": "Token er kopieret til klippebordet.",
88
88
  "Settings.apiTokens.title": "API Tokens",
89
- "Settings.apiTokens.types.full-access": "Fuld adgang",
90
- "Settings.apiTokens.types.read-only": "Read-only",
89
+ "Settings.tokens.types.full-access": "Fuld adgang",
90
+ "Settings.tokens.types.read-only": "Read-only",
91
91
  "Settings.application.description": "Se dit projekts detaljer",
92
92
  "Settings.application.edition-title": "NUVÆRENDE PLAN",
93
93
  "Settings.application.get-help": "Få hjælp",