@strapi/admin 4.6.0 → 4.7.0-beta.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 (211) hide show
  1. package/.browserslistrc +2 -1
  2. package/admin/src/assets/images/onboarding-preview.png +0 -0
  3. package/admin/src/components/AuthenticatedApp/utils/api.js +5 -4
  4. package/admin/src/components/LeftMenu/index.js +9 -3
  5. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +18 -16
  6. package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +5 -5
  7. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findLeafByPathAndReplace.js +1 -3
  8. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/schema.js +6 -5
  9. package/admin/src/content-manager/components/InputUID/index.js +4 -4
  10. package/admin/src/content-manager/components/Inputs/index.js +0 -2
  11. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +35 -14
  12. package/admin/src/content-manager/hooks/useFetchContentTypeLayout/index.js +4 -3
  13. package/admin/src/content-manager/hooks/useLazyComponents/index.js +9 -13
  14. package/admin/src/content-manager/hooks/useRelation/useRelation.js +4 -4
  15. package/admin/src/content-manager/pages/App/useModels.js +8 -3
  16. package/admin/src/content-manager/pages/App/utils/getContentTypeLinks.js +3 -2
  17. package/admin/src/content-manager/pages/ComponentSetttingsView/index.js +4 -4
  18. package/admin/src/content-manager/pages/EditSettingsView/utils/api.js +4 -2
  19. package/admin/src/content-manager/pages/ListSettingsView/utils/api.js +4 -2
  20. package/admin/src/content-manager/pages/ListView/index.js +9 -9
  21. package/admin/src/core/utils/index.js +0 -1
  22. package/admin/src/hooks/useFetchEnabledPlugins/utils/api.js +3 -2
  23. package/admin/src/hooks/useInjectReducer/index.js +1 -0
  24. package/admin/src/hooks/useInjectReducer/useInjectReducer.js +19 -0
  25. package/admin/src/hooks/useRegenerate/index.js +4 -4
  26. package/admin/src/hooks/useRolesList/index.js +5 -3
  27. package/admin/src/hooks/useSettingsMenu/utils/defaultGlobalLinks.js +7 -0
  28. package/admin/src/index.js +4 -3
  29. package/admin/src/pages/Admin/Onboarding/constants.js +46 -0
  30. package/admin/src/pages/Admin/Onboarding/index.js +161 -89
  31. package/admin/src/pages/Admin/index.js +5 -2
  32. package/admin/src/pages/ProfilePage/utils/api.js +5 -3
  33. package/admin/src/pages/SettingsPage/{pages/Users/ListPage → components}/Filters/index.js +0 -0
  34. package/admin/src/pages/SettingsPage/{pages/ApiTokens/EditView/components → components/Tokens}/FormHead/index.js +36 -19
  35. package/admin/src/pages/SettingsPage/components/Tokens/FormiTokenContainer/LifeSpanInput.js +96 -0
  36. package/admin/src/pages/SettingsPage/components/Tokens/LifeSpanInput/index.js +98 -0
  37. package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +73 -0
  38. package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/DefaultButton/index.js +1 -1
  39. package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/DeleteButton/index.js +1 -1
  40. package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/ReadButton/index.js +0 -0
  41. package/admin/src/pages/SettingsPage/{pages/ApiTokens/ListView/DynamicTable → components/Tokens/Table}/UpdateButton/index.js +0 -0
  42. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +135 -0
  43. package/admin/src/pages/SettingsPage/{pages/ApiTokens/EditView/components/ContentBox → components/Tokens/TokenBox}/index.js +17 -17
  44. package/admin/src/pages/SettingsPage/components/Tokens/TokenDescription/index.js +51 -0
  45. package/admin/src/pages/SettingsPage/components/Tokens/TokenName/index.js +46 -0
  46. package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +69 -0
  47. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +5 -3
  48. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +52 -142
  49. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +5 -1
  50. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +43 -19
  51. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +9 -16
  52. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/api.js +5 -3
  53. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +105 -0
  54. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/LoadingView/index.js +50 -0
  55. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +201 -0
  56. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/getDateOfExpiration.js +16 -0
  57. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/index.js +4 -0
  58. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +10 -0
  59. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +182 -0
  60. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/utils/tableHeaders.js +48 -0
  61. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedCreateView/index.js +14 -0
  62. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedEditView/index.js +14 -0
  63. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedListView/index.js +12 -0
  64. package/admin/src/pages/SettingsPage/pages/Users/EditPage/utils/api.js +6 -3
  65. package/admin/src/pages/SettingsPage/pages/Users/ListPage/ModalForm/index.js +9 -3
  66. package/admin/src/pages/SettingsPage/pages/Users/ListPage/index.js +1 -1
  67. package/admin/src/pages/SettingsPage/pages/Users/ListPage/utils/api.js +6 -3
  68. package/admin/src/pages/SettingsPage/pages/Users/components/SelectRoles/index.js +3 -2
  69. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/index.js +3 -2
  70. package/admin/src/pages/SettingsPage/utils/defaultRoutes.js +33 -0
  71. package/admin/src/permissions/defaultPermissions.js +8 -0
  72. package/admin/src/translations/en.json +25 -6
  73. package/admin/src/translations/eu.json +796 -0
  74. package/admin/src/translations/languageNativeNames.js +1 -0
  75. package/admin/src/translations/ru.json +9 -9
  76. package/build/1412.936ed920.chunk.js +159 -0
  77. package/build/1683.c8aa7b7c.chunk.js +268 -0
  78. package/build/19eb2dfcf2603eb55733.png +0 -0
  79. package/build/2607.2e48dbf8.chunk.js +66 -0
  80. package/build/2743.6d1632f9.chunk.js +45 -0
  81. package/build/3075.dc3894fe.chunk.js +108 -0
  82. package/build/3632.0317b618.chunk.js +138 -0
  83. package/build/4649.15cc0afe.chunk.js +30 -0
  84. package/build/{5910.a5374848.chunk.js → 4855.bd092921.chunk.js} +65 -65
  85. package/build/7259.aa68d808.chunk.js +1 -0
  86. package/build/7407.883fb1f5.chunk.js +1 -0
  87. package/build/9707.7290fd92.chunk.js +96 -0
  88. package/build/Admin-authenticatedApp.f29f6021.chunk.js +79 -0
  89. package/build/{Admin_homePage.79ab880c.chunk.js → Admin_homePage.b1730882.chunk.js} +1 -1
  90. package/build/{Admin_marketplace.eabf21b2.chunk.js → Admin_marketplace.ea0316c2.chunk.js} +2 -2
  91. package/build/Admin_pluginsPage.5c24f963.chunk.js +6 -0
  92. package/build/Admin_profilePage.59af1978.chunk.js +15 -0
  93. package/build/Admin_settingsPage.178dc6e3.chunk.js +178 -0
  94. package/build/admin-app.77a50e1f.chunk.js +112 -0
  95. package/build/admin-edit-roles-page.446b69dc.chunk.js +1 -0
  96. package/build/admin-edit-users.2ed69bfd.chunk.js +10 -0
  97. package/build/admin-users.fc003b10.chunk.js +11 -0
  98. package/build/{api-tokens-create-page.0e686c30.chunk.js → api-tokens-create-page.0db3aec1.chunk.js} +1 -1
  99. package/build/{api-tokens-edit-page.d6c7487b.chunk.js → api-tokens-edit-page.671e0e26.chunk.js} +1 -1
  100. package/build/api-tokens-list-page.7387102c.chunk.js +16 -0
  101. package/build/audit-logs-settings-page.c3dce30d.chunk.js +1 -0
  102. package/build/content-manager.42b24d46.chunk.js +1139 -0
  103. package/build/{content-type-builder-list-view.4243b2b1.chunk.js → content-type-builder-list-view.79e84b36.chunk.js} +1 -6
  104. package/build/{content-type-builder.365b6bf4.chunk.js → content-type-builder.855db321.chunk.js} +16 -15
  105. package/build/{email-settings-page.379552b1.chunk.js → email-settings-page.d1fcc7a3.chunk.js} +4 -9
  106. package/build/en-json.b0748970.chunk.js +1 -0
  107. package/build/eu-json.fceecd8b.chunk.js +1 -0
  108. package/build/i18n-settings-page.b8d8753e.chunk.js +60 -0
  109. package/build/index.html +1 -1
  110. package/build/main.1022ed01.js +4393 -0
  111. package/build/ru-json.aa5cd123.chunk.js +1 -0
  112. package/build/runtime~main.84941a97.js +2 -0
  113. package/build/sso-settings-page.b85ad080.chunk.js +41 -0
  114. package/build/transfer-tokens-create-page.16e23791.chunk.js +1 -0
  115. package/build/transfer-tokens-edit-page.3886c973.chunk.js +1 -0
  116. package/build/transfer-tokens-list-page.e8010a89.chunk.js +16 -0
  117. package/build/upload-settings.ef64bbf9.chunk.js +84 -0
  118. package/build/upload.c5730dfa.chunk.js +33 -0
  119. package/build/users-advanced-settings-page.fce9908e.chunk.js +8 -0
  120. package/build/users-email-settings-page.343d0ad2.chunk.js +23 -0
  121. package/build/users-providers-settings-page.e5a9a3f1.chunk.js +99 -0
  122. package/build/users-roles-settings-page.66312f31.chunk.js +30 -0
  123. package/build/webhook-edit-page.73e51e64.chunk.js +75 -0
  124. package/build/{webhook-list-page.f75ba3f2.chunk.js → webhook-list-page.1134f130.chunk.js} +1 -1
  125. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/ComboboxFilter/index.js +41 -0
  126. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/Modal/ActionBody.js +1 -3
  127. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/TableRows/index.js +1 -1
  128. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/hooks/useAuditLogsData.js +47 -0
  129. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/index.js +30 -31
  130. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/utils/getActionTypesDefaultMessages.js +7 -9
  131. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/utils/getDisplayedFilters.js +88 -0
  132. package/ee/admin/pages/SettingsPage/pages/Roles/ListPage/index.js +4 -2
  133. package/ee/server/migrations/audit-logs-table.js +45 -0
  134. package/ee/server/register.js +2 -0
  135. package/ee/server/services/audit-logs.js +11 -1
  136. package/package.json +30 -30
  137. package/server/bootstrap.js +2 -0
  138. package/server/config/admin-actions.js +48 -0
  139. package/server/content-types/index.js +2 -0
  140. package/server/content-types/transfer-token-permission.js +36 -0
  141. package/server/content-types/transfer-token.js +66 -0
  142. package/server/controllers/admin.js +16 -0
  143. package/server/controllers/api-token.js +4 -5
  144. package/server/controllers/index.js +1 -0
  145. package/server/controllers/transfer/index.js +13 -0
  146. package/server/controllers/transfer/runner.js +24 -0
  147. package/server/controllers/transfer/token.js +131 -0
  148. package/server/register.js +2 -9
  149. package/server/routes/index.js +2 -0
  150. package/server/routes/transfer.js +95 -0
  151. package/server/services/api-token.js +2 -3
  152. package/server/services/constants.js +6 -0
  153. package/server/services/index.js +1 -0
  154. package/server/services/transfer/index.js +6 -0
  155. package/server/services/transfer/permission.js +22 -0
  156. package/server/services/transfer/token.js +409 -0
  157. package/server/strategies/api-token.js +4 -2
  158. package/server/strategies/data-transfer.js +107 -0
  159. package/server/strategies/index.js +1 -0
  160. package/server/utils/index.d.ts +2 -0
  161. package/server/validation/api-tokens.js +1 -6
  162. package/server/validation/transfer/index.js +5 -0
  163. package/server/validation/transfer/token.js +34 -0
  164. package/admin/src/content-manager/components/InputJSON/FieldWrapper.js +0 -40
  165. package/admin/src/content-manager/components/InputJSON/Label.js +0 -35
  166. package/admin/src/content-manager/components/InputJSON/components.js +0 -36
  167. package/admin/src/content-manager/components/InputJSON/index.js +0 -223
  168. package/admin/src/content-manager/components/InputJSON/jsonlint.js +0 -680
  169. package/admin/src/core/utils/axiosInstance.js +0 -40
  170. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +0 -78
  171. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +0 -112
  172. package/build/2607.ce06608e.chunk.js +0 -66
  173. package/build/2743.dea372fb.chunk.js +0 -42
  174. package/build/3075.03ebe93d.chunk.js +0 -115
  175. package/build/3632.963ac97d.chunk.js +0 -138
  176. package/build/4318.8cb388a5.chunk.js +0 -30
  177. package/build/4656.a0d43cca.chunk.js +0 -159
  178. package/build/8633.4af74a50.chunk.js +0 -1
  179. package/build/9641.a311b612.chunk.js +0 -276
  180. package/build/9707.62831b4d.chunk.js +0 -101
  181. package/build/Admin-authenticatedApp.50dc27f9.chunk.js +0 -75
  182. package/build/Admin_pluginsPage.953e796b.chunk.js +0 -6
  183. package/build/Admin_profilePage.5c2efda5.chunk.js +0 -15
  184. package/build/Admin_settingsPage.19cfb9ca.chunk.js +0 -178
  185. package/build/admin-app.34295b50.chunk.js +0 -112
  186. package/build/admin-edit-roles-page.d50d9654.chunk.js +0 -1
  187. package/build/admin-edit-users.912b856d.chunk.js +0 -10
  188. package/build/admin-users.e36e7111.chunk.js +0 -11
  189. package/build/api-tokens-list-page.1cd86136.chunk.js +0 -16
  190. package/build/audit-logs-settings-page.308a6250.chunk.js +0 -1
  191. package/build/codemirror-addon-closebrackets.71aa4bbd.chunk.js +0 -2
  192. package/build/codemirror-addon-lint-js.405f70fb.chunk.js +0 -1
  193. package/build/codemirror-addon-lint.8487ad3d.chunk.js +0 -1
  194. package/build/codemirror-addon-mark-selection.1928c849.chunk.js +0 -1
  195. package/build/codemirror-css.359a2a4b.chunk.js +0 -345
  196. package/build/codemirror-javacript.af237b68.chunk.js +0 -1
  197. package/build/codemirror-theme.2fe63a16.chunk.js +0 -33
  198. package/build/content-manager.851f40ce.chunk.js +0 -1170
  199. package/build/en-json.38d182e5.chunk.js +0 -1
  200. package/build/i18n-settings-page.3ab28b1a.chunk.js +0 -65
  201. package/build/main.9f31732e.js +0 -4454
  202. package/build/ru-json.3b411a39.chunk.js +0 -1
  203. package/build/runtime~main.2b8e2318.js +0 -2
  204. package/build/sso-settings-page.b64a44e8.chunk.js +0 -41
  205. package/build/upload-settings.6c26ff37.chunk.js +0 -89
  206. package/build/upload.2c69d238.chunk.js +0 -38
  207. package/build/users-advanced-settings-page.c4270682.chunk.js +0 -13
  208. package/build/users-email-settings-page.60422a2f.chunk.js +0 -28
  209. package/build/users-providers-settings-page.e1834060.chunk.js +0 -104
  210. package/build/users-roles-settings-page.3ef35132.chunk.js +0 -30
  211. package/build/webhook-edit-page.c0080dc1.chunk.js +0 -75
