@strapi/admin 4.5.2 → 4.5.4

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 (119) hide show
  1. package/admin/src/components/AuthenticatedApp/index.js +13 -2
  2. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +1 -1
  3. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +39 -3
  4. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +5 -1
  5. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/recursivelyFindPathsBasedOnCondition.js +8 -1
  6. package/admin/src/content-manager/components/Inputs/index.js +5 -19
  7. package/admin/src/content-manager/components/NonRepeatableComponent/index.js +4 -0
  8. package/admin/src/content-manager/components/RelationInput/RelationInput.js +4 -9
  9. package/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.js +1 -1
  10. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/index.js +4 -0
  11. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +1 -1
  12. package/admin/src/content-manager/components/Wysiwyg/Editor.js +1 -1
  13. package/admin/src/content-manager/hooks/useLazyComponents/index.js +69 -0
  14. package/admin/src/content-manager/pages/CollectionTypeRecursivePath/components/ErrorFallback.js +13 -0
  15. package/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.js +2 -1
  16. package/admin/src/content-manager/pages/EditView/GridRow/index.js +62 -0
  17. package/admin/src/content-manager/pages/EditView/index.js +74 -154
  18. package/admin/src/content-manager/pages/EditView/selectors.js +14 -0
  19. package/admin/src/content-manager/pages/EditView/utils/createAttributesLayout.js +11 -6
  20. package/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js +18 -0
  21. package/admin/src/content-manager/pages/EditView/utils/index.js +1 -0
  22. package/admin/src/content-manager/pages/EditViewLayoutManager/index.js +1 -1
  23. package/admin/src/content-manager/sharedReducers/crudReducer/actions.js +5 -0
  24. package/admin/src/content-manager/sharedReducers/crudReducer/constants.js +2 -0
  25. package/admin/src/content-manager/sharedReducers/crudReducer/reducer.js +7 -0
  26. package/admin/src/core/apis/CustomFields.js +46 -1
  27. package/admin/src/core/utils/axiosInstance.js +4 -2
  28. package/admin/src/hooks/index.js +1 -0
  29. package/admin/src/hooks/useFetchClient/index.js +23 -0
  30. package/admin/src/pages/App/index.js +20 -13
  31. package/admin/src/pages/HomePage/SocialLinks.js +4 -4
  32. package/admin/src/pages/MarketplacePage/components/SortSelect/index.js +20 -0
  33. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +2 -3
  34. package/admin/src/pages/SettingsPage/pages/Users/ListPage/ModalForm/index.js +23 -18
  35. package/admin/src/translations/en.json +4 -0
  36. package/admin/src/translations/ru.json +789 -489
  37. package/admin/src/translations/tr.json +485 -5
  38. package/admin/src/utils/fetchClient.js +45 -0
  39. package/admin/src/utils/getFetchClient.js +10 -0
  40. package/admin/src/utils/index.js +1 -0
  41. package/admin/src/utils/uniqueAdminHash.js +22 -0
  42. package/build/{1233.bddaaa76.chunk.js → 1233.802422fa.chunk.js} +63 -63
  43. package/build/4306.df40a798.chunk.js +98 -0
  44. package/build/4318.9283c350.chunk.js +30 -0
  45. package/build/5057.195a59ff.chunk.js +65 -0
  46. package/build/{805.a1894307.chunk.js → 805.e991a370.chunk.js} +6 -6
  47. package/build/{4986.3820d11d.chunk.js → 8176.e929d326.chunk.js} +3 -3
  48. package/build/{8633.8da5488a.chunk.js → 8633.43ec9042.chunk.js} +1 -1
  49. package/build/8881.c693411a.chunk.js +245 -0
  50. package/build/9161.4a0ab137.chunk.js +2119 -0
  51. package/build/9279.6290c87a.chunk.js +117 -0
  52. package/build/9707.a0cc4ad8.chunk.js +70 -0
  53. package/build/Admin-authenticatedApp.0da578b8.chunk.js +80 -0
  54. package/build/{Admin_homePage.54e33c2d.chunk.js → Admin_homePage.8945f71a.chunk.js} +5 -5
  55. package/build/{Admin_marketplace.ff012eb2.chunk.js → Admin_marketplace.ed754a4a.chunk.js} +5 -5
  56. package/build/{Admin_profilePage.e9fcce92.chunk.js → Admin_profilePage.60ab80bb.chunk.js} +1 -1
  57. package/build/{Admin_settingsPage.a1a5218b.chunk.js → Admin_settingsPage.6ef8acc9.chunk.js} +6 -6
  58. package/build/admin-app.a3277e72.chunk.js +112 -0
  59. package/build/admin-edit-roles-page.f407538c.chunk.js +1 -0
  60. package/build/admin-edit-users.5547b126.chunk.js +10 -0
  61. package/build/{admin-users.a0748674.chunk.js → admin-users.e64fb0f1.chunk.js} +1 -1
  62. package/build/content-manager.f9630c3b.chunk.js +1197 -0
  63. package/build/content-type-builder-list-view.4412efc3.chunk.js +201 -0
  64. package/build/content-type-builder-translation-tr-json.949e22eb.chunk.js +1 -0
  65. package/build/content-type-builder.b132b5f4.chunk.js +145 -0
  66. package/build/email-settings-page.c6e62f6b.chunk.js +15 -0
  67. package/build/email-translation-tr-json.8aa034bb.chunk.js +1 -0
  68. package/build/en-json.7dd57947.chunk.js +1 -0
  69. package/build/i18n-translation-tr-json.34ca9d61.chunk.js +1 -0
  70. package/build/index.html +1 -1
  71. package/build/main.71f24343.js +2034 -0
  72. package/build/ru-json.8830286f.chunk.js +1 -0
  73. package/build/runtime~main.1115f82b.js +2 -0
  74. package/build/sso-settings-page.feed2f45.chunk.js +1 -0
  75. package/build/tr-json.eac8bd79.chunk.js +1 -0
  76. package/build/upload-settings.450cab1a.chunk.js +18 -0
  77. package/build/upload-translation-tr-json.b173223a.chunk.js +1 -0
  78. package/build/upload.74540aab.chunk.js +64 -0
  79. package/build/users-advanced-settings-page.0c0b8230.chunk.js +13 -0
  80. package/build/users-email-settings-page.3126ff8c.chunk.js +28 -0
  81. package/build/users-permissions-translation-tr-json.9bebc250.chunk.js +1 -0
  82. package/build/users-providers-settings-page.b7b602e2.chunk.js +33 -0
  83. package/build/users-roles-settings-page.ce5b582d.chunk.js +30 -0
  84. package/build/webhook-edit-page.1215a6b7.chunk.js +75 -0
  85. package/package.json +13 -13
  86. package/server/controllers/admin.js +2 -0
  87. package/server/routes/admin.js +1 -1
  88. package/server/services/metrics.js +5 -2
  89. package/utils/get-plugins-path.js +17 -3
  90. package/build/1920.208c77f8.chunk.js +0 -245
  91. package/build/2438.afe24949.chunk.js +0 -2525
  92. package/build/2517.5cc235ba.chunk.js +0 -117
  93. package/build/4306.e62b841c.chunk.js +0 -98
  94. package/build/4318.7931eee7.chunk.js +0 -30
  95. package/build/9707.932a3c12.chunk.js +0 -70
  96. package/build/Admin-authenticatedApp.7484bdf1.chunk.js +0 -80
  97. package/build/admin-app.9cb0abc7.chunk.js +0 -112
  98. package/build/admin-edit-roles-page.23f15909.chunk.js +0 -1
  99. package/build/admin-edit-users.283b49ed.chunk.js +0 -10
  100. package/build/content-manager.577fddcb.chunk.js +0 -1200
  101. package/build/content-type-builder-list-view.95012cf0.chunk.js +0 -201
  102. package/build/content-type-builder-translation-tr-json.2e52bc60.chunk.js +0 -1
  103. package/build/content-type-builder.95b9d6a2.chunk.js +0 -145
  104. package/build/email-settings-page.4bb3606f.chunk.js +0 -15
  105. package/build/email-translation-tr-json.87f2feb3.chunk.js +0 -1
  106. package/build/en-json.4a269f6b.chunk.js +0 -1
  107. package/build/main.23670c4c.js +0 -2026
  108. package/build/ru-json.d7cfc2ff.chunk.js +0 -1
  109. package/build/runtime~main.4dc8c7c6.js +0 -2
  110. package/build/sso-settings-page.9f091262.chunk.js +0 -1
  111. package/build/tr-json.9c44ea0c.chunk.js +0 -1
  112. package/build/upload-settings.3010911f.chunk.js +0 -18
  113. package/build/upload.9f19f2e8.chunk.js +0 -64
  114. package/build/users-advanced-settings-page.9df41d67.chunk.js +0 -13
  115. package/build/users-email-settings-page.56d82eaf.chunk.js +0 -28
  116. package/build/users-permissions-translation-tr-json.cdc49a3c.chunk.js +0 -1
  117. package/build/users-providers-settings-page.96bb7da0.chunk.js +0 -33
  118. package/build/users-roles-settings-page.445e5e16.chunk.js +0 -30
  119. package/build/webhook-edit-page.3285abc4.chunk.js +0 -75
