@strapi/admin 4.10.0-beta.0 → 4.10.0-beta.1

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 (193) hide show
  1. package/.eslintignore +4 -0
  2. package/.eslintrc.js +14 -0
  3. package/admin/src/components/LanguageProvider/index.js +1 -1
  4. package/admin/src/components/LocalesProvider/__mocks__/useLocalesProvider.js +7 -0
  5. package/admin/src/components/LocalesProvider/index.js +2 -3
  6. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +3 -6
  7. package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumn.js +2 -0
  8. package/admin/src/content-manager/components/DynamicTable/index.js +11 -29
  9. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +12 -6
  10. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findAllAndReplace.js +10 -3
  11. package/admin/src/content-manager/components/InputUID/endActionStyle.js +4 -13
  12. package/admin/src/content-manager/components/InputUID/index.js +95 -72
  13. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +4 -8
  14. package/admin/src/content-manager/pages/App/LeftMenu/index.js +56 -35
  15. package/admin/src/content-manager/pages/App/actions.js +19 -7
  16. package/admin/src/content-manager/pages/App/constants.js +3 -3
  17. package/admin/src/content-manager/pages/App/index.js +5 -4
  18. package/admin/src/content-manager/pages/App/reducer.js +7 -6
  19. package/admin/src/content-manager/pages/App/selectors.js +3 -0
  20. package/admin/src/content-manager/pages/App/{useModels.js → useContentManagerInitData.js} +29 -28
  21. package/admin/src/content-manager/pages/App/utils/generateModelsLinks.js +2 -2
  22. package/admin/src/content-manager/pages/App/utils/getContentTypeLinks.js +17 -15
  23. package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +4 -5
  24. package/admin/src/content-manager/pages/EditSettingsView/index.js +4 -0
  25. package/admin/src/content-manager/pages/EditSettingsView/reducer.js +6 -7
  26. package/admin/src/content-manager/pages/EditSettingsView/utils/layout.js +1 -30
  27. package/admin/src/content-manager/pages/EditView/DeleteLink/index.js +5 -11
  28. package/admin/src/content-manager/pages/EditView/index.js +2 -7
  29. package/admin/src/content-manager/pages/ListSettingsView/index.js +1 -0
  30. package/admin/src/content-manager/sharedReducers/crudReducer/actions.js +6 -0
  31. package/admin/src/content-manager/sharedReducers/crudReducer/constants.js +1 -0
  32. package/admin/src/content-manager/sharedReducers/crudReducer/reducer.js +5 -0
  33. package/admin/src/hooks/useConfigurations/__mocks__/index.js +7 -0
  34. package/admin/src/hooks/useFetchMarketplacePlugins/utils/api.js +7 -8
  35. package/admin/src/hooks/useFetchMarketplaceProviders/utils/api.js +5 -0
  36. package/admin/src/hooks/useRegenerate/index.js +12 -7
  37. package/admin/src/pages/AuthPage/components/Register/index.js +46 -38
  38. package/admin/src/pages/HomePage/SocialLinks.js +1 -1
  39. package/admin/src/pages/MarketplacePage/components/EmptyNpmPackageSearch/index.js +3 -3
  40. package/admin/src/pages/MarketplacePage/components/NpmPackagesGrid/index.js +42 -9
  41. package/admin/src/pages/MarketplacePage/components/NpmPackagesPagination/index.js +26 -0
  42. package/admin/src/pages/MarketplacePage/components/OfflineLayout/index.js +45 -0
  43. package/admin/src/pages/MarketplacePage/index.js +80 -175
  44. package/admin/src/pages/MarketplacePage/utils/useMarketplaceData.js +85 -0
  45. package/admin/src/pages/SettingsPage/components/Tokens/FormHead/index.js +4 -0
  46. package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +5 -3
  47. package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +7 -5
  48. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/components/RoleRow/index.js +12 -4
  49. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/index.js +21 -2
  50. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +41 -0
  51. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +53 -9
  52. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +1 -0
  53. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +27 -5
  54. package/admin/src/translations/en.json +51 -49
  55. package/admin/src/translations/ru.json +51 -19
  56. package/build/1387.84b454d3.chunk.js +1 -0
  57. package/build/1657.45231968.chunk.js +168 -0
  58. package/build/3081.bcf9a12f.chunk.js +108 -0
  59. package/build/462.8fff7f3b.chunk.js +71 -0
  60. package/build/4628.20631dd1.chunk.js +1 -0
  61. package/build/5542.b8240e3f.chunk.js +70 -0
  62. package/build/5563.905daa13.chunk.js +79 -0
  63. package/build/6404.68405699.chunk.js +100 -0
  64. package/build/7259.b7d00cea.chunk.js +1 -0
  65. package/build/8694.6522968d.chunk.js +247 -0
  66. package/build/Admin-authenticatedApp.52c88751.chunk.js +79 -0
  67. package/build/Admin_InternalErrorPage.15c6bf07.chunk.js +1 -0
  68. package/build/Admin_homePage.f9309c6d.chunk.js +73 -0
  69. package/build/Admin_marketplace.56bc1008.chunk.js +31 -0
  70. package/build/Admin_pluginsPage.f6b52ee9.chunk.js +6 -0
  71. package/build/Admin_profilePage.9112cffc.chunk.js +15 -0
  72. package/build/Admin_settingsPage.257b3477.chunk.js +79 -0
  73. package/build/Upload_ConfigureTheView.eaaec495.chunk.js +1 -0
  74. package/build/admin-app.dfaeea5d.chunk.js +110 -0
  75. package/build/admin-edit-roles-page.4f1858e9.chunk.js +280 -0
  76. package/build/admin-edit-users.7e14d85f.chunk.js +10 -0
  77. package/build/admin-roles-list.329c1f63.chunk.js +31 -0
  78. package/build/admin-users.d02de059.chunk.js +34 -0
  79. package/build/api-tokens-create-page.97595e12.chunk.js +1 -0
  80. package/build/api-tokens-edit-page.cd36e30e.chunk.js +1 -0
  81. package/build/api-tokens-list-page.6757c7b9.chunk.js +16 -0
  82. package/build/audit-logs-settings-page.19d90bda.chunk.js +76 -0
  83. package/build/content-manager.def692c2.chunk.js +1130 -0
  84. package/build/content-type-builder-list-view.9c2c020c.chunk.js +214 -0
  85. package/build/content-type-builder-translation-en-json.510e88ca.chunk.js +1 -0
  86. package/build/content-type-builder.5e1f4afc.chunk.js +126 -0
  87. package/build/email-settings-page.1095e1ab.chunk.js +10 -0
  88. package/build/en-json.08303b37.chunk.js +1 -0
  89. package/build/{highlight.js.26ef649f.chunk.js → highlight.js.28a1547e.chunk.js} +2 -2
  90. package/build/i18n-settings-page.7d80aae0.chunk.js +60 -0
  91. package/build/index.html +1 -1
  92. package/build/main.120be100.js +2280 -0
  93. package/build/review-workflows-settings.9092ed72.chunk.js +106 -0
  94. package/build/ru-json.e0662702.chunk.js +1 -0
  95. package/build/{runtime~main.5a95bee6.js → runtime~main.112b3101.js} +2 -2
  96. package/build/sso-settings-page.1dd4886e.chunk.js +1 -0
  97. package/build/transfer-tokens-create-page.ec2ca215.chunk.js +1 -0
  98. package/build/transfer-tokens-edit-page.22bf28e5.chunk.js +1 -0
  99. package/build/transfer-tokens-list-page.cf8c77f2.chunk.js +16 -0
  100. package/build/upload-settings.945fdcfa.chunk.js +13 -0
  101. package/build/{upload-translation-th-json.3847dae0.chunk.js → upload-translation-th-json.98d35574.chunk.js} +1 -1
  102. package/build/upload.a86b1054.chunk.js +33 -0
  103. package/build/users-advanced-settings-page.5b5a9baa.chunk.js +8 -0
  104. package/build/users-email-settings-page.e5506eb4.chunk.js +23 -0
  105. package/build/users-providers-settings-page.e32089c2.chunk.js +28 -0
  106. package/build/users-roles-settings-page.2f85dcec.chunk.js +30 -0
  107. package/build/webhook-edit-page.213f0075.chunk.js +75 -0
  108. package/build/webhook-list-page.5beb2a5c.chunk.js +71 -0
  109. package/{admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/ReviewWorkflowsStage.js → ee/admin/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/ReviewWorkflowsStageEE.js} +2 -2
  110. package/ee/admin/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumn.js +45 -0
  111. package/ee/admin/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/index.js +3 -0
  112. package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +61 -18
  113. package/ee/admin/hooks/useLicenseLimitNotification/index.js +1 -1
  114. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/hooks/useAuditLogsData.js +6 -3
  115. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/index.js +15 -5
  116. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/utils/getDisplayedFilters.js +52 -45
  117. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +8 -4
  118. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +2 -2
  119. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows.js +2 -2
  120. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +2 -1
  121. package/ee/server/content-types/workflow/index.js +0 -3
  122. package/ee/server/content-types/workflow-stage/index.js +0 -5
  123. package/ee/server/controllers/workflows/stages/index.js +8 -1
  124. package/ee/server/register.js +3 -1
  125. package/ee/server/services/audit-logs.js +75 -16
  126. package/ee/server/services/review-workflows/entity-service-decorator.js +17 -5
  127. package/ee/server/services/review-workflows/review-workflows.js +27 -91
  128. package/ee/server/services/review-workflows/stages.js +108 -7
  129. package/ee/server/utils/persisted-tables.js +114 -22
  130. package/ee/server/utils/review-workflows.js +9 -0
  131. package/jest.config.front.js +1 -6
  132. package/package.json +24 -22
  133. package/server/controllers/transfer/runner.js +4 -2
  134. package/server/middlewares/data-transfer.js +4 -1
  135. package/server/routes/transfer.js +13 -4
  136. package/server/services/constants.js +4 -0
  137. package/server/services/transfer/permission.js +1 -1
  138. package/server/services/transfer/token.js +33 -31
  139. package/server/validation/transfer/token.js +10 -2
  140. package/webpack.config.js +6 -2
  141. package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/index.js +0 -1
  142. package/admin/src/content-manager/pages/App/LeftMenu/utils/index.js +0 -1
  143. package/admin/src/content-manager/pages/App/LeftMenu/utils/matchByTitle.js +0 -24
  144. package/build/2263.4c5916f9.chunk.js +0 -98
  145. package/build/4049.64715f20.chunk.js +0 -1
  146. package/build/4649.213b8a3b.chunk.js +0 -30
  147. package/build/6985.66cca29c.chunk.js +0 -1
  148. package/build/7259.aefb51e8.chunk.js +0 -1
  149. package/build/8469.853c822b.chunk.js +0 -1
  150. package/build/9505.dbe702ab.chunk.js +0 -14
  151. package/build/9816.01ee964f.chunk.js +0 -2
  152. package/build/Admin-authenticatedApp.f50ad423.chunk.js +0 -79
  153. package/build/Admin_InternalErrorPage.4ad8b0df.chunk.js +0 -1
  154. package/build/Admin_homePage.1411fb7c.chunk.js +0 -68
  155. package/build/Admin_marketplace.02608d56.chunk.js +0 -22
  156. package/build/Admin_pluginsPage.15e3b0fd.chunk.js +0 -1
  157. package/build/Admin_profilePage.76afeca0.chunk.js +0 -15
  158. package/build/Admin_settingsPage.147755cd.chunk.js +0 -9
  159. package/build/Upload_ConfigureTheView.34dde278.chunk.js +0 -1
  160. package/build/admin-app.55dd7921.chunk.js +0 -112
  161. package/build/admin-edit-roles-page.cf543488.chunk.js +0 -216
  162. package/build/admin-edit-users.31c20712.chunk.js +0 -10
  163. package/build/admin-roles-list.489c501f.chunk.js +0 -2
  164. package/build/admin-users.3e111a7d.chunk.js +0 -11
  165. package/build/api-tokens-create-page.4328b852.chunk.js +0 -1
  166. package/build/api-tokens-edit-page.bce5050f.chunk.js +0 -1
  167. package/build/api-tokens-list-page.93f24348.chunk.js +0 -16
  168. package/build/audit-logs-settings-page.7be97e82.chunk.js +0 -1
  169. package/build/content-manager.4480ae88.chunk.js +0 -1137
  170. package/build/content-type-builder-list-view.cf38fe2f.chunk.js +0 -191
  171. package/build/content-type-builder-translation-en-json.7961593e.chunk.js +0 -1
  172. package/build/content-type-builder.af9abf1e.chunk.js +0 -126
  173. package/build/email-settings-page.4bdbef9a.chunk.js +0 -3
  174. package/build/en-json.697b4bcf.chunk.js +0 -1
  175. package/build/i18n-settings-page.2bb5be96.chunk.js +0 -1
  176. package/build/main.af8c0f31.js +0 -3790
  177. package/build/review-workflows-settings.7a7dc773.chunk.js +0 -57
  178. package/build/ru-json.6a01cea6.chunk.js +0 -1
  179. package/build/sso-settings-page.272b87c8.chunk.js +0 -1
  180. package/build/transfer-tokens-create-page.a1f14bb1.chunk.js +0 -1
  181. package/build/transfer-tokens-edit-page.00ee1c74.chunk.js +0 -1
  182. package/build/transfer-tokens-list-page.ce37354b.chunk.js +0 -16
  183. package/build/upload-settings.0875e973.chunk.js +0 -1
  184. package/build/upload.c7da1611.chunk.js +0 -13
  185. package/build/users-advanced-settings-page.1d3c14c7.chunk.js +0 -1
  186. package/build/users-email-settings-page.e8db68c4.chunk.js +0 -1
  187. package/build/users-providers-settings-page.14cac425.chunk.js +0 -1
  188. package/build/users-roles-settings-page.2ea4de84.chunk.js +0 -30
  189. package/build/webhook-edit-page.329141a5.chunk.js +0 -23
  190. package/build/webhook-list-page.029957a4.chunk.js +0 -1
  191. package/ee/server/migrations/review-workflows.js +0 -39
  192. package/ee/server/utils/test.js +0 -11
  193. /package/admin/src/{content-manager/components/InputUID/useDebounce.js → hooks/useDebounce/index.js} +0 -0
