mirror of
https://github.com/strapi/strapi.git
synced 2025-12-25 06:04:29 +00:00
Created menu api
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
c68f815a51
commit
ef208589d5
@ -63,6 +63,28 @@ class StrapiApp {
|
||||
}
|
||||
};
|
||||
|
||||
addCorePluginMenuLink = link => {
|
||||
const stringifiedLink = JSON.stringify(link);
|
||||
|
||||
invariant(link.to, `link.to should be defined for ${stringifiedLink}`);
|
||||
invariant(
|
||||
typeof link.to === 'string',
|
||||
`Expected link.to to be a string instead received ${typeof link.to}`
|
||||
);
|
||||
invariant(
|
||||
['/plugins/content-manager', '/plugins/content-type-builder', '/plugins/upload'].includes(
|
||||
link.to
|
||||
),
|
||||
'This method is not available for your plugin'
|
||||
);
|
||||
invariant(
|
||||
link.intlLabel?.id && link.intlLabel?.defaultMessage,
|
||||
`link.intlLabel.id & link.intlLabel.defaultMessage for ${stringifiedLink}`
|
||||
);
|
||||
|
||||
this.menu.push(link);
|
||||
};
|
||||
|
||||
addFields = fields => {
|
||||
if (Array.isArray(fields)) {
|
||||
fields.map(field => this.library.fields.add(field));
|
||||
@ -87,6 +109,8 @@ class StrapiApp {
|
||||
link.Component && typeof link.Component === 'function',
|
||||
`link.Component should be a valid React Component`
|
||||
);
|
||||
|
||||
this.menu.push(link);
|
||||
};
|
||||
|
||||
addMiddlewares = middlewares => {
|
||||
@ -133,6 +157,7 @@ class StrapiApp {
|
||||
Object.keys(this.appPlugins).forEach(plugin => {
|
||||
this.appPlugins[plugin].register({
|
||||
addComponents: this.addComponents,
|
||||
addCorePluginMenuLink: this.addCorePluginMenuLink,
|
||||
addFields: this.addFields,
|
||||
addMenuLink: this.addMenuLink,
|
||||
addMiddlewares: this.addMiddlewares,
|
||||
@ -286,6 +311,7 @@ class StrapiApp {
|
||||
<Provider store={store}>
|
||||
<StrapiAppProvider
|
||||
getPlugin={this.getPlugin}
|
||||
menu={this.menu}
|
||||
plugins={this.plugins}
|
||||
runHookParallel={this.runHookParallel}
|
||||
runHookWaterfall={this.runHookWaterfall}
|
||||
|
||||
@ -4,7 +4,6 @@ import { useSelector, useDispatch } from 'react-redux';
|
||||
import getPluginSectionLinks from './utils/getPluginSectionLinks';
|
||||
import getGeneralLinks from './utils/getGeneralLinks';
|
||||
import { setSectionLinks, unsetIsLoading } from './actions';
|
||||
import toPluginLinks from './utils/toPluginLinks';
|
||||
import selectMenuLinks from './selectors';
|
||||
|
||||
const useMenuSections = () => {
|
||||
@ -12,18 +11,16 @@ const useMenuSections = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { allPermissions } = useRBACProvider();
|
||||
const { shouldUpdateStrapi } = useAppInfos();
|
||||
const { plugins } = useStrapiApp();
|
||||
const { menu } = useStrapiApp();
|
||||
|
||||
// We are using a ref because we don't want our effect to have this in its dependencies array
|
||||
const generalSectionLinksRef = useRef(state.generalSectionLinks);
|
||||
const shouldUpdateStrapiRef = useRef(shouldUpdateStrapi);
|
||||
// Once in the app lifecycle the plugins should not be added into any dependencies array, in order to prevent
|
||||
// the effect to be run when another plugin is using one plugins internal api for instance
|
||||
// so it's definitely ok to use a ref here
|
||||
const pluginsRef = useRef(plugins);
|
||||
// Once in the app lifecycle the menu should not be added into any dependencies array
|
||||
const menuRef = useRef(menu);
|
||||
|
||||
const resolvePermissions = async (permissions = allPermissions) => {
|
||||
const pluginsSectionLinks = toPluginLinks(pluginsRef.current);
|
||||
const pluginsSectionLinks = menuRef.current;
|
||||
|
||||
const authorizedPluginSectionLinks = await getPluginSectionLinks(
|
||||
permissions,
|
||||
@ -46,8 +43,6 @@ const useMenuSections = () => {
|
||||
resolvePermissionsRef.current(allPermissions);
|
||||
}, [allPermissions, dispatch]);
|
||||
|
||||
// TODO remove the isDisplayed key from the links it's not useful anymore
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
import toPluginLinks from '../toPluginLinks';
|
||||
|
||||
describe('toPluginLinks', () => {
|
||||
it('transforms a plugin object into an array of plugin page links', async () => {
|
||||
const plugins = [
|
||||
{
|
||||
id: 'content-type-builder',
|
||||
description: 'content-type-builder.plugin.description',
|
||||
name: 'Content Type Builder',
|
||||
menu: {
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
destination: '/plugins/content-type-builder',
|
||||
icon: 'paint-brush',
|
||||
label: {
|
||||
id: 'content-type-builder.plugin.name',
|
||||
defaultMessage: 'Content-Types Builder',
|
||||
},
|
||||
name: 'Content Type Builder',
|
||||
permissions: [
|
||||
{
|
||||
action: 'plugins::content-type-builder.read',
|
||||
subject: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'content-manager',
|
||||
description: 'content-manager.plugin.description',
|
||||
name: 'Content Manager',
|
||||
},
|
||||
];
|
||||
|
||||
const expected = [
|
||||
{
|
||||
destination: '/plugins/content-type-builder',
|
||||
icon: 'paint-brush',
|
||||
label: {
|
||||
id: 'content-type-builder.plugin.name',
|
||||
defaultMessage: 'Content-Types Builder',
|
||||
},
|
||||
permissions: [
|
||||
{
|
||||
action: 'plugins::content-type-builder.read',
|
||||
subject: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const actual = toPluginLinks(plugins);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@ -1,19 +0,0 @@
|
||||
import get from 'lodash/get';
|
||||
import omit from 'lodash/omit';
|
||||
import sortLinks from '../../../utils/sortLinks';
|
||||
|
||||
const toPluginLinks = plugins => {
|
||||
const pluginsLinks = Object.values(plugins).reduce((acc, current) => {
|
||||
const pluginsSectionLinks = get(current, 'menu.pluginsSectionLinks', []);
|
||||
|
||||
return [...acc, ...pluginsSectionLinks];
|
||||
}, []);
|
||||
|
||||
const sortedLinks = sortLinks(pluginsLinks).map(link => {
|
||||
return { ...omit(link, 'name') };
|
||||
});
|
||||
|
||||
return sortedLinks;
|
||||
};
|
||||
|
||||
export default toPluginLinks;
|
||||
@ -7,9 +7,9 @@ class Plugin {
|
||||
this.injectionZones = pluginConf.injectionZones || {};
|
||||
this.isReady = pluginConf.isReady !== undefined ? pluginConf.isReady : true;
|
||||
this.isRequired = pluginConf.isRequired;
|
||||
this.mainComponent = pluginConf.mainComponent || null;
|
||||
// this.mainComponent = pluginConf.mainComponent || null;
|
||||
// TODO
|
||||
this.menu = pluginConf.menu || null;
|
||||
// this.menu = pluginConf.menu || null;
|
||||
this.name = pluginConf.name;
|
||||
this.pluginId = pluginConf.id;
|
||||
this.pluginLogo = pluginConf.pluginLogo;
|
||||
|
||||
@ -4,10 +4,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import React, { Suspense, useEffect, lazy } from 'react';
|
||||
import React, { Suspense, useEffect, useMemo, lazy } from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
// Components from @strapi/helper-plugin
|
||||
import { CheckPagePermissions, useTracking, LoadingIndicatorPage } from '@strapi/helper-plugin';
|
||||
import {
|
||||
CheckPagePermissions,
|
||||
useTracking,
|
||||
LoadingIndicatorPage,
|
||||
useStrapiApp,
|
||||
} from '@strapi/helper-plugin';
|
||||
import adminPermissions from '../../permissions';
|
||||
import Header from '../../components/Header/index';
|
||||
import NavTopRightWrapper from '../../components/NavTopRightWrapper';
|
||||
@ -20,6 +25,7 @@ import { useReleaseNotification } from '../../hooks';
|
||||
import Logout from './Logout';
|
||||
import Wrapper from './Wrapper';
|
||||
import Content from './Content';
|
||||
import { createRoute } from '../../utils';
|
||||
|
||||
const HomePage = lazy(() => import(/* webpackChunkName: "Admin_homePage" */ '../HomePage'));
|
||||
const InstalledPluginsPage = lazy(() =>
|
||||
@ -29,9 +35,7 @@ const MarketplacePage = lazy(() =>
|
||||
import(/* webpackChunkName: "Admin_marketplace" */ '../MarketplacePage')
|
||||
);
|
||||
const NotFoundPage = lazy(() => import('../NotFoundPage'));
|
||||
const PluginDispatcher = lazy(() =>
|
||||
import(/* webpackChunkName: "Admin_pluginDispatcher" */ '../PluginDispatcher')
|
||||
);
|
||||
|
||||
const ProfilePage = lazy(() =>
|
||||
import(/* webpackChunkName: "Admin_profilePage" */ '../ProfilePage')
|
||||
);
|
||||
@ -69,6 +73,13 @@ const Admin = () => {
|
||||
useTrackUsage();
|
||||
// TODO
|
||||
const { isLoading, generalSectionLinks, pluginsSectionLinks } = useMenuSections();
|
||||
const { menu } = useStrapiApp();
|
||||
|
||||
const routes = useMemo(() => {
|
||||
return menu
|
||||
.filter(link => link.Component)
|
||||
.map(({ to, Component, exact }) => createRoute(Component, to, exact));
|
||||
}, [menu]);
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingIndicatorPage />;
|
||||
@ -94,7 +105,7 @@ const Admin = () => {
|
||||
<Route path="/plugins/content-manager" component={CM} />
|
||||
<Route path="/plugins/content-type-builder" component={CTB} />
|
||||
<Route path="/plugins/upload" component={Upload} />
|
||||
<Route path="/plugins/:pluginId" component={PluginDispatcher} />
|
||||
{routes}
|
||||
<Route path="/settings/:settingId" component={SettingsPage} />
|
||||
<Route path="/settings" component={SettingsPage} exact />
|
||||
<Route path="/marketplace">
|
||||
|
||||
@ -14,12 +14,12 @@ import {
|
||||
TrackingContext,
|
||||
} from '@strapi/helper-plugin';
|
||||
import PrivateRoute from '../../components/PrivateRoute';
|
||||
import { createRoute, makeUniqueRoutes } from '../../utils';
|
||||
import AuthPage from '../AuthPage';
|
||||
import NotFoundPage from '../NotFoundPage';
|
||||
import { getUID } from './utils';
|
||||
import { Content, Wrapper } from './components';
|
||||
import routes from './utils/routes';
|
||||
import { makeUniqueRoutes, createRoute } from '../SettingsPage/utils';
|
||||
|
||||
const AuthenticatedApp = lazy(() =>
|
||||
import(/* webpackChunkName: "Admin-authenticatedApp" */ '../../components/AuthenticatedApp')
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* PluginDispatcher
|
||||
*
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import { Redirect, useParams } from 'react-router-dom';
|
||||
import get from 'lodash/get';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { ErrorFallback, useStrapiApp } from '@strapi/helper-plugin';
|
||||
import PageTitle from '../../components/PageTitle';
|
||||
|
||||
const PluginDispatcher = () => {
|
||||
const { pluginId } = useParams();
|
||||
const { plugins } = useStrapiApp();
|
||||
|
||||
const pluginToRender = get(plugins, pluginId, null);
|
||||
|
||||
if (!pluginToRender) {
|
||||
return <Redirect to="/404" />;
|
||||
}
|
||||
|
||||
const { mainComponent, name } = pluginToRender;
|
||||
const PluginEntryComponent = mainComponent;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageTitle title={`Strapi - ${name}`} />
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
<PluginEntryComponent />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(PluginDispatcher);
|
||||
export { PluginDispatcher };
|
||||
@ -1,73 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Router, Route, Link } from 'react-router-dom';
|
||||
import { StrapiAppProvider } from '@strapi/helper-plugin';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { PluginDispatcher } from '../index';
|
||||
|
||||
const Email = () => <div>Email Plugin</div>;
|
||||
|
||||
const makeApp = (history, plugins) => (
|
||||
<StrapiAppProvider plugins={plugins}>
|
||||
<Router history={history}>
|
||||
<Link to="/plugins/email">Go to email</Link>
|
||||
<Route path="/plugins/:pluginId" component={PluginDispatcher} />
|
||||
<Route path="/404" component={() => <h1>404</h1>} />
|
||||
</Router>
|
||||
</StrapiAppProvider>
|
||||
);
|
||||
|
||||
describe('<PluginDispatcher />', () => {
|
||||
it('should not crash', () => {
|
||||
const history = createMemoryHistory();
|
||||
const App = makeApp(history, {});
|
||||
|
||||
const { container } = render(App);
|
||||
|
||||
expect(container.firstChild).toMatchInlineSnapshot(`
|
||||
<a
|
||||
href="/plugins/email"
|
||||
>
|
||||
Go to email
|
||||
</a>
|
||||
`);
|
||||
});
|
||||
|
||||
it('should redirect to the 404 page if the params does not match the pluginId', () => {
|
||||
const plugins = {
|
||||
email: {
|
||||
mainComponent: Email,
|
||||
name: 'email',
|
||||
},
|
||||
};
|
||||
const history = createMemoryHistory();
|
||||
const route = '/plugins/email-test';
|
||||
history.push(route);
|
||||
|
||||
const App = makeApp(history, plugins);
|
||||
|
||||
render(App);
|
||||
|
||||
expect(screen.getByText(/404/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should match the pluginId params with the correct plugin', () => {
|
||||
const plugins = {
|
||||
email: {
|
||||
mainComponent: Email,
|
||||
name: 'email',
|
||||
},
|
||||
};
|
||||
const history = createMemoryHistory();
|
||||
|
||||
const App = makeApp(history, plugins);
|
||||
|
||||
render(App);
|
||||
|
||||
const leftClick = { button: 0 };
|
||||
userEvent.click(screen.getByText(/Go to email/i), leftClick);
|
||||
|
||||
expect(screen.getByText(/Email Plugin/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@ -22,17 +22,11 @@ import HeaderSearch from '../../components/HeaderSearch';
|
||||
import PageTitle from '../../components/PageTitle';
|
||||
import SettingsSearchHeaderProvider from '../../components/SettingsHeaderSearchContextProvider';
|
||||
import { useSettingsMenu } from '../../hooks';
|
||||
|
||||
import { createRoute, makeUniqueRoutes } from '../../utils';
|
||||
import ApplicationInfosPage from '../ApplicationInfosPage';
|
||||
import { ApplicationDetailLink, MenuWrapper, StyledLeftMenu, Wrapper } from './components';
|
||||
|
||||
import {
|
||||
createRoute,
|
||||
createSectionsRoutes,
|
||||
makeUniqueRoutes,
|
||||
getSectionsToDisplay,
|
||||
routes,
|
||||
} from './utils';
|
||||
import { createSectionsRoutes, getSectionsToDisplay, routes } from './utils';
|
||||
|
||||
function SettingsPage() {
|
||||
const { settingId } = useParams();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import flatMap from 'lodash/flatMap';
|
||||
import createRoute from './createRoute';
|
||||
import { createRoute } from '../../../utils';
|
||||
|
||||
const createSectionsRoutes = settings => {
|
||||
const allLinks = flatMap(settings, section => section.links);
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
export { default as createSectionsRoutes } from './createSectionsRoutes';
|
||||
export { default as createRoute } from './createRoute';
|
||||
export { default as getSectionsToDisplay } from './getSectionsToDisplay';
|
||||
export { default as makeUniqueRoutes } from './makeUniqueRoutes';
|
||||
|
||||
export { default as routes } from './routes';
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
export { default as checkFormValidity } from './checkFormValidity';
|
||||
export { default as createRoute } from './createRoute';
|
||||
export { default as formatAPIErrors } from './formatAPIErrors';
|
||||
export { default as getAttributesToDisplay } from './getAttributesToDisplay';
|
||||
export { default as makeUniqueRoutes } from './makeUniqueRoutes';
|
||||
export { default as sortLinks } from './sortLinks';
|
||||
export { default as getExistingActions } from './getExistingActions';
|
||||
|
||||
|
||||
@ -18,6 +18,15 @@ const name = pluginPkg.strapi.name;
|
||||
export default {
|
||||
register(app) {
|
||||
app.addReducers(reducers);
|
||||
app.addCorePluginMenuLink({
|
||||
to: `/plugins/${pluginId}`,
|
||||
icon: 'book-open',
|
||||
intlLabel: {
|
||||
id: `${pluginId}.plugin.name`,
|
||||
defaultMessage: 'Content manager',
|
||||
},
|
||||
permissions: pluginPermissions.main,
|
||||
});
|
||||
|
||||
app.registerPlugin({
|
||||
description: pluginDescription,
|
||||
@ -31,19 +40,6 @@ export default {
|
||||
isRequired: pluginPkg.strapi.required || false,
|
||||
name,
|
||||
pluginLogo,
|
||||
menu: {
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
to: `/plugins/${pluginId}`,
|
||||
icon: 'book-open',
|
||||
intlLabel: {
|
||||
id: `${pluginId}.plugin.name`,
|
||||
defaultMessage: 'Content manager',
|
||||
},
|
||||
permissions: pluginPermissions.main,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
},
|
||||
boot() {},
|
||||
|
||||
@ -19,6 +19,16 @@ const name = pluginPkg.strapi.name;
|
||||
export default {
|
||||
register(app) {
|
||||
app.addReducers(reducers);
|
||||
app.addCorePluginMenuLink({
|
||||
to: `/plugins/${pluginId}`,
|
||||
icon,
|
||||
intlLabel: {
|
||||
id: `${pluginId}.plugin.name`,
|
||||
defaultMessage: 'Content-Types Builder',
|
||||
},
|
||||
permissions: pluginPermissions.main,
|
||||
});
|
||||
|
||||
app.registerPlugin({
|
||||
description: pluginDescription,
|
||||
icon,
|
||||
@ -27,19 +37,6 @@ export default {
|
||||
isReady: true,
|
||||
name,
|
||||
pluginLogo,
|
||||
menu: {
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
to: `/plugins/${pluginId}`,
|
||||
icon,
|
||||
intlLabel: {
|
||||
id: `${pluginId}.plugin.name`,
|
||||
defaultMessage: 'Content-Types Builder',
|
||||
},
|
||||
permissions: pluginPermissions.main,
|
||||
},
|
||||
],
|
||||
},
|
||||
// Internal APIs exposed by the CTB for the other plugins to use
|
||||
apis: {
|
||||
forms: formsAPI,
|
||||
|
||||
@ -10,6 +10,7 @@ import StrapiAppContext from '../../contexts/StrapiAppContext';
|
||||
const StrapiAppProvider = ({
|
||||
children,
|
||||
getPlugin,
|
||||
menu,
|
||||
plugins,
|
||||
runHookParallel,
|
||||
runHookWaterfall,
|
||||
@ -20,6 +21,7 @@ const StrapiAppProvider = ({
|
||||
<StrapiAppContext.Provider
|
||||
value={{
|
||||
getPlugin,
|
||||
menu,
|
||||
plugins,
|
||||
runHookParallel,
|
||||
runHookWaterfall,
|
||||
@ -35,6 +37,18 @@ const StrapiAppProvider = ({
|
||||
StrapiAppProvider.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
getPlugin: PropTypes.func.isRequired,
|
||||
menu: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
to: PropTypes.string.isRequired,
|
||||
icon: PropTypes.array,
|
||||
intlLabel: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
defaultMessage: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
permissions: PropTypes.array,
|
||||
Component: PropTypes.node,
|
||||
})
|
||||
).isRequired,
|
||||
plugins: PropTypes.object.isRequired,
|
||||
runHookParallel: PropTypes.func.isRequired,
|
||||
runHookWaterfall: PropTypes.func.isRequired,
|
||||
|
||||
@ -25,6 +25,17 @@ export default {
|
||||
register(app) {
|
||||
// TODO update doc and guides
|
||||
app.addComponents({ name: 'media-library', Component: InputModalStepper });
|
||||
|
||||
app.addCorePluginMenuLink({
|
||||
to: `/plugins/${pluginId}`,
|
||||
icon,
|
||||
intlLabel: {
|
||||
id: `${pluginId}.plugin.name`,
|
||||
defaultMessage: 'Media Library',
|
||||
},
|
||||
permissions: pluginPermissions.main,
|
||||
});
|
||||
|
||||
// TODO update guide
|
||||
app.addFields({ type: 'media', Component: InputMedia });
|
||||
|
||||
@ -40,20 +51,6 @@ export default {
|
||||
isRequired: pluginPkg.strapi.required || false,
|
||||
name,
|
||||
pluginLogo,
|
||||
|
||||
menu: {
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
to: `/plugins/${pluginId}`,
|
||||
icon,
|
||||
intlLabel: {
|
||||
id: `${pluginId}.plugin.name`,
|
||||
defaultMessage: 'Media Library',
|
||||
},
|
||||
permissions: pluginPermissions.main,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
},
|
||||
boot(app) {
|
||||
|
||||
@ -17,30 +17,25 @@ const name = pluginPkg.strapi.name;
|
||||
|
||||
export default {
|
||||
register(app) {
|
||||
app.addMenuLink({
|
||||
to: `/plugins/${pluginId}`,
|
||||
icon,
|
||||
intlLabel: {
|
||||
id: `${pluginId}.plugin.name`,
|
||||
defaultMessage: 'Documentation',
|
||||
},
|
||||
permissions: pluginPermissions.main,
|
||||
Component: App,
|
||||
});
|
||||
|
||||
app.registerPlugin({
|
||||
description: pluginDescription,
|
||||
icon,
|
||||
id: pluginId,
|
||||
isReady: true,
|
||||
isRequired: pluginPkg.strapi.required || false,
|
||||
// TODO
|
||||
mainComponent: App,
|
||||
name,
|
||||
pluginLogo,
|
||||
// TODO
|
||||
menu: {
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
to: `/plugins/${pluginId}`,
|
||||
icon,
|
||||
intlLabel: {
|
||||
id: `${pluginId}.plugin.name`,
|
||||
defaultMessage: 'Documentation',
|
||||
},
|
||||
permissions: pluginPermissions.main,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
},
|
||||
boot() {},
|
||||
|
||||
@ -34,7 +34,6 @@ export default {
|
||||
initializer: Initializer,
|
||||
isReady: false,
|
||||
isRequired: pluginPkg.strapi.required || false,
|
||||
mainComponent: null,
|
||||
name,
|
||||
pluginLogo,
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user