@@ -20,7 +20,7 @@ import {
20
20
  fetchUserRoles,
21
21
  } from './utils/api';
22
22
  import checkLatestStrapiVersion from './utils/checkLatestStrapiVersion';
23
- import { getFullName } from '../../utils';
23
+ import { getFullName, hashAdminUserEmail } from '../../utils';
24
24
 
25
25
  const strapiVersion = packageJSON.version;
26
26
 
@@ -31,6 +31,7 @@ const AuthenticatedApp = () => {
31
31
  const userInfo = auth.getUserInfo();
32
32
  const userName = get(userInfo, 'username') || getFullName(userInfo.firstname, userInfo.lastname);
33
33
  const [userDisplayName, setUserDisplayName] = useState(userName);
34
+ const [userId, setUserId] = useState(null);
34
35
  const { showReleaseNotification } = useConfigurations();
35
36
  const [
36
37
  { data: appInfos, status },
@@ -71,6 +72,15 @@ const AuthenticatedApp = () => {
71
72
  }
72
73
  }, [userRoles, appInfos]);
73
74
 
75
+ useEffect(() => {
76
+ const getUserId = async () => {
77
+ const userId = await hashAdminUserEmail(userInfo);
78
+ setUserId(userId);
79
+ };
80
+
81
+ getUserId();
82
+ }, [userInfo]);
83
+
74
84
  // We don't need to wait for the release query to be fetched before rendering the plugins
