mirror of
https://github.com/strapi/strapi.git
synced 2025-11-12 16:22:10 +00:00
commit
c2de5d69d2
@ -5,7 +5,7 @@ import { QueryClientProvider, QueryClient } from 'react-query';
|
|||||||
import { ThemeProvider } from 'styled-components';
|
import { ThemeProvider } from 'styled-components';
|
||||||
import { StrapiProvider } from '@strapi/helper-plugin';
|
import { StrapiProvider } from '@strapi/helper-plugin';
|
||||||
import configureStore from './core/store/configureStore';
|
import configureStore from './core/store/configureStore';
|
||||||
import { Plugin } from './core/apis';
|
import { Components, Fields, Plugin } from './core/apis';
|
||||||
import basename from './utils/basename';
|
import basename from './utils/basename';
|
||||||
import App from './pages/App';
|
import App from './pages/App';
|
||||||
import LanguageProvider from './components/LanguageProvider';
|
import LanguageProvider from './components/LanguageProvider';
|
||||||
@ -38,11 +38,13 @@ const appLocales = Object.keys(translations);
|
|||||||
|
|
||||||
class StrapiApp {
|
class StrapiApp {
|
||||||
constructor({ appPlugins }) {
|
constructor({ appPlugins }) {
|
||||||
this.translationMessages = translations;
|
|
||||||
this.appPlugins = appPlugins || {};
|
this.appPlugins = appPlugins || {};
|
||||||
|
this.componentApi = Components();
|
||||||
|
this.fieldApi = Fields();
|
||||||
this.middlewares = [];
|
this.middlewares = [];
|
||||||
this.plugins = {};
|
this.plugins = {};
|
||||||
this.reducers = { ...reducers };
|
this.reducers = { ...reducers };
|
||||||
|
this.translations = translations;
|
||||||
}
|
}
|
||||||
|
|
||||||
addMiddleware(middleware) {
|
addMiddleware(middleware) {
|
||||||
@ -93,9 +95,9 @@ class StrapiApp {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
this.translationMessages = Object.keys(this.translationMessages).reduce((acc, current) => {
|
this.translations = Object.keys(this.translations).reduce((acc, current) => {
|
||||||
acc[current] = {
|
acc[current] = {
|
||||||
...this.translationMessages[current],
|
...this.translations[current],
|
||||||
...(pluginTranslations[current] || {}),
|
...(pluginTranslations[current] || {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,7 +127,7 @@ class StrapiApp {
|
|||||||
<Fonts />
|
<Fonts />
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<StrapiProvider strapi={this}>
|
<StrapiProvider strapi={this}>
|
||||||
<LanguageProvider messages={this.translationMessages}>
|
<LanguageProvider messages={this.translations}>
|
||||||
<>
|
<>
|
||||||
<AutoReloadOverlayBlocker />
|
<AutoReloadOverlayBlocker />
|
||||||
<OverlayBlocker />
|
<OverlayBlocker />
|
||||||
|
|||||||
43
packages/core/admin/admin/src/core/apis/Components.js
Normal file
43
packages/core/admin/admin/src/core/apis/Components.js
Normal file
@ -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();
|
||||||
|
};
|
||||||
43
packages/core/admin/admin/src/core/apis/Fields.js
Normal file
43
packages/core/admin/admin/src/core/apis/Fields.js
Normal file
@ -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();
|
||||||
|
};
|
||||||
@ -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';
|
export { default as Plugin } from './Plugin';
|
||||||
|
|||||||
@ -3,9 +3,11 @@ import documentationPlugin from '../../../../plugins/documentation/admin/src';
|
|||||||
import graphqlPlugin from '../../../../plugins/graphql/admin/src';
|
import graphqlPlugin from '../../../../plugins/graphql/admin/src';
|
||||||
import sentryPlugin from '../../../../plugins/sentry/admin/src';
|
import sentryPlugin from '../../../../plugins/sentry/admin/src';
|
||||||
import usersPermissionsPlugin from '../../../../plugins/users-permissions/admin/src';
|
import usersPermissionsPlugin from '../../../../plugins/users-permissions/admin/src';
|
||||||
|
import cmPlugin from '../../../content-manager/admin/src';
|
||||||
import emailPlugin from '../../../email/admin/src';
|
import emailPlugin from '../../../email/admin/src';
|
||||||
|
|
||||||
const plugins = {
|
const plugins = {
|
||||||
|
'@strapi/plugin-content-manager': cmPlugin,
|
||||||
'@strapi/plugin-documentation': documentationPlugin,
|
'@strapi/plugin-documentation': documentationPlugin,
|
||||||
'@strapi/plugin-email': emailPlugin,
|
'@strapi/plugin-email': emailPlugin,
|
||||||
'@strapi/plugin-graphql': graphqlPlugin,
|
'@strapi/plugin-graphql': graphqlPlugin,
|
||||||
|
|||||||
@ -36,6 +36,7 @@ function Inputs({
|
|||||||
queryInfos,
|
queryInfos,
|
||||||
value,
|
value,
|
||||||
}) {
|
}) {
|
||||||
|
// TODO change to app
|
||||||
const {
|
const {
|
||||||
strapi: { fieldApi },
|
strapi: { fieldApi },
|
||||||
} = useStrapi();
|
} = useStrapi();
|
||||||
|
|||||||
@ -17,7 +17,7 @@ const MediaLib = ({ isOpen, onChange, onToggle }) => {
|
|||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
const Component = getComponent('media-library').Component;
|
const Component = getComponent('media-library')?.Component;
|
||||||
|
|
||||||
const handleInputChange = data => {
|
const handleInputChange = data => {
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
|
|
||||||
const selectLayout = state => state.get(`${pluginId}_editViewLayoutManager`).currentLayout;
|
const selectLayout = state => state.[`${pluginId}_editViewLayoutManager`].currentLayout;
|
||||||
|
|
||||||
export default selectLayout;
|
export default selectLayout;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { initialState } from './reducer';
|
|||||||
/**
|
/**
|
||||||
* Direct selector to the listView state domain
|
* 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
|
* Other specific selectors
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import pluginId from '../../pluginId';
|
|||||||
import { initialState } from './reducer';
|
import { initialState } from './reducer';
|
||||||
|
|
||||||
const selectMainDomain = () => state => {
|
const selectMainDomain = () => state => {
|
||||||
return state.get(`${pluginId}_main`) || initialState;
|
return state[`${pluginId}_main`] || initialState;
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeSelectMain = () =>
|
const makeSelectMain = () =>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const selectMenuLinks = state => {
|
const selectMenuLinks = state => {
|
||||||
const menuState = state.get('menu');
|
const menuState = state.menu;
|
||||||
|
|
||||||
return menuState.collectionTypesSectionLinks;
|
return menuState.collectionTypesSectionLinks;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,44 +9,43 @@ import pluginPkg from '../../package.json';
|
|||||||
import pluginId from './pluginId';
|
import pluginId from './pluginId';
|
||||||
import pluginLogo from './assets/images/logo.svg';
|
import pluginLogo from './assets/images/logo.svg';
|
||||||
import App from './containers/Main';
|
import App from './containers/Main';
|
||||||
|
|
||||||
import ConfigureViewButton from './InjectedComponents/ContentTypeBuilder/ConfigureViewButton';
|
import ConfigureViewButton from './InjectedComponents/ContentTypeBuilder/ConfigureViewButton';
|
||||||
import lifecycles from './lifecycles';
|
|
||||||
import reducers from './reducers';
|
import reducers from './reducers';
|
||||||
import trads from './translations';
|
import trads from './translations';
|
||||||
|
|
||||||
export default strapi => {
|
const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
|
||||||
const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
|
const icon = pluginPkg.strapi.icon;
|
||||||
const plugin = {
|
const name = pluginPkg.strapi.name;
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
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() {},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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;
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import pluginId from './pluginId';
|
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 =>
|
export const selectCollectionTypePermissions = state =>
|
||||||
state.get('permissionsManager').collectionTypesRelatedPermissions;
|
state.permissionsManager.collectionTypesRelatedPermissions;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
|
|
||||||
const selectCrudReducer = state => state.get(`${pluginId}_editViewCrudReducer`);
|
const selectCrudReducer = state => state[`${pluginId}_editViewCrudReducer`];
|
||||||
|
|
||||||
export default selectCrudReducer;
|
export default selectCrudReducer;
|
||||||
|
|||||||
@ -4,16 +4,16 @@ describe('selectors', () => {
|
|||||||
let store;
|
let store;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
store = new Map();
|
store = {};
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('selectPermissions', () => {
|
describe('selectPermissions', () => {
|
||||||
it('resolves the permissions key of the "content-manager_rbacManager" store key', () => {
|
it('resolves the permissions key of the "content-manager_rbacManager" store key', () => {
|
||||||
store.set('content-manager_rbacManager', {
|
store['content-manager_rbacManager'] = {
|
||||||
permissions: {
|
permissions: {
|
||||||
some: 'permission',
|
some: 'permission',
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
const actual = selectPermissions(store);
|
const actual = selectPermissions(store);
|
||||||
const expected = {
|
const expected = {
|
||||||
@ -26,11 +26,11 @@ describe('selectors', () => {
|
|||||||
|
|
||||||
describe('selectCollectionTypePermissions', () => {
|
describe('selectCollectionTypePermissions', () => {
|
||||||
it('resolves the permissions key of the "permissionsManager" store key', () => {
|
it('resolves the permissions key of the "permissionsManager" store key', () => {
|
||||||
store.set('permissionsManager', {
|
store.permissionsManager = {
|
||||||
collectionTypesRelatedPermissions: {
|
collectionTypesRelatedPermissions: {
|
||||||
some: 'permission again',
|
some: 'permission again',
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
const actual = selectCollectionTypePermissions(store);
|
const actual = selectCollectionTypePermissions(store);
|
||||||
const expected = {
|
const expected = {
|
||||||
|
|||||||
@ -8,7 +8,7 @@ const Select = styled.select`
|
|||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
background-position: right -1px center;
|
background-position: right -1px center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-image: url(${Bkg});
|
background-image: url("${Bkg}");
|
||||||
border: 1px solid #e3e9f3;
|
border: 1px solid #e3e9f3;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
line-height: 3.2rem;
|
line-height: 3.2rem;
|
||||||
|
|||||||
@ -21,7 +21,7 @@ const StyledLink = styled(Link)`
|
|||||||
}
|
}
|
||||||
.layout {
|
.layout {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-image: url(${Layout});
|
background-image: url("${Layout}");
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@ -31,7 +31,7 @@ const StyledLink = styled(Link)`
|
|||||||
color: #007eff;
|
color: #007eff;
|
||||||
}
|
}
|
||||||
.layout {
|
.layout {
|
||||||
background-image: url(${LayoutHover});
|
background-image: url("${LayoutHover}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -18,6 +18,7 @@ const Wrapper = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
> select {
|
> select {
|
||||||
|
background-image: url("${Bkg}");
|
||||||
width: 75px !important;
|
width: 75px !important;
|
||||||
height: 3.2rem !important;
|
height: 3.2rem !important;
|
||||||
padding-top: 0rem;
|
padding-top: 0rem;
|
||||||
@ -25,7 +26,6 @@ const Wrapper = styled.div`
|
|||||||
padding-right: 3rem;
|
padding-right: 3rem;
|
||||||
background-position: right -1px center;
|
background-position: right -1px center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-image: url(${Bkg});
|
|
||||||
border: 1px solid #e3e9f3;
|
border: 1px solid #e3e9f3;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
line-height: 29px;
|
line-height: 29px;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user