@strapi/admin 4.4.0-rc.0 → 4.5.0-alpha.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 (203) hide show
  1. package/admin/src/StrapiApp.js +12 -4
  2. package/admin/src/components/Providers/index.js +10 -14
  3. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +11 -1
  4. package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +11 -7
  5. package/admin/src/content-manager/components/DynamicTable/CellContent/index.js +6 -5
  6. package/admin/src/content-manager/components/DynamicTable/TableRows/index.js +5 -0
  7. package/admin/src/content-manager/components/DynamicTable/index.js +1 -1
  8. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +23 -17
  9. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +123 -24
  10. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +17 -1
  11. package/admin/src/content-manager/components/FieldTypeIcon/index.js +1 -31
  12. package/admin/src/content-manager/components/Inputs/index.js +22 -36
  13. package/admin/src/content-manager/components/RelationInput/RelationInput.js +364 -0
  14. package/admin/src/content-manager/components/{SelectWrapper → RelationInput/components}/Option.js +15 -25
  15. package/admin/src/content-manager/components/RelationInput/components/Relation.js +48 -0
  16. package/admin/src/content-manager/components/RelationInput/components/RelationItem.js +52 -0
  17. package/admin/src/content-manager/components/RelationInput/components/RelationList.js +52 -0
  18. package/admin/src/content-manager/components/RelationInput/constants.js +1 -0
  19. package/admin/src/content-manager/components/RelationInput/index.js +1 -0
  20. package/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.js +250 -0
  21. package/admin/src/content-manager/components/RelationInputDataManager/constants.js +8 -0
  22. package/admin/src/content-manager/components/RelationInputDataManager/index.js +1 -0
  23. package/admin/src/content-manager/components/{SelectWrapper → RelationInputDataManager}/utils/connect.js +0 -1
  24. package/admin/src/content-manager/components/RelationInputDataManager/utils/getRelationLink.js +5 -0
  25. package/admin/src/content-manager/components/{SelectWrapper → RelationInputDataManager}/utils/index.js +1 -0
  26. package/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeRelations.js +58 -0
  27. package/admin/src/content-manager/components/{SelectWrapper → RelationInputDataManager}/utils/select.js +31 -1
  28. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +19 -2
  29. package/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js +7 -69
  30. package/admin/src/content-manager/hooks/useRelation/index.js +1 -0
  31. package/admin/src/content-manager/hooks/useRelation/useRelation.js +73 -0
  32. package/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFields.js +4 -4
  33. package/admin/src/content-manager/pages/EditSettingsView/components/FormModal.js +2 -7
  34. package/admin/src/content-manager/pages/EditSettingsView/index.js +22 -51
  35. package/admin/src/content-manager/pages/EditSettingsView/reducer.js +0 -25
  36. package/admin/src/content-manager/pages/EditView/Header/index.js +3 -90
  37. package/admin/src/content-manager/pages/EditView/Header/utils/index.js +0 -1
  38. package/admin/src/content-manager/pages/EditView/Header/utils/select.js +0 -2
  39. package/admin/src/content-manager/pages/EditView/index.js +93 -155
  40. package/admin/src/content-manager/pages/ListView/FieldPicker/index.js +0 -1
  41. package/admin/src/content-manager/pages/ListView/index.js +0 -1
  42. package/admin/src/content-manager/pages/ListViewLayoutManager/index.js +0 -1
  43. package/admin/src/content-manager/utils/formatLayoutToApi.js +1 -3
  44. package/admin/src/core/apis/index.js +0 -1
  45. package/admin/src/hooks/index.js +0 -1
  46. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +197 -215
  47. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/schema.js +1 -2
  48. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DeleteButton/index.js +0 -1
  49. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/UpdateButton/index.js +36 -3
  50. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +11 -13
  51. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +2 -3
  52. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/utils/tableHeaders.js +8 -8
  53. package/admin/src/pages/SettingsPage/pages/ApiTokens/ProtectedEditView/index.js +1 -1
  54. package/admin/src/permissions/defaultPermissions.js +6 -2
  55. package/admin/src/translations/ar.json +0 -1
  56. package/admin/src/translations/ca.json +0 -9
  57. package/admin/src/translations/cs.json +0 -2
  58. package/admin/src/translations/de.json +0 -11
  59. package/admin/src/translations/dk.json +0 -11
  60. package/admin/src/translations/en.json +0 -28
  61. package/admin/src/translations/es.json +0 -11
  62. package/admin/src/translations/fr.json +0 -11
  63. package/admin/src/translations/gu.json +0 -11
  64. package/admin/src/translations/hi.json +0 -11
  65. package/admin/src/translations/hu.json +0 -10
  66. package/admin/src/translations/id.json +0 -10
  67. package/admin/src/translations/it.json +0 -10
  68. package/admin/src/translations/ja.json +0 -11
  69. package/admin/src/translations/ko.json +0 -11
  70. package/admin/src/translations/ml.json +0 -11
  71. package/admin/src/translations/ms.json +0 -2
  72. package/admin/src/translations/nl.json +0 -11
  73. package/admin/src/translations/pl.json +0 -11
  74. package/admin/src/translations/pt-BR.json +0 -11
  75. package/admin/src/translations/pt.json +0 -1
  76. package/admin/src/translations/ru.json +0 -10
  77. package/admin/src/translations/sa.json +0 -11
  78. package/admin/src/translations/sk.json +0 -10
  79. package/admin/src/translations/sv.json +0 -9
  80. package/admin/src/translations/th.json +0 -2
  81. package/admin/src/translations/tr.json +0 -1
  82. package/admin/src/translations/uk.json +0 -2
  83. package/admin/src/translations/vi.json +0 -1
  84. package/admin/src/translations/zh-Hans.json +0 -12
  85. package/admin/src/translations/zh.json +0 -11
  86. package/build/7098.40dcd7bf.chunk.js +1 -0
  87. package/build/8851.e4ac62f2.chunk.js +158 -0
  88. package/build/{8773.c06c24c0.chunk.js → 9311.7cc03f29.chunk.js} +291 -108
  89. package/build/{Admin-authenticatedApp.9dec5230.chunk.js → Admin-authenticatedApp.e39f36c9.chunk.js} +3 -3
  90. package/build/{Admin_homePage.6d5e3236.chunk.js → Admin_homePage.118926e0.chunk.js} +1 -1
  91. package/build/{Admin_profilePage.da32abbc.chunk.js → Admin_profilePage.9d50ac44.chunk.js} +1 -1
  92. package/build/{Admin_settingsPage.98e2a62b.chunk.js → Admin_settingsPage.98a711e5.chunk.js} +16 -16
  93. package/build/admin-app.4f7618a9.chunk.js +112 -0
  94. package/build/admin-edit-roles-page.554ba3fa.chunk.js +1 -0
  95. package/build/api-tokens-create-page.4c262d6e.chunk.js +1 -0
  96. package/build/api-tokens-edit-page.10a9d368.chunk.js +1 -0
  97. package/build/api-tokens-list-page.442c9f3c.chunk.js +15 -0
  98. package/build/{ar-json.d4cb26d9.chunk.js → ar-json.3489463d.chunk.js} +1 -1
  99. package/build/{ca-json.d16c1d28.chunk.js → ca-json.a16899ae.chunk.js} +1 -1
  100. package/build/content-manager.7d57c9d1.chunk.js +1200 -0
  101. package/build/content-type-builder-list-view.8cc534e0.chunk.js +194 -0
  102. package/build/content-type-builder-translation-en-json.201bfb78.chunk.js +1 -0
  103. package/build/content-type-builder.684df7a4.chunk.js +142 -0
  104. package/build/{cs-json.c8f28ba8.chunk.js → cs-json.ce49da5c.chunk.js} +1 -1
  105. package/build/{de-json.a9b514dc.chunk.js → de-json.aa6026b3.chunk.js} +1 -1
  106. package/build/{dk-json.09e8d145.chunk.js → dk-json.fac2bcfb.chunk.js} +1 -1
  107. package/build/en-json.0c69c7d7.chunk.js +1 -0
  108. package/build/{es-json.3a9c7c09.chunk.js → es-json.d672e181.chunk.js} +1 -1
  109. package/build/{fr-json.4ed1fc2c.chunk.js → fr-json.71a16175.chunk.js} +1 -1
  110. package/build/{gu-json.d8311297.chunk.js → gu-json.ca345cd1.chunk.js} +1 -1
  111. package/build/{hi-json.0edb8d29.chunk.js → hi-json.50c7e6d4.chunk.js} +1 -1
  112. package/build/{hu-json.7855529a.chunk.js → hu-json.e0521dcc.chunk.js} +1 -1
  113. package/build/{id-json.df9618f2.chunk.js → id-json.4b1ff8d6.chunk.js} +1 -1
  114. package/build/index.html +1 -1
  115. package/build/{it-json.a21bf078.chunk.js → it-json.86bac220.chunk.js} +1 -1
  116. package/build/{ja-json.7b0d9067.chunk.js → ja-json.4e44e36b.chunk.js} +1 -1
  117. package/build/{ko-json.983c1f8f.chunk.js → ko-json.1003756e.chunk.js} +1 -1
  118. package/build/main.b47db1a3.js +9337 -0
  119. package/build/{ml-json.8dd021c8.chunk.js → ml-json.c7774425.chunk.js} +1 -1
  120. package/build/{ms-json.836ed013.chunk.js → ms-json.ed51e902.chunk.js} +1 -1
  121. package/build/{nl-json.29d2eb37.chunk.js → nl-json.f58ea235.chunk.js} +1 -1
  122. package/build/{pl-json.1f04f00c.chunk.js → pl-json.fed96aba.chunk.js} +1 -1
  123. package/build/{pt-BR-json.b4bc8efe.chunk.js → pt-BR-json.073799ab.chunk.js} +1 -1
  124. package/build/{pt-json.c23020ab.chunk.js → pt-json.3161ca22.chunk.js} +1 -1
  125. package/build/{ru-json.7ab40ccf.chunk.js → ru-json.7ad2cbbf.chunk.js} +1 -1
  126. package/build/{runtime~main.4204f341.js → runtime~main.feeac6d3.js} +1 -1
  127. package/build/{sa-json.c5a9f4ea.chunk.js → sa-json.f0f704f0.chunk.js} +1 -1
  128. package/build/{sk-json.e4c24c4e.chunk.js → sk-json.a848961b.chunk.js} +1 -1
  129. package/build/sso-settings-page.445184e0.chunk.js +1 -0
  130. package/build/{sv-json.c3f471ae.chunk.js → sv-json.b038acbe.chunk.js} +1 -1
  131. package/build/{th-json.a59ffb32.chunk.js → th-json.72e8de3d.chunk.js} +1 -1
  132. package/build/{tr-json.276e59fe.chunk.js → tr-json.9c44ea0c.chunk.js} +1 -1
  133. package/build/{uk-json.5b5b9c27.chunk.js → uk-json.c4cd2e24.chunk.js} +1 -1
  134. package/build/{vi-json.bf3424be.chunk.js → vi-json.f7890025.chunk.js} +1 -1
  135. package/build/{webhook-edit-page.9e46fc3f.chunk.js → webhook-edit-page.d2ea3351.chunk.js} +1 -1
  136. package/build/{zh-Hans-json.9c99f8d4.chunk.js → zh-Hans-json.03d2bda1.chunk.js} +1 -1
  137. package/build/{zh-json.451a0271.chunk.js → zh-json.3d0cc664.chunk.js} +1 -1
  138. package/package.json +7 -8
  139. package/server/bootstrap.js +1 -19
  140. package/server/config/admin-actions.js +0 -20
  141. package/server/content-types/api-token.js +1 -25
  142. package/server/content-types/index.js +0 -1
  143. package/server/controllers/api-token.js +1 -24
  144. package/server/controllers/index.js +0 -1
  145. package/server/routes/api-tokens.js +0 -11
  146. package/server/routes/index.js +0 -2
  147. package/server/services/api-token.js +29 -310
  148. package/server/services/constants.js +0 -10
  149. package/server/services/permission/engine-hooks.js +82 -0
  150. package/server/services/permission/engine.js +226 -36
  151. package/server/services/permission.js +1 -4
  152. package/server/strategies/admin.js +1 -7
  153. package/server/strategies/api-token.js +11 -71
  154. package/server/validation/api-tokens.js +2 -12
  155. package/admin/src/content-manager/components/SelectMany/ListItem.js +0 -102
  156. package/admin/src/content-manager/components/SelectMany/index.js +0 -148
  157. package/admin/src/content-manager/components/SelectOne/SingleValue.js +0 -67
  158. package/admin/src/content-manager/components/SelectOne/index.js +0 -97
  159. package/admin/src/content-manager/components/SelectWrapper/Label.js +0 -60
  160. package/admin/src/content-manager/components/SelectWrapper/index.js +0 -356
  161. package/admin/src/content-manager/pages/EditSettingsView/components/RelationalFieldButton.js +0 -135
  162. package/admin/src/content-manager/pages/EditSettingsView/components/RelationalFields.js +0 -103
  163. package/admin/src/content-manager/pages/EditView/Header/utils/getDraftRelations.js +0 -62
  164. package/admin/src/contexts/ApiTokenPermissions/index.js +0 -24
  165. package/admin/src/core/apis/CustomFields.js +0 -80
  166. package/admin/src/hooks/useRegenerate/index.js +0 -34
  167. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ActionBoundRoutes/index.js +0 -56
  168. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/BoundRoute/getMethodColor.js +0 -41
  169. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/BoundRoute/index.js +0 -72
  170. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/CheckBoxWrapper.js +0 -30
  171. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +0 -150
  172. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ContenTypesSection/index.js +0 -37
  173. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +0 -254
  174. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +0 -77
  175. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormHead/index.js +0 -85
  176. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Permissions/index.js +0 -40
  177. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +0 -68
  178. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/init.js +0 -13
  179. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/reducer.js +0 -72
  180. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/getDateOfExpiration.js +0 -16
  181. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/index.js +0 -5
  182. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/transformPermissionsData.js +0 -36
  183. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DefaultButton/index.js +0 -63
  184. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/ReadButton/index.js +0 -19
  185. package/build/1669.d1b29c28.chunk.js +0 -1
  186. package/build/4318.7d167b58.chunk.js +0 -30
  187. package/build/524.40377968.chunk.js +0 -644
  188. package/build/7379.d246dd38.chunk.js +0 -1
  189. package/build/admin-app.a61d5c2e.chunk.js +0 -112
  190. package/build/admin-edit-roles-page.4dd6bcb9.chunk.js +0 -1
  191. package/build/api-tokens-create-page.93dd0689.chunk.js +0 -1
  192. package/build/api-tokens-edit-page.b0adac81.chunk.js +0 -1
  193. package/build/api-tokens-list-page.bb36535f.chunk.js +0 -16
  194. package/build/content-manager.feb0d540.chunk.js +0 -1178
  195. package/build/content-type-builder-list-view.5b3cd768.chunk.js +0 -194
  196. package/build/content-type-builder-translation-en-json.f985c9c4.chunk.js +0 -1
  197. package/build/content-type-builder.a684b2e8.chunk.js +0 -145
  198. package/build/en-json.a9918c93.chunk.js +0 -1
  199. package/build/main.e4065f58.js +0 -9337
  200. package/build/sso-settings-page.9ceb0140.chunk.js +0 -1
  201. package/server/content-types/api-token-permission.js +0 -36
  202. package/server/controllers/content-api.js +0 -15
  203. package/server/routes/content-api.js +0 -20
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState, useRef, useReducer } from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
3
  import {
4
4
  SettingsPageTitle,
@@ -8,134 +8,62 @@ import {
8
8
  useNotification,
9
9
  useTracking,
10
10
  useGuidedTour,
11
- useRBAC,
11
+ Link,
12
12
  } from '@strapi/helper-plugin';
13
+ import { HeaderLayout, ContentLayout } from '@strapi/design-system/Layout';
13
14
  import { Main } from '@strapi/design-system/Main';
15
+ import { Button } from '@strapi/design-system/Button';
16
+ import Check from '@strapi/icons/Check';
17
+ import ArrowLeft from '@strapi/icons/ArrowLeft';
14
18
  import { Formik } from 'formik';
15
- import { get } from 'lodash';
19
+ import { Stack } from '@strapi/design-system/Stack';
20
+ import { Box } from '@strapi/design-system/Box';
21
+ import { Typography } from '@strapi/design-system/Typography';
22
+ import { Grid, GridItem } from '@strapi/design-system/Grid';
23
+ import { TextInput } from '@strapi/design-system/TextInput';
24
+ import { Textarea } from '@strapi/design-system/Textarea';
25
+ import { Select, Option } from '@strapi/design-system/Select';
26
+ import get from 'lodash/get';
16
27
  import { useRouteMatch, useHistory } from 'react-router-dom';
17
28
  import { useQuery } from 'react-query';
18
29
  import { formatAPIErrors } from '../../../../../utils';
19
30
  import { axiosInstance } from '../../../../../core/utils';
20
- import { schema } from './utils';
31
+ import schema from './utils/schema';
21
32
  import LoadingView from './components/LoadingView';
22
- import FormHead from './components/FormHead';
23
- import FormBody from './components/FormBody';
24
- import adminPermissions from '../../../../../permissions';
25
- import { ApiTokenPermissionsContextProvider } from '../../../../../contexts/ApiTokenPermissions';
26
- import init from './init';
27
- import reducer, { initialState } from './reducer';
28
-
29
- const MSG_ERROR_NAME_TAKEN = 'Name already taken';
33
+ import HeaderContentBox from './components/ContentBox';
30
34
 
31
35
  const ApiTokenCreateView = () => {
36
+ let apiToken;
32
37
  useFocusWhenNavigate();
33
38
  const { formatMessage } = useIntl();
34
39
  const { lockApp, unlockApp } = useOverlayBlocker();
35
40
  const toggleNotification = useNotification();
36
41
  const history = useHistory();
37
- const [apiToken, setApiToken] = useState(
38
- history.location.state?.apiToken.accessKey
39
- ? {
40
- ...history.location.state.apiToken,
41
- }
42
- : null
43
- );
44
42
  const { trackUsage } = useTracking();
45
43
  const trackUsageRef = useRef(trackUsage);
46
44
  const { setCurrentStep } = useGuidedTour();
47
- const {
48
- allowedActions: { canCreate, canUpdate, canRegenerate },
49
- } = useRBAC(adminPermissions.settings['api-tokens']);
50
- const [state, dispatch] = useReducer(reducer, initialState, (state) => init(state, {}));
45
+
51
46
  const {
52
47
  params: { id },
53
48
  } = useRouteMatch('/settings/api-tokens/:id');
54
49
 
55
50
  const isCreating = id === 'create';
56
51
 
57
- useQuery(
58
- 'content-api-permissions',
59
- async () => {
60
- const [permissions, routes] = await Promise.all(
61
- ['/admin/content-api/permissions', '/admin/content-api/routes'].map(async (url) => {
62
- const { data } = await axiosInstance.get(url);
63
-
64
- return data.data;
65
- })
66
- );
67
-
68
- dispatch({
69
- type: 'UPDATE_PERMISSIONS_LAYOUT',
70
- value: permissions,
71
- });
72
-
73
- dispatch({
74
- type: 'UPDATE_ROUTES',
75
- value: routes,
76
- });
77
-
78
- if (apiToken) {
79
- if (apiToken?.type === 'read-only') {
80
- dispatch({
81
- type: 'ON_CHANGE_READ_ONLY',
82
- });
83
- }
84
- if (apiToken?.type === 'full-access') {
85
- dispatch({
86
- type: 'SELECT_ALL_ACTIONS',
87
- });
88
- }
89
- if (apiToken?.type === 'custom') {
90
- dispatch({
91
- type: 'UPDATE_PERMISSIONS',
92
- value: apiToken?.permissions,
93
- });
94
- }
95
- }
96
- },
97
- {
98
- onError() {
99
- toggleNotification({
100
- type: 'warning',
101
- message: { id: 'notification.error', defaultMessage: 'An error occured' },
102
- });
103
- },
104
- }
105
- );
106
-
107
52
  useEffect(() => {
108
53
  trackUsageRef.current(isCreating ? 'didAddTokenFromList' : 'didEditTokenFromList');
109
54
  }, [isCreating]);
110
55
 
111
- const { status } = useQuery(
56
+ if (history.location.state?.apiToken.accessKey) {
57
+ apiToken = history.location.state.apiToken;
58
+ }
59
+
60
+ const { status, data } = useQuery(
112
61
  ['api-token', id],
113
62
  async () => {
114
63
  const {
115
64
  data: { data },
116
65
  } = await axiosInstance.get(`/admin/api-tokens/${id}`);
117
66
 
118
- setApiToken({
119
- ...data,
120
- });
121
-
122
- if (data?.type === 'read-only') {
123
- dispatch({
124
- type: 'ON_CHANGE_READ_ONLY',
125
- });
126
- }
127
- if (data?.type === 'full-access') {
128
- dispatch({
129
- type: 'SELECT_ALL_ACTIONS',
130
- });
131
- }
132
- if (data?.type === 'custom') {
133
- dispatch({
134
- type: 'UPDATE_PERMISSIONS',
135
- value: data?.permissions,
136
- });
137
- }
138
-
139
67
  return data;
140
68
  },
141
69
  {
@@ -149,6 +77,10 @@ const ApiTokenCreateView = () => {
149
77
  }
150
78
  );
151
79
 
80
+ if (data) {
81
+ apiToken = data;
82
+ }
83
+
152
84
  const handleSubmit = async (body, actions) => {
153
85
  trackUsageRef.current(isCreating ? 'willCreateToken' : 'willEditToken');
154
86
  lockApp();
@@ -157,98 +89,37 @@ const ApiTokenCreateView = () => {
157
89
  const {
158
90
  data: { data: response },
159
91
  } = isCreating
160
- ? await axiosInstance.post(`/admin/api-tokens`, {
161
- ...body,
162
- lifespan:
163
- body.lifespan && parseInt(body.lifespan, 10)
164
- ? parseInt(body.lifespan, 10)
165
- : body.lifespan,
166
- permissions: body.type === 'custom' ? state.selectedActions : null,
167
- })
168
- : await axiosInstance.put(`/admin/api-tokens/${id}`, {
169
- name: body.name,
170
- description: body.description,
171
- type: body.type,
172
- permissions: body.type === 'custom' ? state.selectedActions : null,
173
- });
92
+ ? await axiosInstance.post(`/admin/api-tokens`, body)
93
+ : await axiosInstance.put(`/admin/api-tokens/${id}`, body);
174
94
 
175
- if (isCreating) {
176
- history.replace(`/settings/api-tokens/${response.id}`, { apiToken: response });
177
- setCurrentStep('apiTokens.success');
178
- }
179
- unlockApp();
180
- setApiToken({
181
- ...response,
182
- });
95
+ apiToken = response;
183
96
 
184
97
  toggleNotification({
185
98
  type: 'success',
186
- message: isCreating
187
- ? formatMessage({
188
- id: 'notification.success.tokencreated',
189
- defaultMessage: 'API Token successfully created',
190
- })
191
- : formatMessage({
192
- id: 'notification.success.tokenedited',
193
- defaultMessage: 'API Token successfully edited',
194
- }),
99
+ message: formatMessage({ id: 'notification.success.saved', defaultMessage: 'Saved' }),
195
100
  });
196
101
 
197
102
  trackUsageRef.current(isCreating ? 'didCreateToken' : 'didEditToken', {
198
103
  type: apiToken.type,
199
104
  });
105
+
106
+ if (isCreating) {
107
+ history.replace(`/settings/api-tokens/${response.id}`, { apiToken: response });
108
+ setCurrentStep('apiTokens.success');
109
+ }
200
110
  } catch (err) {
201
111
  const errors = formatAPIErrors(err.response.data);
202
112
  actions.setErrors(errors);
203
113
 
204
- if (err?.response?.data?.error?.message === MSG_ERROR_NAME_TAKEN) {
205
- toggleNotification({
206
- type: 'warning',
207
- message: get(err, 'response.data.message', 'notification.error.tokennamenotunique'),
208
- });
209
- } else {
210
- toggleNotification({
211
- type: 'warning',
212
- message: get(err, 'response.data.message', 'notification.error'),
213
- });
214
- }
215
- unlockApp();
114
+ toggleNotification({
115
+ type: 'warning',
116
+ message: get(err, 'response.data.message', 'notification.error'),
117
+ });
216
118
  }
217
- };
218
119
 
219
- const [hasChangedPermissions, setHasChangedPermissions] = useState(false);
220
-
221
- const handleChangeCheckbox = ({ target: { value } }) => {
222
- setHasChangedPermissions(true);
223
- dispatch({
224
- type: 'ON_CHANGE',
225
- value,
226
- });
227
- };
228
-
229
- const handleChangeSelectAllCheckbox = ({ target: { value } }) => {
230
- setHasChangedPermissions(true);
231
- dispatch({
232
- type: 'SELECT_ALL_IN_PERMISSION',
233
- value,
234
- });
235
- };
236
-
237
- const setSelectedAction = ({ target: { value } }) => {
238
- dispatch({
239
- type: 'SET_SELECTED_ACTION',
240
- value,
241
- });
242
- };
243
-
244
- const providerValue = {
245
- ...state,
246
- onChange: handleChangeCheckbox,
247
- onChangeSelectAll: handleChangeSelectAllCheckbox,
248
- setSelectedAction,
120
+ unlockApp();
249
121
  };
250
122
 
251
- const canEditInputs = (canUpdate && !isCreating) || (canCreate && isCreating);
252
123
  const isLoading = !isCreating && !apiToken && status !== 'success';
253
124
 
254
125
  if (isLoading) {
@@ -256,51 +127,162 @@ const ApiTokenCreateView = () => {
256
127
  }
257
128
 
258
129
  return (
259
- <ApiTokenPermissionsContextProvider value={providerValue}>
260
- <Main>
261
- <SettingsPageTitle name="API Tokens" />
262
- <Formik
263
- validationSchema={schema}
264
- validateOnChange={false}
265
- initialValues={{
266
- name: apiToken?.name || '',
267
- description: apiToken?.description || '',
268
- type: apiToken?.type,
269
- lifespan: apiToken?.lifespan ? apiToken.lifespan.toString() : apiToken?.lifespan,
270
- }}
271
- enableReinitialize
272
- onSubmit={(body, actions) => handleSubmit(body, actions)}
273
- >
274
- {({ errors, handleChange, isSubmitting, values, setFieldValue }) => {
275
- if (hasChangedPermissions && values?.type !== 'custom') {
276
- setFieldValue('type', 'custom');
277
- }
278
-
279
- return (
280
- <Form>
281
- <FormHead
282
- apiToken={apiToken}
283
- setApiToken={setApiToken}
284
- canEditInputs={canEditInputs}
285
- canRegenerate={canRegenerate}
286
- isSubmitting={isSubmitting}
287
- />
288
- <FormBody
289
- apiToken={apiToken}
290
- errors={errors}
291
- onChange={handleChange}
292
- canEditInputs={canEditInputs}
293
- isCreating={isCreating}
294
- values={values}
295
- onDispatch={dispatch}
296
- setHasChangedPermissions={setHasChangedPermissions}
297
- />
298
- </Form>
299
- );
300
- }}
301
- </Formik>
302
- </Main>
303
- </ApiTokenPermissionsContextProvider>
130
+ <Main>
131
+ <SettingsPageTitle name="API Tokens" />
132
+ <Formik
133
+ validationSchema={schema}
134
+ validateOnChange={false}
135
+ initialValues={{
136
+ name: apiToken?.name || '',
137
+ description: apiToken?.description || '',
138
+ type: apiToken?.type || 'read-only',
139
+ }}
140
+ onSubmit={handleSubmit}
141
+ >
142
+ {({ errors, handleChange, isSubmitting, values }) => {
143
+ return (
144
+ <Form>
145
+ <HeaderLayout
146
+ title={
147
+ apiToken?.name ||
148
+ formatMessage({
149
+ id: 'Settings.apiTokens.createPage.title',
150
+ defaultMessage: 'Create API Token',
151
+ })
152
+ }
153
+ primaryAction={
154
+ <Button
155
+ disabled={isSubmitting}
156
+ loading={isSubmitting}
157
+ startIcon={<Check />}
158
+ type="submit"
159
+ size="L"
160
+ >
161
+ {formatMessage({
162
+ id: 'global.save',
163
+ defaultMessage: 'Save',
164
+ })}
165
+ </Button>
166
+ }
167
+ navigationAction={
168
+ <Link startIcon={<ArrowLeft />} to="/settings/api-tokens">
169
+ {formatMessage({
170
+ id: 'global.back',
171
+ defaultMessage: 'Back',
172
+ })}
173
+ </Link>
174
+ }
175
+ />
176
+ <ContentLayout>
177
+ <Stack spacing={6}>
178
+ {Boolean(apiToken?.name) && <HeaderContentBox apiToken={apiToken.accessKey} />}
179
+ <Box
180
+ background="neutral0"
181
+ hasRadius
182
+ shadow="filterShadow"
183
+ paddingTop={6}
184
+ paddingBottom={6}
185
+ paddingLeft={7}
186
+ paddingRight={7}
187
+ >
188
+ <Stack spacing={4}>
189
+ <Typography variant="delta" as="h2">
190
+ {formatMessage({
191
+ id: 'global.details',
192
+ defaultMessage: 'Details',
193
+ })}
194
+ </Typography>
195
+ <Grid gap={5}>
196
+ <GridItem key="name" col={6} xs={12}>
197
+ <TextInput
198
+ name="name"
199
+ error={
200
+ errors.name
201
+ ? formatMessage(
202
+ errors.name?.id
203
+ ? errors.name
204
+ : { id: errors.name, defaultMessage: errors.name }
205
+ )
206
+ : null
207
+ }
208
+ label={formatMessage({
209
+ id: 'Settings.apiTokens.form.name',
210
+ defaultMessage: 'Name',
211
+ })}
212
+ onChange={handleChange}
213
+ value={values.name}
214
+ required
215
+ />
216
+ </GridItem>
217
+ <GridItem key="description" col={6} xs={12}>
218
+ <Textarea
219
+ label={formatMessage({
220
+ id: 'Settings.apiTokens.form.description',
221
+ defaultMessage: 'Description',
222
+ })}
223
+ name="description"
224
+ error={
225
+ errors.description
226
+ ? formatMessage(
227
+ errors.description?.id
228
+ ? errors.description
229
+ : {
230
+ id: errors.description,
231
+ defaultMessage: errors.description,
232
+ }
233
+ )
234
+ : null
235
+ }
236
+ onChange={handleChange}
237
+ >
238
+ {values.description}
239
+ </Textarea>
240
+ </GridItem>
241
+ <GridItem key="type" col={6} xs={12}>
242
+ <Select
243
+ name="type"
244
+ label={formatMessage({
245
+ id: 'Settings.apiTokens.form.type',
246
+ defaultMessage: 'Token type',
247
+ })}
248
+ value={values.type}
249
+ error={
250
+ errors.type
251
+ ? formatMessage(
252
+ errors.type?.id
253
+ ? errors.type
254
+ : { id: errors.type, defaultMessage: errors.type }
255
+ )
256
+ : null
257
+ }
258
+ onChange={(value) => {
259
+ handleChange({ target: { name: 'type', value } });
260
+ }}
261
+ >
262
+ <Option value="read-only">
263
+ {formatMessage({
264
+ id: 'Settings.apiTokens.types.read-only',
265
+ defaultMessage: 'Read-only',
266
+ })}
267
+ </Option>
268
+ <Option value="full-access">
269
+ {formatMessage({
270
+ id: 'Settings.apiTokens.types.full-access',
271
+ defaultMessage: 'Full access',
272
+ })}
273
+ </Option>
274
+ </Select>
275
+ </GridItem>
276
+ </Grid>
277
+ </Stack>
278
+ </Box>
279
+ </Stack>
280
+ </ContentLayout>
281
+ </Form>
282
+ );
283
+ }}
284
+ </Formik>
285
+ </Main>
304
286
  );
305
287
  };
306
288
 
@@ -5,10 +5,9 @@ const schema = yup.object().shape({
5
5
  name: yup.string(translatedErrors.string).required(translatedErrors.required),
6
6
  type: yup
7
7
  .string(translatedErrors.string)
8
- .oneOf(['read-only', 'full-access', 'custom'])
8
+ .oneOf(['read-only', 'full-access'])
9
9
  .required(translatedErrors.required),
10
10
  description: yup.string().nullable(),
11
- lifespan: yup.number().integer().min(1).nullable().defined(translatedErrors.required),
12
11
  });
13
12
 
14
13
  export default schema;
@@ -24,7 +24,6 @@ const DeleteButton = ({ tokenName, onClickDelete }) => {
24
24
  },
25
25
  { target: `${tokenName}` }
26
26
  )}
27
- name="delete"
28
27
  noBorder
29
28
  icon={<Trash />}
30
29
  />
@@ -1,13 +1,46 @@
1
1
  import React from 'react';
2
2
  import Pencil from '@strapi/icons/Pencil';
3
+ import { useIntl } from 'react-intl';
3
4
  import PropTypes from 'prop-types';
4
- import DefaultButton from '../DefaultButton';
5
+ import { Link } from '@strapi/helper-plugin';
6
+ import { useHistory } from 'react-router-dom';
7
+ import styled from 'styled-components';
8
+
9
+ const LinkUpdate = styled(Link)`
10
+ svg {
11
+ path {
12
+ fill: ${({ theme }) => theme.colors.neutral500};
13
+ }
14
+ }
15
+
16
+ &:hover {
17
+ svg {
18
+ path {
19
+ fill: ${({ theme }) => theme.colors.neutral800};
20
+ }
21
+ }
22
+ }
23
+ `;
5
24
 
6
25
  const UpdateButton = ({ tokenName, tokenId }) => {
26
+ const { formatMessage } = useIntl();
27
+ const {
28
+ location: { pathname },
29
+ } = useHistory();
30
+
7
31
  return (
8
- <DefaultButton tokenName={tokenName} tokenId={tokenId}>
32
+ <LinkUpdate
33
+ to={`${pathname}/${tokenId}`}
34
+ title={formatMessage(
35
+ {
36
+ id: 'app.component.table.edit',
37
+ defaultMessage: 'Edit {target}',
38
+ },
39
+ { target: `${tokenName}` }
40
+ )}
41
+ >
9
42
  <Pencil />
10
- </DefaultButton>
43
+ </LinkUpdate>
11
44
  );
12
45
  };
13
46
 
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { useIntl } from 'react-intl';
2
3
  import PropTypes from 'prop-types';
3
4
  import { useHistory } from 'react-router-dom';
4
5
 
@@ -12,11 +13,12 @@ import {
12
13
  pxToRem,
13
14
  useTracking,
14
15
  } from '@strapi/helper-plugin';
16
+
15
17
  import DeleteButton from './DeleteButton';
16
18
  import UpdateButton from './UpdateButton';
17
- import ReadButton from './ReadButton';
18
19
 
19
- const TableRows = ({ canDelete, canUpdate, canRead, onClickDelete, withBulkActions, rows }) => {
20
+ const TableRows = ({ canDelete, canUpdate, onClickDelete, withBulkActions, rows }) => {
21
+ const { formatMessage } = useIntl();
20
22
  const [{ query }] = useQueryParams();
21
23
  const [, sortOrder] = query.sort.split(':');
22
24
  const {
@@ -57,24 +59,22 @@ const TableRows = ({ canDelete, canUpdate, canRead, onClickDelete, withBulkActio
57
59
  </Td>
58
60
  <Td>
59
61
  <Typography textColor="neutral800">
60
- <RelativeTime timestamp={new Date(apiToken.createdAt)} />
62
+ {formatMessage({
63
+ id: `Settings.apiTokens.types.${apiToken.type}`,
64
+ defaultMessage: 'Type unknown',
65
+ })}
61
66
  </Typography>
62
67
  </Td>
63
68
  <Td>
64
- {apiToken.lastUsedAt && (
65
- <Typography textColor="neutral800">
66
- <RelativeTime timestamp={new Date(apiToken.lastUsedAt)} />
67
- </Typography>
68
- )}
69
+ <Typography textColor="neutral800">
70
+ <RelativeTime timestamp={new Date(apiToken.createdAt)} />
71
+ </Typography>
69
72
  </Td>
70
73
 
71
74
  {withBulkActions && (
72
75
  <Td>
73
76
  <Flex justifyContent="end">
74
77
  {canUpdate && <UpdateButton tokenName={apiToken.name} tokenId={apiToken.id} />}
75
- {!canUpdate && canRead && (
76
- <ReadButton tokenName={apiToken.name} tokenId={apiToken.id} />
77
- )}
78
78
  {canDelete && (
79
79
  <DeleteButton
80
80
  tokenName={apiToken.name}
@@ -94,7 +94,6 @@ const TableRows = ({ canDelete, canUpdate, canRead, onClickDelete, withBulkActio
94
94
  TableRows.defaultProps = {
95
95
  canDelete: false,
96
96
  canUpdate: false,
97
- canRead: false,
98
97
  onClickDelete() {},
99
98
  rows: [],
100
99
  withBulkActions: false,
@@ -103,7 +102,6 @@ TableRows.defaultProps = {
103
102
  TableRows.propTypes = {
104
103
  canDelete: PropTypes.bool,
105
104
  canUpdate: PropTypes.bool,
106
- canRead: PropTypes.bool,
107
105
  onClickDelete: PropTypes.func,
108
106
  rows: PropTypes.array,
109
107
  withBulkActions: PropTypes.bool,
@@ -147,16 +147,15 @@ const ApiTokenListView = () => {
147
147
  headers={headers}
148
148
  contentType="api-tokens"
149
149
  rows={apiTokens}
150
- withBulkActions={canDelete || canUpdate || canRead}
150
+ withBulkActions={canDelete || canUpdate}
151
151
  isLoading={isLoading}
152
152
  onConfirmDelete={(id) => deleteMutation.mutateAsync(id)}
153
153
  >
154
154
  <TableRows
155
- canRead={canRead}
156
155
  canDelete={canDelete}
157
156
  canUpdate={canUpdate}
158
157
  rows={apiTokens}
159
- withBulkActions={canDelete || canUpdate || canRead}
158
+ withBulkActions={canDelete || canUpdate}
160
159
  />
161
160
  </DynamicTable>
162
161
  )}
@@ -22,23 +22,23 @@ const tableHeaders = [
22
22
  },
23
23
  },
24
24
  {
25
- name: 'createdAt',
26
- key: 'createdAt',
25
+ name: 'type',
26
+ key: 'type',
27
27
  metadatas: {
28
28
  label: {
29
- id: 'Settings.apiTokens.ListView.headers.createdAt',
30
- defaultMessage: 'Created at',
29
+ id: 'Settings.apiTokens.ListView.headers.type',
30
+ defaultMessage: 'Token type',
31
31
  },
32
32
  sortable: false,
33
33
  },
34
34
  },
35
35
  {
36
- name: 'lastUsedAt',
37
- key: 'lastUsedAt',
36
+ name: 'createdAt',
37
+ key: 'createdAt',
38
38
  metadatas: {
39
39
  label: {
40
- id: 'Settings.apiTokens.ListView.headers.lastUsedAt',
41
- defaultMessage: 'Last used',
40
+ id: 'Settings.apiTokens.ListView.headers.createdAt',
41
+ defaultMessage: 'Created at',
42
42
  },
43
43
  sortable: false,
44
44
  },