@@ -1,15 +1,17 @@
1
1
  import omit from 'lodash/omit';
2
- import { axiosInstance } from '../../../core/utils';
2
+ import { getFetchClient } from '@strapi/helper-plugin';
3
3
 
4
4
  const fetchUser = async () => {
5
- const { data } = await axiosInstance.get('/admin/users/me');
5
+ const { get } = getFetchClient();
6
+ const { data } = await get('/admin/users/me');
6
7
 
7
8
  return data.data;
8
9
  };
9
10
 
10
11
  const putUser = async (body) => {
11
12
  const dataToSend = omit(body, ['confirmPassword', 'currentTheme']);
12
- const { data } = await axiosInstance.put('/admin/users/me', dataToSend);
13
+ const { put } = getFetchClient();
14
+ const { data } = await put('/admin/users/me', dataToSend);
13
15
 
14
16
  return { ...data.data, currentTheme: body.currentTheme };
15
17
  };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { useIntl } from 'react-intl';
3
- import { Link } from '@strapi/helper-plugin';
4
3
  import PropTypes from 'prop-types';
4
+ import { Link } from '@strapi/helper-plugin';
5
5
  import ArrowLeft from '@strapi/icons/ArrowLeft';
6
6
  import Check from '@strapi/icons/Check';
