@strapi/admin 4.9.1 → 4.9.2

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 (71) hide show
  1. package/admin/src/components/LanguageProvider/index.js +1 -1
  2. package/admin/src/components/LocalesProvider/index.js +2 -3
  3. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +3 -6
  4. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +9 -5
  5. package/admin/src/content-manager/components/InputUID/index.js +1 -1
  6. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +4 -8
  7. package/admin/src/content-manager/pages/App/LeftMenu/index.js +56 -35
  8. package/admin/src/content-manager/pages/App/actions.js +19 -7
  9. package/admin/src/content-manager/pages/App/constants.js +3 -3
  10. package/admin/src/content-manager/pages/App/index.js +3 -2
  11. package/admin/src/content-manager/pages/App/reducer.js +7 -6
  12. package/admin/src/content-manager/pages/App/selectors.js +3 -0
  13. package/admin/src/content-manager/pages/App/{useModels.js → useContentManagerInitData.js} +29 -28
  14. package/admin/src/content-manager/pages/App/utils/generateModelsLinks.js +2 -2
  15. package/admin/src/content-manager/pages/App/utils/getContentTypeLinks.js +17 -15
  16. package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +4 -5
  17. package/admin/src/content-manager/pages/EditSettingsView/index.js +4 -0
  18. package/admin/src/content-manager/pages/EditSettingsView/reducer.js +6 -7
  19. package/admin/src/content-manager/pages/EditSettingsView/utils/layout.js +1 -30
  20. package/admin/src/content-manager/pages/EditView/DeleteLink/index.js +5 -11
  21. package/admin/src/content-manager/pages/EditView/index.js +2 -7
  22. package/admin/src/content-manager/pages/ListSettingsView/index.js +1 -0
  23. package/admin/src/hooks/useFetchMarketplacePlugins/utils/api.js +7 -8
  24. package/admin/src/hooks/useFetchMarketplaceProviders/utils/api.js +5 -0
  25. package/admin/src/pages/HomePage/SocialLinks.js +1 -1
  26. package/admin/src/pages/MarketplacePage/components/EmptyNpmPackageSearch/index.js +1 -1
  27. package/admin/src/pages/MarketplacePage/components/NpmPackagesGrid/index.js +42 -9
  28. package/admin/src/pages/MarketplacePage/components/NpmPackagesPagination/index.js +26 -0
  29. package/admin/src/pages/MarketplacePage/components/OfflineLayout/index.js +45 -0
  30. package/admin/src/pages/MarketplacePage/index.js +80 -175
  31. package/admin/src/pages/MarketplacePage/utils/useMarketplaceData.js +85 -0
  32. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/components/RoleRow/index.js +12 -4
  33. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/index.js +21 -2
  34. package/admin/src/translations/en.json +51 -50
  35. package/admin/src/translations/ru.json +51 -19
  36. package/build/{Admin-authenticatedApp.a168aa38.chunk.js → Admin-authenticatedApp.217db666.chunk.js} +5 -5
  37. package/build/{Admin_homePage.da2181fe.chunk.js → Admin_homePage.f9309c6d.chunk.js} +1 -1
  38. package/build/Admin_marketplace.56bc1008.chunk.js +31 -0
  39. package/build/{Admin_settingsPage.cb63220f.chunk.js → Admin_settingsPage.1dbfc9ce.chunk.js} +1 -1
  40. package/build/{admin-app.8cde5b22.chunk.js → admin-app.558af642.chunk.js} +6 -6
  41. package/build/admin-roles-list.329c1f63.chunk.js +31 -0
  42. package/build/audit-logs-settings-page.19d90bda.chunk.js +76 -0
  43. package/build/content-manager.d1565bfc.chunk.js +1132 -0
  44. package/build/content-type-builder-translation-en-json.6c8e69ab.chunk.js +1 -0
  45. package/build/content-type-builder.9d780e7f.chunk.js +126 -0
  46. package/build/en-json.cf600231.chunk.js +1 -0
  47. package/build/index.html +1 -1
  48. package/build/main.ef8db4a2.js +2280 -0
  49. package/build/ru-json.e0662702.chunk.js +1 -0
  50. package/build/{runtime~main.03cdff31.js → runtime~main.3a92d953.js} +2 -2
  51. package/build/users-roles-settings-page.2f85dcec.chunk.js +30 -0
  52. package/ee/admin/hooks/useLicenseLimitNotification/index.js +1 -1
  53. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/hooks/useAuditLogsData.js +6 -3
  54. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/index.js +15 -5
  55. package/ee/admin/pages/SettingsPage/pages/AuditLogs/ListView/utils/getDisplayedFilters.js +52 -45
  56. package/package.json +10 -10
  57. package/webpack.config.js +5 -1
  58. package/admin/src/content-manager/pages/App/LeftMenu/utils/index.js +0 -1
  59. package/admin/src/content-manager/pages/App/LeftMenu/utils/matchByTitle.js +0 -24
  60. package/build/9347.058ddb22.chunk.js +0 -1
  61. package/build/Admin_marketplace.99e25059.chunk.js +0 -31
  62. package/build/admin-roles-list.97e198f9.chunk.js +0 -31
  63. package/build/audit-logs-settings-page.ca9a3c46.chunk.js +0 -76
  64. package/build/content-manager.ba088a66.chunk.js +0 -1132
  65. package/build/content-type-builder-translation-en-json.e577d595.chunk.js +0 -1
  66. package/build/content-type-builder.fef159db.chunk.js +0 -126
  67. package/build/en-json.b052667a.chunk.js +0 -1
  68. package/build/main.0df5f5ca.js +0 -2280
  69. package/build/ru-json.6a01cea6.chunk.js +0 -1
  70. package/build/users-roles-settings-page.9359e4d1.chunk.js +0 -30
  71. /package/admin/src/{content-manager/components/InputUID/useDebounce.js → hooks/useDebounce/index.js} +0 -0
