diff --git a/packages/core/content-type-builder/admin/src/components/AttributeOptions/AttributeOption/index.js b/packages/core/content-type-builder/admin/src/components/AttributeOptions/AttributeOption/index.js index 330d4351e0..50aef213a4 100644 --- a/packages/core/content-type-builder/admin/src/components/AttributeOptions/AttributeOption/index.js +++ b/packages/core/content-type-builder/admin/src/components/AttributeOptions/AttributeOption/index.js @@ -7,43 +7,25 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import { useHistory } from 'react-router-dom'; -import { useTracking, useQueryParams } from '@strapi/helper-plugin'; import { Box } from '@strapi/parts/Box'; import { Row } from '@strapi/parts/Row'; import { Text } from '@strapi/parts/Text'; +import useFormModalNavigation from '../../../hooks/useFormModalNavigation'; import getTrad from '../../../utils/getTrad'; -import makeSearch from '../../../utils/makeSearch'; import AttributeIcon from '../../AttributeIcon'; import BoxWrapper from './BoxWrapper'; const AttributeOption = ({ type }) => { - const { push } = useHistory(); - const { trackUsage } = useTracking(); const { formatMessage } = useIntl(); - const [{ query }] = useQueryParams(); + + const { onClickSelectField } = useFormModalNavigation(); const handleClick = () => { - // FIXME refacto - const forTarget = query.forTarget || null; - const targetUid = query.targetUid || null; + const step = type === 'component' ? '1' : null; - const search = makeSearch({ - modalType: 'attribute', - actionType: 'create', - settingType: 'base', - forTarget, - targetUid, + onClickSelectField({ attributeType: type, - step: type === 'component' ? '1' : null, - }); - - if (forTarget === 'contentType') { - trackUsage('didSelectContentTypeFieldType', { type }); - } - - push({ - search, + step, }); }; diff --git a/packages/core/content-type-builder/admin/src/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.js b/packages/core/content-type-builder/admin/src/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.js index e776ddb224..42a895068a 100644 --- a/packages/core/content-type-builder/admin/src/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.js +++ b/packages/core/content-type-builder/admin/src/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.js @@ -4,12 +4,10 @@ import isEmpty from 'lodash/isEmpty'; import sortBy from 'lodash/sortBy'; import toLower from 'lodash/toLower'; import matchSorter from 'match-sorter'; -import { useHistory } from 'react-router-dom'; import useDataManager from '../../hooks/useDataManager'; import useFormModalNavigation from '../../hooks/useFormModalNavigation'; import pluginId from '../../pluginId'; import getTrad from '../../utils/getTrad'; -import makeSearch from '../../utils/makeSearch'; const useContentTypeBuilderMenu = () => { const { @@ -21,9 +19,8 @@ const useContentTypeBuilderMenu = () => { } = useDataManager(); const toggleNotification = useNotification(); const { trackUsage } = useTracking(); - const { push } = useHistory(); const [search, setSearch] = useState(''); - const { onOpenModal } = useFormModalNavigation(); + const { onOpenModalCreateSchema, onOpenModalEditCategory } = useFormModalNavigation(); const componentsData = sortBy( Object.keys(componentsGroupedByCategory).map(category => ({ @@ -33,14 +30,11 @@ const useContentTypeBuilderMenu = () => { onClickEdit: (e, data) => { e.stopPropagation(); - const search = makeSearch({ - actionType: 'edit', - modalType: 'editCategory', - categoryName: data.name, - settingType: 'base', - }); - - push({ search }); + if (canOpenModalCreateCTorComponent) { + onOpenModalEditCategory(data.name); + } else { + toggleNotificationCannotCreateSchema(); + } }, links: sortBy( componentsGroupedByCategory[category].map(compo => ({ @@ -58,16 +52,6 @@ const useContentTypeBuilderMenu = () => { !Object.keys(contentTypes).some(ct => contentTypes[ct].isTemporary === true) && !Object.keys(components).some(component => components[component].isTemporary === true); - const toggleNotificationCannotCreateSchema = () => { - toggleNotification({ - type: 'info', - message: { - id: `${getTrad('notification.info.creating.notSaved')}`, - defaultMessage: 'Please save your work before creating a new collection type or component', - }, - }); - }; - const handleClickOpenModalCreateCollectionType = () => { if (canOpenModalCreateCTorComponent) { trackUsage(`willCreateContentType`); @@ -80,14 +64,7 @@ const useContentTypeBuilderMenu = () => { forTarget: 'contentType', }; - onOpenModal(nextState); - - // FIXME: to remove - const search = makeSearch(nextState); - - push({ - search, - }); + onOpenModalCreateSchema(nextState); } else { toggleNotificationCannotCreateSchema(); } @@ -105,34 +82,12 @@ const useContentTypeBuilderMenu = () => { forTarget: 'contentType', }; - const search = makeSearch(nextState); - - onOpenModal(nextState); - - push({ - search, - }); + onOpenModalCreateSchema(nextState); } else { toggleNotificationCannotCreateSchema(); } }; - // FIXME : open modal edit - // const handleClickOpenModalEditCategory = categoryName => { - // if (canOpenModalCreateCTorComponent) { - // const search = makeSearch({ - // actionType: 'edit', - // modalType: 'editCategory', - // categoryName, - // settingType: 'base', - // }); - - // push({ search }); - // } else { - // toggleNotificationCannotCreateSchema(); - // } - // }; - const handleClickOpenModalCreateComponent = () => { if (canOpenModalCreateCTorComponent) { trackUsage('willCreateComponent'); @@ -145,17 +100,22 @@ const useContentTypeBuilderMenu = () => { forTarget: 'component', }; - onOpenModal(nextState); - - const search = makeSearch(nextState); - push({ - search, - }); + onOpenModalCreateSchema(nextState); } else { toggleNotificationCannotCreateSchema(); } }; + const toggleNotificationCannotCreateSchema = () => { + toggleNotification({ + type: 'info', + message: { + id: `${getTrad('notification.info.creating.notSaved')}`, + defaultMessage: 'Please save your work before creating a new collection type or component', + }, + }); + }; + const displayedContentTypes = sortedContentTypesList.filter(obj => obj.visible); const data = [ diff --git a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/index.js b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/index.js index 12e3e43015..b95d43071e 100644 --- a/packages/core/content-type-builder/admin/src/components/DataManagerProvider/index.js +++ b/packages/core/content-type-builder/admin/src/components/DataManagerProvider/index.js @@ -12,15 +12,15 @@ import { useRBACProvider, } from '@strapi/helper-plugin'; import { useIntl } from 'react-intl'; -import { useHistory, useLocation, useRouteMatch, Redirect } from 'react-router-dom'; +import { useLocation, useRouteMatch, Redirect } from 'react-router-dom'; import { connect, useDispatch } from 'react-redux'; import { compose } from 'redux'; import DataManagerContext from '../../contexts/DataManagerContext'; +import useFormModalNavigation from '../../hooks/useFormModalNavigation'; import getTrad from '../../utils/getTrad'; import makeUnique from '../../utils/makeUnique'; import pluginId from '../../pluginId'; import FormModal from '../FormModal'; -import FormModalNavigationProvider from '../FormModalNavigationProvider'; import createDataObject from './utils/createDataObject'; import createModifiedDataSchema from './utils/createModifiedDataSchema'; import retrieveSpecificInfoFromComponents from './utils/retrieveSpecificInfoFromComponents'; @@ -70,9 +70,8 @@ const DataManagerProvider = ({ const { formatMessage } = useIntl(); const { trackUsage } = useTracking(); const { refetchPermissions } = useRBACProvider(); - const { pathname } = useLocation(); - const { push } = useHistory(); + const { onCloseModal } = useFormModalNavigation(); const contentTypeMatch = useRouteMatch(`/plugins/${pluginId}/content-types/:uid`); const componentMatch = useRouteMatch( `/plugins/${pluginId}/component-categories/:categoryUid/:componentUid` @@ -230,7 +229,7 @@ const DataManagerProvider = ({ }) ); // Close the modal - push({ search: '' }); + onCloseModal(); if (userConfirm) { lockAppWithAutoreload(); @@ -269,7 +268,7 @@ const DataManagerProvider = ({ ); // Close the modal - push({ search: '' }); + onCloseModal(); if (userConfirm) { if (isTemporary) { @@ -311,7 +310,7 @@ const DataManagerProvider = ({ const requestURL = `/${pluginId}/component-categories/${categoryUid}`; // Close the modal - push({ search: '' }); + onCloseModal(); // Lock the app lockAppWithAutoreload(); @@ -544,7 +543,7 @@ const DataManagerProvider = ({ updateSchema, }} > - + <> {isLoadingForDataToBeSet ? ( ) : ( @@ -553,7 +552,7 @@ const DataManagerProvider = ({ {isInDevelopmentMode && } )} - + ); }; diff --git a/packages/core/content-type-builder/admin/src/components/FormModalNavigationProvider/index.js b/packages/core/content-type-builder/admin/src/components/FormModalNavigationProvider/index.js index 093fbe0d75..f1bff989a7 100644 --- a/packages/core/content-type-builder/admin/src/components/FormModalNavigationProvider/index.js +++ b/packages/core/content-type-builder/admin/src/components/FormModalNavigationProvider/index.js @@ -1,24 +1,197 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; +import { useHistory } from 'react-router-dom'; +import { useTracking } from '@strapi/helper-plugin'; import FormModalNavigationContext from '../../contexts/FormModalNavigationContext'; +import makeSearch from '../../utils/makeSearch'; import { INITIAL_STATE_DATA } from './constants'; const FormModalNavigationProvider = ({ children }) => { const [state, setFormModalNavigationState] = useState(INITIAL_STATE_DATA); + const { trackUsage } = useTracking(); + // FIXME + const { push } = useHistory(); - const onOpenModal = nextState => { + const onClickSelectField = ({ attributeType, step }) => { + if (state.forTarget === 'contentType') { + trackUsage('didSelectContentTypeFieldType', { type: attributeType }); + } + + setFormModalNavigationState(prevState => { + return { + ...prevState, + actionType: 'create', + modalType: 'attribute', + settingType: 'base', + step, + attributeType, + }; + }); + + const search = { + modalType: 'attribute', + forTarget: state.forTarget, + targetUid: state.targetUid, + attributeType, + settingType: 'base', + step, + actionType: 'create', + }; + + push({ search: makeSearch(search) }); + }; + + const onOpenModalAddComponentsToDZ = ({ dynamicZoneTarget, targetUid }) => { + setFormModalNavigationState(prevState => { + return { + ...prevState, + dynamicZoneTarget, + targetUid, + modalType: 'addComponentToDynamicZone', + forTarget: 'contentType', + settingType: 'base', + step: '1', + actionType: 'edit', + }; + }); + + const search = { + modalType: 'addComponentToDynamicZone', + forTarget: 'contentType', + targetUid, + dynamicZoneTarget, + settingType: 'base', + step: '1', + actionType: 'edit', + }; + + push({ search: makeSearch(search) }); + }; + + const onOpenModalAddField = ({ forTarget, targetUid }) => { + setFormModalNavigationState(prevState => { + return { + ...prevState, + actionType: 'create', + forTarget, + targetUid, + modalType: 'chooseAttribute', + isOpen: true, + }; + }); + + // FIXME + const nextSearch = { + modalType: 'chooseAttribute', + forTarget, + targetUid, + actionType: 'create', + }; + + push({ search: makeSearch(nextSearch) }); + }; + + const onOpenModalCreateSchema = nextState => { setFormModalNavigationState(prevState => { return { ...prevState, ...nextState, isOpen: true }; }); + + push({ search: makeSearch(nextState) }); + }; + + const onOpenModalEditCategory = categoryName => { + setFormModalNavigationState(prevState => { + return { + ...prevState, + categoryName, + isOpen: true, + }; + }); + + const nextSearch = { + actionType: 'edit', + modalType: 'editCategory', + categoryName, + settingType: 'base', + }; + + push({ search: makeSearch(nextSearch) }); + }; + + const onOpenModalEditField = ({ forTarget, targetUid, attributeName, attributeType, step }) => { + setFormModalNavigationState(prevState => { + return { + ...prevState, + modalType: 'attribute', + actionType: 'edit', + settingType: 'base', + forTarget, + targetUid, + attributeName, + attributeType, + step, + isOpen: true, + }; + }); + + const nextSearch = { + modalType: 'attribute', + actionType: 'edit', + settingType: 'base', + forTarget, + targetUid, + attributeName, + attributeType, + step, + }; + + push({ search: makeSearch(nextSearch) }); + }; + + const onOpenModalEditSchema = ({ modalType, forTarget, targetUid }) => { + setFormModalNavigationState(prevState => { + return { + ...prevState, + modalType, + actionType: 'edit', + settingType: 'base', + forTarget, + targetUid, + isOpen: true, + }; + }); + + const nextSearch = { + modalType, + actionType: 'edit', + settingType: 'base', + forTarget, + targetUid, + }; + + push({ search: makeSearch(nextSearch) }); }; const onCloseModal = () => { setFormModalNavigationState(INITIAL_STATE_DATA); + + push({ search: '' }); }; return ( {children} diff --git a/packages/core/content-type-builder/admin/src/components/List/index.js b/packages/core/content-type-builder/admin/src/components/List/index.js index 55cabc9414..bf4c458581 100644 --- a/packages/core/content-type-builder/admin/src/components/List/index.js +++ b/packages/core/content-type-builder/admin/src/components/List/index.js @@ -14,7 +14,7 @@ import { TableLabel } from '@strapi/parts/Text'; import { Table, Thead, Tr, Th, TFooter } from '@strapi/parts/Table'; import AddIcon from '@strapi/icons/AddIcon'; import { useIntl } from 'react-intl'; -import useListView from '../../hooks/useListView'; +import useFormModalNavigation from '../../hooks/useFormModalNavigation'; import useDataManager from '../../hooks/useDataManager'; import DynamicZoneList from '../DynamicZoneList'; import ComponentList from '../ComponentList'; @@ -42,11 +42,11 @@ function List({ const { trackUsage } = useTracking(); const { isInDevelopmentMode, modifiedData, isInContentTypeView } = useDataManager(); - const { openModalAddField } = useListView(); + const { onOpenModalAddField } = useFormModalNavigation(); const onClickAddField = () => { trackUsage('hasClickedCTBAddFieldBanner'); - openModalAddField(editTarget, targetUid); + onOpenModalAddField({ forTarget: editTarget, targetUid }); }; if (!targetUid) { diff --git a/packages/core/content-type-builder/admin/src/contexts/ListViewContext.js b/packages/core/content-type-builder/admin/src/contexts/ListViewContext.js deleted file mode 100644 index 9fe426405d..0000000000 --- a/packages/core/content-type-builder/admin/src/contexts/ListViewContext.js +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from 'react'; - -const ListViewContext = createContext(); - -export default ListViewContext; diff --git a/packages/core/content-type-builder/admin/src/hooks/useListView.js b/packages/core/content-type-builder/admin/src/hooks/useListView.js deleted file mode 100644 index 559873bf15..0000000000 --- a/packages/core/content-type-builder/admin/src/hooks/useListView.js +++ /dev/null @@ -1,6 +0,0 @@ -import { useContext } from 'react'; -import ListViewContext from '../contexts/ListViewContext'; - -const useListView = () => useContext(ListViewContext); - -export default useListView; diff --git a/packages/core/content-type-builder/admin/src/pages/App/index.js b/packages/core/content-type-builder/admin/src/pages/App/index.js index 0b78514d83..96c2ac76b0 100644 --- a/packages/core/content-type-builder/admin/src/pages/App/index.js +++ b/packages/core/content-type-builder/admin/src/pages/App/index.js @@ -11,6 +11,7 @@ import { Layout } from '@strapi/parts/Layout'; import pluginPermissions from '../../permissions'; import pluginId from '../../pluginId'; import DataManagerProvider from '../../components/DataManagerProvider'; +import FormModalNavigationProvider from '../../components/FormModalNavigationProvider'; import RecursivePath from '../RecursivePath'; import icons from './utils/icons.json'; import ContentTypeBuilderNav from '../../components/ContentTypeBuilderNav'; @@ -20,23 +21,25 @@ const ListView = lazy(() => import('../ListView')); const App = () => { return ( - - }> - }> - - - - - - - - + + + }> + }> + + + + + + + + + ); }; diff --git a/packages/core/content-type-builder/admin/src/pages/ListView/index.js b/packages/core/content-type-builder/admin/src/pages/ListView/index.js index d85e1eb577..567e313231 100644 --- a/packages/core/content-type-builder/admin/src/pages/ListView/index.js +++ b/packages/core/content-type-builder/admin/src/pages/ListView/index.js @@ -19,14 +19,13 @@ import has from 'lodash/has'; import isEqual from 'lodash/isEqual'; import upperFirst from 'lodash/upperFirst'; import { useIntl } from 'react-intl'; -import { Prompt, useHistory, useRouteMatch } from 'react-router-dom'; +import { Prompt, useRouteMatch } from 'react-router-dom'; import List from '../../components/List'; import ListRow from '../../components/ListRow'; -import ListViewContext from '../../contexts/ListViewContext'; import useDataManager from '../../hooks/useDataManager'; +import useFormModalNavigation from '../../hooks/useFormModalNavigation'; import getAttributeDisplayedType from '../../utils/getAttributeDisplayedType'; import getTrad from '../../utils/getTrad'; -import makeSearch from '../../utils/makeSearch'; import LinkToCMSettingsView from './LinkToCMSettingsView'; /* eslint-disable indent */ @@ -41,11 +40,17 @@ const ListView = () => { } = useDataManager(); const { formatMessage } = useIntl(); const { trackUsage } = useTracking(); - const { push } = useHistory(); - // const { search } = useLocation(); + // const [enablePrompt, togglePrompt] = useState(true); const match = useRouteMatch('/plugins/content-type-builder/:kind/:currentUID'); + const { + onOpenModalAddComponentsToDZ, + onOpenModalAddField, + onOpenModalEditField, + onOpenModalEditSchema, + } = useFormModalNavigation(); + // useEffect(() => { // if (search === '') { // togglePrompt(true); @@ -67,60 +72,26 @@ const ListView = () => { const contentTypeKind = get(modifiedData, [firstMainDataPath, 'schema', 'kind'], null); const attributes = get(modifiedData, mainDataTypeAttributesPath, []); - // const attributesLength = attributes.length; const currentDataName = get(initialData, [firstMainDataPath, 'schema', 'name'], ''); const isFromPlugin = has(initialData, [firstMainDataPath, 'plugin']); // const hasModelBeenModified = !isEqual(modifiedData, initialData); const forTarget = isInContentTypeView ? 'contentType' : 'component'; - const handleClickAddField = async (forTarget, targetUid) => { - // disable the prompt - // await wait(); - - const searchObj = { - modalType: 'chooseAttribute', - forTarget, - targetUid, - }; - - push({ search: makeSearch(searchObj) }); - }; - - const handleClickAddComponentToDZ = async dzName => { - const search = { - modalType: 'addComponentToDynamicZone', - forTarget: 'contentType', - targetUid, - dynamicZoneTarget: dzName, - settingType: 'base', - step: '1', - actionType: 'edit', - }; - - // await wait(); - - push({ search: makeSearch(search, true) }); + const handleClickAddComponentToDZ = dynamicZoneTarget => { + onOpenModalAddComponentsToDZ({ dynamicZoneTarget, targetUid }); }; const handleClickEditField = async (forTarget, targetUid, attributeName, type) => { const attributeType = getAttributeDisplayedType(type); + const step = type === 'component' ? '2' : null; - // await wait(); - - const search = { - modalType: 'attribute', - actionType: 'edit', - settingType: 'base', + onOpenModalEditField({ forTarget, targetUid, attributeName, attributeType, - step: type === 'component' ? '2' : null, - }; - - // await wait(); - - push({ search: makeSearch(search, true) }); + step, + }); }; const getDescription = () => { @@ -134,12 +105,6 @@ const ListView = () => { ); }; - // FIXME - // const wait = async () => { - // togglePrompt(false); - - // return new Promise(resolve => setTimeout(resolve, 100)); - // }; let label = get(modifiedData, [firstMainDataPath, 'schema', 'name'], ''); const kind = get(modifiedData, [firstMainDataPath, 'schema', 'kind'], ''); @@ -152,18 +117,7 @@ const ListView = () => { }); } - // const listTitle = [ - // formatMessage( - // { - // id: `${pluginId}.table.attributes.title.${attributesLength > 1 ? 'plural' : 'singular'}`, - // }, - // { number: attributesLength } - // ), - // ]; - const onEdit = () => { - // await wait(); - const contentType = kind || firstMainDataPath; if (contentType === 'collectionType') { @@ -173,109 +127,103 @@ const ListView = () => { trackUsage('willEditNameOfSingleType'); } - push({ - search: makeSearch({ - modalType: firstMainDataPath, - actionType: 'edit', - settingType: 'base', - forTarget: firstMainDataPath, - targetUid, - }), + onOpenModalEditSchema({ + modalType: firstMainDataPath, + forTarget: firstMainDataPath, + targetUid, }); }; return ( - - <> - - - {/* DON'T display the add field button when the content type has not been created */} - {!isCreatingFirstContentType && ( - - )} + <> + + + {/* DON'T display the add field button when the content type has not been created */} + {!isCreatingFirstContentType && ( - - ) - } - secondaryAction={ - isInDevelopmentMode && - !isFromPlugin && - !isCreatingFirstContentType && ( - - ) - } - title={upperFirst(label)} - subtitle={getDescription()} - navigationAction={ - } to="/plugins/content-type-builder/"> + + ) + } + secondaryAction={ + isInDevelopmentMode && + !isFromPlugin && + !isCreatingFirstContentType && ( + + ) + } + title={upperFirst(label)} + subtitle={getDescription()} + navigationAction={ + } to="/plugins/content-type-builder/"> + {formatMessage({ + id: 'app.components.go-back', + defaultMessage: 'Go back', + })} + + } + /> + + + + + - - - - - + + + + } + addComponentToDZ={handleClickAddComponentToDZ} + targetUid={targetUid} + dataType={forTarget} + dataTypeName={currentDataName} + mainTypeName={currentDataName} + editTarget={forTarget} + isMain + /> + + + + ); };