diff --git a/packages/core/admin/admin/src/StrapiApp.js b/packages/core/admin/admin/src/StrapiApp.js index 85d0535b5f..f36c126a28 100644 --- a/packages/core/admin/admin/src/StrapiApp.js +++ b/packages/core/admin/admin/src/StrapiApp.js @@ -5,7 +5,7 @@ import { QueryClientProvider, QueryClient } from 'react-query'; import { ThemeProvider } from 'styled-components'; import { StrapiProvider } from '@strapi/helper-plugin'; import configureStore from './core/store/configureStore'; -import { Plugin } from './core/apis'; +import { Components, Fields, Plugin } from './core/apis'; import basename from './utils/basename'; import App from './pages/App'; import LanguageProvider from './components/LanguageProvider'; @@ -38,11 +38,13 @@ const appLocales = Object.keys(translations); class StrapiApp { constructor({ appPlugins }) { - this.translationMessages = translations; this.appPlugins = appPlugins || {}; + this.componentApi = Components(); + this.fieldApi = Fields(); this.middlewares = []; this.plugins = {}; this.reducers = { ...reducers }; + this.translations = translations; } addMiddleware(middleware) { @@ -93,9 +95,9 @@ class StrapiApp { return acc; }, {}); - this.translationMessages = Object.keys(this.translationMessages).reduce((acc, current) => { + this.translations = Object.keys(this.translations).reduce((acc, current) => { acc[current] = { - ...this.translationMessages[current], + ...this.translations[current], ...(pluginTranslations[current] || {}), }; @@ -125,7 +127,7 @@ class StrapiApp { - + <> diff --git a/packages/core/admin/admin/src/core/apis/Components.js b/packages/core/admin/admin/src/core/apis/Components.js new file mode 100644 index 0000000000..5b2aeb5e6b --- /dev/null +++ b/packages/core/admin/admin/src/core/apis/Components.js @@ -0,0 +1,43 @@ +import { cloneDeep } from 'lodash'; +import invariant from 'invariant'; + +// TODO this API should be merged with the components one +class Components { + components = {}; + + getComponent = name => { + invariant(name, 'A name must be provided'); + + return cloneDeep(this.components[name]) || null; + }; + + getComponents = () => { + const components = cloneDeep(this.components); + + return Object.keys(components).reduce((acc, current) => { + acc[current] = components[current].Component; + + return acc; + }, {}); + }; + + registerComponent = component => { + const { name, Component } = component; + + invariant(Component, 'A Component must be provided'); + invariant(name, 'A name must be provided'); + invariant(this.components[name] === undefined, 'A similar field already exists'); + + this.components[name] = { Component }; + }; + + removeComponent = name => { + invariant(name, 'A name must be provided in order to remove a field'); + + delete this.components[name]; + }; +} + +export default () => { + return new Components(); +}; diff --git a/packages/core/admin/admin/src/core/apis/Fields.js b/packages/core/admin/admin/src/core/apis/Fields.js new file mode 100644 index 0000000000..2db0b16e67 --- /dev/null +++ b/packages/core/admin/admin/src/core/apis/Fields.js @@ -0,0 +1,43 @@ +import { cloneDeep } from 'lodash'; +import invariant from 'invariant'; + +// TODO this API should be merged with the components one +class Fields { + fields = {}; + + getField = type => { + invariant(type, 'A type must be provided'); + + return cloneDeep(this.fields[type]) || null; + }; + + getFields = () => { + const fields = cloneDeep(this.fields); + + return Object.keys(fields).reduce((acc, current) => { + acc[current] = fields[current].Component; + + return acc; + }, {}); + }; + + registerField = field => { + const { type, Component } = field; + + invariant(Component, 'A Component must be provided'); + invariant(type, 'A type must be provided'); + invariant(this.fields[type] === undefined, 'A similar field already exists'); + + this.fields[type] = { Component }; + }; + + removeField = type => { + invariant(type, 'A type must be provided in order to remove a field'); + + delete this.fields[type]; + }; +} + +export default () => { + return new Fields(); +}; diff --git a/packages/core/admin/admin/src/core/apis/index.js b/packages/core/admin/admin/src/core/apis/index.js index 77c8702e6d..1837f9a21b 100644 --- a/packages/core/admin/admin/src/core/apis/index.js +++ b/packages/core/admin/admin/src/core/apis/index.js @@ -1,2 +1,3 @@ -// eslint-disable-next-line import/prefer-default-export +export { default as Components } from './Components'; +export { default as Fields } from './Fields'; export { default as Plugin } from './Plugin'; diff --git a/packages/core/admin/admin/src/plugins.js b/packages/core/admin/admin/src/plugins.js index 0b3059d2cc..f595fe116a 100644 --- a/packages/core/admin/admin/src/plugins.js +++ b/packages/core/admin/admin/src/plugins.js @@ -3,9 +3,11 @@ import documentationPlugin from '../../../../plugins/documentation/admin/src'; import graphqlPlugin from '../../../../plugins/graphql/admin/src'; import sentryPlugin from '../../../../plugins/sentry/admin/src'; import usersPermissionsPlugin from '../../../../plugins/users-permissions/admin/src'; +import cmPlugin from '../../../content-manager/admin/src'; import emailPlugin from '../../../email/admin/src'; const plugins = { + '@strapi/plugin-content-manager': cmPlugin, '@strapi/plugin-documentation': documentationPlugin, '@strapi/plugin-email': emailPlugin, '@strapi/plugin-graphql': graphqlPlugin, diff --git a/packages/core/content-manager/admin/src/components/Inputs/index.js b/packages/core/content-manager/admin/src/components/Inputs/index.js index c10d170bc1..39630fa06b 100644 --- a/packages/core/content-manager/admin/src/components/Inputs/index.js +++ b/packages/core/content-manager/admin/src/components/Inputs/index.js @@ -36,6 +36,7 @@ function Inputs({ queryInfos, value, }) { + // TODO change to app const { strapi: { fieldApi }, } = useStrapi(); diff --git a/packages/core/content-manager/admin/src/components/Wysiwyg/MediaLib.js b/packages/core/content-manager/admin/src/components/Wysiwyg/MediaLib.js index a2bf70ddec..a14aa1b312 100644 --- a/packages/core/content-manager/admin/src/components/Wysiwyg/MediaLib.js +++ b/packages/core/content-manager/admin/src/components/Wysiwyg/MediaLib.js @@ -17,7 +17,7 @@ const MediaLib = ({ isOpen, onChange, onToggle }) => { } }, [isOpen]); - const Component = getComponent('media-library').Component; + const Component = getComponent('media-library')?.Component; const handleInputChange = data => { if (data) { diff --git a/packages/core/content-manager/admin/src/containers/EditViewLayoutManager/selectors.js b/packages/core/content-manager/admin/src/containers/EditViewLayoutManager/selectors.js index 6d44325b79..e8a8011197 100644 --- a/packages/core/content-manager/admin/src/containers/EditViewLayoutManager/selectors.js +++ b/packages/core/content-manager/admin/src/containers/EditViewLayoutManager/selectors.js @@ -1,5 +1,5 @@ import pluginId from '../../pluginId'; -const selectLayout = state => state.get(`${pluginId}_editViewLayoutManager`).currentLayout; +const selectLayout = state => state.[`${pluginId}_editViewLayoutManager`].currentLayout; export default selectLayout; diff --git a/packages/core/content-manager/admin/src/containers/ListView/selectors.js b/packages/core/content-manager/admin/src/containers/ListView/selectors.js index eaedece71a..da6b6143a1 100644 --- a/packages/core/content-manager/admin/src/containers/ListView/selectors.js +++ b/packages/core/content-manager/admin/src/containers/ListView/selectors.js @@ -5,7 +5,7 @@ import { initialState } from './reducer'; /** * Direct selector to the listView state domain */ -const listViewDomain = () => state => state.get(`${pluginId}_listView`) || initialState; +const listViewDomain = () => state => state[`${pluginId}_listView`] || initialState; /** * Other specific selectors diff --git a/packages/core/content-manager/admin/src/containers/Main/selectors.js b/packages/core/content-manager/admin/src/containers/Main/selectors.js index b0a3fa9022..8d6e83473d 100644 --- a/packages/core/content-manager/admin/src/containers/Main/selectors.js +++ b/packages/core/content-manager/admin/src/containers/Main/selectors.js @@ -3,7 +3,7 @@ import pluginId from '../../pluginId'; import { initialState } from './reducer'; const selectMainDomain = () => state => { - return state.get(`${pluginId}_main`) || initialState; + return state[`${pluginId}_main`] || initialState; }; const makeSelectMain = () => diff --git a/packages/core/content-manager/admin/src/hooks/useFindRedirectionLink/selectors.js b/packages/core/content-manager/admin/src/hooks/useFindRedirectionLink/selectors.js index 857c325c94..762110e486 100644 --- a/packages/core/content-manager/admin/src/hooks/useFindRedirectionLink/selectors.js +++ b/packages/core/content-manager/admin/src/hooks/useFindRedirectionLink/selectors.js @@ -1,5 +1,5 @@ const selectMenuLinks = state => { - const menuState = state.get('menu'); + const menuState = state.menu; return menuState.collectionTypesSectionLinks; }; diff --git a/packages/core/content-manager/admin/src/index.js b/packages/core/content-manager/admin/src/index.js index cc0fc01123..4f25f982a2 100644 --- a/packages/core/content-manager/admin/src/index.js +++ b/packages/core/content-manager/admin/src/index.js @@ -9,44 +9,43 @@ import pluginPkg from '../../package.json'; import pluginId from './pluginId'; import pluginLogo from './assets/images/logo.svg'; import App from './containers/Main'; - import ConfigureViewButton from './InjectedComponents/ContentTypeBuilder/ConfigureViewButton'; -import lifecycles from './lifecycles'; import reducers from './reducers'; import trads from './translations'; -export default strapi => { - const pluginDescription = pluginPkg.strapi.description || pluginPkg.description; - const plugin = { - blockerComponent: null, - blockerComponentProps: {}, - description: pluginDescription, - icon: pluginPkg.strapi.icon, - id: pluginId, - initializer: null, - injectedComponents: [ - { - plugin: 'content-type-builder.listView', - area: 'list.link', - component: ConfigureViewButton, - key: 'content-manager.link', - }, - ], - injectionZones: { - editView: { informations: [] }, - listView: { actions: [], deleteModalAdditionalInfos: [] }, - }, - isReady: true, - isRequired: pluginPkg.strapi.required || false, - layout: null, - lifecycles, - mainComponent: App, - name: pluginPkg.strapi.name, - pluginLogo, - preventComponentRendering: false, - reducers, - trads, - }; +const pluginDescription = pluginPkg.strapi.description || pluginPkg.description; +const icon = pluginPkg.strapi.icon; +const name = pluginPkg.strapi.name; - return strapi.registerPlugin(plugin); +export default { + register(app) { + app.addReducers(reducers); + + app.registerPlugin({ + description: pluginDescription, + icon, + id: pluginId, + // TODO + injectedComponents: [ + { + plugin: 'content-type-builder.listView', + area: 'list.link', + component: ConfigureViewButton, + key: 'content-manager.link', + }, + ], + injectionZones: { + editView: { informations: [] }, + listView: { actions: [], deleteModalAdditionalInfos: [] }, + }, + isReady: true, + isRequired: pluginPkg.strapi.required || false, + mainComponent: App, + name, + pluginLogo, + preventComponentRendering: false, + trads, + }); + }, + boot() {}, }; diff --git a/packages/core/content-manager/admin/src/lifecycles.js b/packages/core/content-manager/admin/src/lifecycles.js deleted file mode 100644 index 4e2850191c..0000000000 --- a/packages/core/content-manager/admin/src/lifecycles.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * - * SET THE HOOKS TO ENABLE THE MAGIC OF STRAPI. - * ------------------------------------------- - * - * Secure, customise and enhance your project by setting - * the hooks via this file. - * - */ - -function lifecycles() { - // Set hooks for the AdminPage container. - // Note: we don't need to specify the first argument because we already know what "willSecure" refers to. - // this.setHooks({ - // didGetSecuredData, - // }); -} - -export default lifecycles; diff --git a/packages/core/content-manager/admin/src/selectors.js b/packages/core/content-manager/admin/src/selectors.js index c9c1d3ca77..4f0296c725 100644 --- a/packages/core/content-manager/admin/src/selectors.js +++ b/packages/core/content-manager/admin/src/selectors.js @@ -1,6 +1,6 @@ import pluginId from './pluginId'; -export const selectPermissions = state => state.get(`${pluginId}_rbacManager`).permissions; +export const selectPermissions = state => state[`${pluginId}_rbacManager`].permissions; export const selectCollectionTypePermissions = state => - state.get('permissionsManager').collectionTypesRelatedPermissions; + state.permissionsManager.collectionTypesRelatedPermissions; diff --git a/packages/core/content-manager/admin/src/sharedReducers/crudReducer/selectors.js b/packages/core/content-manager/admin/src/sharedReducers/crudReducer/selectors.js index 0669de9051..31a3823f07 100644 --- a/packages/core/content-manager/admin/src/sharedReducers/crudReducer/selectors.js +++ b/packages/core/content-manager/admin/src/sharedReducers/crudReducer/selectors.js @@ -1,5 +1,5 @@ import pluginId from '../../pluginId'; -const selectCrudReducer = state => state.get(`${pluginId}_editViewCrudReducer`); +const selectCrudReducer = state => state[`${pluginId}_editViewCrudReducer`]; export default selectCrudReducer; diff --git a/packages/core/content-manager/admin/src/tests/selectors.test.js b/packages/core/content-manager/admin/src/tests/selectors.test.js index e26e982b17..622aad3304 100644 --- a/packages/core/content-manager/admin/src/tests/selectors.test.js +++ b/packages/core/content-manager/admin/src/tests/selectors.test.js @@ -4,16 +4,16 @@ describe('selectors', () => { let store; beforeEach(() => { - store = new Map(); + store = {}; }); describe('selectPermissions', () => { it('resolves the permissions key of the "content-manager_rbacManager" store key', () => { - store.set('content-manager_rbacManager', { + store['content-manager_rbacManager'] = { permissions: { some: 'permission', }, - }); + }; const actual = selectPermissions(store); const expected = { @@ -26,11 +26,11 @@ describe('selectors', () => { describe('selectCollectionTypePermissions', () => { it('resolves the permissions key of the "permissionsManager" store key', () => { - store.set('permissionsManager', { + store.permissionsManager = { collectionTypesRelatedPermissions: { some: 'permission again', }, - }); + }; const actual = selectCollectionTypePermissions(store); const expected = { diff --git a/packages/core/helper-plugin/lib/src/components/InputSelect/Select.js b/packages/core/helper-plugin/lib/src/components/InputSelect/Select.js index 8ca10cc1eb..10f0d05d7a 100644 --- a/packages/core/helper-plugin/lib/src/components/InputSelect/Select.js +++ b/packages/core/helper-plugin/lib/src/components/InputSelect/Select.js @@ -8,7 +8,7 @@ const Select = styled.select` padding-left: 1rem; background-position: right -1px center; background-repeat: no-repeat; - background-image: url(${Bkg}); + background-image: url("${Bkg}"); border: 1px solid #e3e9f3; border-radius: 0.25rem; line-height: 3.2rem; diff --git a/packages/core/helper-plugin/lib/src/components/LiLink/StyledLink.js b/packages/core/helper-plugin/lib/src/components/LiLink/StyledLink.js index 6d0bb1b479..a0934c6c9c 100644 --- a/packages/core/helper-plugin/lib/src/components/LiLink/StyledLink.js +++ b/packages/core/helper-plugin/lib/src/components/LiLink/StyledLink.js @@ -21,7 +21,7 @@ const StyledLink = styled(Link)` } .layout { display: inline-block; - background-image: url(${Layout}); + background-image: url("${Layout}"); } &:hover { text-decoration: none; @@ -31,7 +31,7 @@ const StyledLink = styled(Link)` color: #007eff; } .layout { - background-image: url(${LayoutHover}); + background-image: url("${LayoutHover}"); } } `; diff --git a/packages/core/helper-plugin/lib/src/components/PageFooter/Wrapper.js b/packages/core/helper-plugin/lib/src/components/PageFooter/Wrapper.js index e15fe2a40b..19ba881721 100644 --- a/packages/core/helper-plugin/lib/src/components/PageFooter/Wrapper.js +++ b/packages/core/helper-plugin/lib/src/components/PageFooter/Wrapper.js @@ -18,6 +18,7 @@ const Wrapper = styled.div` display: flex; > select { + background-image: url("${Bkg}"); width: 75px !important; height: 3.2rem !important; padding-top: 0rem; @@ -25,7 +26,6 @@ const Wrapper = styled.div` padding-right: 3rem; background-position: right -1px center; background-repeat: no-repeat; - background-image: url(${Bkg}); border: 1px solid #e3e9f3; border-radius: 0.25rem; line-height: 29px;