Logs show page (#4611)

* Being implementing events on the frontend

* Rename JSON to RAW JSON

* Fix handling of json field on frontend

* Log user id

* Add frontend tests

* Update packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/save-event-to-db.job.ts

Co-authored-by: Weiko <corentin@twenty.com>

* Move db calls to a dedicated repository

* Add server-side tests

---------

Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
Félix Malfait
2024-03-22 14:01:16 +01:00
committed by GitHub
parent aee6d49ea9
commit d876b40056
38 changed files with 488 additions and 95 deletions

View File

@ -4,5 +4,6 @@ export class ObjectRecordUpdateEvent<T> extends ObjectRecordBaseEvent {
details: {
before: T;
after: T;
diff?: Partial<T>;
};
}

View File

@ -3,6 +3,7 @@ import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metad
export class ObjectRecordBaseEvent {
workspaceId: string;
recordId: string;
userId?: string;
objectMetadata: ObjectMetadataInterface;
details: any;
}

View File

@ -0,0 +1,65 @@
import { objectRecordChangedValues } from 'src/engine/integrations/event-emitter/utils/object-record-changed-values';
describe('objectRecordChangedValues', () => {
it('detects changes in scalar values correctly', () => {
const oldRecord = { id: 1, name: 'Original Name', updatedAt: new Date() };
const newRecord = { id: 1, name: 'Updated Name', updatedAt: new Date() };
const result = objectRecordChangedValues(oldRecord, newRecord);
expect(result).toEqual({
name: { before: 'Original Name', after: 'Updated Name' },
});
});
});
it('ignores changes in properties that are objects', () => {
const oldRecord = { id: 1, details: { age: 20 } };
const newRecord = { id: 1, details: { age: 21 } };
const result = objectRecordChangedValues(oldRecord, newRecord);
expect(result).toEqual({});
});
it('ignores changes to the updatedAt field', () => {
const oldRecord = { id: 1, updatedAt: new Date('2020-01-01') };
const newRecord = { id: 1, updatedAt: new Date('2024-01-01') };
const result = objectRecordChangedValues(oldRecord, newRecord);
expect(result).toEqual({});
});
it('returns an empty object when there are no changes', () => {
const oldRecord = { id: 1, name: 'Name', value: 100 };
const newRecord = { id: 1, name: 'Name', value: 100 };
const result = objectRecordChangedValues(oldRecord, newRecord);
expect(result).toEqual({});
});
it('correctly handles a mix of changed, unchanged, and special case values', () => {
const oldRecord = {
id: 1,
name: 'Original',
status: 'active',
updatedAt: new Date(2020, 1, 1),
config: { theme: 'dark' },
};
const newRecord = {
id: 1,
name: 'Updated',
status: 'active',
updatedAt: new Date(2021, 1, 1),
config: { theme: 'light' },
};
const expectedChanges = {
name: { before: 'Original', after: 'Updated' },
};
const result = objectRecordChangedValues(oldRecord, newRecord);
expect(result).toEqual(expectedChanges);
});

View File

@ -0,0 +1,28 @@
import deepEqual from 'deep-equal';
export const objectRecordChangedValues = (
oldRecord: Record<string, any>,
newRecord: Record<string, any>,
) => {
const isObject = (value: any) => {
return typeof value === 'object' && value !== null && !Array.isArray(value);
};
const changedValues = Object.keys(newRecord).reduce(
(acc, key) => {
// Discard if values are objects (e.g. we don't want Company.AccountOwner ; we have AccountOwnerId already)
if (isObject(oldRecord[key]) || isObject(newRecord[key])) {
return acc;
}
if (!deepEqual(oldRecord[key], newRecord[key]) && key != 'updatedAt') {
acc[key] = { before: oldRecord[key], after: newRecord[key] };
}
return acc;
},
{} as Record<string, { before: any; after: any }>,
);
return changedValues;
};