@@ -35,7 +35,7 @@ const LanguageProvider = ({ children, localeNames, messages }) => {
35
35
 
36
36
  return (
37
37
  <IntlProvider locale={locale} defaultLocale="en" messages={appMessages} textComponent="span">
38
- <LocalesProvider changeLocale={changeLocale} localeNames={localeNames} messages={appMessages}>
38
+ <LocalesProvider changeLocale={changeLocale} localeNames={localeNames}>
39
39
  {children}
40
40
  </LocalesProvider>
41
41
  </IntlProvider>
@@ -2,9 +2,9 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import LocalesProviderContext from './context';
4
4
 
5
- const LocalesProvider = ({ changeLocale, children, localeNames, messages }) => {
5
+ const LocalesProvider = ({ changeLocale, children, localeNames }) => {
6
6
  return (
7
- <LocalesProviderContext.Provider value={{ changeLocale, localeNames, messages }}>
7
+ <LocalesProviderContext.Provider value={{ changeLocale, localeNames }}>
8
8
  {children}
9
9
  </LocalesProviderContext.Provider>
10
10
  );
@@ -14,7 +14,6 @@ LocalesProvider.propTypes = {
14
14
  changeLocale: PropTypes.func.isRequired,
15
15
  children: PropTypes.element.isRequired,
16
16
  localeNames: PropTypes.object.isRequired,
17
- messages: PropTypes.object.isRequired,
18
17
  };
19
18
 
20
19
  export default LocalesProvider;
@@ -222,6 +222,8 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
222
222
 
223
223
  trackUsageRef.current('didDeleteEntry', trackerProperty);
224
224
 
225
+ replace(redirectionLink);
226
+
225
227
  return Promise.resolve(data);
226
228
  } catch (err) {
227
229
  trackUsageRef.current('didNotDeleteEntry', { error: err, ...trackerProperty });
@@ -229,13 +231,9 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
229
231
  return Promise.reject(err);
230
232
  }
231
233
  },
232
- [id, slug, toggleNotification, del]
234
+ [id, slug, toggleNotification, del, redirectionLink, replace]
233
235
  );
234
236
 
235
- const onDeleteSucceeded = useCallback(() => {
236
- replace(redirectionLink);
237
- }, [redirectionLink, replace]);
238
-
239
237
  const onPost = useCallback(
240
238
  async (body, trackerProperty) => {
241
239
  const endPoint = `${getRequestUrl(`collection-types/${slug}`)}${rawQuery}`;
@@ -409,7 +407,6 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
409
407
  isCreatingEntry,
410
408
  isLoadingForData: isLoading,
411
409
  onDelete,
412
- onDeleteSucceeded,
413
410
  onPost,
414
411
  onPublish,
415
412
  onDraftRelationCheck,
@@ -186,11 +186,15 @@ const reducer = (state, action) =>
186
186
  const newRelations = [...modifiedDataRelations];
187
187
 
188
188
  if (action.type === 'REORDER_RELATION') {
189
- const [newKey] = generateNKeysBetween(
190
- modifiedDataRelations[newIndex - 1]?.__temp_key__,
191
- modifiedDataRelations[newIndex]?.__temp_key__,
192
- 1
193
- );
189
+ const startKey =
190
+ oldIndex > newIndex
191
+ ? modifiedDataRelations[newIndex - 1]?.__temp_key__
192
+ : modifiedDataRelations[newIndex]?.__temp_key__;
193
+ const endKey =
194
+ oldIndex > newIndex
195
+ ? modifiedDataRelations[newIndex]?.__temp_key__
196
+ : modifiedDataRelations[newIndex + 1]?.__temp_key__;
197
+ const [newKey] = generateNKeysBetween(startKey, endKey, 1);
194
198
 
195
199
  newRelations.splice(oldIndex, 1);
196
200
  newRelations.splice(newIndex, 0, { ...currentItem, __temp_key__: newKey });
@@ -11,7 +11,7 @@ import { Flex, TextInput, Typography } from '@strapi/design-system';
11
11
  import { Refresh, CheckCircle, ExclamationMarkCircle, Loader } from '@strapi/icons';
12
12
 
13
13
  import { getRequestUrl } from '../../utils';
14
- import useDebounce from './useDebounce';
14
+ import useDebounce from '../../../hooks/useDebounce';
15
15
  import UID_REGEX from './regex';
16
16
  import { FieldActionWrapper, TextValidation, LoadingWrapper } from './endActionStyle';
17
17
 
@@ -172,6 +172,9 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
172
172
 
173
173
  trackUsageRef.current('didDeleteEntry', trackerProperty);
174
174
 
175
+ setIsCreatingEntry(true);
176
+ dispatch(initForm(rawQuery, true));
177
+
175
178
  return Promise.resolve(data);
176
179
  } catch (err) {
177
180
  trackUsageRef.current('didNotDeleteEntry', { error: err, ...trackerProperty });
@@ -181,15 +184,9 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
181
184
  return Promise.reject(err);
182
185
  }
183
186
  },
184
- [del, slug, displayErrors, toggleNotification, searchToSend]
187
+ [del, slug, displayErrors, toggleNotification, searchToSend, dispatch, rawQuery]
185
188
  );
186
189
 
187
- const onDeleteSucceeded = useCallback(() => {
188
- setIsCreatingEntry(true);
189
-
190
- dispatch(initForm(rawQuery, true));
191
- }, [dispatch, rawQuery]);
192
-
193
190
  const onPost = useCallback(
194
191
  async (body, trackerProperty) => {
195
192
  const endPoint = getRequestUrl(`${slug}${rawQuery}`);
@@ -370,7 +367,6 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
370
367
  isCreatingEntry,
371
368
  isLoadingForData: isLoading,
372
369
  onDelete,
373
- onDeleteSucceeded,
374
370
  onPost,
375
371
  onDraftRelationCheck,
376
372
  onPublish,
@@ -16,51 +16,72 @@ import {
16
16
  SubNavSections,
17
17
  SubNavLink,
18
18
  } from '@strapi/design-system/v2';
19
+ import { useFilter, useCollator } from '@strapi/helper-plugin';
19
20
 
20
- import { matchByTitle } from './utils';
21
21
  import getTrad from '../../../utils/getTrad';
22
22
  import { makeSelectModelLinks } from '../selectors';
23
23
 
24
24
  const LeftMenu = () => {
25
25
  const [search, setSearch] = useState('');
26
- const { formatMessage } = useIntl();
26
+ const { formatMessage, locale } = useIntl();
27
27
  const modelLinksSelector = useMemo(makeSelectModelLinks, []);
28
- const { collectionTypeLinks, singleTypeLinks } = useSelector(
29
- (state) => modelLinksSelector(state),
30
- shallowEqual
31
- );
28
+ const { collectionTypeLinks, singleTypeLinks } = useSelector(modelLinksSelector, shallowEqual);
32
29
 
33
- const toIntl = (links) =>
34
- links.map((link) => {
35
- return {
36
- ...link,
37
- title: formatMessage({ id: link.title, defaultMessage: link.title }),
38
- };
39
- });
30
+ const { startsWith } = useFilter(locale, {
31
+ sensitivity: 'base',
32
+ });
40
33
 
41
- const intlCollectionTypeLinks = toIntl(collectionTypeLinks);
42
- const intlSingleTypeLinks = toIntl(singleTypeLinks);
34
+ /**
35
+ * @type {Intl.Collator}
36
+ */
37
+ const formatter = useCollator(locale, {
38
+ sensitivity: 'base',
39
+ });
43
40
 
44
- const menu = [
45
- {
46
- id: 'collectionTypes',
47
- title: {
48
- id: getTrad('components.LeftMenu.collection-types'),
49
- defaultMessage: 'Collection Types',
50
- },
51
- searchable: true,
52
- links: matchByTitle(intlCollectionTypeLinks, search),
53
- },
54
- {
55
- id: 'singleTypes',
56
- title: {
57
- id: getTrad('components.LeftMenu.single-types'),
58
- defaultMessage: 'Single Types',
59
- },
60
- searchable: true,
61
- links: matchByTitle(intlSingleTypeLinks, search),
62
- },
63
- ];
41
+ const menu = useMemo(
42
+ () =>
43
+ [
44
+ {
45
+ id: 'collectionTypes',
46
+ title: {
47
+ id: getTrad('components.LeftMenu.collection-types'),
48
+ defaultMessage: 'Collection Types',
49
+ },
50
+ searchable: true,
51
+ links: collectionTypeLinks,
52
+ },
53
+ {
54
+ id: 'singleTypes',
55
+ title: {
56
+ id: getTrad('components.LeftMenu.single-types'),
57
+ defaultMessage: 'Single Types',
58
+ },
59
+ searchable: true,
60
+ links: singleTypeLinks,
61
+ },
62
+ ].map((section) => ({
63
+ ...section,
64
+ links: section.links
65
+ /**
66
+ * Filter by the search value
67
+ */
68
+ .filter((link) => startsWith(link.title, search))
69
+ /**
70
+ * Sort correctly using the language
71
+ */
72
+ .sort((a, b) => formatter.compare(a.title, b.title))
73
+ /**
74
+ * Apply the formated strings to the links from react-intl
75
+ */
76
+ .map((link) => {
77
+ return {
78
+ ...link,
79
+ title: formatMessage({ id: link.title, defaultMessage: link.title }),
80
+ };
81
+ }),
82
+ })),
83
+ [collectionTypeLinks, search, singleTypeLinks, startsWith, formatMessage, formatter]
84
+ );
64
85
 
65
86
  const handleClear = () => {
66
87
  setSearch('');
@@ -1,12 +1,24 @@
1
- import { GET_DATA, RESET_PROPS, SET_CONTENT_TYPE_LINKS } from './constants';
1
+ import { GET_INIT_DATA, RESET_INIT_DATA, SET_INIT_DATA } from './constants';
2
2
 
3
- export const getData = () => ({
4
- type: GET_DATA,
3
+ export const getInitData = () => ({
4
+ type: GET_INIT_DATA,
5
5
  });
6
6
 
7
- export const resetProps = () => ({ type: RESET_PROPS });
7
+ export const resetInitData = () => ({ type: RESET_INIT_DATA });
8
8
 
9
- export const setContentTypeLinks = (authorizedCtLinks, authorizedStLinks, models, components) => ({
10
- type: SET_CONTENT_TYPE_LINKS,
11
- data: { authorizedCtLinks, authorizedStLinks, components, contentTypeSchemas: models },
9
+ export const setInitData = ({
10
+ authorizedCollectionTypeLinks,
11
+ authorizedSingleTypeLinks,
12
+ contentTypeSchemas,
13
+ components,
14
+ fieldSizes,
15
+ }) => ({
16
+ type: SET_INIT_DATA,
17
+ data: {
18
+ authorizedCollectionTypeLinks,
19
+ authorizedSingleTypeLinks,
20
+ components,
21
+ contentTypeSchemas,
22
+ fieldSizes,
23
+ },
12
24
  });
@@ -1,3 +1,3 @@
1
- export const GET_DATA = 'ContentManager/App/GET_DATA';
2
- export const RESET_PROPS = 'ContentManager/App/RESET_PROPS';
3
- export const SET_CONTENT_TYPE_LINKS = 'ContentManager/App/SET_CONTENT_TYPE_LINKS';
1
+ export const GET_INIT_DATA = 'ContentManager/App/GET_INIT_DATA';
2
+ export const RESET_INIT_DATA = 'ContentManager/App/RESET_INIT_DATA';
3
+ export const SET_INIT_DATA = 'ContentManager/App/SET_INIT_DATA';
@@ -20,13 +20,14 @@ import NoContentType from '../NoContentType';
20
20
  import NoPermissions from '../NoPermissions';
21
21
  import SingleTypeRecursivePath from '../SingleTypeRecursivePath';
22
22
  import LeftMenu from './LeftMenu';
23
- import useModels from './useModels';
23
+ import useContentManagerInitData from './useContentManagerInitData';
24
24
 
25
25
  const cmPermissions = permissions.contentManager;
26
26
 
27
27
  const App = () => {
28
28
  const contentTypeMatch = useRouteMatch(`/content-manager/:kind/:uid`);
29
- const { status, collectionTypeLinks, singleTypeLinks, models, refetchData } = useModels();
29
+ const { status, collectionTypeLinks, singleTypeLinks, models, refetchData } =
30
+ useContentManagerInitData();
30
31
  const authorisedModels = sortBy([...collectionTypeLinks, ...singleTypeLinks], (model) =>
31
32
  model.title.toLowerCase()
32
33
  );
@@ -4,7 +4,7 @@
4
4
  */
5
5
  /* eslint-disable consistent-return */
6
6
  import produce from 'immer';
7
- import { GET_DATA, RESET_PROPS, SET_CONTENT_TYPE_LINKS } from './constants';
7
+ import { GET_INIT_DATA, RESET_INIT_DATA, SET_INIT_DATA } from './constants';
8
8
 
9
9
  const initialState = {
10
10
  components: [],
@@ -20,22 +20,23 @@ const initialState = {
20
20
  const mainReducer = (state = initialState, action) =>
21
21
  produce(state, (draftState) => {
22
22
  switch (action.type) {
23
- case GET_DATA: {
23
+ case GET_INIT_DATA: {
24
24
  draftState.status = 'loading';
25
25
  break;
26
26
  }
27
- case RESET_PROPS: {
27
+ case RESET_INIT_DATA: {
28
28
  return initialState;
29
29
  }
30
- case SET_CONTENT_TYPE_LINKS: {
31
- draftState.collectionTypeLinks = action.data.authorizedCtLinks.filter(
30
+ case SET_INIT_DATA: {
31
+ draftState.collectionTypeLinks = action.data.authorizedCollectionTypeLinks.filter(
32
32
  ({ isDisplayed }) => isDisplayed
33
33
  );
34
- draftState.singleTypeLinks = action.data.authorizedStLinks.filter(
34
+ draftState.singleTypeLinks = action.data.authorizedSingleTypeLinks.filter(
35
35
  ({ isDisplayed }) => isDisplayed
36
36
  );
37
37
  draftState.components = action.data.components;
38
38
  draftState.models = action.data.contentTypeSchemas;
39
+ draftState.fieldSizes = action.data.fieldSizes;
39
40
  draftState.status = 'resolved';
40
41
  break;
41
42
  }
@@ -23,10 +23,13 @@ const makeSelectModelAndComponentSchemas = () =>
23
23
  schemas: [...components, ...models],
24
24
  }));
25
25
 
26
+ const selectFieldSizes = createSelector(selectAppDomain(), (state) => state.fieldSizes);
27
+
26
28
  export default makeSelectApp;
27
29
  export {
28
30
  makeSelectModelAndComponentSchemas,
29
31
  makeSelectModelLinks,
30
32
  makeSelectModels,
33
+ selectFieldSizes,
31
34
  selectAppDomain,
32
35
  };
@@ -11,11 +11,11 @@ import axios from 'axios';
11
11
  import { useIntl } from 'react-intl';
12
12
  import { MUTATE_COLLECTION_TYPES_LINKS, MUTATE_SINGLE_TYPES_LINKS } from '../../../exposedHooks';
13
13
  import { getRequestUrl, getTrad } from '../../utils';
14
- import { getData, resetProps, setContentTypeLinks } from './actions';
14
+ import { getInitData, resetInitData, setInitData } from './actions';
15
15
  import { selectAppDomain } from './selectors';
16
16
  import getContentTypeLinks from './utils/getContentTypeLinks';
17
17
 
18
- const useModels = () => {
18
+ const useContentManagerInitData = () => {
19
19
  const dispatch = useDispatch();
20
20
  const toggleNotification = useNotification();
21
21
  const state = useSelector(selectAppDomain());
@@ -29,22 +29,14 @@ const useModels = () => {
29
29
  const { get } = useFetchClient();
30
30
 
31
31
  const fetchData = async () => {
32
- dispatch(getData());
32
+ dispatch(getInitData());
33
33
 
34
34
  try {
35
- const [
36
- {
37
- data: { data: components },
38
- },
39
- {
40
- data: { data: models },
35
+ const {
36
+ data: {
37
+ data: { components, contentTypes: models, fieldSizes },
41
38
  },
42
- ] = await Promise.all(
43
- ['components', 'content-types'].map((endPoint) =>
44
- get(getRequestUrl(endPoint), { cancelToken: source.token })
45
- )
46
- );
47
-
39
+ } = await get(getRequestUrl('init'), { cancelToken: source.token });
48
40
  notifyStatus(
49
41
  formatMessage({
50
42
  id: getTrad('App.schemas.data-loaded'),
@@ -52,22 +44,31 @@ const useModels = () => {
52
44
  })
53
45
  );
54
46
 
55
- const { authorizedCtLinks, authorizedStLinks } = await getContentTypeLinks(
56
- models,
57
- allPermissions,
58
- toggleNotification
59
- );
60
-
61
- const { ctLinks } = runHookWaterfall(MUTATE_COLLECTION_TYPES_LINKS, {
62
- ctLinks: authorizedCtLinks,
47
+ const unmutatedContentTypeLinks = await getContentTypeLinks({
63
48
  models,
49
+ userPermissions: allPermissions,
50
+ toggleNotification,
64
51
  });
65
- const { stLinks } = runHookWaterfall(MUTATE_SINGLE_TYPES_LINKS, {
66
- stLinks: authorizedStLinks,
52
+
53
+ const { ctLinks: authorizedCollectionTypeLinks } = runHookWaterfall(
54
+ MUTATE_COLLECTION_TYPES_LINKS,
55
+ {
56
+ ctLinks: unmutatedContentTypeLinks.authorizedCollectionTypeLinks,
57
+ models,
58
+ }
59
+ );
60
+ const { stLinks: authorizedSingleTypeLinks } = runHookWaterfall(MUTATE_SINGLE_TYPES_LINKS, {
61
+ stLinks: unmutatedContentTypeLinks.authorizedSingleTypeLinks,
67
62
  models,
68
63
  });
69
64
 
70
- const actionToDispatch = setContentTypeLinks(ctLinks, stLinks, models, components);
65
+ const actionToDispatch = setInitData({
66
+ authorizedCollectionTypeLinks,
67
+ authorizedSingleTypeLinks,
68
+ contentTypeSchemas: models,
69
+ components,
70
+ fieldSizes,
71
+ });
71
72
 
72
73
  dispatch(actionToDispatch);
73
74
  } catch (err) {
@@ -88,7 +89,7 @@ const useModels = () => {
88
89
 
89
90
  return () => {
90
91
  source.cancel('Operation canceled by the user.');
91
- dispatch(resetProps());
92
+ dispatch(resetInitData());
92
93
  };
93
94
  // eslint-disable-next-line react-hooks/exhaustive-deps
94
95
  }, [dispatch, toggleNotification]);
@@ -96,4 +97,4 @@ const useModels = () => {
96
97
  return { ...state, refetchData: fetchDataRef.current };
97
98
  };
98
99
 
99
- export default useModels;
100
+ export default useContentManagerInitData;
@@ -52,12 +52,12 @@ const generateModelsLinks = (models, modelsConfigurations) => {
52
52
  const [collectionTypes, singleTypes] = sortBy(groupedModels, 'name');
53
53
 
54
54
  return {
55
- collectionTypesSectionLinks: generateLinks(
55
+ collectionTypeSectionLinks: generateLinks(
56
56
  collectionTypes?.links || [],
57
57
  'collectionTypes',
58
58
  modelsConfigurations
59
59
  ),
60
- singleTypesSectionLinks: generateLinks(singleTypes?.links ?? [], 'singleTypes'),
60
+ singleTypeSectionLinks: generateLinks(singleTypes?.links ?? [], 'singleTypes'),
61
61
  };
62
62
  };
63
63
 
@@ -3,36 +3,38 @@ import generateModelsLinks from './generateModelsLinks';
3
3
  import checkPermissions from './checkPermissions';
4
4
  import { getRequestUrl } from '../../../utils';
5
5
 
6
- const getContentTypeLinks = async (models, userPermissions, toggleNotification) => {
6
+ const getContentTypeLinks = async ({ models, userPermissions, toggleNotification }) => {
7
7
  const { get } = getFetchClient();
8
8
  try {
9
9
  const {
10
10
  data: { data: contentTypeConfigurations },
11
11
  } = await get(getRequestUrl('content-types-settings'));
12
12
 
13
- const { collectionTypesSectionLinks, singleTypesSectionLinks } = generateModelsLinks(
13
+ const { collectionTypeSectionLinks, singleTypeSectionLinks } = generateModelsLinks(
14
14
  models,
15
15
  contentTypeConfigurations
16
16
  );
17
17
 
18
- // Content Types verifications
19
- const ctLinksPermissionsPromises = checkPermissions(
20
- userPermissions,
21
- collectionTypesSectionLinks
18
+ // Collection Types verifications
19
+ const collectionTypeLinksPermissions = await Promise.all(
20
+ checkPermissions(userPermissions, collectionTypeSectionLinks)
22
21
  );
23
- const ctLinksPermissions = await Promise.all(ctLinksPermissionsPromises);
24
- const authorizedCtLinks = collectionTypesSectionLinks.filter(
25
- (_, index) => ctLinksPermissions[index]
22
+ const authorizedCollectionTypeLinks = collectionTypeSectionLinks.filter(
23
+ (_, index) => collectionTypeLinksPermissions[index]
26
24
  );
27
25
 
28
26
  // Single Types verifications
29
- const stLinksPermissionsPromises = checkPermissions(userPermissions, singleTypesSectionLinks);
30
- const stLinksPermissions = await Promise.all(stLinksPermissionsPromises);
31
- const authorizedStLinks = singleTypesSectionLinks.filter(
32
- (_, index) => stLinksPermissions[index]
27
+ const singleTypeLinksPermissions = await Promise.all(
28
+ checkPermissions(userPermissions, singleTypeSectionLinks)
29
+ );
30
+ const authorizedSingleTypeLinks = singleTypeSectionLinks.filter(
31
+ (_, index) => singleTypeLinksPermissions[index]
33
32
  );
34
33
 
35
- return { authorizedCtLinks, authorizedStLinks };
34
+ return {
35
+ authorizedCollectionTypeLinks,
36
+ authorizedSingleTypeLinks,
37
+ };
36
38
  } catch (err) {
37
39
  console.error(err);
38
40
 
@@ -41,7 +43,7 @@ const getContentTypeLinks = async (models, userPermissions, toggleNotification)
41
43
  message: { id: 'notification.error' },
42
44
  });
43
45
 
44
- return { authorizedCtLinks: [], authorizedStLinks: [], contentTypes: [] };
46
+ return { authorizedCollectionTypeLinks: [], authorizedSingleTypeLinks: [] };
45
47
  }
46
48
  };
47
49
 
@@ -6,7 +6,7 @@ import { useSelector, shallowEqual } from 'react-redux';
6
6
  import { useIntl } from 'react-intl';
7
7
  import { useLayoutDnd } from '../../../hooks';
8
8
  import { createPossibleMainFieldsForModelsAndComponents, getInputProps } from '../utils';
9
- import { makeSelectModelAndComponentSchemas } from '../../App/selectors';
9
+ import { makeSelectModelAndComponentSchemas, selectFieldSizes } from '../../App/selectors';
10
10
  import getTrad from '../../../utils/getTrad';
11
11
  import GenericInput from './GenericInput';
12
12
 
@@ -17,8 +17,6 @@ const FIELD_SIZES = [
17
17
  [12, '100%'],
18
18
  ];
19
19
 
20
- const NON_RESIZABLE_FIELD_TYPES = ['dynamiczone', 'component', 'json', 'richtext'];
21
-
22
20
  const TIME_FIELD_OPTIONS = [1, 5, 10, 15, 30, 60];
23
21
 
24
22
  const TIME_FIELD_TYPES = ['datetime', 'time'];
@@ -28,6 +26,7 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => {
28
26
  const { modifiedData, selectedField, attributes, fieldForm } = useLayoutDnd();
29
27
  const schemasSelector = useMemo(makeSelectModelAndComponentSchemas, []);
30
28
  const { schemas } = useSelector((state) => schemasSelector(state), shallowEqual);
29
+ const fieldSizes = useSelector(selectFieldSizes);
31
30
 
32
31
  const formToDisplay = useMemo(() => {
33
32
  if (!selectedField) {
@@ -103,7 +102,7 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => {
103
102
  );
104
103
  });
105
104
 
106
- const canResize = !NON_RESIZABLE_FIELD_TYPES.includes(attributes[selectedField].type);
105
+ const { isResizable } = fieldSizes[attributes[selectedField].type];
107
106
 
108
107
  const sizeField = (
109
108
  <GridItem col={6} key="size">
@@ -152,7 +151,7 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => {
152
151
  return (
153
152
  <>
154
153
  {metaFields}
155
- {canResize && sizeField}
154
+ {isResizable && sizeField}
156
155
  {hasTimePicker && timeStepField}
157
156
  </>
158
157
  );
@@ -26,6 +26,7 @@ import {
26
26
  Divider,
27
27
  } from '@strapi/design-system';
28
28
  import { ArrowLeft, Check } from '@strapi/icons';
29
+ import { useSelector } from 'react-redux';
29
30
  import { getTrad } from '../../utils';
30
31
  import reducer, { initialState } from './reducer';
31
32
  import init from './init';
@@ -34,6 +35,7 @@ import ModalForm from './components/FormModal';
34
35
  import LayoutDndProvider from '../../components/LayoutDndProvider';
35
36
  import { unformatLayout } from './utils/layout';
36
37
  import putCMSettingsEV from './utils/api';
38
+ import { selectFieldSizes } from '../App/selectors';
37
39
 
38
40
  const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, updateLayout }) => {
39
41
  const [reducerState, dispatch] = useReducer(reducer, initialState, () =>
@@ -49,6 +51,7 @@ const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, upd
49
51
  const { formatMessage } = useIntl();
50
52
  const modelName = get(mainLayout, ['info', 'displayName'], '');
51
53
  const attributes = get(modifiedData, ['attributes'], {});
54
+ const fieldSizes = useSelector(selectFieldSizes);
52
55
 
53
56
  const entryTitleOptions = Object.keys(attributes).filter((attr) => {
54
57
  const type = get(attributes, [attr, 'type'], '');
@@ -318,6 +321,7 @@ const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, upd
318
321
  dispatch({
319
322
  type: 'ON_ADD_FIELD',
320
323
  name: field,
324
+ fieldSizes,
321
325
  });
322
326
  }}
323
327
  onRemoveField={(rowId, index) => {
@@ -2,9 +2,10 @@ import produce from 'immer';
2
2
  import set from 'lodash/set';
3
3
  import get from 'lodash/get';
4
4
  import cloneDeep from 'lodash/cloneDeep';
5
-
6
5
  import { arrayMoveItem } from '../../utils';
7
- import { formatLayout, getDefaultInputSize, getFieldSize, setFieldSize } from './utils/layout';
6
+ import { formatLayout, getFieldSize, setFieldSize } from './utils/layout';
7
+
8
+ const DEFAULT_FIELD_SIZE = 6;
8
9
 
9
10
  const initialState = {
10
11
  fieldForm: {},
@@ -29,9 +30,8 @@ const reducer = (state = initialState, action) =>
29
30
  }
30
31
  case 'ON_ADD_FIELD': {
31
32
  const newState = cloneDeep(state);
32
- const size = getDefaultInputSize(
33
- get(newState, ['modifiedData', 'attributes', action.name, 'type'], '')
34
- );
33
+ const type = get(newState, ['modifiedData', 'attributes', action.name, 'type'], '');
34
+ const size = action.fieldSizes[type]?.default ?? DEFAULT_FIELD_SIZE;
35
35
  const listSize = get(newState, layoutPathEdit, []).length;
36
36
  const actualRowContentPath = [...layoutPathEdit, listSize - 1, 'rowContent'];
37
37
  const rowContentToSet = get(newState, actualRowContentPath, []);
@@ -149,8 +149,7 @@ const reducer = (state = initialState, action) =>
149
149
  draftState.metaToEdit = action.name;
150
150
  draftState.metaForm = {
151
151
  metadata: get(state, ['modifiedData', 'metadatas', action.name, 'edit'], {}),
152
- size:
153
- getFieldSize(action.name, state.modifiedData?.layouts?.edit) ?? getDefaultInputSize(),
152
+ size: getFieldSize(action.name, state.modifiedData?.layouts?.edit) ?? DEFAULT_FIELD_SIZE,
154
153
  };
155
154
 
156
155
  break;