@@ -2,6 +2,7 @@ import {
2
2
  GET_DATA,
3
3
  GET_DATA_SUCCEEDED,
4
4
  INIT_FORM,
5
+ UPDATE_PARTIAL_DATA,
5
6
  RESET_PROPS,
6
7
  SET_DATA_STRUCTURES,
7
8
  SET_STATUS,
@@ -47,3 +48,8 @@ export const submitSucceeded = (data) => ({
47
48
  export const clearSetModifiedDataOnly = () => ({
48
49
  type: CLEAR_SET_MODIFIED_DATA_ONLY,
49
50
  });
51
+
52
+ export const updatePartialData = (data) => ({
53
+ type: UPDATE_PARTIAL_DATA,
54
+ data,
55
+ });
@@ -7,3 +7,4 @@ export const SET_STATUS = 'ContentManager/CrudReducer/SET_STATUS';
7
7
  export const SUBMIT_SUCCEEDED = 'ContentManager/CrudReducer/SUBMIT_SUCCEEDED';
8
8
  export const CLEAR_SET_MODIFIED_DATA_ONLY =
9
9
  'ContentManager/CrudReducer/CLEAR_SET_MODIFIED_DATA_ONLY';
10
+ export const UPDATE_PARTIAL_DATA = 'ContentManager/CrudReducer/PARTIAL_DATA_UPDATE';
@@ -12,6 +12,7 @@ import {
12
12
  GET_DATA,
13
13
  GET_DATA_SUCCEEDED,
14
14
  INIT_FORM,
15
+ UPDATE_PARTIAL_DATA,
15
16
  RESET_PROPS,
16
17
  SET_DATA_STRUCTURES,
17
18
  SET_STATUS,
@@ -53,6 +54,10 @@ const crudReducer = (state = crudInitialState, action) =>
53
54
  draftState.data = state.contentTypeDataStructure;
54
55
  break;
55
56
  }
57
+ case UPDATE_PARTIAL_DATA: {
58
+ draftState.data = { ...state.data, ...action.data };
59
+ break;
60
+ }
56
61
  case RESET_PROPS: {
57
62
  return crudInitialState;
58
63
  }
@@ -0,0 +1,7 @@
1
+ export default function () {
2
+ return {
3
+ logos: {
4
+ auth: { custom: 'customAuthLogo.png', default: 'defaultAuthLogo.png' },
5
+ },
6
+ };
7
+ }
@@ -1,19 +1,18 @@
1
1
  import axios from 'axios';
2
+ import qs from 'qs';
2
3
 
3
4
  const MARKETPLACE_API_URL = 'https://market-api.strapi.io';
4
5
 
5
6
  const fetchMarketplacePlugins = async (params = {}) => {
6
- const { data: response } = await axios.get(`${MARKETPLACE_API_URL}/plugins`, {
7
+ const { data } = await axios.get(`${MARKETPLACE_API_URL}/plugins`, {
7
8
  params,
9
+ paramsSerializer: {
10
+ encode: qs.parse,
11
+ serialize: qs.stringify,
12
+ },
8
13
  });
9
14
 
10
- // Only keep v4 plugins
11
- const filteredResponse = {
12
- ...response,
13
- data: response.data.filter((plugin) => plugin.attributes.strapiCompatibility === 'v4'),
14
- };
15
-
16
- return filteredResponse;
15
+ return data;
17
16
  };
18
17
 
19
18
  export { fetchMarketplacePlugins };
@@ -1,10 +1,15 @@
1
1
  import axios from 'axios';
2
+ import qs from 'qs';
2
3
 
3
4
  const MARKETPLACE_API_URL = 'https://market-api.strapi.io';
4
5
 
5
6
  const fetchMarketplaceProviders = async (params = {}) => {
6
7
  const { data } = await axios.get(`${MARKETPLACE_API_URL}/providers`, {
7
8
  params,
9
+ paramsSerializer: {
10
+ encode: qs.parse,
11
+ serialize: qs.stringify,
12
+ },
8
13
  });
9
14
 
10
15
  return data;
@@ -1,11 +1,11 @@
1
1
  import { useState } from 'react';
2
- import get from 'lodash/get';
3
- import { useFetchClient, useNotification } from '@strapi/helper-plugin';
2
+ import { useFetchClient, useNotification, useAPIErrorHandler } from '@strapi/helper-plugin';
4
3
 
5
- const useRegenerate = (url, id, onRegenerate) => {
4
+ const useRegenerate = (url, id, onRegenerate, onError) => {
6
5
  const [isLoadingConfirmation, setIsLoadingConfirmation] = useState(false);
7
6
  const toggleNotification = useNotification();
8
7
  const { post } = useFetchClient();
8
+ const { formatAPIError } = useAPIErrorHandler();
9
9
 
10
10
  const regenerateData = async () => {
11
11
  try {
@@ -18,10 +18,15 @@ const useRegenerate = (url, id, onRegenerate) => {
18
18
  onRegenerate(accessKey);
19
19
  } catch (error) {
20
20
  setIsLoadingConfirmation(false);
21
- toggleNotification({
22
- type: 'warning',
23
- message: get(error, 'response.data.message', 'notification.error'),
24
- });
21
+
22
+ if (onError) {
23
+ onError(error);
24
+ } else {
25
+ toggleNotification({
26
+ type: 'warning',
27
+ message: formatAPIError(error),
28
+ });
29
+ }
25
30
  }
26
31
  };
27
32
 
@@ -1,7 +1,6 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
3
  import styled from 'styled-components';
4
- import get from 'lodash/get';
5
4
  import omit from 'lodash/omit';
6
5
  import { useHistory } from 'react-router-dom';
7
6
  import PropTypes from 'prop-types';
@@ -14,6 +13,7 @@ import {
14
13
  useTracking,
15
14
  getYupInnerErrors,
16
15
  Link,
16
+ useAPIErrorHandler,
17
17
  } from '@strapi/helper-plugin';
18
18
  import {
19
19
  Box,
@@ -27,17 +27,10 @@ import {
27
27
  Typography,
28
28
  } from '@strapi/design-system';
29
29
  import { EyeStriked, Eye } from '@strapi/icons';
30
- import UnauthenticatedLayout, {
31
- Column,
32
- LayoutContent,
33
- } from '../../../../layouts/UnauthenticatedLayout';
30
+ import UnauthenticatedLayout, { LayoutContent } from '../../../../layouts/UnauthenticatedLayout';
34
31
  import Logo from '../../../../components/UnauthenticatedLogo';
35
32
  import FieldActionWrapper from '../FieldActionWrapper';
36
33
 
37
- const CenteredBox = styled(Box)`
38
- text-align: center;
39
- `;
40
-
41
34
  const A = styled.a`
42
35
  color: ${({ theme }) => theme.colors.primary600};
43
36
  `;
@@ -58,6 +51,8 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) =>
58
51
  const { trackUsage } = useTracking();
59
52
  const { formatMessage } = useIntl();
60
53
  const query = useQuery();
54
+ const { formatAPIError } = useAPIErrorHandler();
55
+
61
56
  const registrationToken = query.get('registrationToken');
62
57
 
63
58
  useEffect(() => {
@@ -73,17 +68,17 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) =>
73
68
  if (data) {
74
69
  setUserInfo(data);
75
70
  }
76
- } catch (err) {
77
- const errorMessage = get(err, ['response', 'data', 'message'], 'An error occurred');
71
+ } catch (error) {
72
+ const message = formatAPIError(error);
78
73
 
79
74
  toggleNotification({
80
75
  type: 'warning',
81
- message: errorMessage,
76
+ message,
82
77
  });
83
78
 
84
79
  // Redirect to the oops page in case of an invalid token
85
80
  // @alexandrebodin @JAB I am not sure it is the wanted behavior
86
- push(`/auth/oops?info=${encodeURIComponent(errorMessage)}`);
81
+ push(`/auth/oops?info=${encodeURIComponent(message)}`);
87
82
  }
88
83
  };
89
84
 
@@ -92,6 +87,20 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) =>
92
87
  // eslint-disable-next-line react-hooks/exhaustive-deps
93
88
  }, [registrationToken]);
94
89
 
90
+ function normalizeData(data) {
91
+ return Object.entries(data).reduce((acc, [key, value]) => {
92
+ let normalizedvalue = value;
93
+
94
+ if (!['password', 'confirmPassword'].includes(key) && typeof value === 'string') {
95
+ normalizedvalue = normalizedvalue.trim();
96
+ }
97
+
98
+ acc[key] = normalizedvalue;
99
+
100
+ return acc;
101
+ }, {});
102
+ }
103
+
95
104
  return (
96
105
  <UnauthenticatedLayout>
97
106
  <LayoutContent>
@@ -107,8 +116,10 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) =>
107
116
  news: false,
108
117
  }}
109
118
  onSubmit={async (data, formik) => {
119
+ const normalizedData = normalizeData(data);
120
+
110
121
  try {
111
- await schema.validate(data, { abortEarly: false });
122
+ await schema.validate(normalizedData, { abortEarly: false });
112
123
 
113
124
  if (submitCount > 0 && authType === 'register-admin') {
114
125
  trackUsage('didSubmitWithErrorsFirstAdmin', { count: submitCount.toString() });
@@ -117,11 +128,11 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) =>
117
128
  if (registrationToken) {
118
129
  // We need to pass the registration token in the url param to the api in order to submit another admin user
119
130
  onSubmit(
120
- { userInfo: omit(data, ['registrationToken']), registrationToken },
131
+ { userInfo: omit(normalizedData, ['registrationToken']), registrationToken },
121
132
  formik
122
133
  );
123
134
  } else {
124
- onSubmit(data, formik);
135
+ onSubmit(normalizedData, formik);
125
136
  }
126
137
  } catch (err) {
127
138
  const errors = getYupInnerErrors(err);
@@ -138,27 +149,26 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) =>
138
149
  return (
139
150
  <Form noValidate>
140
151
  <Main>
141
- <Column>
152
+ <Flex direction="column" alignItems="stretch" gap={3}>
142
153
  <Logo />
143
- <Box paddingTop={6} paddingBottom={1}>
144
- <Typography as="h1" variant="alpha">
145
- {formatMessage({
146
- id: 'Auth.form.welcome.title',
147
- defaultMessage: 'Welcome to Strapi!',
148
- })}
149
- </Typography>
150
- </Box>
151
- <CenteredBox paddingBottom={7}>
152
- <Typography variant="epsilon" textColor="neutral600">
153
- {formatMessage({
154
- id: 'Auth.form.register.subtitle',
155
- defaultMessage:
156
- 'Credentials are only used to authenticate in Strapi. All saved data will be stored in your database.',
157
- })}
158
- </Typography>
159
- </CenteredBox>
160
- </Column>
161
- <Flex direction="column" alignItems="stretch" gap={6}>
154
+
155
+ <Typography as="h1" variant="alpha" textAlign="center">
156
+ {formatMessage({
157
+ id: 'Auth.form.welcome.title',
158
+ defaultMessage: 'Welcome to Strapi!',
159
+ })}
160
+ </Typography>
161
+
162
+ <Typography variant="epsilon" textColor="neutral600" textAlign="center">
163
+ {formatMessage({
164
+ id: 'Auth.form.register.subtitle',
165
+ defaultMessage:
166
+ 'Credentials are only used to authenticate in Strapi. All saved data will be stored in your database.',
167
+ })}
168
+ </Typography>
169
+ </Flex>
170
+
171
+ <Flex direction="column" alignItems="stretch" gap={6} marginTop={7}>
162
172
  <Grid gap={4}>
163
173
  <GridItem col={6}>
164
174
  <TextInput
@@ -204,7 +214,6 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) =>
204
214
  value={values.password}
205
215
  error={errors.password ? formatMessage(errors.password) : undefined}
206
216
  endAction={
207
- // eslint-disable-next-line react/jsx-wrap-multilines
208
217
  <FieldActionWrapper
209
218
  onClick={(e) => {
210
219
  e.preventDefault();
@@ -245,7 +254,6 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) =>
245
254
  errors.confirmPassword ? formatMessage(errors.confirmPassword) : undefined
246
255
  }
247
256
  endAction={
248
- // eslint-disable-next-line react/jsx-wrap-multilines
249
257
  <FieldActionWrapper
250
258
  onClick={(e) => {
251
259
  e.preventDefault();
@@ -187,7 +187,7 @@ const SocialLinks = () => {
187
187
  <GridGap>
188
188
  {socialLinksExtended.map(({ icon, link, name }) => {
189
189
  return (
190
- <GridItem col={6} s={12} key={name}>
190
+ <GridItem col={6} s={12} key={name.id}>
191
191
  <LinkCustom size="L" startIcon={icon} variant="tertiary" href={link} isExternal>
192
192
  {formatMessage(name)}
193
193
  </LinkCustom>
@@ -1,16 +1,16 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { Typography, Box, Flex, Icon } from '@strapi/design-system';
4
- import { EmptyStateDocument } from '@strapi/icons';
4
+ import { EmptyDocuments } from '@strapi/icons';
5
5
  import { EmptyNpmPackageGrid } from './EmptyNpmPackageGrid';
6
6
 
7
7
  const EmptyNpmPackageSearch = ({ content }) => {
8
8
  return (
9
- <Box position="relative">
9
+ <Box position="relative" data-testid="marketplace-results">
10
10
  <EmptyNpmPackageGrid />
11
11
  <Box position="absolute" top={11} width="100%">
12
12
  <Flex alignItems="center" justifyContent="center" direction="column">
13
- <Icon as={EmptyStateDocument} color="" width="160px" height="88px" />
13
+ <Icon as={EmptyDocuments} color="" width="160px" height="88px" />
14
14
  <Box paddingTop={6}>
15
15
  <Typography variant="delta" as="p" textColor="neutral600">
16
16
  {content}
@@ -1,29 +1,58 @@
1
- import React, { useCallback } from 'react';
1
+ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { Grid, GridItem } from '@strapi/design-system';
3
+ import { Grid, GridItem, Flex, Loader } from '@strapi/design-system';
4
+ import { useIntl } from 'react-intl';
5
+ import { AnErrorOccurred } from '@strapi/helper-plugin';
4
6
  import NpmPackageCard from '../NpmPackageCard';
7
+ import EmptyNpmPackageSearch from '../EmptyNpmPackageSearch';
5
8
 
6
9
  const NpmPackagesGrid = ({
10
+ status,
7
11
  npmPackages,
8
12
  installedPackageNames,
9
13
  useYarn,
10
14
  isInDevelopmentMode,
11
15
  npmPackageType,
12
16
  strapiAppVersion,
17
+ debouncedSearch,
13
18
  }) => {
14
- // Check if an individual package is in the dependencies
15
- const isAlreadyInstalled = useCallback(
16
- (npmPackageName) => installedPackageNames.includes(npmPackageName),
17
- [installedPackageNames]
19
+ const { formatMessage } = useIntl();
20
+
21
+ if (status === 'error') {
22
+ return (
23
+ <Flex paddingTop={8}>
24
+ <AnErrorOccurred />
25
+ </Flex>
26
+ );
27
+ }
28
+
29
+ if (status === 'loading') {
30
+ return (
31
+ <Flex justifyContent="center" paddingTop={8}>
32
+ <Loader>Loading content...</Loader>
33
+ </Flex>
34
+ );
35
+ }
36
+
37
+ const emptySearchMessage = formatMessage(
38
+ {
39
+ id: 'admin.pages.MarketPlacePage.search.empty',
40
+ defaultMessage: 'No result for "{target}"',
41
+ },
42
+ { target: debouncedSearch }
18
43
  );
19
44
 
45
+ if (npmPackages.length === 0) {
46
+ return <EmptyNpmPackageSearch content={emptySearchMessage} />;
47
+ }
48
+
20
49
  return (
21
- <Grid gap={4}>
50
+ <Grid gap={4} data-testid="marketplace-results">
22
51
  {npmPackages.map((npmPackage) => (
23
52
  <GridItem col={4} s={6} xs={12} style={{ height: '100%' }} key={npmPackage.id}>
24
53
  <NpmPackageCard
25
54
  npmPackage={npmPackage}
26
- isInstalled={isAlreadyInstalled(npmPackage.attributes.npmPackageName)}
55
+ isInstalled={installedPackageNames.includes(npmPackage.attributes.npmPackageName)}
27
56
  useYarn={useYarn}
28
57
  isInDevelopmentMode={isInDevelopmentMode}
29
58
  npmPackageType={npmPackageType}
@@ -36,17 +65,21 @@ const NpmPackagesGrid = ({
36
65
  };
37
66
 
38
67
  NpmPackagesGrid.defaultProps = {
68
+ npmPackages: [],
39
69
  installedPackageNames: [],
40
70
  strapiAppVersion: null,
71
+ debouncedSearch: '',
41
72
  };
42
73
 
43
74
  NpmPackagesGrid.propTypes = {
44
- npmPackages: PropTypes.array.isRequired,
75
+ status: PropTypes.string.isRequired,
76
+ npmPackages: PropTypes.array,
45
77
  installedPackageNames: PropTypes.arrayOf(PropTypes.string),
46
78
  useYarn: PropTypes.bool.isRequired,
47
79
  isInDevelopmentMode: PropTypes.bool.isRequired,
48
80
  npmPackageType: PropTypes.string.isRequired,
49
81
  strapiAppVersion: PropTypes.string,
82
+ debouncedSearch: PropTypes.string,
50
83
  };
51
84
 
52
85
  export default NpmPackagesGrid;
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Box, Flex } from '@strapi/design-system';
4
+ import { PaginationURLQuery, PageSizeURLQuery } from '@strapi/helper-plugin';
5
+
6
+ const NpmPackagesPagination = ({ pagination }) => {
7
+ return (
8
+ <Box paddingTop={4}>
9
+ <Flex alignItems="flex-end" justifyContent="space-between">
10
+ <PageSizeURLQuery options={['12', '24', '50', '100']} defaultValue="24" />
11
+ <PaginationURLQuery pagination={pagination} />
12
+ </Flex>
13
+ </Box>
14
+ );
15
+ };
16
+
17
+ NpmPackagesPagination.propTypes = {
18
+ pagination: PropTypes.shape({
19
+ page: PropTypes.number.isRequired,
20
+ pageCount: PropTypes.number.isRequired,
21
+ pageSize: PropTypes.number.isRequired,
22
+ total: PropTypes.number.isRequired,
23
+ }).isRequired,
24
+ };
25
+
26
+ export default NpmPackagesPagination;
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { pxToRem } from '@strapi/helper-plugin';
4
+ import { Box, Flex, Typography, Layout, Main } from '@strapi/design-system';
5
+ import PageHeader from '../PageHeader';
6
+ import offlineCloud from '../../../../assets/images/icon_offline-cloud.svg';
7
+
8
+ const OfflineLayout = () => {
9
+ const { formatMessage } = useIntl();
10
+
11
+ return (
12
+ <Layout>
13
+ <Main>
14
+ <PageHeader isOnline={false} />
15
+ <Flex
16
+ width="100%"
17
+ direction="column"
18
+ alignItems="center"
19
+ justifyContent="center"
20
+ paddingTop={pxToRem(120)}
21
+ >
22
+ <Box paddingBottom={2}>
23
+ <Typography textColor="neutral700" variant="alpha">
24
+ {formatMessage({
25
+ id: 'admin.pages.MarketPlacePage.offline.title',
26
+ defaultMessage: 'You are offline',
27
+ })}
28
+ </Typography>
29
+ </Box>
30
+ <Box paddingBottom={6}>
31
+ <Typography textColor="neutral700" variant="epsilon">
32
+ {formatMessage({
33
+ id: 'admin.pages.MarketPlacePage.offline.subtitle',
34
+ defaultMessage: 'You need to be connected to the Internet to access Strapi Market.',
35
+ })}
36
+ </Typography>
37
+ </Box>
38
+ <img src={offlineCloud} alt="offline" style={{ width: '88px', height: '88px' }} />
39
+ </Flex>
40
+ </Main>
41
+ </Layout>
42
+ );
43
+ };
44
+
45
+ export default OfflineLayout;