Merge pull request #16871 from strapi/enhancement/use-enterprise-hook

POC: Add useEnterprise() hook; refactor settings router
This commit is contained in:
Gustav Hansen 2023-06-19 11:04:25 +02:00 committed by GitHub
commit 86eaf9f728
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 422 additions and 432 deletions

View File

@ -0,0 +1,56 @@
---
title: useEnterprise
description: API reference for the useEnterprise hook
tags:
- admin
- hooks
- users
---
A hook that returns either community or enterprise-edition data-structures based on the global `window.strapi.isEE` flag.
## Usage
```
import { CE_DATA } from './data';
function Component() {
const data = useEnterprise(CE_DATA, async () => (await import('./ee/data')).default);
}
```
It accepts an optional third argument to pass in options customizing the hook behavior:
### `combine()`
THe `combine` callback can be used as a custom "merge" function for the ce and ee arguments:
```
const data = useEnterprise({ a: 1 }, () => { b: 1 }, { combine(ce, ee) { return { ...ce, ...ee } } });
console.log(data); // { a: 1, b: 1 }
```
### `defaultValue`
By default the hook returns `null` if `window.strapi.isEE` is true and the enterprise data structure is not yet loaded. Customizing
this value can help implementing various loading scenarios:
```
// display a loading state while an EE component is loading
const Component = useEnterprise(() => <p>CE</p>, () => <p>EE</p>, {
defaultValue: () => <div>loading ...</div>
})
// display nothing while an EE component is loading, but don't block the overall rendering
const Component = useEnterprise(() => <p>CE</p>, () => <p>EE</p>, {
defaultValue: () => null
})
// display nothing while an EE component is loading
const Component = useEnterprise(() => <p>CE</p>, () => <p>EE</p>)
if (!Component) {
return;
}
```

View File

@ -0,0 +1 @@
export * from './useEnterprise';

View File

@ -0,0 +1,66 @@
import { renderHook, waitFor } from '@testing-library/react';
import { useEnterprise } from '../useEnterprise';
const CE_DATA_FIXTURE = ['CE'];
const EE_DATA_FIXTURE = ['EE'];
function setup(...args) {
return renderHook(() => useEnterprise(...args));
}
describe('useEnterprise (CE)', () => {
test('Returns CE data', async () => {
const { result } = setup(CE_DATA_FIXTURE, async () => EE_DATA_FIXTURE);
expect(result.current).toBe(CE_DATA_FIXTURE);
});
});
describe('useEnterprise (EE)', () => {
beforeAll(() => {
window.strapi.isEE = true;
});
afterAll(() => {
window.strapi.isEE = false;
});
test('Returns default data on first render and EE data on second', async () => {
const { result } = setup(CE_DATA_FIXTURE, async () => EE_DATA_FIXTURE);
expect(result.current).toBe(null);
await waitFor(() => expect(result.current).toBe(EE_DATA_FIXTURE));
});
test('Combines CE and EE data', async () => {
const { result } = setup(CE_DATA_FIXTURE, async () => EE_DATA_FIXTURE, {
combine(ceData, eeData) {
return [...ceData, ...eeData];
},
});
expect(result.current).toBe(null);
await waitFor(() =>
expect(result.current).toStrictEqual([...CE_DATA_FIXTURE, ...EE_DATA_FIXTURE])
);
});
test('Returns EE data without custom combine', async () => {
const { result } = setup(CE_DATA_FIXTURE, async () => EE_DATA_FIXTURE);
await waitFor(() => expect(result.current).toStrictEqual(EE_DATA_FIXTURE));
});
test('Returns a custom defaultValue on first render followed by the EE data', async () => {
const { result } = setup(CE_DATA_FIXTURE, async () => EE_DATA_FIXTURE, {
defaultValue: false,
});
expect(result.current).toBe(false);
await waitFor(() => expect(result.current).toStrictEqual(EE_DATA_FIXTURE));
});
});

View File

