New Timeline (#4936)
Refactored the code to introduce two different concepts: - AuditLogs (immutable, raw data) - TimelineActivities (user-friendly, transformed data) Still some work needed: - Add message, files, calendar events to timeline (~2 hours if done naively) - Refactor repository to try to abstract concept when we can (tbd, wait for Twenty ORM) - Introduce ability to display child timelines on parent timeline with filtering (~2 days) - Improve UI: add links to open note/task, improve diff display, etc (half a day) - Decide the path forward for Task vs Notes: either introduce a new field type "Record Type" and start going into that direction ; or split in two objects? - Trigger updates when a field is changed (will be solved by real-time / websockets: 2 weeks) - Integrate behavioral events (1 day for POC, 1 week for clean/documented) <img width="1248" alt="Screenshot 2024-04-12 at 09 24 49" src="https://github.com/twentyhq/twenty/assets/6399865/9428db1a-ab2b-492c-8b0b-d4d9a36e81fa">
This commit is contained in:
@ -0,0 +1,61 @@
|
||||
import { renderHook } from '@testing-library/react';
|
||||
|
||||
import { useTimelineActivities } from '@/activities/timelineActivities/hooks/useTimelineActivities';
|
||||
|
||||
jest.mock('@/object-record/hooks/useFindManyRecords', () => ({
|
||||
useFindManyRecords: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('useTimelineActivities', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('fetches events correctly for a given targetableObject', () => {
|
||||
const mockedTimelineActivities = [
|
||||
{
|
||||
__typename: 'Event',
|
||||
id: '166ec73f-26b1-4934-bb3b-c86c8513b99b',
|
||||
workspaceMember: {
|
||||
__typename: 'WorkspaceMember',
|
||||
locale: 'en',
|
||||
avatarUrl: '',
|
||||
updatedAt: '2024-03-21T16:01:41.839Z',
|
||||
name: {
|
||||
__typename: 'FullName',
|
||||
firstName: 'Tim',
|
||||
lastName: 'Apple',
|
||||
},
|
||||
id: '20202020-0687-4c41-b707-ed1bfca972a7',
|
||||
userEmail: 'tim@apple.dev',
|
||||
colorScheme: 'Light',
|
||||
createdAt: '2024-03-21T16:01:41.839Z',
|
||||
userId: '20202020-9e3b-46d4-a556-88b9ddc2b034',
|
||||
},
|
||||
workspaceMemberId: '20202020-0687-4c41-b707-ed1bfca972a7',
|
||||
createdAt: '2024-03-22T08:28:44.830Z',
|
||||
name: 'updated.company',
|
||||
companyId: '460b6fb1-ed89-413a-b31a-962986e67bb4',
|
||||
properties: '{"diff": {"address": {"after": "Paris", "before": ""}}}',
|
||||
updatedAt: '2024-03-22T08:28:44.830Z',
|
||||
},
|
||||
];
|
||||
const mockTargetableObject = {
|
||||
id: '1',
|
||||
targetObjectNameSingular: 'Opportunity',
|
||||
};
|
||||
|
||||
const useFindManyRecordsMock = jest.requireMock(
|
||||
'@/object-record/hooks/useFindManyRecords',
|
||||
);
|
||||
useFindManyRecordsMock.useFindManyRecords.mockReturnValue({
|
||||
records: mockedTimelineActivities,
|
||||
});
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useTimelineActivities(mockTargetableObject),
|
||||
);
|
||||
|
||||
expect(result.current.timelineActivities).toEqual(mockedTimelineActivities);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,31 @@
|
||||
import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getActivityTargetObjectFieldIdName';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
|
||||
// do we need to test this?
|
||||
export const useTimelineActivities = (
|
||||
targetableObject: ActivityTargetableObject,
|
||||
) => {
|
||||
const targetableObjectFieldIdName = getActivityTargetObjectFieldIdName({
|
||||
nameSingular: targetableObject.targetObjectNameSingular,
|
||||
});
|
||||
|
||||
const { records: TimelineActivities } = useFindManyRecords({
|
||||
objectNameSingular: CoreObjectNameSingular.TimelineActivity,
|
||||
filter: {
|
||||
[targetableObjectFieldIdName]: {
|
||||
eq: targetableObject.id,
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'DescNullsFirst',
|
||||
},
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
|
||||
return {
|
||||
timelineActivities: TimelineActivities as TimelineActivity[],
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user