diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js index 61a0e47d73..2620850117 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/actions.js @@ -37,21 +37,27 @@ import { RESET_NEW_CONTENT_TYPE_MAIN_INFOS, RESET_EDIT_EXISTING_CONTENT_TYPE, RESET_EXISTING_CONTENT_TYPE_MAIN_INFOS, + RESET_EXISTING_GROUP_MAIN_INFOS, RESET_EDIT_TEMP_CONTENT_TYPE, RESET_EDIT_TEMP_GROUP, RESET_PROPS, SAVE_EDITED_ATTRIBUTE, + SAVE_EDITED_ATTRIBUTE_GROUP, SAVE_EDITED_ATTRIBUTE_RELATION, SET_TEMPORARY_ATTRIBUTE, + SET_TEMPORARY_ATTRIBUTE_GROUP, SET_TEMPORARY_ATTRIBUTE_RELATION, SUBMIT_CONTENT_TYPE, SUBMIT_CONTENT_TYPE_SUCCEEDED, + SUBMIT_GROUP, + SUBMIT_GROUP_SUCCEEDED, SUBMIT_TEMP_CONTENT_TYPE, SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED, SUBMIT_TEMP_GROUP, SUBMIT_TEMP_GROUP_SUCCEEDED, UPDATE_TEMP_CONTENT_TYPE, ON_CHANGE_EXISTING_CONTENT_TYPE_MAIN_INFOS, + ON_CHANGE_EXISTING_GROUP_MAIN_INFOS, } from './constants'; export function addAttributeRelation(isModelTemporary, modelName) { @@ -267,6 +273,22 @@ export function onChangeExistingContentTypeMainInfos({ target }) { }; } +export function onChangeExistingGroupMainInfos({ target }) { + const value = + target.name === 'name' + ? camelCase(target.value.trim()).toLowerCase() + : target.value; + + const array = target.name.split('.'); + array.splice(1, 0, 'schema'); + + return { + type: ON_CHANGE_EXISTING_GROUP_MAIN_INFOS, + keys: array, + value, + }; +} + export function onChangeNewContentTypeMainInfos({ target }) { const value = target.name === 'name' @@ -365,6 +387,13 @@ export function resetExistingContentTypeMainInfos(contentTypeName) { }; } +export function resetExistingGroupMainInfos(groupName) { + return { + type: RESET_EXISTING_GROUP_MAIN_INFOS, + groupName, + }; +} + export function resetEditTempContentType() { return { type: RESET_EDIT_TEMP_CONTENT_TYPE, @@ -396,6 +425,19 @@ export function saveEditedAttribute( }; } +export function saveEditedAttributeGroup( + attributeIndex, + isGroupTemporary, + groupName +) { + return { + type: SAVE_EDITED_ATTRIBUTE_GROUP, + attributeIndex, + isGroupTemporary, + groupName, + }; +} + export function saveEditedAttributeRelation( attributeName, isModelTemporary, @@ -422,6 +464,19 @@ export function setTemporaryAttribute( }; } +export function setTemporaryAttributeGroup( + attributeIndex, + isGroupTemporary, + groupName +) { + return { + type: SET_TEMPORARY_ATTRIBUTE_GROUP, + attributeIndex, + isGroupTemporary, + groupName, + }; +} + export function setTemporaryAttributeRelation( target, isModelTemporary, @@ -452,6 +507,19 @@ export function submitContentType(oldContentTypeName, data, context, source) { }; } +export function submitGroup(oldGroupName, data, context, source) { + const attributes = formatGroupAttributes(data.attributes); + const body = Object.assign(cloneDeep(data), { attributes }); + + return { + type: SUBMIT_GROUP, + oldGroupName, + body, + source, + context, + }; +} + export function submitContentTypeSucceeded() { return { type: SUBMIT_CONTENT_TYPE_SUCCEEDED, @@ -469,6 +537,12 @@ export function submitTempContentType(data, context) { }; } +export function submitGroupSucceeded() { + return { + type: SUBMIT_GROUP_SUCCEEDED, + }; +} + export function submitTempContentTypeSucceeded() { return { type: SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED, diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js index 41264a7dd2..7eba83fcbe 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/constants.js @@ -43,6 +43,8 @@ export const GET_DATA = 'ContentTypeBuilder/App/GET_DATA'; export const GET_DATA_SUCCEEDED = 'ContentTypeBuilder/App/GET_DATA_SUCCEEDED'; export const ON_CHANGE_EXISTING_CONTENT_TYPE_MAIN_INFOS = 'ContentTypeBuilder/App/ON_CHANGE_EXISTING_CONTENT_TYPE_MAIN_INFOS'; +export const ON_CHANGE_EXISTING_GROUP_MAIN_INFOS = + 'ContentTypeBuilder/App/ON_CHANGE_EXISTING_GROUP_MAIN_INFOS'; export const ON_CHANGE_NEW_CONTENT_TYPE_MAIN_INFOS = 'ContentTypeBuilder/App/ON_CHANGE_NEW_CONTENT_TYPE_MAIN_INFOS'; export const ON_CHANGE_NEW_GROUP_MAIN_INFOS = @@ -61,6 +63,8 @@ export const RESET_EDIT_EXISTING_CONTENT_TYPE = 'ContentTypeBuilder/App/RESET_EDIT_EXISTING_CONTENT_TYPE'; export const RESET_EXISTING_CONTENT_TYPE_MAIN_INFOS = 'ContentTypeBuilder/App/RESET_EXISTING_CONTENT_TYPE_MAIN_INFOS'; +export const RESET_EXISTING_GROUP_MAIN_INFOS = + 'ContentTypeBuilder/App/RESET_EXISTING_GROUP_MAIN_INFOS'; export const RESET_EDIT_TEMP_CONTENT_TYPE = 'ContentTypeBuilder/App/RESET_EDIT_TEMP_CONTENT_TYPE'; export const RESET_EDIT_TEMP_GROUP = @@ -68,15 +72,22 @@ export const RESET_EDIT_TEMP_GROUP = export const RESET_PROPS = 'ContentTypeBuilder/App/RESET_PROPS'; export const SAVE_EDITED_ATTRIBUTE = 'ContentTypeBuilder/App/SAVE_EDITED_ATTRIBUTE'; +export const SAVE_EDITED_ATTRIBUTE_GROUP = + 'ContentTypeBuilder/App/SAVE_EDITED_ATTRIBUTE_GROUP'; export const SAVE_EDITED_ATTRIBUTE_RELATION = 'ContentTypeBuilder/App/SAVE_EDITED_ATTRIBUTE_RELATION'; export const SET_TEMPORARY_ATTRIBUTE = 'ContentTypeBuilder/App/SET_TEMPORARY_ATTRIBUTE'; +export const SET_TEMPORARY_ATTRIBUTE_GROUP = + 'ContentTypeBuilder/App/SET_TEMPORARY_ATTRIBUTE_GROUP'; export const SET_TEMPORARY_ATTRIBUTE_RELATION = 'ContentTypeBuilder/App/SET_TEMPORARY_ATTRIBUTE_RELATION'; export const SUBMIT_CONTENT_TYPE = 'ContentTypeBuilder/App/SUBMIT_CONTENT_TYPE'; export const SUBMIT_CONTENT_TYPE_SUCCEEDED = 'ContentTypeBuilder/App/SUBMIT_CONTENT_TYPE_SUCCEEDED'; +export const SUBMIT_GROUP = 'ContentTypeBuilder/App/SUBMIT_GROUP'; +export const SUBMIT_GROUP_SUCCEEDED = + 'ContentTypeBuilder/App/SUBMIT_GROUP_SUCCEEDED'; export const SUBMIT_TEMP_CONTENT_TYPE = 'ContentTypeBuilder/App/SUBMIT_TEMP_CONTENT_TYPE'; export const SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED = diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js index e7077d0983..054638ad3f 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/index.js @@ -35,6 +35,7 @@ import { deleteTemporaryModel, getData, onChangeExistingContentTypeMainInfos, + onChangeExistingGroupMainInfos, onChangeNewContentTypeMainInfos, onChangeNewGroupMainInfos, onChangeRelation, @@ -42,6 +43,7 @@ import { onChangeRelationTarget, resetExistingContentTypeMainInfos, resetNewContentTypeMainInfos, + resetExistingGroupMainInfos, resetProps, saveEditedAttribute, saveEditedAttributeRelation, @@ -124,8 +126,31 @@ export class App extends React.Component { return get(modifiedData, this.getFeatureNameFromSearch(), {}); }; + getFormDataForGroup = () => { + const { modifiedDataGroup, newGroup } = this.props; + + if (this.isUpdatingTemporaryFeature()) { + return newGroup; + } + + return get( + modifiedDataGroup, + [this.getFeatureNameFromSearch(), 'schema'], + {} + ); + }; + + // getFeatureName = () => { + // const { modifiedDataGroup } = this.props; + // return get( + // modifiedDataGroup, + // [this.getFeatureNameFromSearch(), 'schema', 'name'], + // {} + // ); + // }; + getFeatureNameFromSearch = () => - getQueryParameters(this.getSearch(), 'modelName'); + getQueryParameters(this.getSearch(), `${this.getFeatureType()}Name`); isUpdatingTemporaryModel = (modelName = this.getFeatureNameFromSearch()) => { const { models } = this.props; @@ -184,11 +209,12 @@ export class App extends React.Component { location: { pathname, search }, isLoading, models, - newGroup, onChangeExistingContentTypeMainInfos, + onChangeExistingGroupMainInfos, onChangeNewContentTypeMainInfos, onChangeNewGroupMainInfos, resetExistingContentTypeMainInfos, + resetExistingGroupMainInfos, resetNewContentTypeMainInfos, updateTempContentType, } = this.props; @@ -223,18 +249,17 @@ export class App extends React.Component { activeTab: getQueryParameters(search, 'settingType'), allTakenNames: this.getAllGroupsAndModelsNames(), cancelNewFeature: () => {}, - connections, createTempFeature: createTempGroup, featureToEditName: this.getFeatureNameFromSearch(), featureType: 'group', isOpen: getQueryParameters(search, 'modalType') === 'group', isUpdatingTemporaryFeature: this.isUpdatingTemporaryFeature(), - modifiedData: newGroup, - onChangeExistingFeatureMainInfos: () => {}, + modifiedData: this.getFormDataForGroup(), + onChangeExistingFeatureMainInfos: onChangeExistingGroupMainInfos, onChangeNewFeatureMainInfos: onChangeNewGroupMainInfos, pathname, push, - resetExistingFeatureMainInfos: () => {}, + resetExistingFeatureMainInfos: resetExistingGroupMainInfos, resetNewFeatureMainInfos: () => {}, updateTempFeature: () => {}, }, @@ -281,9 +306,11 @@ App.propTypes = { location: PropTypes.object.isRequired, models: PropTypes.array.isRequired, modifiedData: PropTypes.object.isRequired, + modifiedDataGroup: PropTypes.object.isRequired, newContentType: PropTypes.object.isRequired, newGroup: PropTypes.object.isRequired, onChangeExistingContentTypeMainInfos: PropTypes.func.isRequired, + onChangeExistingGroupMainInfos: PropTypes.func.isRequired, onChangeNewContentTypeMainInfos: PropTypes.func.isRequired, onChangeNewGroupMainInfos: PropTypes.func.isRequired, resetProps: PropTypes.func.isRequired, @@ -292,6 +319,7 @@ App.propTypes = { setTemporaryAttribute: PropTypes.func.isRequired, setTemporaryAttributeRelation: PropTypes.func.isRequired, resetExistingContentTypeMainInfos: PropTypes.func.isRequired, + resetExistingGroupMainInfos: PropTypes.func.isRequired, resetNewContentTypeMainInfos: PropTypes.func.isRequired, shouldRefetchData: PropTypes.bool, updateTempContentType: PropTypes.func.isRequired, @@ -313,6 +341,7 @@ export function mapDispatchToProps(dispatch) { deleteTemporaryModel, getData, onChangeExistingContentTypeMainInfos, + onChangeExistingGroupMainInfos, onChangeNewContentTypeMainInfos, onChangeNewGroupMainInfos, onChangeRelation, @@ -320,6 +349,7 @@ export function mapDispatchToProps(dispatch) { onChangeRelationTarget, resetExistingContentTypeMainInfos, resetNewContentTypeMainInfos, + resetExistingGroupMainInfos, resetProps, saveEditedAttribute, saveEditedAttributeRelation, diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js index 48adb379d1..83f45ef504 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/reducer.js @@ -26,6 +26,7 @@ import { DELETE_TEMPORARY_MODEL, GET_DATA_SUCCEEDED, ON_CHANGE_EXISTING_CONTENT_TYPE_MAIN_INFOS, + ON_CHANGE_EXISTING_GROUP_MAIN_INFOS, ON_CHANGE_NEW_GROUP_MAIN_INFOS, ON_CHANGE_NEW_CONTENT_TYPE_MAIN_INFOS, ON_CHANGE_ATTRIBUTE, @@ -33,16 +34,20 @@ import { ON_CHANGE_RELATION, ON_CHANGE_RELATION_TARGET, RESET_EXISTING_CONTENT_TYPE_MAIN_INFOS, + RESET_EXISTING_GROUP_MAIN_INFOS, RESET_NEW_CONTENT_TYPE_MAIN_INFOS, RESET_EDIT_EXISTING_CONTENT_TYPE, RESET_EDIT_TEMP_CONTENT_TYPE, RESET_EDIT_TEMP_GROUP, RESET_PROPS, SAVE_EDITED_ATTRIBUTE, + SAVE_EDITED_ATTRIBUTE_GROUP, SAVE_EDITED_ATTRIBUTE_RELATION, SET_TEMPORARY_ATTRIBUTE, + SET_TEMPORARY_ATTRIBUTE_GROUP, SET_TEMPORARY_ATTRIBUTE_RELATION, SUBMIT_CONTENT_TYPE_SUCCEEDED, + SUBMIT_GROUP_SUCCEEDED, SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED, SUBMIT_TEMP_GROUP_SUCCEEDED, UPDATE_TEMP_CONTENT_TYPE, @@ -399,6 +404,11 @@ function appReducer(state = initialState, action) { ['modifiedData', ...action.keys], () => action.value ); + case ON_CHANGE_EXISTING_GROUP_MAIN_INFOS: + return state.updateIn( + ['modifiedDataGroup', ...action.keys], + () => action.value + ); case ON_CHANGE_NEW_CONTENT_TYPE_MAIN_INFOS: return state.updateIn( ['newContentType', ...action.keys], @@ -494,6 +504,26 @@ function appReducer(state = initialState, action) { return initialContentType; }); + case RESET_EXISTING_GROUP_MAIN_INFOS: { + return state.updateIn( + ['modifiedDataGroup', action.groupName, 'schema'], + () => { + const initialGroup = state + .getIn(['initialDataGroup', action.groupName, 'schema']) + .set( + 'attributes', + state.getIn([ + 'modifiedDataGroup', + action.groupName, + 'schema', + 'attributes', + ]) + ); + + return initialGroup; + } + ); + } case RESET_NEW_CONTENT_TYPE_MAIN_INFOS: return state.updateIn(['newContentType'], () => { const initialContentType = state @@ -536,6 +566,21 @@ function appReducer(state = initialState, action) { return obj.set('attributes', OrderedMap(newObj)); }); } + + case SAVE_EDITED_ATTRIBUTE_GROUP: { + const basePath = action.isGroupTemporary + ? ['newGroup', 'schema'] + : ['modifiedDataGroup', action.groupName, 'schema']; + + const temporaryAttribute = state.get('temporaryAttributeGroup'); + state.update('temporaryAttributeGroup', () => {}); + + return state.updateIn( + [...basePath, 'attributes', action.attributeIndex], + () => temporaryAttribute + ); + } + case SAVE_EDITED_ATTRIBUTE_RELATION: { const basePath = action.isModelTemporary ? ['newContentType'] @@ -652,6 +697,26 @@ function appReducer(state = initialState, action) { return attribute; }); + case SET_TEMPORARY_ATTRIBUTE_GROUP: + return state.update('temporaryAttributeGroup', () => { + const basePath = action.isGroupTemporary + ? ['newGroup', 'schema'] + : ['modifiedDataGroup', action.groupName, 'schema']; + + const attribute = state + .getIn([...basePath, 'attributes', action.attributeIndex]) + .set( + 'name', + state.getIn([ + ...basePath, + 'attributes', + action.attributeIndex, + 'name', + ]) + ); + + return attribute; + }); case SET_TEMPORARY_ATTRIBUTE_RELATION: { if (action.isEditing) { const basePath = action.isModelTemporary @@ -684,6 +749,26 @@ function appReducer(state = initialState, action) { .update('isLoading', () => true) .update('shouldRefetchData', v => !v); } + + case SUBMIT_GROUP_SUCCEEDED: { + let modifiedGroup = state + .get('modifiedDataGroup') + .find( + (group, key) => !group.equals(state.getIn(['initialDataGroup', key])) + ); + + const uid = modifiedGroup.get('uid'); + const groupToUpdate = state.get('groups').findIndex(group => { + return group.get('uid') === uid; + }); + + return state + .updateIn(['initialDataGroup', uid], () => modifiedGroup) + .updateIn(['groups', groupToUpdate, 'name'], () => + modifiedGroup.getIn(['schema', 'name']) + ); + } + case SUBMIT_TEMP_CONTENT_TYPE_SUCCEEDED: return state .update('isLoading', () => true) diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/saga.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/saga.js index 04d863a3e1..ef237bc81d 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/saga.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/saga.js @@ -9,6 +9,7 @@ import { getDataSucceeded, deleteModelSucceeded, submitContentTypeSucceeded, + submitGroupSucceeded, submitTempContentTypeSucceeded, submitTempGroupSucceeded, deleteGroupSucceeded, @@ -18,6 +19,7 @@ import { DELETE_GROUP, DELETE_MODEL, SUBMIT_CONTENT_TYPE, + SUBMIT_GROUP, SUBMIT_TEMP_CONTENT_TYPE, SUBMIT_TEMP_GROUP, } from './constants'; @@ -139,6 +141,70 @@ export function* submitCT({ } } +export function* submitGroup({ + oldGroupName, + body, + source, + context: { emitEvent, history }, +}) { + try { + const { name } = body; + + if (source) { + body.plugin = source; + } + + emitEvent('willSaveGroup'); + + emitEvent('didSaveGroup'); + + yield put(submitGroupSucceeded({ oldGroupName })); + const suffixUrl = source ? `&source=${source}` : ''; + history.push(`/plugins/${pluginId}/groups/${name}${suffixUrl}`); + } catch (error) { + const errorMessage = get( + error, + ['response', 'payload', 'message', '0', 'messages', '0', 'id'], + 'notification.error' + ); + strapi.notification.error(errorMessage); + } +} + +// TODO: UNCOMMENT WHEN API IS AVAILABLE +// export function* submitGroup({ +// oldGroupName, +// body, +// source, +// context: { emitEvent, history }, +// }) { +// try { +// const { name } = body; + +// if (source) { +// body.plugin = source; +// } + +// emitEvent('willSaveGroup'); + +// const opts = { method: 'PUT', body }; + +// yield call(request, getRequestUrl(`groups/${oldGroupName}`), opts, true); +// emitEvent('didSaveGroup'); + +// yield put(submitGroupSucceeded()); +// const suffixUrl = source ? `&source=${source}` : ''; +// history.push(`/plugins/${pluginId}/groups/${name}${suffixUrl}`); +// } catch (error) { +// const errorMessage = get( +// error, +// ['response', 'payload', 'message', '0', 'messages', '0', 'id'], +// 'notification.error' +// ); +// strapi.notification.error(errorMessage); +// } +// } + /* istanbul ignore-next */ export function* submitTempCT({ body, @@ -223,6 +289,7 @@ export default function* defaultSaga() { fork(takeLatest, DELETE_GROUP, deleteGroup), fork(takeLatest, DELETE_MODEL, deleteModel), fork(takeLatest, SUBMIT_CONTENT_TYPE, submitCT), + fork(takeLatest, SUBMIT_GROUP, submitGroup), fork(takeLatest, SUBMIT_TEMP_CONTENT_TYPE, submitTempCT), fork(takeLatest, SUBMIT_TEMP_GROUP, submitTempGroup), ]); diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/tests/index.test.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/tests/index.test.js index 5f86ed7c4b..7afc2089fc 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/App/tests/index.test.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/App/tests/index.test.js @@ -79,9 +79,11 @@ describe('', () => { }, ], modifiedData: {}, + modifiedDataGroup: {}, newContentType: {}, newGroup: {}, onChangeExistingContentTypeMainInfos: jest.fn(), + onChangeExistingGroupMainInfos: jest.fn(), onChangeNewContentTypeMainInfos: jest.fn(), onChangeNewGroupMainInfos: jest.fn(), saveEditedAttribute: jest.fn(), @@ -90,6 +92,7 @@ describe('', () => { setTemporaryAttributeRelation: jest.fn(), resetProps: jest.fn(), resetExistingContentTypeMainInfos: jest.fn(), + resetExistingGroupMainInfos: jest.fn(), resetNewContentTypeMainInfos: jest.fn(), updateTempContentType: jest.fn(), }; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/AttributeForm/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/AttributeForm/index.js index 31e6f238ca..e3d36d6211 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/AttributeForm/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/AttributeForm/index.js @@ -173,10 +173,14 @@ class AttributeForm extends React.Component { }; renderInput = (input, index) => { - const { modifiedData, onChange } = this.props; + const { featureType, modifiedData, onChange } = this.props; const { didCheckErrors, formErrors } = this.state; const { custom, defaultValue, name } = input; - const value = get(modifiedData, name, defaultValue); + + const value = + featureType === 'model' + ? get(modifiedData, name, defaultValue) + : get(modifiedData, name, defaultValue); const errors = get(formErrors, name, []); diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/GroupPage/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/GroupPage/index.js index 0d526e106c..79e3cc750d 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/GroupPage/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/GroupPage/index.js @@ -31,6 +31,9 @@ import { clearTemporaryAttributeGroup, deleteGroupAttribute, onChangeAttributeGroup, + saveEditedAttributeGroup, + setTemporaryAttributeGroup, + submitGroup, submitTempGroup, resetEditTempGroup, } from '../App/actions'; @@ -40,13 +43,49 @@ export class GroupPage extends React.Component { state = { attrToDelete: null, showWarning: false }; featureType = 'group'; + componentDidMount() { + const { setTemporaryAttributeGroup } = this.props; + if ( + this.getModalType() === 'attributeForm' && + this.getActionType() === 'edit' && + !this.isTryingToEditAnUnknownAttribute() + ) { + setTemporaryAttributeGroup( + this.getAttributeIndex(), + this.isUpdatingTempFeature(), + this.getFeatureName() + ); + } + } + displayNotificationCTNotSaved = () => strapi.notification.info( `${pluginId}.notification.info.contentType.creating.notSaved` ); + isTryingToEditAnUnknownAttribute = () => { + const hasAttribute = + this.getFeatureAttributes().findIndex( + attr => attr.name === this.getAttributeName() + ) !== -1; + + return ( + this.getActionType() === 'edit' && + this.getModalType() === 'attributeForm' && + !hasAttribute + ); + }; + getActionType = () => getQueryParameters(this.getSearch(), 'actionType'); + getAttributeIndex = () => { + return getQueryParameters(this.getSearch(), 'attributeName'); + }; + + getAttributeName = () => { + return get(this.getFeatureAttributesNames(), this.getAttributeIndex()); + }; + getAttributeType = () => getQueryParameters(this.getSearch(), 'attributeType'); @@ -106,7 +145,7 @@ export class GroupPage extends React.Component { /* istanbul ignore if */ const title = this.isUpdatingTempFeature() ? get(newGroup, 'name', null) - : get(modifiedDataGroup, [name, 'name'], null); + : get(modifiedDataGroup, [name, 'schema', 'name'], null); return title; }; @@ -119,17 +158,27 @@ export class GroupPage extends React.Component { modifiedDataGroup, newGroup, resetEditTempGroup, + submitGroup, submitTempGroup, } = this.props; + const featureName = this.getFeatureName(); /* istanbul ignore if */ const shouldShowActions = this.isUpdatingTempFeature() ? this.getFeatureAttributesLength() > 0 - : !isEqual( - modifiedDataGroup[this.getFeatureName()], - initialDataGroup[this.getFeatureName()] - ); + : !isEqual(modifiedDataGroup[featureName], initialDataGroup[featureName]); + + const handleSubmit = () => + this.isUpdatingTempFeature() + ? submitTempGroup(newGroup, this.context) + : submitGroup( + featureName, + get(modifiedDataGroup, [featureName, 'schema']), + Object.assign(this.context, { + history: this.props.history, + }), + this.getSource() + ); - const handleSubmit = () => submitTempGroup(newGroup, this.context); const handleCancel = resetEditTempGroup; /* istanbul ignore if */ @@ -170,6 +219,38 @@ export class GroupPage extends React.Component { return !!source ? source : null; }; + handleClickEditAttribute = (attributeIndex, type) => { + const { emitEvent } = this.context; + const { + canOpenModal, + history: { push }, + setTemporaryAttributeGroup, + } = this.props; + const attributeType = [ + 'integer', + 'biginteger', + 'float', + 'decimal', + ].includes(type) + ? 'number' + : type; + + if (canOpenModal || this.isUpdatingTempFeature()) { + setTemporaryAttributeGroup( + attributeIndex, + this.isUpdatingTempFeature(), + this.getFeatureName() + ); + + emitEvent('willEditFieldOfGroup'); + push({ + search: `modalType=attributeForm&attributeType=${attributeType}&settingType=base&actionType=edit&attributeName=${attributeIndex}`, + }); + } else { + this.displayNotificationCTNotSaved(); + } + }; + handleClickOnTrashIcon = attrToDelete => { const { emitEvent } = this.context; const { canOpenModal } = this.props; @@ -229,6 +310,23 @@ export class GroupPage extends React.Component { push({ search: nextSearch }); }; + handleSubmitEdit = (shouldContinue = false) => { + const { + history: { push }, + saveEditedAttributeGroup, + } = this.props; + + saveEditedAttributeGroup( + this.getAttributeIndex(), + this.isUpdatingTempFeature(), + this.getFeatureName() + ); + + const nextSearch = shouldContinue ? 'modalType=chooseAttributes' : ''; + + push({ search: nextSearch }); + }; + isUpdatingTempFeature = () => { const { groups } = this.props; const currentData = groups.find(d => d.name === this.getFeatureName()); @@ -249,6 +347,20 @@ export class GroupPage extends React.Component { } }; + openEditFeatureModal = () => { + const { emitEvent } = this.context; + const { canOpenModal } = this.props; + + if (canOpenModal || this.isUpdatingTempFeature()) { + this.props.history.push({ + search: `modalType=group&settingType=base&actionType=edit&groupName=${this.getFeatureName()}`, + }); + emitEvent('willEditNameOfGroup'); + } else { + this.displayNotificationCTNotSaved(); + } + }; + toggleModalWarning = () => this.setState(prevState => ({ showWarning: !prevState.showWarning })); @@ -303,6 +415,7 @@ export class GroupPage extends React.Component { headerTitle={this.getFeatureHeaderTitle()} headerDescription={this.getFeatureHeaderDescription()} pluginHeaderActions={this.getPluginHeaderActions()} + onClickIcon={this.openEditFeatureModal} > {attributesNumber === 0 ? ( {}} + onSubmitEdit={this.handleSubmitEdit} push={push} /> @@ -412,6 +526,9 @@ GroupPage.propTypes = { newGroup: PropTypes.object.isRequired, onChangeAttributeGroup: PropTypes.func.isRequired, resetEditTempGroup: PropTypes.func.isRequired, + saveEditedAttributeGroup: PropTypes.func.isRequired, + setTemporaryAttributeGroup: PropTypes.func.isRequired, + submitGroup: PropTypes.func.isRequired, submitTempGroup: PropTypes.func.isRequired, temporaryAttributeGroup: PropTypes.object.isRequired, }; @@ -424,6 +541,9 @@ export function mapDispatchToProps(dispatch) { clearTemporaryAttributeGroup, deleteGroupAttribute, onChangeAttributeGroup, + saveEditedAttributeGroup, + setTemporaryAttributeGroup, + submitGroup, submitTempGroup, resetEditTempGroup, }, diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/GroupPage/tests/index.test.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/GroupPage/tests/index.test.js index 30918e6221..57ad3ea5e8 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/GroupPage/tests/index.test.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/GroupPage/tests/index.test.js @@ -123,7 +123,10 @@ const props = { }, onChangeAttributeGroup: jest.fn(), resetEditTempGroup: jest.fn(), + saveEditedAttributeGroup: jest.fn(), + setTemporaryAttributeGroup: jest.fn(), submitTempGroup: jest.fn(), + submitGroup: jest.fn(), temporaryAttributeGroup: {}, }; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelForm/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelForm/index.js index 43a38d03a8..86a8cac484 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelForm/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/ModelForm/index.js @@ -216,6 +216,7 @@ class ModelForm extends React.Component { activeTab, featureToEditName, featureType, + modifiedData, isOpen, } = this.props; const currentForm = get(forms, activeTab, forms.base); @@ -242,7 +243,9 @@ class ModelForm extends React.Component {
diff --git a/packages/strapi-plugin-content-type-builder/admin/src/translations/fr.json b/packages/strapi-plugin-content-type-builder/admin/src/translations/fr.json index 8ed22b5692..25a3fd6be1 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/translations/fr.json +++ b/packages/strapi-plugin-content-type-builder/admin/src/translations/fr.json @@ -163,7 +163,7 @@ "popUpForm.create.group.header.title": "Créer un Groupe", "popUpForm.create.model.header.subTitle": "Paramètres du Type de Contenu", "popUpForm.create.group.header.subTitle": "Paramètres du Groupe", - "popUpForm.edit": "Modifer", + "popUpForm.edit": "Modifier", "popUpForm.edit.contentType.header.title": "Modifier un Type de Contenu", "popUpForm.field": "Champ", "popUpForm.navContainer.advanced": "Réglages avancés",