Fix CM menu update when changing the LV settings. Remove menu legacy

Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
soupette 2021-06-16 08:55:49 +02:00
parent a389ab443c
commit be03d496d8
16 changed files with 101 additions and 199 deletions

View File

@ -1,14 +1,10 @@
import { TOGGLE_IS_LOADING, SET_SECTION_LINKS, UNSET_IS_LOADING } from './constants';
import { SET_SECTION_LINKS, UNSET_IS_LOADING } from './constants';
export const setSectionLinks = (authorizedGeneralLinks, authorizedPluginLinks) => ({
type: SET_SECTION_LINKS,
data: { authorizedGeneralLinks, authorizedPluginLinks },
});
export const toggleIsLoading = () => ({
type: TOGGLE_IS_LOADING,
});
export const unsetIsLoading = () => ({
type: UNSET_IS_LOADING,
});

View File

@ -1,3 +1,2 @@
export const SET_SECTION_LINKS = 'StrapiAdmin/LeftMenu/SET_SECTION_LINKS';
export const TOGGLE_IS_LOADING = 'StrapiAdmin/LeftMenu/TOGGLE_IS_LOADING';
export const UNSET_IS_LOADING = 'StrapiAdmin/LeftMenu/UNSET_IS_LOADING';

View File

@ -1,31 +1,18 @@
import React, { memo, useEffect } from 'react';
import PropTypes from 'prop-types';
import React, { memo } from 'react';
import { useLocation } from 'react-router-dom';
import { useAppInfos, useStrapiApp } from '@strapi/helper-plugin';
import { Footer, Header, Loader, LinksContainer, LinksSection } from './compos';
import Wrapper from './Wrapper';
import useMenuSections from './useMenuSections';
const LeftMenu = ({ setUpdateMenu }) => {
const LeftMenu = () => {
const location = useLocation();
const { shouldUpdateStrapi } = useAppInfos();
const { plugins } = useStrapiApp();
const {
state: { isLoading, generalSectionLinks, pluginsSectionLinks },
toggleLoading,
generateMenu,
} = useMenuSections(plugins, shouldUpdateStrapi);
// This effect is really temporary until we create the menu api
// We need this because we need to regenerate the links when the settings are being changed
// in the content manager configurations list
useEffect(() => {
setUpdateMenu(() => {
toggleLoading();
generateMenu();
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const { isLoading, generalSectionLinks, pluginsSectionLinks } = useMenuSections(
plugins,
shouldUpdateStrapi
);
return (
<Wrapper>
@ -57,8 +44,4 @@ const LeftMenu = ({ setUpdateMenu }) => {
);
};
LeftMenu.propTypes = {
setUpdateMenu: PropTypes.func.isRequired,
};
export default memo(LeftMenu);

View File

@ -1,7 +1,7 @@
/* eslint-disable consistent-return */
import produce from 'immer';
import adminPermissions from '../../permissions';
import { SET_SECTION_LINKS, TOGGLE_IS_LOADING, UNSET_IS_LOADING } from './constants';
import { SET_SECTION_LINKS, UNSET_IS_LOADING } from './constants';
const initialState = {
generalSectionLinks: [
@ -45,16 +45,10 @@ const reducer = (state = initialState, action) =>
draftState.pluginsSectionLinks = authorizedPluginLinks;
break;
}
case TOGGLE_IS_LOADING: {
draftState.isLoading = !state.isLoading;
break;
}
case UNSET_IS_LOADING: {
draftState.isLoading = false;
break;
}
default:
return draftState;
}

View File

@ -1,5 +1,5 @@
import reducer, { initialState } from '../reducer';
import { SET_SECTION_LINKS, TOGGLE_IS_LOADING } from '../constants';
import { SET_SECTION_LINKS } from '../constants';
describe('ADMIN | LeftMenu | reducer', () => {
describe('DEFAULT_ACTION', () => {
@ -12,24 +12,6 @@ describe('ADMIN | LeftMenu | reducer', () => {
});
});
describe('TOGGLE_IS_LOADING', () => {
it('should change the isLoading property correctly', () => {
const state = {
isLoading: true,
};
const expected = {
isLoading: false,
};
const action = {
type: TOGGLE_IS_LOADING,
};
expect(reducer(state, action)).toEqual(expected);
});
});
describe('SET_SECTION_LINKS', () => {
it('sets the generalSectionLinks and the pluginsSectionLinks with the action', () => {
const state = { ...initialState };

View File

@ -3,7 +3,7 @@ import { useRBACProvider } from '@strapi/helper-plugin';
import { useSelector, useDispatch } from 'react-redux';
import getPluginSectionLinks from './utils/getPluginSectionLinks';
import getGeneralLinks from './utils/getGeneralLinks';
import { setSectionLinks, toggleIsLoading, unsetIsLoading } from './actions';
import { setSectionLinks, unsetIsLoading } from './actions';
import toPluginLinks from './utils/toPluginLinks';
import selectMenuLinks from './selectors';
@ -20,8 +20,6 @@ const useMenuSections = (plugins, shouldUpdateStrapi) => {
// so it's definitely ok to use a ref here
const pluginsRef = useRef(plugins);
const toggleLoading = () => dispatch(toggleIsLoading());
const resolvePermissions = async (permissions = allPermissions) => {
const pluginsSectionLinks = toPluginLinks(pluginsRef.current);
@ -46,7 +44,7 @@ const useMenuSections = (plugins, shouldUpdateStrapi) => {
resolvePermissionsRef.current(allPermissions);
}, [allPermissions, dispatch]);
return { state, generateMenu: resolvePermissionsRef.current, toggleLoading };
return state;
};
export default useMenuSections;

View File

@ -4,15 +4,10 @@
*
*/
import React, { Suspense, useEffect, useState, lazy } from 'react';
import React, { Suspense, useEffect, lazy } from 'react';
import { Switch, Route } from 'react-router-dom';
// Components from @strapi/helper-plugin
import {
CheckPagePermissions,
AppMenuContext,
useTracking,
LoadingIndicatorPage,
} from '@strapi/helper-plugin';
import { CheckPagePermissions, useTracking, LoadingIndicatorPage } from '@strapi/helper-plugin';
import adminPermissions from '../../permissions';
import Header from '../../components/Header/index';
import NavTopRightWrapper from '../../components/NavTopRightWrapper';
@ -69,54 +64,45 @@ const Admin = () => {
// Show a notification when the current version of Strapi is not the latest one
useReleaseNotification();
useTrackUsage();
// FIXME:
// This is temporary until we refactor the menu
const [{ updateMenu }, setUpdateMenuFn] = useState({ updateMenu: null });
const setUpdateMenu = updateMenuFn => {
setUpdateMenuFn({ updateMenu: updateMenuFn });
};
return (
<AppMenuContext.Provider value={updateMenu}>
<Wrapper>
<LeftMenu setUpdateMenu={setUpdateMenu} />
<NavTopRightWrapper>
{/* Injection zone not ready yet */}
<Logout />
</NavTopRightWrapper>
<div className="adminPageRightWrapper">
<Header />
<Content>
<Suspense fallback={<LoadingIndicatorPage />}>
<Switch>
<Route path="/" component={HomePage} exact />
<Route path="/me" component={ProfilePage} exact />
<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} />
<Route path="/settings/:settingId" component={SettingsPage} />
<Route path="/settings" component={SettingsPage} exact />
<Route path="/marketplace">
<CheckPagePermissions permissions={adminPermissions.marketplace.main}>
<MarketplacePage />
</CheckPagePermissions>
</Route>
<Route path="/list-plugins" exact>
<CheckPagePermissions permissions={adminPermissions.marketplace.main}>
<InstalledPluginsPage />
</CheckPagePermissions>
</Route>
<Route path="/404" component={NotFoundPage} />
<Route path="" component={NotFoundPage} />
</Switch>
</Suspense>
</Content>
</div>
<Onboarding />
</Wrapper>
</AppMenuContext.Provider>
<Wrapper>
<LeftMenu />
<NavTopRightWrapper>
{/* Injection zone not ready yet */}
<Logout />
</NavTopRightWrapper>
<div className="adminPageRightWrapper">
<Header />
<Content>
<Suspense fallback={<LoadingIndicatorPage />}>
<Switch>
<Route path="/" component={HomePage} exact />
<Route path="/me" component={ProfilePage} exact />
<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} />
<Route path="/settings/:settingId" component={SettingsPage} />
<Route path="/settings" component={SettingsPage} exact />
<Route path="/marketplace">
<CheckPagePermissions permissions={adminPermissions.marketplace.main}>
<MarketplacePage />
</CheckPagePermissions>
</Route>
<Route path="/list-plugins" exact>
<CheckPagePermissions permissions={adminPermissions.marketplace.main}>
<InstalledPluginsPage />
</CheckPagePermissions>
</Route>
<Route path="/404" component={NotFoundPage} />
<Route path="" component={NotFoundPage} />
</Switch>
</Suspense>
</Content>
</div>
<Onboarding />
</Wrapper>
);
};

View File

@ -0,0 +1,5 @@
import { createContext } from 'react';
const ModelsContext = createContext();
export default ModelsContext;

View File

@ -6,6 +6,7 @@ import HTML5Backend from 'react-dnd-html5-backend';
import pluginId from '../../pluginId';
import pluginPermissions from '../../permissions';
import DragLayer from '../../components/DragLayer';
import ModelsContext from '../../contexts/ModelsContext';
import CollectionTypeRecursivePath from '../CollectionTypeRecursivePath';
import ComponentSettingsView from '../ComponentSetttingsView';
import SingleTypeRecursivePath from '../SingleTypeRecursivePath';
@ -14,7 +15,7 @@ import useModels from './useModels';
const App = () => {
const contentTypeMatch = useRouteMatch(`/plugins/${pluginId}/:kind/:uid`);
const { status, collectionTypeLinks, singleTypeLinks, models } = useModels();
const { status, collectionTypeLinks, singleTypeLinks, models, refetchData } = useModels();
const authorisedModels = [...collectionTypeLinks, ...singleTypeLinks];
const { pathname } = useLocation();
@ -49,40 +50,41 @@ const App = () => {
return (
<DndProvider backend={HTML5Backend}>
<DragLayer />
<ModelsContext.Provider value={{ refetchData }}>
<div className="container-fluid">
<div className="row">
<LeftMenu />
<div className="col-md-9 content" style={{ padding: '0 30px' }}>
<Switch>
<Route path={`/plugins/${pluginId}/components/:uid/configurations/edit`}>
<CheckPagePermissions permissions={pluginPermissions.componentsConfigurations}>
<ComponentSettingsView />
</CheckPagePermissions>
</Route>
<Route
path={`/plugins/${pluginId}/collectionType/:slug`}
component={CollectionTypeRecursivePath}
/>
<Route
path={`/plugins/${pluginId}/singleType/:slug`}
component={SingleTypeRecursivePath}
/>
<div className="container-fluid">
<div className="row">
<LeftMenu />
<div className="col-md-9 content" style={{ padding: '0 30px' }}>
<Switch>
<Route path={`/plugins/${pluginId}/components/:uid/configurations/edit`}>
<CheckPagePermissions permissions={pluginPermissions.componentsConfigurations}>
<ComponentSettingsView />
</CheckPagePermissions>
</Route>
<Route
path={`/plugins/${pluginId}/collectionType/:slug`}
component={CollectionTypeRecursivePath}
/>
<Route
path={`/plugins/${pluginId}/singleType/:slug`}
component={SingleTypeRecursivePath}
/>
{/* These pages must be defined */}
<Route
path={`/plugins/${pluginId}/403`}
render={() => <div>TBD No rights to see the content types</div>}
/>
<Route
path={`/plugins/${pluginId}/no-content-types`}
render={() => <div>TBD No ct</div>}
/>
<Route path="" component={NotFound} />
</Switch>
{/* These pages must be defined */}
<Route
path={`/plugins/${pluginId}/403`}
render={() => <div>TBD No rights to see the content types</div>}
/>
<Route
path={`/plugins/${pluginId}/no-content-types`}
render={() => <div>TBD No ct</div>}
/>
<Route path="" component={NotFound} />
</Switch>
</div>
</div>
</div>
</div>
</ModelsContext.Provider>
</DndProvider>
);
};

View File

@ -45,19 +45,20 @@ const useModels = () => {
fetchDataRef.current = fetchData;
useEffect(() => {
const abortController = new AbortController();
const { signal } = abortController;
const abortController = new AbortController();
const { signal } = abortController;
useEffect(() => {
fetchDataRef.current(signal);
return () => {
abortController.abort();
dispatch(resetProps());
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dispatch, toggleNotification]);
return state;
return { ...state, refetchData: fetchDataRef.current };
};
export default useModels;

View File

@ -1,7 +1,7 @@
import React, { memo, useMemo, useReducer, useState } from 'react';
import React, { memo, useContext, useMemo, useReducer, useState } from 'react';
import PropTypes from 'prop-types';
import { get, pick } from 'lodash';
import { request, useAppMenu, useNotification, useTracking } from '@strapi/helper-plugin';
import { request, useNotification, useTracking } from '@strapi/helper-plugin';
import { FormattedMessage, useIntl } from 'react-intl';
import { useDrop } from 'react-dnd';
import { DropdownItem } from 'reactstrap';
@ -12,6 +12,7 @@ import PopupForm from '../../components/PopupForm';
import SettingsViewWrapper from '../../components/SettingsViewWrapper';
import SortWrapper from '../../components/SortWrapper';
import LayoutDndProvider from '../../components/LayoutDndProvider';
import ModelsContext from '../../contexts/ModelsContext';
import Label from './Label';
import MenuDropdown from './MenuDropdown';
import DropdownButton from './DropdownButton';
@ -23,6 +24,7 @@ import forms from './forms.json';
const ListSettingsView = ({ layout, slug, updateLayout }) => {
const toggleNotification = useNotification();
const { refetchData } = useContext(ModelsContext);
const [reducerState, dispatch] = useReducer(reducer, initialState, () =>
init(initialState, layout)
);
@ -30,8 +32,6 @@ const ListSettingsView = ({ layout, slug, updateLayout }) => {
const [isModalFormOpen, setIsModalFormOpen] = useState(false);
const [isDraggingSibling, setIsDraggingSibling] = useState(false);
const { formatMessage } = useIntl();
// FIXME when we create the CM menu remove the useAppMenu completely
const updateMenu = useAppMenu();
const { trackUsage } = useTracking();
const toggleModalForm = () => setIsModalFormOpen(prevState => !prevState);
const { labelForm, labelToEdit, initialData, modifiedData } = reducerState;
@ -184,7 +184,7 @@ const ListSettingsView = ({ layout, slug, updateLayout }) => {
});
}}
onConfirmSubmit={handleConfirm}
onModalConfirmClosed={updateMenu}
onModalConfirmClosed={refetchData}
name={getName}
>
<DragWrapper>

View File

@ -1,13 +0,0 @@
/**
*
* AppMenuContext
* // TODO: This is a very temporary context provider that will needs to be removed when
* we refactor the menu
*
*/
import { createContext } from 'react';
const AppMenuContext = createContext();
export default AppMenuContext;

View File

@ -1,17 +0,0 @@
/**
*
* useAppMenu
*
*/
import { useContext, useRef } from 'react';
import AppMenuContext from '../../contexts/AppMenuContext';
const useAppMenu = () => {
const updateMenu = useContext(AppMenuContext);
const updateMenuRef = useRef(updateMenu);
return updateMenuRef.current;
};
export default useAppMenu;

View File

@ -113,8 +113,6 @@ export { default as OverlayBlockerContext } from './contexts/OverlayBlockerConte
export { default as ContentManagerEditViewDataManagerContext } from './contexts/ContentManagerEditViewDataManagerContext';
export { default as RBACProviderContext } from './contexts/RBACProviderContext';
export { default as TrackingContext } from './contexts/TrackingContext';
// TODO Remove this context
export { default as AppMenuContext } from './contexts/AppMenuContext';
// Hooks
export { default as useAppInfos } from './hooks/useAppInfos';
@ -124,8 +122,6 @@ export { default as useLibrary } from './hooks/useLibrary';
export { default as useNotification } from './hooks/useNotification';
export { default as useStrapiApp } from './hooks/useStrapiApp';
export { default as useTracking } from './hooks/useTracking';
// TODO remove this hook
export { default as useAppMenu } from './hooks/useAppMenu';
export { default as useQueryParams } from './hooks/useQueryParams';
export { default as useOverlayBlocker } from './hooks/useOverlayBlocker';

View File

@ -1,6 +1,6 @@
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import { Modal, ModalFooter, TabPanel, useAppMenu } from '@strapi/helper-plugin';
import { Modal, ModalFooter, TabPanel } from '@strapi/helper-plugin';
import { useIntl } from 'react-intl';
import { Button } from '@buffetjs/core';
import { Formik } from 'formik';
@ -14,7 +14,6 @@ import SettingsModal from '../SettingsModal';
const ModalEdit = ({ localeToEdit, onClose, locales }) => {
const { isEditing, editLocale } = useEditLocale();
const shouldUpdateMenu = useRef(false);
const updateMenu = useAppMenu();
const { formatMessage } = useIntl();
const isOpened = Boolean(localeToEdit);
@ -29,14 +28,6 @@ const ModalEdit = ({ localeToEdit, onClose, locales }) => {
.then(onClose);
};
const handleClose = () => {
if (shouldUpdateMenu.current) {
updateMenu();
}
shouldUpdateMenu.current = false;
};
let options = [];
let defaultOption;
@ -46,7 +37,7 @@ const ModalEdit = ({ localeToEdit, onClose, locales }) => {
}
return (
<Modal isOpen={isOpened} onToggle={onClose} onClosed={handleClose}>
<Modal isOpen={isOpened} onToggle={onClose}>
<Formik
initialValues={{
displayName: localeToEdit ? localeToEdit.name : '',

View File

@ -67,7 +67,6 @@ jest.mock('@strapi/helper-plugin', () => ({
useRBAC: jest.fn(),
request: jest.fn(),
selectStyles: () => ({ control: () => ({}), indicatorsContainer: () => ({}) }),
useAppMenu: () => jest.fn(),
useRBACProvider: () => ({ refetchPermissions: jest.fn() }),
useNotification: () => toggleNotificationMock,
}));