Handle edit relation

This commit is contained in:
soupette 2019-11-22 15:57:00 +01:00
parent d9ca6451d7
commit b9ffe9de46
5 changed files with 197 additions and 9 deletions

View File

@ -18,6 +18,14 @@
"review": { "review": {
"model": "review", "model": "review",
"via": "likes" "via": "likes"
},
"like_left": {
"collection": "like",
"via": "like_right"
},
"like_right": {
"model": "like",
"via": "like_left"
} }
} }
} }

View File

@ -73,12 +73,21 @@ const DataManagerProvider = ({ children }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoading, pathname]); }, [isLoading, pathname]);
const addAttribute = (attributeToSet, forTarget, targetUid) => { const addAttribute = (
attributeToSet,
forTarget,
targetUid,
isEditing = false,
initialAttribute
) => {
const actionType = isEditing ? 'EDIT_ATTRIBUTE' : 'ADD_ATTRIBUTE';
dispatch({ dispatch({
type: 'ADD_ATTRIBUTE', type: actionType,
attributeToSet, attributeToSet,
forTarget, forTarget,
targetUid, targetUid,
initialAttribute,
}); });
}; };
@ -138,7 +147,7 @@ const DataManagerProvider = ({ children }) => {
return <Redirect to={`/plugins/${pluginId}/content-types/${firstCTUid}`} />; return <Redirect to={`/plugins/${pluginId}/content-types/${firstCTUid}`} />;
} }
console.log({ modifiedData, contentTypes }); console.log({ modifiedData: modifiedData.contentType });
return ( return (
<DataManagerContext.Provider <DataManagerContext.Provider

View File

@ -1,5 +1,5 @@
import { fromJS } from 'immutable'; import { fromJS, OrderedMap } from 'immutable';
import { get } from 'lodash'; import { get, has } from 'lodash';
const initialState = fromJS({ const initialState = fromJS({
components: {}, components: {},
contentTypes: {}, contentTypes: {},
@ -9,6 +9,17 @@ const initialState = fromJS({
isLoadingForDataToBeSet: true, isLoadingForDataToBeSet: true,
}); });
const ONE_SIDE_RELATIONS = ['oneWay', 'manyWay'];
const getOppositeNature = originalNature => {
if (originalNature === 'manyToOne') {
return 'oneToMany';
} else if (originalNature === 'oneToMany') {
return 'manyToOne';
} else {
return originalNature;
}
};
const reducer = (state, action) => { const reducer = (state, action) => {
switch (action.type) { switch (action.type) {
case 'ADD_ATTRIBUTE': { case 'ADD_ATTRIBUTE': {
@ -49,13 +60,14 @@ const reducer = (state, action) => {
target === currentUid target === currentUid
) { ) {
const oppositeAttribute = { const oppositeAttribute = {
nature, nature: getOppositeNature(nature),
target, target,
type,
unique: rest.unique, unique: rest.unique,
required: rest.required, required: rest.required,
dominant: nature === 'manyToMany' ? !rest.dominant : null, dominant: nature === 'manyToMany' ? !rest.dominant : null,
targetAttribute: name, targetAttribute: name,
columnName: rest.targetColumnName,
targetColumnName: rest.columnName,
}; };
return obj.update(rest.targetAttribute, () => { return obj.update(rest.targetAttribute, () => {
@ -67,6 +79,150 @@ const reducer = (state, action) => {
} }
); );
} }
case 'EDIT_ATTRIBUTE': {
const {
attributeToSet: { name, ...rest },
forTarget,
targetUid,
initialAttribute,
} = action;
const initialAttributeName = get(initialAttribute, ['name'], '');
const pathToDataToEdit = ['component', 'contentType'].includes(forTarget)
? [forTarget]
: [forTarget, targetUid];
return state.updateIn(
['modifiedData', ...pathToDataToEdit, 'schema'],
obj => {
let oppositeAttributeNameToRemove = null;
let oppositeAttributeNameToUpdate = null;
let oppositeAttributeNameToCreateBecauseOfNatureChange = null;
let oppositeAttributeToCreate = null;
const newObj = OrderedMap(
obj
.get('attributes')
.keySeq()
.reduce((acc, current) => {
const isEditingCurrentAttribute =
current === initialAttributeName;
if (isEditingCurrentAttribute) {
const currentUid = state.getIn([
'modifiedData',
...pathToDataToEdit,
'uid',
]);
const isEditingRelation = has(initialAttribute, 'nature');
const didChangeTargetRelation =
initialAttribute.target !== rest.target;
const didCreateInternalRelation = rest.target === currentUid;
const nature = rest.nature;
const initialNature = initialAttribute.nature;
const hadInternalRelation =
initialAttribute.target === currentUid;
const didChangeRelationNature =
initialAttribute.nature !== nature;
const shouldRemoveOppositeAttributeBecauseOfTargetChange =
didChangeTargetRelation &&
!didCreateInternalRelation &&
hadInternalRelation &&
isEditingRelation;
const shouldRemoveOppositeAttributeBecauseOfNatureChange =
didChangeRelationNature &&
hadInternalRelation &&
['oneWay', 'manyWay'].includes(nature) &&
isEditingRelation;
const shouldUpdateOppositeAttributeBecauseOfNatureChange =
!ONE_SIDE_RELATIONS.includes(initialNature) &&
!ONE_SIDE_RELATIONS.includes(nature) &&
hadInternalRelation &&
didCreateInternalRelation &&
isEditingRelation;
const shouldCreateOppositeAttributeBecauseOfNatureChange =
ONE_SIDE_RELATIONS.includes(initialNature) &&
!ONE_SIDE_RELATIONS.includes(nature) &&
hadInternalRelation &&
didCreateInternalRelation &&
isEditingRelation;
// Update the opposite attribute name so it is removed at the end of the loop
if (
shouldRemoveOppositeAttributeBecauseOfTargetChange ||
shouldRemoveOppositeAttributeBecauseOfNatureChange
) {
oppositeAttributeNameToRemove =
initialAttribute.targetAttribute;
}
// Set the opposite attribute that will be updated when the loop attribute matches the name
if (
shouldUpdateOppositeAttributeBecauseOfNatureChange ||
shouldCreateOppositeAttributeBecauseOfNatureChange
) {
oppositeAttributeNameToUpdate =
initialAttribute.targetAttribute;
oppositeAttributeNameToCreateBecauseOfNatureChange =
rest.targetAttribute;
oppositeAttributeToCreate = {
nature: getOppositeNature(rest.nature),
target: rest.target,
unique: rest.unique,
required: rest.required,
dominant:
rest.nature === 'manyToMany' ? !rest.dominant : null,
targetAttribute: name,
columnName: rest.targetColumnName,
targetColumnName: rest.columnName,
};
// First update the current attribute with the value
acc[name] = fromJS(rest);
// Then (if needed) create the opposite attribute the case is changing the relation from
// We do it here so keep the order of the attributes
// oneWay || manyWay to something another relation
if (shouldCreateOppositeAttributeBecauseOfNatureChange) {
acc[
oppositeAttributeNameToCreateBecauseOfNatureChange
] = fromJS(oppositeAttributeToCreate);
oppositeAttributeToCreate = null;
oppositeAttributeNameToCreateBecauseOfNatureChange = null;
}
return acc;
}
acc[name] = fromJS(rest);
} else if (current === oppositeAttributeNameToUpdate) {
acc[
oppositeAttributeNameToCreateBecauseOfNatureChange
] = fromJS(oppositeAttributeToCreate);
} else {
acc[current] = obj.getIn(['attributes', current]);
}
return acc;
}, {})
);
let updatedObj;
// Remove the opposite attribute
if (oppositeAttributeNameToRemove !== null) {
console.log('ppppp');
updatedObj = newObj.remove(oppositeAttributeNameToRemove);
} else {
updatedObj = newObj;
}
return obj.set('attributes', updatedObj);
}
);
}
case 'GET_DATA_SUCCEEDED': case 'GET_DATA_SUCCEEDED':
return state return state
.update('components', () => fromJS(action.components)) .update('components', () => fromJS(action.components))

View File

@ -285,7 +285,13 @@ const FormModal = () => {
search: nextSearch, search: nextSearch,
}); });
} else if (state.modalType === 'attribute') { } else if (state.modalType === 'attribute') {
addAttribute(modifiedData, state.forTarget, state.targetUid); addAttribute(
modifiedData,
state.forTarget,
state.targetUid,
state.actionType === 'edit',
initialData
);
push({ search: nextSearch }); push({ search: nextSearch });
} else { } else {
console.log('Do something with component later'); console.log('Do something with component later');

View File

@ -47,6 +47,13 @@ const reducer = (state, action) => {
: oldValue, : oldValue,
shouldPluralizeTargetAttribute(value) shouldPluralizeTargetAttribute(value)
); );
})
.update('targetColumnName', oldValue => {
if (['oneWay', 'manyWay'].includes(value)) {
return null;
}
return oldValue;
}); });
} }
@ -110,6 +117,8 @@ const reducer = (state, action) => {
unique: false, unique: false,
required: false, required: false,
dominant: null, dominant: null,
columnName: null,
targetColumnName: null,
}; };
} else { } else {
dataToSet = { type: attributeType, default: null }; dataToSet = { type: attributeType, default: null };