Refactor Views by cleaning the code, relying on apolloCache and improving performances (#4516)
* Wip refactoring view * Post merge conflicts * Fix review * Add create view capability * Fix create object missing view * Fix tests
This commit is contained in:
@ -26,127 +26,129 @@ export const triggerUpdateRelationsOptimisticEffect = ({
|
||||
currentSourceRecord: CachedObjectRecord | null;
|
||||
updatedSourceRecord: CachedObjectRecord | null;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
}) =>
|
||||
sourceObjectMetadataItem.fields.forEach((fieldMetadataItemOnSourceRecord) => {
|
||||
const notARelationField =
|
||||
fieldMetadataItemOnSourceRecord.type !== FieldMetadataType.Relation;
|
||||
}) => {
|
||||
return sourceObjectMetadataItem.fields.forEach(
|
||||
(fieldMetadataItemOnSourceRecord) => {
|
||||
const notARelationField =
|
||||
fieldMetadataItemOnSourceRecord.type !== FieldMetadataType.Relation;
|
||||
|
||||
if (notARelationField) {
|
||||
return;
|
||||
}
|
||||
if (notARelationField) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fieldDoesNotExist =
|
||||
isDefined(updatedSourceRecord) &&
|
||||
!(fieldMetadataItemOnSourceRecord.name in updatedSourceRecord);
|
||||
const fieldDoesNotExist =
|
||||
isDefined(updatedSourceRecord) &&
|
||||
!(fieldMetadataItemOnSourceRecord.name in updatedSourceRecord);
|
||||
|
||||
if (fieldDoesNotExist) {
|
||||
return;
|
||||
}
|
||||
if (fieldDoesNotExist) {
|
||||
return;
|
||||
}
|
||||
|
||||
const relationDefinition = getRelationDefinition({
|
||||
fieldMetadataItemOnSourceRecord,
|
||||
objectMetadataItems,
|
||||
});
|
||||
const relationDefinition = getRelationDefinition({
|
||||
fieldMetadataItemOnSourceRecord,
|
||||
objectMetadataItems,
|
||||
});
|
||||
if (!relationDefinition) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!relationDefinition) {
|
||||
return;
|
||||
}
|
||||
const { targetObjectMetadataItem, fieldMetadataItemOnTargetRecord } =
|
||||
relationDefinition;
|
||||
|
||||
const { targetObjectMetadataItem, fieldMetadataItemOnTargetRecord } =
|
||||
relationDefinition;
|
||||
const currentFieldValueOnSourceRecord:
|
||||
| ObjectRecordConnection
|
||||
| CachedObjectRecord
|
||||
| null = currentSourceRecord?.[fieldMetadataItemOnSourceRecord.name];
|
||||
|
||||
const currentFieldValueOnSourceRecord:
|
||||
| ObjectRecordConnection
|
||||
| CachedObjectRecord
|
||||
| null = currentSourceRecord?.[fieldMetadataItemOnSourceRecord.name];
|
||||
const updatedFieldValueOnSourceRecord:
|
||||
| ObjectRecordConnection
|
||||
| CachedObjectRecord
|
||||
| null = updatedSourceRecord?.[fieldMetadataItemOnSourceRecord.name];
|
||||
|
||||
const updatedFieldValueOnSourceRecord:
|
||||
| ObjectRecordConnection
|
||||
| CachedObjectRecord
|
||||
| null = updatedSourceRecord?.[fieldMetadataItemOnSourceRecord.name];
|
||||
if (
|
||||
isDeeplyEqual(
|
||||
currentFieldValueOnSourceRecord,
|
||||
updatedFieldValueOnSourceRecord,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
isDeeplyEqual(
|
||||
currentFieldValueOnSourceRecord,
|
||||
updatedFieldValueOnSourceRecord,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: replace this by a relation type check, if it's one to many,
|
||||
// it's an object record connection (we can still check it though as a safeguard)
|
||||
const currentFieldValueOnSourceRecordIsARecordConnection =
|
||||
isObjectRecordConnection(
|
||||
targetObjectMetadataItem.nameSingular,
|
||||
currentFieldValueOnSourceRecord,
|
||||
);
|
||||
|
||||
const targetRecordsToDetachFrom =
|
||||
currentFieldValueOnSourceRecordIsARecordConnection
|
||||
? currentFieldValueOnSourceRecord.edges.map(
|
||||
({ node }) => node as CachedObjectRecord,
|
||||
)
|
||||
: [currentFieldValueOnSourceRecord].filter(isDefined);
|
||||
|
||||
const updatedFieldValueOnSourceRecordIsARecordConnection =
|
||||
isObjectRecordConnection(
|
||||
targetObjectMetadataItem.nameSingular,
|
||||
updatedFieldValueOnSourceRecord,
|
||||
);
|
||||
|
||||
const targetRecordsToAttachTo =
|
||||
updatedFieldValueOnSourceRecordIsARecordConnection
|
||||
? updatedFieldValueOnSourceRecord.edges.map(
|
||||
({ node }) => node as CachedObjectRecord,
|
||||
)
|
||||
: [updatedFieldValueOnSourceRecord].filter(isDefined);
|
||||
|
||||
const shouldDetachSourceFromAllTargets =
|
||||
isDefined(currentSourceRecord) && targetRecordsToDetachFrom.length > 0;
|
||||
|
||||
if (shouldDetachSourceFromAllTargets) {
|
||||
// TODO: see if we can de-hardcode this, put cascade delete in relation metadata item
|
||||
// Instead of hardcoding it here
|
||||
const shouldCascadeDeleteTargetRecords =
|
||||
CORE_OBJECT_NAMES_TO_DELETE_ON_TRIGGER_RELATION_DETACH.includes(
|
||||
targetObjectMetadataItem.nameSingular as CoreObjectNameSingular,
|
||||
// TODO: replace this by a relation type check, if it's one to many,
|
||||
// it's an object record connection (we can still check it though as a safeguard)
|
||||
const currentFieldValueOnSourceRecordIsARecordConnection =
|
||||
isObjectRecordConnection(
|
||||
targetObjectMetadataItem.nameSingular,
|
||||
currentFieldValueOnSourceRecord,
|
||||
);
|
||||
|
||||
if (shouldCascadeDeleteTargetRecords) {
|
||||
triggerDeleteRecordsOptimisticEffect({
|
||||
cache,
|
||||
objectMetadataItem: targetObjectMetadataItem,
|
||||
recordsToDelete: targetRecordsToDetachFrom,
|
||||
objectMetadataItems,
|
||||
});
|
||||
} else {
|
||||
targetRecordsToDetachFrom.forEach((targetRecordToDetachFrom) => {
|
||||
triggerDetachRelationOptimisticEffect({
|
||||
const targetRecordsToDetachFrom =
|
||||
currentFieldValueOnSourceRecordIsARecordConnection
|
||||
? currentFieldValueOnSourceRecord.edges.map(
|
||||
({ node }) => node as CachedObjectRecord,
|
||||
)
|
||||
: [currentFieldValueOnSourceRecord].filter(isDefined);
|
||||
|
||||
const updatedFieldValueOnSourceRecordIsARecordConnection =
|
||||
isObjectRecordConnection(
|
||||
targetObjectMetadataItem.nameSingular,
|
||||
updatedFieldValueOnSourceRecord,
|
||||
);
|
||||
|
||||
const targetRecordsToAttachTo =
|
||||
updatedFieldValueOnSourceRecordIsARecordConnection
|
||||
? updatedFieldValueOnSourceRecord.edges.map(
|
||||
({ node }) => node as CachedObjectRecord,
|
||||
)
|
||||
: [updatedFieldValueOnSourceRecord].filter(isDefined);
|
||||
|
||||
const shouldDetachSourceFromAllTargets =
|
||||
isDefined(currentSourceRecord) && targetRecordsToDetachFrom.length > 0;
|
||||
|
||||
if (shouldDetachSourceFromAllTargets) {
|
||||
// TODO: see if we can de-hardcode this, put cascade delete in relation metadata item
|
||||
// Instead of hardcoding it here
|
||||
const shouldCascadeDeleteTargetRecords =
|
||||
CORE_OBJECT_NAMES_TO_DELETE_ON_TRIGGER_RELATION_DETACH.includes(
|
||||
targetObjectMetadataItem.nameSingular as CoreObjectNameSingular,
|
||||
);
|
||||
|
||||
if (shouldCascadeDeleteTargetRecords) {
|
||||
triggerDeleteRecordsOptimisticEffect({
|
||||
cache,
|
||||
objectMetadataItem: targetObjectMetadataItem,
|
||||
recordsToDelete: targetRecordsToDetachFrom,
|
||||
objectMetadataItems,
|
||||
});
|
||||
} else {
|
||||
targetRecordsToDetachFrom.forEach((targetRecordToDetachFrom) => {
|
||||
triggerDetachRelationOptimisticEffect({
|
||||
cache,
|
||||
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
|
||||
sourceRecordId: currentSourceRecord.id,
|
||||
fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name,
|
||||
targetObjectNameSingular: targetObjectMetadataItem.nameSingular,
|
||||
targetRecordId: targetRecordToDetachFrom.id,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const shouldAttachSourceToAllTargets =
|
||||
isDefined(updatedSourceRecord) && targetRecordsToAttachTo.length > 0;
|
||||
|
||||
if (shouldAttachSourceToAllTargets) {
|
||||
targetRecordsToAttachTo.forEach((targetRecordToAttachTo) =>
|
||||
triggerAttachRelationOptimisticEffect({
|
||||
cache,
|
||||
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
|
||||
sourceRecordId: currentSourceRecord.id,
|
||||
sourceRecordId: updatedSourceRecord.id,
|
||||
fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name,
|
||||
targetObjectNameSingular: targetObjectMetadataItem.nameSingular,
|
||||
targetRecordId: targetRecordToDetachFrom.id,
|
||||
});
|
||||
});
|
||||
targetRecordId: targetRecordToAttachTo.id,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const shouldAttachSourceToAllTargets =
|
||||
isDefined(updatedSourceRecord) && targetRecordsToAttachTo.length > 0;
|
||||
|
||||
if (shouldAttachSourceToAllTargets) {
|
||||
targetRecordsToAttachTo.forEach((targetRecordToAttachTo) =>
|
||||
triggerAttachRelationOptimisticEffect({
|
||||
cache,
|
||||
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
|
||||
sourceRecordId: updatedSourceRecord.id,
|
||||
fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name,
|
||||
targetObjectNameSingular: targetObjectMetadataItem.nameSingular,
|
||||
targetRecordId: targetRecordToAttachTo.id,
|
||||
}),
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user