diff --git a/packages/core/admin/admin/src/StrapiApp.js b/packages/core/admin/admin/src/StrapiApp.js index 2e92a79eb6..4e811881de 100644 --- a/packages/core/admin/admin/src/StrapiApp.js +++ b/packages/core/admin/admin/src/StrapiApp.js @@ -10,8 +10,9 @@ import basename from './utils/basename'; import App from './pages/App'; import LanguageProvider from './components/LanguageProvider'; import AutoReloadOverlayBlocker from './components/AutoReloadOverlayBlocker'; -import Fonts from './components/Fonts'; import OverlayBlocker from './components/OverlayBlocker'; +import Fonts from './components/Fonts'; + import GlobalStyle from './components/GlobalStyle'; import Notifications from './components/Notifications'; import themes from './themes'; @@ -152,16 +153,15 @@ class StrapiApp { - - <> - - - - - - - - + + + + + + + + + diff --git a/packages/core/admin/admin/src/components/AutoReloadOverlayBlocker/Portal.js b/packages/core/admin/admin/src/components/AutoReloadOverlayBlocker/Portal.js new file mode 100644 index 0000000000..b6b3a50395 --- /dev/null +++ b/packages/core/admin/admin/src/components/AutoReloadOverlayBlocker/Portal.js @@ -0,0 +1,62 @@ +import React, { useEffect } from 'react'; +import ReactDOM from 'react-dom'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import PropTypes from 'prop-types'; +import Content from './Content'; +import Overlay from './Overlay'; +import Wrapper from './Wrapper'; + +const overlayContainer = document.createElement('div'); +const ID = 'autoReloadOverlayBlocker'; +overlayContainer.setAttribute('id', ID); + +const Portal = ({ className, displayedIcon, description, title, elapsed, isOpen }) => { + useEffect(() => { + document.body.appendChild(overlayContainer); + + return () => { + document.body.removeChild(overlayContainer); + }; + }, []); + + if (isOpen) { + return ReactDOM.createPortal( + + +
+ +
+
+ + {elapsed < 15 && ( +
+ + Read the documentation + +
+ )} +
+
+
, + overlayContainer + ); + } + + return null; +}; + +Portal.propTypes = { + className: PropTypes.string.isRequired, + displayedIcon: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired, + description: PropTypes.object.isRequired, + elapsed: PropTypes.number.isRequired, + isOpen: PropTypes.bool.isRequired, + title: PropTypes.object.isRequired, +}; + +export default Portal; diff --git a/packages/core/admin/admin/src/components/AutoReloadOverlayBlocker/index.js b/packages/core/admin/admin/src/components/AutoReloadOverlayBlocker/index.js index d844c000a5..b831be6bcc 100644 --- a/packages/core/admin/admin/src/components/AutoReloadOverlayBlocker/index.js +++ b/packages/core/admin/admin/src/components/AutoReloadOverlayBlocker/index.js @@ -1,22 +1,14 @@ -import React, { useEffect, useState } from 'react'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import ReactDOM from 'react-dom'; -import Content from './Content'; -import Overlay from './Overlay'; -import Wrapper from './Wrapper'; +import React, { useEffect, useRef, useState } from 'react'; +import { AutoReloadOverlayBockerContext } from '@strapi/helper-plugin'; +import PropTypes from 'prop-types'; +import Portal from './Portal'; -const overlayContainer = document.createElement('div'); -const ID = 'autoReloadOverlayBlocker'; -overlayContainer.setAttribute('id', ID); - -const AutoReloadOverlayBlocker = () => { +const AutoReloadOverlayBlocker = ({ children }) => { const [isOpen, setIsOpen] = useState(false); const [{ elapsed }, setState] = useState({ elapsed: 0, start: 0 }); const [config, setConfig] = useState(undefined); const lockAppWithAutoreload = (config = undefined) => { - document.body.appendChild(overlayContainer); - setIsOpen(true); setConfig(config); setState(prev => ({ ...prev, start: Date.now() })); @@ -26,18 +18,10 @@ const AutoReloadOverlayBlocker = () => { setIsOpen(false); setState({ start: 0, elapsed: 0 }); setConfig(undefined); - - if (document.getElementById(ID)) { - document.body.removeChild(overlayContainer); - } }; - useEffect(() => { - window.strapi = Object.assign(window.strapi || {}, { - lockAppWithAutoreload, - unlockAppWithAutoreload, - }); - }, []); + const lockApp = useRef(lockAppWithAutoreload); + const unlockApp = useRef(unlockAppWithAutoreload); useEffect(() => { let timer = null; @@ -89,35 +73,25 @@ const AutoReloadOverlayBlocker = () => { }; } - if (isOpen) { - return ReactDOM.createPortal( - - -
- -
-
- - {elapsed < 15 && ( -
- - Read the documentation - -
- )} -
-
-
, - overlayContainer - ); - } + return ( + + + {children} + + ); +}; - return null; +AutoReloadOverlayBlocker.propTypes = { + children: PropTypes.element.isRequired, }; export default AutoReloadOverlayBlocker; diff --git a/packages/core/admin/admin/src/components/LanguageProvider/reducer.js b/packages/core/admin/admin/src/components/LanguageProvider/reducer.js index a2f71a09d8..960ad7edf6 100644 --- a/packages/core/admin/admin/src/components/LanguageProvider/reducer.js +++ b/packages/core/admin/admin/src/components/LanguageProvider/reducer.js @@ -41,7 +41,6 @@ function languageProviderReducer(state = initialState, action) { case CHANGE_LOCALE: // Set user language in local storage. window.localStorage.setItem(localStorageKey, action.locale); - strapi.currentLanguage = action.locale; return state.set('locale', action.locale); default: diff --git a/packages/core/admin/admin/src/components/OverlayBlocker/Overlay.js b/packages/core/admin/admin/src/components/OverlayBlocker/Overlay.js deleted file mode 100644 index 0fbb04c3b1..0000000000 --- a/packages/core/admin/admin/src/components/OverlayBlocker/Overlay.js +++ /dev/null @@ -1,14 +0,0 @@ -import styled from 'styled-components'; - -const Overlay = styled.div` - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1140; -`; - -Overlay.defaultProps = {}; - -export default Overlay; diff --git a/packages/core/admin/admin/src/components/OverlayBlocker/index.js b/packages/core/admin/admin/src/components/OverlayBlocker/index.js index 2c35433b63..39864e19f0 100644 --- a/packages/core/admin/admin/src/components/OverlayBlocker/index.js +++ b/packages/core/admin/admin/src/components/OverlayBlocker/index.js @@ -1,39 +1,33 @@ /** * - * OverlayBlocker - * This component is used to prevent user interactions + * OverlayBlockerProvider * */ - import React, { useEffect, useState } from 'react'; import ReactDOM from 'react-dom'; -import Overlay from './Overlay'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; +import { OverlayBlockerContext } from '@strapi/helper-plugin'; const overlayContainer = document.createElement('div'); overlayContainer.setAttribute('id', 'overlayBlocker'); -const OverlayBlocker = () => { - const [isOpen, setIsOpen] = useState(false); +const Overlay = styled.div` + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1140; +`; - const lockApp = () => { +const Portal = ({ isOpen }) => { + useEffect(() => { document.body.appendChild(overlayContainer); - setIsOpen(true); - }; - - const unlockApp = () => { - setIsOpen(false); - - if (document.getElementById('overlayBlocker')) { + return () => { document.body.removeChild(overlayContainer); - } - }; - - useEffect(() => { - window.strapi = Object.assign(window.strapi || {}, { - lockApp, - unlockApp, - }); + }; }, []); if (isOpen) { @@ -43,4 +37,27 @@ const OverlayBlocker = () => { return null; }; -export default OverlayBlocker; +const OverlayBlockerProvider = ({ children }) => { + const [isOpen, setIsOpen] = useState(false); + + const lockApp = () => { + setIsOpen(true); + }; + + const unlockApp = () => { + setIsOpen(false); + }; + + return ( + + {children} + + + ); +}; + +OverlayBlockerProvider.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default OverlayBlockerProvider; diff --git a/packages/core/admin/admin/src/components/Users/ModalCreateBody/index.js b/packages/core/admin/admin/src/components/Users/ModalCreateBody/index.js index 540c74840f..46f3753524 100644 --- a/packages/core/admin/admin/src/components/Users/ModalCreateBody/index.js +++ b/packages/core/admin/admin/src/components/Users/ModalCreateBody/index.js @@ -1,6 +1,12 @@ import React, { forwardRef, useReducer, useImperativeHandle, useRef } from 'react'; import PropTypes from 'prop-types'; -import { BaselineAlignment, ModalSection, request, useNotification } from '@strapi/helper-plugin'; +import { + BaselineAlignment, + ModalSection, + request, + useNotification, + useOverlayBlocker, +} from '@strapi/helper-plugin'; import { useIntl } from 'react-intl'; import { get } from 'lodash'; import { Padded, Text } from '@buffetjs/core'; @@ -19,6 +25,8 @@ import RoleSettingsModalSection from '../RoleSettingsModalSection'; // This component accepts a ref so we can have access to the submit handler. const ModalCreateBody = forwardRef( ({ isDisabled, onSubmit, registrationToken, setIsSubmiting, showMagicLink }, ref) => { + const { lockApp, unlockApp } = useOverlayBlocker(); + const toggleNotification = useNotification(); const [reducerState, dispatch] = useReducer(reducer, initialState, init); const { formErrors, modifiedData } = reducerState; @@ -47,7 +55,7 @@ const ModalCreateBody = forwardRef( if (!errors) { try { // Prevent user interactions until the request is completed - strapi.lockApp(); + lockApp(); setIsSubmiting(true); @@ -65,7 +73,7 @@ const ModalCreateBody = forwardRef( toggleNotification({ type: 'warning', message }); } finally { - strapi.unlockApp(); + unlockApp(); setIsSubmiting(false); } } diff --git a/packages/core/admin/admin/src/hooks/useSettingsForm/index.js b/packages/core/admin/admin/src/hooks/useSettingsForm/index.js index 3997135fdb..04c29bb18a 100644 --- a/packages/core/admin/admin/src/hooks/useSettingsForm/index.js +++ b/packages/core/admin/admin/src/hooks/useSettingsForm/index.js @@ -1,5 +1,5 @@ import { useEffect, useReducer } from 'react'; -import { request, useNotification } from '@strapi/helper-plugin'; +import { request, useNotification, useOverlayBlocker } from '@strapi/helper-plugin'; import { get, has, omit } from 'lodash'; import { checkFormValidity, formatAPIErrors } from '../../utils'; import { initialState, reducer } from './reducer'; @@ -11,6 +11,7 @@ const useSettingsForm = (endPoint, schema, cbSuccess, fieldsToPick) => { dispatch, ] = useReducer(reducer, initialState, () => init(initialState, fieldsToPick)); const toggleNotification = useNotification(); + const { lockApp, unlockApp } = useOverlayBlocker(); useEffect(() => { const getData = async () => { @@ -72,7 +73,7 @@ const useSettingsForm = (endPoint, schema, cbSuccess, fieldsToPick) => { if (!errors) { try { - strapi.lockApp(); + lockApp(); dispatch({ type: 'ON_SUBMIT', @@ -122,7 +123,7 @@ const useSettingsForm = (endPoint, schema, cbSuccess, fieldsToPick) => { errors: apiErrors, }); } finally { - strapi.unlockApp(); + unlockApp(); } } }; diff --git a/packages/core/admin/admin/src/pages/Admin/index.js b/packages/core/admin/admin/src/pages/Admin/index.js index c4805c5cbd..768c8a55a7 100644 --- a/packages/core/admin/admin/src/pages/Admin/index.js +++ b/packages/core/admin/admin/src/pages/Admin/index.js @@ -185,9 +185,6 @@ export class Admin extends React.Component { emitEvent={this.emitEvent} currentEnvironment={currentEnvironment} currentLocale={locale} - // FIXME - disableGlobalOverlayBlocker={() => console.log('todo')} - enableGlobalOverlayBlocker={() => console.log('todo')} formatMessage={formatMessage} plugins={plugins} shouldUpdateStrapi={shouldUpdateStrapi} diff --git a/packages/core/admin/admin/src/pages/InstalledPluginsPage/index.js b/packages/core/admin/admin/src/pages/InstalledPluginsPage/index.js index e9dda50e99..0ce8e94fcb 100644 --- a/packages/core/admin/admin/src/pages/InstalledPluginsPage/index.js +++ b/packages/core/admin/admin/src/pages/InstalledPluginsPage/index.js @@ -1,5 +1,10 @@ import React from 'react'; -import { useGlobalContext, request, useNotification } from '@strapi/helper-plugin'; +import { + useGlobalContext, + request, + useNotification, + useAutoReloadOverlayBlocker, +} from '@strapi/helper-plugin'; import { Header, List } from '@buffetjs/custom'; import PageTitle from '../../components/PageTitle'; import ContainerFluid from '../../components/ContainerFluid'; @@ -9,6 +14,7 @@ import generateRows from './utils/generateRows'; const InstalledPluginsPage = () => { const toggleNotification = useNotification(); + const { lockAppWithAutoreload, unlockAppWithAutoreload } = useAutoReloadOverlayBlocker(); const { formatMessage, plugins } = useGlobalContext(); const onConfirm = async id => { try { @@ -20,7 +26,7 @@ const InstalledPluginsPage = () => { description: 'app.components.ListPluginsPage.deletePlugin.description', }; // Lock the app - strapi.lockAppWithAutoreload(overlayblockerParams); + lockAppWithAutoreload(overlayblockerParams); const response = await request(requestUrl, { method: 'DELETE' }, overlayblockerParams); if (response.ok) { @@ -28,7 +34,7 @@ const InstalledPluginsPage = () => { window.location.reload(); } } catch (err) { - strapi.unlockAppWithAutoreload(); + unlockAppWithAutoreload(); toggleNotification({ type: 'warning', message: { id: 'app.components.listPluginsPage.deletePlugin.error' }, diff --git a/packages/core/admin/admin/src/pages/MarketplacePage/index.js b/packages/core/admin/admin/src/pages/MarketplacePage/index.js index 6237824f3a..0872d6a096 100644 --- a/packages/core/admin/admin/src/pages/MarketplacePage/index.js +++ b/packages/core/admin/admin/src/pages/MarketplacePage/index.js @@ -4,6 +4,7 @@ import { useGlobalContext, request, useNotification, + useAutoReloadOverlayBlocker, } from '@strapi/helper-plugin'; import { Header } from '@buffetjs/custom'; import { useHistory } from 'react-router-dom'; @@ -14,6 +15,7 @@ import Wrapper from './Wrapper'; const MarketPlacePage = () => { const toggleNotification = useNotification(); + const { lockAppWithAutoreload, unlockAppWithAutoreload } = useAutoReloadOverlayBlocker(); const history = useHistory(); const { autoReload, currentEnvironment, formatMessage, plugins } = useGlobalContext(); const { error, isLoading, data } = useFetchPluginsFromMarketPlace(); @@ -30,7 +32,7 @@ const MarketPlacePage = () => { description: 'app.components.InstallPluginPage.Download.description', }; // Lock the app - strapi.lockAppWithAutoreload(overlayblockerParams); + lockAppWithAutoreload(overlayblockerParams); try { const opts = { @@ -47,7 +49,7 @@ const MarketPlacePage = () => { window.location.reload(); } } catch (err) { - strapi.unlockApp(); + unlockAppWithAutoreload(); toggleNotification({ type: 'warning', message: { id: 'notification.error' }, diff --git a/packages/core/admin/admin/src/pages/Roles/EditPage/index.js b/packages/core/admin/admin/src/pages/Roles/EditPage/index.js index 4bf1827227..ea61199fe5 100644 --- a/packages/core/admin/admin/src/pages/Roles/EditPage/index.js +++ b/packages/core/admin/admin/src/pages/Roles/EditPage/index.js @@ -6,6 +6,7 @@ import { useGlobalContext, request, useNotification, + useOverlayBlocker, } from '@strapi/helper-plugin'; import { Header } from '@buffetjs/custom'; import { Padded } from '@buffetjs/core'; @@ -26,6 +27,7 @@ const EditPage = () => { } = useRouteMatch('/settings/roles/:id'); const [isSubmiting, setIsSubmiting] = useState(false); const permissionsRef = useRef(); + const { lockApp, unlockApp } = useOverlayBlocker(); const { isLoading: isLayoutLoading, data: permissionsLayout } = useFetchPermissionsLayout(id); const { @@ -69,7 +71,7 @@ const EditPage = () => { const handleEditRoleSubmit = async data => { try { - strapi.lockApp(); + lockApp(); setIsSubmiting(true); const { permissionsToSend, didUpdateConditions } = permissionsRef.current.getPermissions(); @@ -111,7 +113,7 @@ const EditPage = () => { }); } finally { setIsSubmiting(false); - strapi.unlockApp(); + unlockApp(); } }; diff --git a/packages/core/admin/admin/src/pages/Webhooks/EditView/index.js b/packages/core/admin/admin/src/pages/Webhooks/EditView/index.js index 512b03ba10..93bbf72d40 100644 --- a/packages/core/admin/admin/src/pages/Webhooks/EditView/index.js +++ b/packages/core/admin/admin/src/pages/Webhooks/EditView/index.js @@ -16,6 +16,7 @@ import { BackHeader, LoadingIndicatorPage, useNotification, + useOverlayBlocker, } from '@strapi/helper-plugin'; import { useModels } from '../../../hooks'; import PageTitle from '../../../components/SettingsPageTitle'; @@ -27,6 +28,7 @@ import Wrapper from './Wrapper'; function EditView() { const { isLoading: isLoadingForModels, collectionTypes } = useModels(); const toggleNotification = useNotification(); + const { lockApp, unlockApp } = useOverlayBlocker(); const isMounted = useRef(); const { formatMessage } = useGlobalContext(); const [submittedOnce, setSubmittedOnce] = useState(false); @@ -191,7 +193,7 @@ function EditView() { const createWebhooks = async () => { try { - strapi.lockApp(); + lockApp(); setIsSubmitting(true); const { data } = await request('/admin/webhooks', { method: 'POST', @@ -213,7 +215,7 @@ function EditView() { message: { id: 'notification.error' }, }); } finally { - strapi.unlockApp(); + unlockApp(); } }; @@ -355,7 +357,7 @@ function EditView() { const updateWebhook = async () => { try { - strapi.lockApp(); + lockApp(); setIsSubmitting(true); const body = cleanData(modifiedData); @@ -380,7 +382,7 @@ function EditView() { message: { id: 'notification.error' }, }); } finally { - strapi.unlockApp(); + unlockApp(); } }; diff --git a/packages/core/admin/admin/src/tests/StrapiApp.test.js b/packages/core/admin/admin/src/tests/StrapiApp.test.js index a0d280f7c1..0bc2c8870e 100644 --- a/packages/core/admin/admin/src/tests/StrapiApp.test.js +++ b/packages/core/admin/admin/src/tests/StrapiApp.test.js @@ -73,6 +73,12 @@ describe('ADMIN | StrapiApp', () => {
+
+
, "container":
{ const toggleNotification = useNotification(); + const { lockApp, unlockApp } = useOverlayBlocker(); const { formatMessage } = useIntl(); const [isSubmiting, setIsSubmiting] = useState(false); const { replace } = useHistory(); @@ -62,7 +64,7 @@ const CreatePage = () => { ]; const handleCreateRoleSubmit = data => { - strapi.lockApp(); + lockApp(); setIsSubmiting(true); if (id) { @@ -112,7 +114,7 @@ const CreatePage = () => { }); }) .finally(() => { - strapi.unlockApp(); + unlockApp(); }); }; diff --git a/packages/core/content-manager/admin/src/containers/EditViewDataManagerProvider/index.js b/packages/core/content-manager/admin/src/containers/EditViewDataManagerProvider/index.js index d5e13aea37..88ac3eda1d 100644 --- a/packages/core/content-manager/admin/src/containers/EditViewDataManagerProvider/index.js +++ b/packages/core/content-manager/admin/src/containers/EditViewDataManagerProvider/index.js @@ -5,9 +5,10 @@ import { Prompt, Redirect } from 'react-router-dom'; import { LoadingIndicatorPage, useGlobalContext, - OverlayBlocker, + // OverlayBlocker, ContentManagerEditViewDataManagerContext, useNotification, + useOverlayBlocker, } from '@strapi/helper-plugin'; import { getTrad, removeKeyInObject } from '../../utils'; import reducer, { initialState } from './reducer'; @@ -45,6 +46,7 @@ const EditViewDataManagerProvider = ({ shouldCheckErrors, } = reducerState.toJS(); const toggleNotification = useNotification(); + const { lockApp, unlockApp } = useOverlayBlocker(); const currentContentTypeLayout = get(allLayoutData, ['contentType'], {}); @@ -75,6 +77,14 @@ const EditViewDataManagerProvider = ({ return false; }, [isLoadingForData, isCreatingEntry, canRead, canUpdate]); + useEffect(() => { + if (status === 'resolved') { + unlockApp(); + } else { + lockApp(); + } + }, [lockApp, unlockApp, status]); + // TODO check this effect if it is really needed (not prio) useEffect(() => { if (!isLoadingForData) { @@ -421,13 +431,13 @@ const EditViewDataManagerProvider = ({ }); }, []); - const overlayBlockerParams = useMemo( - () => ({ - children:
, - noGradient: true, - }), - [] - ); + // const overlayBlockerParams = useMemo( + // () => ({ + // children:
, + // noGradient: true, + // }), + // [] + // ); // Redirect the user to the previous page if he is not allowed to read/update a document if (shouldRedirectToHomepageWhenEditingEntry) { @@ -472,11 +482,11 @@ const EditViewDataManagerProvider = ({ }} > <> - + /> */} {isLoadingForData ? ( ) : ( diff --git a/packages/core/content-type-builder/admin/src/containers/DataManagerProvider/index.js b/packages/core/content-type-builder/admin/src/containers/DataManagerProvider/index.js index 4f779b4985..c5d33322f4 100644 --- a/packages/core/content-type-builder/admin/src/containers/DataManagerProvider/index.js +++ b/packages/core/content-type-builder/admin/src/containers/DataManagerProvider/index.js @@ -9,6 +9,7 @@ import { useNotification, useStrapiApp, useUser, + useAutoReloadOverlayBlocker, } from '@strapi/helper-plugin'; import { useHistory, useLocation, useRouteMatch, Redirect } from 'react-router-dom'; import { connect, useDispatch } from 'react-redux'; @@ -65,6 +66,11 @@ const DataManagerProvider = ({ }) => { const dispatch = useDispatch(); const toggleNotification = useNotification(); +<<<<<<< HEAD +======= + const toggleNotificationRef = useRef(toggleNotification); + const { lockAppWithAutoreload, unlockAppWithAutoreload } = useAutoReloadOverlayBlocker(); +>>>>>>> 5b870248a (Remove strapi.lockApp) const { getPlugin } = useStrapiApp(); @@ -247,7 +253,7 @@ const DataManagerProvider = ({ push({ search: '' }); if (userConfirm) { - strapi.lockApp(); + lockAppWithAutoreload(); await request(requestURL, { method: 'DELETE' }, true); @@ -265,7 +271,7 @@ const DataManagerProvider = ({ message: { id: 'notification.error' }, }); } finally { - strapi.unlockApp(); + unlockAppWithAutoreload(); } }; @@ -296,7 +302,7 @@ const DataManagerProvider = ({ return; } - strapi.lockApp(); + lockAppWithAutoreload(); await request(requestURL, { method: 'DELETE' }, true); @@ -316,7 +322,7 @@ const DataManagerProvider = ({ message: { id: 'notification.error' }, }); } finally { - strapi.unlockApp(); + unlockAppWithAutoreload(); } }; @@ -328,7 +334,7 @@ const DataManagerProvider = ({ push({ search: '' }); // Lock the app - strapi.lockApp(); + lockAppWithAutoreload(); // Update the category await request(requestURL, { method: 'PUT', body }, true); @@ -346,7 +352,7 @@ const DataManagerProvider = ({ message: { id: 'notification.error' }, }); } finally { - strapi.unlockApp(); + unlockAppWithAutoreload(); } }; @@ -467,7 +473,7 @@ const DataManagerProvider = ({ const requestURL = isCreating ? baseURL : `${baseURL}/${currentUid}`; // Lock the app - strapi.lockApp(); + lockAppWithAutoreload(); await request(requestURL, { method, body }, true); @@ -502,7 +508,7 @@ const DataManagerProvider = ({ message: { id: 'notification.error' }, }); } finally { - strapi.unlockApp(); + unlockAppWithAutoreload(); } }; diff --git a/packages/core/helper-plugin/lib/src/contexts/AutoReloadOverlayBockerContext.js b/packages/core/helper-plugin/lib/src/contexts/AutoReloadOverlayBockerContext.js new file mode 100644 index 0000000000..2574a881a4 --- /dev/null +++ b/packages/core/helper-plugin/lib/src/contexts/AutoReloadOverlayBockerContext.js @@ -0,0 +1,12 @@ +/** + * + * AutoReloadOverlayBlocker + * + * + */ + +import { createContext } from 'react'; + +const AutoReloadOverlayBlocker = createContext(); + +export default AutoReloadOverlayBlocker; diff --git a/packages/core/helper-plugin/lib/src/contexts/OverlayBlockerContext.js b/packages/core/helper-plugin/lib/src/contexts/OverlayBlockerContext.js new file mode 100644 index 0000000000..d6c40743d5 --- /dev/null +++ b/packages/core/helper-plugin/lib/src/contexts/OverlayBlockerContext.js @@ -0,0 +1,11 @@ +/** + * + * OverlayBlockerContext + * + */ + +import { createContext } from 'react'; + +const OverlayBlockerContext = createContext(); + +export default OverlayBlockerContext; diff --git a/packages/core/helper-plugin/lib/src/hooks/useAutoReloadOverlayBlocker/index.js b/packages/core/helper-plugin/lib/src/hooks/useAutoReloadOverlayBlocker/index.js new file mode 100644 index 0000000000..25f6397ddb --- /dev/null +++ b/packages/core/helper-plugin/lib/src/hooks/useAutoReloadOverlayBlocker/index.js @@ -0,0 +1,23 @@ +/** + * + * useAutoReloadOverlayBlocker + * + */ + +import { useContext, useRef } from 'react'; +import AutoReloadOverlayBlockerContext from '../../contexts/AutoReloadOverlayBockerContext'; + +const useAutoReloadOverlayBlocker = () => { + const { lockApp, unlockApp } = useContext(AutoReloadOverlayBlockerContext); + // Use a ref so we can safely add the components or the fields + // to a hook dependencies array + const lockAppRef = useRef(lockApp); + const unlockAppRef = useRef(unlockApp); + + return { + lockAppWithAutoreload: lockAppRef.current, + unlockAppWithAutoreload: unlockAppRef.current, + }; +}; + +export default useAutoReloadOverlayBlocker; diff --git a/packages/core/helper-plugin/lib/src/hooks/useOverlayBlocker/index.js b/packages/core/helper-plugin/lib/src/hooks/useOverlayBlocker/index.js new file mode 100644 index 0000000000..9d06eaccce --- /dev/null +++ b/packages/core/helper-plugin/lib/src/hooks/useOverlayBlocker/index.js @@ -0,0 +1,20 @@ +/** + * + * useOverlayBlocker + * + */ + +import { useContext, useRef } from 'react'; +import OverlayBlockerContext from '../../contexts/OverlayBlockerContext'; + +const useOverlayBlocker = () => { + const { lockApp, unlockApp } = useContext(OverlayBlockerContext); + // Use a ref so we can safely add the components or the fields + // to a hook dependencies array + const lockAppRef = useRef(lockApp); + const unlockAppRef = useRef(unlockApp); + + return { lockApp: lockAppRef.current, unlockApp: unlockAppRef.current }; +}; + +export default useOverlayBlocker; diff --git a/packages/core/helper-plugin/lib/src/index.js b/packages/core/helper-plugin/lib/src/index.js index 52e916eec8..b2af23f031 100644 --- a/packages/core/helper-plugin/lib/src/index.js +++ b/packages/core/helper-plugin/lib/src/index.js @@ -78,7 +78,7 @@ export { default as ModalForm } from './components/FormModal'; export { default as ModalSection } from './components/ModalSection'; export { default as NotAllowedInput } from './components/NotAllowedInput'; export { default as NotFound } from './components/NotFound'; -export { default as OverlayBlocker } from './components/OverlayBlocker'; + export { default as PageFooter } from './components/PageFooter'; export { default as PluginHeader } from './components/PluginHeader'; export { default as RelationDPState } from './components/RelationDPState'; @@ -95,6 +95,7 @@ export { default as SettingsPageTitle } from './components/SettingsPageTitle'; export { default as FormBloc } from './components/FormBloc'; export { default as IntlInput } from './components/IntlInput'; export { default as SizedInput } from './components/SizedInput'; + export * from './components/Permissions'; // PopUpWarning @@ -105,7 +106,9 @@ export { default as PopUpWarningIcon } from './components/PopUpWarning/Icon'; export { default as PopUpWarningModal } from './components/PopUpWarning/StyledModal'; // Contexts +export { default as AutoReloadOverlayBockerContext } from './contexts/AutoReloadOverlayBockerContext'; export { default as NotificationsContext } from './contexts/NotificationsContext'; +export { default as OverlayBlockerContext } from './contexts/OverlayBlockerContext'; export { GlobalContext, GlobalContextProvider, useGlobalContext } from './contexts/GlobalContext'; export { default as UserContext } from './contexts/UserContext'; export { default as ContentManagerEditViewDataManagerContext } from './contexts/ContentManagerEditViewDataManagerContext'; @@ -119,6 +122,8 @@ export { default as useStrapiApp } from './hooks/useStrapiApp'; export { default as useUser } from './hooks/useUser'; export { default as useUserPermissions } from './hooks/useUserPermissions'; export { default as useQueryParams } from './hooks/useQueryParams'; +export { default as useOverlayBlocker } from './hooks/useOverlayBlocker'; +export { default as useAutoReloadOverlayBlocker } from './hooks/useAutoReloadOverlayBlocker'; // Providers export { default as LibraryProvider } from './providers/LibraryProvider'; diff --git a/packages/plugins/users-permissions/admin/src/containers/AdvancedSettings/index.js b/packages/plugins/users-permissions/admin/src/containers/AdvancedSettings/index.js index 0616128b6d..3945855277 100644 --- a/packages/plugins/users-permissions/admin/src/containers/AdvancedSettings/index.js +++ b/packages/plugins/users-permissions/admin/src/containers/AdvancedSettings/index.js @@ -10,6 +10,7 @@ import { useUserPermissions, request, useNotification, + useOverlayBlocker, } from '@strapi/helper-plugin'; import pluginPermissions from '../../permissions'; import { getTrad, getRequestURL } from '../../utils'; @@ -20,6 +21,7 @@ import reducer, { initialState } from './reducer'; const AdvancedSettingsPage = () => { const { formatMessage } = useIntl(); const toggleNotification = useNotification(); + const { lockApp, unlockApp } = useOverlayBlocker(); const [showModalWarning, setShowModalWarning] = useState(false); const pageTitle = formatMessage({ id: getTrad('HeaderNav.link.advancedSettings') }); const updatePermissions = useMemo(() => { @@ -93,7 +95,7 @@ const AdvancedSettingsPage = () => { type: 'ON_SUBMIT', }); - strapi.lockAppWithOverlay(); + lockApp(); await request(getRequestURL('advanced'), { method: 'PUT', body: modifiedData }); dispatch({ @@ -115,9 +117,9 @@ const AdvancedSettingsPage = () => { }); } - strapi.unlockApp(); + unlockApp(); }, - [modifiedData, toggleNotification] + [lockApp, modifiedData, toggleNotification, unlockApp] ); const handleConfirmReset = useCallback(() => { diff --git a/packages/plugins/users-permissions/admin/src/containers/EmailTemplates/index.js b/packages/plugins/users-permissions/admin/src/containers/EmailTemplates/index.js index e9e85d6fc6..d26a4e5644 100644 --- a/packages/plugins/users-permissions/admin/src/containers/EmailTemplates/index.js +++ b/packages/plugins/users-permissions/admin/src/containers/EmailTemplates/index.js @@ -10,6 +10,7 @@ import { request, getYupInnerErrors, useNotification, + useOverlayBlocker, } from '@strapi/helper-plugin'; import { Row } from 'reactstrap'; import pluginPermissions from '../../permissions'; @@ -25,6 +26,7 @@ const EmailTemplatesPage = () => { const { formatMessage } = useIntl(); const { emitEvent } = useGlobalContext(); const toggleNotification = useNotification(); + const { lockApp, unlockApp } = useOverlayBlocker(); const emitEventRef = useRef(emitEvent); const buttonSubmitRef = useRef(null); const pageTitle = formatMessage({ id: getTrad('HeaderNav.link.emailTemplates') }); @@ -101,7 +103,7 @@ const EmailTemplatesPage = () => { setIsSubmiting(true); await schema.validate(modifiedData[templateToEdit.id], { abortEarly: false }); - strapi.lockAppWithOverlay(); + lockApp(); try { emitEventRef.current('willEditEmailTemplates'); @@ -133,7 +135,7 @@ const EmailTemplatesPage = () => { errors = getYupInnerErrors(err); } finally { setIsSubmiting(false); - strapi.unlockApp(); + unlockApp(); } dispatchSetFormErrors(errors); @@ -145,6 +147,8 @@ const EmailTemplatesPage = () => { templateToEdit, handleToggle, toggleNotification, + lockApp, + unlockApp, ] ); diff --git a/packages/plugins/users-permissions/admin/src/containers/Providers/index.js b/packages/plugins/users-permissions/admin/src/containers/Providers/index.js index 0db46d42ba..e578fa37a6 100644 --- a/packages/plugins/users-permissions/admin/src/containers/Providers/index.js +++ b/packages/plugins/users-permissions/admin/src/containers/Providers/index.js @@ -10,6 +10,7 @@ import { getYupInnerErrors, request, useNotification, + useOverlayBlocker, } from '@strapi/helper-plugin'; import { get, upperFirst, has } from 'lodash'; import { Row } from 'reactstrap'; @@ -32,6 +33,7 @@ const ProvidersPage = () => { const [showForm, setShowForm] = useState(false); const [providerToEditName, setProviderToEditName] = useState(null); const toggleNotification = useNotification(); + const { lockApp, unlockApp } = useOverlayBlocker(); const updatePermissions = useMemo(() => { return { update: pluginPermissions.updateProviders }; @@ -140,7 +142,7 @@ const ProvidersPage = () => { try { await schema.validate(modifiedData[providerToEditName], { abortEarly: false }); - strapi.lockAppWithOverlay(); + lockApp(); try { emitEventRef.current('willEditAuthenticationProvider'); @@ -176,7 +178,7 @@ const ProvidersPage = () => { dispatchSetFormErrors(errors); setIsSubmiting(false); - strapi.unlockApp(); + unlockApp(); }, [ dispatchSetFormErrors, @@ -186,6 +188,8 @@ const ProvidersPage = () => { modifiedData, providerToEditName, toggleNotification, + lockApp, + unlockApp, ] ); diff --git a/packages/plugins/users-permissions/admin/src/containers/Roles/CreatePage/index.js b/packages/plugins/users-permissions/admin/src/containers/Roles/CreatePage/index.js index 1f4bf4f878..527148f25a 100644 --- a/packages/plugins/users-permissions/admin/src/containers/Roles/CreatePage/index.js +++ b/packages/plugins/users-permissions/admin/src/containers/Roles/CreatePage/index.js @@ -4,7 +4,12 @@ import { Header } from '@buffetjs/custom'; import { Padded } from '@buffetjs/core'; import { Formik } from 'formik'; import { useIntl } from 'react-intl'; -import { request, useGlobalContext, useNotification } from '@strapi/helper-plugin'; +import { + request, + useGlobalContext, + useNotification, + useOverlayBlocker, +} from '@strapi/helper-plugin'; import BaselineAlignement from '../../../components/BaselineAlignement'; import ContainerFluid from '../../../components/ContainerFluid'; import FormCard from '../../../components/FormBloc'; @@ -19,6 +24,7 @@ const CreatePage = () => { const { formatMessage } = useIntl(); const { emitEvent } = useGlobalContext(); const toggleNotification = useNotification(); + const { lockApp, unlockApp } = useOverlayBlocker(); const { goBack } = useHistory(); const [isSubmiting, setIsSubmiting] = useState(false); const { permissions, routes, policies, isLoading } = usePlugins(); @@ -56,7 +62,7 @@ const CreatePage = () => { }; const handleCreateRoleSubmit = data => { - strapi.lockAppWithOverlay(); + lockApp(); setIsSubmiting(true); const permissions = permissionsRef.current.getPermissions(); @@ -86,7 +92,7 @@ const CreatePage = () => { }) .finally(() => { setIsSubmiting(false); - strapi.unlockApp(); + unlockApp(); }); }; diff --git a/packages/plugins/users-permissions/admin/src/containers/Roles/EditPage/index.js b/packages/plugins/users-permissions/admin/src/containers/Roles/EditPage/index.js index 4e16ed7b54..9a7d928ce8 100644 --- a/packages/plugins/users-permissions/admin/src/containers/Roles/EditPage/index.js +++ b/packages/plugins/users-permissions/admin/src/containers/Roles/EditPage/index.js @@ -4,7 +4,7 @@ import { Padded } from '@buffetjs/core'; import { Formik } from 'formik'; import { useIntl } from 'react-intl'; import { useRouteMatch } from 'react-router-dom'; -import { request, useNotification } from '@strapi/helper-plugin'; +import { request, useNotification, useOverlayBlocker } from '@strapi/helper-plugin'; import BaselineAlignement from '../../../components/BaselineAlignement'; import ContainerFluid from '../../../components/ContainerFluid'; @@ -21,6 +21,7 @@ const EditPage = () => { const { formatMessage } = useIntl(); const [isSubmiting, setIsSubmiting] = useState(false); const toggleNotification = useNotification(); + const { lockApp, unlockApp } = useOverlayBlocker(); const { params: { id }, } = useRouteMatch(`/settings/${pluginId}/roles/:id`); @@ -60,7 +61,7 @@ const EditPage = () => { }; const handleCreateRoleSubmit = data => { - strapi.lockAppWithOverlay(); + lockApp(); setIsSubmiting(true); const permissions = permissionsRef.current.getPermissions(); @@ -88,7 +89,7 @@ const EditPage = () => { }) .finally(() => { setIsSubmiting(false); - strapi.unlockApp(); + unlockApp(); }); }; diff --git a/packages/plugins/users-permissions/admin/src/containers/Roles/ListPage/index.js b/packages/plugins/users-permissions/admin/src/containers/Roles/ListPage/index.js index 77a7743210..07f95bb7f6 100644 --- a/packages/plugins/users-permissions/admin/src/containers/Roles/ListPage/index.js +++ b/packages/plugins/users-permissions/admin/src/containers/Roles/ListPage/index.js @@ -10,6 +10,7 @@ import { request, useGlobalContext, useNotification, + useOverlayBlocker, } from '@strapi/helper-plugin'; import permissions from '../../../permissions'; @@ -24,7 +25,7 @@ const RoleListPage = () => { const { emitEvent } = useGlobalContext(); const { push } = useHistory(); const toggleNotification = useNotification(); - + const { lockApp, unlockApp } = useOverlayBlocker(); const [modalToDelete, setModalDelete] = useState(); const [shouldRefetchData, setShouldRefetchData] = useState(false); const [showModalConfirmButtonLoading, setModalButtonLoading] = useState(false); @@ -52,7 +53,7 @@ const RoleListPage = () => { }; const handleDelete = () => { - strapi.lockAppWithOverlay(); + lockApp(); setModalButtonLoading(true); @@ -77,7 +78,7 @@ const RoleListPage = () => { }) .finally(() => { setModalDelete(null); - strapi.unlockApp(); + unlockApp(); }); };