fix timeline activity deleted field (#6433)

Fixes https://github.com/twentyhq/twenty/issues/6362
This commit is contained in:
Weiko 2024-07-29 15:17:40 +02:00 committed by GitHub
parent fed12ddfcd
commit 4389e81e64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 161 additions and 3 deletions

View File

@ -1,8 +1,9 @@
import { ReactElement } from 'react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { ReactElement } from 'react';
import { EventsGroup } from '@/activities/timelineActivities/components/EventsGroup'; import { EventsGroup } from '@/activities/timelineActivities/components/EventsGroup';
import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity'; import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity';
import { filterOutInvalidTimelineActivities } from '@/activities/timelineActivities/utils/filterOutInvalidTimelineActivities';
import { groupEventsByMonth } from '@/activities/timelineActivities/utils/groupEventsByMonth'; import { groupEventsByMonth } from '@/activities/timelineActivities/utils/groupEventsByMonth';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
@ -29,12 +30,17 @@ const StyledTimelineContainer = styled.div`
`; `;
export const EventList = ({ events, targetableObject }: EventListProps) => { export const EventList = ({ events, targetableObject }: EventListProps) => {
const groupedEvents = groupEventsByMonth(events);
const mainObjectMetadataItem = useObjectMetadataItem({ const mainObjectMetadataItem = useObjectMetadataItem({
objectNameSingular: targetableObject.targetObjectNameSingular, objectNameSingular: targetableObject.targetObjectNameSingular,
}).objectMetadataItem; }).objectMetadataItem;
const filteredEvents = filterOutInvalidTimelineActivities(
events,
mainObjectMetadataItem,
);
const groupedEvents = groupEventsByMonth(filteredEvents);
return ( return (
<ScrollWrapper> <ScrollWrapper>
<StyledTimelineContainer> <StyledTimelineContainer>

View File

@ -0,0 +1,117 @@
import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity';
import { filterOutInvalidTimelineActivities } from '@/activities/timelineActivities/utils/filterOutInvalidTimelineActivities';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
describe('filterOutInvalidTimelineActivities', () => {
it('should filter out TimelineActivities with deleted fields from the properties diff', () => {
const events = [
{
id: '1',
properties: {
diff: {
field1: { before: 'value1', after: 'value2' },
field2: { before: 'value3', after: 'value4' },
field3: { before: 'value5', after: 'value6' },
},
},
},
{
id: '2',
properties: {
diff: {
field1: { before: 'value7', after: 'value8' },
field2: { before: 'value9', after: 'value10' },
field4: { before: 'value11', after: 'value12' },
},
},
},
] as TimelineActivity[];
const mainObjectMetadataItem = {
fields: [{ name: 'field1' }, { name: 'field2' }, { name: 'field3' }],
} as ObjectMetadataItem;
const filteredEvents = filterOutInvalidTimelineActivities(
events,
mainObjectMetadataItem,
);
expect(filteredEvents).toEqual([
{
id: '1',
properties: {
diff: {
field1: { before: 'value1', after: 'value2' },
field2: { before: 'value3', after: 'value4' },
field3: { before: 'value5', after: 'value6' },
},
},
},
{
id: '2',
properties: {
diff: {
field1: { before: 'value7', after: 'value8' },
field2: { before: 'value9', after: 'value10' },
},
},
},
]);
});
it('should return an empty array if all TimelineActivities have deleted fields in the properties diff', () => {
const events = [
{
id: '1',
properties: {
diff: {
field3: { before: 'value5', after: 'value6' },
},
},
},
{
id: '2',
properties: {
diff: {
field4: { before: 'value11', after: 'value12' },
},
},
},
] as TimelineActivity[];
const mainObjectMetadataItem = {
fields: [{ name: 'field1' }, { name: 'field2' }],
} as ObjectMetadataItem;
const filteredEvents = filterOutInvalidTimelineActivities(
events,
mainObjectMetadataItem,
);
expect(filteredEvents).toEqual([]);
});
it('should return the same TimelineActivities if there are no properties diffs', () => {
const events = [
{
id: '1',
properties: {},
},
{
id: '2',
properties: {},
},
] as TimelineActivity[];
const mainObjectMetadataItem = {
fields: [{ name: 'field1' }, { name: 'field2' }],
} as ObjectMetadataItem;
const filteredEvents = filterOutInvalidTimelineActivities(
events,
mainObjectMetadataItem,
);
expect(filteredEvents).toEqual(events);
});
});

View File

@ -0,0 +1,35 @@
import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
export const filterOutInvalidTimelineActivities = (
timelineActivities: TimelineActivity[],
mainObjectMetadataItem: ObjectMetadataItem,
): TimelineActivity[] => {
const fieldMetadataItemMap = new Map(
mainObjectMetadataItem.fields.map((field) => [field.name, field]),
);
return timelineActivities.filter((timelineActivity) => {
const diff = timelineActivity.properties?.diff;
const canSkipValidation = !diff;
if (canSkipValidation) {
return true;
}
const validDiffEntries = Object.entries(diff).filter(([diffKey]) =>
fieldMetadataItemMap.has(diffKey),
);
if (validDiffEntries.length === 0) {
return false;
}
timelineActivity.properties = {
...timelineActivity.properties,
diff: Object.fromEntries(validDiffEntries),
};
return true;
});
};