@strapi/admin 4.6.0-alpha.0 → 4.6.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/admin/src/content-manager/components/ComponentInitializer/index.js +1 -7
  2. package/admin/src/content-manager/components/{RepeatableComponent/DragPreview.js → DragLayer/ComponentDragPreview.js} +25 -12
  3. package/admin/src/content-manager/components/DragLayer/RelationDragPreview.js +75 -0
  4. package/admin/src/content-manager/components/DragLayer/index.js +23 -7
  5. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +130 -84
  6. package/admin/src/content-manager/components/DynamicZone/index.js +99 -24
  7. package/admin/src/content-manager/components/DynamicZone/utils/select.js +9 -5
  8. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +76 -14
  9. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +23 -23
  10. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +24 -5
  11. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/recursivelyFindPathsBasedOnCondition.js +8 -1
  12. package/admin/src/content-manager/components/Inputs/index.js +5 -19
  13. package/admin/src/content-manager/components/NonRepeatableComponent/index.js +4 -0
  14. package/admin/src/content-manager/components/RelationInput/RelationInput.js +203 -63
  15. package/admin/src/content-manager/components/RelationInput/components/RelationItem.js +134 -21
  16. package/admin/src/content-manager/components/RelationInput/components/RelationList.js +1 -2
  17. package/admin/src/content-manager/components/RelationInput/constants.js +1 -0
  18. package/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.js +132 -10
  19. package/admin/src/content-manager/components/RepeatableComponent/components/Accordion.js +77 -0
  20. package/admin/src/content-manager/components/RepeatableComponent/components/Component.js +262 -0
  21. package/admin/src/content-manager/components/RepeatableComponent/{DraggedItem → components}/Preview.js +0 -0
  22. package/admin/src/content-manager/components/RepeatableComponent/index.js +147 -87
  23. package/admin/src/content-manager/components/RepeatableComponent/utils/getComponentErrorKeys.js +1 -1
  24. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +1 -1
  25. package/admin/src/content-manager/components/Wysiwyg/Editor.js +1 -1
  26. package/admin/src/content-manager/hooks/index.js +2 -0
  27. package/admin/src/content-manager/hooks/useDragAndDrop.js +120 -0
  28. package/admin/src/content-manager/hooks/useKeyboardDragAndDrop.js +98 -0
  29. package/admin/src/content-manager/hooks/useLazyComponents/index.js +69 -0
  30. package/admin/src/content-manager/pages/CollectionTypeRecursivePath/components/ErrorFallback.js +13 -0
  31. package/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.js +2 -1
  32. package/admin/src/content-manager/pages/EditView/GridRow/index.js +62 -0
  33. package/admin/src/content-manager/pages/EditView/index.js +74 -154
  34. package/admin/src/content-manager/pages/EditView/selectors.js +14 -0
  35. package/admin/src/content-manager/pages/EditView/utils/createAttributesLayout.js +11 -6
  36. package/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js +18 -0
  37. package/admin/src/content-manager/pages/EditView/utils/index.js +1 -0
  38. package/admin/src/content-manager/pages/EditViewLayoutManager/index.js +1 -1
  39. package/admin/src/content-manager/sharedReducers/crudReducer/actions.js +5 -0
  40. package/admin/src/content-manager/sharedReducers/crudReducer/constants.js +2 -0
  41. package/admin/src/content-manager/sharedReducers/crudReducer/reducer.js +7 -0
  42. package/admin/src/content-manager/utils/ItemTypes.js +1 -1
  43. package/admin/src/content-manager/utils/composeRefs.js +28 -0
  44. package/admin/src/content-manager/utils/getMaxTempKey.js +1 -1
  45. package/admin/src/content-manager/utils/index.js +7 -0
  46. package/admin/src/core/utils/axiosInstance.js +4 -2
  47. package/admin/src/hooks/index.js +1 -0
  48. package/admin/src/hooks/useFetchClient/index.js +23 -0
  49. package/admin/src/pages/HomePage/SocialLinks.js +4 -4
  50. package/admin/src/pages/SettingsPage/pages/Users/ListPage/ModalForm/index.js +23 -18
  51. package/admin/src/translations/en.json +6 -0
  52. package/admin/src/translations/ru.json +789 -489
  53. package/admin/src/utils/fetchClient.js +45 -0
  54. package/admin/src/utils/getFetchClient.js +10 -0
  55. package/build/4306.df40a798.chunk.js +98 -0
  56. package/build/{4318.daf31770.chunk.js → 4318.80bdf035.chunk.js} +2 -2
  57. package/build/5057.195a59ff.chunk.js +65 -0
  58. package/build/{805.a1894307.chunk.js → 805.e991a370.chunk.js} +6 -6
  59. package/build/{4986.3820d11d.chunk.js → 8176.b19bc128.chunk.js} +32 -32
  60. package/build/{1233.32d6888d.chunk.js → 8186.55910742.chunk.js} +94 -94
  61. package/build/{8633.8da5488a.chunk.js → 8633.59223842.chunk.js} +1 -1
  62. package/build/8881.c693411a.chunk.js +245 -0
  63. package/build/9161.4a0ab137.chunk.js +2119 -0
  64. package/build/9279.6290c87a.chunk.js +117 -0
  65. package/build/9707.a0cc4ad8.chunk.js +70 -0
  66. package/build/Admin-authenticatedApp.f9e74dc0.chunk.js +80 -0
  67. package/build/{Admin_homePage.b4db4df8.chunk.js → Admin_homePage.8945f71a.chunk.js} +5 -5
  68. package/build/{Admin_marketplace.fa51405b.chunk.js → Admin_marketplace.ed754a4a.chunk.js} +1 -1
  69. package/build/{Admin_pluginsPage.14d2840f.chunk.js → Admin_pluginsPage.3c872de7.chunk.js} +1 -1
  70. package/build/{Admin_profilePage.6c2c8398.chunk.js → Admin_profilePage.c07bdf08.chunk.js} +1 -1
  71. package/build/{Admin_settingsPage.5e740514.chunk.js → Admin_settingsPage.50a8765b.chunk.js} +5 -5
  72. package/build/admin-app.2861b6d2.chunk.js +112 -0
  73. package/build/{admin-edit-roles-page.c7c338b3.chunk.js → admin-edit-roles-page.f407538c.chunk.js} +1 -1
  74. package/build/{admin-edit-users.d254c128.chunk.js → admin-edit-users.85231e4c.chunk.js} +1 -1
  75. package/build/{admin-users.7c423e41.chunk.js → admin-users.a2707644.chunk.js} +2 -2
  76. package/build/api-tokens-create-page.dd4ddfcb.chunk.js +1 -0
  77. package/build/api-tokens-edit-page.821c5a6c.chunk.js +1 -0
  78. package/build/{api-tokens-list-page.fe994b6b.chunk.js → api-tokens-list-page.700e575f.chunk.js} +1 -1
  79. package/build/content-manager.ee948f75.chunk.js +1186 -0
  80. package/build/content-type-builder-list-view.4412efc3.chunk.js +201 -0
  81. package/build/content-type-builder.b132b5f4.chunk.js +145 -0
  82. package/build/email-settings-page.db0d98d1.chunk.js +15 -0
  83. package/build/{en-json.7dd57947.chunk.js → en-json.4a56dca7.chunk.js} +1 -1
  84. package/build/index.html +1 -1
  85. package/build/main.faac89ee.js +2025 -0
  86. package/build/ru-json.8830286f.chunk.js +1 -0
  87. package/build/{runtime~main.6e7d95b9.js → runtime~main.75a15b8e.js} +1 -1
  88. package/build/{sso-settings-page.eb30a02e.chunk.js → sso-settings-page.adb12ac3.chunk.js} +1 -1
  89. package/build/upload-settings.450cab1a.chunk.js +18 -0
  90. package/build/upload.e2034370.chunk.js +64 -0
  91. package/build/users-advanced-settings-page.0c0b8230.chunk.js +13 -0
  92. package/build/users-email-settings-page.3126ff8c.chunk.js +28 -0
  93. package/build/users-providers-settings-page.b7b602e2.chunk.js +33 -0
  94. package/build/users-roles-settings-page.ce5b582d.chunk.js +30 -0
  95. package/build/webhook-edit-page.1215a6b7.chunk.js +75 -0
  96. package/build/{webhook-list-page.42533b59.chunk.js → webhook-list-page.b87821f2.chunk.js} +1 -1
  97. package/ee/server/services/passport/provider-registry.js +1 -1
  98. package/package.json +15 -15
  99. package/utils/get-plugins-path.js +17 -3
  100. package/admin/src/content-manager/components/RepeatableComponent/AccordionGroupCustom/index.js +0 -122
  101. package/admin/src/content-manager/components/RepeatableComponent/AddFieldButton.js +0 -58
  102. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/DraggingSibling.js +0 -72
  103. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/IconButtonCustoms.js +0 -32
  104. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/index.js +0 -322
  105. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/utils/connect.js +0 -11
  106. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/utils/index.js +0 -2
  107. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/utils/select.js +0 -30
  108. package/admin/src/content-manager/components/RepeatableComponent/utils/connect.js +0 -11
  109. package/admin/src/content-manager/components/RepeatableComponent/utils/select.js +0 -12
  110. package/admin/src/content-manager/hooks/__test__/usePrev.test.js +0 -26
  111. package/build/2438.afe24949.chunk.js +0 -2525
  112. package/build/2517.5cc235ba.chunk.js +0 -117
  113. package/build/4306.53359960.chunk.js +0 -98
  114. package/build/8881.bfdb6877.chunk.js +0 -245
  115. package/build/9707.932a3c12.chunk.js +0 -70
  116. package/build/Admin-authenticatedApp.cfc3b4c9.chunk.js +0 -80
  117. package/build/admin-app.ee1211cb.chunk.js +0 -112
  118. package/build/api-tokens-create-page.4ca2778d.chunk.js +0 -1
  119. package/build/api-tokens-edit-page.70a791c2.chunk.js +0 -1
  120. package/build/content-manager.794d3373.chunk.js +0 -1200
  121. package/build/content-type-builder-list-view.95012cf0.chunk.js +0 -201
  122. package/build/content-type-builder.95b9d6a2.chunk.js +0 -145
  123. package/build/email-settings-page.4bb3606f.chunk.js +0 -15
  124. package/build/main.a6470578.js +0 -2031
  125. package/build/ru-json.d7cfc2ff.chunk.js +0 -1
  126. package/build/upload-settings.3010911f.chunk.js +0 -18
  127. package/build/upload.9f19f2e8.chunk.js +0 -64
  128. package/build/users-advanced-settings-page.9df41d67.chunk.js +0 -13
  129. package/build/users-email-settings-page.56d82eaf.chunk.js +0 -28
  130. package/build/users-providers-settings-page.96bb7da0.chunk.js +0 -33
  131. package/build/users-roles-settings-page.445e5e16.chunk.js +0 -30
  132. package/build/webhook-edit-page.c5efc08b.chunk.js +0 -75
