mirror of
https://github.com/strapi/strapi.git
synced 2025-12-30 08:43:28 +00:00
461 lines
13 KiB
JavaScript
461 lines
13 KiB
JavaScript
import React, { memo, useEffect, useCallback, useState } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import { connect } from 'react-redux';
|
|
import { bindActionCreators, compose } from 'redux';
|
|
import { get, isEqual, upperFirst } from 'lodash';
|
|
|
|
import {
|
|
BackHeader,
|
|
HeaderNav,
|
|
InputsIndex as Input,
|
|
PluginHeader,
|
|
PopUpWarning,
|
|
LoadingIndicatorPage,
|
|
} from 'strapi-helper-plugin';
|
|
|
|
import pluginId from '../../pluginId';
|
|
import { LayoutDndProvider } from '../../contexts/LayoutDnd';
|
|
|
|
import Block from '../../components/Block';
|
|
import Container from '../../components/Container';
|
|
import FieldsReorder from '../../components/FieldsReorder';
|
|
import FormTitle from '../../components/FormTitle';
|
|
import LayoutTitle from '../../components/LayoutTitle';
|
|
import SectionTitle from '../../components/SectionTitle';
|
|
import Separator from '../../components/Separator';
|
|
import SortableList from '../../components/SortableList';
|
|
|
|
import ListLayout from './ListLayout';
|
|
|
|
import {
|
|
addFieldToList,
|
|
addRelation,
|
|
formatLayout,
|
|
getData,
|
|
moveListField,
|
|
moveRow,
|
|
moveRelation,
|
|
onAddData,
|
|
onChange,
|
|
onReset,
|
|
onSubmit,
|
|
onRemoveListField,
|
|
removeField,
|
|
removeRelation,
|
|
reorderDiffRow,
|
|
reorderRow,
|
|
resetProps,
|
|
setListFieldToEditIndex,
|
|
} from './actions';
|
|
import reducer from './reducer';
|
|
import saga from './saga';
|
|
import makeSelectSettingViewModel from './selectors';
|
|
|
|
import forms from './forms.json';
|
|
|
|
const getUrl = (name, to) =>
|
|
`/plugins/${pluginId}/ctm-configurations/models/${name}/${to}`;
|
|
|
|
function SettingViewModel({
|
|
addFieldToList,
|
|
addRelation,
|
|
didDrop,
|
|
emitEvent,
|
|
formatLayout,
|
|
getData,
|
|
history: { goBack },
|
|
initialData,
|
|
isLoading,
|
|
listFieldToEditIndex,
|
|
match: {
|
|
params: { name, settingType },
|
|
},
|
|
modifiedData,
|
|
moveListField,
|
|
moveRelation,
|
|
moveRow,
|
|
onAddData,
|
|
onChange,
|
|
onRemoveListField,
|
|
onReset,
|
|
onSubmit,
|
|
removeField,
|
|
removeRelation,
|
|
reorderDiffRow,
|
|
reorderRow,
|
|
resetProps,
|
|
setListFieldToEditIndex,
|
|
shouldToggleModalSubmit,
|
|
}) {
|
|
strapi.useInjectReducer({ key: 'settingViewModel', reducer, pluginId });
|
|
strapi.useInjectSaga({ key: 'settingViewModel', saga, pluginId });
|
|
const [showWarningSubmit, setWarningSubmit] = useState(false);
|
|
const [showWarningCancel, setWarningCancel] = useState(false);
|
|
const toggleWarningSubmit = () => setWarningSubmit(prevState => !prevState);
|
|
const toggleWarningCancel = () => setWarningCancel(prevState => !prevState);
|
|
|
|
useEffect(() => {
|
|
getData(name);
|
|
|
|
return () => {
|
|
resetProps();
|
|
};
|
|
}, [getData, name, resetProps]);
|
|
|
|
useEffect(() => {
|
|
if (showWarningSubmit) {
|
|
toggleWarningSubmit();
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [shouldToggleModalSubmit]);
|
|
|
|
useEffect(() => {
|
|
if (!isLoading) {
|
|
formatLayout();
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [didDrop]);
|
|
|
|
const getAttributes = useCallback(() => {
|
|
return get(modifiedData, ['schema', 'attributes'], {});
|
|
}, [modifiedData]);
|
|
|
|
const getEditLayout = useCallback(() => {
|
|
return get(modifiedData, ['layouts', 'edit'], []);
|
|
}, [modifiedData]);
|
|
|
|
const getRelationsLayout = useCallback(() => {
|
|
return get(modifiedData, ['layouts', 'editRelations'], []);
|
|
}, [modifiedData]);
|
|
|
|
if (isLoading) {
|
|
return <LoadingIndicatorPage />;
|
|
}
|
|
|
|
const handleSubmit = e => {
|
|
e.preventDefault();
|
|
toggleWarningSubmit();
|
|
emitEvent('willSaveContentTypeLayout');
|
|
};
|
|
|
|
const getPluginHeaderActions = () => {
|
|
if (isEqual(modifiedData, initialData)) {
|
|
return [];
|
|
}
|
|
|
|
return [
|
|
{
|
|
label: `${pluginId}.popUpWarning.button.cancel`,
|
|
kind: 'secondary',
|
|
onClick: toggleWarningCancel,
|
|
type: 'button',
|
|
},
|
|
{
|
|
kind: 'primary',
|
|
label: `${pluginId}.containers.Edit.submit`,
|
|
onClick: e => {
|
|
handleSubmit(e);
|
|
},
|
|
type: 'submit',
|
|
},
|
|
];
|
|
};
|
|
|
|
const getListDisplayedFields = () =>
|
|
get(modifiedData, ['layouts', 'list'], []);
|
|
const getEditRemainingFields = () => {
|
|
const attributes = getAttributes();
|
|
const metadatas = get(modifiedData, ['metadatas'], {});
|
|
const displayedFields = getEditLayout().reduce(
|
|
(acc, curr) => [...acc, ...curr.rowContent],
|
|
[]
|
|
);
|
|
|
|
return Object.keys(attributes)
|
|
.filter(attr => get(attributes, [attr, 'type'], '') !== 'relation')
|
|
.filter(attr => get(metadatas, [attr, 'edit', 'visible'], false) === true)
|
|
.filter(attr => {
|
|
return displayedFields.findIndex(el => el.name === attr) === -1;
|
|
});
|
|
};
|
|
const getEditRelationsRemaingFields = () => {
|
|
const attributes = getAttributes();
|
|
const displayedFields = getRelationsLayout();
|
|
|
|
return Object.keys(attributes)
|
|
.filter(attr => get(attributes, [attr, 'type'], '') === 'relation')
|
|
.filter(attr => displayedFields.indexOf(attr) === -1);
|
|
};
|
|
const getListRemainingFields = () => {
|
|
const metadatas = get(modifiedData, ['metadatas'], {});
|
|
const attributes = getAttributes();
|
|
|
|
return Object.keys(metadatas)
|
|
.filter(key => {
|
|
const type = get(attributes, [key, 'type'], '');
|
|
|
|
return !['json', 'relation', 'group'].includes(type) && !!type;
|
|
})
|
|
.filter(field => {
|
|
return !getListDisplayedFields().includes(field);
|
|
});
|
|
};
|
|
const getSelectOptions = input => {
|
|
if (input.name === 'settings.defaultSortBy') {
|
|
return getListDisplayedFields();
|
|
}
|
|
|
|
if (input.name === 'settings.mainField') {
|
|
const attributes = getAttributes();
|
|
const options = Object.keys(attributes).filter(attr => {
|
|
const type = get(attributes, [attr, 'type'], '');
|
|
|
|
return (
|
|
!['json', 'text', 'relation', 'group', 'boolean', 'date'].includes(
|
|
type
|
|
) && !!type
|
|
);
|
|
});
|
|
|
|
return ['id', ...options];
|
|
}
|
|
|
|
return input.selectOptions;
|
|
};
|
|
|
|
const moveItem = (dragIndex, hoverIndex, dragRowIndex, hoverRowIndex) => {
|
|
// Same row = just reorder
|
|
if (dragRowIndex === hoverRowIndex) {
|
|
reorderRow(dragRowIndex, dragIndex, hoverIndex);
|
|
} else {
|
|
reorderDiffRow(dragIndex, hoverIndex, dragRowIndex, hoverRowIndex);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<LayoutDndProvider
|
|
attributes={getAttributes()}
|
|
buttonData={getEditRemainingFields()}
|
|
layout={getEditLayout()}
|
|
moveItem={moveItem}
|
|
moveRow={moveRow}
|
|
onAddData={onAddData}
|
|
relationsLayout={getRelationsLayout()}
|
|
removeField={removeField}
|
|
>
|
|
<BackHeader onClick={() => goBack()} />
|
|
<Container className="container-fluid">
|
|
<form onSubmit={handleSubmit}>
|
|
<PluginHeader
|
|
actions={getPluginHeaderActions()}
|
|
title={{
|
|
id: `${pluginId}.containers.SettingViewModel.pluginHeader.title`,
|
|
values: { name: upperFirst(name) },
|
|
}}
|
|
description={{
|
|
id: `${pluginId}.containers.SettingPage.pluginHeaderDescription`,
|
|
}}
|
|
/>
|
|
<HeaderNav
|
|
links={[
|
|
{
|
|
name:
|
|
'content-manager.containers.SettingPage.listSettings.title',
|
|
to: getUrl(name, 'list-settings'),
|
|
},
|
|
{
|
|
name:
|
|
'content-manager.containers.SettingPage.editSettings.title',
|
|
to: getUrl(name, 'edit-settings'),
|
|
},
|
|
]}
|
|
/>
|
|
<div className="row">
|
|
<Block
|
|
style={{
|
|
marginBottom: '13px',
|
|
paddingBottom: '30px',
|
|
paddingTop: '30px',
|
|
}}
|
|
>
|
|
<SectionTitle isSettings />
|
|
<div className="row">
|
|
{forms[settingType].map(input => {
|
|
return (
|
|
<Input
|
|
key={input.name}
|
|
{...input}
|
|
onChange={onChange}
|
|
selectOptions={getSelectOptions(input)}
|
|
value={get(modifiedData, input.name)}
|
|
/>
|
|
);
|
|
})}
|
|
<div className="col-12">
|
|
<Separator />
|
|
</div>
|
|
</div>
|
|
<SectionTitle />
|
|
|
|
<div className="row">
|
|
<LayoutTitle
|
|
className={
|
|
settingType === 'list-settings' ? 'col-12' : 'col-8'
|
|
}
|
|
>
|
|
<FormTitle
|
|
title={`${pluginId}.global.displayedFields`}
|
|
description={`${pluginId}.containers.SettingPage.${
|
|
settingType === 'list-settings'
|
|
? 'attributes'
|
|
: 'editSettings'
|
|
}.description`}
|
|
/>
|
|
</LayoutTitle>
|
|
{settingType === 'edit-settings' && (
|
|
<LayoutTitle className="col-4">
|
|
<FormTitle
|
|
title={`${pluginId}.containers.SettingPage.relations`}
|
|
description={`${pluginId}.containers.SettingPage.${
|
|
settingType === 'list-settings'
|
|
? 'attributes'
|
|
: 'editSettings'
|
|
}.description`}
|
|
/>
|
|
</LayoutTitle>
|
|
)}
|
|
|
|
{settingType === 'list-settings' && (
|
|
<ListLayout
|
|
addField={addFieldToList}
|
|
displayedData={getListDisplayedFields()}
|
|
availableData={getListRemainingFields()}
|
|
fieldToEditIndex={listFieldToEditIndex}
|
|
modifiedData={modifiedData}
|
|
moveListField={moveListField}
|
|
onClick={setListFieldToEditIndex}
|
|
onChange={onChange}
|
|
onRemove={onRemoveListField}
|
|
onSubmit={handleSubmit}
|
|
/>
|
|
)}
|
|
|
|
{settingType === 'edit-settings' && <FieldsReorder />}
|
|
{settingType === 'edit-settings' && (
|
|
<SortableList
|
|
addItem={addRelation}
|
|
buttonData={getEditRelationsRemaingFields()}
|
|
moveItem={moveRelation}
|
|
removeItem={removeRelation}
|
|
/>
|
|
)}
|
|
</div>
|
|
</Block>
|
|
</div>
|
|
</form>
|
|
</Container>
|
|
<PopUpWarning
|
|
isOpen={showWarningCancel}
|
|
toggleModal={toggleWarningCancel}
|
|
content={{
|
|
title: `${pluginId}.popUpWarning.title`,
|
|
message: `${pluginId}.popUpWarning.warning.cancelAllSettings`,
|
|
cancel: `${pluginId}.popUpWarning.button.cancel`,
|
|
confirm: `${pluginId}.popUpWarning.button.confirm`,
|
|
}}
|
|
popUpWarningType="danger"
|
|
onConfirm={() => {
|
|
onReset();
|
|
toggleWarningCancel();
|
|
}}
|
|
/>
|
|
<PopUpWarning
|
|
isOpen={showWarningSubmit}
|
|
toggleModal={toggleWarningSubmit}
|
|
content={{
|
|
title: `${pluginId}.popUpWarning.title`,
|
|
message: `${pluginId}.popUpWarning.warning.updateAllSettings`,
|
|
cancel: `${pluginId}.popUpWarning.button.cancel`,
|
|
confirm: `${pluginId}.popUpWarning.button.confirm`,
|
|
}}
|
|
popUpWarningType="danger"
|
|
onConfirm={() => onSubmit(name, emitEvent)}
|
|
/>
|
|
</LayoutDndProvider>
|
|
);
|
|
}
|
|
|
|
SettingViewModel.propTypes = {
|
|
addFieldToList: PropTypes.func.isRequired,
|
|
addRelation: PropTypes.func.isRequired,
|
|
didDrop: PropTypes.bool.isRequired,
|
|
emitEvent: PropTypes.func.isRequired,
|
|
formatLayout: PropTypes.func.isRequired,
|
|
getData: PropTypes.func.isRequired,
|
|
history: PropTypes.shape({
|
|
goBack: PropTypes.func,
|
|
}).isRequired,
|
|
initialData: PropTypes.object.isRequired,
|
|
isLoading: PropTypes.bool.isRequired,
|
|
listFieldToEditIndex: PropTypes.number.isRequired,
|
|
match: PropTypes.shape({
|
|
params: PropTypes.shape({
|
|
name: PropTypes.string,
|
|
settingType: PropTypes.string,
|
|
}),
|
|
}).isRequired,
|
|
modifiedData: PropTypes.object.isRequired,
|
|
moveListField: PropTypes.func.isRequired,
|
|
moveRelation: PropTypes.func.isRequired,
|
|
moveRow: PropTypes.func.isRequired,
|
|
onAddData: PropTypes.func.isRequired,
|
|
onChange: PropTypes.func.isRequired,
|
|
onRemoveListField: PropTypes.func.isRequired,
|
|
onReset: PropTypes.func.isRequired,
|
|
onSubmit: PropTypes.func.isRequired,
|
|
removeField: PropTypes.func.isRequired,
|
|
removeRelation: PropTypes.func.isRequired,
|
|
reorderDiffRow: PropTypes.func.isRequired,
|
|
reorderRow: PropTypes.func.isRequired,
|
|
resetProps: PropTypes.func.isRequired,
|
|
setListFieldToEditIndex: PropTypes.func.isRequired,
|
|
shouldToggleModalSubmit: PropTypes.bool.isRequired,
|
|
};
|
|
|
|
const mapStateToProps = makeSelectSettingViewModel();
|
|
|
|
export function mapDispatchToProps(dispatch) {
|
|
return bindActionCreators(
|
|
{
|
|
addFieldToList,
|
|
addRelation,
|
|
formatLayout,
|
|
getData,
|
|
moveListField,
|
|
moveRelation,
|
|
moveRow,
|
|
onAddData,
|
|
onChange,
|
|
onRemoveListField,
|
|
onReset,
|
|
onSubmit,
|
|
removeField,
|
|
removeRelation,
|
|
reorderDiffRow,
|
|
reorderRow,
|
|
resetProps,
|
|
setListFieldToEditIndex,
|
|
},
|
|
dispatch
|
|
);
|
|
}
|
|
const withConnect = connect(
|
|
mapStateToProps,
|
|
mapDispatchToProps
|
|
);
|
|
|
|
export default compose(
|
|
withConnect,
|
|
memo
|
|
)(SettingViewModel);
|