diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/hooks/useLinkedObjectObjectMetadataItem.ts b/packages/twenty-front/src/modules/activities/timeline-activities/hooks/useLinkedObjectObjectMetadataItem.ts index 9f230bef6..3bc1e9cbe 100644 --- a/packages/twenty-front/src/modules/activities/timeline-activities/hooks/useLinkedObjectObjectMetadataItem.ts +++ b/packages/twenty-front/src/modules/activities/timeline-activities/hooks/useLinkedObjectObjectMetadataItem.ts @@ -3,11 +3,14 @@ import { useRecoilValue } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -export const useLinkedObjectObjectMetadataItem = (id: string) => { +export const useLinkedObjectObjectMetadataItem = (id: string | null) => { const objectMetadataItems: ObjectMetadataItem[] = useRecoilValue( objectMetadataItemsState, ); + if (id === null) { + return null; + } return ( objectMetadataItems.find( (objectMetadataItem) => objectMetadataItem.id === id, diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/hooks/useTimelineActivities.ts b/packages/twenty-front/src/modules/activities/timeline-activities/hooks/useTimelineActivities.ts index 96c00233e..679b84213 100644 --- a/packages/twenty-front/src/modules/activities/timeline-activities/hooks/useTimelineActivities.ts +++ b/packages/twenty-front/src/modules/activities/timeline-activities/hooks/useTimelineActivities.ts @@ -6,6 +6,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; +import { isDefined } from 'twenty-shared/utils'; // do we need to test this? export const useTimelineActivities = ( @@ -41,7 +42,8 @@ export const useTimelineActivities = ( const activityIds = timelineActivities .filter((timelineActivity) => timelineActivity.name.match(/note|task/i)) - .map((timelineActivity) => timelineActivity.linkedRecordId); + .map((timelineActivity) => timelineActivity.linkedRecordId) + .filter(isDefined); const { loading: loadingLinkedObjectsTitle } = useLinkedObjectsTitle(activityIds); diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/rows/activity/components/EventRowActivity.tsx b/packages/twenty-front/src/modules/activities/timeline-activities/rows/activity/components/EventRowActivity.tsx index 308efaf2e..54d72d990 100644 --- a/packages/twenty-front/src/modules/activities/timeline-activities/rows/activity/components/EventRowActivity.tsx +++ b/packages/twenty-front/src/modules/activities/timeline-activities/rows/activity/components/EventRowActivity.tsx @@ -5,12 +5,13 @@ import { StyledEventRowItemAction, StyledEventRowItemColumn, } from '@/activities/timeline-activities/rows/components/EventRowDynamicComponent'; +import { isTimelineActivityWithLinkedRecord } from '@/activities/timeline-activities/types/TimelineActivity'; import { useOpenRecordInCommandMenu } from '@/command-menu/hooks/useOpenRecordInCommandMenu'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache'; import { isNonEmptyString } from '@sniptt/guards'; -import { MOBILE_VIEWPORT } from 'twenty-ui/theme'; import { OverflowingTextWithTooltip } from 'twenty-ui/display'; +import { MOBILE_VIEWPORT } from 'twenty-ui/theme'; type EventRowActivityProps = EventRowDynamicComponentProps; @@ -67,7 +68,7 @@ export const EventRowActivity = ({ const eventObject = eventLinkedObject.replace('linked-', ''); - if (!event.linkedRecordId) { + if (!isTimelineActivityWithLinkedRecord(event)) { throw new Error('Could not find linked record id for event'); } @@ -81,11 +82,18 @@ export const EventRowActivity = ({ const activityInStore = getActivityFromCache(event.linkedRecordId); - const activityTitle = isNonEmptyString(activityInStore?.title) - ? activityInStore?.title - : isNonEmptyString(event.linkedRecordCachedName) - ? event.linkedRecordCachedName - : 'Untitled'; + const computeActivityTitle = () => { + if (isNonEmptyString(activityInStore?.title)) { + return activityInStore?.title; + } + + if (isNonEmptyString(event.linkedRecordCachedName)) { + return event.linkedRecordCachedName; + } + + return 'Untitled'; + }; + const activityTitle = computeActivityTitle(); const { openRecordInCommandMenu } = useOpenRecordInCommandMenu(); diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/rows/calendar/components/EventRowCalendarEvent.tsx b/packages/twenty-front/src/modules/activities/timeline-activities/rows/calendar/components/EventRowCalendarEvent.tsx index a4172b8f4..128687a6f 100644 --- a/packages/twenty-front/src/modules/activities/timeline-activities/rows/calendar/components/EventRowCalendarEvent.tsx +++ b/packages/twenty-front/src/modules/activities/timeline-activities/rows/calendar/components/EventRowCalendarEvent.tsx @@ -9,6 +9,7 @@ import { StyledEventRowItemAction, StyledEventRowItemColumn, } from '@/activities/timeline-activities/rows/components/EventRowDynamicComponent'; +import { isTimelineActivityWithLinkedRecord } from '@/activities/timeline-activities/types/TimelineActivity'; type EventRowCalendarEventProps = EventRowDynamicComponentProps; @@ -45,9 +46,11 @@ export const EventRowCalendarEvent = ({ - - - + {isTimelineActivityWithLinkedRecord(event) && ( + + + + )} ); }; diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventRowMessage.tsx b/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventRowMessage.tsx index 00bd68e93..ddd5ed274 100644 --- a/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventRowMessage.tsx +++ b/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventRowMessage.tsx @@ -9,6 +9,7 @@ import { StyledEventRowItemColumn, } from '@/activities/timeline-activities/rows/components/EventRowDynamicComponent'; import { EventCardMessage } from '@/activities/timeline-activities/rows/message/components/EventCardMessage'; +import { isTimelineActivityWithLinkedRecord } from '@/activities/timeline-activities/types/TimelineActivity'; type EventRowMessageProps = EventRowDynamicComponentProps; @@ -49,10 +50,12 @@ export const EventRowMessage = ({ - + {isTimelineActivityWithLinkedRecord(event) && ( + + )} ); diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/types/TimelineActivity.ts b/packages/twenty-front/src/modules/activities/timeline-activities/types/TimelineActivity.ts index b3afecd68..a3caee5f7 100644 --- a/packages/twenty-front/src/modules/activities/timeline-activities/types/TimelineActivity.ts +++ b/packages/twenty-front/src/modules/activities/timeline-activities/types/TimelineActivity.ts @@ -1,3 +1,4 @@ +import { isDefined } from 'twenty-shared/utils'; import { WorkspaceMember } from '~/generated/graphql'; export type TimelineActivity = { @@ -10,7 +11,18 @@ export type TimelineActivity = { properties: any; name: string; linkedRecordCachedName: string; - linkedRecordId: string; - linkedObjectMetadataId: string; + linkedRecordId: string | null; + linkedObjectMetadataId: string | null; __typename: 'TimelineActivity'; } & Record; + +export type TimelineActivityWithRecord = TimelineActivity & { + linkedRecordId: string; + linkedObjectMetadataId: string; +}; + +export const isTimelineActivityWithLinkedRecord = ( + timelineActivity: TimelineActivity, +): timelineActivity is TimelineActivityWithRecord => + isDefined(timelineActivity.linkedObjectMetadataId) && + isDefined(timelineActivity.linkedRecordId);