7
7
  import { Button } from '@strapi/design-system/Button';
@@ -9,29 +9,36 @@ import { HeaderLayout } from '@strapi/design-system/Layout';
9
9
  import { Stack } from '@strapi/design-system/Stack';
10
10
  import Regenerate from '../Regenerate';
11
11
 
12
- const FormHead = ({ apiToken, setApiToken, canEditInputs, canRegenerate, isSubmitting }) => {
12
+ const FormHead = ({
13
+ title,
14
+ token,
15
+ setToken,
16
+ canEditInputs,
17
+ canRegenerate,
18
+ isSubmitting,
19
+ backUrl,
20
+ regenerateUrl,
21
+ }) => {
13
22
  const { formatMessage } = useIntl();
14
23
  const handleRegenerate = (newKey) => {
15
- setApiToken({
16
- ...apiToken,
24
+ setToken({
25
+ ...token,
17
26
  accessKey: newKey,
18
27
  });
19
28
  };
20
29
 
21
30
  return (
22
31
  <HeaderLayout
23
- title={
24
- apiToken?.name ||
25
- formatMessage({
26
- id: 'Settings.apiTokens.createPage.title',
27
- defaultMessage: 'Create API Token',
28
- })
29
- }
32
+ title={token?.name || formatMessage(title)}
30
33
  primaryAction={
31
34
  canEditInputs ? (
32
35
  <Stack horizontal spacing={2}>
33
- {canRegenerate && apiToken?.id && (
34
- <Regenerate onRegenerate={handleRegenerate} idToRegenerate={apiToken?.id} />
36
+ {canRegenerate && token?.id && (
37
+ <Regenerate
38
+ backUrl={regenerateUrl}
39
+ onRegenerate={handleRegenerate}
40
+ idToRegenerate={token?.id}
41
+ />
35
42
  )}
36
43
  <Button
37
44
  disabled={isSubmitting}
@@ -48,13 +55,17 @@ const FormHead = ({ apiToken, setApiToken, canEditInputs, canRegenerate, isSubmi
48
55
  </Stack>
49
56
  ) : (
50
57
  canRegenerate &&
51
- apiToken?.id && (
52
- <Regenerate onRegenerate={handleRegenerate} idToRegenerate={apiToken?.id} />
58
+ token?.id && (
59
+ <Regenerate
60
+ onRegenerate={handleRegenerate}
61
+ idToRegenerate={token?.id}
62
+ backUrl={regenerateUrl}
63
+ />
53
64
  )
54
65
  )
55
66
  }
56
67
  navigationAction={
57
- <Link startIcon={<ArrowLeft />} to="/settings/api-tokens">
68
+ <Link startIcon={<ArrowLeft />} to={backUrl}>
58
69
  {formatMessage({
59
70
  id: 'global.back',
60
71
  defaultMessage: 'Back',
@@ -66,7 +77,7 @@ const FormHead = ({ apiToken, setApiToken, canEditInputs, canRegenerate, isSubmi
66
77
  };
67
78
 
68
79
  FormHead.propTypes = {
69
- apiToken: PropTypes.shape({
80
+ token: PropTypes.shape({
70
81
  id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
71
82
  type: PropTypes.string,
72
83
  lifespan: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
@@ -78,12 +89,18 @@ FormHead.propTypes = {
78
89
  }),
79
90
  canEditInputs: PropTypes.bool.isRequired,
80
91
  canRegenerate: PropTypes.bool.isRequired,
81
- setApiToken: PropTypes.func.isRequired,
92
+ setToken: PropTypes.func.isRequired,
82
93
  isSubmitting: PropTypes.bool.isRequired,
94
+ backUrl: PropTypes.string.isRequired,
95
+ title: PropTypes.shape({
96
+ id: PropTypes.string,
97
+ label: PropTypes.string,
98
+ }).isRequired,
99
+ regenerateUrl: PropTypes.string.isRequired,
83
100
  };
84
101
 
85
102
  FormHead.defaultProps = {
86
- apiToken: undefined,
103
+ token: undefined,
87
104
  };
88
105
 
89
106
  export default FormHead;
@@ -0,0 +1,96 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { usePersistentState } from '@strapi/helper-plugin';
5
+ import { Select, Option } from '@strapi/design-system/Select';
6
+ import { Typography } from '@strapi/design-system/Typography';
7
+ import { getDateOfExpiration } from '../../../pages/ApiTokens/EditView/utils';
8
+
9
+ const LifeSpanInput = ({ token, errors, values, onChange, disabled }) => {
10
+ const { formatMessage } = useIntl();
11
+ const [lang] = usePersistentState('strapi-admin-language', 'en');
12
+
13
+ return (
14
+ <>
15
+ <Select
16
+ name="lifespan"
17
+ label={formatMessage({
18
+ id: 'Settings.apiTokens.form.duration',
19
+ defaultMessage: 'Token duration',
20
+ })}
21
+ value={values.lifespan !== null ? values.lifespan : '0'}
22
+ error={
23
+ errors.lifespan
24
+ ? formatMessage(
25
+ errors.lifespan?.id
26
+ ? errors.lifespan
27
+ : { id: errors.lifespan, defaultMessage: errors.lifespan }
28
+ )
29
+ : null
30
+ }
31
+ onChange={(value) => {
32
+ onChange({ target: { name: 'lifespan', value } });
33
+ }}
34
+ required
35
+ disabled={disabled}
36
+ placeholder="Select"
37
+ >
38
+ <Option value="604800000">
39
+ {formatMessage({
40
+ id: 'Settings.apiTokens.duration.7-days',
41
+ defaultMessage: '7 days',
42
+ })}
43
+ </Option>
44
+ <Option value="2592000000">
45
+ {formatMessage({
46
+ id: 'Settings.apiTokens.duration.30-days',
47
+ defaultMessage: '30 days',
48
+ })}
49
+ </Option>
50
+ <Option value="7776000000">
51
+ {formatMessage({
52
+ id: 'Settings.apiTokens.duration.90-days',
53
+ defaultMessage: '90 days',
54
+ })}
55
+ </Option>
56
+ <Option value="0">
57
+ {formatMessage({
58
+ id: 'Settings.apiTokens.duration.unlimited',
59
+ defaultMessage: 'Unlimited',
60
+ })}
61
+ </Option>
62
+ </Select>
63
+ <Typography variant="pi" textColor="neutral600">
64
+ {disabled &&
65
+ `${formatMessage({
66
+ id: 'Settings.apiTokens.duration.expiration-date',
67
+ defaultMessage: 'Expiration date',
68
+ })}: ${getDateOfExpiration(token?.createdAt, parseInt(values.lifespan, 10, lang))}`}
69
+ </Typography>
70
+ </>
71
+ );
72
+ };
73
+
74
+ LifeSpanInput.propTypes = {
75
+ errors: PropTypes.string,
76
+ onChange: PropTypes.func.isRequired,
77
+ values: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
78
+ disabled: PropTypes.bool.isRequired,
79
+ token: PropTypes.shape({
80
+ id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
81
+ type: PropTypes.string,
82
+ lifespan: PropTypes.string,
83
+ name: PropTypes.string,
84
+ accessKey: PropTypes.string,
85
+ permissions: PropTypes.array,
86
+ description: PropTypes.string,
87
+ createdAt: PropTypes.string,
88
+ }),
89
+ };
90
+
91
+ LifeSpanInput.defaultProps = {
92
+ errors: {},
93
+ token: {},
94
+ };
95
+
96
+ export default LifeSpanInput;
@@ -0,0 +1,98 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { Select, Option } from '@strapi/design-system/Select';
5
+ import { Typography } from '@strapi/design-system/Typography';
6
+ import { getDateOfExpiration } from '../../../pages/ApiTokens/EditView/utils';
7
+
8
+ const LifeSpanInput = ({ token, errors, values, onChange, isCreating }) => {
9
+ const { formatMessage } = useIntl();
10
+
11
+ return (
12
+ <>
13
+ <Select
14
+ name="lifespan"
15
+ label={formatMessage({
16
+ id: 'Settings.apiTokens.form.duration',
17
+ defaultMessage: 'Token duration',
18
+ })}
19
+ value={values.lifespan !== null ? values.lifespan : '0'}
20
+ error={
21
+ errors.lifespan
22
+ ? formatMessage(
23
+ errors.lifespan?.id
24
+ ? errors.lifespan
25
+ : { id: errors.lifespan, defaultMessage: errors.lifespan }
26
+ )
27
+ : null
28
+ }
29
+ onChange={(value) => {
30
+ onChange({ target: { name: 'lifespan', value } });
31
+ }}
32
+ required
33
+ disabled={!isCreating}
34
+ placeholder="Select"
35
+ >
36
+ <Option value="604800000">
37
+ {formatMessage({
38
+ id: 'Settings.tokens.duration.7-days',
39
+ defaultMessage: '7 days',
40
+ })}
41
+ </Option>
42
+ <Option value="2592000000">
43
+ {formatMessage({
44
+ id: 'Settings.tokens.duration.30-days',
45
+ defaultMessage: '30 days',
46
+ })}
47
+ </Option>
48
+ <Option value="7776000000">
49
+ {formatMessage({
50
+ id: 'Settings.tokens.duration.90-days',
51
+ defaultMessage: '90 days',
52
+ })}
53
+ </Option>
54
+ <Option value="0">
55
+ {formatMessage({
56
+ id: 'Settings.tokens.duration.unlimited',
57
+ defaultMessage: 'Unlimited',
58
+ })}
59
+ </Option>
60
+ </Select>
61
+ <Typography variant="pi" textColor="neutral600">
62
+ {!isCreating &&
63
+ `${formatMessage({
64
+ id: 'Settings.tokens.duration.expiration-date',
65
+ defaultMessage: 'Expiration date',
66
+ })}: ${getDateOfExpiration(token?.createdAt, parseInt(values.lifespan, 10))}`}
67
+ </Typography>
68
+ </>
69
+ );
70
+ };
71
+
72
+ LifeSpanInput.propTypes = {
73
+ errors: PropTypes.shape({
74
+ lifespan: PropTypes.string,
75
+ }),
76
+ onChange: PropTypes.func.isRequired,
77
+ values: PropTypes.shape({
78
+ lifespan: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
79
+ }).isRequired,
80
+ isCreating: PropTypes.bool.isRequired,
81
+ token: PropTypes.shape({
82
+ id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
83
+ type: PropTypes.string,
84
+ lifespan: PropTypes.string,
85
+ name: PropTypes.string,
86
+ accessKey: PropTypes.string,
87
+ permissions: PropTypes.array,
88
+ description: PropTypes.string,
89
+ createdAt: PropTypes.string,
90
+ }),
91
+ };
92
+
93
+ LifeSpanInput.defaultProps = {
94
+ errors: {},
95
+ token: {},
96
+ };
97
+
98
+ export default LifeSpanInput;
@@ -0,0 +1,73 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { Button } from '@strapi/design-system/Button';
5
+ import Refresh from '@strapi/icons/Refresh';
6
+ import { ConfirmDialog } from '@strapi/helper-plugin';
7
+ import { useRegenerate } from '../../../../../hooks';
8
+
9
+ export const Regenerate = ({ onRegenerate, idToRegenerate, backUrl }) => {
10
+ const { formatMessage } = useIntl();
11
+ const [showConfirmDialog, setShowConfirmDialog] = useState(false);
12
+ const { regenerateData, isLoadingConfirmation } = useRegenerate(
13
+ backUrl,
14
+ idToRegenerate,
15
+ onRegenerate
16
+ );
17
+ const handleConfirmRegeneration = async () => {
18
+ regenerateData();
19
+ setShowConfirmDialog(false);
20
+ };
21
+
22
+ return (
23
+ <>
24
+ <Button
25
+ startIcon={<Refresh />}
26
+ type="button"
27
+ size="S"
28
+ variant="tertiary"
29
+ onClick={() => setShowConfirmDialog(true)}
30
+ name="regenerate"
31
+ >
32
+ {formatMessage({
33
+ id: 'Settings.apiTokens.regenerate',
34
+ defaultMessage: 'Regenerate',
35
+ })}
36
+ </Button>
37
+
38
+ <ConfirmDialog
39
+ bodyText={{
40
+ id: 'Settings.apiTokens.popUpWarning.message',
41
+ defaultMessage: 'Are you sure you want to regenerate this token?',
42
+ }}
43
+ iconRightButton={<Refresh />}
44
+ isConfirmButtonLoading={isLoadingConfirmation}
45
+ isOpen={showConfirmDialog}
46
+ onToggleDialog={() => setShowConfirmDialog(false)}
47
+ onConfirm={handleConfirmRegeneration}
48
+ leftButtonText={{
49
+ id: 'Settings.apiTokens.Button.cancel',
50
+ defaultMessage: 'Cancel',
51
+ }}
52
+ rightButtonText={{
53
+ id: 'Settings.apiTokens.Button.regenerate',
54
+ defaultMessage: 'Regenerate',
55
+ }}
56
+ title={{
57
+ id: 'Settings.apiTokens.RegenerateDialog.title',
58
+ defaultMessage: 'Regenerate token',
59
+ }}
60
+ />
61
+ </>
62
+ );
63
+ };
64
+
65
+ Regenerate.defaultProps = { onRegenerate() {} };
66
+
67
+ Regenerate.propTypes = {
68
+ onRegenerate: PropTypes.func,
69
+ idToRegenerate: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
70
+ backUrl: PropTypes.string.isRequired,
71
+ };
72
+
73
+ export default Regenerate;
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
2
  import { useIntl } from 'react-intl';
3
3
  import PropTypes from 'prop-types';
4
- import { Link } from '@strapi/helper-plugin';
5
4
  import { useHistory } from 'react-router-dom';
6
5
  import styled from 'styled-components';
6
+ import { Link } from '@strapi/helper-plugin';
7
7
 
8
8
  const MESSAGES_MAP = {
9
9
  edit: {
@@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
8
8
 
9
9
  const DeleteButton = ({ tokenName, onClickDelete }) => {
10
10
  const { formatMessage } = useIntl();
11
- const { trackUsage } = useTracking();
11
+ const { trackUsage } = useTracking(); // TODO: Track different types of tokens
12
12
 
13
13
  return (
14
14
  <Box paddingLeft={1} {...stopPropagation}>
@@ -0,0 +1,135 @@
1
+ import React from 'react';
2
+ import { useHistory } from 'react-router-dom';
3
+ import PropTypes from 'prop-types';
4
+ import { Typography } from '@strapi/design-system/Typography';
5
+ import { Tbody, Tr, Td } from '@strapi/design-system/Table';
6
+ import { Flex } from '@strapi/design-system/Flex';
7
+ import {
8
+ RelativeTime,
9
+ onRowClick,
10
+ pxToRem,
11
+ DynamicTable,
12
+ useQueryParams,
13
+ useTracking,
14
+ } from '@strapi/helper-plugin';
15
+ import DeleteButton from './DeleteButton';
16
+ import UpdateButton from './UpdateButton';
17
+ import ReadButton from './ReadButton';
18
+
19
+ const Table = ({ permissions, headers, contentType, isLoading, tokens, onConfirmDelete }) => {
20
+ const { canDelete, canUpdate, canRead } = permissions;
21
+ const withBulkActions = canDelete || canUpdate || canRead;
22
+ const [{ query }] = useQueryParams();
23
+ const [, sortOrder] = query ? query.sort.split(':') : 'ASC';
24
+ const {
25
+ push,
26
+ location: { pathname },
27
+ } = useHistory();
28
+ const { trackUsage } = useTracking(); // TODO: Track different types of tokens
29
+
30
+ const sortedTokens = tokens.sort((a, b) => {
31
+ const comparison = a.name.localeCompare(b.name);
32
+
33
+ return sortOrder === 'DESC' ? -comparison : comparison;
34
+ });
35
+
36
+ return (
37
+ <DynamicTable
38
+ headers={headers}
39
+ contentType={contentType}
40
+ rows={tokens}
41
+ withBulkActions={withBulkActions}
42
+ isLoading={isLoading}
43
+ onConfirmDelete={onConfirmDelete}
44
+ >
45
+ <Tbody>
46
+ {sortedTokens.map((token) => {
47
+ return (
48
+ <Tr
49
+ key={token.id}
50
+ {...onRowClick({
51
+ fn() {
52
+ trackUsage('willEditTokenFromList');
53
+ push(`${pathname}/${token.id}`);
54
+ },
55
+ condition: canUpdate,
56
+ })}
57
+ >
58
+ <Td>
59
+ <Typography textColor="neutral800" fontWeight="bold">
60
+ {token.name}
61
+ </Typography>
62
+ </Td>
63
+ <Td maxWidth={pxToRem(250)}>
64
+ <Typography textColor="neutral800" ellipsis>
65
+ {token.description}
66
+ </Typography>
67
+ </Td>
68
+ <Td>
69
+ <Typography textColor="neutral800">
70
+ <RelativeTime timestamp={new Date(token.createdAt)} />
71
+ </Typography>
72
+ </Td>
73
+ <Td>
74
+ {token.lastUsedAt && (
75
+ <Typography textColor="neutral800">
76
+ <RelativeTime timestamp={new Date(token.lastUsedAt)} />
77
+ </Typography>
78
+ )}
79
+ </Td>
80
+
81
+ {withBulkActions && (
82
+ <Td>
83
+ <Flex justifyContent="end">
84
+ {canUpdate && <UpdateButton tokenName={token.name} tokenId={token.id} />}
85
+ {!canUpdate && canRead && (
86
+ <ReadButton tokenName={token.name} tokenId={token.id} />
87
+ )}
88
+ {canDelete && (
89
+ <DeleteButton
90
+ tokenName={token.name}
91
+ onClickDelete={() => onConfirmDelete(token.id)}
92
+ />
93
+ )}
94
+ </Flex>
95
+ </Td>
96
+ )}
97
+ </Tr>
98
+ );
99
+ })}
100
+ </Tbody>
101
+ </DynamicTable>
102
+ );
103
+ };
104
+
105
+ Table.propTypes = {
106
+ tokens: PropTypes.array,
107
+ permissions: PropTypes.shape({
108
+ canRead: PropTypes.bool,
109
+ canDelete: PropTypes.bool,
110
+ canUpdate: PropTypes.bool,
111
+ }).isRequired,
112
+ headers: PropTypes.arrayOf(
113
+ PropTypes.shape({
114
+ cellFormatter: PropTypes.func,
115
+ key: PropTypes.string.isRequired,
116
+ metadatas: PropTypes.shape({
117
+ label: PropTypes.string.isRequired,
118
+ sortable: PropTypes.bool,
119
+ }).isRequired,
120
+ name: PropTypes.string.isRequired,
121
+ })
122
+ ),
123
+ contentType: PropTypes.string.isRequired,
124
+ isLoading: PropTypes.bool,
125
+ onConfirmDelete: PropTypes.func,
126
+ };
127
+
128
+ Table.defaultProps = {
129
+ tokens: [],
130
+ headers: [],
131
+ isLoading: false,
132
+ onConfirmDelete() {},
133
+ };
134
+
135
+ export default Table;
@@ -1,32 +1,32 @@
1
1
  import React, { useRef } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
+ import PropTypes from 'prop-types';
4
+ import { CopyToClipboard } from 'react-copy-to-clipboard';
3
5
  import { ContentBox, useNotification, useTracking } from '@strapi/helper-plugin';
4
6
  import { IconButton } from '@strapi/design-system/IconButton';
5
7
  import Duplicate from '@strapi/icons/Duplicate';
6
- import PropTypes from 'prop-types';
7
- import { CopyToClipboard } from 'react-copy-to-clipboard';
8
8
  import Key from '@strapi/icons/Key';
9
9
 
10
- const HeaderContentBox = ({ apiToken }) => {
10
+ const TokenBox = ({ token }) => {
11
11
  const { formatMessage } = useIntl();
12
12
  const toggleNotification = useNotification();
13
- const { trackUsage } = useTracking();
13
+ const { trackUsage } = useTracking(); // TODO: Track different types of tokens
14
14
  const trackUsageRef = useRef(trackUsage);
15
15
 
16
16
  return (
17
17
  <ContentBox
18
18
  endAction={
19
- apiToken && (
19
+ token && (
20
20
  <span style={{ alignSelf: 'start' }}>
21
21
  <CopyToClipboard
22
22
  onCopy={() => {
23
23
  trackUsageRef.current('didCopyTokenKey');
24
24
  toggleNotification({
25
25
  type: 'success',
26
- message: { id: 'Settings.apiTokens.notification.copied' },
26
+ message: { id: 'Settings.tokens.notification.copied' },
27
27
  });
28
28
  }}
29
- text={apiToken}
29
+ text={token}
30
30
  >
31
31
  <IconButton
32
32
  label={formatMessage({
@@ -42,20 +42,20 @@ const HeaderContentBox = ({ apiToken }) => {
42
42
  )
43
43
  }
44
44
  title={
45
- apiToken ||
45
+ token ||
46
46
  formatMessage({
47
- id: 'Settings.apiTokens.copy.editTitle',
47
+ id: 'Settings.tokens.copy.editTitle',
48
48
  defaultMessage: 'This token isn’t accessible anymore.',
49
49
  })
50
50
  }
51
51
  subtitle={
52
- apiToken
52
+ token
53
53
  ? formatMessage({
54
- id: 'Settings.apiTokens.copy.lastWarning',
54
+ id: 'Settings.tokens.copy.lastWarning',
55
55
  defaultMessage: 'Make sure to copy this token, you won’t be able to see it again!',
56
56
  })
57
57
  : formatMessage({
58
- id: 'Settings.apiTokens.copy.editMessage',
58
+ id: 'Settings.tokens.copy.editMessage',
59
59
  defaultMessage: 'For security reasons, you can only see your token once.',
60
60
  })
61
61
  }
@@ -65,12 +65,12 @@ const HeaderContentBox = ({ apiToken }) => {
65
65
  );
66
66
  };
67
67
 
68
- HeaderContentBox.defaultProps = {
69
- apiToken: null,
68
+ TokenBox.defaultProps = {
69
+ token: null,
70
70
  };
71
71
 
72
- HeaderContentBox.propTypes = {
73
- apiToken: PropTypes.string,
72
+ TokenBox.propTypes = {
73
+ token: PropTypes.string,
74
74
  };
75
75
 
76
- export default HeaderContentBox;
76
+ export default TokenBox;