Migrate modal header

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2021-10-07 12:08:33 +02:00
parent e2fdcee602
commit 1d2f790d92
6 changed files with 670 additions and 545 deletions

View File

@ -2,7 +2,7 @@
"collectionName": "components_basic_simples",
"info": {
"name": "simple",
"icon": "address-card",
"icon": "ambulance",
"description": ""
},
"options": {},

View File

@ -2,7 +2,7 @@
"collectionName": "components_blog_test_comos",
"info": {
"name": "test comp",
"icon": "ad",
"icon": "air-freshener",
"description": ""
},
"options": {},

View File

@ -58,9 +58,11 @@ const IconBox = styled(Box)`
`;
const AttributeIcon = ({ type, ...rest }) => {
const Compo = iconByTypes[type];
const iconType = type === 'collectionType' ? 'contentType' : type;
if (!iconByTypes[type]) {
const Compo = iconByTypes[iconType];
if (!iconByTypes[iconType]) {
return null;
}

View File

@ -1,37 +1,45 @@
import React, { useCallback, useEffect, useRef, useState, useMemo } from 'react';
import {
HeaderModal,
HeaderModalTitle,
Modal,
ModalBody,
ModalFooter,
ModalForm,
PopUpWarning,
// HeaderModal,
// HeaderModalTitle,
// Modal,
// ModalBody,
// ModalFooter,
// ModalForm,
// PopUpWarning,
getYupInnerErrors,
useTracking,
useNotification,
useQuery,
useStrapiApp,
} from '@strapi/helper-plugin';
import { useIntl, FormattedMessage } from 'react-intl';
import { Button, Text, Padded } from '@buffetjs/core';
import { Inputs } from '@buffetjs/custom';
import { ModalLayout } from '@strapi/parts/ModalLayout';
import { useIntl } from 'react-intl';
import { useHistory, useLocation } from 'react-router-dom';
import { get, has, isEmpty, set, toLower, toString, upperFirst } from 'lodash';
import {
get,
has,
isEmpty,
set,
toLower,
// toString, upperFirst
} from 'lodash';
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
import pluginId from '../../pluginId';
import useDataManager from '../../hooks/useDataManager';
import AttributeOption from '../AttributeOption';
import BooleanBox from '../BooleanBox';
import ComponentIconPicker from '../ComponentIconPicker';
import CheckboxWithDescription from '../CheckboxWithDescription';
import CustomCheckbox from '../CustomCheckbox';
import ModalHeader from '../ModalHeader';
import HeaderModalNavContainer from '../HeaderModalNavContainer';
import RelationForm from '../RelationForm';
import HeaderNavLink from '../HeaderNavLink';
import WrapperSelect from '../WrapperSelect';
// New compos
import FormModalHeader from '../FormModalHeader';
// import AttributeOption from '../AttributeOption';
// import BooleanBox from '../BooleanBox';
// import ComponentIconPicker from '../ComponentIconPicker';
// import CheckboxWithDescription from '../CheckboxWithDescription';
// import CustomCheckbox from '../CustomCheckbox';
// import ModalHeader from '../ModalHeader';
// import HeaderModalNavContainer from '../HeaderModalNavContainer';
// import RelationForm from '../RelationForm';
// import HeaderNavLink from '../HeaderNavLink';
// import WrapperSelect from '../WrapperSelect';
import findAttribute from '../../utils/findAttribute';
import getTrad from '../../utils/getTrad';
import makeSearch from '../../utils/makeSearch';
@ -40,13 +48,16 @@ import {
createHeadersArray,
createHeadersObjectFromArray,
getAttributesToDisplay,
getModalTitleSubHeader,
getNextSearch,
// getModalTitleSubHeader,
// getNextSearch,
} from './utils';
import forms from './forms';
import { createComponentUid, createUid } from './utils/createUid';
import { NAVLINKS, INITIAL_STATE_DATA } from './utils/staticData';
import CustomButton from './CustomButton';
import {
// NAVLINKS,
INITIAL_STATE_DATA,
} from './utils/staticData';
// import CustomButton from './CustomButton';
import makeSelectFormModal from './selectors';
import {
SET_DATA_TO_EDIT,
@ -1047,21 +1058,22 @@ const FormModal = () => {
});
}
};
const handleToggle = () => {
const handleClosed = () => {
// Close the modal
push({ search: '' });
};
const onClosed = () => {
// Reset the state
setState(INITIAL_STATE_DATA);
// Reset the reducer
dispatch({
type: RESET_PROPS,
});
};
const onOpened = () => {
if (state.modalType === 'chooseAttribute') {
attributeOptionRef.current.focus();
}
};
// const onOpened = () => {
// if (state.modalType === 'chooseAttribute') {
// attributeOptionRef.current.focus();
// }
// };
const sendAdvancedTabEvent = tab => {
if (tab !== 'advanced') {
@ -1117,424 +1129,436 @@ const FormModal = () => {
// Styles
const modalBodyStyle = isPickingAttribute ? { paddingTop: '0.5rem', paddingBottom: '3rem' } : {};
if (!isOpen) {
return null;
}
return (
<>
<Modal
isOpen={isOpen}
onOpened={onOpened}
onClosed={onClosed}
onToggle={handleToggle}
withoverflow={toString(
state.modalType === 'addComponentToDynamicZone' ||
(state.modalType === 'attribute' && state.attributeType === 'media')
)}
>
<HeaderModal>
<ModalHeader headerId={state.headerId} headers={headers} />
<section>
<HeaderModalTitle>
<FormattedMessage
id={getModalTitleSubHeader(state)}
values={{
type: upperFirst(
formatMessage({
id: getTrad(`attribute.${state.attributeType}`),
})
),
name: upperFirst(state.attributeName),
step: state.step,
}}
>
{msg => <span>{upperFirst(msg)}</span>}
</FormattedMessage>
{!isPickingAttribute && (
<>
<div className="settings-tabs">
<HeaderModalNavContainer>
{NAVLINKS.map((link, index) => {
return (
<HeaderNavLink
// The advanced tab is disabled when adding an existing component
// step 1
isDisabled={index === 1 && shouldDisableAdvancedTab()}
isActive={state.settingType === link.id}
key={link.id}
{...link}
onClick={() => {
setState(prev => ({
...prev,
settingType: link.id,
}));
sendAdvancedTabEvent(link.id);
push({ search: getNextSearch(link.id, state) });
}}
nextTab={index === NAVLINKS.length - 1 ? 0 : index + 1}
/>
);
})}
</HeaderModalNavContainer>
</div>
<hr />
</>
)}
</HeaderModalTitle>
</section>
</HeaderModal>
<form onSubmit={handleSubmit}>
<ModalForm>
<ModalBody style={modalBodyStyle}>
<div className="container-fluid">
{isPickingAttribute
? displayedAttributes.map((row, i) => {
return (
<div key={i} className="row">
{i === 1 && (
<hr
style={{
width: 'calc(100% - 30px)',
marginBottom: 16,
marginTop: 19,
borderColor: '#F0F3F8',
}}
/>
)}
{row.map((attr, index) => {
const tabIndex =
i === 0 ? index : displayedAttributes[0].length + index;
return (
<AttributeOption
key={attr}
tabIndex={tabIndex}
isDisplayed
onClick={() => {}}
ref={i === 0 && index === 0 ? attributeOptionRef : null}
type={attr}
/>
);
})}
</div>
);
})
: form({
data: modifiedData,
type: state.attributeType,
step: state.step,
actionType: state.actionType,
attributes,
extensions: ctbFormsAPI,
forTarget: state.forTarget,
contentTypeSchema: allDataSchema.contentType || {},
}).items.map((row, index) => {
return (
<div className="row" key={index}>
{row.map((input, i) => {
// The divider type is used mainly the advanced tab
// It is the one responsible for displaying the settings label
if (input.type === 'divider' || input.type === 'dividerDraftPublish') {
const tradId =
input.type === 'divider'
? 'form.attribute.item.settings.name'
: 'form.contentType.divider.draft-publish';
return (
<div className="col-12" key="divider">
<Padded bottom size="smd">
<div style={{ paddingTop: 3 }} />
<Text
fontSize="xs"
color="grey"
fontWeight="bold"
textTransform="uppercase"
>
<FormattedMessage id={getTrad(tradId)}>
{txt => txt}
</FormattedMessage>
</Text>
</Padded>
</div>
);
}
// The spacer type is used mainly to align the icon picker...
if (input.type === 'spacer') {
return <div key="spacer" style={{ height: 8 }} />;
}
// The spacer type is used mainly to align the icon picker...
if (input.type === 'spacer-small') {
return <div key={`${index}.${i}`} style={{ height: 4 }} />;
}
if (input.type === 'spacer-medium') {
return <div key={`${index}.${i}`} style={{ height: 8 }} />;
}
// This type is used in the addComponentToDynamicZone modal when selecting the option add an existing component
// It pushes select the components to the right
if (input.type === 'pushRight') {
return <div key={`${index}.${i}`} className={`col-${input.size}`} />;
}
if (input.type === 'relation') {
return (
<RelationForm
key="relation"
mainBoxHeader={get(headers, [0, 'label'], '')}
modifiedData={modifiedData}
naturePickerType={state.forTarget}
onChange={handleChange}
errors={formErrors}
/>
);
}
// When extending the yup schema of an existing field (like in https://github.com/strapi/strapi/blob/293ff3b8f9559236609d123a2774e3be05ce8274/packages/strapi-plugin-i18n/admin/src/index.js#L52)
// and triggering a yup validation error in the UI (missing a required field for example)
// We got an object that looks like: formErrors = { "pluginOptions.i18n.localized": {...} }
// In order to deal with this error, we can't rely on lodash.get to resolve this key
// - lodash will try to access {pluginOptions: {i18n: {localized: true}}})
// - and we just want to access { "pluginOptions.i18n.localized": {...} }
// NOTE: this is a hack
const pluginOptionError = Object.keys(formErrors).find(
key => key === input.name
);
// Retrieve the error for a specific input
const errorId = pluginOptionError
? formErrors[pluginOptionError].id
: get(
formErrors,
[
...input.name
.split('.')
// The filter here is used when creating a component
// in the component step 1 modal
// Since the component info is stored in the
// componentToCreate object we can access the error
// By removing the key
.filter(key => key !== 'componentToCreate'),
'id',
],
null
);
const retrievedValue = get(modifiedData, input.name, '');
let value;
// Condition for the boolean default value
// The radio input doesn't accept false, true or null as value
// So we pass them as string
// This way the data stays accurate and we don't have to operate
// any data mutation
if (input.name === 'default' && state.attributeType === 'boolean') {
value = toString(retrievedValue);
// Same here for the enum
} else if (input.name === 'enum' && Array.isArray(retrievedValue)) {
value = retrievedValue.join('\n');
} else if (input.name === 'uid') {
value = input.value;
} else if (input.name === 'allowedTypes' && retrievedValue === '') {
value = null;
} else if (input.type === 'checkbox' && !retrievedValue) {
value = false;
} else {
value = retrievedValue;
}
return (
<div className={`col-${input.size || 6}`} key={input.name}>
<Inputs
{...input}
modifiedData={modifiedData}
addComponentsToDynamicZone={handleClickAddComponentsToDynamicZone}
changeMediaAllowedTypes={handleChangeMediaAllowedTypes}
customInputs={{
allowedTypesSelect: WrapperSelect,
checkbox: CheckboxWithDescription,
componentIconPicker: ComponentIconPicker,
componentSelect: WrapperSelect,
creatableSelect: WrapperSelect,
customCheckboxWithChildren: CustomCheckbox,
booleanBox: BooleanBox,
...inputsFromPlugins,
}}
isCreating={isCreating}
// Props for the componentSelect
isCreatingComponentWhileAddingAField={
isCreatingComponentWhileAddingAField
}
// Props for the componentSelect
// Since the component is created after adding it to a type
// its name and category can't be retrieved from the data manager
componentCategoryNeededForAddingAfieldWhileCreatingAComponent={get(
componentToCreate,
'category',
null
)}
// Props for the componentSelect same explanation
componentNameNeededForAddingAfieldWhileCreatingAComponent={get(
componentToCreate,
'name',
null
)}
isAddingAComponentToAnotherComponent={
state.forTarget === 'components' ||
state.forTarget === 'component'
}
value={value}
error={isEmpty(errorId) ? null : formatMessage({ id: errorId })}
onChange={handleChange}
onBlur={() => {}}
description={
get(input, 'description.id', null)
? formatMessage(input.description)
: input.description
}
placeholder={
get(input, 'placeholder.id', null)
? formatMessage(input.placeholder)
: input.placeholder
}
label={
get(input, 'label.id', null)
? formatMessage(input.label)
: input.label
}
/>
</div>
);
})}
</div>
);
})}
</div>
</ModalBody>
</ModalForm>
{!isPickingAttribute && (
<ModalFooter>
<section style={{ alignItems: 'center' }}>
<Button type="button" color="cancel" onClick={handleToggle}>
{formatMessage({
id: 'app.components.Button.cancel',
})}
</Button>
<div>
{isCreatingAttribute && !isInFirstComponentStep && (
<Button
type={isCreating ? 'button' : 'submit'}
color="success"
onClick={e => {
handleSubmit(e, false);
}}
style={{ marginRight: '10px' }}
>
{formatMessage({ id: 'form.button.finish' })}
</Button>
)}
{(isCreatingContentType || isCreatingComponent) && !isCreating && (
<Button
type="button"
color="delete"
onClick={e => {
e.preventDefault();
deleteData();
}}
style={{ marginRight: '10px' }}
>
{formatMessage({ id: getTrad('form.button.delete') })}
</Button>
)}
{isEditingCategory && (
<Button
type="button"
color="delete"
onClick={e => {
e.preventDefault();
deleteCategory(initialData.name);
}}
style={{ marginRight: '10px' }}
>
{formatMessage({ id: getTrad('form.button.delete') })}
</Button>
)}
{isCreating && state.attributeType === 'dynamiczone' && (
<CustomButton
type={isCreating ? 'submit' : 'button'}
color={
(isCreatingContentType ||
isCreatingComponent ||
isEditingCategory ||
(state.modalType === 'addComponentToDynamicZone' &&
state.step === '1' &&
!isCreatingComponentFromAView)) &&
!isCreating
? 'success'
: 'primary'
}
onClick={e => handleSubmit(e, true)}
icon={
(isCreatingAttribute &&
!isCreatingComponentFromAView &&
state.step !== '1') ||
(state.modalType === 'addComponentToDynamicZone' &&
isCreatingComponentFromAView) ||
(isCreatingComponentFromAView && state.step === '2')
}
>
{getButtonSubmitMessage()}
</CustomButton>
)}
{state.attributeType !== 'dynamiczone' && (
<CustomButton
type={isCreating ? 'submit' : 'button'}
color={
(isCreatingContentType ||
isCreatingComponent ||
isEditingCategory ||
(state.modalType === 'addComponentToDynamicZone' &&
state.step === '1' &&
!isCreatingComponentFromAView)) &&
!isCreating
? 'success'
: 'primary'
}
onClick={e => handleSubmit(e, true)}
icon={
(isCreatingAttribute &&
!isCreatingComponentFromAView &&
state.step !== '1') ||
(state.modalType === 'addComponentToDynamicZone' &&
isCreatingComponentFromAView) ||
(isCreatingComponentFromAView && state.step === '2')
}
>
{getButtonSubmitMessage()}
</CustomButton>
)}
</div>
</section>
</ModalFooter>
)}
</form>
</Modal>
{/* CONFIRM MODAL FOR DRAFT AND PUBLISH */}
<PopUpWarning
isOpen={showConfirmModal}
onConfirm={handleConfirmDisableDraftAndPublish}
toggleModal={toggleConfirmModal}
popUpWarningType="danger"
content={{
message: getTrad('popUpWarning.draft-publish.message'),
secondMessage: getTrad('popUpWarning.draft-publish.second-message'),
confirm: getTrad('popUpWarning.draft-publish.button.confirm'),
}}
/>
<ModalLayout onClose={handleClosed} labelledBy="title">
<FormModalHeader headerId={state.headerId} headers={headers} />
</ModalLayout>
</>
);
// return (
// <>
// <Modal
// isOpen={isOpen}
// onOpened={onOpened}
// onClosed={onClosed}
// onToggle={handleClosed}
// withoverflow={toString(
// state.modalType === 'addComponentToDynamicZone' ||
// (state.modalType === 'attribute' && state.attributeType === 'media')
// )}
// >
// <HeaderModal>
// <ModalHeader headerId={state.headerId} headers={headers} />
// <section>
// <HeaderModalTitle>
// <FormattedMessage
// id={getModalTitleSubHeader(state)}
// values={{
// type: upperFirst(
// formatMessage({
// id: getTrad(`attribute.${state.attributeType}`),
// })
// ),
// name: upperFirst(state.attributeName),
// step: state.step,
// }}
// >
// {msg => <span>{upperFirst(msg)}</span>}
// </FormattedMessage>
// {!isPickingAttribute && (
// <>
// <div className="settings-tabs">
// <HeaderModalNavContainer>
// {NAVLINKS.map((link, index) => {
// return (
// <HeaderNavLink
// // The advanced tab is disabled when adding an existing component
// // step 1
// isDisabled={index === 1 && shouldDisableAdvancedTab()}
// isActive={state.settingType === link.id}
// key={link.id}
// {...link}
// onClick={() => {
// setState(prev => ({
// ...prev,
// settingType: link.id,
// }));
// sendAdvancedTabEvent(link.id);
// push({ search: getNextSearch(link.id, state) });
// }}
// nextTab={index === NAVLINKS.length - 1 ? 0 : index + 1}
// />
// );
// })}
// </HeaderModalNavContainer>
// </div>
// <hr />
// </>
// )}
// </HeaderModalTitle>
// </section>
// </HeaderModal>
// <form onSubmit={handleSubmit}>
// <ModalForm>
// <ModalBody style={modalBodyStyle}>
// <div className="container-fluid">
// {isPickingAttribute
// ? displayedAttributes.map((row, i) => {
// return (
// <div key={i} className="row">
// {i === 1 && (
// <hr
// style={{
// width: 'calc(100% - 30px)',
// marginBottom: 16,
// marginTop: 19,
// borderColor: '#F0F3F8',
// }}
// />
// )}
// {row.map((attr, index) => {
// const tabIndex =
// i === 0 ? index : displayedAttributes[0].length + index;
// return (
// <AttributeOption
// key={attr}
// tabIndex={tabIndex}
// isDisplayed
// onClick={() => {}}
// ref={i === 0 && index === 0 ? attributeOptionRef : null}
// type={attr}
// />
// );
// })}
// </div>
// );
// })
// : form({
// data: modifiedData,
// type: state.attributeType,
// step: state.step,
// actionType: state.actionType,
// attributes,
// extensions: ctbFormsAPI,
// forTarget: state.forTarget,
// contentTypeSchema: allDataSchema.contentType || {},
// }).items.map((row, index) => {
// return (
// <div className="row" key={index}>
// {row.map((input, i) => {
// // The divider type is used mainly the advanced tab
// // It is the one responsible for displaying the settings label
// if (input.type === 'divider' || input.type === 'dividerDraftPublish') {
// const tradId =
// input.type === 'divider'
// ? 'form.attribute.item.settings.name'
// : 'form.contentType.divider.draft-publish';
// return (
// <div className="col-12" key="divider">
// <Padded bottom size="smd">
// <div style={{ paddingTop: 3 }} />
// <Text
// fontSize="xs"
// color="grey"
// fontWeight="bold"
// textTransform="uppercase"
// >
// <FormattedMessage id={getTrad(tradId)}>
// {txt => txt}
// </FormattedMessage>
// </Text>
// </Padded>
// </div>
// );
// }
// // The spacer type is used mainly to align the icon picker...
// if (input.type === 'spacer') {
// return <div key="spacer" style={{ height: 8 }} />;
// }
// // The spacer type is used mainly to align the icon picker...
// if (input.type === 'spacer-small') {
// return <div key={`${index}.${i}`} style={{ height: 4 }} />;
// }
// if (input.type === 'spacer-medium') {
// return <div key={`${index}.${i}`} style={{ height: 8 }} />;
// }
// // This type is used in the addComponentToDynamicZone modal when selecting the option add an existing component
// // It pushes select the components to the right
// if (input.type === 'pushRight') {
// return <div key={`${index}.${i}`} className={`col-${input.size}`} />;
// }
// if (input.type === 'relation') {
// return (
// <RelationForm
// key="relation"
// mainBoxHeader={get(headers, [0, 'label'], '')}
// modifiedData={modifiedData}
// naturePickerType={state.forTarget}
// onChange={handleChange}
// errors={formErrors}
// />
// );
// }
// // When extending the yup schema of an existing field (like in https://github.com/strapi/strapi/blob/293ff3b8f9559236609d123a2774e3be05ce8274/packages/strapi-plugin-i18n/admin/src/index.js#L52)
// // and triggering a yup validation error in the UI (missing a required field for example)
// // We got an object that looks like: formErrors = { "pluginOptions.i18n.localized": {...} }
// // In order to deal with this error, we can't rely on lodash.get to resolve this key
// // - lodash will try to access {pluginOptions: {i18n: {localized: true}}})
// // - and we just want to access { "pluginOptions.i18n.localized": {...} }
// // NOTE: this is a hack
// const pluginOptionError = Object.keys(formErrors).find(
// key => key === input.name
// );
// // Retrieve the error for a specific input
// const errorId = pluginOptionError
// ? formErrors[pluginOptionError].id
// : get(
// formErrors,
// [
// ...input.name
// .split('.')
// // The filter here is used when creating a component
// // in the component step 1 modal
// // Since the component info is stored in the
// // componentToCreate object we can access the error
// // By removing the key
// .filter(key => key !== 'componentToCreate'),
// 'id',
// ],
// null
// );
// const retrievedValue = get(modifiedData, input.name, '');
// let value;
// // Condition for the boolean default value
// // The radio input doesn't accept false, true or null as value
// // So we pass them as string
// // This way the data stays accurate and we don't have to operate
// // any data mutation
// if (input.name === 'default' && state.attributeType === 'boolean') {
// value = toString(retrievedValue);
// // Same here for the enum
// } else if (input.name === 'enum' && Array.isArray(retrievedValue)) {
// value = retrievedValue.join('\n');
// } else if (input.name === 'uid') {
// value = input.value;
// } else if (input.name === 'allowedTypes' && retrievedValue === '') {
// value = null;
// } else if (input.type === 'checkbox' && !retrievedValue) {
// value = false;
// } else {
// value = retrievedValue;
// }
// return (
// <div className={`col-${input.size || 6}`} key={input.name}>
// <Inputs
// {...input}
// modifiedData={modifiedData}
// addComponentsToDynamicZone={handleClickAddComponentsToDynamicZone}
// changeMediaAllowedTypes={handleChangeMediaAllowedTypes}
// customInputs={{
// allowedTypesSelect: WrapperSelect,
// checkbox: CheckboxWithDescription,
// componentIconPicker: ComponentIconPicker,
// componentSelect: WrapperSelect,
// creatableSelect: WrapperSelect,
// customCheckboxWithChildren: CustomCheckbox,
// booleanBox: BooleanBox,
// ...inputsFromPlugins,
// }}
// isCreating={isCreating}
// // Props for the componentSelect
// isCreatingComponentWhileAddingAField={
// isCreatingComponentWhileAddingAField
// }
// // Props for the componentSelect
// // Since the component is created after adding it to a type
// // its name and category can't be retrieved from the data manager
// componentCategoryNeededForAddingAfieldWhileCreatingAComponent={get(
// componentToCreate,
// 'category',
// null
// )}
// // Props for the componentSelect same explanation
// componentNameNeededForAddingAfieldWhileCreatingAComponent={get(
// componentToCreate,
// 'name',
// null
// )}
// isAddingAComponentToAnotherComponent={
// state.forTarget === 'components' ||
// state.forTarget === 'component'
// }
// value={value}
// error={isEmpty(errorId) ? null : formatMessage({ id: errorId })}
// onChange={handleChange}
// onBlur={() => {}}
// description={
// get(input, 'description.id', null)
// ? formatMessage(input.description)
// : input.description
// }
// placeholder={
// get(input, 'placeholder.id', null)
// ? formatMessage(input.placeholder)
// : input.placeholder
// }
// label={
// get(input, 'label.id', null)
// ? formatMessage(input.label)
// : input.label
// }
// />
// </div>
// );
// })}
// </div>
// );
// })}
// </div>
// </ModalBody>
// </ModalForm>
// {!isPickingAttribute && (
// <ModalFooter>
// <section style={{ alignItems: 'center' }}>
// <Button type="button" color="cancel" onClick={handleClosed}>
// {formatMessage({
// id: 'app.components.Button.cancel',
// })}
// </Button>
// <div>
// {isCreatingAttribute && !isInFirstComponentStep && (
// <Button
// type={isCreating ? 'button' : 'submit'}
// color="success"
// onClick={e => {
// handleSubmit(e, false);
// }}
// style={{ marginRight: '10px' }}
// >
// {formatMessage({ id: 'form.button.finish' })}
// </Button>
// )}
// {(isCreatingContentType || isCreatingComponent) && !isCreating && (
// <Button
// type="button"
// color="delete"
// onClick={e => {
// e.preventDefault();
// deleteData();
// }}
// style={{ marginRight: '10px' }}
// >
// {formatMessage({ id: getTrad('form.button.delete') })}
// </Button>
// )}
// {isEditingCategory && (
// <Button
// type="button"
// color="delete"
// onClick={e => {
// e.preventDefault();
// deleteCategory(initialData.name);
// }}
// style={{ marginRight: '10px' }}
// >
// {formatMessage({ id: getTrad('form.button.delete') })}
// </Button>
// )}
// {isCreating && state.attributeType === 'dynamiczone' && (
// <CustomButton
// type={isCreating ? 'submit' : 'button'}
// color={
// (isCreatingContentType ||
// isCreatingComponent ||
// isEditingCategory ||
// (state.modalType === 'addComponentToDynamicZone' &&
// state.step === '1' &&
// !isCreatingComponentFromAView)) &&
// !isCreating
// ? 'success'
// : 'primary'
// }
// onClick={e => handleSubmit(e, true)}
// icon={
// (isCreatingAttribute &&
// !isCreatingComponentFromAView &&
// state.step !== '1') ||
// (state.modalType === 'addComponentToDynamicZone' &&
// isCreatingComponentFromAView) ||
// (isCreatingComponentFromAView && state.step === '2')
// }
// >
// {getButtonSubmitMessage()}
// </CustomButton>
// )}
// {state.attributeType !== 'dynamiczone' && (
// <CustomButton
// type={isCreating ? 'submit' : 'button'}
// color={
// (isCreatingContentType ||
// isCreatingComponent ||
// isEditingCategory ||
// (state.modalType === 'addComponentToDynamicZone' &&
// state.step === '1' &&
// !isCreatingComponentFromAView)) &&
// !isCreating
// ? 'success'
// : 'primary'
// }
// onClick={e => handleSubmit(e, true)}
// icon={
// (isCreatingAttribute &&
// !isCreatingComponentFromAView &&
// state.step !== '1') ||
// (state.modalType === 'addComponentToDynamicZone' &&
// isCreatingComponentFromAView) ||
// (isCreatingComponentFromAView && state.step === '2')
// }
// >
// {getButtonSubmitMessage()}
// </CustomButton>
// )}
// </div>
// </section>
// </ModalFooter>
// )}
// </form>
// </Modal>
// {/* CONFIRM MODAL FOR DRAFT AND PUBLISH */}
// <PopUpWarning
// isOpen={showConfirmModal}
// onConfirm={handleConfirmDisableDraftAndPublish}
// toggleModal={toggleConfirmModal}
// popUpWarningType="danger"
// content={{
// message: getTrad('popUpWarning.draft-publish.message'),
// secondMessage: getTrad('popUpWarning.draft-publish.second-message'),
// confirm: getTrad('popUpWarning.draft-publish.button.confirm'),
// }}
// />
// </>
// );
};
export default FormModal;

View File

@ -0,0 +1,98 @@
/**
*
* FormModalHeader
*
*/
import React from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import upperFirst from 'lodash/upperFirst';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Breadcrumbs, Crumb } from '@strapi/parts/Breadcrumbs';
import { ModalHeader } from '@strapi/parts/ModalLayout';
import { Box } from '@strapi/parts/Box';
import { Row } from '@strapi/parts/Row';
import { Stack } from '@strapi/parts/Stack';
import { ButtonText } from '@strapi/parts/Text';
import styled from 'styled-components';
import AttributeIcon from '../AttributeIcon';
const IconBox = styled(Box)`
svg {
color: ${({ theme }) => theme.colors.primary600};
}
`;
const FormModalHeader = ({ headerId, headers }) => {
const { formatMessage } = useIntl();
// TODO refacto
// Editing a content type or component
if (headerId) {
return (
<ModalHeader>
<Row>
<Box>
<AttributeIcon type={headers[0].icon.name} />
</Box>
<Box paddingLeft={3}>
<ButtonText textColor="neutral800" as="h2" id="title">
{formatMessage({ id: headerId }, { name: headers[0].label })}
</ButtonText>
</Box>
</Row>
</ModalHeader>
);
}
const breadcrumbsLabel = headers.map(({ label }) => label).join(',');
const { name, isCustom } = headers[0].icon;
return (
<ModalHeader>
<Stack horizontal size={3}>
{!isCustom && <AttributeIcon type={name} />}
{isCustom && (
<IconBox>
<FontAwesomeIcon icon={name} />
</IconBox>
)}
<Breadcrumbs label={breadcrumbsLabel}>
{headers.map((header, index) => {
const label = upperFirst(header.label);
const key = `${header.label}.${index}`;
if (header.info.category) {
const content = `${label} (${upperFirst(header.info.category)} - ${upperFirst(
header.info.name
)})`;
return <Crumb key={key}>{content}</Crumb>;
}
return <Crumb key={key}>{label}</Crumb>;
})}
</Breadcrumbs>
</Stack>
</ModalHeader>
);
};
FormModalHeader.defaultProps = {
headerId: null,
};
FormModalHeader.propTypes = {
headerId: PropTypes.string,
headers: PropTypes.arrayOf(
PropTypes.shape({
icon: PropTypes.shape({ name: PropTypes.string, isCustom: PropTypes.bool }),
label: PropTypes.string.isRequired,
})
).isRequired,
};
export default FormModalHeader;

View File

@ -1,99 +1,100 @@
import React from 'react';
import { ThemeProvider } from 'styled-components';
import 'bootstrap/dist/css/bootstrap.css';
// import React from 'react';
// import { ThemeProvider } from 'styled-components';
// import 'bootstrap/dist/css/bootstrap.css';
const theme = {
main: {
colors: {
black: '#333740',
white: '#ffffff',
red: '#ff203c',
orange: '#ff5d00',
lightOrange: '#f64d0a',
yellow: '#ffd500',
green: '#6dbb1a',
blue: '#0097f7',
teal: '#5bc0de',
pink: '#ff5b77',
purple: '#613d7c',
gray: '#464a4c',
border: '#e3e9f3',
'gray-dark': '#292b2c',
grayLight: '#636c72',
'gray-lighter': '#eceeef',
'gray-lightest': '#f7f7f9',
brightGrey: '#f0f3f8',
darkGrey: '#e3e9f3',
lightGrey: '#fafafa',
lightestGrey: '#fbfbfb',
mediumGrey: '#f2f3f4',
grey: '#9ea7b8',
greyDark: '#292b2c',
greyAlpha: 'rgba(227, 233, 243, 0.5)',
lightestBlue: '#e4f0fc',
lightBlue: '#e6f0fb',
mediumBlue: '#007eff',
darkBlue: '#aed4fb',
pale: '#f7f8f8',
content: {
background: '#fafafb',
'background-alpha': 'rgba(14, 22, 34, 0.02)',
},
leftMenu: {
'link-hover': '#1c2431',
'link-color': '#919bae',
'title-color': '#5b626f',
'background-header-link': '#007eff',
},
strapi: {
'gray-light': '#eff3f6',
gray: '#535f76',
'blue-darker': '#18202e',
'blue-dark': '#151c2e',
blue: '#0097f7',
},
},
fontWeights: {
regular: 400,
semiBold: 500,
bold: 600,
black: 900,
},
sizes: {
borderRadius: '2px',
header: {
height: '6rem',
},
leftMenu: {
height: '6rem',
width: '24rem',
},
margins: {
// TODO:
sm: '10px',
},
paddings: {
// TODO
xs: '5px',
sm: '10px',
smd: '20px',
md: '30px',
lg: '40px',
},
fonts: {
xs: '11px',
sm: '12px',
md: '13px',
lg: '18px',
xl: '24px',
},
},
},
};
// const theme = {
// main: {
// colors: {
// black: '#333740',
// white: '#ffffff',
// red: '#ff203c',
// orange: '#ff5d00',
// lightOrange: '#f64d0a',
// yellow: '#ffd500',
// green: '#6dbb1a',
// blue: '#0097f7',
// teal: '#5bc0de',
// pink: '#ff5b77',
// purple: '#613d7c',
// gray: '#464a4c',
// border: '#e3e9f3',
// 'gray-dark': '#292b2c',
// grayLight: '#636c72',
// 'gray-lighter': '#eceeef',
// 'gray-lightest': '#f7f7f9',
// brightGrey: '#f0f3f8',
// darkGrey: '#e3e9f3',
// lightGrey: '#fafafa',
// lightestGrey: '#fbfbfb',
// mediumGrey: '#f2f3f4',
// grey: '#9ea7b8',
// greyDark: '#292b2c',
// greyAlpha: 'rgba(227, 233, 243, 0.5)',
// lightestBlue: '#e4f0fc',
// lightBlue: '#e6f0fb',
// mediumBlue: '#007eff',
// darkBlue: '#aed4fb',
// pale: '#f7f8f8',
// content: {
// background: '#fafafb',
// 'background-alpha': 'rgba(14, 22, 34, 0.02)',
// },
// leftMenu: {
// 'link-hover': '#1c2431',
// 'link-color': '#919bae',
// 'title-color': '#5b626f',
// 'background-header-link': '#007eff',
// },
// strapi: {
// 'gray-light': '#eff3f6',
// gray: '#535f76',
// 'blue-darker': '#18202e',
// 'blue-dark': '#151c2e',
// blue: '#0097f7',
// },
// },
// fontWeights: {
// regular: 400,
// semiBold: 500,
// bold: 600,
// black: 900,
// },
// sizes: {
// borderRadius: '2px',
// header: {
// height: '6rem',
// },
// leftMenu: {
// height: '6rem',
// width: '24rem',
// },
// margins: {
// // TODO:
// sm: '10px',
// },
// paddings: {
// // TODO
// xs: '5px',
// sm: '10px',
// smd: '20px',
// md: '30px',
// lg: '40px',
// },
// fonts: {
// xs: '11px',
// sm: '12px',
// md: '13px',
// lg: '18px',
// xl: '24px',
// },
// },
// },
// };
// eslint-disable-next-line react/prop-types
const TempTP = ({ children }) => {
return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
// return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
return children;
};
export default TempTP;