75
85
  // however, we need the appInfos and the permissions
76
86
  const shouldShowNotDependentQueriesLoader =
@@ -81,12 +91,13 @@ const AuthenticatedApp = () => {
81
91
  const appInfosValue = useMemo(() => {
82
92
  return {
83
93
  ...appInfos,
94
+ userId,
84
95
  latestStrapiReleaseTag: tag_name,
85
96
  setUserDisplayName,
86
97
  shouldUpdateStrapi,
87
98
  userDisplayName,
88
99
  };
89
- }, [appInfos, tag_name, shouldUpdateStrapi, userDisplayName]);
100
+ }, [appInfos, tag_name, shouldUpdateStrapi, userDisplayName, userId]);
90
101
 
91
102
  if (shouldShowLoader) {
92
103
  return <LoadingIndicatorPage />;
@@ -111,7 +111,7 @@ const DynamicZoneComponent = ({
111
111
  <StyledBox hasRadius>
112
112
  <Accordion expanded={isOpen} onToggle={handleToggle} size="S" error={errorMessage}>
113
113
  <AccordionToggle
114
- startIcon={<FontAwesomeIcon icon={icon} />}
114
+ startIcon={icon && <FontAwesomeIcon icon={icon} />}
115
115
  action={
116
116
  <Stack horizontal spacing={0} expanded={isOpen}>
117
117
  {showDownIcon && (
@@ -8,7 +8,9 @@ import set from 'lodash/set';
8
8
  import PropTypes from 'prop-types';
9
9
  import { useIntl } from 'react-intl';
10
10
  import { Prompt, Redirect } from 'react-router-dom';
11
- import { Main } from '@strapi/design-system/Main';
11
+ import { useDispatch, useSelector } from 'react-redux';
12
+
13
+ import { Main } from '@strapi/design-system';
12
14
  import {
13
15
  LoadingIndicatorPage,
14
16
  ContentManagerEditViewDataManagerContext,
@@ -20,8 +22,13 @@ import {
20
22
  } from '@strapi/helper-plugin';
21
23
 
22
24
  import { getTrad, removeKeyInObject } from '../../utils';
25
+
26
+ import selectCrudReducer from '../../sharedReducers/crudReducer/selectors';
27
+
23
28
  import reducer, { initialState } from './reducer';
24
29
  import { cleanData, createYupSchema, recursivelyFindPathsBasedOnCondition } from './utils';
30
+ import { clearSetModifiedDataOnly } from '../../sharedReducers/crudReducer/actions';
31
+ import { usePrev } from '../../hooks';
25
32
 
26
33
  const EditViewDataManagerProvider = ({
27
34
  allLayoutData,
@@ -61,6 +68,9 @@ const EditViewDataManagerProvider = ({
61
68
  publishConfirmation,
62
69
  } = reducerState;
63
70
 
71
+ const { setModifiedDataOnly } = useSelector(selectCrudReducer);
72
+ const reduxDispatch = useDispatch();
73
+
64
74
  const toggleNotification = useNotification();
65
75
  const { lockApp, unlockApp } = useOverlayBlocker();
66
76
 
@@ -144,8 +154,18 @@ const EditViewDataManagerProvider = ({
144
154
 
145
155
  const { components } = allLayoutData;
146
156
 
157
+ const previousInitialValues = usePrev(initialValues);
158
+
147
159
  useEffect(() => {
148
- if (initialValues && currentContentTypeLayout?.attributes) {
160
+ /**
161
+ * Only fire this effect if the initialValues are different
162
+ * otherwise it's a fruitless effort no matter what happens.
163
+ */
164
+ if (
165
+ initialValues &&
166
+ currentContentTypeLayout?.attributes &&
167
+ !isEqual(previousInitialValues, initialValues)
168
+ ) {
149
169
  /**
150
170
  * This will return an array of paths:
151
171
  * ['many_to_one', 'one_to_many', 'one_to_one']
@@ -179,9 +199,25 @@ const EditViewDataManagerProvider = ({
179
199
  componentPaths,
180
200
  repeatableComponentPaths,
181
201
  dynamicZonePaths,
202
+ setModifiedDataOnly,
182
203
  });
204
+
205
+ /**
206
+ * TODO: This should be moved to a side-effect e.g. thunks
207
+ * something to consider for V5
208
+ */
209
+ if (setModifiedDataOnly) {
210
+ reduxDispatch(clearSetModifiedDataOnly());
211
+ }
183
212
  }
184
- }, [initialValues, currentContentTypeLayout, components]);
213
+ }, [
214
+ initialValues,
215
+ currentContentTypeLayout,
216
+ components,
217
+ setModifiedDataOnly,
218
+ reduxDispatch,
219
+ previousInitialValues,
220
+ ]);
185
221
 
186
222
  const dispatchAddComponent = useCallback(
187
223
  (type) =>
@@ -192,6 +192,7 @@ const reducer = (state, action) =>
192
192
  componentPaths = [],
193
193
  repeatableComponentPaths = [],
194
194
  dynamicZonePaths = [],
195
+ setModifiedDataOnly,
195
196
  } = action;
196
197
 
197
198
  /**
@@ -243,7 +244,10 @@ const reducer = (state, action) =>
243
244
  return acc;
244
245
  }, data);
245
246
 
246
- draftState.initialData = mergeDataWithPreparedRelations;
247
+ if (!setModifiedDataOnly) {
248
+ draftState.initialData = mergeDataWithPreparedRelations;
249
+ }
250
+
247
251
  draftState.modifiedData = mergeDataWithPreparedRelations;
248
252
 
249
253
  draftState.formErrors = {};
@@ -55,8 +55,15 @@ const recursivelyFindPathsBasedOnConditionSetup = (components, predicate = () =>
55
55
  *
56
56
  * NOTE: we don't need to know the path to the `array` because it's about data shape not about the actual data
57
57
  */
58
- }).map((path) => path.split(`${componentName}.`)[1]);
58
+ }).map((path) => {
59
+ return path.split(`${componentName}.`)[1];
60
+ });
59
61
  })
62
+ /**
63
+ * We filter because this will give you `dynamiczone.undefined` because the dynamic_zone component
64
+ * is not required to be returned in this circumstance.
65
+ */
66
+ .filter((path) => Boolean(path))
60
67
  .map((path) => `${key}.${path}`);
61
68
 
62
69
  acc = [...acc, attributesInDynamicComponents];
@@ -5,7 +5,7 @@ import get from 'lodash/get';
5
5
  import omit from 'lodash/omit';
6
6
  import take from 'lodash/take';
7
7
  import isEqual from 'react-fast-compare';
8
- import { GenericInput, NotAllowedInput, useLibrary, useCustomFields } from '@strapi/helper-plugin';
8
+ import { GenericInput, NotAllowedInput, useLibrary } from '@strapi/helper-plugin';
9
9
  import { useContentTypeLayout } from '../../hooks';
10
10
  import { getFieldName } from '../../utils';
11
11
  import Wysiwyg from '../Wysiwyg';
@@ -37,11 +37,11 @@ function Inputs({
37
37
  queryInfos,
38
38
  value,
39
39
  size,
40
+ customFieldInputs,
40
41
  }) {
41
42
  const { fields } = useLibrary();
42
43
  const { formatMessage } = useIntl();
43
44
  const { contentType: currentContentTypeLayout } = useContentTypeLayout();
44
- const customFieldsRegistry = useCustomFields();
45
45
 
46
46
  const disabled = useMemo(() => !get(metadatas, 'editable', true), [metadatas]);
47
47
  const { type, customField: customFieldUid } = fieldSchema;
@@ -194,19 +194,6 @@ function Inputs({
194
194
  return minutes % metadatas.step === 0 ? metadatas.step : step;
195
195
  }, [inputType, inputValue, metadatas.step, step]);
196
196
 
197
- // Memoize the component to avoid remounting it and losing state
198
- const CustomFieldInput = useMemo(() => {
199
- if (customFieldUid) {
200
- const customField = customFieldsRegistry.get(customFieldUid);
201
- const CustomFieldInput = React.lazy(customField.components.Input);
202
-
203
- return CustomFieldInput;
204
- }
205
-
206
- // Not a custom field, component won't be used
207
- return null;
208
- }, [customFieldUid, customFieldsRegistry]);
209
-
210
197
  if (visible === false) {
211
198
  return null;
212
199
  }
@@ -268,12 +255,9 @@ function Inputs({
268
255
  media: fields.media,
269
256
  wysiwyg: Wysiwyg,
270
257
  ...fields,
258
+ ...customFieldInputs,
271
259
  };
272
260
 
273
- if (customFieldUid) {
274
- customInputs[customFieldUid] = CustomFieldInput;
275
- }
276
-
277
261
  return (
278
262
  <GenericInput
279
263
  attribute={fieldSchema}
@@ -309,6 +293,7 @@ Inputs.defaultProps = {
309
293
  size: undefined,
310
294
  value: null,
311
295
  queryInfos: {},
296
+ customFieldInputs: {},
312
297
  };
313
298
 
314
299
  Inputs.propTypes = {
@@ -330,6 +315,7 @@ Inputs.propTypes = {
330
315
  defaultParams: PropTypes.object,
331
316
  endPoint: PropTypes.string,
332
317
  }),
318
+ customFieldInputs: PropTypes.object,
333
319
  };
334
320
 
335
321
  const Memoized = memo(Inputs, isEqual);
@@ -9,6 +9,7 @@ import { Stack } from '@strapi/design-system/Stack';
9
9
  import { useContentTypeLayout } from '../../hooks';
10
10
  import FieldComponent from '../FieldComponent';
11
11
  import Inputs from '../Inputs';
12
+ import useLazyComponents from '../../hooks/useLazyComponents';
12
13
 
13
14
  const NonRepeatableComponent = ({ componentUid, isFromDynamicZone, isNested, name }) => {
14
15
  const { getComponentLayout } = useContentTypeLayout();
@@ -18,6 +19,8 @@ const NonRepeatableComponent = ({ componentUid, isFromDynamicZone, isNested, nam
18
19
  );
19
20
  const fields = componentLayoutData.layouts.edit;
20
21
 
22
+ const { lazyComponentStore } = useLazyComponents();
23
+
21
24
  return (
22
25
  <Box
23
26
  background={isFromDynamicZone ? '' : 'neutral100'}
@@ -67,6 +70,7 @@ const NonRepeatableComponent = ({ componentUid, isFromDynamicZone, isNested, nam
67
70
  metadatas={metadatas}
68
71
  queryInfos={queryInfos}
69
72
  size={size}
73
+ customFieldInputs={lazyComponentStore}
70
74
  />
71
75
  </GridItem>
72
76
  );
@@ -24,18 +24,13 @@ import { RELATION_ITEM_HEIGHT } from './constants';
24
24
  import { usePrev } from '../../hooks';
25
25
 
26
26
  const LinkEllipsis = styled(Link)`
27
- white-space: nowrap;
28
- overflow: hidden;
29
- text-overflow: ellipsis;
30
- display: inherit;
31
- `;
27
+ display: block;
32
28
 
33
- const BoxEllipsis = styled(Box)`
34
29
  > span {
35
30
  white-space: nowrap;
36
31
  overflow: hidden;
37
32
  text-overflow: ellipsis;
38
- display: inherit;
33
+ display: block;
39
34
  }
40
35
  `;
41
36
 
@@ -322,7 +317,7 @@ const RelationInput = ({
322
317
  }
323
318
  style={style}
324
319
  >
325
- <BoxEllipsis minWidth={0} paddingTop={1} paddingBottom={1} paddingRight={4}>
320
+ <Box minWidth={0} paddingTop={1} paddingBottom={1} paddingRight={4}>
326
321
  <Tooltip description={mainField ?? `${id}`}>
327
322
  {href ? (
328
323
  <LinkEllipsis to={href} disabled={disabled}>
@@ -334,7 +329,7 @@ const RelationInput = ({
334
329
  </Typography>
335
330
  )}
336
331
  </Tooltip>
337
- </BoxEllipsis>
332
+ </Box>
338
333
 
339
334
  {publicationState && (
340
335
  <Status variant={statusColor} showBullet={false} size="S">
@@ -40,7 +40,7 @@ export const RelationInputDataManager = ({
40
40
  const { connectRelation, disconnectRelation, loadRelation, modifiedData, slug, initialData } =
41
41
  useCMEditViewDataManager();
42
42
 
43
- const relationsFromModifiedData = get(modifiedData, name) ?? [];
43
+ const relationsFromModifiedData = get(modifiedData, name, []);
44
44
 
45
45
  const currentLastPage = Math.ceil(get(initialData, name, []).length / RELATIONS_TO_DISPLAY);
46
46
 
@@ -21,6 +21,7 @@ import Preview from './Preview';
21
21
  import DraggingSibling from './DraggingSibling';
22
22
  import { CustomIconButton } from './IconButtonCustoms';
23
23
  import { connect, select } from './utils';
24
+ import useLazyComponents from '../../../hooks/useLazyComponents';
24
25
 
25
26
  const DragButton = styled.span`
26
27
  display: flex;
@@ -177,6 +178,8 @@ const DraggedItem = ({
177
178
  const accordionTitle = toString(displayedValue);
178
179
  const accordionHasError = hasErrors ? 'error' : undefined;
179
180
 
181
+ const { lazyComponentStore } = useLazyComponents();
182
+
180
183
  return (
181
184
  <Box ref={refs ? refs.dropRef : null}>
182
185
  {isDragging && <Preview />}
@@ -273,6 +276,7 @@ const DraggedItem = ({
273
276
  // onBlur={hasErrors ? checkFormErrors : null}
274
277
  queryInfos={queryInfos}
275
278
  size={size}
279
+ customFieldInputs={lazyComponentStore}
276
280
  />
277
281
  </GridItem>
278
282
  );
@@ -103,7 +103,7 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
103
103
  setIsCreatingEntry(true);
104
104
 
105
105
  try {
106
- const { data } = await axiosInstance(getRequestUrl(`${slug}${searchToSend}`), {
106
+ const { data } = await axiosInstance.get(getRequestUrl(`${slug}${searchToSend}`), {
107
107
  cancelToken: source.token,
108
108
  });
109
109
 
@@ -43,7 +43,7 @@ const Editor = ({
43
43
  }, [editorRef, textareaRef, name, placeholder]);
44
44
 
45
45
  useEffect(() => {
46
- if (value && !editorRef.current.state.focused) {
46
+ if (value && !editorRef.current.hasFocus()) {
47
47
  editorRef.current.setValue(value);
48
48
  }
49
49
  }, [editorRef, value]);
@@ -0,0 +1,69 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { useCustomFields } from '@strapi/helper-plugin';
3
+
4
+ const componentStore = new Map();
5
+
6
+ /**
7
+ * @description
8
+ * A hook to lazy load custom field components
9
+ * @param {Array.<string>} componentUids - The uids to look up components
10
+ * @returns object
11
+ */
12
+ const useLazyComponents = (componentUids = []) => {
13
+ const [lazyComponentStore, setLazyComponentStore] = useState(Object.fromEntries(componentStore));
14
+ const [loading, setLoading] = useState(() => {
15
+ if (componentStore.size === 0 && componentUids.length > 0) {
16
+ return true;
17
+ }
18
+
19
+ return false;
20
+ });
21
+ const customFieldsRegistry = useCustomFields();
22
+
23
+ useEffect(() => {
24
+ const setStore = (store) => {
25
+ setLazyComponentStore(store);
26
+ setLoading(false);
27
+ };
28
+
29
+ const lazyLoadComponents = async (uids, components) => {
30
+ const modules = await Promise.all(components);
31
+
32
+ uids.forEach((uid, index) => {
33
+ componentStore.set(uid, modules[index].default);
34
+ });
35
+
36
+ setStore(Object.fromEntries(componentStore));
37
+ };
38
+
39
+ if (componentUids.length && loading) {
40
+ /**
41
+ * These uids are not in the component store therefore we need to get the components
42
+ */
43
+ const newUids = componentUids.filter((uid) => !componentStore.get(uid));
44
+
45
+ const componentPromises = newUids.map((uid) => {
46
+ const customField = customFieldsRegistry.get(uid);
47
+
48
+ return customField.components.Input();
49
+ });
50
+
51
+ if (componentPromises.length > 0) {
52
+ lazyLoadComponents(newUids, componentPromises);
53
+ }
54
+ }
55
+ }, [componentUids, customFieldsRegistry, loading]);
56
+
57
+ /**
58
+ * Wrap this in a callback so it can be used in
59
+ * effects to cleanup the cached store if required
60
+ */
61
+ const cleanup = useCallback(() => {
62
+ componentStore.clear();
63
+ setLazyComponentStore({});
64
+ }, []);
65
+
66
+ return { isLazyLoading: loading, lazyComponentStore, cleanup };
67
+ };
68
+
69
+ export default useLazyComponents;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { AnErrorOccurred } from '@strapi/helper-plugin';
3
+ import { Box } from '@strapi/design-system/Box';
4
+
5
+ const ErrorFallback = () => {
6
+ return (
7
+ <Box padding={8}>
8
+ <AnErrorOccurred />
9
+ </Box>
10
+ );
11
+ };
12
+
13
+ export default ErrorFallback;
@@ -3,7 +3,7 @@ import { Switch, Route } from 'react-router-dom';
3
3
  import { ErrorBoundary } from 'react-error-boundary';
4
4
  import { get } from 'lodash';
5
5
  import PropTypes from 'prop-types';
6
- import { ErrorFallback, LoadingIndicatorPage, CheckPagePermissions } from '@strapi/helper-plugin';
6
+ import { LoadingIndicatorPage, CheckPagePermissions } from '@strapi/helper-plugin';
7
7
  import permissions from '../../../permissions';
8
8
  import { ContentTypeLayoutContext } from '../../contexts';
9
9
  import { useFetchContentTypeLayout } from '../../hooks';
@@ -12,6 +12,7 @@ import EditViewLayoutManager from '../EditViewLayoutManager';
12
12
  import EditSettingsView from '../EditSettingsView';
13
13
  import ListViewLayout from '../ListViewLayoutManager';
14
14
  import ListSettingsView from '../ListSettingsView';
15
+ import ErrorFallback from './components/ErrorFallback';
15
16
 
16
17
  const cmPermissions = permissions.contentManager;
17
18
 
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Grid, GridItem } from '@strapi/design-system/Grid';
4
+ import Inputs from '../../../components/Inputs';
5
+ import FieldComponent from '../../../components/FieldComponent';
6
+
7
+ const GridRow = ({ columns, customFieldInputs }) => {
8
+ return (
9
+ <Grid gap={4}>
10
+ {columns.map(({ fieldSchema, labelAction, metadatas, name, size, queryInfos }) => {
11
+ const isComponent = fieldSchema.type === 'component';
12
+
13
+ if (isComponent) {
14
+ const { component, max, min, repeatable = false, required = false } = fieldSchema;
15
+
16
+ return (
17
+ <GridItem col={size} s={12} xs={12} key={component}>
18
+ <FieldComponent
19
+ componentUid={component}
20
+ labelAction={labelAction}
21
+ isRepeatable={repeatable}
22
+ intlLabel={{
23
+ id: metadatas.label,
24
+ defaultMessage: metadatas.label,
25
+ }}
26
+ max={max}
27
+ min={min}
28
+ name={name}
29
+ required={required}
30
+ />
31
+ </GridItem>
32
+ );
33
+ }
34
+
35
+ return (
36
+ <GridItem col={size} key={name} s={12} xs={12}>
37
+ <Inputs
38
+ size={size}
39
+ fieldSchema={fieldSchema}
40
+ keys={name}
41
+ labelAction={labelAction}
42
+ metadatas={metadatas}
43
+ queryInfos={queryInfos}
44
+ customFieldInputs={customFieldInputs}
45
+ />
46
+ </GridItem>
47
+ );
48
+ })}
49
+ </Grid>
50
+ );
51
+ };
52
+
53
+ GridRow.defaultProps = {
54
+ customFieldInputs: {},
55
+ };
56
+
57
+ GridRow.propTypes = {
58
+ columns: PropTypes.array.isRequired,
59
+ customFieldInputs: PropTypes.object,
60
+ };
61
+
62
+ export default GridRow;