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": {
"model": "review",
"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
}, [isLoading, pathname]);
const addAttribute = (attributeToSet, forTarget, targetUid) => {
dispatch({
type: 'ADD_ATTRIBUTE',
const addAttribute = (
attributeToSet,
forTarget,
targetUid,
isEditing = false,
initialAttribute
) => {
const actionType = isEditing ? 'EDIT_ATTRIBUTE' : 'ADD_ATTRIBUTE';
dispatch({
type: actionType,
attributeToSet,
forTarget,
targetUid,
initialAttribute,
});
};
@ -138,7 +147,7 @@ const DataManagerProvider = ({ children }) => {
return <Redirect to={`/plugins/${pluginId}/content-types/${firstCTUid}`} />;
}
console.log({ modifiedData, contentTypes });
console.log({ modifiedData: modifiedData.contentType });
return (
<DataManagerContext.Provider

View File

@ -1,5 +1,5 @@
import { fromJS } from 'immutable';
import { get } from 'lodash';
import { fromJS, OrderedMap } from 'immutable';
import { get, has } from 'lodash';
const initialState = fromJS({
components: {},
contentTypes: {},
@ -9,6 +9,17 @@ const initialState = fromJS({
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) => {
switch (action.type) {
case 'ADD_ATTRIBUTE': {
@ -49,13 +60,14 @@ const reducer = (state, action) => {
target === currentUid
) {
const oppositeAttribute = {
nature,
nature: getOppositeNature(nature),
target,
type,
unique: rest.unique,
required: rest.required,
dominant: nature === 'manyToMany' ? !rest.dominant : null,
targetAttribute: name,
columnName: rest.targetColumnName,
targetColumnName: rest.columnName,
};
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':
return state
.update('components', () => fromJS(action.components))

View File

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

View File

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