@@ -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;
@@ -1,11 +1,11 @@
1
- import React, { Suspense, memo, useCallback, useMemo } from 'react';
1
+ import React, { memo } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import get from 'lodash/get';
3
+ import { useSelector } from 'react-redux';
4
4
  import {
5
5
  CheckPermissions,
6
- LoadingIndicatorPage,
7
6
  useTracking,
8
7
  LinkButton,
8
+ LoadingIndicatorPage,
9
9
  } from '@strapi/helper-plugin';
10
10
  import { useIntl } from 'react-intl';
11
11
  import { ContentLayout } from '@strapi/design-system/Layout';
@@ -18,73 +18,60 @@ import Pencil from '@strapi/icons/Pencil';
18
18
  import { InjectionZone } from '../../../shared/components';
19
19
  import permissions from '../../../permissions';
20
20
  import DynamicZone from '../../components/DynamicZone';
21
- import FieldComponent from '../../components/FieldComponent';
22
- import Inputs from '../../components/Inputs';
21
+
23
22
  import CollectionTypeFormWrapper from '../../components/CollectionTypeFormWrapper';
24
23
  import EditViewDataManagerProvider from '../../components/EditViewDataManagerProvider';
25
24
  import SingleTypeFormWrapper from '../../components/SingleTypeFormWrapper';