@ -0,0 +1,36 @@
import * as React from 'react';
import { useCallbackRef } from '@strapi/helper-plugin';
function isEnterprise() {
return window.strapi.isEE;
}
export function useEnterprise(
ceData,
eeCallback,
{ defaultValue = null, combine = (ceData, eeData) => eeData } = {}
) {
const eeCallbackRef = useCallbackRef(eeCallback);
const combineCallbackRef = useCallbackRef(combine);
// We have to use a nested object here, because functions (e.g. Components)
// can not be stored as value directly
const [{ data }, setData] = React.useState({
data: isEnterprise() ? defaultValue : ceData,
});
React.useEffect(() => {
async function importEE() {
const eeData = await eeCallbackRef();
setData({ data: combineCallbackRef(ceData, eeData) });
}
if (isEnterprise()) {
importEE();
}
}, [ceData, eeCallbackRef, combineCallbackRef]);
return data;
}

View File

@ -0,0 +1,46 @@
import adminPermissions from '../../permissions';
export const LINKS_CE = {
global: [
{
intlLabel: { id: 'Settings.application.title', defaultMessage: 'Overview' },
to: '/settings/application-infos',
id: '000-application-infos',
permissions: [],
},
{
intlLabel: { id: 'Settings.webhooks.title', defaultMessage: 'Webhooks' },
to: '/settings/webhooks',
id: 'webhooks',
permissions: adminPermissions.settings.webhooks.main,
},
{
intlLabel: { id: 'Settings.apiTokens.title', defaultMessage: 'API Tokens' },
to: '/settings/api-tokens?sort=name:ASC',
id: 'api-tokens',
permissions: adminPermissions.settings['api-tokens'].main,
},
{
intlLabel: { id: 'Settings.transferTokens.title', defaultMessage: 'Transfer Tokens' },
to: '/settings/transfer-tokens?sort=name:ASC',
id: 'transfer-tokens',
permissions: adminPermissions.settings['transfer-tokens'].main,
},
],
admin: [
{
intlLabel: { id: 'global.roles', defaultMessage: 'Roles' },
to: '/settings/roles',
id: 'roles',
permissions: adminPermissions.settings.roles.main,
},
{
intlLabel: { id: 'global.users' },
// Init the search params directly
to: '/settings/users?pageSize=10&page=1&sort=firstname',
id: 'users',
permissions: adminPermissions.settings.users.main,
},
],
};

View File

