From 660349845d0bd32ae27cf8404d9184747e2ba293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Thu, 13 Apr 2023 11:52:40 +0200 Subject: [PATCH 01/14] Add content-manager/init endpoint --- .../server/controllers/index.js | 2 + .../server/controllers/init.js | 13 ++++++ .../content-manager/server/routes/admin.js | 8 ++++ .../server/services/field-sizes.js | 42 +++++++++++++++++++ .../content-manager/server/services/index.js | 6 ++- 5 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 packages/core/content-manager/server/controllers/init.js create mode 100644 packages/core/content-manager/server/services/field-sizes.js diff --git a/packages/core/content-manager/server/controllers/index.js b/packages/core/content-manager/server/controllers/index.js index c5cf9b56c8..f6e1275aea 100644 --- a/packages/core/content-manager/server/controllers/index.js +++ b/packages/core/content-manager/server/controllers/index.js @@ -3,6 +3,7 @@ const collectionTypes = require('./collection-types'); const components = require('./components'); const contentTypes = require('./content-types'); +const init = require('./init'); const relations = require('./relations'); const singleTypes = require('./single-types'); const uid = require('./uid'); @@ -11,6 +12,7 @@ module.exports = { 'collection-types': collectionTypes, components, 'content-types': contentTypes, + init, relations, 'single-types': singleTypes, uid, diff --git a/packages/core/content-manager/server/controllers/init.js b/packages/core/content-manager/server/controllers/init.js new file mode 100644 index 0000000000..fcdbabaeb0 --- /dev/null +++ b/packages/core/content-manager/server/controllers/init.js @@ -0,0 +1,13 @@ +'use strict'; + +const { getService } = require('../utils'); + +module.exports = { + getInitData(ctx) { + ctx.body = { + data: { + fieldSizes: getService('field-sizes').getFieldSizes(), + }, + }; + }, +}; diff --git a/packages/core/content-manager/server/routes/admin.js b/packages/core/content-manager/server/routes/admin.js index 7bc0e8cdcc..c33cee7c6e 100644 --- a/packages/core/content-manager/server/routes/admin.js +++ b/packages/core/content-manager/server/routes/admin.js @@ -5,6 +5,14 @@ const { routing } = require('../middlewares'); module.exports = { type: 'admin', routes: [ + { + method: 'GET', + path: '/init', + handler: 'init.getInitData', + config: { + policies: [], + }, + }, { method: 'GET', path: '/content-types', diff --git a/packages/core/content-manager/server/services/field-sizes.js b/packages/core/content-manager/server/services/field-sizes.js new file mode 100644 index 0000000000..e55d7981db --- /dev/null +++ b/packages/core/content-manager/server/services/field-sizes.js @@ -0,0 +1,42 @@ +'use strict'; + +const fullSize = { + default: 12, + resizable: false, +}; + +const smallSize = { + default: 4, + resizable: true, +}; + +const defaultSize = { + default: 6, + resizable: true, +}; + +const fieldSizes = { + // Full row and not resizable + dynamiczone: fullSize, + component: fullSize, + json: fullSize, + richtext: fullSize, + // Small and resizable + checkbox: smallSize, + boolean: smallSize, + date: smallSize, + time: smallSize, + biginteger: smallSize, + decimal: smallSize, + float: smallSize, + integer: smallSize, + number: smallSize, + // Medium and resizable + // TODO +}; + +module.exports = () => ({ + getFieldSizes() { + return fieldSizes; + }, +}); diff --git a/packages/core/content-manager/server/services/index.js b/packages/core/content-manager/server/services/index.js index 745c54ba25..7a416e428b 100644 --- a/packages/core/content-manager/server/services/index.js +++ b/packages/core/content-manager/server/services/index.js @@ -3,19 +3,21 @@ const components = require('./components'); const contentTypes = require('./content-types'); const dataMapper = require('./data-mapper'); +const entityManager = require('./entity-manager'); +const fieldSizes = require('./field-sizes'); const metrics = require('./metrics'); const permissionChecker = require('./permission-checker'); const permission = require('./permission'); const uid = require('./uid'); -const entityManager = require('./entity-manager'); module.exports = { components, 'content-types': contentTypes, 'data-mapper': dataMapper, + 'entity-manager': entityManager, + 'field-sizes': fieldSizes, metrics, 'permission-checker': permissionChecker, permission, uid, - 'entity-manager': entityManager, }; From 0ab74b0799ec201e21a99481daf4a9b98de1a11f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Thu, 13 Apr 2023 12:14:43 +0200 Subject: [PATCH 02/14] Add useContentManagerInitData hook --- .../src/content-manager/pages/App/actions.js | 20 ++++++++++------ .../content-manager/pages/App/constants.js | 6 ++--- .../src/content-manager/pages/App/index.js | 5 ++-- .../src/content-manager/pages/App/reducer.js | 9 ++++---- ...Models.js => useContentManagerInitData.js} | 23 +++++++++++++------ 5 files changed, 40 insertions(+), 23 deletions(-) rename packages/core/admin/admin/src/content-manager/pages/App/{useModels.js => useContentManagerInitData.js} (81%) diff --git a/packages/core/admin/admin/src/content-manager/pages/App/actions.js b/packages/core/admin/admin/src/content-manager/pages/App/actions.js index 9125a7caae..28493e61f3 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/actions.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/actions.js @@ -1,12 +1,18 @@ -import { GET_DATA, RESET_PROPS, SET_CONTENT_TYPE_LINKS } from './constants'; +import { GET_INIT_DATA, RESET_INIT_DATA, SET_INIT_DATA } from './constants'; -export const getData = () => ({ - type: GET_DATA, +export const getInitData = () => ({ + type: GET_INIT_DATA, }); -export const resetProps = () => ({ type: RESET_PROPS }); +export const resetInitData = () => ({ type: RESET_INIT_DATA }); -export const setContentTypeLinks = (authorizedCtLinks, authorizedStLinks, models, components) => ({ - type: SET_CONTENT_TYPE_LINKS, - data: { authorizedCtLinks, authorizedStLinks, components, contentTypeSchemas: models }, +export const setInitData = ({ + authorizedCtLinks, + authorizedStLinks, + contentTypeSchemas, + components, + fieldSizes, +}) => ({ + type: SET_INIT_DATA, + data: { authorizedCtLinks, authorizedStLinks, components, contentTypeSchemas, fieldSizes }, }); diff --git a/packages/core/admin/admin/src/content-manager/pages/App/constants.js b/packages/core/admin/admin/src/content-manager/pages/App/constants.js index 35ead6c083..5d71dae2c8 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/constants.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/constants.js @@ -1,3 +1,3 @@ -export const GET_DATA = 'ContentManager/App/GET_DATA'; -export const RESET_PROPS = 'ContentManager/App/RESET_PROPS'; -export const SET_CONTENT_TYPE_LINKS = 'ContentManager/App/SET_CONTENT_TYPE_LINKS'; +export const GET_INIT_DATA = 'ContentManager/App/GET_INIT_DATA'; +export const RESET_INIT_DATA = 'ContentManager/App/RESET_INIT_DATA'; +export const SET_INIT_DATA = 'ContentManager/App/SET_INIT_DATA'; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/index.js b/packages/core/admin/admin/src/content-manager/pages/App/index.js index 8dae70fecc..602d81364e 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/index.js @@ -20,13 +20,14 @@ import NoContentType from '../NoContentType'; import NoPermissions from '../NoPermissions'; import SingleTypeRecursivePath from '../SingleTypeRecursivePath'; import LeftMenu from './LeftMenu'; -import useModels from './useModels'; +import useContentManagerInitData from './useContentManagerInitData'; const cmPermissions = permissions.contentManager; const App = () => { const contentTypeMatch = useRouteMatch(`/content-manager/:kind/:uid`); - const { status, collectionTypeLinks, singleTypeLinks, models, refetchData } = useModels(); + const { status, collectionTypeLinks, singleTypeLinks, models, refetchData, fieldSizes } = + useContentManagerInitData(); const authorisedModels = sortBy([...collectionTypeLinks, ...singleTypeLinks], (model) => model.title.toLowerCase() ); diff --git a/packages/core/admin/admin/src/content-manager/pages/App/reducer.js b/packages/core/admin/admin/src/content-manager/pages/App/reducer.js index c43268d117..d3a268f692 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/reducer.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/reducer.js @@ -4,7 +4,7 @@ */ /* eslint-disable consistent-return */ import produce from 'immer'; -import { GET_DATA, RESET_PROPS, SET_CONTENT_TYPE_LINKS } from './constants'; +import { GET_INIT_DATA, RESET_INIT_DATA, SET_INIT_DATA } from './constants'; const initialState = { components: [], @@ -20,14 +20,14 @@ const initialState = { const mainReducer = (state = initialState, action) => produce(state, (draftState) => { switch (action.type) { - case GET_DATA: { + case GET_INIT_DATA: { draftState.status = 'loading'; break; } - case RESET_PROPS: { + case RESET_INIT_DATA: { return initialState; } - case SET_CONTENT_TYPE_LINKS: { + case SET_INIT_DATA: { draftState.collectionTypeLinks = action.data.authorizedCtLinks.filter( ({ isDisplayed }) => isDisplayed ); @@ -36,6 +36,7 @@ const mainReducer = (state = initialState, action) => ); draftState.components = action.data.components; draftState.models = action.data.contentTypeSchemas; + draftState.fieldSizes = action.data.fieldSizes; draftState.status = 'resolved'; break; } diff --git a/packages/core/admin/admin/src/content-manager/pages/App/useModels.js b/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js similarity index 81% rename from packages/core/admin/admin/src/content-manager/pages/App/useModels.js rename to packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js index 973467c6dc..9eb8d1b5ba 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/useModels.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js @@ -11,11 +11,11 @@ import axios from 'axios'; import { useIntl } from 'react-intl'; import { MUTATE_COLLECTION_TYPES_LINKS, MUTATE_SINGLE_TYPES_LINKS } from '../../../exposedHooks'; import { getRequestUrl, getTrad } from '../../utils'; -import { getData, resetProps, setContentTypeLinks } from './actions'; +import { getInitData, resetInitData, setInitData } from './actions'; import { selectAppDomain } from './selectors'; import getContentTypeLinks from './utils/getContentTypeLinks'; -const useModels = () => { +const useContentManagerInitData = () => { const dispatch = useDispatch(); const toggleNotification = useNotification(); const state = useSelector(selectAppDomain()); @@ -29,7 +29,7 @@ const useModels = () => { const { get } = useFetchClient(); const fetchData = async () => { - dispatch(getData()); + dispatch(getInitData()); try { const [ @@ -39,8 +39,11 @@ const useModels = () => { { data: { data: models }, }, + { + data: { data: initData }, + }, ] = await Promise.all( - ['components', 'content-types'].map((endPoint) => + ['components', 'content-types', 'init'].map((endPoint) => get(getRequestUrl(endPoint), { cancelToken: source.token }) ) ); @@ -67,7 +70,13 @@ const useModels = () => { models, }); - const actionToDispatch = setContentTypeLinks(ctLinks, stLinks, models, components); + const actionToDispatch = setInitData({ + authorizedCtLinks: ctLinks, + authorizedStLinks: stLinks, + contentTypeSchemas: models, + components, + fieldSizes: initData.fieldSizes, + }); dispatch(actionToDispatch); } catch (err) { @@ -88,7 +97,7 @@ const useModels = () => { return () => { source.cancel('Operation canceled by the user.'); - dispatch(resetProps()); + dispatch(resetInitData()); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [dispatch, toggleNotification]); @@ -96,4 +105,4 @@ const useModels = () => { return { ...state, refetchData: fetchDataRef.current }; }; -export default useModels; +export default useContentManagerInitData; From ce467fdf4ef2a45c4372bc8041f3de86a635006d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Thu, 13 Apr 2023 18:53:30 +0200 Subject: [PATCH 03/14] Add all types to fieldSize service --- .../server/controllers/init.js | 2 +- .../server/services/field-sizes.js | 16 +++++++-- .../services/utils/configuration/layouts.js | 36 ++++++------------- .../content-manager/server/utils/index.d.ts | 2 ++ 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/core/content-manager/server/controllers/init.js b/packages/core/content-manager/server/controllers/init.js index fcdbabaeb0..58b2e923f6 100644 --- a/packages/core/content-manager/server/controllers/init.js +++ b/packages/core/content-manager/server/controllers/init.js @@ -6,7 +6,7 @@ module.exports = { getInitData(ctx) { ctx.body = { data: { - fieldSizes: getService('field-sizes').getFieldSizes(), + fieldSizes: getService('field-sizes').getAllFieldSizes(), }, }; }, diff --git a/packages/core/content-manager/server/services/field-sizes.js b/packages/core/content-manager/server/services/field-sizes.js index e55d7981db..ab0dcb98d6 100644 --- a/packages/core/content-manager/server/services/field-sizes.js +++ b/packages/core/content-manager/server/services/field-sizes.js @@ -32,11 +32,23 @@ const fieldSizes = { integer: smallSize, number: smallSize, // Medium and resizable - // TODO + datetime: defaultSize, + email: defaultSize, + enumeration: defaultSize, + media: defaultSize, + password: defaultSize, + relation: defaultSize, + string: defaultSize, + text: defaultSize, + timestamp: defaultSize, + uid: defaultSize, }; module.exports = () => ({ - getFieldSizes() { + getAllFieldSizes() { return fieldSizes; }, + getFieldSize(type) { + return fieldSizes[type]; + }, }); diff --git a/packages/core/content-manager/server/services/utils/configuration/layouts.js b/packages/core/content-manager/server/services/utils/configuration/layouts.js index ba6f0a07f2..84f977218d 100644 --- a/packages/core/content-manager/server/services/utils/configuration/layouts.js +++ b/packages/core/content-manager/server/services/utils/configuration/layouts.js @@ -1,42 +1,28 @@ 'use strict'; const _ = require('lodash'); +const { getService } = require('../../../utils'); const { isListable, hasEditableAttribute, hasRelationAttribute } = require('./attributes'); const DEFAULT_LIST_LENGTH = 4; const MAX_ROW_SIZE = 12; -const FIELD_TYPES_FULL_SIZE = ['dynamiczone', 'component', 'json', 'richtext']; -const FIELD_TYPES_SMALL = [ - 'checkbox', - 'boolean', - 'date', - 'time', - 'biginteger', - 'decimal', - 'float', - 'integer', - 'number', -]; const isAllowedFieldSize = (type, size) => { - if (FIELD_TYPES_FULL_SIZE.includes(type)) { - return size === MAX_ROW_SIZE; + const { getFieldSize } = getService('field-sizes'); + const fieldSize = getFieldSize(type); + + // Check if field was locked to another size + if (!fieldSize.resizable && size !== fieldSize.default) { + return false; } - // validate, whether the field has 4, 6, 8 or 12 columns? - return size <= MAX_ROW_SIZE; + // Otherwise always allow + return true; }; const getDefaultFieldSize = (type) => { - if (FIELD_TYPES_FULL_SIZE.includes(type)) { - return MAX_ROW_SIZE; - } - - if (FIELD_TYPES_SMALL.includes(type)) { - return MAX_ROW_SIZE / 3; - } - - return MAX_ROW_SIZE / 2; + const { getFieldSize } = getService('field-sizes'); + return getFieldSize(type).default; }; async function createDefaultLayouts(schema) { diff --git a/packages/core/content-manager/server/utils/index.d.ts b/packages/core/content-manager/server/utils/index.d.ts index 1eed522b60..2ad4310ce1 100644 --- a/packages/core/content-manager/server/utils/index.d.ts +++ b/packages/core/content-manager/server/utils/index.d.ts @@ -3,6 +3,7 @@ import * as configuration from '../services/configuration'; import * as contentTypes from '../services/content-types'; import * as dataMapper from '../services/data-mapper'; import * as entityManager from '../services/entity-manager'; +import * as fieldSizes from '../services/field-sizes'; import * as metris from '../services/metris'; import * as permissionChecker from '../services/permission-checker'; import * as permission from '../services/permission'; @@ -15,6 +16,7 @@ type S = { ['permission-checker']: typeof permissionChecker; components: typeof components; configuration: typeof configuration; + ['field-sizes']: typeof fieldSizes; metris: typeof metris; permission: typeof permission; uid: typeof uid; From 1402527b45316c8c862abf6a36f00f2583f4fb07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Thu, 13 Apr 2023 19:10:36 +0200 Subject: [PATCH 04/14] Use field sizes data from init endpoint --- .../src/content-manager/pages/App/index.js | 2 +- .../content-manager/pages/App/selectors.js | 3 ++ .../pages/App/tests/actions.test.js | 16 ++++---- .../pages/App/tests/index.test.js | 16 ++++---- .../pages/App/tests/reducer.test.js | 21 ++++++---- .../EditSettingsView/components/ModalForm.js | 10 ++--- .../pages/EditSettingsView/index.js | 7 +++- .../pages/EditSettingsView/reducer.js | 13 +++--- .../EditSettingsView/tests/index.test.js | 40 ++++++++++++------- .../EditSettingsView/tests/reducer.test.js | 18 +++++++-- .../pages/EditSettingsView/utils/layout.js | 31 +------------- .../utils/tests/layout.test.js | 19 --------- 12 files changed, 92 insertions(+), 104 deletions(-) diff --git a/packages/core/admin/admin/src/content-manager/pages/App/index.js b/packages/core/admin/admin/src/content-manager/pages/App/index.js index 602d81364e..4f8a64d5a6 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/index.js @@ -26,7 +26,7 @@ const cmPermissions = permissions.contentManager; const App = () => { const contentTypeMatch = useRouteMatch(`/content-manager/:kind/:uid`); - const { status, collectionTypeLinks, singleTypeLinks, models, refetchData, fieldSizes } = + const { status, collectionTypeLinks, singleTypeLinks, models, refetchData } = useContentManagerInitData(); const authorisedModels = sortBy([...collectionTypeLinks, ...singleTypeLinks], (model) => model.title.toLowerCase() diff --git a/packages/core/admin/admin/src/content-manager/pages/App/selectors.js b/packages/core/admin/admin/src/content-manager/pages/App/selectors.js index e5b433387e..6fd9b09a65 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/selectors.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/selectors.js @@ -23,10 +23,13 @@ const makeSelectModelAndComponentSchemas = () => schemas: [...components, ...models], })); +const makeSelectFieldSizes = () => createSelector(selectAppDomain(), (state) => state.fieldSizes); + export default makeSelectApp; export { makeSelectModelAndComponentSchemas, makeSelectModelLinks, makeSelectModels, + makeSelectFieldSizes, selectAppDomain, }; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js b/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js index d2920167c5..e34cb8eb5a 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js @@ -1,27 +1,27 @@ -import { setContentTypeLinks } from '../actions'; +import { setInitData } from '../actions'; describe('Content Manager | App | actions', () => { - it('should format the setContentTypeLinks action', () => { + it('should format the setInitData action', () => { const authorizedCtLinks = [{ title: 'addresses', uid: 'address' }]; const authorizedStLinks = [{ title: 'Home page', uid: 'homepage' }]; - const models = [ + const contentTypeSchemas = [ { kind: 'singleType', uid: 'homepage' }, { kind: 'collectionType', uid: 'address' }, ]; const components = []; const expected = { - type: 'ContentManager/App/SET_CONTENT_TYPE_LINKS', + type: 'ContentManager/App/SET_INIT_DATA', data: { authorizedCtLinks, authorizedStLinks, - contentTypeSchemas: models, + contentTypeSchemas, components, }, }; - expect(setContentTypeLinks(authorizedCtLinks, authorizedStLinks, models, components)).toEqual( - expected - ); + expect( + setInitData({ authorizedCtLinks, authorizedStLinks, contentTypeSchemas, components }) + ).toEqual(expected); }); }); diff --git a/packages/core/admin/admin/src/content-manager/pages/App/tests/index.test.js b/packages/core/admin/admin/src/content-manager/pages/App/tests/index.test.js index a780f69d59..4be62d601d 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/tests/index.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/tests/index.test.js @@ -13,9 +13,9 @@ import Theme from '../../../../components/Theme'; import ThemeToggleProvider from '../../../../components/ThemeToggleProvider'; import { App as ContentManagerApp } from '..'; import cmReducers from '../../../../reducers'; -import useModels from '../useModels'; +import useContentManagerInitData from '../useContentManagerInitData'; -jest.mock('../useModels', () => +jest.mock('../useContentManagerInitData', () => jest.fn(() => { return {}; }) @@ -88,7 +88,7 @@ describe('Content manager | App | main', () => { components: [], status: 'resolved', }; - useModels.mockImplementation(() => contentManagerState); + useContentManagerInitData.mockImplementation(() => contentManagerState); const rootReducer = combineReducers(cmReducers); const store = createStore(rootReducer, { 'content-manager_app': contentManagerState }); const history = createMemoryHistory(); @@ -815,7 +815,7 @@ describe('Content manager | App | main', () => { components: [], status: 'resolved', }; - useModels.mockImplementation(() => contentManagerState); + useContentManagerInitData.mockImplementation(() => contentManagerState); const rootReducer = combineReducers(cmReducers); const store = createStore(rootReducer, { 'content-manager_app': contentManagerState }); const history = createMemoryHistory(); @@ -857,8 +857,8 @@ describe('Content manager | App | main', () => { components: [], status: 'resolved', }; - useModels.mockImplementation(() => contentManagerState); - jest.mock('../useModels', () => + useContentManagerInitData.mockImplementation(() => contentManagerState); + jest.mock('../useContentManagerInitData', () => jest.fn(() => { return contentManagerState; }) @@ -902,8 +902,8 @@ describe('Content manager | App | main', () => { components: [], status: 'resolved', }; - useModels.mockImplementation(() => contentManagerState); - jest.mock('../useModels', () => + useContentManagerInitData.mockImplementation(() => contentManagerState); + jest.mock('../useContentManagerInitData', () => jest.fn(() => { return contentManagerState; }) diff --git a/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js b/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js index 7817b09107..2f305bb5a5 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js @@ -1,5 +1,5 @@ import produce from 'immer'; -import { getData, setContentTypeLinks, resetProps } from '../actions'; +import { getInitData, setInitData, resetInitData } from '../actions'; import mainReducer from '../reducer'; describe('Content Manager | App | reducer', () => { @@ -12,6 +12,7 @@ describe('Content Manager | App | reducer', () => { models: [], collectionTypeLinks: [], singleTypeLinks: [], + fieldSizes: {}, }; }); @@ -19,17 +20,17 @@ describe('Content Manager | App | reducer', () => { expect(mainReducer(state, {})).toEqual(state); }); - it('should handle the getData action correctly', () => { + it('should handle the getInitData action correctly', () => { state.status = 'resolved'; const expected = produce(state, (draft) => { draft.status = 'loading'; }); - expect(mainReducer(state, getData())).toEqual(expected); + expect(mainReducer(state, getInitData())).toEqual(expected); }); - it('should handle the getData action correctly', () => { + it('should handle the setInitData action correctly', () => { const collectionTypeLinks = [ { name: 'authorizedCt', @@ -71,15 +72,21 @@ describe('Content Manager | App | reducer', () => { expect( mainReducer( state, - setContentTypeLinks(collectionTypeLinks, singleTypeLinks, ['test'], ['test']) + setInitData({ + authorizedCtLinks: collectionTypeLinks, + authorizedStLinks: singleTypeLinks, + contentTypeSchemas: ['test'], + components: ['test'], + fieldSizes: {}, + }) ) ).toEqual(expected); }); - it('should handle the resetProps action correctly', () => { + it('should handle the resetInitData action correctly', () => { state = 'test'; - expect(mainReducer(state, resetProps())).toEqual({ + expect(mainReducer(state, resetInitData())).toEqual({ components: [], models: [], collectionTypeLinks: [], diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js index 6394a77bcf..cd34da865c 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js @@ -6,7 +6,7 @@ import { useSelector, shallowEqual } from 'react-redux'; import { useIntl } from 'react-intl'; import { useLayoutDnd } from '../../../hooks'; import { createPossibleMainFieldsForModelsAndComponents, getInputProps } from '../utils'; -import { makeSelectModelAndComponentSchemas } from '../../App/selectors'; +import { makeSelectModelAndComponentSchemas, makeSelectFieldSizes } from '../../App/selectors'; import getTrad from '../../../utils/getTrad'; import GenericInput from './GenericInput'; @@ -17,8 +17,6 @@ const FIELD_SIZES = [ [12, '100%'], ]; -const NON_RESIZABLE_FIELD_TYPES = ['dynamiczone', 'component', 'json', 'richtext']; - const TIME_FIELD_OPTIONS = [1, 5, 10, 15, 30, 60]; const TIME_FIELD_TYPES = ['datetime', 'time']; @@ -27,7 +25,9 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => { const { formatMessage } = useIntl(); const { modifiedData, selectedField, attributes, fieldForm } = useLayoutDnd(); const schemasSelector = useMemo(makeSelectModelAndComponentSchemas, []); + const fieldSizesSelector = useMemo(makeSelectFieldSizes, []); const { schemas } = useSelector((state) => schemasSelector(state), shallowEqual); + const fieldSizes = useSelector((state) => fieldSizesSelector(state)); const formToDisplay = useMemo(() => { if (!selectedField) { @@ -103,7 +103,7 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => { ); }); - const canResize = !NON_RESIZABLE_FIELD_TYPES.includes(attributes[selectedField].type); + const fieldSizeInfo = fieldSizes[attributes[selectedField].type]; const sizeField = ( @@ -152,7 +152,7 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => { return ( <> {metaFields} - {canResize && sizeField} + {fieldSizeInfo.resizable && sizeField} {hasTimePicker && timeStepField} ); diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js index e4bc62ac59..6749fc9866 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js @@ -1,4 +1,4 @@ -import React, { useReducer, useState } from 'react'; +import React, { useMemo, useReducer, useState } from 'react'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import { useMutation } from 'react-query'; @@ -26,6 +26,7 @@ import { Divider, } from '@strapi/design-system'; import { ArrowLeft, Check } from '@strapi/icons'; +import { useSelector } from 'react-redux'; import { getTrad } from '../../utils'; import reducer, { initialState } from './reducer'; import init from './init'; @@ -34,6 +35,7 @@ import ModalForm from './components/FormModal'; import LayoutDndProvider from '../../components/LayoutDndProvider'; import { unformatLayout } from './utils/layout'; import putCMSettingsEV from './utils/api'; +import { makeSelectFieldSizes } from '../App/selectors'; const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, updateLayout }) => { const [reducerState, dispatch] = useReducer(reducer, initialState, () => @@ -49,6 +51,8 @@ const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, upd const { formatMessage } = useIntl(); const modelName = get(mainLayout, ['info', 'displayName'], ''); const attributes = get(modifiedData, ['attributes'], {}); + const fieldSizesSelector = useMemo(makeSelectFieldSizes, []); + const fieldSizes = useSelector((state) => fieldSizesSelector(state)); const entryTitleOptions = Object.keys(attributes).filter((attr) => { const type = get(attributes, [attr, 'type'], ''); @@ -318,6 +322,7 @@ const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, upd dispatch({ type: 'ON_ADD_FIELD', name: field, + fieldSizes, }); }} onRemoveField={(rowId, index) => { diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/reducer.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/reducer.js index 57190bc166..6b79791202 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/reducer.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/reducer.js @@ -2,9 +2,10 @@ import produce from 'immer'; import set from 'lodash/set'; import get from 'lodash/get'; import cloneDeep from 'lodash/cloneDeep'; - import { arrayMoveItem } from '../../utils'; -import { formatLayout, getDefaultInputSize, getFieldSize, setFieldSize } from './utils/layout'; +import { formatLayout, getFieldSize, setFieldSize } from './utils/layout'; + +const DEFAULT_FIELD_SIZE = 6; const initialState = { fieldForm: {}, @@ -29,9 +30,8 @@ const reducer = (state = initialState, action) => } case 'ON_ADD_FIELD': { const newState = cloneDeep(state); - const size = getDefaultInputSize( - get(newState, ['modifiedData', 'attributes', action.name, 'type'], '') - ); + const type = get(newState, ['modifiedData', 'attributes', action.name, 'type'], ''); + const size = action.fieldSizes[type]?.default ?? DEFAULT_FIELD_SIZE; const listSize = get(newState, layoutPathEdit, []).length; const actualRowContentPath = [...layoutPathEdit, listSize - 1, 'rowContent']; const rowContentToSet = get(newState, actualRowContentPath, []); @@ -149,8 +149,7 @@ const reducer = (state = initialState, action) => draftState.metaToEdit = action.name; draftState.metaForm = { metadata: get(state, ['modifiedData', 'metadatas', action.name, 'edit'], {}), - size: - getFieldSize(action.name, state.modifiedData?.layouts?.edit) ?? getDefaultInputSize(), + size: getFieldSize(action.name, state.modifiedData?.layouts?.edit) ?? DEFAULT_FIELD_SIZE, }; break; diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/index.test.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/index.test.js index d8d4337ebc..66c85a1021 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/index.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/index.test.js @@ -4,10 +4,13 @@ import { Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import { IntlProvider } from 'react-intl'; import { QueryClient, QueryClientProvider } from 'react-query'; +import { combineReducers, createStore } from 'redux'; +import { Provider } from 'react-redux'; import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { ThemeProvider, lightTheme } from '@strapi/design-system'; import EditSettingsView from '../index'; +import cmReducers from '../../../../reducers'; jest.mock('@strapi/helper-plugin', () => ({ ...jest.requireActual('@strapi/helper-plugin'), @@ -57,22 +60,31 @@ const makeApp = (history, layout) => { compo1: { uid: 'compo1' }, }; + const rootReducer = combineReducers(cmReducers); + const store = createStore(rootReducer, { + 'content-manager_app': { + fieldSizes: {}, + }, + }); + return ( - - - - - - - - - + + + + + + + + + + + ); }; diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/reducer.test.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/reducer.test.js index 23553533a0..3d7c26abd2 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/reducer.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/reducer.test.js @@ -1,5 +1,11 @@ import reducer from '../reducer'; +const fieldSizes = { + richtext: { default: 12, resizable: false }, + string: { default: 6, resizable: true }, + boolean: { default: 4, resizable: true }, +}; + describe('CONTENT MANAGER | CONTAINERS | EditSettingsView | reducer', () => { let state; @@ -82,7 +88,11 @@ describe('CONTENT MANAGER | CONTAINERS | EditSettingsView | reducer', () => { }, }, }; - const action = { type: 'ON_ADD_FIELD', name: 'description' }; + const action = { + type: 'ON_ADD_FIELD', + name: 'description', + fieldSizes, + }; expect(reducer(state, action)).toEqual(expected); }); @@ -121,7 +131,7 @@ describe('CONTENT MANAGER | CONTAINERS | EditSettingsView | reducer', () => { }, }, }; - const action = { type: 'ON_ADD_FIELD', name: 'title' }; + const action = { type: 'ON_ADD_FIELD', name: 'title', fieldSizes }; expect(reducer(state, action)).toEqual(expected); }); @@ -163,7 +173,7 @@ describe('CONTENT MANAGER | CONTAINERS | EditSettingsView | reducer', () => { }, }, }; - const action = { type: 'ON_ADD_FIELD', name: 'isActive' }; + const action = { type: 'ON_ADD_FIELD', name: 'isActive', fieldSizes }; expect(reducer(state, action)).toEqual(expected); }); @@ -214,7 +224,7 @@ describe('CONTENT MANAGER | CONTAINERS | EditSettingsView | reducer', () => { }, }, }; - const action = { type: 'ON_ADD_FIELD', name: 'title' }; + const action = { type: 'ON_ADD_FIELD', name: 'title', fieldSizes }; expect(reducer(state, action)).toEqual(expected); }); }); diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/utils/layout.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/utils/layout.js index 2b655b6476..8db770aa50 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/utils/layout.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/utils/layout.js @@ -1,4 +1,3 @@ -/* eslint-disable indent */ const getRowSize = (arr) => arr.reduce((sum, value) => sum + value.size, 0); const createLayout = (arr) => { @@ -75,26 +74,6 @@ const unformatLayout = (arr) => { }, []); }; -const getDefaultInputSize = (type) => { - switch (type) { - case 'boolean': - case 'date': - case 'integer': - case 'float': - case 'biginteger': - case 'decimal': - case 'time': - return 4; - case 'json': - case 'component': - case 'richtext': - case 'dynamiczone': - return 12; - default: - return 6; - } -}; - const getFieldSize = (name, layouts = []) => { return layouts.reduce((acc, { rowContent }) => { const size = rowContent.find((row) => row.name === name)?.size ?? null; @@ -124,12 +103,4 @@ const setFieldSize = (name, size, layouts = []) => { }); }; -export { - createLayout, - formatLayout, - getDefaultInputSize, - getFieldSize, - setFieldSize, - getRowSize, - unformatLayout, -}; +export { createLayout, formatLayout, getFieldSize, setFieldSize, getRowSize, unformatLayout }; diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/utils/tests/layout.test.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/utils/tests/layout.test.js index 2558d5ff3e..2ba8730b57 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/utils/tests/layout.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/utils/tests/layout.test.js @@ -1,7 +1,6 @@ import { createLayout, formatLayout, - getDefaultInputSize, getFieldSize, setFieldSize, getRowSize, @@ -118,24 +117,6 @@ describe('Content Manager | containers | EditSettingsView | utils | layout', () }); }); - describe('getDefaultInputSize', () => { - it('Should return 6 if the type is unknown, undefined or text', () => { - expect(getDefaultInputSize(undefined)).toBe(6); - expect(getDefaultInputSize('unkown')).toBe(6); - expect(getDefaultInputSize('text')).toBe(6); - }); - - it('Should return 12 if the type is either json, component or richtext', () => { - expect(getDefaultInputSize('json')).toBe(12); - expect(getDefaultInputSize('richtext')).toBe(12); - expect(getDefaultInputSize('component')).toBe(12); - }); - - it('Should return 4 if the type is boolean', () => { - expect(getDefaultInputSize('boolean')).toBe(4); - }); - }); - describe('getFieldSize', () => { const fixture = [ { From f57ddb4cef9b815396828e0169a9cc4eecb45a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Thu, 13 Apr 2023 19:35:15 +0200 Subject: [PATCH 05/14] Merge /content-types and /components into /init route --- .../pages/App/useContentManagerInitData.js | 21 +++++-------------- .../server/controllers/init.js | 9 +++++++- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js b/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js index 9eb8d1b5ba..5873335ad8 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js @@ -32,22 +32,11 @@ const useContentManagerInitData = () => { dispatch(getInitData()); try { - const [ - { - data: { data: components }, + const { + data: { + data: { components, contentTypes: models, fieldSizes }, }, - { - data: { data: models }, - }, - { - data: { data: initData }, - }, - ] = await Promise.all( - ['components', 'content-types', 'init'].map((endPoint) => - get(getRequestUrl(endPoint), { cancelToken: source.token }) - ) - ); - + } = await get(getRequestUrl('init'), { cancelToken: source.token }); notifyStatus( formatMessage({ id: getTrad('App.schemas.data-loaded'), @@ -75,7 +64,7 @@ const useContentManagerInitData = () => { authorizedStLinks: stLinks, contentTypeSchemas: models, components, - fieldSizes: initData.fieldSizes, + fieldSizes, }); dispatch(actionToDispatch); diff --git a/packages/core/content-manager/server/controllers/init.js b/packages/core/content-manager/server/controllers/init.js index 58b2e923f6..82f76492a8 100644 --- a/packages/core/content-manager/server/controllers/init.js +++ b/packages/core/content-manager/server/controllers/init.js @@ -4,9 +4,16 @@ const { getService } = require('../utils'); module.exports = { getInitData(ctx) { + const { toDto } = getService('data-mapper'); + const { findAllComponents } = getService('components'); + const { getAllFieldSizes } = getService('field-sizes'); + const { findAllContentTypes } = getService('content-types'); + ctx.body = { data: { - fieldSizes: getService('field-sizes').getAllFieldSizes(), + fieldSizes: getAllFieldSizes(), + components: findAllComponents().map(toDto), + contentTypes: findAllContentTypes().map(toDto), }, }; }, From 6729cd1a1a88d5814ef03ad4aad7b04348eb6412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Fri, 14 Apr 2023 15:26:40 +0200 Subject: [PATCH 06/14] Compare field size to max row --- .../server/services/utils/configuration/layouts.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/content-manager/server/services/utils/configuration/layouts.js b/packages/core/content-manager/server/services/utils/configuration/layouts.js index 84f977218d..6cb3262217 100644 --- a/packages/core/content-manager/server/services/utils/configuration/layouts.js +++ b/packages/core/content-manager/server/services/utils/configuration/layouts.js @@ -16,8 +16,8 @@ const isAllowedFieldSize = (type, size) => { return false; } - // Otherwise always allow - return true; + // Otherwise allow unless it's bigger than a row + return size <= MAX_ROW_SIZE; }; const getDefaultFieldSize = (type) => { From 77e05c260a137b23a6e5b80b64d05b0783543760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Fri, 14 Apr 2023 17:51:31 +0200 Subject: [PATCH 07/14] Avoid ct and st abbreviation --- .../src/content-manager/pages/App/actions.js | 12 ++- .../src/content-manager/pages/App/reducer.js | 4 +- .../pages/App/tests/actions.test.js | 15 ++- .../pages/App/tests/reducer.test.js | 8 +- .../pages/App/useContentManagerInitData.js | 16 ++-- .../pages/App/utils/generateModelsLinks.js | 4 +- .../pages/App/utils/getContentTypeLinks.js | 32 ++++--- .../utils/tests/generateModelsLinks.test.js | 4 +- ...peLinks.js => getContentTypeLinks.test.js} | 94 ++++++++++--------- 9 files changed, 106 insertions(+), 83 deletions(-) rename packages/core/admin/admin/src/content-manager/pages/App/utils/tests/{getContentTypeLinks.js => getContentTypeLinks.test.js} (63%) diff --git a/packages/core/admin/admin/src/content-manager/pages/App/actions.js b/packages/core/admin/admin/src/content-manager/pages/App/actions.js index 28493e61f3..eb85daab62 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/actions.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/actions.js @@ -7,12 +7,18 @@ export const getInitData = () => ({ export const resetInitData = () => ({ type: RESET_INIT_DATA }); export const setInitData = ({ - authorizedCtLinks, - authorizedStLinks, + authorizedCollectionTypeLinks, + authorizedSingleTypeLinks, contentTypeSchemas, components, fieldSizes, }) => ({ type: SET_INIT_DATA, - data: { authorizedCtLinks, authorizedStLinks, components, contentTypeSchemas, fieldSizes }, + data: { + authorizedCollectionTypeLinks, + authorizedSingleTypeLinks, + components, + contentTypeSchemas, + fieldSizes, + }, }); diff --git a/packages/core/admin/admin/src/content-manager/pages/App/reducer.js b/packages/core/admin/admin/src/content-manager/pages/App/reducer.js index d3a268f692..e3dbd20f2f 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/reducer.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/reducer.js @@ -28,10 +28,10 @@ const mainReducer = (state = initialState, action) => return initialState; } case SET_INIT_DATA: { - draftState.collectionTypeLinks = action.data.authorizedCtLinks.filter( + draftState.collectionTypeLinks = action.data.authorizedCollectionTypeLinks.filter( ({ isDisplayed }) => isDisplayed ); - draftState.singleTypeLinks = action.data.authorizedStLinks.filter( + draftState.singleTypeLinks = action.data.authorizedSingleTypeLinks.filter( ({ isDisplayed }) => isDisplayed ); draftState.components = action.data.components; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js b/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js index e34cb8eb5a..fff0e17381 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js @@ -2,8 +2,8 @@ import { setInitData } from '../actions'; describe('Content Manager | App | actions', () => { it('should format the setInitData action', () => { - const authorizedCtLinks = [{ title: 'addresses', uid: 'address' }]; - const authorizedStLinks = [{ title: 'Home page', uid: 'homepage' }]; + const authorizedCollectionTypeLinks = [{ title: 'addresses', uid: 'address' }]; + const authorizedSingleTypeLinks = [{ title: 'Home page', uid: 'homepage' }]; const contentTypeSchemas = [ { kind: 'singleType', uid: 'homepage' }, { kind: 'collectionType', uid: 'address' }, @@ -13,15 +13,20 @@ describe('Content Manager | App | actions', () => { const expected = { type: 'ContentManager/App/SET_INIT_DATA', data: { - authorizedCtLinks, - authorizedStLinks, + authorizedCollectionTypeLinks, + authorizedSingleTypeLinks, contentTypeSchemas, components, }, }; expect( - setInitData({ authorizedCtLinks, authorizedStLinks, contentTypeSchemas, components }) + setInitData({ + authorizedCollectionTypeLinks, + authorizedSingleTypeLinks, + contentTypeSchemas, + components, + }) ).toEqual(expected); }); }); diff --git a/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js b/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js index 2f305bb5a5..de21071bff 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js @@ -31,7 +31,7 @@ describe('Content Manager | App | reducer', () => { }); it('should handle the setInitData action correctly', () => { - const collectionTypeLinks = [ + const authorizedCollectionTypeLinks = [ { name: 'authorizedCt', isDisplayed: true, @@ -41,7 +41,7 @@ describe('Content Manager | App | reducer', () => { isDisplayed: false, }, ]; - const singleTypeLinks = [ + const authorizedSingleTypeLinks = [ { name: 'authorizedSt', isDisplayed: false, @@ -73,8 +73,8 @@ describe('Content Manager | App | reducer', () => { mainReducer( state, setInitData({ - authorizedCtLinks: collectionTypeLinks, - authorizedStLinks: singleTypeLinks, + authorizedCollectionTypeLinks, + authorizedSingleTypeLinks, contentTypeSchemas: ['test'], components: ['test'], fieldSizes: {}, diff --git a/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js b/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js index 5873335ad8..48ee7217db 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js @@ -44,24 +44,24 @@ const useContentManagerInitData = () => { }) ); - const { authorizedCtLinks, authorizedStLinks } = await getContentTypeLinks( + const { authorizedContentTypeLinks, authorizedSingleTypeLinks } = await getContentTypeLinks({ models, - allPermissions, - toggleNotification - ); + userPermissions: allPermissions, + toggleNotification, + }); const { ctLinks } = runHookWaterfall(MUTATE_COLLECTION_TYPES_LINKS, { - ctLinks: authorizedCtLinks, + ctLinks: authorizedContentTypeLinks, models, }); const { stLinks } = runHookWaterfall(MUTATE_SINGLE_TYPES_LINKS, { - stLinks: authorizedStLinks, + stLinks: authorizedSingleTypeLinks, models, }); const actionToDispatch = setInitData({ - authorizedCtLinks: ctLinks, - authorizedStLinks: stLinks, + authorizedCollectionTypeLinks: ctLinks, + authorizedSingleTypeLinks: stLinks, contentTypeSchemas: models, components, fieldSizes, diff --git a/packages/core/admin/admin/src/content-manager/pages/App/utils/generateModelsLinks.js b/packages/core/admin/admin/src/content-manager/pages/App/utils/generateModelsLinks.js index db121ef756..7af9f4be85 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/utils/generateModelsLinks.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/utils/generateModelsLinks.js @@ -52,12 +52,12 @@ const generateModelsLinks = (models, modelsConfigurations) => { const [collectionTypes, singleTypes] = sortBy(groupedModels, 'name'); return { - collectionTypesSectionLinks: generateLinks( + collectionTypeSectionLinks: generateLinks( collectionTypes?.links || [], 'collectionTypes', modelsConfigurations ), - singleTypesSectionLinks: generateLinks(singleTypes?.links ?? [], 'singleTypes'), + singleTypeSectionLinks: generateLinks(singleTypes?.links ?? [], 'singleTypes'), }; }; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/utils/getContentTypeLinks.js b/packages/core/admin/admin/src/content-manager/pages/App/utils/getContentTypeLinks.js index 759913657f..44a5084740 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/utils/getContentTypeLinks.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/utils/getContentTypeLinks.js @@ -3,36 +3,38 @@ import generateModelsLinks from './generateModelsLinks'; import checkPermissions from './checkPermissions'; import { getRequestUrl } from '../../../utils'; -const getContentTypeLinks = async (models, userPermissions, toggleNotification) => { +const getContentTypeLinks = async ({ models, userPermissions, toggleNotification }) => { const { get } = getFetchClient(); try { const { data: { data: contentTypeConfigurations }, } = await get(getRequestUrl('content-types-settings')); - const { collectionTypesSectionLinks, singleTypesSectionLinks } = generateModelsLinks( + const { collectionTypeSectionLinks, singleTypeSectionLinks } = generateModelsLinks( models, contentTypeConfigurations ); - // Content Types verifications - const ctLinksPermissionsPromises = checkPermissions( - userPermissions, - collectionTypesSectionLinks + // Collection Types verifications + const collectionTypeLinksPermissions = await Promise.all( + checkPermissions(userPermissions, collectionTypeSectionLinks) ); - const ctLinksPermissions = await Promise.all(ctLinksPermissionsPromises); - const authorizedCtLinks = collectionTypesSectionLinks.filter( - (_, index) => ctLinksPermissions[index] + const authorizedCollectionTypeLinks = collectionTypeSectionLinks.filter( + (_, index) => collectionTypeLinksPermissions[index] ); // Single Types verifications - const stLinksPermissionsPromises = checkPermissions(userPermissions, singleTypesSectionLinks); - const stLinksPermissions = await Promise.all(stLinksPermissionsPromises); - const authorizedStLinks = singleTypesSectionLinks.filter( - (_, index) => stLinksPermissions[index] + const singleTypeLinksPermissions = await Promise.all( + checkPermissions(userPermissions, singleTypeSectionLinks) + ); + const authorizedSingleTypeLinks = singleTypeSectionLinks.filter( + (_, index) => singleTypeLinksPermissions[index] ); - return { authorizedCtLinks, authorizedStLinks }; + return { + authorizedCollectionTypeLinks, + authorizedSingleTypeLinks, + }; } catch (err) { console.error(err); @@ -41,7 +43,7 @@ const getContentTypeLinks = async (models, userPermissions, toggleNotification) message: { id: 'notification.error' }, }); - return { authorizedCtLinks: [], authorizedStLinks: [], contentTypes: [] }; + return { authorizedCollectionTypeLinks: [], authorizedSingleTypeLinks: [] }; } }; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/utils/tests/generateModelsLinks.test.js b/packages/core/admin/admin/src/content-manager/pages/App/utils/tests/generateModelsLinks.test.js index a160f7551c..fb67531fd9 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/utils/tests/generateModelsLinks.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/utils/tests/generateModelsLinks.test.js @@ -119,7 +119,7 @@ describe('ADMIN | LeftMenu | utils', () => { ]; const expected = { - collectionTypesSectionLinks: [ + collectionTypeSectionLinks: [ { isDisplayed: true, search: null, @@ -140,7 +140,7 @@ describe('ADMIN | LeftMenu | utils', () => { ], }, ], - singleTypesSectionLinks: [ + singleTypeSectionLinks: [ { isDisplayed: true, kind: 'singleType', diff --git a/packages/core/admin/admin/src/content-manager/pages/App/utils/tests/getContentTypeLinks.js b/packages/core/admin/admin/src/content-manager/pages/App/utils/tests/getContentTypeLinks.test.js similarity index 63% rename from packages/core/admin/admin/src/content-manager/pages/App/utils/tests/getContentTypeLinks.js rename to packages/core/admin/admin/src/content-manager/pages/App/utils/tests/getContentTypeLinks.test.js index 37dae5842d..71a65d5f02 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/utils/tests/getContentTypeLinks.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/utils/tests/getContentTypeLinks.test.js @@ -1,4 +1,4 @@ -import { request, hasPermissions } from '@strapi/helper-plugin'; +import { getFetchClient, hasPermissions } from '@strapi/helper-plugin'; import getContentTypeLinks from '../getContentTypeLinks'; // FIXME @@ -44,24 +44,24 @@ describe('checkPermissions', () => { }, ]; - const data = [ + const contentTypes = [ { - uid: 'api::address.address', - isDisplayed: true, apiID: 'address', - kind: 'collectionType', info: { - label: 'address', + displayName: 'Address', }, + isDisplayed: true, + kind: 'collectionType', + uid: 'api::address.address', }, { - uid: 'api::article.article', - isDisplayed: true, apiID: 'article', - kind: 'collectionType', info: { - label: 'article', + displayName: 'Article', }, + isDisplayed: true, + kind: 'collectionType', + uid: 'api::article.article', pluginOptions: { i18n: { localized: true, @@ -70,32 +70,36 @@ describe('checkPermissions', () => { }, ]; - request.mockImplementation((url) => { - if (url === '/content-manager/content-types') { - return Promise.resolve({ data }); - } - - return Promise.resolve({ - data: [ - { - uid: 'api::address.address', - settings: { - pageSize: 10, - defaultSortBy: 'name', - defaultSortOrder: 'ASC', + getFetchClient.mockImplementation(() => ({ + get(url) { + if (url === '/content-manager/content-types-settings') { + return Promise.resolve({ + data: { + data: [ + { + uid: 'api::address.address', + settings: { + pageSize: 10, + defaultSortBy: 'name', + defaultSortOrder: 'ASC', + }, + }, + ], }, - }, - ], - }); - }); + }); + } + + // To please the linter + return Promise.resolve(null); + }, + })); const expected = { - authorizedCtLinks: [ + authorizedCollectionTypeLinks: [ { - destination: '/content-manager/collectionType/api::address.address', - icon: 'circle', isDisplayed: true, - label: 'address', + kind: 'collectionType', + name: 'api::address.address', permissions: [ { action: 'plugin::content-manager.explorer.create', @@ -107,13 +111,14 @@ describe('checkPermissions', () => { }, ], search: 'page=1&pageSize=10&sort=name:ASC', + title: 'Address', + to: '/content-manager/collectionType/api::address.address', + uid: 'api::address.address', }, { - destination: '/content-manager/collectionType/api::article.article', - icon: 'circle', isDisplayed: true, - label: 'article', - search: null, + kind: 'collectionType', + name: 'api::article.article', permissions: [ { action: 'plugin::content-manager.explorer.create', @@ -124,12 +129,15 @@ describe('checkPermissions', () => { subject: 'api::article.article', }, ], + search: null, + title: 'Article', + to: '/content-manager/collectionType/api::article.article', + uid: 'api::article.article', }, ], - authorizedStLinks: [], - contentTypes: data, + authorizedSingleTypeLinks: [], }; - const actual = await getContentTypeLinks(userPermissions); + const actual = await getContentTypeLinks({ userPermissions, models: contentTypes }); expect(actual).toEqual(expected); }); @@ -139,11 +147,13 @@ describe('checkPermissions', () => { const toggleNotification = jest.fn(); const userPermissions = []; - request.mockImplementation(() => { - throw new Error('Something went wrong'); - }); + getFetchClient.mockImplementation(() => ({ + get() { + throw new Error('Something went wrong'); + }, + })); - await getContentTypeLinks(userPermissions, toggleNotification); + await getContentTypeLinks({ userPermissions, toggleNotification }); expect(toggleNotification).toBeCalled(); }); }); From 8bb88415c75582aeee2e542fe0bbead79b8d0429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Mon, 17 Apr 2023 10:27:19 +0200 Subject: [PATCH 08/14] Rename full size object --- .../content-manager/server/services/field-sizes.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/core/content-manager/server/services/field-sizes.js b/packages/core/content-manager/server/services/field-sizes.js index ab0dcb98d6..38116aea4a 100644 --- a/packages/core/content-manager/server/services/field-sizes.js +++ b/packages/core/content-manager/server/services/field-sizes.js @@ -1,6 +1,6 @@ 'use strict'; -const fullSize = { +const needsFullSize = { default: 12, resizable: false, }; @@ -17,10 +17,10 @@ const defaultSize = { const fieldSizes = { // Full row and not resizable - dynamiczone: fullSize, - component: fullSize, - json: fullSize, - richtext: fullSize, + dynamiczone: needsFullSize, + component: needsFullSize, + json: needsFullSize, + richtext: needsFullSize, // Small and resizable checkbox: smallSize, boolean: smallSize, From 96ba7cc4315894242d424375cab752805df2ae74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Mon, 17 Apr 2023 10:30:12 +0200 Subject: [PATCH 09/14] getFieldSize error handling --- .../content-manager/server/services/field-sizes.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/core/content-manager/server/services/field-sizes.js b/packages/core/content-manager/server/services/field-sizes.js index 38116aea4a..767335bd96 100644 --- a/packages/core/content-manager/server/services/field-sizes.js +++ b/packages/core/content-manager/server/services/field-sizes.js @@ -49,6 +49,15 @@ module.exports = () => ({ return fieldSizes; }, getFieldSize(type) { - return fieldSizes[type]; + if (!type) { + throw new Error('The type is required'); + } + + const fieldSize = fieldSizes[type]; + if (!fieldSize) { + throw new Error(`Could not find field size for type ${type}`); + } + + return fieldSize; }, }); From d06af0d8fc2030764925ff4cb290ea77fe9e64d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Mon, 17 Apr 2023 12:02:08 +0200 Subject: [PATCH 10/14] Rename to isResizable --- .../pages/EditSettingsView/components/ModalForm.js | 2 +- .../pages/EditSettingsView/tests/reducer.test.js | 6 +++--- .../core/content-manager/server/services/field-sizes.js | 6 +++--- .../server/services/utils/configuration/layouts.js | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js index cd34da865c..cb38264f29 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js @@ -152,7 +152,7 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => { return ( <> {metaFields} - {fieldSizeInfo.resizable && sizeField} + {fieldSizeInfo.isResizable && sizeField} {hasTimePicker && timeStepField} ); diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/reducer.test.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/reducer.test.js index 3d7c26abd2..439e430511 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/reducer.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/tests/reducer.test.js @@ -1,9 +1,9 @@ import reducer from '../reducer'; const fieldSizes = { - richtext: { default: 12, resizable: false }, - string: { default: 6, resizable: true }, - boolean: { default: 4, resizable: true }, + richtext: { default: 12, isResizable: false }, + string: { default: 6, isResizable: true }, + boolean: { default: 4, isResizable: true }, }; describe('CONTENT MANAGER | CONTAINERS | EditSettingsView | reducer', () => { diff --git a/packages/core/content-manager/server/services/field-sizes.js b/packages/core/content-manager/server/services/field-sizes.js index 767335bd96..bdbeffe83f 100644 --- a/packages/core/content-manager/server/services/field-sizes.js +++ b/packages/core/content-manager/server/services/field-sizes.js @@ -2,17 +2,17 @@ const needsFullSize = { default: 12, - resizable: false, + isResizable: false, }; const smallSize = { default: 4, - resizable: true, + isResizable: true, }; const defaultSize = { default: 6, - resizable: true, + isResizable: true, }; const fieldSizes = { diff --git a/packages/core/content-manager/server/services/utils/configuration/layouts.js b/packages/core/content-manager/server/services/utils/configuration/layouts.js index 6cb3262217..18dd5f5c6e 100644 --- a/packages/core/content-manager/server/services/utils/configuration/layouts.js +++ b/packages/core/content-manager/server/services/utils/configuration/layouts.js @@ -12,7 +12,7 @@ const isAllowedFieldSize = (type, size) => { const fieldSize = getFieldSize(type); // Check if field was locked to another size - if (!fieldSize.resizable && size !== fieldSize.default) { + if (!fieldSize.isResizable && size !== fieldSize.default) { return false; } From f721091221bdeef37ce588f2292478f2ca4a717f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Mon, 17 Apr 2023 12:05:12 +0200 Subject: [PATCH 11/14] Destructure isResizable --- .../pages/EditSettingsView/components/ModalForm.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js index cb38264f29..69b7d2b23b 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js @@ -103,7 +103,7 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => { ); }); - const fieldSizeInfo = fieldSizes[attributes[selectedField].type]; + const { isResizable } = fieldSizes[attributes[selectedField].type]; const sizeField = ( @@ -152,7 +152,7 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => { return ( <> {metaFields} - {fieldSizeInfo.isResizable && sizeField} + {isResizable && sizeField} {hasTimePicker && timeStepField} ); From 227f5cdfccff6a120bdceccf3328ef3e650096e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Mon, 17 Apr 2023 17:08:46 +0200 Subject: [PATCH 12/14] Fix mutate content types hook --- .../content-manager/pages/App/selectors.js | 4 ++-- .../pages/App/useContentManagerInitData.js | 21 +++++++++++-------- .../EditSettingsView/components/ModalForm.js | 5 ++--- .../pages/EditSettingsView/index.js | 5 ++--- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/packages/core/admin/admin/src/content-manager/pages/App/selectors.js b/packages/core/admin/admin/src/content-manager/pages/App/selectors.js index 6fd9b09a65..8096c8e87a 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/selectors.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/selectors.js @@ -23,13 +23,13 @@ const makeSelectModelAndComponentSchemas = () => schemas: [...components, ...models], })); -const makeSelectFieldSizes = () => createSelector(selectAppDomain(), (state) => state.fieldSizes); +const selectFieldSizes = createSelector(selectAppDomain(), (state) => state.fieldSizes); export default makeSelectApp; export { makeSelectModelAndComponentSchemas, makeSelectModelLinks, makeSelectModels, - makeSelectFieldSizes, + selectFieldSizes, selectAppDomain, }; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js b/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js index 48ee7217db..133bb5d749 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js @@ -44,24 +44,27 @@ const useContentManagerInitData = () => { }) ); - const { authorizedContentTypeLinks, authorizedSingleTypeLinks } = await getContentTypeLinks({ + const unmutatedContentTypeLinks = await getContentTypeLinks({ models, userPermissions: allPermissions, toggleNotification, }); - const { ctLinks } = runHookWaterfall(MUTATE_COLLECTION_TYPES_LINKS, { - ctLinks: authorizedContentTypeLinks, - models, - }); - const { stLinks } = runHookWaterfall(MUTATE_SINGLE_TYPES_LINKS, { - stLinks: authorizedSingleTypeLinks, + const { ctLinks: authorizedCollectionTypeLinks } = runHookWaterfall( + MUTATE_COLLECTION_TYPES_LINKS, + { + ctLinks: unmutatedContentTypeLinks.authorizedCollectionTypeLinks, + models, + } + ); + const { stLinks: authorizedSingleTypeLinks } = runHookWaterfall(MUTATE_SINGLE_TYPES_LINKS, { + stLinks: unmutatedContentTypeLinks.authorizedSingleTypeLinks, models, }); const actionToDispatch = setInitData({ - authorizedCollectionTypeLinks: ctLinks, - authorizedSingleTypeLinks: stLinks, + authorizedCollectionTypeLinks, + authorizedSingleTypeLinks, contentTypeSchemas: models, components, fieldSizes, diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js index 69b7d2b23b..3b532666bb 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js @@ -6,7 +6,7 @@ import { useSelector, shallowEqual } from 'react-redux'; import { useIntl } from 'react-intl'; import { useLayoutDnd } from '../../../hooks'; import { createPossibleMainFieldsForModelsAndComponents, getInputProps } from '../utils'; -import { makeSelectModelAndComponentSchemas, makeSelectFieldSizes } from '../../App/selectors'; +import { makeSelectModelAndComponentSchemas, selectFieldSizes } from '../../App/selectors'; import getTrad from '../../../utils/getTrad'; import GenericInput from './GenericInput'; @@ -25,9 +25,8 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => { const { formatMessage } = useIntl(); const { modifiedData, selectedField, attributes, fieldForm } = useLayoutDnd(); const schemasSelector = useMemo(makeSelectModelAndComponentSchemas, []); - const fieldSizesSelector = useMemo(makeSelectFieldSizes, []); const { schemas } = useSelector((state) => schemasSelector(state), shallowEqual); - const fieldSizes = useSelector((state) => fieldSizesSelector(state)); + const fieldSizes = useSelector(selectFieldSizes); const formToDisplay = useMemo(() => { if (!selectedField) { diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js index 6749fc9866..e7a7ccdcae 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js @@ -35,7 +35,7 @@ import ModalForm from './components/FormModal'; import LayoutDndProvider from '../../components/LayoutDndProvider'; import { unformatLayout } from './utils/layout'; import putCMSettingsEV from './utils/api'; -import { makeSelectFieldSizes } from '../App/selectors'; +import { selectFieldSizes } from '../App/selectors'; const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, updateLayout }) => { const [reducerState, dispatch] = useReducer(reducer, initialState, () => @@ -51,8 +51,7 @@ const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, upd const { formatMessage } = useIntl(); const modelName = get(mainLayout, ['info', 'displayName'], ''); const attributes = get(modifiedData, ['attributes'], {}); - const fieldSizesSelector = useMemo(makeSelectFieldSizes, []); - const fieldSizes = useSelector((state) => fieldSizesSelector(state)); + const fieldSizes = useSelector(selectFieldSizes); const entryTitleOptions = Object.keys(attributes).filter((attr) => { const type = get(attributes, [attr, 'type'], ''); From 30bacd6626a5ccb793f93bed9b35ff4d55e831c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Mon, 17 Apr 2023 17:29:13 +0200 Subject: [PATCH 13/14] Add tests to field sizes service --- .../services/__tests__/field-sizes.test.js | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 packages/core/content-manager/server/services/__tests__/field-sizes.test.js diff --git a/packages/core/content-manager/server/services/__tests__/field-sizes.test.js b/packages/core/content-manager/server/services/__tests__/field-sizes.test.js new file mode 100644 index 0000000000..43c79cc101 --- /dev/null +++ b/packages/core/content-manager/server/services/__tests__/field-sizes.test.js @@ -0,0 +1,33 @@ +'use strict'; + +const fieldSizesService = require('../field-sizes'); + +describe('field sizes service', () => { + it('should return the correct field sizes', () => { + const { getAllFieldSizes } = fieldSizesService(); + const fieldSizes = getAllFieldSizes(); + Object.values(fieldSizes).forEach((fieldSize) => { + expect(typeof fieldSize.isResizable).toBe('boolean'); + expect([4, 6, 8, 12]).toContain(fieldSize.default); + }); + }); + + it('should return the correct field size for a given type', () => { + const { getFieldSize } = fieldSizesService(); + const fieldSize = getFieldSize('string'); + expect(fieldSize.isResizable).toBe(true); + expect(fieldSize.default).toBe(6); + }); + + it('should throw an error if the type is not found', () => { + const { getFieldSize } = fieldSizesService(); + expect(() => getFieldSize('not-found')).toThrowError( + 'Could not find field size for type not-found' + ); + }); + + it('should throw an error if the type is not provided', () => { + const { getFieldSize } = fieldSizesService(); + expect(() => getFieldSize()).toThrowError('The type is required'); + }); +}); From d343c1f3738c5bfb86384bfd26a94c5b969fe015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20de=20Juvigny?= Date: Mon, 17 Apr 2023 18:03:18 +0200 Subject: [PATCH 14/14] Fix linter error --- .../admin/src/content-manager/pages/EditSettingsView/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js index e7a7ccdcae..77c3af9a47 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.js @@ -1,4 +1,4 @@ -import React, { useMemo, useReducer, useState } from 'react'; +import React, { useReducer, useState } from 'react'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import { useMutation } from 'react-query';