26
25
  import { getTrad } from '../../utils';
26
+ import useLazyComponents from '../../hooks/useLazyComponents';
27
27
  import DraftAndPublishBadge from './DraftAndPublishBadge';
28
28
  import Informations from './Informations';
29
29
  import Header from './Header';
30
- import { createAttributesLayout, getFieldsActionMatchingPermissions } from './utils';
30
+ import { getFieldsActionMatchingPermissions } from './utils';
31
31
  import DeleteLink from './DeleteLink';
32
+ import GridRow from './GridRow';
33
+ import { selectCurrentLayout, selectAttributesLayout, selectCustomFieldUids } from './selectors';
32
34
 
33
35
  const cmPermissions = permissions.contentManager;
34
36
  const ctbPermissions = [{ action: 'plugin::content-type-builder.read', subject: null }];
35
37
 
36
38
  /* eslint-disable react/no-array-index-key */
37
- const EditView = ({
38
- allowedActions,
39
- isSingleType,
40
- goBack,
41
- layout,
42
- slug,
43
- id,
44
- origin,
45
- userPermissions,
46
- }) => {
39
+ const EditView = ({ allowedActions, isSingleType, goBack, slug, id, origin, userPermissions }) => {
47
40
  const { trackUsage } = useTracking();
48
41
  const { formatMessage } = useIntl();
42
+
43
+ const { layout, formattedContentTypeLayout, customFieldUids } = useSelector((state) => ({
44
+ layout: selectCurrentLayout(state),
45
+ formattedContentTypeLayout: selectAttributesLayout(state),
46
+ customFieldUids: selectCustomFieldUids(state),
47
+ }));
48
+
49
+ const { isLazyLoading, lazyComponentStore } = useLazyComponents(customFieldUids);
50
+
49
51
  const { createActionAllowedFields, readActionAllowedFields, updateActionAllowedFields } =
50
- useMemo(() => {
51
- return getFieldsActionMatchingPermissions(userPermissions, slug);
52
- }, [userPermissions, slug]);
52
+ getFieldsActionMatchingPermissions(userPermissions, slug);
53
53
 
54
- const configurationPermissions = useMemo(() => {
55
- return isSingleType
56
- ? cmPermissions.singleTypesConfigurations
57
- : cmPermissions.collectionTypesConfigurations;
58
- }, [isSingleType]);
54
+ const configurationPermissions = isSingleType
55
+ ? cmPermissions.singleTypesConfigurations
56
+ : cmPermissions.collectionTypesConfigurations;
59
57
 
60
58
  // // FIXME when changing the routing
61
59
  const configurationsURL = `/content-manager/${
62
60
  isSingleType ? 'singleType' : 'collectionType'
63
61
  }/${slug}/configurations/edit`;
64
- const currentContentTypeLayoutData = get(layout, ['contentType'], {});
65
62
 
66
- const DataManagementWrapper = useMemo(
67
- () => (isSingleType ? SingleTypeFormWrapper : CollectionTypeFormWrapper),
68
- [isSingleType]
69
- );
63
+ const DataManagementWrapper = isSingleType ? SingleTypeFormWrapper : CollectionTypeFormWrapper;
70
64
 
71
65
  // Check if a block is a dynamic zone
72
- const isDynamicZone = useCallback((block) => {
66
+ const isDynamicZone = (block) => {
73
67
  return block.every((subBlock) => {
74
68
  return subBlock.every((obj) => obj.fieldSchema.type === 'dynamiczone');
75
69
  });
76
- }, []);
70
+ };
77
71
 
78
- const formattedContentTypeLayout = useMemo(() => {
79
- if (!currentContentTypeLayoutData.layouts) {
80
- return [];
81
- }
82
-
83
- return createAttributesLayout(
84
- currentContentTypeLayoutData.layouts.edit,
85
- currentContentTypeLayoutData.attributes
86
- );
87
- }, [currentContentTypeLayoutData]);
72
+ if (isLazyLoading) {
73
+ return <LoadingIndicatorPage />;
74
+ }
88
75
 
89
76
  return (
90
77
  <DataManagementWrapper allLayoutData={layout} slug={slug} id={id} origin={origin}>
@@ -132,110 +119,56 @@ const EditView = ({
132
119
  <ContentLayout>
133
120
  <Grid gap={4}>
134
121
  <GridItem col={9} s={12}>
135
- <Suspense fallback={<LoadingIndicatorPage />}>
136
- <Stack spacing={6}>
137
- {formattedContentTypeLayout.map((row, index) => {
138
- if (isDynamicZone(row)) {
139
- const {
140
- 0: {
141
- 0: { name, fieldSchema, metadatas, labelAction },
142
- },
143
- } = row;
144
-
145
- return (
146
- <Box key={index}>
147
- <Grid gap={4}>
148
- <GridItem col={12} s={12} xs={12}>
149
- <DynamicZone
150
- name={name}
151
- fieldSchema={fieldSchema}
152
- labelAction={labelAction}
153
- metadatas={metadatas}
154
- />
155
- </GridItem>
156
- </Grid>
157
- </Box>
158
- );
159
- }
122
+ <Stack spacing={6}>
123
+ {formattedContentTypeLayout.map((row, index) => {
124
+ if (isDynamicZone(row)) {
125
+ const {
126
+ 0: {
127
+ 0: { name, fieldSchema, metadatas, labelAction },
128
+ },
129
+ } = row;
160
130
 
161
131
  return (
162
- <Box
163
- key={index}
164
- hasRadius
165
- background="neutral0"
166
- shadow="tableShadow"
167
- paddingLeft={6}
168
- paddingRight={6}
169
- paddingTop={6}
170
- paddingBottom={6}
171
- borderColor="neutral150"
172
- >
173
- <Stack spacing={6}>
174
- {row.map((grid, gridIndex) => {
175
- return (
176
- <Grid gap={4} key={gridIndex}>
177
- {grid.map(
178
- ({
179
- fieldSchema,
180
- labelAction,
181
- metadatas,
182
- name,
183
- size,
184
- queryInfos,
185
- }) => {
186
- const isComponent = fieldSchema.type === 'component';
187
-
188
- if (isComponent) {
189
- const {
190
- component,
191
- max,
192
- min,
193
- repeatable = false,
194
- required = false,
195
- } = fieldSchema;
196
-
197
- return (
198
- <GridItem col={size} s={12} xs={12} key={component}>
199
- <FieldComponent
200
- componentUid={component}
201
- labelAction={labelAction}
202
- isRepeatable={repeatable}
203
- intlLabel={{
204
- id: metadatas.label,
205
- defaultMessage: metadatas.label,
206
- }}
207
- max={max}
208
- min={min}
209
- name={name}
210
- required={required}
211
- />
212
- </GridItem>
213
- );
214
- }
215
-
216
- return (
217
- <GridItem col={size} key={name} s={12} xs={12}>
218
- <Inputs
219
- size={size}
220
- fieldSchema={fieldSchema}
221
- keys={name}
222
- labelAction={labelAction}
223
- metadatas={metadatas}
224
- queryInfos={queryInfos}
225
- />
226
- </GridItem>
227
- );
228
- }
229
- )}
230
- </Grid>
231
- );
232
- })}
233
- </Stack>
132
+ <Box key={index}>
133
+ <Grid gap={4}>
134
+ <GridItem col={12} s={12} xs={12}>
135
+ <DynamicZone
136
+ name={name}
137
+ fieldSchema={fieldSchema}
138
+ labelAction={labelAction}
139
+ metadatas={metadatas}
140
+ />
141
+ </GridItem>
142
+ </Grid>
234
143
  </Box>
235
144
  );
236
- })}
237
- </Stack>
238
- </Suspense>
145
+ }
146
+
147
+ return (
148
+ <Box
149
+ key={index}
150
+ hasRadius
151
+ background="neutral0"
152
+ shadow="tableShadow"
153
+ paddingLeft={6}
154
+ paddingRight={6}
155
+ paddingTop={6}
156
+ paddingBottom={6}
157
+ borderColor="neutral150"
158
+ >
159
+ <Stack spacing={6}>
160
+ {row.map((grid, gridRowIndex) => (
161
+ <GridRow
162
+ columns={grid}
163
+ customFieldInputs={lazyComponentStore}
164
+ key={gridRowIndex}
165
+ />
166
+ ))}
167
+ </Stack>
168
+ </Box>
169
+ );
170
+ })}
171
+ </Stack>
239
172
  </GridItem>
240
173
  <GridItem col={3} s={12}>
241
174
  <Stack spacing={2}>
@@ -328,16 +261,6 @@ EditView.propTypes = {
328
261
  canCreate: PropTypes.bool.isRequired,
329
262
  canDelete: PropTypes.bool.isRequired,
330
263
  }).isRequired,
331
- layout: PropTypes.shape({
332
- components: PropTypes.object.isRequired,
333
- contentType: PropTypes.shape({
334
- uid: PropTypes.string.isRequired,
335
- settings: PropTypes.object.isRequired,
336
- metadatas: PropTypes.object.isRequired,
337
- options: PropTypes.object.isRequired,
338
- attributes: PropTypes.object.isRequired,
339
- }).isRequired,
340
- }).isRequired,
341
264
  id: PropTypes.string,
342
265
  isSingleType: PropTypes.bool,
343
266
  goBack: PropTypes.func.isRequired,
@@ -346,7 +269,4 @@ EditView.propTypes = {
346
269
  userPermissions: PropTypes.array,
347
270
  };
348
271
 
349
- export { EditView };
350
272
  export default memo(EditView);
351
-
352
- // export default () => 'TODO Edit view';
@@ -0,0 +1,14 @@
1
+ import { createSelector } from 'reselect';
2
+ import { createAttributesLayout, getCustomFieldUidsFromLayout } from './utils';
3
+
4
+ const selectCurrentLayout = (state) => state['content-manager_editViewLayoutManager'].currentLayout;
5
+
6
+ const selectAttributesLayout = createSelector(selectCurrentLayout, (layout) =>
7
+ createAttributesLayout(layout?.contentType ?? {})
8
+ );
9
+
10
+ const selectCustomFieldUids = createSelector(selectCurrentLayout, (layout) =>
11
+ getCustomFieldUidsFromLayout(layout)
12
+ );
13
+
14
+ export { selectCurrentLayout, selectAttributesLayout, selectCustomFieldUids };
@@ -1,14 +1,19 @@
1
1
  import { get, isEmpty } from 'lodash';
2
- // TODO: refacto this file to avoid eslint issues
3
- /* eslint-disable no-restricted-syntax */
4
- /* eslint-disable no-unused-vars */
5
2
 
6
- const createAttributesLayout = (currentLayout, attributes) => {
3
+ const createAttributesLayout = (currentContentTypeLayoutData) => {
4
+ if (!currentContentTypeLayoutData.layouts) {
5
+ return [];
6
+ }
7
+
8
+ const currentLayout = currentContentTypeLayoutData.layouts.edit;
9
+ const attributes = currentContentTypeLayoutData.attributes;
10
+
7
11
  const getType = (name) => get(attributes, [name, 'type'], '');
12
+
8
13
  let currentRowIndex = 0;
9
14
  const newLayout = [];
10
15
 
11
- for (let row of currentLayout) {
16
+ currentLayout.forEach((row) => {
12
17
  const hasDynamicZone = row.some(({ name }) => getType(name) === 'dynamiczone');
13
18
 
14
19
  if (!newLayout[currentRowIndex]) {
@@ -27,7 +32,7 @@ const createAttributesLayout = (currentLayout, attributes) => {
27
32
  } else {
28
33
  newLayout[currentRowIndex].push(row);
29
34
  }
30
- }
35
+ });
31
36
 
32
37
  return newLayout.filter((arr) => arr.length > 0);
33
38
  };
@@ -0,0 +1,18 @@
1
+ const getCustomFieldUidsFromLayout = (layout) => {
2
+ if (!layout) return [];
3
+ // Get all the fields on the content-type and its components
4
+ const allFields = [
5
+ ...layout.contentType.layouts.edit,
6
+ ...Object.values(layout.components).flatMap((component) => component.layouts.edit),
7
+ ].flat();
8
+ // Filter that down to custom fields and map the uids
9
+ const customFieldUids = allFields
10
+ .filter((field) => field.fieldSchema.customField)
11
+ .map((customField) => customField.fieldSchema.customField);
12
+ // Make sure the list is unique
13
+ const uniqueCustomFieldUids = [...new Set(customFieldUids)];
14
+
15
+ return uniqueCustomFieldUids;
16
+ };
17
+
18
+ export default getCustomFieldUidsFromLayout;
@@ -1,3 +1,4 @@
1
1
  // eslint-disable-next-line import/prefer-default-export
2
2
  export { default as createAttributesLayout } from './createAttributesLayout';
3
3
  export { default as getFieldsActionMatchingPermissions } from './getFieldsActionMatchingPermissions';
4
+ export { default as getCustomFieldUidsFromLayout } from './getCustomFieldUidsFromLayout';
@@ -30,7 +30,7 @@ const EditViewLayoutManager = ({ layout, ...rest }) => {
30
30
  return <LoadingIndicatorPage />;
31
31
  }
32
32
 
33
- return <Permissions {...rest} layout={currentLayout} userPermissions={permissions} />;
33
+ return <Permissions {...rest} userPermissions={permissions} />;
34
34
  };
35
35
 
36
36
  EditViewLayoutManager.propTypes = {
@@ -6,6 +6,7 @@ import {
6
6
  SET_DATA_STRUCTURES,
7
7
  SET_STATUS,
8
8
  SUBMIT_SUCCEEDED,
9
+ CLEAR_SET_MODIFIED_DATA_ONLY,
9
10
  } from './constants';
10
11
 
11
12
  export const getData = () => {
@@ -42,3 +43,7 @@ export const submitSucceeded = (data) => ({
42
43
  type: SUBMIT_SUCCEEDED,
43
44
  data,
44
45
  });
46
+
47
+ export const clearSetModifiedDataOnly = () => ({
48
+ type: CLEAR_SET_MODIFIED_DATA_ONLY,
49
+ });
@@ -5,3 +5,5 @@ export const RESET_PROPS = 'ContentManager/CrudReducer/RESET_PROPS';
5
5
  export const SET_DATA_STRUCTURES = 'ContentManager/CrudReducer/SET_DATA_STRUCTURES';
6
6
  export const SET_STATUS = 'ContentManager/CrudReducer/SET_STATUS';
7
7
  export const SUBMIT_SUCCEEDED = 'ContentManager/CrudReducer/SUBMIT_SUCCEEDED';
8
+ export const CLEAR_SET_MODIFIED_DATA_ONLY =
9
+ 'ContentManager/CrudReducer/CLEAR_SET_MODIFIED_DATA_ONLY';
@@ -8,6 +8,7 @@ import produce from 'immer';
8
8
  // to do any of this.
9
9
 
10
10
  import {
11
+ CLEAR_SET_MODIFIED_DATA_ONLY,
11
12
  GET_DATA,
12
13
  GET_DATA_SUCCEEDED,
13
14
  INIT_FORM,
@@ -23,6 +24,7 @@ const crudInitialState = {
23
24
  isLoading: true,
24
25
  data: null,
25
26
  status: 'resolved',
27
+ setModifiedDataOnly: false,
26
28
  };
27
29
 
28
30
  const crudReducer = (state = crudInitialState, action) =>
@@ -36,6 +38,7 @@ const crudReducer = (state = crudInitialState, action) =>
36
38
  case GET_DATA_SUCCEEDED: {
37
39
  draftState.isLoading = false;
38
40
  draftState.data = action.data;
41
+ draftState.setModifiedDataOnly = action.setModifiedDataOnly ?? false;
39
42
  break;
40
43
  }
41
44
  case INIT_FORM: {
@@ -66,6 +69,10 @@ const crudReducer = (state = crudInitialState, action) =>
66
69
  draftState.data = action.data;
67
70
  break;
68
71
  }
72
+ case CLEAR_SET_MODIFIED_DATA_ONLY: {
73
+ draftState.setModifiedDataOnly = false;
74
+ break;
75
+ }
69
76
  default:
70
77
  return draftState;
71
78
  }
@@ -1,7 +1,7 @@
1
1
  export default {
2
2
  COMPONENT: 'component',
3
3
  EDIT_FIELD: 'editField',
4
- EDIT_RELATION: 'editRelation',
5
4
  FIELD: 'field',
5
+ DYNAMIC_ZONE: 'dynamicZone',
6
6
  RELATION: 'relation',
7
7
  };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @typedef PossibleRef<T>
3
+ * @type {React.Ref<T> | undefined;}
4
+ *
5
+ * @typedef setRef
6
+ * @type {<T>(ref: PossibleRef<T>, value: T) => React.RefCallback<T>}
7
+ */
8
+
9
+ /**
10
+ * @type {setRef}
11
+ */
12
+ const setRef = (ref, value) => {
13
+ if (typeof ref === 'function') {
14
+ ref(value);
15
+ } else if (ref !== null && ref !== undefined) {
16
+ ref.current = value;
17
+ }
18
+ };
19
+
20
+ /**
21
+ * A utility to compose multiple refs together
22
+ * Accepts callback refs and RefObject(s)
23
+ *
24
+ * @type {<T>(...refs: PossibleRef<T>[]) => (node: T) => void}
25
+ */
26
+ export const composeRefs = (...refs) => {
27
+ return (node) => refs.forEach((ref) => setRef(ref, node));
28
+ };
@@ -5,7 +5,7 @@ const getMaxTempKey = (arr) => {
5
5
 
6
6
  return Math.max.apply(
7
7
  Math,
8
- arr.map((o) => o.__temp_key__)
8
+ arr.map((o) => o.__temp_key__ ?? o.id)
9
9
  );
10
10
  };
11
11
 
@@ -1,13 +1,20 @@
1
1
  export { default as arrayMoveItem } from './arrayMoveItem';
2
+
2
3
  export { default as checkIfAttributeIsDisplayable } from './checkIfAttributeIsDisplayable';
4
+ export { composeRefs } from './composeRefs';
3
5
  export { default as createDefaultForm } from './createDefaultForm';
6
+
4
7
  export { default as formatLayoutToApi } from './formatLayoutToApi';
8
+
5
9
  export { default as generatePermissionsObject } from './generatePermissionsObject';
6
10
  export { default as getFieldName } from './getFieldName';
7
11
  export { default as getMaxTempKey } from './getMaxTempKey';
8
12
  export { default as getRequestUrl } from './getRequestUrl';
9
13
  export { default as getTrad } from './getTrad';
14
+
10
15
  export { default as ItemTypes } from './ItemTypes';
16
+
11
17
  export { default as mergeMetasWithSchema } from './mergeMetasWithSchema';
18
+
12
19
  export { default as removeKeyInObject } from './removeKeyInObject';
13
20
  export { default as removePasswordFieldsFromData } from './removePasswordFieldsFromData';
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import { auth } from '@strapi/helper-plugin';
2
+ import { auth, wrapAxiosInstance } from '@strapi/helper-plugin';
3
3
 
4
4
  const instance = axios.create({
5
5
  baseURL: process.env.STRAPI_ADMIN_BACKEND_URL,
@@ -33,4 +33,6 @@ instance.interceptors.response.use(
33
33
  }
34
34
  );
35
35
 
36
- export default instance;
36
+ const wrapper = wrapAxiosInstance(instance);
37
+
38
+ export default wrapper;
@@ -10,3 +10,4 @@ export { default as usePermissionsDataManager } from './usePermissionsDataManage
10
10
  export { default as useReleaseNotification } from './useReleaseNotification';
11
11
  export { default as useThemeToggle } from './useThemeToggle';
12
12
  export { default as useRegenerate } from './useRegenerate';
13
+ export { default as useFetchClient } from './useFetchClient';
@@ -0,0 +1,23 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { getFetchClient } from '../../utils/getFetchClient';
3
+
4
+ const useFetchClient = () => {
5
+ const controller = useRef(null);
6
+
7
+ if (controller.current === null) {
8
+ controller.current = new AbortController();
9
+ }
10
+ useEffect(() => {
11
+ return () => {
12
+ controller.current.abort();
13
+ };
14
+ }, []);
15
+
16
+ const defaultOptions = {
17
+ signal: controller.current.signal,
18
+ };
19
+
20
+ return getFetchClient(defaultOptions);
21
+ };
22
+
23
+ export default useFetchClient;
@@ -33,13 +33,13 @@ const StyledReddit = styled(Reddit)`
33
33
  `;
34
34
  const StyledStrapi = styled(Strapi)`
35
35
  > path:first-child {
36
- fill: #8e75ff;
36
+ fill: #4945ff;
37
37
  }
38
38
  > path:nth-child(2) {
39
- fill: #8e75ff;
39
+ fill: #fff;
40
40
  }
41
- > path:nth-child(3) {
42
- fill: #8e75ff;
41
+ > path:nth-child(4) {
42
+ fill: #9593ff;
43
43
  }
44
44
  `;
45
45