@ -1,56 +1,95 @@
import { useEffect, useReducer } from 'react';
import { useState, useEffect } from 'react';
import { hasPermissions, useAppInfo, useRBACProvider, useStrapiApp } from '@strapi/helper-plugin';
import { hasPermissions, useRBACProvider, useStrapiApp, useAppInfo } from '@strapi/helper-plugin';
import init from './init';
import reducer, { initialState } from './reducer';
import { useEnterprise } from '../useEnterprise';
const useSettingsMenu = (noCheck = false) => {
import { LINKS_CE } from './constants';
import formatLinks from './utils/formatLinks';
import sortLinks from './utils/sortLinks';
const useSettingsMenu = () => {
const [{ isLoading, menu }, setData] = useState({
isLoading: true,
menu: [],
});
const { allPermissions: permissions } = useRBACProvider();
const { shouldUpdateStrapi } = useAppInfo();
const { settings } = useStrapiApp();
const [{ isLoading, menu }, dispatch] = useReducer(reducer, initialState, () =>
init(initialState, { settings, shouldUpdateStrapi })
const { global: globalLinks, admin: adminLinks } = useEnterprise(
LINKS_CE,
async () => (await import('../../../../ee/admin/hooks/useSettingsMenu/constants')).LINKS_EE,
{
combine(ceLinks, eeLinks) {
return {
admin: [...eeLinks.admin, ...ceLinks.admin],
global: [...ceLinks.global, ...eeLinks.global],
};
},
defaultValue: {
admin: [],
global: [],
},
}
);
useEffect(() => {
const getData = async () => {
const checkPermissions = async (permissionsToCheck, path) => {
const hasPermission = await hasPermissions(permissions, permissionsToCheck);
const buildMenuPermissions = (sections) =>
Promise.all(
sections.reduce((acc, section, sectionIndex) => {
const buildMenuPermissions = (links) =>
links.map(async (link, linkIndex) => ({
hasPermission: await hasPermissions(permissions, link.permissions),
sectionIndex,
linkIndex,
}));
return { hasPermission, path };
};
return [...acc, ...buildMenuPermissions(section.links)];
}, [])
);
const generateArrayOfPromises = (array) => {
return array.reduce((acc, current, sectionIndex) => {
const generateArrayOfPromises = (array) =>
array.map((link, index) =>
checkPermissions(array[index].permissions, `${sectionIndex}.links.${index}`)
const menuPermissions = await buildMenuPermissions(sections);
setData((prev) => ({
...prev,
isLoading: false,
menu: sections.map((section, sectionIndex) => ({
...section,
links: section.links.map((link, linkIndex) => {
const permission = menuPermissions.find(
(permission) =>
permission.sectionIndex === sectionIndex && permission.linkIndex === linkIndex
);
return [...acc, ...generateArrayOfPromises(current.links)];
}, []);
};
const generalSectionLinksArrayOfPromises = generateArrayOfPromises(menu);
const data = await Promise.all(generalSectionLinksArrayOfPromises);
dispatch({
type: 'CHECK_PERMISSIONS_SUCCEEDED',
data,
});
return {
...link,
isDisplayed: Boolean(permission.hasPermission),
};
}),
})),
}));
};
// This hook is also used by the main LeftMenu component in order to know which sections it needs to display/hide
// Therefore, we don't need to make the checking all the times when the hook is used.
if (!noCheck) {
getData();
}
const { global, ...otherSections } = settings;
const sections = formatLinks([
{
...settings.global,
links: sortLinks([...settings.global.links, ...globalLinks]).map((link) => ({
...link,
hasNotification: link.id === '000-application-infos' && shouldUpdateStrapi,
})),
},
{
id: 'permissions',
intlLabel: { id: 'Settings.permissions', defaultMessage: 'Administration Panel' },
links: adminLinks,
},
...Object.values(otherSections),
]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [permissions, noCheck]);
getData();
}, [adminLinks, globalLinks, permissions, settings, shouldUpdateStrapi]);
return { isLoading, menu };
};

View File

@ -1,35 +0,0 @@
import omit from 'lodash/omit';
import adminLinks from './utils/adminLinks';
import formatLinks from './utils/formatLinks';
import globalLinks from './utils/globalLinks';
import sortLinks from './utils/sortLinks';
const init = (initialState, { settings, shouldUpdateStrapi }) => {
// Retrieve the links that will be injected into the global section
const pluginsGlobalLinks = settings.global.links;
// Sort the links by name
const sortedGlobalLinks = sortLinks([...pluginsGlobalLinks, ...globalLinks]).map((link) => ({
...link,
hasNotification: link.id === '000-application-infos' && shouldUpdateStrapi,
}));
const otherSections = Object.values(omit(settings, 'global'));
const menu = [
{
...settings.global,
links: sortedGlobalLinks,
},
{
id: 'permissions',
intlLabel: { id: 'Settings.permissions', defaultMessage: 'Administration Panel' },
links: adminLinks,
},
...otherSections,
];
return { ...initialState, menu: formatLinks(menu) };
};
export default init;

View File

@ -1,41 +0,0 @@
import produce from 'immer';
import set from 'lodash/set';
const initialState = {
menu: [],
isLoading: true,
};
const reducer = (state, action) =>
// eslint-disable-next-line consistent-return
produce(state, (draftState) => {
switch (action.type) {
case 'CHECK_PERMISSIONS_SUCCEEDED': {
action.data.forEach((checkedPermissions) => {
if (checkedPermissions.hasPermission) {
set(
draftState,
['menu', ...checkedPermissions.path.split('.'), 'isDisplayed'],
checkedPermissions.hasPermission
);
}
});
// Remove the not needed links in each section
draftState.menu.forEach((section, sectionIndex) => {
draftState.menu[sectionIndex].links = section.links.filter(
(link) => link.isDisplayed === true
);
});
draftState.isLoading = false;
break;
}
default:
return draftState;
}
});
export default reducer;
export { initialState };

View File

@ -1,116 +0,0 @@
import reducer from '../reducer';
describe('ADMIN | hooks | useSettingsMenu | reducer', () => {
describe('DEFAULT_ACTION', () => {
it('should return the state', () => {
const initialState = {
ok: true,
};
const expected = {
ok: true,
};
expect(reducer(initialState, {})).toEqual(expected);
});
});
describe('CHECK_PERMISSIONS_SUCCEEDED', () => {
it('should set the permissions correctly', () => {
const initialState = {
isLoading: true,
menu: [
{
id: 'global',
links: [
{
to: 'global.test',
isDisplayed: false,
},
{
to: 'global.test2',
isDisplayed: false,
},
],
},
{
id: 'test',
links: [
{
to: 'test.test',
isDisplayed: false,
},
{
to: 'test.test2',
isDisplayed: false,
},
{
to: 'test.test3',
isDisplayed: false,
},
],
},
{
id: 'test1',
links: [
{
to: 'test1.test',
isDisplayed: false,
},
{
to: 'test1.test2',
isDisplayed: false,
},
{
to: 'test1.test3',
isDisplayed: false,
},
],
},
],
};
const action = {
type: 'CHECK_PERMISSIONS_SUCCEEDED',
data: [
{ hasPermission: true, path: '1.links.0' },
{ hasPermission: true, path: '1.links.1' },
{ hasPermission: true, path: '0.links.1' },
{ hasPermission: undefined, path: '2.links.0' },
],
};
const expected = {
isLoading: false,
menu: [
{
id: 'global',
links: [
{
to: 'global.test2',
isDisplayed: true,
},
],
},
{
id: 'test',
links: [
{
to: 'test.test',
isDisplayed: true,
},
{
to: 'test.test2',
isDisplayed: true,
},
],
},
{
id: 'test1',
links: [],
},
],
};
expect(reducer(initialState, action)).toEqual(expected);
});
});
});

View File

@ -1,5 +0,0 @@
import customAdminLinks from 'ee_else_ce/hooks/useSettingsMenu/utils/customAdminLinks';
import defaultAdminLinks from './defaultAdminLinks';
export default [...customAdminLinks, ...defaultAdminLinks];

View File

@ -1,21 +0,0 @@
import adminPermissions from '../../../permissions';
const defaultAdminLinks = [
{
intlLabel: { id: 'global.roles', defaultMessage: 'Roles' },
to: '/settings/roles',
id: 'roles',
isDisplayed: false,
permissions: adminPermissions.settings.roles.main,
},
{
intlLabel: { id: 'global.users' },
// Init the search params directly
to: '/settings/users?pageSize=10&page=1&sort=firstname',
id: 'users',
isDisplayed: false,
permissions: adminPermissions.settings.users.main,
},
];
export default defaultAdminLinks;

View File

@ -1,34 +0,0 @@
import adminPermissions from '../../../permissions';
const defaultGlobalLinks = [
{
intlLabel: { id: 'Settings.application.title', defaultMessage: 'Overview' },
to: '/settings/application-infos',
id: '000-application-infos',
isDisplayed: false,
permissions: [],
},
{
intlLabel: { id: 'Settings.webhooks.title', defaultMessage: 'Webhooks' },
to: '/settings/webhooks',
id: 'webhooks',
isDisplayed: false,
permissions: adminPermissions.settings.webhooks.main,
},
{
intlLabel: { id: 'Settings.apiTokens.title', defaultMessage: 'API Tokens' },
to: '/settings/api-tokens?sort=name:ASC',
id: 'api-tokens',
isDisplayed: false,
permissions: adminPermissions.settings['api-tokens'].main,
},
{
intlLabel: { id: 'Settings.transferTokens.title', defaultMessage: 'Transfer Tokens' },
to: '/settings/transfer-tokens?sort=name:ASC',
id: 'transfer-tokens',
isDisplayed: false,
permissions: adminPermissions.settings['transfer-tokens'].main,
},
];
export default defaultGlobalLinks;

View File

@ -1,5 +0,0 @@
import customGlobalLinks from 'ee_else_ce/hooks/useSettingsMenu/utils/customGlobalLinks';
import defaultGlobalLinks from './defaultGlobalLinks';
export default [...defaultGlobalLinks, ...customGlobalLinks];

View File

@ -1 +1,3 @@
export const SET_APP_RUNTIME_STATUS = 'StrapiAdmin/APP/SET_APP_RUNTIME_STATUS';
export const ROUTES_CE = [];

View File

@ -21,19 +21,27 @@ import { Route, Switch } from 'react-router-dom';
import PrivateRoute from '../../components/PrivateRoute';
import { useConfigurations } from '../../hooks';
import { useEnterprise } from '../../hooks/useEnterprise';
import { createRoute, makeUniqueRoutes } from '../../utils';
import AuthPage from '../AuthPage';
import NotFoundPage from '../NotFoundPage';
import UseCasePage from '../UseCasePage';
import { ROUTES_CE } from './constants';
import { getUID } from './utils';
import routes from './utils/routes';
const AuthenticatedApp = lazy(() =>
import(/* webpackChunkName: "Admin-authenticatedApp" */ '../../components/AuthenticatedApp')
);
function App() {
const routes = useEnterprise(
ROUTES_CE,
async () => (await import('../../../../ee/admin/pages/App/constants')).ROUTES_EE,
{
defaultValue: [],
}
);
const toggleNotification = useNotification();
const { updateProjectSettings } = useConfigurations();
const { formatMessage } = useIntl();
@ -48,7 +56,7 @@ function App() {
return makeUniqueRoutes(
routes.map(({ to, Component, exact }) => createRoute(Component, to, exact))
);
}, []);
}, [routes]);
const [telemetryProperties, setTelemetryProperties] = useState(null);

View File

@ -1,3 +0,0 @@
const customRoutes = [];
export default customRoutes;

View File

@ -1,3 +0,0 @@
const defaultRoutes = [];
export default defaultRoutes;

View File

@ -1,3 +1,3 @@
/* eslint-disable import/prefer-default-export */
export { default as routes } from './routes';
export { default as getUID } from './unique-identifier';

View File

@ -1,5 +0,0 @@
import customRoutes from 'ee_else_ce/pages/App/utils/customRoutes';
import defaultRoutes from './defaultRoutes';
export default [...customRoutes, ...defaultRoutes];

View File

@ -1,8 +1,8 @@
const defaultRoutes = [
export const ROUTES_CE = [
{
async Component() {
const component = await import(
/* webpackChunkName: "admin-roles-list" */ '../pages/Roles/ProtectedListPage'
/* webpackChunkName: "admin-roles-list" */ './pages/Roles/ProtectedListPage'
);
return component;
@ -13,7 +13,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "admin-edit-roles-page" */ '../pages/Roles/CreatePage'
/* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/CreatePage'
);
return component;
@ -24,7 +24,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "admin-edit-roles-page" */ '../pages/Roles/CreatePage'
/* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/CreatePage'
);
return component;
@ -35,7 +35,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "admin-edit-roles-page" */ '../pages/Roles/ProtectedEditPage'
/* webpackChunkName: "admin-edit-roles-page" */ './pages/Roles/ProtectedEditPage'
);
return component;
@ -46,7 +46,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "admin-users" */ '../pages/Users/ProtectedListPage'
/* webpackChunkName: "admin-users" */ './pages/Users/ProtectedListPage'
);
return component;
@ -57,7 +57,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "admin-edit-users" */ '../pages/Users/ProtectedEditPage'
/* webpackChunkName: "admin-edit-users" */ './pages/Users/ProtectedEditPage'
);
return component;
@ -68,7 +68,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "webhook-edit-page" */ '../pages/Webhooks/ProtectedCreateView'
/* webpackChunkName: "webhook-edit-page" */ './pages/Webhooks/ProtectedCreateView'
);
return component;
@ -79,7 +79,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "webhook-edit-page" */ '../pages/Webhooks/ProtectedEditView'
/* webpackChunkName: "webhook-edit-page" */ './pages/Webhooks/ProtectedEditView'
);
return component;
@ -90,7 +90,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "webhook-list-page" */ '../pages/Webhooks/ProtectedListView'
/* webpackChunkName: "webhook-list-page" */ './pages/Webhooks/ProtectedListView'
);
return component;
@ -101,7 +101,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "api-tokens-list-page" */ '../pages/ApiTokens/ProtectedListView'
/* webpackChunkName: "api-tokens-list-page" */ './pages/ApiTokens/ProtectedListView'
);
return component;
@ -112,7 +112,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "api-tokens-create-page" */ '../pages/ApiTokens/ProtectedCreateView'
/* webpackChunkName: "api-tokens-create-page" */ './pages/ApiTokens/ProtectedCreateView'
);
return component;
@ -123,7 +123,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "api-tokens-edit-page" */ '../pages/ApiTokens/ProtectedEditView'
/* webpackChunkName: "api-tokens-edit-page" */ './pages/ApiTokens/ProtectedEditView'
);
return component;
@ -134,7 +134,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "transfer-tokens-create-page" */ '../pages/TransferTokens/ProtectedCreateView'
/* webpackChunkName: "transfer-tokens-create-page" */ './pages/TransferTokens/ProtectedCreateView'
);
return component;
@ -145,7 +145,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "transfer-tokens-list-page" */ '../pages/TransferTokens/ProtectedListView'
/* webpackChunkName: "transfer-tokens-list-page" */ './pages/TransferTokens/ProtectedListView'
);
return component;
@ -156,7 +156,7 @@ const defaultRoutes = [
{
async Component() {
const component = await import(
/* webpackChunkName: "transfer-tokens-edit-page" */ '../pages/TransferTokens/ProtectedEditView'
/* webpackChunkName: "transfer-tokens-edit-page" */ './pages/TransferTokens/ProtectedEditView'
);
return component;
@ -165,5 +165,3 @@ const defaultRoutes = [
exact: true,
},
];
export default defaultRoutes;

View File

@ -18,24 +18,36 @@ import { useIntl } from 'react-intl';
import { Redirect, Route, Switch, useParams } from 'react-router-dom';
import { useSettingsMenu } from '../../hooks';
import { useEnterprise } from '../../hooks/useEnterprise';
import { createRoute, makeUniqueRoutes } from '../../utils';
import SettingsNav from './components/SettingsNav';
import { ROUTES_CE } from './constants';
import ApplicationInfosPage from './pages/ApplicationInfosPage';
import { createSectionsRoutes, routes } from './utils';
import { createSectionsRoutes } from './utils';
function SettingsPage() {
const { settingId } = useParams();
const { settings } = useStrapiApp();
const { formatMessage } = useIntl();
const { isLoading, menu } = useSettingsMenu();
const routes = useEnterprise(
ROUTES_CE,
async () => (await import('../../../../ee/admin/pages/SettingsPage/constants')).ROUTES_EE,
{
combine(ceRoutes, eeRoutes) {
return [...ceRoutes, ...eeRoutes];
},
defaultValue: [],
}
);
// Creates the admin routes
const adminRoutes = useMemo(() => {
return makeUniqueRoutes(
routes.map(({ to, Component, exact }) => createRoute(Component, to, exact))
);
}, []);
}, [routes]);
const pluginsRoutes = createSectionsRoutes(settings);

View File

@ -1,3 +0,0 @@
const customRoutes = [];
export default customRoutes;

View File

@ -1,3 +1,2 @@
export { default as createSectionsRoutes } from './createSectionsRoutes';
export { default as getSectionsToDisplay } from './getSectionsToDisplay';
export { default as routes } from './routes';

View File

@ -1,6 +0,0 @@
// This file makes it easier to make the difference between the ee and ce version
import customRoutes from 'ee_else_ce/pages/SettingsPage/utils/customRoutes';
import defaultRoutes from './defaultRoutes';
export default [...customRoutes, ...defaultRoutes];

View File

@ -0,0 +1,43 @@
import adminPermissions from '../../../../admin/src/permissions';
export const LINKS_EE = {
global: [
...(window.strapi.features.isEnabled(window.strapi.features.SSO)
? [
{
intlLabel: { id: 'Settings.sso.title', defaultMessage: 'Single Sign-On' },
to: '/settings/single-sign-on',
id: 'sso',
permissions: adminPermissions.settings.sso.main,
},
]
: []),
...(window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS)
? [
{
intlLabel: {
id: 'Settings.review-workflows.page.title',
defaultMessage: 'Review Workflows',
},
to: '/settings/review-workflows',
id: 'review-workflows',
permissions: adminPermissions.settings['review-workflows'].main,
},
]
: []),
],
admin: [
...(window.strapi.features.isEnabled(window.strapi.features.AUDIT_LOGS)
? [
{
intlLabel: { id: 'global.auditLogs', defaultMessage: 'Audit Logs' },
to: '/settings/audit-logs?pageSize=50&page=1&sort=date:DESC',
id: 'auditLogs',
permissions: adminPermissions.settings.auditLogs.main,
},
]
: []),
],
};

