Handle edit attribute

This commit is contained in:
soupette 2019-03-20 11:34:12 +01:00
parent f0f76e9606
commit 2e03cd90aa
11 changed files with 197 additions and 53 deletions

View File

@ -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}`} />

View File

@ -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,

View File

@ -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';

View File

@ -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,

View File

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

View File

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

View File

@ -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'}`} />
&nbsp; &nbsp;
<span style={{ fontStyle: 'italic', textTransform: 'capitalize' }}>{attributeType}</span> <span style={{ fontStyle: 'italic', textTransform: 'capitalize' }}>{titleContent}</span>
&nbsp; &nbsp;
<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,
}; };

View File

@ -19,6 +19,7 @@ describe('<AttributeForm />', () => {
beforeEach(() => { beforeEach(() => {
props = { props = {
onSubmit: jest.fn(), onSubmit: jest.fn(),
onSubmitEdit: jest.fn(),
}; };
}); });

View File

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

View File

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

View File

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