diff --git a/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInDB.ts b/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInDB.ts index 961514ede..470e9fda0 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInDB.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useCreateActivityInDB.ts @@ -3,35 +3,98 @@ import { isNonEmptyArray } from '@sniptt/guards'; import { CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE } from '@/activities/graphql/operation-signatures/CreateOneActivityOperationSignature'; import { ActivityForEditor } from '@/activities/types/ActivityForEditor'; import { ActivityTarget } from '@/activities/types/ActivityTarget'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { getRecordConnectionFromRecords } from '@/object-record/cache/utils/getRecordConnectionFromRecords'; +import { modifyRecordFromCache } from '@/object-record/cache/utils/modifyRecordFromCache'; import { useCreateManyRecords } from '@/object-record/hooks/useCreateManyRecords'; import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; +import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; +import { useApolloClient } from '@apollo/client'; + +import { useRecoilCallback } from 'recoil'; +import { capitalize } from '~/utils/string/capitalize'; export const useCreateActivityInDB = () => { const { createOneRecord: createOneActivity } = useCreateOneRecord({ objectNameSingular: CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE.objectNameSingular, recordGqlFields: CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE.fields, + shouldMatchRootQueryFilter: true, }); const { createManyRecords: createManyActivityTargets } = useCreateManyRecords({ objectNameSingular: CoreObjectNameSingular.ActivityTarget, - skipPostOptmisticEffect: true, + shouldMatchRootQueryFilter: true, }); - const createActivityInDB = async (activityToCreate: ActivityForEditor) => { - await createOneActivity?.({ - ...activityToCreate, - updatedAt: new Date().toISOString(), + const { objectMetadataItems } = useObjectMetadataItems(); + + const { objectMetadataItem: objectMetadataItemActivityTarget } = + useObjectMetadataItem({ + objectNameSingular: CoreObjectNameSingular.ActivityTarget, }); - const activityTargetsToCreate = activityToCreate.activityTargets ?? []; + const { objectMetadataItem: objectMetadataItemActivity } = + useObjectMetadataItem({ + objectNameSingular: CoreObjectNameSingular.Activity, + }); - if (isNonEmptyArray(activityTargetsToCreate)) { - await createManyActivityTargets(activityTargetsToCreate); - } - }; + const cache = useApolloClient().cache; + + const createActivityInDB = useRecoilCallback( + ({ set }) => + async (activityToCreate: ActivityForEditor) => { + const createdActivity = await createOneActivity?.({ + ...activityToCreate, + updatedAt: new Date().toISOString(), + }); + + const activityTargetsToCreate = activityToCreate.activityTargets ?? []; + + if (isNonEmptyArray(activityTargetsToCreate)) { + await createManyActivityTargets(activityTargetsToCreate); + } + + const activityTargetsConnection = getRecordConnectionFromRecords({ + objectMetadataItems, + objectMetadataItem: objectMetadataItemActivityTarget, + records: activityTargetsToCreate.map((activityTarget) => ({ + ...activityTarget, + __typename: capitalize( + objectMetadataItemActivityTarget.nameSingular, + ), + })), + withPageInfo: false, + computeReferences: true, + isRootLevel: false, + }); + + modifyRecordFromCache({ + recordId: createdActivity.id, + cache, + fieldModifiers: { + activityTargets: () => activityTargetsConnection, + }, + objectMetadataItem: objectMetadataItemActivity, + }); + + set(recordStoreFamilyState(createdActivity.id), { + ...createdActivity, + activityTargets: activityTargetsToCreate, + }); + }, + [ + cache, + createManyActivityTargets, + createOneActivity, + objectMetadataItemActivity, + objectMetadataItemActivityTarget, + objectMetadataItems, + ], + ); return { createActivityInDB, diff --git a/packages/twenty-front/src/modules/activities/timeline/components/Timeline.tsx b/packages/twenty-front/src/modules/activities/timeline/components/Timeline.tsx deleted file mode 100644 index a6b2fd9b0..000000000 --- a/packages/twenty-front/src/modules/activities/timeline/components/Timeline.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import styled from '@emotion/styled'; -import { useRecoilValue } from 'recoil'; - -import { SkeletonLoader } from '@/activities/components/SkeletonLoader'; -import { TimelineCreateButtonGroup } from '@/activities/timeline/components/TimelineCreateButtonGroup'; -import { timelineActivitiesForGroupState } from '@/activities/timeline/states/timelineActivitiesForGroupState'; -import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; -import AnimatedPlaceholder from '@/ui/layout/animated-placeholder/components/AnimatedPlaceholder'; -import { - AnimatedPlaceholderEmptyContainer, - AnimatedPlaceholderEmptySubTitle, - AnimatedPlaceholderEmptyTextContainer, - AnimatedPlaceholderEmptyTitle, - EMPTY_PLACEHOLDER_TRANSITION_PROPS, -} from '@/ui/layout/animated-placeholder/components/EmptyPlaceholderStyled'; -import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; - -import { TimelineItemsContainer } from './TimelineItemsContainer'; - -const StyledMainContainer = styled.div` - align-items: flex-start; - align-self: stretch; - border-top: ${({ theme }) => - useIsMobile() ? `1px solid ${theme.border.color.medium}` : 'none'}; - display: flex; - flex-direction: column; - height: 100%; - - justify-content: center; -`; - -export const Timeline = ({ - targetableObject, - loading, -}: { - targetableObject: ActivityTargetableObject; - loading: boolean; -}) => { - const timelineActivitiesForGroup = useRecoilValue( - timelineActivitiesForGroupState, - ); - - if (loading) { - return ; - } - - if (timelineActivitiesForGroup.length === 0) { - return ( - - - - - Add your first Activity - - - There are no activities associated with this record.{' '} - - - - - ); - } - - return ( - - - - ); -}; diff --git a/packages/twenty-front/src/modules/activities/timeline/components/TimelineCreateButtonGroup.tsx b/packages/twenty-front/src/modules/activities/timeline/components/TimelineCreateButtonGroup.tsx index 21c0c5713..a4ca49149 100644 --- a/packages/twenty-front/src/modules/activities/timeline/components/TimelineCreateButtonGroup.tsx +++ b/packages/twenty-front/src/modules/activities/timeline/components/TimelineCreateButtonGroup.tsx @@ -1,44 +1,30 @@ import { useSetRecoilState } from 'recoil'; import { IconCheckbox, IconNotes, IconPaperclip } from 'twenty-ui'; -import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; -import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { Button } from '@/ui/input/button/components/Button'; import { ButtonGroup } from '@/ui/input/button/components/ButtonGroup'; import { TAB_LIST_COMPONENT_ID } from '@/ui/layout/show-page/components/ShowPageRightContainer'; import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; -export const TimelineCreateButtonGroup = ({ - targetableObject, -}: { - targetableObject: ActivityTargetableObject; -}) => { +export const TimelineCreateButtonGroup = () => { const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID); const setActiveTabId = useSetRecoilState(activeTabIdState); - const openCreateActivity = useOpenCreateActivityDrawer(); - return (