View File

@ -1,17 +0,0 @@
import adminPermissions from '../../../../../admin/src/permissions';
const items = [];
if (window.strapi.features.isEnabled(window.strapi.features.AUDIT_LOGS)) {
items.push({
intlLabel: { id: 'global.auditLogs', defaultMessage: 'Audit Logs' },
to: '/settings/audit-logs?pageSize=50&page=1&sort=date:DESC',
id: 'auditLogs',
isDisplayed: false,
permissions: adminPermissions.settings.auditLogs.main,
});
}
const customAdminLinks = items;
export default customAdminLinks;

View File

@ -1,25 +0,0 @@
import adminPermissions from '../../../../../admin/src/permissions';
const items = [];
if (window.strapi.features.isEnabled(window.strapi.features.SSO)) {
items.push({
intlLabel: { id: 'Settings.sso.title', defaultMessage: 'Single Sign-On' },
to: '/settings/single-sign-on',
id: 'sso',
isDisplayed: false,
permissions: adminPermissions.settings.sso.main,
});
}
if (window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS)) {
items.push({
intlLabel: { id: 'Settings.review-workflows.page.title', defaultMessage: 'Review Workflows' },
to: '/settings/review-workflows',
id: 'review-workflows',
isDisplayed: false,
permissions: adminPermissions.settings['review-workflows'].main,
});
}
export default items;

