mirror of
https://github.com/strapi/strapi.git
synced 2025-09-04 22:32:57 +00:00
Handle edit attribute
This commit is contained in:
parent
f0f76e9606
commit
2e03cd90aa
@ -53,7 +53,14 @@ function AttributeLi({
|
|||||||
const configurableStyle = configurable === false ? null : styles.editable;
|
const configurableStyle = configurable === false ? null : styles.editable;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className={`${styles.attributeLi} ${relationStyle} ${configurableStyle}`} onClick={onClick}>
|
<li
|
||||||
|
className={`${styles.attributeLi} ${relationStyle} ${configurableStyle}`}
|
||||||
|
onClick={() => {
|
||||||
|
if (configurable !== false) {
|
||||||
|
onClick(name, type);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className={styles.flex}>
|
<div className={styles.flex}>
|
||||||
<div className={styles.nameContainer}>
|
<div className={styles.nameContainer}>
|
||||||
<img src={src} alt={`icon-${ico}`} />
|
<img src={src} alt={`icon-${ico}`} />
|
||||||
|
@ -23,6 +23,8 @@ import {
|
|||||||
RESET_EXISTING_CONTENT_TYPE_MAIN_INFOS,
|
RESET_EXISTING_CONTENT_TYPE_MAIN_INFOS,
|
||||||
RESET_EDIT_TEMP_CONTENT_TYPE,
|
RESET_EDIT_TEMP_CONTENT_TYPE,
|
||||||
RESET_PROPS,
|
RESET_PROPS,
|
||||||
|
SAVE_EDITED_ATTRIBUTE,
|
||||||
|
SET_TEMPORARY_ATTRIBUTE,
|
||||||
SUBMIT_TEMP_CONTENT_TYPE,
|
SUBMIT_TEMP_CONTENT_TYPE,
|
||||||
SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED,
|
SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED,
|
||||||
UPDATE_TEMP_CONTENT_TYPE,
|
UPDATE_TEMP_CONTENT_TYPE,
|
||||||
@ -140,6 +142,24 @@ export function onCreateAttribute({ target }) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function saveEditedAttribute(attributeName, isModelTemporary, modelName) {
|
||||||
|
return {
|
||||||
|
type: SAVE_EDITED_ATTRIBUTE,
|
||||||
|
attributeName,
|
||||||
|
isModelTemporary,
|
||||||
|
modelName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setTemporaryAttribute(attributeName, isModelTemporary, modelName) {
|
||||||
|
return {
|
||||||
|
type: SET_TEMPORARY_ATTRIBUTE,
|
||||||
|
attributeName,
|
||||||
|
isModelTemporary,
|
||||||
|
modelName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function resetNewContentTypeMainInfos() {
|
export function resetNewContentTypeMainInfos() {
|
||||||
return {
|
return {
|
||||||
type: RESET_NEW_CONTENT_TYPE_MAIN_INFOS,
|
type: RESET_NEW_CONTENT_TYPE_MAIN_INFOS,
|
||||||
|
@ -28,6 +28,8 @@ export const RESET_EXISTING_CONTENT_TYPE_MAIN_INFOS =
|
|||||||
'ContentTypeBuilder/App/RESET_EXISTING_CONTENT_TYPE_MAIN_INFOS';
|
'ContentTypeBuilder/App/RESET_EXISTING_CONTENT_TYPE_MAIN_INFOS';
|
||||||
export const RESET_EDIT_TEMP_CONTENT_TYPE = 'ContentTypeBuilder/App/RESET_EDIT_TEMP_CONTENT_TYPE';
|
export const RESET_EDIT_TEMP_CONTENT_TYPE = 'ContentTypeBuilder/App/RESET_EDIT_TEMP_CONTENT_TYPE';
|
||||||
export const RESET_PROPS = 'ContentTypeBuilder/App/RESET_PROPS';
|
export const RESET_PROPS = 'ContentTypeBuilder/App/RESET_PROPS';
|
||||||
|
export const SAVE_EDITED_ATTRIBUTE = 'ContentTypeBuilder/App/SAVE_EDITED_ATTRIBUTE';
|
||||||
|
export const SET_TEMPORARY_ATTRIBUTE = 'ContentTypeBuilder/App/SET_TEMPORARY_ATTRIBUTE';
|
||||||
export const SUBMIT_TEMP_CONTENT_TYPE = 'ContentTypeBuilder/App/SUBMIT_TEMP_CONTENT_TYPE';
|
export const SUBMIT_TEMP_CONTENT_TYPE = 'ContentTypeBuilder/App/SUBMIT_TEMP_CONTENT_TYPE';
|
||||||
export const SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED = 'ContentTypeBuilder/App/SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED';
|
export const SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED = 'ContentTypeBuilder/App/SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED';
|
||||||
export const UPDATE_TEMP_CONTENT_TYPE = 'ContentTypeBuilder/App/UPDATE_TEMP_CONTENT_TYPE';
|
export const UPDATE_TEMP_CONTENT_TYPE = 'ContentTypeBuilder/App/UPDATE_TEMP_CONTENT_TYPE';
|
||||||
|
@ -29,6 +29,8 @@ import {
|
|||||||
resetExistingContentTypeMainInfos,
|
resetExistingContentTypeMainInfos,
|
||||||
resetNewContentTypeMainInfos,
|
resetNewContentTypeMainInfos,
|
||||||
resetProps,
|
resetProps,
|
||||||
|
saveEditedAttribute,
|
||||||
|
setTemporaryAttribute,
|
||||||
updateTempContentType,
|
updateTempContentType,
|
||||||
} from './actions';
|
} from './actions';
|
||||||
|
|
||||||
@ -106,6 +108,7 @@ App.propTypes = {
|
|||||||
onChangeExistingContentTypeMainInfos: PropTypes.func.isRequired,
|
onChangeExistingContentTypeMainInfos: PropTypes.func.isRequired,
|
||||||
onChangeNewContentTypeMainInfos: PropTypes.func.isRequired,
|
onChangeNewContentTypeMainInfos: PropTypes.func.isRequired,
|
||||||
resetProps: PropTypes.func.isRequired,
|
resetProps: PropTypes.func.isRequired,
|
||||||
|
saveEditedAttribute: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = makeSelectApp();
|
const mapStateToProps = makeSelectApp();
|
||||||
@ -123,6 +126,8 @@ export function mapDispatchToProps(dispatch) {
|
|||||||
resetExistingContentTypeMainInfos,
|
resetExistingContentTypeMainInfos,
|
||||||
resetNewContentTypeMainInfos,
|
resetNewContentTypeMainInfos,
|
||||||
resetProps,
|
resetProps,
|
||||||
|
saveEditedAttribute,
|
||||||
|
setTemporaryAttribute,
|
||||||
updateTempContentType,
|
updateTempContentType,
|
||||||
},
|
},
|
||||||
dispatch,
|
dispatch,
|
||||||
|
@ -24,6 +24,8 @@ import {
|
|||||||
RESET_EDIT_EXISTING_CONTENT_TYPE,
|
RESET_EDIT_EXISTING_CONTENT_TYPE,
|
||||||
RESET_EDIT_TEMP_CONTENT_TYPE,
|
RESET_EDIT_TEMP_CONTENT_TYPE,
|
||||||
RESET_PROPS,
|
RESET_PROPS,
|
||||||
|
SAVE_EDITED_ATTRIBUTE,
|
||||||
|
SET_TEMPORARY_ATTRIBUTE,
|
||||||
SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED,
|
SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED,
|
||||||
UPDATE_TEMP_CONTENT_TYPE,
|
UPDATE_TEMP_CONTENT_TYPE,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
@ -158,6 +160,25 @@ function appReducer(state = initialState, action) {
|
|||||||
});
|
});
|
||||||
case RESET_PROPS:
|
case RESET_PROPS:
|
||||||
return initialState;
|
return initialState;
|
||||||
|
case SAVE_EDITED_ATTRIBUTE: {
|
||||||
|
const basePath = action.isModelTemporary ? ['newContentType'] : ['modifiedData', action.modelName];
|
||||||
|
|
||||||
|
return state.updateIn([...basePath, 'attributes'], attributes => {
|
||||||
|
const temporaryAttribute = state.get('temporaryAttribute');
|
||||||
|
const newAttribute = temporaryAttribute.remove('name');
|
||||||
|
|
||||||
|
return attributes.remove(action.attributeName).set(temporaryAttribute.get('name'), newAttribute);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case SET_TEMPORARY_ATTRIBUTE:
|
||||||
|
return state.update('temporaryAttribute', () => {
|
||||||
|
const basePath = action.isModelTemporary ? ['newContentType'] : ['modifiedData', action.modelName];
|
||||||
|
const attribute = state
|
||||||
|
.getIn([...basePath, 'attributes', action.attributeName])
|
||||||
|
.set('name', action.attributeName);
|
||||||
|
|
||||||
|
return attribute;
|
||||||
|
});
|
||||||
case SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED:
|
case SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED:
|
||||||
return state
|
return state
|
||||||
.updateIn(['initialData', state.getIn(['newContentType', 'name'])], () => state.get('newContentType'))
|
.updateIn(['initialData', state.getIn(['newContentType', 'name'])], () => state.get('newContentType'))
|
||||||
|
@ -46,6 +46,7 @@ describe('<App />', () => {
|
|||||||
modifiedData: {},
|
modifiedData: {},
|
||||||
onChangeExistingContentTypeMainInfos: jest.fn(),
|
onChangeExistingContentTypeMainInfos: jest.fn(),
|
||||||
onChangeNewContentTypeMainInfos: jest.fn(),
|
onChangeNewContentTypeMainInfos: jest.fn(),
|
||||||
|
saveEditedAttribute: jest.fn(),
|
||||||
resetProps: jest.fn(),
|
resetProps: jest.fn(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -40,15 +40,17 @@ class AttributeForm extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getFormErrors = () => {
|
getFormErrors = () => {
|
||||||
const { alreadyTakenAttributes, modifiedData } = this.props;
|
const { alreadyTakenAttributes, attributeToEditName, modifiedData } = this.props;
|
||||||
const currentForm = this.getCurrentForm();
|
const currentForm = this.getCurrentForm();
|
||||||
let formErrors = {};
|
let formErrors = {};
|
||||||
|
const alreadyTakenAttributesUpdated = alreadyTakenAttributes.filter(
|
||||||
|
attribute => attribute !== attributeToEditName,
|
||||||
|
);
|
||||||
if (isEmpty(modifiedData.name)) {
|
if (isEmpty(modifiedData.name)) {
|
||||||
formErrors = { name: [{ id: `${pluginId}.error.validation.required` }] };
|
formErrors = { name: [{ id: `${pluginId}.error.validation.required` }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alreadyTakenAttributes.includes(get(modifiedData, 'name', ''))) {
|
if (alreadyTakenAttributesUpdated.includes(get(modifiedData, 'name', ''))) {
|
||||||
formErrors = { name: [{ id: `${pluginId}.error.attribute.taken` }] };
|
formErrors = { name: [{ id: `${pluginId}.error.attribute.taken` }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,10 +83,10 @@ class AttributeForm extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleGoTo = to => {
|
handleGoTo = to => {
|
||||||
const { attributeType, push } = this.props;
|
const { actionType, attributeType, push } = this.props;
|
||||||
|
|
||||||
push({
|
push({
|
||||||
search: `modalType=attributeForm&attributeType=${attributeType}&settingType=${to}&actionType=create`,
|
search: `modalType=attributeForm&attributeType=${attributeType}&settingType=${to}&actionType=${actionType}`,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,7 +101,11 @@ class AttributeForm extends React.Component {
|
|||||||
|
|
||||||
handleSubmit = () => {
|
handleSubmit = () => {
|
||||||
if (isEmpty(this.getFormErrors())) {
|
if (isEmpty(this.getFormErrors())) {
|
||||||
|
if (this.props.actionType === 'create') {
|
||||||
this.props.onSubmit();
|
this.props.onSubmit();
|
||||||
|
} else {
|
||||||
|
this.props.onSubmitEdit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -107,7 +113,11 @@ class AttributeForm extends React.Component {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (isEmpty(this.getFormErrors())) {
|
if (isEmpty(this.getFormErrors())) {
|
||||||
|
if (this.props.actionType === 'create') {
|
||||||
this.props.onSubmit(true);
|
this.props.onSubmit(true);
|
||||||
|
} else {
|
||||||
|
this.props.onSubmitEdit(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -166,9 +176,10 @@ class AttributeForm extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { attributeType, isOpen } = this.props;
|
const { actionType, attributeToEditName, attributeType, isOpen } = this.props;
|
||||||
const { showForm } = this.state;
|
const { showForm } = this.state;
|
||||||
const currentForm = this.getCurrentForm();
|
const currentForm = this.getCurrentForm();
|
||||||
|
const titleContent = actionType === 'create' ? attributeType : attributeToEditName;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WrapperModal
|
<WrapperModal
|
||||||
@ -179,9 +190,9 @@ class AttributeForm extends React.Component {
|
|||||||
>
|
>
|
||||||
<HeaderModal>
|
<HeaderModal>
|
||||||
<div style={{ fontSize: '1.8rem', fontWeight: 'bold' }}>
|
<div style={{ fontSize: '1.8rem', fontWeight: 'bold' }}>
|
||||||
<FormattedMessage id={`${pluginId}.popUpForm.create`} />
|
<FormattedMessage id={`${pluginId}.popUpForm.${actionType || 'create'}`} />
|
||||||
|
|
||||||
<span style={{ fontStyle: 'italic', textTransform: 'capitalize' }}>{attributeType}</span>
|
<span style={{ fontStyle: 'italic', textTransform: 'capitalize' }}>{titleContent}</span>
|
||||||
|
|
||||||
<FormattedMessage id={`${pluginId}.popUpForm.field`} />
|
<FormattedMessage id={`${pluginId}.popUpForm.field`} />
|
||||||
</div>
|
</div>
|
||||||
@ -205,7 +216,9 @@ class AttributeForm extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AttributeForm.defaultProps = {
|
AttributeForm.defaultProps = {
|
||||||
|
actionType: 'create',
|
||||||
activeTab: 'base',
|
activeTab: 'base',
|
||||||
|
attributeToEditName: '',
|
||||||
alreadyTakenAttributes: [],
|
alreadyTakenAttributes: [],
|
||||||
attributeType: 'string',
|
attributeType: 'string',
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
@ -216,14 +229,17 @@ AttributeForm.defaultProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
AttributeForm.propTypes = {
|
AttributeForm.propTypes = {
|
||||||
|
actionType: PropTypes.string,
|
||||||
activeTab: PropTypes.string,
|
activeTab: PropTypes.string,
|
||||||
alreadyTakenAttributes: PropTypes.array,
|
alreadyTakenAttributes: PropTypes.array,
|
||||||
|
attributeToEditName: PropTypes.string,
|
||||||
attributeType: PropTypes.string,
|
attributeType: PropTypes.string,
|
||||||
isOpen: PropTypes.bool,
|
isOpen: PropTypes.bool,
|
||||||
modifiedData: PropTypes.object, // TODO: Clearly define this object (It's working without it though)
|
modifiedData: PropTypes.object, // TODO: Clearly define this object (It's working without it though)
|
||||||
onCancel: PropTypes.func,
|
onCancel: PropTypes.func,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
onSubmit: PropTypes.func.isRequired,
|
onSubmit: PropTypes.func.isRequired,
|
||||||
|
onSubmitEdit: PropTypes.func.isRequired,
|
||||||
push: PropTypes.func,
|
push: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ describe('<AttributeForm />', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
props = {
|
props = {
|
||||||
onSubmit: jest.fn(),
|
onSubmit: jest.fn(),
|
||||||
|
onSubmitEdit: jest.fn(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,7 +19,8 @@ import WrapperModal from '../../components/WrapperModal';
|
|||||||
|
|
||||||
import attributes from './attributes.json';
|
import attributes from './attributes.json';
|
||||||
|
|
||||||
class AttributesPickerModal extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
class AttributesPickerModal extends React.Component {
|
||||||
|
// eslint-disable-line react/prefer-stateless-function
|
||||||
state = { isDisplayed: false, nodeToFocus: 0 };
|
state = { isDisplayed: false, nodeToFocus: 0 };
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -55,24 +56,24 @@ class AttributesPickerModal extends React.Component { // eslint-disable-line rea
|
|||||||
|
|
||||||
return attr.type !== 'media';
|
return attr.type !== 'media';
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
addEventListener = () => {
|
addEventListener = () => {
|
||||||
document.addEventListener('keydown', this.handleKeyDown);
|
document.addEventListener('keydown', this.handleKeyDown);
|
||||||
}
|
};
|
||||||
|
|
||||||
removeEventListener = () => {
|
removeEventListener = () => {
|
||||||
document.removeEventListener('keydown', this.handleKeyDown);
|
document.removeEventListener('keydown', this.handleKeyDown);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleClick = (type) => {
|
handleClick = type => {
|
||||||
const { push } = this.props;
|
const { push } = this.props;
|
||||||
|
|
||||||
push({ search: `modalType=attributeForm&attributeType=${type}&settingType=base` });
|
push({ search: `modalType=attributeForm&attributeType=${type}&settingType=base&actionType=create` });
|
||||||
}
|
};
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
handleKeyDown = (e) => {
|
handleKeyDown = e => {
|
||||||
const { push } = this.props;
|
const { push } = this.props;
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
@ -101,7 +102,9 @@ class AttributesPickerModal extends React.Component { // eslint-disable-line rea
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
push({
|
push({
|
||||||
search: `modalType=attributeForm&attributeType=${attributes[nodeToFocus].type}&settingType=base`,
|
search: `modalType=attributeForm&attributeType=${
|
||||||
|
attributes[nodeToFocus].type
|
||||||
|
}&settingType=base&actionType=create`,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -110,7 +113,7 @@ class AttributesPickerModal extends React.Component { // eslint-disable-line rea
|
|||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
this.updateNodeToFocus(next);
|
this.updateNodeToFocus(next);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleOnClosed = () => this.setState(prevState => ({ isDisplayed: !prevState.isDisplayed }));
|
handleOnClosed = () => this.setState(prevState => ({ isDisplayed: !prevState.isDisplayed }));
|
||||||
|
|
||||||
@ -120,7 +123,7 @@ class AttributesPickerModal extends React.Component { // eslint-disable-line rea
|
|||||||
const { push } = this.props;
|
const { push } = this.props;
|
||||||
|
|
||||||
push({ search: '' });
|
push({ search: '' });
|
||||||
}
|
};
|
||||||
|
|
||||||
updateNodeToFocus = position => this.setState({ nodeToFocus: position });
|
updateNodeToFocus = position => this.setState({ nodeToFocus: position });
|
||||||
|
|
||||||
@ -138,7 +141,7 @@ class AttributesPickerModal extends React.Component { // eslint-disable-line rea
|
|||||||
{...attribute}
|
{...attribute}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isOpen } = this.props;
|
const { isOpen } = this.props;
|
||||||
@ -151,13 +154,9 @@ class AttributesPickerModal extends React.Component { // eslint-disable-line rea
|
|||||||
onOpened={this.handleOnOpened}
|
onOpened={this.handleOnOpened}
|
||||||
>
|
>
|
||||||
<HeaderModal>
|
<HeaderModal>
|
||||||
<HeaderModalTitle
|
<HeaderModalTitle title={`${pluginId}.popUpForm.choose.attributes.header.title`} />
|
||||||
title={`${pluginId}.popUpForm.choose.attributes.header.title`}
|
|
||||||
/>
|
|
||||||
</HeaderModal>
|
</HeaderModal>
|
||||||
<BodyModal style={{ paddingTop: '2.3rem' }}>
|
<BodyModal style={{ paddingTop: '2.3rem' }}>{attributes.map(this.renderAttribute)}</BodyModal>
|
||||||
{attributes.map(this.renderAttribute)}
|
|
||||||
</BodyModal>
|
|
||||||
<FooterModal />
|
<FooterModal />
|
||||||
</WrapperModal>
|
</WrapperModal>
|
||||||
);
|
);
|
||||||
|
@ -11,7 +11,8 @@ import AttributesPickerModal from '../index';
|
|||||||
|
|
||||||
const messages = formatMessagesWithPluginId(pluginId, pluginTradsEn);
|
const messages = formatMessagesWithPluginId(pluginId, pluginTradsEn);
|
||||||
|
|
||||||
const renderComponent = (props = {}, context = {}) => mountWithIntl(<AttributesPickerModal {...props} />, messages, context);
|
const renderComponent = (props = {}, context = {}) =>
|
||||||
|
mountWithIntl(<AttributesPickerModal {...props} />, messages, context);
|
||||||
|
|
||||||
describe('<AttributesPickerModal />', () => {
|
describe('<AttributesPickerModal />', () => {
|
||||||
let props;
|
let props;
|
||||||
@ -80,8 +81,8 @@ describe('<AttributesPickerModal />', () => {
|
|||||||
const { getAttributes } = wrapper.instance();
|
const { getAttributes } = wrapper.instance();
|
||||||
|
|
||||||
expect(getAttributes()).not.toContain({
|
expect(getAttributes()).not.toContain({
|
||||||
"type": "media",
|
type: 'media',
|
||||||
"description": "content-type-builder.popUpForm.attributes.media.description",
|
description: 'content-type-builder.popUpForm.attributes.media.description',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -89,15 +90,15 @@ describe('<AttributesPickerModal />', () => {
|
|||||||
const context = {
|
const context = {
|
||||||
plugins: {
|
plugins: {
|
||||||
'content-type-builder': {},
|
'content-type-builder': {},
|
||||||
'upload': {},
|
upload: {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const wrapper = renderComponent(props, context);
|
const wrapper = renderComponent(props, context);
|
||||||
const { getAttributes } = wrapper.instance();
|
const { getAttributes } = wrapper.instance();
|
||||||
|
|
||||||
expect(getAttributes()).toContainEqual({
|
expect(getAttributes()).toContainEqual({
|
||||||
"type": "media",
|
type: 'media',
|
||||||
"description": "content-type-builder.popUpForm.attributes.media.description",
|
description: 'content-type-builder.popUpForm.attributes.media.description',
|
||||||
});
|
});
|
||||||
|
|
||||||
wrapper.unmount();
|
wrapper.unmount();
|
||||||
@ -107,7 +108,7 @@ describe('<AttributesPickerModal />', () => {
|
|||||||
const context = {
|
const context = {
|
||||||
plugins: fromJS({
|
plugins: fromJS({
|
||||||
'content-type-builder': {},
|
'content-type-builder': {},
|
||||||
'upload': {},
|
upload: {},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
const wrapper = renderComponent(props, context);
|
const wrapper = renderComponent(props, context);
|
||||||
@ -154,7 +155,7 @@ describe('<AttributesPickerModal />', () => {
|
|||||||
const context = {
|
const context = {
|
||||||
plugins: fromJS({
|
plugins: fromJS({
|
||||||
'content-type-builder': {},
|
'content-type-builder': {},
|
||||||
'upload': {},
|
upload: {},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
const wrapper = renderComponent(props, context);
|
const wrapper = renderComponent(props, context);
|
||||||
@ -175,7 +176,9 @@ describe('<AttributesPickerModal />', () => {
|
|||||||
|
|
||||||
handleClick('test');
|
handleClick('test');
|
||||||
|
|
||||||
expect(props.push).toHaveBeenCalledWith({ search: 'modalType=attributeForm&attributeType=test&settingType=base' });
|
expect(props.push).toHaveBeenCalledWith({
|
||||||
|
search: 'modalType=attributeForm&attributeType=test&settingType=base&actionType=create',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -62,6 +62,22 @@ export class ModelPage extends React.Component {
|
|||||||
// eslint-disable-line react/prefer-stateless-function
|
// eslint-disable-line react/prefer-stateless-function
|
||||||
state = { attrToDelete: null, removePrompt: false, showWarning: false };
|
state = { attrToDelete: null, removePrompt: false, showWarning: false };
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { setTemporaryAttribute } = this.props;
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.getModalType() === 'attributeForm' &&
|
||||||
|
this.getActionType() === 'edit' &&
|
||||||
|
!this.isTryingToEditAnUnknownAttribute()
|
||||||
|
) {
|
||||||
|
setTemporaryAttribute(
|
||||||
|
this.getAttributeName(),
|
||||||
|
this.isUpdatingTemporaryContentType(),
|
||||||
|
this.getModelName(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const {
|
const {
|
||||||
location: { search },
|
location: { search },
|
||||||
@ -80,20 +96,22 @@ export class ModelPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getFormData = () => {
|
getActionType = () => getQueryParameters(this.getSearch(), 'actionType');
|
||||||
const {
|
|
||||||
location: { search },
|
|
||||||
modifiedData,
|
|
||||||
newContentType,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (getQueryParameters(search, 'actionType') === 'create' || this.isUpdatingTemporaryContentType()) {
|
getAttributeName = () => getQueryParameters(this.getSearch(), 'attributeName');
|
||||||
|
|
||||||
|
getFormData = () => {
|
||||||
|
const { modifiedData, newContentType } = this.props;
|
||||||
|
|
||||||
|
if (this.getActionType() === 'create' || this.isUpdatingTemporaryContentType()) {
|
||||||
return newContentType;
|
return newContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return get(modifiedData, this.getModelName());
|
return get(modifiedData, this.getModelName());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getModalType = () => getQueryParameters(this.getSearch(), 'modalType');
|
||||||
|
|
||||||
getModel = () => {
|
getModel = () => {
|
||||||
const { modifiedData, newContentType } = this.props;
|
const { modifiedData, newContentType } = this.props;
|
||||||
|
|
||||||
@ -194,14 +212,41 @@ export class ModelPage extends React.Component {
|
|||||||
return title;
|
return title;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getSearch = () => {
|
||||||
|
const {
|
||||||
|
location: { search },
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return search;
|
||||||
|
};
|
||||||
|
|
||||||
getSectionTitle = () => {
|
getSectionTitle = () => {
|
||||||
const base = `${pluginId}.menu.section.contentTypeBuilder.name.`;
|
const base = `${pluginId}.menu.section.contentTypeBuilder.name.`;
|
||||||
|
|
||||||
return this.getModelsNumber() > 1 ? `${base}plural` : `${base}singular`;
|
return this.getModelsNumber() > 1 ? `${base}plural` : `${base}singular`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleClickEditAttribute = async (attributeName, type) => {
|
||||||
|
// modalType=attributeForm&attributeType=boolean&settingType=base
|
||||||
|
const {
|
||||||
|
history: { push },
|
||||||
|
} = this.props;
|
||||||
|
const attributeType = ['integer', 'biginteger', 'float', 'decimal'].includes(type) ? 'number' : type;
|
||||||
|
|
||||||
|
this.props.setTemporaryAttribute(
|
||||||
|
attributeName,
|
||||||
|
this.isUpdatingTemporaryContentType(),
|
||||||
|
this.getModelName(),
|
||||||
|
);
|
||||||
|
await this.wait();
|
||||||
|
push({
|
||||||
|
search: `modalType=attributeForm&attributeType=${attributeType}&settingType=base&actionType=edit&attributeName=${attributeName}`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
handleClickEditModelMainInfos = async () => {
|
handleClickEditModelMainInfos = async () => {
|
||||||
const { canOpenModal } = this.props;
|
const { canOpenModal } = this.props;
|
||||||
|
|
||||||
await this.wait();
|
await this.wait();
|
||||||
|
|
||||||
if (canOpenModal || this.isUpdatingTemporaryContentType()) {
|
if (canOpenModal || this.isUpdatingTemporaryContentType()) {
|
||||||
@ -284,15 +329,25 @@ export class ModelPage extends React.Component {
|
|||||||
push({ search: nextSearch });
|
push({ search: nextSearch });
|
||||||
};
|
};
|
||||||
|
|
||||||
hasModelBeenModified = () => {
|
handleSubmitEdit = (shouldContinue = false) => {
|
||||||
const {
|
const {
|
||||||
initialData,
|
history: { push },
|
||||||
location: { search },
|
saveEditedAttribute,
|
||||||
modifiedData,
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
const attributeName = this.getAttributeName();
|
||||||
|
|
||||||
|
saveEditedAttribute(attributeName, this.isUpdatingTemporaryContentType(), this.getModelName());
|
||||||
|
|
||||||
|
const nextSearch = shouldContinue ? 'modalType=chooseAttributes' : '';
|
||||||
|
|
||||||
|
push({ search: nextSearch });
|
||||||
|
};
|
||||||
|
|
||||||
|
hasModelBeenModified = () => {
|
||||||
|
const { initialData, modifiedData } = this.props;
|
||||||
const currentModel = this.getModelName();
|
const currentModel = this.getModelName();
|
||||||
|
|
||||||
return !isEqual(initialData[currentModel], modifiedData[currentModel]) && search === '';
|
return !isEqual(initialData[currentModel], modifiedData[currentModel]) && this.getSearch() === '';
|
||||||
};
|
};
|
||||||
|
|
||||||
isUpdatingTemporaryContentType = (modelName = this.getModelName()) => {
|
isUpdatingTemporaryContentType = (modelName = this.getModelName()) => {
|
||||||
@ -307,10 +362,19 @@ export class ModelPage extends React.Component {
|
|||||||
|
|
||||||
setPrompt = () => this.setState({ removePrompt: false });
|
setPrompt = () => this.setState({ removePrompt: false });
|
||||||
|
|
||||||
|
isTryingToEditAnUnknownAttribute = () => {
|
||||||
|
const hasAttribute = Object.keys(this.getModelAttributes()).indexOf(this.getAttributeName()) !== -1;
|
||||||
|
|
||||||
|
return this.getActionType() === 'edit' && this.getModalType() === 'attributeForm' && !hasAttribute;
|
||||||
|
};
|
||||||
|
|
||||||
shouldRedirect = () => {
|
shouldRedirect = () => {
|
||||||
const { models } = this.props;
|
const { models } = this.props;
|
||||||
|
|
||||||
return models.findIndex(model => model.name === this.getModelName()) === -1;
|
return (
|
||||||
|
models.findIndex(model => model.name === this.getModelName()) === -1 ||
|
||||||
|
this.isTryingToEditAnUnknownAttribute()
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleModalWarning = () => this.setState(prevState => ({ showWarning: !prevState.showWarning }));
|
toggleModalWarning = () => this.setState(prevState => ({ showWarning: !prevState.showWarning }));
|
||||||
@ -353,6 +417,7 @@ export class ModelPage extends React.Component {
|
|||||||
key={attribute}
|
key={attribute}
|
||||||
name={attribute}
|
name={attribute}
|
||||||
attributeInfos={attributeInfos}
|
attributeInfos={attributeInfos}
|
||||||
|
onClick={this.handleClickEditAttribute}
|
||||||
onClickOnTrashIcon={this.handleClickOnTrashIcon}
|
onClickOnTrashIcon={this.handleClickOnTrashIcon}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -385,10 +450,11 @@ export class ModelPage extends React.Component {
|
|||||||
return <Redirect to={to} />;
|
return <Redirect to={to} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalType = getQueryParameters(search, 'modalType');
|
// const modalType = getQueryParameters(search, 'modalType');
|
||||||
|
const modalType = this.getModalType();
|
||||||
const settingType = getQueryParameters(search, 'settingType');
|
const settingType = getQueryParameters(search, 'settingType');
|
||||||
const attributeType = getQueryParameters(search, 'attributeType');
|
const attributeType = getQueryParameters(search, 'attributeType');
|
||||||
const actionType = getQueryParameters(search, 'actionType');
|
const actionType = this.getActionType();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.modelpage}>
|
<div className={styles.modelpage}>
|
||||||
@ -473,15 +539,18 @@ export class ModelPage extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<AttributesModalPicker isOpen={modalType === 'chooseAttributes'} push={push} />
|
<AttributesModalPicker isOpen={modalType === 'chooseAttributes'} push={push} />
|
||||||
<AttributeForm
|
<AttributeForm
|
||||||
|
actionType={actionType}
|
||||||
activeTab={settingType}
|
activeTab={settingType}
|
||||||
alreadyTakenAttributes={Object.keys(this.getModelAttributes())}
|
alreadyTakenAttributes={Object.keys(this.getModelAttributes())}
|
||||||
attributeType={attributeType}
|
attributeType={attributeType}
|
||||||
|
attributeToEditName={this.getAttributeName()}
|
||||||
isContentTypeTemporary={this.isUpdatingTemporaryContentType()}
|
isContentTypeTemporary={this.isUpdatingTemporaryContentType()}
|
||||||
isOpen={modalType === 'attributeForm' && attributeType !== 'relation'}
|
isOpen={modalType === 'attributeForm' && attributeType !== 'relation'}
|
||||||
modifiedData={temporaryAttribute}
|
modifiedData={temporaryAttribute}
|
||||||
onCancel={clearTemporaryAttribute}
|
onCancel={clearTemporaryAttribute}
|
||||||
onChange={onCreateAttribute}
|
onChange={onCreateAttribute}
|
||||||
onSubmit={this.handleSubmit}
|
onSubmit={this.handleSubmit}
|
||||||
|
onSubmitEdit={this.handleSubmitEdit}
|
||||||
push={push}
|
push={push}
|
||||||
/>
|
/>
|
||||||
<ModelForm
|
<ModelForm
|
||||||
|
Loading…
x
Reference in New Issue
Block a user