Activity cache injection (#3791)

* WIP

* Minor fixes

* Added TODO

* Fix post merge

* Fix

* Fixed warnings

* Fixed comments

* Fixed comments

* Fixed naming

* Removed comment

* WIP

* WIP 2

* Finished working version

* Fixes

* Fixed typing

* Fixes

* Fixes

* Fixes

* Naming fixes

* WIP

* Fix import

* WIP

* Working version on title

* Fixed create record id overwrite

* Removed unecessary callback

* Masterpiece

* Fixed delete on click outside drawer or delete

* Cleaned

* Cleaned

* Cleaned

* Minor fixes

* Fixes

* Fixed naming

* WIP

* Fix

* Fixed create from target inline cell

* Removed console.log

* Fixed delete activity optimistic effect

* Fixed no title

* Fixed debounce and title body creation

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Lucas Bordeau
2024-02-09 14:51:30 +01:00
committed by GitHub
parent 9ceff84bbf
commit cca72da708
87 changed files with 2195 additions and 1058 deletions

View File

@ -0,0 +1,34 @@
import { useSetRecoilState } from 'recoil';
import { useActivityConnectionUtils } from '@/activities/utils/useActivityConnectionUtils';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
const QUERY_DEPTH_TO_GET_ACTIVITY_TARGET_RELATIONS = 3;
export const useActivityById = ({ activityId }: { activityId: string }) => {
const setEntityFields = useSetRecoilState(recordStoreFamilyState(activityId));
const { makeActivityWithoutConnection } = useActivityConnectionUtils();
const { record: activityWithConnections } = useFindOneRecord({
objectNameSingular: CoreObjectNameSingular.Activity,
objectRecordId: activityId,
skip: !activityId,
onCompleted: (activityWithConnections: any) => {
const { activity } = makeActivityWithoutConnection(
activityWithConnections,
);
setEntityFields(activity);
},
depth: QUERY_DEPTH_TO_GET_ACTIVITY_TARGET_RELATIONS,
});
const { activity } = makeActivityWithoutConnection(activityWithConnections);
return {
activity,
};
};

View File

@ -1,3 +1,4 @@
import { isNonEmptyString } from '@sniptt/guards';
import { useRecoilValue } from 'recoil';
import { ActivityTargetObjectRecord } from '@/activities/types/ActivityTargetObject';
@ -17,6 +18,7 @@ export const useActivityTargetObjectRecords = ({
const { records: activityTargets, loading: loadingActivityTargets } =
useFindManyRecords({
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
skip: !isNonEmptyString(activityId),
filter: {
activityId: {
eq: activityId,

View File

@ -1,4 +1,5 @@
import { useState } from 'react';
import { isNonEmptyString } from '@sniptt/guards';
import { ActivityTarget } from '@/activities/types/ActivityTarget';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
@ -6,7 +7,7 @@ import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getTarget
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
export const useActivityTargets = ({
export const useActivityTargetsForTargetableObject = ({
targetableObject,
}: {
targetableObject: ActivityTargetableObject;
@ -17,9 +18,14 @@ export const useActivityTargets = ({
const [initialized, setInitialized] = useState(false);
const targetableObjectId = targetableObject.id;
const skipRequest = !isNonEmptyString(targetableObjectId);
const { records: activityTargets, loading: loadingActivityTargets } =
useFindManyRecords({
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
skip: skipRequest,
filter: {
[targetObjectFieldName]: {
eq: targetableObject.id,

View File

@ -0,0 +1,91 @@
import { useApolloClient } from '@apollo/client';
import { StringKeyOf } from 'type-fest';
import { getRelationDefinition } from '@/apollo/optimistic-effect/utils/getRelationDefinition';
import { triggerAttachRelationOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerAttachRelationOptimisticEffect';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { getObjectMetadataItemByNameSingular } from '@/object-metadata/utils/getObjectMetadataItemBySingularName';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { isDefined } from '~/utils/isDefined';
export const useAttachRelationInBothDirections = () => {
const { objectMetadataItems } = useObjectMetadataItems();
const apolloClient = useApolloClient();
const attachRelationInBothDirections = <
Source extends ObjectRecord = ObjectRecord,
Target extends ObjectRecord = ObjectRecord,
>({
sourceRecord,
targetRecords,
sourceObjectNameSingular,
targetObjectNameSingular,
fieldNameOnSourceRecord,
fieldNameOnTargetRecord,
}: {
sourceRecord: Source;
targetRecords: Target[];
sourceObjectNameSingular: string;
targetObjectNameSingular: string;
fieldNameOnSourceRecord: StringKeyOf<Source>;
fieldNameOnTargetRecord: StringKeyOf<Target>;
}) => {
const sourceObjectMetadataItem = getObjectMetadataItemByNameSingular({
objectMetadataItems,
objectNameSingular: sourceObjectNameSingular,
});
const targetObjectMetadataItem = getObjectMetadataItemByNameSingular({
objectMetadataItems,
objectNameSingular: targetObjectNameSingular,
});
const fieldMetadataItemOnSourceRecord =
sourceObjectMetadataItem.fields.find(
(field) => field.name === fieldNameOnSourceRecord,
);
if (!isDefined(fieldMetadataItemOnSourceRecord)) {
throw new Error(
`Field ${fieldNameOnSourceRecord} not found on object ${sourceObjectNameSingular}`,
);
}
const relationDefinition = getRelationDefinition({
fieldMetadataItemOnSourceRecord: fieldMetadataItemOnSourceRecord,
objectMetadataItems,
});
if (!isDefined(relationDefinition)) {
throw new Error(
`Relation metadata not found for field ${fieldNameOnSourceRecord} on object ${sourceObjectNameSingular}`,
);
}
// TODO: could we use triggerUpdateRelationsOptimisticEffect here?
targetRecords.forEach((relationTargetRecord) => {
triggerAttachRelationOptimisticEffect({
cache: apolloClient.cache,
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
sourceRecordId: sourceRecord.id,
fieldNameOnTargetRecord: fieldNameOnTargetRecord,
targetObjectNameSingular: targetObjectMetadataItem.nameSingular,
targetRecordId: relationTargetRecord.id,
});
triggerAttachRelationOptimisticEffect({
cache: apolloClient.cache,
sourceObjectNameSingular: targetObjectMetadataItem.nameSingular,
sourceRecordId: relationTargetRecord.id,
fieldNameOnTargetRecord: fieldNameOnSourceRecord,
targetObjectNameSingular: sourceObjectMetadataItem.nameSingular,
targetRecordId: sourceRecord.id,
});
});
};
return {
attachRelationInBothDirections,
};
};

View File

@ -0,0 +1,115 @@
import { isNonEmptyString } from '@sniptt/guards';
import { useRecoilValue } from 'recoil';
import { v4 } from 'uuid';
import { useAttachRelationInBothDirections } from '@/activities/hooks/useAttachRelationInBothDirections';
import { useInjectIntoActivityTargetInlineCellCache } from '@/activities/inline-cell/hooks/useInjectIntoActivityTargetInlineCellCache';
import { useInjectIntoTimelineActivitiesQueryAfterDrawerMount } from '@/activities/timeline/hooks/useInjectIntoTimelineActivitiesQueryAfterDrawerMount';
import { Activity, ActivityType } from '@/activities/types/Activity';
import { ActivityTarget } from '@/activities/types/ActivityTarget';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { getActivityTargetsToCreateFromTargetableObjects } from '@/activities/utils/getActivityTargetsToCreateFromTargetableObjects';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateManyRecordsInCache } from '@/object-record/hooks/useCreateManyRecordsInCache';
import { useCreateOneRecordInCache } from '@/object-record/hooks/useCreateOneRecordInCache';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
export const useCreateActivityInCache = () => {
const { createManyRecordsInCache: createManyActivityTargetsInCache } =
useCreateManyRecordsInCache<ActivityTarget>({
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
});
const { createOneRecordInCache: createOneActivityInCache } =
useCreateOneRecordInCache<Activity>({
objectNameSingular: CoreObjectNameSingular.Activity,
});
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { record: workspaceMemberRecord } = useFindOneRecord({
objectNameSingular: CoreObjectNameSingular.WorkspaceMember,
objectRecordId: currentWorkspaceMember?.id,
depth: 3,
});
const { injectIntoTimelineActivitiesQueryAfterDrawerMount } =
useInjectIntoTimelineActivitiesQueryAfterDrawerMount();
const { injectIntoActivityTargetInlineCellCache } =
useInjectIntoActivityTargetInlineCellCache();
const {
attachRelationInBothDirections:
attachRelationSourceRecordToItsRelationTargetRecordsAndViceVersaInCache,
} = useAttachRelationInBothDirections();
const createActivityInCache = ({
type,
targetableObjects,
timelineTargetableObject,
assigneeId,
}: {
type: ActivityType;
targetableObjects: ActivityTargetableObject[];
timelineTargetableObject: ActivityTargetableObject;
assigneeId?: string;
}) => {
const activityId = v4();
const createdActivityInCache = createOneActivityInCache({
id: activityId,
author: workspaceMemberRecord,
authorId: workspaceMemberRecord?.id,
assignee: !assigneeId ? workspaceMemberRecord : undefined,
assigneeId:
assigneeId ?? isNonEmptyString(workspaceMemberRecord?.id)
? workspaceMemberRecord?.id
: undefined,
type: type,
});
const activityTargetsToCreate =
getActivityTargetsToCreateFromTargetableObjects({
activityId,
targetableObjects,
});
const createdActivityTargetsInCache = createManyActivityTargetsInCache(
activityTargetsToCreate,
);
injectIntoTimelineActivitiesQueryAfterDrawerMount({
activityToInject: createdActivityInCache,
activityTargetsToInject: createdActivityTargetsInCache,
timelineTargetableObject,
});
injectIntoActivityTargetInlineCellCache({
activityId,
activityTargetsToInject: createdActivityTargetsInCache,
});
attachRelationSourceRecordToItsRelationTargetRecordsAndViceVersaInCache({
sourceRecord: createdActivityInCache,
fieldNameOnSourceRecord: 'activityTargets',
sourceObjectNameSingular: CoreObjectNameSingular.Activity,
fieldNameOnTargetRecord: 'activity',
targetObjectNameSingular: CoreObjectNameSingular.ActivityTarget,
targetRecords: createdActivityTargetsInCache,
});
return {
createdActivityInCache: {
...createdActivityInCache,
activityTargets: createdActivityTargetsInCache,
},
createdActivityTargetsInCache,
};
};
return {
createActivityInCache,
};
};

View File

@ -0,0 +1,59 @@
import { isNonEmptyArray } from '@sniptt/guards';
import { useModifyActivityTargetsOnActivityCache } from '@/activities/hooks/useModifyActivityTargetsOnActivityCache';
import { ActivityForEditor } from '@/activities/types/ActivityForEditor';
import { ActivityTarget } from '@/activities/types/ActivityTarget';
import { useActivityConnectionUtils } from '@/activities/utils/useActivityConnectionUtils';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateManyRecords } from '@/object-record/hooks/useCreateManyRecords';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
export const useCreateActivityInDB = () => {
const { createOneRecord: createOneActivity } = useCreateOneRecord({
objectNameSingular: CoreObjectNameSingular.Activity,
});
const { createManyRecords: createManyActivityTargets } =
useCreateManyRecords<ActivityTarget>({
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
});
const { makeActivityWithConnection } = useActivityConnectionUtils();
const { modifyActivityTargetsOnActivityCache } =
useModifyActivityTargetsOnActivityCache();
const createActivityInDB = async (activityToCreate: ActivityForEditor) => {
const { activityWithConnection } = makeActivityWithConnection(
activityToCreate as any, // TODO: fix type
);
await createOneActivity?.(
{
...activityWithConnection,
updatedAt: new Date().toISOString(),
},
{
skipOptimisticEffect: true,
},
);
const activityTargetsToCreate = activityToCreate.activityTargets ?? [];
if (isNonEmptyArray(activityTargetsToCreate)) {
await createManyActivityTargets(activityTargetsToCreate, {
skipOptimisticEffect: true,
});
}
// TODO: replace by trigger optimistic effect
modifyActivityTargetsOnActivityCache({
activityId: activityToCreate.id,
activityTargets: activityTargetsToCreate,
});
};
return {
createActivityInDB,
};
};

View File

@ -0,0 +1,39 @@
import { useApolloClient } from '@apollo/client';
import { ActivityForEditor } from '@/activities/types/ActivityForEditor';
import { useActivityConnectionUtils } from '@/activities/utils/useActivityConnectionUtils';
import { triggerDeleteRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect';
import { useObjectMetadataItemOnly } from '@/object-metadata/hooks/useObjectMetadataItemOnly';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
// TODO: this should be useDeleteRecordFromCache
export const useDeleteActivityFromCache = () => {
const { makeActivityWithConnection } = useActivityConnectionUtils();
const apolloClient = useApolloClient();
const { objectMetadataItem: objectMetadataItemActivity } =
useObjectMetadataItemOnly({
objectNameSingular: CoreObjectNameSingular.Activity,
});
const { objectMetadataItems } = useObjectMetadataItems();
const deleteActivityFromCache = (activityToDelete: ActivityForEditor) => {
const { activityWithConnection } = makeActivityWithConnection(
activityToDelete as any, // TODO: fix type
);
triggerDeleteRecordsOptimisticEffect({
cache: apolloClient.cache,
objectMetadataItem: objectMetadataItemActivity,
objectMetadataItems,
recordsToDelete: [activityWithConnection],
});
};
return {
deleteActivityFromCache,
};
};

View File

@ -1,163 +1,61 @@
import { useCallback } from 'react';
import { isNonEmptyString } from '@sniptt/guards';
import { useRecoilState, useRecoilValue } from 'recoil';
import { v4 } from 'uuid';
import { useRecoilState, useSetRecoilState } from 'recoil';
import { useActivityTargets } from '@/activities/hooks/useActivityTargets';
import { useModifyActivityOnActivityTargetsCache } from '@/activities/hooks/useModifyActivityOnActivityTargetCache';
import { useModifyActivityTargetsOnActivityCache } from '@/activities/hooks/useModifyActivityTargetsOnActivityCache';
import { useWriteActivityTargetsInCache } from '@/activities/hooks/useWriteActivityTargetsInCache';
import { useInjectIntoActivityTargetInlineCellCache } from '@/activities/inline-cell/hooks/useInjectIntoActivityTargetInlineCellCache';
import { useInjectIntoTimelineActivitiesQuery } from '@/activities/timeline/hooks/useInjectIntoTimelineActivitiesQuery';
import { Activity, ActivityType } from '@/activities/types/Activity';
import { ActivityTarget } from '@/activities/types/ActivityTarget';
import { getActivityTargetsToCreateFromTargetableObjects } from '@/activities/utils/getActivityTargetsToCreateFromTargetableObjects';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateManyRecordsInCache } from '@/object-record/hooks/useCreateManyRecordsInCache';
import { useCreateOneRecordInCache } from '@/object-record/hooks/useCreateOneRecordInCache';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { mapToRecordId } from '@/object-record/utils/mapToObjectId';
import { useCreateActivityInCache } from '@/activities/hooks/useCreateActivityInCache';
import { activityTargetableEntityArrayState } from '@/activities/states/activityTargetableEntityArrayState';
import { isCreatingActivityState } from '@/activities/states/isCreatingActivityState';
import { temporaryActivityForEditorState } from '@/activities/states/temporaryActivityForEditorState';
import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState';
import { ActivityType } from '@/activities/types/Activity';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { activityTargetableEntityArrayState } from '../states/activityTargetableEntityArrayState';
import { viewableActivityIdState } from '../states/viewableActivityIdState';
import { ActivityTargetableObject } from '../types/ActivityTargetableEntity';
export const useOpenCreateActivityDrawerV2 = ({
targetableObject,
}: {
targetableObject: ActivityTargetableObject;
}) => {
export const useOpenCreateActivityDrawerV2 = () => {
const { openRightDrawer } = useRightDrawer();
const { createManyRecordsInCache: createManyActivityTargetsInCache } =
useCreateManyRecordsInCache<ActivityTarget>({
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
});
const { createOneRecordInCache: createOneActivityInCache } =
useCreateOneRecordInCache<Activity>({
objectNameSingular: CoreObjectNameSingular.Activity,
});
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { record: workspaceMemberRecord } = useFindOneRecord({
objectNameSingular: CoreObjectNameSingular.WorkspaceMember,
objectRecordId: currentWorkspaceMember?.id,
});
const setHotkeyScope = useSetHotkeyScope();
const { createActivityInCache } = useCreateActivityInCache();
const [, setActivityTargetableEntityArray] = useRecoilState(
activityTargetableEntityArrayState,
);
const [, setViewableActivityId] = useRecoilState(viewableActivityIdState);
const { activityTargets } = useActivityTargets({
targetableObject,
});
const setIsCreatingActivity = useSetRecoilState(isCreatingActivityState);
const { injectIntoTimelineActivitiesNextQuery } =
useInjectIntoTimelineActivitiesQuery();
const setTemporaryActivityForEditor = useSetRecoilState(
temporaryActivityForEditorState,
);
const { injectIntoActivityTargetInlineCellCache } =
useInjectIntoActivityTargetInlineCellCache();
const { injectIntoUseActivityTargets } = useWriteActivityTargetsInCache();
const { modifyActivityTargetsOnActivityCache } =
useModifyActivityTargetsOnActivityCache();
const { modifyActivityOnActivityTargetsCache } =
useModifyActivityOnActivityTargetsCache();
return useCallback(
async ({
const openCreateActivityDrawer = async ({
type,
targetableObjects,
timelineTargetableObject,
assigneeId,
}: {
type: ActivityType;
targetableObjects: ActivityTargetableObject[];
timelineTargetableObject: ActivityTargetableObject;
assigneeId?: string;
}) => {
const { createdActivityInCache } = createActivityInCache({
type,
targetableObjects,
timelineTargetableObject,
assigneeId,
}: {
type: ActivityType;
targetableObjects: ActivityTargetableObject[];
assigneeId?: string;
}) => {
const activityId = v4();
});
const createdActivityInCache = await createOneActivityInCache({
id: activityId,
author: workspaceMemberRecord,
authorId: workspaceMemberRecord?.id,
assignee: !assigneeId ? workspaceMemberRecord : undefined,
assigneeId:
assigneeId ?? isNonEmptyString(workspaceMemberRecord?.id)
? workspaceMemberRecord?.id
: undefined,
type: type,
});
setTemporaryActivityForEditor(createdActivityInCache);
setIsCreatingActivity(true);
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
setViewableActivityId(createdActivityInCache.id);
setActivityTargetableEntityArray(targetableObjects ?? []);
openRightDrawer(RightDrawerPages.CreateActivity);
};
if (!createdActivityInCache) {
return;
}
const activityTargetsToCreate =
getActivityTargetsToCreateFromTargetableObjects({
activityId,
targetableObjects,
});
const createdActivityTargetsInCache =
await createManyActivityTargetsInCache(activityTargetsToCreate);
injectIntoUseActivityTargets({
targetableObject,
activityTargetsToInject: createdActivityTargetsInCache,
});
injectIntoTimelineActivitiesNextQuery({
activityTargets,
activityToInject: createdActivityInCache,
});
injectIntoActivityTargetInlineCellCache({
activityId,
activityTargetsToInject: createdActivityTargetsInCache,
});
modifyActivityTargetsOnActivityCache({
activityId,
activityTargets: createdActivityTargetsInCache,
});
modifyActivityOnActivityTargetsCache({
activityTargetIds: createdActivityTargetsInCache.map(mapToRecordId),
activity: createdActivityInCache,
});
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
setViewableActivityId(activityId);
setActivityTargetableEntityArray(targetableObjects ?? []);
openRightDrawer(RightDrawerPages.CreateActivity);
},
[
openRightDrawer,
setActivityTargetableEntityArray,
createManyActivityTargetsInCache,
setHotkeyScope,
setViewableActivityId,
createOneActivityInCache,
workspaceMemberRecord,
activityTargets,
targetableObject,
injectIntoTimelineActivitiesNextQuery,
injectIntoActivityTargetInlineCellCache,
injectIntoUseActivityTargets,
modifyActivityTargetsOnActivityCache,
modifyActivityOnActivityTargetsCache,
],
);
return openCreateActivityDrawer;
};

View File

@ -0,0 +1,45 @@
import { useRecoilState } from 'recoil';
import { useCreateActivityInDB } from '@/activities/hooks/useCreateActivityInDB';
import { isCreatingActivityState } from '@/activities/states/isCreatingActivityState';
import { Activity } from '@/activities/types/Activity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
export const useUpsertActivity = () => {
const [isCreatingActivity, setIsCreatingActivity] = useRecoilState(
isCreatingActivityState,
);
const { updateOneRecord: updateOneActivity } = useUpdateOneRecord<Activity>({
objectNameSingular: CoreObjectNameSingular.Activity,
});
const { createActivityInDB } = useCreateActivityInDB();
const upsertActivity = ({
activity,
input,
}: {
activity: Activity;
input: Partial<Activity>;
}) => {
if (isCreatingActivity) {
createActivityInDB({
...activity,
...input,
});
setIsCreatingActivity(false);
} else {
updateOneActivity?.({
idToUpdate: activity.id,
updateOneRecordInput: input,
});
}
};
return {
upsertActivity,
};
};

View File

@ -1,84 +0,0 @@
import { useApolloClient } from '@apollo/client';
import { ActivityTarget } from '@/activities/types/ActivityTarget';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getTargetObjectFilterFieldName';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { getRecordConnectionFromRecords } from '@/object-record/cache/utils/getRecordConnectionFromRecords';
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
export const useWriteActivityTargetsInCache = () => {
const apolloClient = useApolloClient();
const {
objectMetadataItem: objectMetadataItemActivityTarget,
findManyRecordsQuery: findManyActivityTargetsQuery,
} = useObjectMetadataItem({
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
});
const injectIntoUseActivityTargets = ({
targetableObject,
activityTargetsToInject,
}: {
targetableObject: Pick<
ActivityTargetableObject,
'id' | 'targetObjectNameSingular'
>;
activityTargetsToInject: ActivityTarget[];
}) => {
const targetObjectFieldName = getActivityTargetObjectFieldIdName({
nameSingular: targetableObject.targetObjectNameSingular,
});
const existingActivityTargetsForTargetableObjectQueryResult =
apolloClient.readQuery({
query: findManyActivityTargetsQuery,
variables: {
filter: {
[targetObjectFieldName]: {
eq: targetableObject.id,
},
},
},
});
const existingActivityTargetsForTargetableObject =
getRecordsFromRecordConnection({
recordConnection: existingActivityTargetsForTargetableObjectQueryResult[
objectMetadataItemActivityTarget.namePlural
] as ObjectRecordConnection<ActivityTarget>,
});
const newActivityTargetsForTargetableObject = [
...existingActivityTargetsForTargetableObject,
...activityTargetsToInject,
];
const newActivityTargetsConnection = getRecordConnectionFromRecords({
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
records: newActivityTargetsForTargetableObject,
});
apolloClient.writeQuery({
query: findManyActivityTargetsQuery,
variables: {
filter: {
[targetObjectFieldName]: {
eq: targetableObject.id,
},
},
},
data: {
[objectMetadataItemActivityTarget.namePlural]:
newActivityTargetsConnection,
},
});
};
return {
injectIntoUseActivityTargets,
};
};