View File

@ -1,11 +1,9 @@
import AuthResponse from '../../AuthResponse';
import { AuthResponse } from '../AuthResponse';
const customRoutes = [
export const ROUTES_EE = [
{
Component: () => ({ default: AuthResponse }),
to: '/auth/login/:authResponse',
exact: true,
},
];
export default customRoutes;

View File

@ -7,7 +7,7 @@ import { useHistory, useRouteMatch } from 'react-router-dom';
import { getRequestUrl } from '../../../../admin/src/utils';
const AuthResponse = () => {
export const AuthResponse = () => {
const {
params: { authResponse },
} = useRouteMatch('/auth/login/:authResponse');

View File

@ -0,0 +1,49 @@
export const ROUTES_EE = [
...(window.strapi.features.isEnabled(window.strapi.features.AUDIT_LOGS)
? [
{
async Component() {
const component = await import(
/* webpackChunkName: "audit-logs-settings-page" */ './pages/AuditLogs/ProtectedListPage'
);
return component;
},
to: '/settings/audit-logs',
exact: true,
},
]
: []),
...(window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS)
? [
{
async Component() {
const component = await import(
/* webpackChunkName: "review-workflows-settings" */ './pages/ReviewWorkflows'
);
return component;
},
to: '/settings/review-workflows',
exact: true,
},
]
: []),
...(window.strapi.features.isEnabled(window.strapi.features.SSO)
? [
{
async Component() {
const component = await import(
/* webpackChunkName: "sso-settings-page" */ './pages/SingleSignOn'
);
return component;
},
to: '/settings/single-sign-on',
exact: true,
},
]
: []),
];

View File

@ -1,45 +0,0 @@
const routes = [];
if (window.strapi.features.isEnabled(window.strapi.features.SSO)) {
routes.push({
async Component() {
const component = await import(
/* webpackChunkName: "sso-settings-page" */ '../pages/SingleSignOn'
);
return component;
},
to: '/settings/single-sign-on',
exact: true,
});
}
if (window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS)) {
routes.push({
async Component() {
const component = await import(
/* webpackChunkName: "review-workflows-settings" */ '../pages/ReviewWorkflows'
);
return component;
},
to: '/settings/review-workflows',
exact: true,
});
}
if (window.strapi.features.isEnabled(window.strapi.features.AUDIT_LOGS)) {
routes.push({
async Component() {
const component = await import(
/* webpackChunkName: "audit-logs-settings-page" */ '../pages/AuditLogs/ProtectedListPage'
);
return component;
},
to: '/settings/audit-logs',
exact: true,
});
}
export default routes;

View File

@ -48,7 +48,10 @@ export type RouterConfig<TContentTypeUID extends Common.UID.ContentType> = {
except?: string[];
config: Utils.Expression.MatchFirst<
[
Utils.Expression.Test<Common.UID.IsCollectionType<TContentTypeUID>, CollectionTypeRouterConfig>,
Utils.Expression.Test<
Common.UID.IsCollectionType<TContentTypeUID>,
CollectionTypeRouterConfig
>,
Utils.Expression.Test<Common.UID.IsSingleType<TContentTypeUID>, SingleTypeRouterConfig>
],
Generic