2019-10-29 18:03:06 +01:00
|
|
|
import React, {
|
|
|
|
|
memo,
|
|
|
|
|
useCallback,
|
|
|
|
|
useMemo,
|
|
|
|
|
useEffect,
|
|
|
|
|
// useState,
|
|
|
|
|
useReducer,
|
|
|
|
|
useRef,
|
|
|
|
|
} from 'react';
|
2019-07-11 11:35:18 +02:00
|
|
|
import PropTypes from 'prop-types';
|
2019-10-29 18:03:06 +01:00
|
|
|
import {
|
|
|
|
|
// cloneDeep,
|
|
|
|
|
get,
|
|
|
|
|
// isEqual,
|
|
|
|
|
} from 'lodash';
|
|
|
|
|
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
2019-07-11 11:35:18 +02:00
|
|
|
import {
|
2019-07-11 15:33:49 +02:00
|
|
|
BackHeader,
|
2019-07-11 11:35:18 +02:00
|
|
|
getQueryParameters,
|
2019-10-29 18:03:06 +01:00
|
|
|
// LoadingIndicatorPage,
|
2019-07-11 16:53:00 +02:00
|
|
|
LiLink,
|
2019-07-11 11:35:18 +02:00
|
|
|
PluginHeader,
|
2019-10-29 18:03:06 +01:00
|
|
|
// PopUpWarning,
|
|
|
|
|
// getYupInnerErrors,
|
|
|
|
|
// request,
|
2019-07-11 11:35:18 +02:00
|
|
|
templateObject,
|
|
|
|
|
} from 'strapi-helper-plugin';
|
|
|
|
|
import pluginId from '../../pluginId';
|
2019-07-17 17:39:43 +02:00
|
|
|
import { EditViewProvider } from '../../contexts/EditView';
|
2019-07-11 11:35:18 +02:00
|
|
|
import Container from '../../components/Container';
|
2019-10-29 18:03:06 +01:00
|
|
|
import DynamicZone from '../../components/DynamicZone';
|
|
|
|
|
import FormWrapper from '../../components/FormWrapper';
|
|
|
|
|
// import ComponentField from '../../components/ComponentField';
|
2019-10-29 19:26:42 +01:00
|
|
|
import Inputs from '../../components/Inputs';
|
2019-07-17 17:39:43 +02:00
|
|
|
import SelectWrapper from '../../components/SelectWrapper';
|
2019-10-29 18:03:06 +01:00
|
|
|
// import createYupSchema from './utils/schema';
|
|
|
|
|
// import setDefaultForm from './utils/createDefaultForm';
|
2019-08-22 17:15:15 +02:00
|
|
|
import getInjectedComponents from './utils/getComponents';
|
|
|
|
|
import init from './init';
|
2019-07-11 11:35:18 +02:00
|
|
|
import reducer, { initialState } from './reducer';
|
2019-08-22 17:15:15 +02:00
|
|
|
import {
|
2019-10-29 18:03:06 +01:00
|
|
|
LinkWrapper,
|
|
|
|
|
// MainWrapper,
|
|
|
|
|
SubWrapper,
|
|
|
|
|
} from './components';
|
|
|
|
|
// import {
|
|
|
|
|
// getMediaAttributes,
|
|
|
|
|
// cleanData,
|
|
|
|
|
// mapDataKeysToFilesToUpload,
|
|
|
|
|
// } from './utils/formatData';
|
|
|
|
|
|
|
|
|
|
// import {
|
|
|
|
|
// getDefaultComponentValues,
|
|
|
|
|
// retrieveDisplayedComponents,
|
|
|
|
|
// retrieveComponentsLayoutsToFetch,
|
|
|
|
|
// } from './utils/components';
|
|
|
|
|
import createAttributesLayout from './utils/createAttributesLayout';
|
|
|
|
|
// const getRequestUrl = path => `/${pluginId}/explorer/${path}`;
|
|
|
|
|
|
|
|
|
|
const EditView = ({
|
2019-07-11 16:53:00 +02:00
|
|
|
currentEnvironment,
|
|
|
|
|
emitEvent,
|
2019-07-11 11:35:18 +02:00
|
|
|
layouts,
|
2019-07-11 16:53:00 +02:00
|
|
|
plugins,
|
2019-10-29 18:03:06 +01:00
|
|
|
slug,
|
|
|
|
|
}) => {
|
|
|
|
|
const formatLayoutRef = useRef();
|
|
|
|
|
formatLayoutRef.current = createAttributesLayout;
|
|
|
|
|
// Retrieve push to programmatically navigate between views
|
|
|
|
|
const { push } = useHistory();
|
|
|
|
|
// Retrieve the search
|
|
|
|
|
const { search } = useLocation();
|
|
|
|
|
|
|
|
|
|
// Retrieve the document's id
|
2019-10-24 17:08:52 +02:00
|
|
|
const { id } = useParams();
|
2019-10-29 18:03:06 +01:00
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
2019-07-11 11:35:18 +02:00
|
|
|
const [reducerState, dispatch] = useReducer(reducer, initialState, () =>
|
2019-10-29 18:03:06 +01:00
|
|
|
init(initialState)
|
|
|
|
|
);
|
|
|
|
|
const currentContentTypeLayoutData = useMemo(
|
|
|
|
|
() => get(layouts, [slug, 'contentType'], {}),
|
|
|
|
|
[layouts, slug]
|
|
|
|
|
);
|
|
|
|
|
const currentContentTypeLayout = useMemo(
|
|
|
|
|
() => get(currentContentTypeLayoutData, ['layouts', 'edit'], []),
|
|
|
|
|
[currentContentTypeLayoutData]
|
|
|
|
|
);
|
|
|
|
|
const currentContentTypeLayoutRelations = useMemo(
|
|
|
|
|
() => get(currentContentTypeLayoutData, ['layouts', 'editRelations'], []),
|
|
|
|
|
[currentContentTypeLayoutData]
|
|
|
|
|
);
|
|
|
|
|
const currentContentTypeSchema = useMemo(
|
|
|
|
|
() => get(currentContentTypeLayoutData, ['schema'], {}),
|
|
|
|
|
[currentContentTypeLayoutData]
|
2019-07-11 11:35:18 +02:00
|
|
|
);
|
|
|
|
|
const source = getQueryParameters(search, 'source');
|
2019-10-29 18:03:06 +01:00
|
|
|
const getFieldType = useCallback(
|
|
|
|
|
fieldName => {
|
|
|
|
|
return get(
|
|
|
|
|
currentContentTypeSchema,
|
|
|
|
|
['attributes', fieldName, 'type'],
|
|
|
|
|
''
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
[currentContentTypeSchema]
|
|
|
|
|
);
|
|
|
|
|
// Check if a block is a dynamic zone
|
|
|
|
|
const isDynamicZone = useCallback(
|
|
|
|
|
block => {
|
|
|
|
|
return block.every(subBlock => {
|
|
|
|
|
return subBlock.every(obj => getFieldType(obj.name) === 'dynamiczone');
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
[getFieldType]
|
|
|
|
|
);
|
2019-07-11 11:35:18 +02:00
|
|
|
|
2019-10-29 18:03:06 +01:00
|
|
|
const isCreatingEntry = id === 'create';
|
2019-07-12 18:38:29 +02:00
|
|
|
|
2019-10-29 18:03:06 +01:00
|
|
|
useEffect(() => {
|
2019-09-16 17:47:43 +02:00
|
|
|
// Force state to be cleared when navigation from one entry to another
|
|
|
|
|
dispatch({ type: 'RESET_PROPS' });
|
2019-10-29 18:03:06 +01:00
|
|
|
dispatch({
|
|
|
|
|
type: 'SET_LAYOUT_DATA',
|
|
|
|
|
formattedContentTypeLayout: formatLayoutRef.current(
|
|
|
|
|
currentContentTypeLayout,
|
|
|
|
|
currentContentTypeSchema.attributes
|
|
|
|
|
),
|
|
|
|
|
});
|
|
|
|
|
}, [currentContentTypeLayout, currentContentTypeSchema.attributes]);
|
2019-09-16 17:47:43 +02:00
|
|
|
|
2019-10-29 18:03:06 +01:00
|
|
|
const { formattedContentTypeLayout, initialData } = reducerState.toJS();
|
2019-07-18 16:53:12 +02:00
|
|
|
|
2019-10-29 18:03:06 +01:00
|
|
|
const currentContentTypeMainField = get(
|
|
|
|
|
currentContentTypeLayoutData,
|
2019-07-11 15:33:49 +02:00
|
|
|
['settings', 'mainField'],
|
|
|
|
|
'id'
|
|
|
|
|
);
|
2019-07-11 11:35:18 +02:00
|
|
|
const pluginHeaderTitle = isCreatingEntry
|
|
|
|
|
? { id: `${pluginId}.containers.Edit.pluginHeader.title.new` }
|
2019-10-29 18:03:06 +01:00
|
|
|
: templateObject({ mainField: currentContentTypeMainField }, initialData)
|
2019-07-11 11:35:18 +02:00
|
|
|
.mainField;
|
2019-09-13 14:46:31 +02:00
|
|
|
|
2019-10-29 18:03:06 +01:00
|
|
|
// We can't use the getQueryParameters helper here because the search
|
|
|
|
|
// can contain 'redirectUrl' several times since we can navigate between documents
|
|
|
|
|
const redirectURL = search
|
|
|
|
|
.split('redirectUrl=')
|
|
|
|
|
.filter((_, index) => index !== 0)
|
|
|
|
|
.join('');
|
|
|
|
|
const redirectToPreviousPage = () => push(redirectURL);
|
2019-09-13 14:46:31 +02:00
|
|
|
|
2019-07-18 16:53:12 +02:00
|
|
|
const handleSubmit = async e => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-11 11:35:18 +02:00
|
|
|
return (
|
2019-10-29 19:26:42 +01:00
|
|
|
<EditViewProvider layout={currentContentTypeLayoutData}>
|
2019-07-11 15:33:49 +02:00
|
|
|
<BackHeader onClick={() => redirectToPreviousPage()} />
|
|
|
|
|
<Container className="container-fluid">
|
|
|
|
|
<form onSubmit={handleSubmit}>
|
|
|
|
|
<PluginHeader
|
|
|
|
|
actions={[
|
|
|
|
|
{
|
|
|
|
|
label: `${pluginId}.containers.Edit.reset`,
|
|
|
|
|
kind: 'secondary',
|
|
|
|
|
onClick: () => {
|
2019-10-29 18:03:06 +01:00
|
|
|
// toggleWarningCancel();
|
2019-07-11 15:33:49 +02:00
|
|
|
},
|
|
|
|
|
type: 'button',
|
2019-10-29 18:03:06 +01:00
|
|
|
// disabled: isSubmitting, // TODO STATE WHEN SUBMITING
|
2019-07-11 15:33:49 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
kind: 'primary',
|
|
|
|
|
label: `${pluginId}.containers.Edit.submit`,
|
|
|
|
|
type: 'submit',
|
2019-10-29 18:03:06 +01:00
|
|
|
// loader: isSubmitting,
|
|
|
|
|
// style: isSubmitting ? { marginRight: '18px' } : {},
|
|
|
|
|
// disabled: isSubmitting, // TODO STATE WHEN SUBMITING
|
2019-07-11 15:33:49 +02:00
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
subActions={
|
|
|
|
|
isCreatingEntry
|
|
|
|
|
? []
|
|
|
|
|
: [
|
|
|
|
|
{
|
|
|
|
|
label: 'app.utils.delete',
|
|
|
|
|
kind: 'delete',
|
|
|
|
|
onClick: () => {
|
2019-10-29 18:03:06 +01:00
|
|
|
// toggleWarningDelete();
|
2019-07-11 15:33:49 +02:00
|
|
|
},
|
|
|
|
|
type: 'button',
|
2019-10-29 18:03:06 +01:00
|
|
|
// disabled: isSubmitting, // TODO STATE WHEN SUBMITING
|
2019-07-11 15:33:49 +02:00
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
title={pluginHeaderTitle}
|
|
|
|
|
/>
|
2019-07-11 16:53:00 +02:00
|
|
|
<div className="row">
|
2019-07-24 18:24:23 +02:00
|
|
|
<div className="col-md-12 col-lg-9">
|
2019-10-29 18:03:06 +01:00
|
|
|
{formattedContentTypeLayout.map((block, blockIndex) => {
|
|
|
|
|
if (isDynamicZone(block)) {
|
|
|
|
|
const {
|
|
|
|
|
0: {
|
|
|
|
|
0: { name },
|
|
|
|
|
},
|
|
|
|
|
} = block;
|
2019-08-09 13:23:39 +02:00
|
|
|
|
2019-10-29 19:26:42 +01:00
|
|
|
return <DynamicZone key={blockIndex} name={name} />;
|
2019-10-29 18:03:06 +01:00
|
|
|
}
|
|
|
|
|
|
2019-10-29 19:26:42 +01:00
|
|
|
return (
|
|
|
|
|
<FormWrapper key={blockIndex}>
|
|
|
|
|
{block.map((fieldsBlock, fieldsBlockIndex) => {
|
|
|
|
|
return (
|
|
|
|
|
<div className="row" key={fieldsBlockIndex}>
|
|
|
|
|
{fieldsBlock.map(({ name, size }, fieldIndex) => {
|
|
|
|
|
return (
|
|
|
|
|
<div className={`col-${size}`} key={name}>
|
|
|
|
|
<Inputs
|
|
|
|
|
autoFocus={
|
|
|
|
|
blockIndex === 0 &&
|
|
|
|
|
fieldsBlockIndex === 0 &&
|
|
|
|
|
fieldIndex === 0
|
|
|
|
|
}
|
|
|
|
|
keys={name}
|
|
|
|
|
layout={currentContentTypeLayoutData}
|
|
|
|
|
name={name}
|
|
|
|
|
onChange={() => {}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</FormWrapper>
|
|
|
|
|
);
|
2019-10-29 18:03:06 +01:00
|
|
|
})}
|
2019-07-12 14:15:56 +02:00
|
|
|
</div>
|
2019-10-29 18:03:06 +01:00
|
|
|
|
2019-07-12 14:15:56 +02:00
|
|
|
<div className="col-md-12 col-lg-3">
|
2019-10-29 18:03:06 +01:00
|
|
|
{currentContentTypeLayoutRelations.length > 0 && (
|
2019-07-12 14:15:56 +02:00
|
|
|
<SubWrapper
|
2019-07-29 17:11:53 +02:00
|
|
|
style={{ padding: '0 20px 1px', marginBottom: '26px' }}
|
2019-07-12 14:15:56 +02:00
|
|
|
>
|
2019-07-22 11:41:27 +02:00
|
|
|
<div style={{ paddingTop: '22px' }}>
|
2019-10-29 18:03:06 +01:00
|
|
|
{currentContentTypeLayoutRelations.map(relationName => {
|
2019-07-16 18:53:41 +02:00
|
|
|
const relation = get(
|
2019-10-29 18:03:06 +01:00
|
|
|
currentContentTypeLayoutData,
|
2019-07-16 18:53:41 +02:00
|
|
|
['schema', 'attributes', relationName],
|
|
|
|
|
{}
|
|
|
|
|
);
|
|
|
|
|
const relationMetas = get(
|
2019-10-29 18:03:06 +01:00
|
|
|
currentContentTypeLayoutData,
|
2019-07-24 10:16:44 +02:00
|
|
|
['metadatas', relationName, 'edit'],
|
2019-07-16 18:53:41 +02:00
|
|
|
{}
|
|
|
|
|
);
|
2019-10-29 18:03:06 +01:00
|
|
|
const value = get({}, [relationName], null);
|
2019-07-16 18:53:41 +02:00
|
|
|
|
|
|
|
|
return (
|
2019-07-17 12:06:19 +02:00
|
|
|
<SelectWrapper
|
2019-07-16 18:53:41 +02:00
|
|
|
{...relation}
|
|
|
|
|
{...relationMetas}
|
2019-07-17 12:06:19 +02:00
|
|
|
key={relationName}
|
2019-07-16 18:53:41 +02:00
|
|
|
name={relationName}
|
2019-07-24 10:16:44 +02:00
|
|
|
relationsType={relation.relationType}
|
2019-07-16 18:53:41 +02:00
|
|
|
value={value}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
})}
|
2019-07-15 13:00:31 +02:00
|
|
|
</div>
|
2019-07-12 14:15:56 +02:00
|
|
|
</SubWrapper>
|
|
|
|
|
)}
|
2019-07-11 16:53:00 +02:00
|
|
|
<LinkWrapper>
|
|
|
|
|
<ul>
|
|
|
|
|
<LiLink
|
|
|
|
|
message={{
|
2019-10-15 11:17:26 +02:00
|
|
|
id: 'app.links.configure-view',
|
2019-07-11 16:53:00 +02:00
|
|
|
}}
|
|
|
|
|
icon="layout"
|
|
|
|
|
key={`${pluginId}.link`}
|
2019-10-24 17:08:52 +02:00
|
|
|
// url={`/plugins/${pluginId}/ctm-configurations/edit-settings/content-types/${slug}${`?source=${source}`}`}
|
|
|
|
|
url={`ctm-configurations/edit-settings/content-types${`?source=${source}`}`}
|
2019-07-11 16:53:00 +02:00
|
|
|
onClick={() => {
|
2019-10-29 18:03:06 +01:00
|
|
|
// emitEvent('willEditContentTypeLayoutFromEditView');
|
2019-07-11 16:53:00 +02:00
|
|
|
}}
|
|
|
|
|
/>
|
2019-08-22 17:15:15 +02:00
|
|
|
{getInjectedComponents(
|
|
|
|
|
'right.links',
|
|
|
|
|
plugins,
|
|
|
|
|
currentEnvironment,
|
|
|
|
|
slug,
|
|
|
|
|
source,
|
|
|
|
|
emitEvent
|
|
|
|
|
)}
|
2019-07-11 16:53:00 +02:00
|
|
|
</ul>
|
|
|
|
|
</LinkWrapper>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2019-07-11 15:33:49 +02:00
|
|
|
</form>
|
|
|
|
|
</Container>
|
2019-07-17 17:39:43 +02:00
|
|
|
</EditViewProvider>
|
2019-07-11 11:35:18 +02:00
|
|
|
);
|
2019-10-29 18:03:06 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
EditView.defaultProps = {
|
|
|
|
|
currentEnvironment: 'production',
|
|
|
|
|
emitEvent: () => {},
|
|
|
|
|
plugins: {},
|
|
|
|
|
};
|
2019-07-10 09:31:26 +02:00
|
|
|
|
2019-07-11 11:35:18 +02:00
|
|
|
EditView.propTypes = {
|
2019-10-29 18:03:06 +01:00
|
|
|
currentEnvironment: PropTypes.string,
|
|
|
|
|
emitEvent: PropTypes.func,
|
|
|
|
|
layouts: PropTypes.object.isRequired,
|
2019-10-24 17:08:52 +02:00
|
|
|
slug: PropTypes.string.isRequired,
|
2019-07-11 16:53:00 +02:00
|
|
|
plugins: PropTypes.object,
|
2019-07-11 11:35:18 +02:00
|
|
|
};
|
|
|
|
|
|
2019-10-29 18:03:06 +01:00
|
|
|
export { EditView };
|
2019-07-11 11:35:18 +02:00
|
|
|
export default memo(EditView);
|
2019-10-29 18:03:06 +01:00
|
|
|
|
|
|
|
|
// function EditView({
|
|
|
|
|
// currentEnvironment,
|
|
|
|
|
// emitEvent,
|
|
|
|
|
// layouts,
|
|
|
|
|
// location: { pathname, search },
|
|
|
|
|
// history: { push },
|
|
|
|
|
|
|
|
|
|
// slug,
|
|
|
|
|
// plugins,
|
|
|
|
|
// }) {
|
|
|
|
|
// const { id } = useParams();
|
|
|
|
|
// const abortController = new AbortController();
|
|
|
|
|
// const { signal } = abortController;
|
|
|
|
|
// const layout = get(layouts, [slug, 'contentType'], {});
|
|
|
|
|
// const isCreatingEntry = id === 'create';
|
|
|
|
|
// const attributes = get(layout, ['schema', 'attributes'], {});
|
|
|
|
|
|
|
|
|
|
// const components = retrieveDisplayedComponents(attributes);
|
|
|
|
|
// const componentLayoutsToGet = retrieveComponentsLayoutsToFetch(components);
|
|
|
|
|
|
|
|
|
|
// // States
|
|
|
|
|
// const [showWarningCancel, setWarningCancel] = useState(false);
|
|
|
|
|
// const [showWarningDelete, setWarningDelete] = useState(false);
|
|
|
|
|
// const [isSubmitting, setIsSubmitting] = useState(false);
|
|
|
|
|
// const [reducerState, dispatch] = useReducer(reducer, initialState, () =>
|
|
|
|
|
// init(initialState, layout, isCreatingEntry)
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// const state = reducerState.toJS();
|
|
|
|
|
// const {
|
|
|
|
|
// didCheckErrors,
|
|
|
|
|
// errors,
|
|
|
|
|
// componentLayoutsData,
|
|
|
|
|
// initialData,
|
|
|
|
|
// modifiedData,
|
|
|
|
|
// isLoading,
|
|
|
|
|
// isLoadingForLayouts,
|
|
|
|
|
// } = state;
|
|
|
|
|
|
|
|
|
|
// const source = getQueryParameters(search, 'source');
|
|
|
|
|
// const shouldShowLoader =
|
|
|
|
|
// isLoadingForLayouts || (!isCreatingEntry && isLoading);
|
|
|
|
|
|
|
|
|
|
// useEffect(() => {
|
|
|
|
|
// const fetchComponentLayouts = async () => {
|
|
|
|
|
// try {
|
|
|
|
|
// const data = await Promise.all(
|
|
|
|
|
// componentLayoutsToGet.map(uid =>
|
|
|
|
|
// request(`/${pluginId}/components/${uid}`, {
|
|
|
|
|
// method: 'GET',
|
|
|
|
|
// signal,
|
|
|
|
|
// })
|
|
|
|
|
// )
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// const componentLayouts = data.reduce((acc, current) => {
|
|
|
|
|
// acc[current.data.uid] = current.data;
|
|
|
|
|
|
|
|
|
|
// return acc;
|
|
|
|
|
// }, {});
|
|
|
|
|
|
|
|
|
|
// // Retrieve all the default values for the repeatables and init the form
|
|
|
|
|
// const defaultComponentValues = getDefaultComponentValues(
|
|
|
|
|
// components,
|
|
|
|
|
// componentLayouts
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'GET_COMPONENT_LAYOUTS_SUCCEEDED',
|
|
|
|
|
// componentLayouts,
|
|
|
|
|
// defaultComponentValues,
|
|
|
|
|
// isCreatingEntry,
|
|
|
|
|
// });
|
|
|
|
|
// } catch (err) {
|
|
|
|
|
// // TODO ADD A TRAD
|
|
|
|
|
|
|
|
|
|
// if (err.code !== 20) {
|
|
|
|
|
// strapi.notification.error('notification.error');
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
// const fetchData = async () => {
|
|
|
|
|
// try {
|
|
|
|
|
// const data = await request(getRequestUrl(`${slug}/${id}`), {
|
|
|
|
|
// method: 'GET',
|
|
|
|
|
// params: { source },
|
|
|
|
|
// signal,
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'GET_DATA_SUCCEEDED',
|
|
|
|
|
// data,
|
|
|
|
|
// defaultForm: setDefaultForm(get(layout, ['schema', 'attributes'])),
|
|
|
|
|
// });
|
|
|
|
|
// fetchComponentLayouts();
|
|
|
|
|
// } catch (err) {
|
|
|
|
|
// if (err.code !== 20) {
|
|
|
|
|
// strapi.notification.error(`${pluginId}.error.record.fetch`);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// // Force state to be cleared when navigation from one entry to another
|
|
|
|
|
// dispatch({ type: 'RESET_PROPS' });
|
|
|
|
|
|
|
|
|
|
// if (!isCreatingEntry) {
|
|
|
|
|
// fetchData();
|
|
|
|
|
// } else {
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'INIT',
|
|
|
|
|
// data: setDefaultForm(get(layout, ['schema', 'attributes'])),
|
|
|
|
|
// defaultForm: setDefaultForm(get(layout, ['schema', 'attributes'])),
|
|
|
|
|
// });
|
|
|
|
|
// fetchComponentLayouts();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// return () => {
|
|
|
|
|
// abortController.abort();
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
|
// }, [id, isCreatingEntry, slug, source, pathname]);
|
|
|
|
|
|
|
|
|
|
// if (shouldShowLoader) {
|
|
|
|
|
// return <LoadingIndicatorPage />;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const toggleWarningCancel = () => setWarningCancel(prevState => !prevState);
|
|
|
|
|
// const toggleWarningDelete = () => setWarningDelete(prevState => !prevState);
|
|
|
|
|
// const redirectURL = search
|
|
|
|
|
// .split('redirectUrl=')
|
|
|
|
|
// .filter((_, index) => index !== 0)
|
|
|
|
|
// .join('');
|
|
|
|
|
|
|
|
|
|
// const redirectToPreviousPage = () => push(redirectURL);
|
|
|
|
|
// const handleConfirmDelete = async () => {
|
|
|
|
|
// toggleWarningDelete();
|
|
|
|
|
// setIsSubmitting(true);
|
|
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
// await request(getRequestUrl(`${slug}/${id}`), {
|
|
|
|
|
// method: 'DELETE',
|
|
|
|
|
// params: { source },
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// strapi.notification.success(`${pluginId}.success.record.delete`);
|
|
|
|
|
// redirectToPreviousPage();
|
|
|
|
|
// } catch (err) {
|
|
|
|
|
// setIsSubmitting(false);
|
|
|
|
|
// strapi.notification.error(`${pluginId}.error.record.delete`);
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// const displayedFieldNameInHeader = get(
|
|
|
|
|
// layout,
|
|
|
|
|
// ['settings', 'mainField'],
|
|
|
|
|
// 'id'
|
|
|
|
|
// );
|
|
|
|
|
// const pluginHeaderTitle = isCreatingEntry
|
|
|
|
|
// ? { id: `${pluginId}.containers.Edit.pluginHeader.title.new` }
|
|
|
|
|
// : templateObject({ mainField: displayedFieldNameInHeader }, initialData)
|
|
|
|
|
// .mainField;
|
|
|
|
|
// const displayedRelations = get(layout, ['layouts', 'editRelations'], []);
|
|
|
|
|
// const hasRelations = displayedRelations.length > 0;
|
|
|
|
|
// const fields = get(layout, ['layouts', 'edit'], []);
|
|
|
|
|
|
|
|
|
|
// const checkFormErrors = async () => {
|
|
|
|
|
// const schema = createYupSchema(layout, {
|
|
|
|
|
// components: componentLayoutsData,
|
|
|
|
|
// });
|
|
|
|
|
// let errors = {};
|
|
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
// // Validate the form using yup
|
|
|
|
|
// await schema.validate(modifiedData, { abortEarly: false });
|
|
|
|
|
// } catch (err) {
|
|
|
|
|
// errors = getYupInnerErrors(err);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'SET_ERRORS',
|
|
|
|
|
// errors,
|
|
|
|
|
// });
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// const handleChange = ({ target: { name, value, type } }) => {
|
|
|
|
|
// let inputValue = value;
|
|
|
|
|
|
|
|
|
|
// // Empty string is not a valid date,
|
|
|
|
|
// // Set the date to null when it's empty
|
|
|
|
|
// if (type === 'date' && value === '') {
|
|
|
|
|
// inputValue = null;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'ON_CHANGE',
|
|
|
|
|
// keys: name.split('.'),
|
|
|
|
|
// value: inputValue,
|
|
|
|
|
// });
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// const handleSubmit = async e => {
|
|
|
|
|
// e.preventDefault();
|
|
|
|
|
// const schema = createYupSchema(layout, {
|
|
|
|
|
// components: componentLayoutsData,
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
// // Validate the form using yup
|
|
|
|
|
// await schema.validate(modifiedData, { abortEarly: false });
|
|
|
|
|
// // Set the loading state in the plugin header
|
|
|
|
|
// setIsSubmitting(true);
|
|
|
|
|
// emitEvent('willSaveEntry');
|
|
|
|
|
// // Create an object containing all the paths of the media fields
|
|
|
|
|
// const filesMap = getMediaAttributes(layout, componentLayoutsData);
|
|
|
|
|
// // Create an object that maps the keys with the related files to upload
|
|
|
|
|
// const filesToUpload = mapDataKeysToFilesToUpload(filesMap, modifiedData);
|
|
|
|
|
|
|
|
|
|
// const cleanedData = cleanData(
|
|
|
|
|
// cloneDeep(modifiedData),
|
|
|
|
|
// layout,
|
|
|
|
|
// componentLayoutsData
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// const formData = new FormData();
|
|
|
|
|
|
|
|
|
|
// formData.append('data', JSON.stringify(cleanedData));
|
|
|
|
|
|
|
|
|
|
// Object.keys(filesToUpload).forEach(key => {
|
|
|
|
|
// const files = filesToUpload[key];
|
|
|
|
|
|
|
|
|
|
// files.forEach(file => {
|
|
|
|
|
// formData.append(`files.${key}`, file);
|
|
|
|
|
// });
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// // Change the request helper default headers so we can pass a FormData
|
|
|
|
|
// const headers = {};
|
|
|
|
|
// const method = isCreatingEntry ? 'POST' : 'PUT';
|
|
|
|
|
// const endPoint = isCreatingEntry ? slug : `${slug}/${id}`;
|
|
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
// // Time to actually send the data
|
|
|
|
|
// await request(
|
|
|
|
|
// getRequestUrl(endPoint),
|
|
|
|
|
// {
|
|
|
|
|
// method,
|
|
|
|
|
// headers,
|
|
|
|
|
// params: { source },
|
|
|
|
|
// body: formData,
|
|
|
|
|
// signal,
|
|
|
|
|
// },
|
|
|
|
|
// false,
|
|
|
|
|
// false
|
|
|
|
|
// );
|
|
|
|
|
// emitEvent('didSaveEntry');
|
|
|
|
|
// redirectToPreviousPage();
|
|
|
|
|
// } catch (err) {
|
|
|
|
|
// const error = get(
|
|
|
|
|
// err,
|
|
|
|
|
// ['response', 'payload', 'message', '0', 'messages', '0', 'id'],
|
|
|
|
|
// 'SERVER ERROR'
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// setIsSubmitting(false);
|
|
|
|
|
// emitEvent('didNotSaveEntry', { error: err });
|
|
|
|
|
// strapi.notification.error(error);
|
|
|
|
|
// }
|
|
|
|
|
// } catch (err) {
|
|
|
|
|
// setIsSubmitting(false);
|
|
|
|
|
// const errors = get(err, 'inner', []).reduce((acc, curr) => {
|
|
|
|
|
// acc[
|
|
|
|
|
// curr.path
|
|
|
|
|
// .split('[')
|
|
|
|
|
// .join('.')
|
|
|
|
|
// .split(']')
|
|
|
|
|
// .join('')
|
|
|
|
|
// ] = [{ id: curr.message }];
|
|
|
|
|
|
|
|
|
|
// return acc;
|
|
|
|
|
// }, {});
|
|
|
|
|
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'SET_ERRORS',
|
|
|
|
|
// errors,
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// strapi.notification.error(
|
|
|
|
|
// `${pluginId}.containers.EditView.notification.errors`
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// // return null;
|
|
|
|
|
|
|
|
|
|
// return (
|
|
|
|
|
// <EditViewProvider
|
|
|
|
|
// addRelation={({ target: { name, value } }) => {
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'ADD_RELATION',
|
|
|
|
|
// keys: name.split('.'),
|
|
|
|
|
// value,
|
|
|
|
|
// });
|
|
|
|
|
// }}
|
|
|
|
|
// checkFormErrors={checkFormErrors}
|
|
|
|
|
// didCheckErrors={didCheckErrors}
|
|
|
|
|
// errors={errors}
|
|
|
|
|
// moveRelation={(dragIndex, overIndex, name) => {
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'MOVE_FIELD',
|
|
|
|
|
// dragIndex,
|
|
|
|
|
// overIndex,
|
|
|
|
|
// keys: name.split('.'),
|
|
|
|
|
// });
|
|
|
|
|
// }}
|
|
|
|
|
// onChange={handleChange}
|
|
|
|
|
// onRemove={keys => {
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'REMOVE_RELATION',
|
|
|
|
|
// keys,
|
|
|
|
|
// });
|
|
|
|
|
// }}
|
|
|
|
|
// pathname={pathname}
|
|
|
|
|
// resetErrors={() => {
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'SET_ERRORS',
|
|
|
|
|
// errors: {},
|
|
|
|
|
// });
|
|
|
|
|
// }}
|
|
|
|
|
// resetComponentData={componentName => {
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'RESET_COMPONENT_DATA',
|
|
|
|
|
// componentName,
|
|
|
|
|
// });
|
|
|
|
|
// }}
|
|
|
|
|
// search={search}
|
|
|
|
|
// >
|
|
|
|
|
// <BackHeader onClick={() => redirectToPreviousPage()} />
|
|
|
|
|
// <Container className="container-fluid">
|
|
|
|
|
// <form onSubmit={handleSubmit}>
|
|
|
|
|
// <PluginHeader
|
|
|
|
|
// actions={[
|
|
|
|
|
// {
|
|
|
|
|
// label: `${pluginId}.containers.Edit.reset`,
|
|
|
|
|
// kind: 'secondary',
|
|
|
|
|
// onClick: () => {
|
|
|
|
|
// toggleWarningCancel();
|
|
|
|
|
// },
|
|
|
|
|
// type: 'button',
|
|
|
|
|
// disabled: isSubmitting, // TODO STATE WHEN SUBMITING
|
|
|
|
|
// },
|
|
|
|
|
// {
|
|
|
|
|
// kind: 'primary',
|
|
|
|
|
// label: `${pluginId}.containers.Edit.submit`,
|
|
|
|
|
// type: 'submit',
|
|
|
|
|
// loader: isSubmitting,
|
|
|
|
|
// style: isSubmitting ? { marginRight: '18px' } : {},
|
|
|
|
|
// disabled: isSubmitting, // TODO STATE WHEN SUBMITING
|
|
|
|
|
// },
|
|
|
|
|
// ]}
|
|
|
|
|
// subActions={
|
|
|
|
|
// isCreatingEntry
|
|
|
|
|
// ? []
|
|
|
|
|
// : [
|
|
|
|
|
// {
|
|
|
|
|
// label: 'app.utils.delete',
|
|
|
|
|
// kind: 'delete',
|
|
|
|
|
// onClick: () => {
|
|
|
|
|
// toggleWarningDelete();
|
|
|
|
|
// },
|
|
|
|
|
// type: 'button',
|
|
|
|
|
// disabled: isSubmitting, // TODO STATE WHEN SUBMITING
|
|
|
|
|
// },
|
|
|
|
|
// ]
|
|
|
|
|
// }
|
|
|
|
|
// title={pluginHeaderTitle}
|
|
|
|
|
// />
|
|
|
|
|
// <div className="row">
|
|
|
|
|
// <div className="col-md-12 col-lg-9">
|
|
|
|
|
// <MainWrapper>
|
|
|
|
|
// {fields.map((fieldsRow, key) => {
|
|
|
|
|
// if (fieldsRow.length === 0) {
|
|
|
|
|
// return null;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const [{ name }] = fieldsRow;
|
|
|
|
|
// const component = get(
|
|
|
|
|
// layout,
|
|
|
|
|
// ['schema', 'attributes', name],
|
|
|
|
|
// {}
|
|
|
|
|
// );
|
|
|
|
|
// const componentMetas = get(
|
|
|
|
|
// layout,
|
|
|
|
|
// ['metadatas', name, 'edit'],
|
|
|
|
|
// {}
|
|
|
|
|
// );
|
|
|
|
|
// const componentValue = get(
|
|
|
|
|
// modifiedData,
|
|
|
|
|
// [name],
|
|
|
|
|
// component.repeatable ? [] : {}
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// if (
|
|
|
|
|
// fieldsRow.length === 1 &&
|
|
|
|
|
// component.type === 'component'
|
|
|
|
|
// ) {
|
|
|
|
|
// // Array containing all the keys with of the error object created by YUP
|
|
|
|
|
// // It is used only to know if whether or not we need to apply an orange border to the n+1 field item
|
|
|
|
|
// const componentErrorKeys = Object.keys(errors)
|
|
|
|
|
// .filter(errorKey => errorKey.includes(name))
|
|
|
|
|
// .map(errorKey =>
|
|
|
|
|
// errorKey
|
|
|
|
|
// .split('.')
|
|
|
|
|
// .slice(0, 2)
|
|
|
|
|
// .join('.')
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// return (
|
|
|
|
|
// <ComponentField
|
|
|
|
|
// {...component}
|
|
|
|
|
// {...componentMetas}
|
|
|
|
|
// addField={(keys, isRepeatable = true) => {
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'ADD_FIELD_TO_COMPONENT',
|
|
|
|
|
// keys: keys.split('.'),
|
|
|
|
|
// isRepeatable,
|
|
|
|
|
// });
|
|
|
|
|
// }}
|
|
|
|
|
// componentErrorKeys={componentErrorKeys}
|
|
|
|
|
// componentValue={componentValue}
|
|
|
|
|
// key={key}
|
|
|
|
|
// isRepeatable={component.repeatable || false}
|
|
|
|
|
// name={name}
|
|
|
|
|
// modifiedData={modifiedData}
|
|
|
|
|
// moveComponentField={(dragIndex, overIndex, name) => {
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'MOVE_FIELD',
|
|
|
|
|
// dragIndex,
|
|
|
|
|
// overIndex,
|
|
|
|
|
// keys: name.split('.'),
|
|
|
|
|
// });
|
|
|
|
|
// }}
|
|
|
|
|
// onChange={handleChange}
|
|
|
|
|
// layout={get(
|
|
|
|
|
// componentLayoutsData,
|
|
|
|
|
// component.component,
|
|
|
|
|
// {}
|
|
|
|
|
// )}
|
|
|
|
|
// pathname={pathname}
|
|
|
|
|
// removeField={(keys, shouldAddEmptyField) => {
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'ON_REMOVE_FIELD',
|
|
|
|
|
// keys: keys.split('.'),
|
|
|
|
|
// shouldAddEmptyField,
|
|
|
|
|
// });
|
|
|
|
|
// }}
|
|
|
|
|
// />
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// return (
|
|
|
|
|
// <div key={key} className="row">
|
|
|
|
|
// {fieldsRow.map(({ name }, index) => {
|
|
|
|
|
// return (
|
|
|
|
|
// <Inputs
|
|
|
|
|
// autoFocus={key === 0 && index === 0}
|
|
|
|
|
// didCheckErrors={didCheckErrors}
|
|
|
|
|
// errors={errors}
|
|
|
|
|
// key={name}
|
|
|
|
|
// keys={name}
|
|
|
|
|
// layout={layout}
|
|
|
|
|
// modifiedData={modifiedData}
|
|
|
|
|
// name={name}
|
|
|
|
|
// onChange={handleChange}
|
|
|
|
|
// />
|
|
|
|
|
// );
|
|
|
|
|
// })}
|
|
|
|
|
// </div>
|
|
|
|
|
// );
|
|
|
|
|
// })}
|
|
|
|
|
// </MainWrapper>
|
|
|
|
|
// </div>
|
|
|
|
|
// <div className="col-md-12 col-lg-3">
|
|
|
|
|
// {hasRelations && (
|
|
|
|
|
// <SubWrapper
|
|
|
|
|
// style={{ padding: '0 20px 1px', marginBottom: '26px' }}
|
|
|
|
|
// >
|
|
|
|
|
// <div style={{ paddingTop: '22px' }}>
|
|
|
|
|
// {displayedRelations.map(relationName => {
|
|
|
|
|
// const relation = get(
|
|
|
|
|
// layout,
|
|
|
|
|
// ['schema', 'attributes', relationName],
|
|
|
|
|
// {}
|
|
|
|
|
// );
|
|
|
|
|
// const relationMetas = get(
|
|
|
|
|
// layout,
|
|
|
|
|
// ['metadatas', relationName, 'edit'],
|
|
|
|
|
// {}
|
|
|
|
|
// );
|
|
|
|
|
// const value = get(modifiedData, [relationName], null);
|
|
|
|
|
|
|
|
|
|
// return (
|
|
|
|
|
// <SelectWrapper
|
|
|
|
|
// {...relation}
|
|
|
|
|
// {...relationMetas}
|
|
|
|
|
// key={relationName}
|
|
|
|
|
// name={relationName}
|
|
|
|
|
// relationsType={relation.relationType}
|
|
|
|
|
// value={value}
|
|
|
|
|
// />
|
|
|
|
|
// );
|
|
|
|
|
// })}
|
|
|
|
|
// </div>
|
|
|
|
|
// </SubWrapper>
|
|
|
|
|
// )}
|
|
|
|
|
// <LinkWrapper>
|
|
|
|
|
// <ul>
|
|
|
|
|
// <LiLink
|
|
|
|
|
// message={{
|
|
|
|
|
// id: 'app.links.configure-view',
|
|
|
|
|
// }}
|
|
|
|
|
// icon="layout"
|
|
|
|
|
// key={`${pluginId}.link`}
|
|
|
|
|
// // url={`/plugins/${pluginId}/ctm-configurations/edit-settings/content-types/${slug}${`?source=${source}`}`}
|
|
|
|
|
// url={`ctm-configurations/edit-settings/content-types${`?source=${source}`}`}
|
|
|
|
|
// onClick={() => {
|
|
|
|
|
// emitEvent('willEditContentTypeLayoutFromEditView');
|
|
|
|
|
// }}
|
|
|
|
|
// />
|
|
|
|
|
// {getInjectedComponents(
|
|
|
|
|
// 'right.links',
|
|
|
|
|
// plugins,
|
|
|
|
|
// currentEnvironment,
|
|
|
|
|
// slug,
|
|
|
|
|
// source,
|
|
|
|
|
// emitEvent
|
|
|
|
|
// )}
|
|
|
|
|
// </ul>
|
|
|
|
|
// </LinkWrapper>
|
|
|
|
|
// </div>
|
|
|
|
|
// </div>
|
|
|
|
|
// </form>
|
|
|
|
|
// <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={() => {
|
|
|
|
|
// dispatch({
|
|
|
|
|
// type: 'RESET_FORM',
|
|
|
|
|
// });
|
|
|
|
|
// toggleWarningCancel();
|
|
|
|
|
// }}
|
|
|
|
|
// />
|
|
|
|
|
// <PopUpWarning
|
|
|
|
|
// isOpen={showWarningDelete}
|
|
|
|
|
// toggleModal={toggleWarningDelete}
|
|
|
|
|
// content={{
|
|
|
|
|
// title: `${pluginId}.popUpWarning.title`,
|
|
|
|
|
// message: `${pluginId}.popUpWarning.bodyMessage.contentType.delete`,
|
|
|
|
|
// cancel: `${pluginId}.popUpWarning.button.cancel`,
|
|
|
|
|
// confirm: `${pluginId}.popUpWarning.button.confirm`,
|
|
|
|
|
// }}
|
|
|
|
|
// popUpWarningType="danger"
|
|
|
|
|
// onConfirm={handleConfirmDelete}
|
|
|
|
|
// />
|
|
|
|
|
// </Container>
|
|
|
|
|
// </EditViewProvider>
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// EditView.propTypes = {
|
|
|
|
|
// currentEnvironment: PropTypes.string.isRequired,
|
|
|
|
|
// emitEvent: PropTypes.func.isRequired,
|
|
|
|
|
// history: PropTypes.shape({
|
|
|
|
|
// push: PropTypes.func.isRequired,
|
|
|
|
|
// }),
|
|
|
|
|
// layouts: PropTypes.object,
|
|
|
|
|
// location: PropTypes.shape({
|
|
|
|
|
// pathname: PropTypes.string,
|
|
|
|
|
// search: PropTypes.string,
|
|
|
|
|
// }),
|
|
|
|
|
// slug: PropTypes.string.isRequired,
|
|
|
|
|
// plugins: PropTypes.object,
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// export default memo(EditView);
|