Remove search from components except FormModal

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2021-10-18 14:07:05 +02:00
parent d0f6dcad75
commit cb2bf64a68
9 changed files with 330 additions and 276 deletions

View File

@ -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,
});
};

View File

@ -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 = [

View File

@ -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,
}}
>
<FormModalNavigationProvider>
<>
{isLoadingForDataToBeSet ? (
<LoadingIndicatorPage />
) : (
@ -553,7 +552,7 @@ const DataManagerProvider = ({
{isInDevelopmentMode && <FormModal />}
</>
)}
</FormModalNavigationProvider>
</>
</DataManagerContext.Provider>
);
};

View File

@ -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 (
<FormModalNavigationContext.Provider
value={{ ...state, onCloseModal, onOpenModal, setFormModalNavigationState }}
value={{
...state,
onClickSelectField,
onCloseModal,
onOpenModalAddComponentsToDZ,
onOpenModalAddField,
onOpenModalCreateSchema,
onOpenModalEditCategory,
onOpenModalEditField,
onOpenModalEditSchema,
setFormModalNavigationState,
}}
>
{children}
</FormModalNavigationContext.Provider>

View File

@ -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) {

View File

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

View File

@ -1,6 +0,0 @@
import { useContext } from 'react';
import ListViewContext from '../contexts/ListViewContext';
const useListView = () => useContext(ListViewContext);
export default useListView;

View File

@ -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 (
<CheckPagePermissions permissions={pluginPermissions.main}>
<DataManagerProvider allIcons={icons}>
<Layout sideNav={<ContentTypeBuilderNav />}>
<Suspense fallback={<LoadingIndicatorPage />}>
<Switch>
<Route
path={`/plugins/${pluginId}/content-types/create-content-type`}
component={ListView}
/>
<Route path={`/plugins/${pluginId}/content-types/:uid`} component={ListView} />
<Route
path={`/plugins/${pluginId}/component-categories/:categoryUid`}
component={RecursivePath}
/>
</Switch>
</Suspense>
</Layout>
</DataManagerProvider>
<FormModalNavigationProvider>
<DataManagerProvider allIcons={icons}>
<Layout sideNav={<ContentTypeBuilderNav />}>
<Suspense fallback={<LoadingIndicatorPage />}>
<Switch>
<Route
path={`/plugins/${pluginId}/content-types/create-content-type`}
component={ListView}
/>
<Route path={`/plugins/${pluginId}/content-types/:uid`} component={ListView} />
<Route
path={`/plugins/${pluginId}/component-categories/:categoryUid`}
component={RecursivePath}
/>
</Switch>
</Suspense>
</Layout>
</DataManagerProvider>
</FormModalNavigationProvider>
</CheckPagePermissions>
);
};

View File

@ -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 (
<ListViewContext.Provider value={{ openModalAddField: handleClickAddField }}>
<>
<Prompt
message={formatMessage({ id: getTrad('prompt.unsaved') })}
// when={hasModelBeenModified && enablePrompt}
when={false}
/>
<HeaderLayout
id="title"
primaryAction={
isInDevelopmentMode && (
<Stack horizontal size={2}>
{/* DON'T display the add field button when the content type has not been created */}
{!isCreatingFirstContentType && (
<Button
startIcon={<AddIcon />}
variant="secondary"
onClick={() => {
handleClickAddField(forTarget, targetUid);
}}
>
{formatMessage({ id: getTrad('button.attributes.add.another') })}
</Button>
)}
<>
<Prompt
message={formatMessage({ id: getTrad('prompt.unsaved') })}
// when={hasModelBeenModified && enablePrompt}
when={false}
/>
<HeaderLayout
id="title"
primaryAction={
isInDevelopmentMode && (
<Stack horizontal size={2}>
{/* DON'T display the add field button when the content type has not been created */}
{!isCreatingFirstContentType && (
<Button
startIcon={<CheckIcon />}
onClick={() => submitData()}
type="submit"
disabled={isEqual(modifiedData, initialData)}
startIcon={<AddIcon />}
variant="secondary"
onClick={() => {
onOpenModalAddField({ forTarget, targetUid });
}}
>
{formatMessage({
id: getTrad('form.button.save'),
defaultMessage: 'Save',
})}
{formatMessage({ id: getTrad('button.attributes.add.another') })}
</Button>
</Stack>
)
}
secondaryAction={
isInDevelopmentMode &&
!isFromPlugin &&
!isCreatingFirstContentType && (
<Button startIcon={<EditIcon />} variant="tertiary" onClick={onEdit}>
)}
<Button
startIcon={<CheckIcon />}
onClick={() => submitData()}
type="submit"
disabled={isEqual(modifiedData, initialData)}
>
{formatMessage({
id: getTrad('app.utils.edit'),
defaultMessage: 'Edit',
id: getTrad('form.button.save'),
defaultMessage: 'Save',
})}
</Button>
)
}
title={upperFirst(label)}
subtitle={getDescription()}
navigationAction={
<Link startIcon={<BackIcon />} to="/plugins/content-type-builder/">
</Stack>
)
}
secondaryAction={
isInDevelopmentMode &&
!isFromPlugin &&
!isCreatingFirstContentType && (
<Button startIcon={<EditIcon />} variant="tertiary" onClick={onEdit}>
{formatMessage({
id: 'app.components.go-back',
defaultMessage: 'Go back',
id: getTrad('app.utils.edit'),
defaultMessage: 'Edit',
})}
</Link>
}
/>
<ContentLayout>
<Stack size={4}>
<Row justifyContent="flex-end">
<Stack horizontal size={2}>
<LinkToCMSettingsView
key="link-to-cm-settings-view"
targetUid={targetUid}
isTemporary={isTemporary}
isInContentTypeView={isInContentTypeView}
contentTypeKind={contentTypeKind}
/>
</Stack>
</Row>
<Box background="neutral0" shadow="filterShadow" hasRadius>
<List
items={attributes}
customRowComponent={props => <ListRow {...props} onClick={handleClickEditField} />}
addComponentToDZ={handleClickAddComponentToDZ}
</Button>
)
}
title={upperFirst(label)}
subtitle={getDescription()}
navigationAction={
<Link startIcon={<BackIcon />} to="/plugins/content-type-builder/">
{formatMessage({
id: 'app.components.go-back',
defaultMessage: 'Go back',
})}
</Link>
}
/>
<ContentLayout>
<Stack size={4}>
<Row justifyContent="flex-end">
<Stack horizontal size={2}>
<LinkToCMSettingsView
key="link-to-cm-settings-view"
targetUid={targetUid}
dataType={forTarget}
dataTypeName={currentDataName}
mainTypeName={currentDataName}
editTarget={forTarget}
isMain
isTemporary={isTemporary}
isInContentTypeView={isInContentTypeView}
contentTypeKind={contentTypeKind}
/>
</Box>
</Stack>
</ContentLayout>
</>
</ListViewContext.Provider>
</Stack>
</Row>
<Box background="neutral0" shadow="filterShadow" hasRadius>
<List
items={attributes}
customRowComponent={props => <ListRow {...props} onClick={handleClickEditField} />}
addComponentToDZ={handleClickAddComponentToDZ}
targetUid={targetUid}
dataType={forTarget}
dataTypeName={currentDataName}
mainTypeName={currentDataName}
editTarget={forTarget}
isMain
/>
</Box>
</Stack>
</ContentLayout>
</>
);
};