mirror of
https://github.com/strapi/strapi.git
synced 2025-10-27 16:10:08 +00:00
Update settings api and documentation
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
acb43e5aa9
commit
904eb3ab7a
@ -42,6 +42,7 @@ export default strapi => {
|
||||
title: 'Setting page 1',
|
||||
to: `${strapi.settingsBaseURL}/${pluginId}/setting1`,
|
||||
name: 'setting1',
|
||||
permissions: [{ action: 'plugins::my-plugin.action-name', subject: null }], // This key is required
|
||||
},
|
||||
{
|
||||
// Using i18n with a corresponding translation key
|
||||
@ -51,6 +52,7 @@ export default strapi => {
|
||||
},
|
||||
to: `${strapi.settingsBaseURL}/${pluginId}/setting2`,
|
||||
name: 'setting2',
|
||||
permissions: [{ action: 'plugins::my-plugin.action-name', subject: null }], // This key is required
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -147,6 +149,7 @@ export default strapi => {
|
||||
title: 'Setting page 1',
|
||||
to: `${strapi.settingsBaseURL}/${pluginId}/setting1`,
|
||||
name: 'setting1',
|
||||
permissions: [{ action: 'plugins::my-plugin.action-name', subject: null }], // This key is required
|
||||
},
|
||||
{
|
||||
title: {
|
||||
@ -155,6 +158,7 @@ export default strapi => {
|
||||
},
|
||||
to: `${strapi.settingsBaseURL}/${pluginId}/setting2`,
|
||||
name: 'setting2',
|
||||
permissions: [{ action: 'plugins::my-plugin.action-name', subject: null }], // This key is required
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -240,16 +244,19 @@ export default strapi => {
|
||||
preventComponentRendering: false,
|
||||
settings: {
|
||||
// Add a link into the global section of the settings view
|
||||
global: [
|
||||
{
|
||||
title: 'Setting link 1',
|
||||
to: `${strapi.settingsBaseURL}/setting-link-1`,
|
||||
name: 'settingLink1',
|
||||
Component: SettingLink,
|
||||
// Bool : https://reacttraining.com/react-router/web/api/Route/exact-bool
|
||||
exact: false,
|
||||
},
|
||||
],
|
||||
global: {
|
||||
links: [
|
||||
{
|
||||
title: 'Setting link 1',
|
||||
to: `${strapi.settingsBaseURL}/setting-link-1`,
|
||||
name: 'settingLink1',
|
||||
Component: SettingLink,
|
||||
// Bool : https://reacttraining.com/react-router/web/api/Route/exact-bool
|
||||
exact: false,
|
||||
permissions: [{ action: 'plugins::my-plugin.action-name', subject: null }], // This key is required
|
||||
},
|
||||
],
|
||||
},
|
||||
mainComponent: Settings,
|
||||
menuSection,
|
||||
},
|
||||
|
||||
@ -1,22 +1,6 @@
|
||||
import { get, omit, set, sortBy } from 'lodash';
|
||||
import { get, omit, set } from 'lodash';
|
||||
import { SETTINGS_BASE_URL } from '../../config';
|
||||
|
||||
const getPluginsSettingsPermissions = plugins =>
|
||||
Object.values(plugins).reduce((acc, current) => {
|
||||
const pluginSettings = get(current, 'settings.global', []);
|
||||
|
||||
pluginSettings.forEach(setting => {
|
||||
const permissions = get(setting, 'permissions', []);
|
||||
|
||||
permissions.forEach(permission => {
|
||||
acc.push(permission);
|
||||
});
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const sortLinks = links => sortBy(links, object => object.name);
|
||||
import { getPluginsSettingsPermissions, sortLinks } from './utils';
|
||||
|
||||
const init = (initialState, plugins = {}) => {
|
||||
// For each plugin retrieve the permissions associated to each injected link
|
||||
@ -50,4 +34,3 @@ const init = (initialState, plugins = {}) => {
|
||||
};
|
||||
|
||||
export default init;
|
||||
export { sortLinks };
|
||||
|
||||
@ -1,140 +1,264 @@
|
||||
import init, { sortLinks } from '../init';
|
||||
import { SETTINGS_BASE_URL } from '../../../config';
|
||||
import init from '../init';
|
||||
|
||||
describe('ADMIN | LeftMenu | init', () => {
|
||||
describe('init', () => {
|
||||
it('should return the initialState if the plugins are empty', () => {
|
||||
const initialState = {
|
||||
ok: true,
|
||||
generalSectionLinks: [],
|
||||
};
|
||||
it('should return the initialState if the plugins are empty', () => {
|
||||
const initialState = {
|
||||
ok: true,
|
||||
generalSectionLinks: [],
|
||||
};
|
||||
|
||||
expect(init(initialState)).toEqual({ ok: true, generalSectionLinks: [] });
|
||||
});
|
||||
|
||||
it('should create the pluginsSectionLinks correctly', () => {
|
||||
const plugins = {
|
||||
documentation: {
|
||||
menu: {
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
destination: '/plugins/documentation',
|
||||
icon: 'doc',
|
||||
label: {
|
||||
id: 'documentation.plugin.name',
|
||||
defaultMessage: 'Documentation',
|
||||
},
|
||||
name: 'documentation',
|
||||
permissions: [{ action: 'plugins::documentation.read', subject: null }],
|
||||
},
|
||||
{
|
||||
destination: '/plugins/documentation/test',
|
||||
icon: 'doc',
|
||||
label: {
|
||||
id: 'documentation.plugin.name.test',
|
||||
defaultMessage: 'Documentation Test',
|
||||
},
|
||||
name: 'documentation test',
|
||||
permissions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
test: {},
|
||||
'content-type-builder': {
|
||||
menu: {
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
destination: '/plugins/content-type-builder',
|
||||
icon: 'plug',
|
||||
label: {
|
||||
id: 'content-type-builder.plugin.name',
|
||||
defaultMessage: 'content-type-builder',
|
||||
},
|
||||
name: 'content-type-builder',
|
||||
permissions: [{ action: 'plugins::content-type-builder.read', subject: null }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
const initialState = {
|
||||
generalSectionLinks: [],
|
||||
pluginsSectionLinks: [],
|
||||
isLoading: true,
|
||||
};
|
||||
const expected = {
|
||||
generalSectionLinks: [],
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
destination: '/plugins/content-type-builder',
|
||||
icon: 'plug',
|
||||
label: {
|
||||
id: 'content-type-builder.plugin.name',
|
||||
defaultMessage: 'content-type-builder',
|
||||
},
|
||||
isDisplayed: false,
|
||||
permissions: [{ action: 'plugins::content-type-builder.read', subject: null }],
|
||||
},
|
||||
{
|
||||
destination: '/plugins/documentation',
|
||||
icon: 'doc',
|
||||
label: {
|
||||
id: 'documentation.plugin.name',
|
||||
defaultMessage: 'Documentation',
|
||||
},
|
||||
isDisplayed: false,
|
||||
permissions: [{ action: 'plugins::documentation.read', subject: null }],
|
||||
},
|
||||
{
|
||||
destination: '/plugins/documentation/test',
|
||||
icon: 'doc',
|
||||
label: {
|
||||
id: 'documentation.plugin.name.test',
|
||||
defaultMessage: 'Documentation Test',
|
||||
},
|
||||
isDisplayed: false,
|
||||
permissions: [],
|
||||
},
|
||||
],
|
||||
isLoading: true,
|
||||
};
|
||||
|
||||
expect(init(initialState, plugins)).toEqual(expected);
|
||||
});
|
||||
expect(init(initialState)).toEqual({ ok: true, generalSectionLinks: [] });
|
||||
});
|
||||
|
||||
describe('sortLinks', () => {
|
||||
it('should return an empty array', () => {
|
||||
expect(sortLinks([])).toEqual([]);
|
||||
});
|
||||
it('should create the pluginsSectionLinks correctly', () => {
|
||||
const plugins = {
|
||||
documentation: {
|
||||
menu: {
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
destination: '/plugins/documentation',
|
||||
icon: 'doc',
|
||||
label: {
|
||||
id: 'documentation.plugin.name',
|
||||
defaultMessage: 'Documentation',
|
||||
},
|
||||
name: 'documentation',
|
||||
permissions: [{ action: 'plugins::documentation.read', subject: null }],
|
||||
},
|
||||
{
|
||||
destination: '/plugins/documentation/test',
|
||||
icon: 'doc',
|
||||
label: {
|
||||
id: 'documentation.plugin.name.test',
|
||||
defaultMessage: 'Documentation Test',
|
||||
},
|
||||
name: 'documentation test',
|
||||
permissions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
test: {},
|
||||
'content-type-builder': {
|
||||
menu: {
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
destination: '/plugins/content-type-builder',
|
||||
icon: 'plug',
|
||||
label: {
|
||||
id: 'content-type-builder.plugin.name',
|
||||
defaultMessage: 'content-type-builder',
|
||||
},
|
||||
name: 'content-type-builder',
|
||||
permissions: [{ action: 'plugins::content-type-builder.read', subject: null }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
const initialState = {
|
||||
generalSectionLinks: [],
|
||||
pluginsSectionLinks: [],
|
||||
isLoading: true,
|
||||
};
|
||||
const expected = {
|
||||
generalSectionLinks: [],
|
||||
pluginsSectionLinks: [
|
||||
{
|
||||
destination: '/plugins/content-type-builder',
|
||||
icon: 'plug',
|
||||
label: {
|
||||
id: 'content-type-builder.plugin.name',
|
||||
defaultMessage: 'content-type-builder',
|
||||
},
|
||||
isDisplayed: false,
|
||||
permissions: [{ action: 'plugins::content-type-builder.read', subject: null }],
|
||||
},
|
||||
{
|
||||
destination: '/plugins/documentation',
|
||||
icon: 'doc',
|
||||
label: {
|
||||
id: 'documentation.plugin.name',
|
||||
defaultMessage: 'Documentation',
|
||||
},
|
||||
isDisplayed: false,
|
||||
permissions: [{ action: 'plugins::documentation.read', subject: null }],
|
||||
},
|
||||
{
|
||||
destination: '/plugins/documentation/test',
|
||||
icon: 'doc',
|
||||
label: {
|
||||
id: 'documentation.plugin.name.test',
|
||||
defaultMessage: 'Documentation Test',
|
||||
},
|
||||
isDisplayed: false,
|
||||
permissions: [],
|
||||
},
|
||||
],
|
||||
isLoading: true,
|
||||
};
|
||||
|
||||
it('should return a sorted array', () => {
|
||||
const data = [
|
||||
{
|
||||
name: 'un',
|
||||
},
|
||||
{ name: 'deux' },
|
||||
{ name: 'un-un' },
|
||||
{ name: 'un-deux' },
|
||||
{ name: 'un un' },
|
||||
];
|
||||
const expected = [
|
||||
{
|
||||
name: 'deux',
|
||||
},
|
||||
{
|
||||
name: 'un',
|
||||
},
|
||||
{ name: 'un un' },
|
||||
{
|
||||
name: 'un-deux',
|
||||
},
|
||||
{
|
||||
name: 'un-un',
|
||||
},
|
||||
];
|
||||
expect(init(initialState, plugins)).toEqual(expected);
|
||||
});
|
||||
|
||||
expect(sortLinks(data)).toEqual(expected);
|
||||
});
|
||||
it('should set the permissions in the settings link correctly for the plugins', () => {
|
||||
const initialState = {
|
||||
generalSectionLinks: [
|
||||
{
|
||||
icon: 'list',
|
||||
label: 'app.components.LeftMenuLinkContainer.listPlugins',
|
||||
destination: '/list-plugins',
|
||||
isDisplayed: false,
|
||||
permissions: [
|
||||
{ action: 'admin::marketplace.read', subject: null },
|
||||
{ action: 'admin::marketplace.plugins.uninstall', subject: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'shopping-basket',
|
||||
label: 'app.components.LeftMenuLinkContainer.installNewPlugin',
|
||||
destination: '/marketplace',
|
||||
isDisplayed: false,
|
||||
permissions: [
|
||||
{ action: 'admin::marketplace.read', subject: null },
|
||||
{ action: 'admin::marketplace.plugins.install', subject: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'cog',
|
||||
label: 'app.components.LeftMenuLinkContainer.settings',
|
||||
isDisplayed: false,
|
||||
destination: SETTINGS_BASE_URL,
|
||||
permissions: [
|
||||
// webhooks
|
||||
{ action: 'admin::webhook.create', subject: null },
|
||||
{ action: 'admin::webhook.read', subject: null },
|
||||
{ action: 'admin::webhook.update', subject: null },
|
||||
{ action: 'admin::webhook.delete', subject: null },
|
||||
// users
|
||||
{ action: 'admin::users.create', subject: null },
|
||||
{ action: 'admin::users.read', subject: null },
|
||||
{ action: 'admin::users.update', subject: null },
|
||||
{ action: 'admin::users.delete', subject: null },
|
||||
// roles
|
||||
{ action: 'admin::roles.create', subject: null },
|
||||
{ action: 'admin::roles.update', subject: null },
|
||||
{ action: 'admin::roles.read', subject: null },
|
||||
{ action: 'admin::roles.delete', subject: null },
|
||||
// Here are added the plugins settings permissions during the init phase
|
||||
],
|
||||
},
|
||||
],
|
||||
pluginsSectionLinks: [],
|
||||
isLoading: true,
|
||||
};
|
||||
const plugins = {
|
||||
test: {
|
||||
settings: {
|
||||
global: {
|
||||
links: [
|
||||
{
|
||||
title: {
|
||||
id: 'test.plugin.name',
|
||||
defaultMessage: 'Test',
|
||||
},
|
||||
name: 'test',
|
||||
to: '/settings/test',
|
||||
Component: () => null,
|
||||
permissions: [{ action: 'plugins::test.settings.read', subject: null }],
|
||||
},
|
||||
{
|
||||
title: {
|
||||
id: 'test.plugin.name1',
|
||||
defaultMessage: 'Test1',
|
||||
},
|
||||
name: 'test1',
|
||||
to: '/settings/test1',
|
||||
Component: () => null,
|
||||
permissions: [{ action: 'plugins::test1.settings.read', subject: null }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
other: {},
|
||||
upload: {
|
||||
settings: {
|
||||
global: {
|
||||
links: [
|
||||
{
|
||||
title: {
|
||||
id: 'upload.plugin.name',
|
||||
defaultMessage: 'Media Library',
|
||||
},
|
||||
name: 'media-library',
|
||||
to: 'settings/media-library',
|
||||
Component: () => null,
|
||||
permissions: [
|
||||
{ action: 'plugins::upload.settings.read', subject: null },
|
||||
{ action: 'plugins::upload.settings.read.test', subject: null },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
generalSectionLinks: [
|
||||
{
|
||||
icon: 'list',
|
||||
label: 'app.components.LeftMenuLinkContainer.listPlugins',
|
||||
destination: '/list-plugins',
|
||||
isDisplayed: false,
|
||||
permissions: [
|
||||
{ action: 'admin::marketplace.read', subject: null },
|
||||
{ action: 'admin::marketplace.plugins.uninstall', subject: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'shopping-basket',
|
||||
label: 'app.components.LeftMenuLinkContainer.installNewPlugin',
|
||||
destination: '/marketplace',
|
||||
isDisplayed: false,
|
||||
permissions: [
|
||||
{ action: 'admin::marketplace.read', subject: null },
|
||||
{ action: 'admin::marketplace.plugins.install', subject: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'cog',
|
||||
label: 'app.components.LeftMenuLinkContainer.settings',
|
||||
isDisplayed: false,
|
||||
destination: SETTINGS_BASE_URL,
|
||||
permissions: [
|
||||
// webhooks
|
||||
{ action: 'admin::webhook.create', subject: null },
|
||||
{ action: 'admin::webhook.read', subject: null },
|
||||
{ action: 'admin::webhook.update', subject: null },
|
||||
{ action: 'admin::webhook.delete', subject: null },
|
||||
// users
|
||||
{ action: 'admin::users.create', subject: null },
|
||||
{ action: 'admin::users.read', subject: null },
|
||||
{ action: 'admin::users.update', subject: null },
|
||||
{ action: 'admin::users.delete', subject: null },
|
||||
// roles
|
||||
{ action: 'admin::roles.create', subject: null },
|
||||
{ action: 'admin::roles.update', subject: null },
|
||||
{ action: 'admin::roles.read', subject: null },
|
||||
{ action: 'admin::roles.delete', subject: null },
|
||||
{ action: 'plugins::test.settings.read', subject: null },
|
||||
{ action: 'plugins::test1.settings.read', subject: null },
|
||||
{ action: 'plugins::upload.settings.read', subject: null },
|
||||
{ action: 'plugins::upload.settings.read.test', subject: null },
|
||||
],
|
||||
},
|
||||
],
|
||||
pluginsSectionLinks: [],
|
||||
isLoading: true,
|
||||
};
|
||||
|
||||
expect(init(initialState, plugins)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
// Retrieve the plugin settings object
|
||||
// The settings API works as follows for a plugin
|
||||
// Declare the links that will be injected into the settings menu
|
||||
//
|
||||
// Path: my-plugin/admin/src/index.js
|
||||
/*
|
||||
************************************************************
|
||||
* 1. Declare a section that will be added to the setting menu
|
||||
* const menuSection = {
|
||||
* // Unique id of the section
|
||||
* id: pluginId,
|
||||
* // Title of Menu section using i18n
|
||||
* title: {
|
||||
* id: `${pluginId}.foo`,
|
||||
* defaultMessage: 'Super cool setting',
|
||||
* },
|
||||
* // Array of links to be displayed
|
||||
* links: [
|
||||
* {
|
||||
* // Using string
|
||||
* title: 'Setting page 1',
|
||||
* to: `${strapi.settingsBaseURL}/${pluginId}/setting1`,
|
||||
* name: 'setting1',
|
||||
* permissions: [{ action: 'plugins::my-plugin.action-name', subject: null }],
|
||||
* },
|
||||
* {
|
||||
* // Using i18n with a corresponding translation key
|
||||
* title: {
|
||||
* id: `${pluginId}.bar`,
|
||||
* defaultMessage: 'Setting page 2',
|
||||
* },
|
||||
* to: `${strapi.settingsBaseURL}/${pluginId}/setting2`,
|
||||
* name: 'setting2',
|
||||
* permissions: [{ action: 'plugins::my-plugin.action-name2', subject: null }],
|
||||
* },
|
||||
* ],
|
||||
* };
|
||||
* ************************************************************
|
||||
* 2. Add a setting to the global section of the menu
|
||||
* const global = {
|
||||
* links: [
|
||||
* {
|
||||
* title: {
|
||||
* id: getTrad('plugin.name'),
|
||||
* defaultMessage: 'Media Library',
|
||||
* },
|
||||
* name: 'media-library',
|
||||
* to: `${strapi.settingsBaseURL}/media-library`,
|
||||
* Component: SettingsPage,
|
||||
* // TODO write documentation
|
||||
* permissions: [{ action: 'plugins::my-plugin.action-name', subject: null }],
|
||||
* },
|
||||
* ],
|
||||
* };
|
||||
***********************************************************
|
||||
* 3. Define the settings in the plugin object
|
||||
* const settings = { global, menuSection };
|
||||
*/
|
||||
|
||||
import { get } from 'lodash';
|
||||
|
||||
const getPluginsSettingsPermissions = plugins => {
|
||||
const globalSettingsLinksPermissions = Object.values(plugins).reduce((acc, current) => {
|
||||
const pluginSettings = get(current, 'settings', {});
|
||||
const getSettingsLinkPermissions = settings => {
|
||||
return Object.values(settings).reduce((acc, current) => {
|
||||
const links = get(current, 'links', []);
|
||||
|
||||
links.forEach(link => {
|
||||
const permissions = get(link, 'permissions', []);
|
||||
|
||||
permissions.forEach(permission => {
|
||||
acc.push(permission);
|
||||
});
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
|
||||
const pluginPermissions = getSettingsLinkPermissions(pluginSettings);
|
||||
|
||||
return [...acc, ...pluginPermissions];
|
||||
}, []);
|
||||
|
||||
return [...globalSettingsLinksPermissions];
|
||||
};
|
||||
|
||||
export default getPluginsSettingsPermissions;
|
||||
@ -0,0 +1,2 @@
|
||||
export { default as getPluginsSettingsPermissions } from './getPluginsSettingsPermissions';
|
||||
export { default as sortLinks } from './sortLinks';
|
||||
@ -0,0 +1,5 @@
|
||||
import { sortBy } from 'lodash';
|
||||
|
||||
const sortLinks = links => sortBy(links, object => object.name);
|
||||
|
||||
export default sortLinks;
|
||||
@ -0,0 +1,100 @@
|
||||
import getPluginsSettingsPermissions from '../getPluginsSettingsPermissions';
|
||||
|
||||
describe('ADMIN | LeftMenu | utils | getPluginsSettingsPermissions', () => {
|
||||
it('should return an empty array', () => {
|
||||
expect(getPluginsSettingsPermissions({})).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return an array containing all the permissions of the plugins settings links', () => {
|
||||
const menuSection = {
|
||||
// Unique id of the section
|
||||
id: 'test',
|
||||
// Title of Menu section using i18n
|
||||
title: {
|
||||
id: 'test.foo',
|
||||
defaultMessage: 'Super cool setting',
|
||||
},
|
||||
// Array of links to be displayed
|
||||
links: [
|
||||
{
|
||||
// Using string
|
||||
title: 'Setting page 1',
|
||||
to: 'settings/test/setting1',
|
||||
name: 'setting1',
|
||||
permissions: [{ action: 'plugins::test.action-name', subject: null }],
|
||||
},
|
||||
{
|
||||
// Using i18n with a corresponding translation key
|
||||
title: {
|
||||
id: 'test.bar',
|
||||
defaultMessage: 'Setting page 2',
|
||||
},
|
||||
to: 'settings/test/setting2',
|
||||
name: 'setting2',
|
||||
permissions: [{ action: 'plugins::my-plugin.action-name2', subject: null }],
|
||||
},
|
||||
],
|
||||
};
|
||||
const plugins = {
|
||||
test: {
|
||||
settings: {
|
||||
global: {
|
||||
links: [
|
||||
{
|
||||
title: {
|
||||
id: 'test.plugin.name',
|
||||
defaultMessage: 'Test',
|
||||
},
|
||||
name: 'test',
|
||||
to: '/settings/test',
|
||||
Component: () => null,
|
||||
permissions: [{ action: 'plugins::test.settings.read', subject: null }],
|
||||
},
|
||||
{
|
||||
title: {
|
||||
id: 'test.plugin.name1',
|
||||
defaultMessage: 'Test1',
|
||||
},
|
||||
name: 'test1',
|
||||
to: '/settings/test1',
|
||||
Component: () => null,
|
||||
permissions: [{ action: 'plugins::test1.settings.read', subject: null }],
|
||||
},
|
||||
],
|
||||
},
|
||||
menuSection,
|
||||
},
|
||||
},
|
||||
other: {},
|
||||
upload: {
|
||||
settings: {
|
||||
global: {
|
||||
links: [
|
||||
{
|
||||
title: {
|
||||
id: 'upload.plugin.name',
|
||||
defaultMessage: 'Media Library',
|
||||
},
|
||||
name: 'media-library',
|
||||
to: 'settings/media-library',
|
||||
Component: () => null,
|
||||
permissions: [
|
||||
{ action: 'plugins::upload.settings.read', subject: null },
|
||||
{ action: 'plugins::upload.settings.read.test', subject: null },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const expected = [
|
||||
{ action: 'plugins::test.action-name', subject: null },
|
||||
{ action: 'plugins::my-plugin.action-name2', subject: null },
|
||||
{ action: 'plugins::upload.settings.read', subject: null },
|
||||
{ action: 'plugins::upload.settings.read.test', subject: null },
|
||||
];
|
||||
|
||||
expect(getPluginsSettingsPermissions(plugins)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,36 @@
|
||||
import sortLinks from '../sortLinks';
|
||||
|
||||
describe('ADMIN | LeftMenu | utils | sortLinks', () => {
|
||||
it('should return an empty array', () => {
|
||||
expect(sortLinks([])).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return a sorted array', () => {
|
||||
const data = [
|
||||
{
|
||||
name: 'un',
|
||||
},
|
||||
{ name: 'deux' },
|
||||
{ name: 'un-un' },
|
||||
{ name: 'un-deux' },
|
||||
{ name: 'un un' },
|
||||
];
|
||||
const expected = [
|
||||
{
|
||||
name: 'deux',
|
||||
},
|
||||
{
|
||||
name: 'un',
|
||||
},
|
||||
{ name: 'un un' },
|
||||
{
|
||||
name: 'un-deux',
|
||||
},
|
||||
{
|
||||
name: 'un-un',
|
||||
},
|
||||
];
|
||||
|
||||
expect(sortLinks(data)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@ -2,7 +2,7 @@ import { get } from 'lodash';
|
||||
|
||||
const retrieveGlobalLinks = pluginsObj => {
|
||||
return Object.values(pluginsObj).reduce((acc, current) => {
|
||||
const links = get(current, ['settings', 'global'], null);
|
||||
const links = get(current, ['settings', 'global', 'links'], null);
|
||||
|
||||
if (links) {
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
|
||||
@ -10,18 +10,22 @@ describe('ADMIN | containers | SettingsPage | utils', () => {
|
||||
const plugins = {
|
||||
test: {
|
||||
settings: {
|
||||
global: [],
|
||||
global: {
|
||||
links: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
noSettings: {},
|
||||
foo: {
|
||||
settings: {
|
||||
global: ['test'],
|
||||
global: {
|
||||
links: ['test'],
|
||||
},
|
||||
},
|
||||
},
|
||||
bar: {
|
||||
settings: {
|
||||
global: ['test2'],
|
||||
global: { links: ['test2'] },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -21,6 +21,7 @@ export default strapi => {
|
||||
const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
|
||||
const icon = pluginPkg.strapi.icon;
|
||||
const name = pluginPkg.strapi.name;
|
||||
|
||||
const plugin = {
|
||||
blockerComponent: null,
|
||||
blockerComponentProps: {},
|
||||
@ -41,19 +42,20 @@ export default strapi => {
|
||||
pluginLogo,
|
||||
preventComponentRendering: false,
|
||||
settings: {
|
||||
global: [
|
||||
{
|
||||
title: {
|
||||
id: getTrad('plugin.name'),
|
||||
defaultMessage: 'Media Library',
|
||||
global: {
|
||||
links: [
|
||||
{
|
||||
title: {
|
||||
id: getTrad('plugin.name'),
|
||||
defaultMessage: 'Media Library',
|
||||
},
|
||||
name: 'media-library',
|
||||
to: `${strapi.settingsBaseURL}/media-library`,
|
||||
Component: SettingsPage,
|
||||
permissions: [{ action: 'plugins::upload.settings.read', subject: null }],
|
||||
},
|
||||
name: 'media-library',
|
||||
to: `${strapi.settingsBaseURL}/media-library`,
|
||||
Component: SettingsPage,
|
||||
// TODO write documentation
|
||||
permissions: [{ action: 'plugins::upload.settings.read', subject: null }],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
trads,
|
||||
menu: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user