Skip to content

Commit

Permalink
Fix timelineActivity updated fields (twentyhq#6494)
Browse files Browse the repository at this point in the history
## Context
We recently introduced the new twenty ORM and used it in the update
methods in the query runner.
Initially we were using pg_graphql to fetch the record before updating
it allowing us to compare the before and the after and create a diff.
This diff is then used for the timeline activity creation. Now,
twentyORM is doing the fetch and pg_graphql is still doing the update
and their responses are not exactly the same, which means the diff is
not working as intended (e.g date types were always in the diff due to
one being in Date format and the other as a string)

This PR introduces a updatedFields property to the update event which
comes from the input. This is not ideal as this won't work for API users
that send the whole payload but will be sufficient enough for our FE
that only sends modified fields. We then compare only those fields in
the diff.
  • Loading branch information
Weiko authored Aug 1, 2024
1 parent a424c63 commit 676c902
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export class EntityEventsToDbListener {
payload.properties.diff = objectRecordChangedValues(
payload.properties.before,
payload.properties.after,
payload.properties.updatedFields,
payload.objectMetadata,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ export class WorkspaceQueryRunnerService {
recordId: existingRecord.id,
objectMetadata: objectMetadataItem,
properties: {
updatedFields: Object.keys(args.data),
before: this.removeNestedProperties(existingRecord as Record),
after: this.removeNestedProperties(parsedResults?.[0]),
},
Expand Down Expand Up @@ -518,6 +519,7 @@ export class WorkspaceQueryRunnerService {
recordId: existingRecord.id,
objectMetadata: objectMetadataItem,
properties: {
updatedFields: Object.keys(args.data),
before: this.removeNestedProperties(existingRecord as Record),
after: this.removeNestedProperties(record),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ObjectRecordBaseEvent } from 'src/engine/integrations/event-emitter/typ

export class ObjectRecordUpdateEvent<T> extends ObjectRecordBaseEvent {
properties: {
updatedFields: string[];
before: T;
after: T;
diff?: Partial<T>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ describe('objectRecordChangedValues', () => {
const result = objectRecordChangedValues(
oldRecord,
newRecord,
['name'],
mockObjectMetadata,
);

Expand All @@ -58,6 +59,7 @@ it('ignores changes to the updatedAt field', () => {
const result = objectRecordChangedValues(
oldRecord,
newRecord,
[],
mockObjectMetadata,
);

Expand All @@ -79,6 +81,7 @@ it('returns an empty object when there are no changes', () => {
const result = objectRecordChangedValues(
oldRecord,
newRecord,
['name', 'value'],
mockObjectMetadata,
);

Expand Down Expand Up @@ -108,6 +111,7 @@ it('correctly handles a mix of changed, unchanged, and special case values', ()
const result = objectRecordChangedValues(
oldRecord,
newRecord,
['name', 'config', 'status'],
mockObjectMetadata,
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
import deepEqual from 'deep-equal';

import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';

import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';

export const objectRecordChangedValues = (
oldRecord: Partial<IRecord>,
newRecord: Partial<IRecord>,
updatedKeys: string[],
objectMetadata: ObjectMetadataInterface,
) => {
const fieldsByKey = new Map(
objectMetadata.fields.map((field) => [field.name, field]),
);

const changedValues = Object.keys(newRecord).reduce(
(acc, key) => {
const field = fieldsByKey.get(key);
const oldRecordValue = oldRecord[key];
const newRecordValue = newRecord[key];

if (
objectMetadata.fields.find(
(field) =>
field.type === FieldMetadataType.RELATION && field.name === key,
)
key === 'updatedAt' ||
!updatedKeys.includes(key) ||
field?.type === FieldMetadataType.RELATION ||
deepEqual(oldRecordValue, newRecordValue)
) {
return acc;
}

if (objectMetadata.nameSingular === 'activity' && key === 'body') {
return acc;
}

if (!deepEqual(oldRecord[key], newRecord[key]) && key !== 'updatedAt') {
acc[key] = { before: oldRecord[key], after: newRecord[key] };
}
acc[key] = { before: oldRecordValue, after: newRecordValue };

return acc;
},
Expand Down

0 comments on commit 676c902

Please sign in to comment.