diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useOpenMergeRecordsPageInCommandMenu.tsx b/packages/twenty-front/src/modules/command-menu/hooks/useOpenMergeRecordsPageInCommandMenu.tsx
index 04e5198ef8..199a42556b 100644
--- a/packages/twenty-front/src/modules/command-menu/hooks/useOpenMergeRecordsPageInCommandMenu.tsx
+++ b/packages/twenty-front/src/modules/command-menu/hooks/useOpenMergeRecordsPageInCommandMenu.tsx
@@ -1,11 +1,15 @@
import { useCommandMenuUpdateNavigationMorphItemsByPage } from '@/command-menu/hooks/useCommandMenuUpdateNavigationMorphItemsByPage';
import { useNavigateCommandMenu } from '@/command-menu/hooks/useNavigateCommandMenu';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
+import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
+
import { msg, t } from '@lingui/core/macro';
+import { useRecoilCallback } from 'recoil';
import { IconArrowMerge } from 'twenty-ui/display';
+import { v4 } from 'uuid';
type UseOpenMergeRecordsPageInCommandMenuProps = {
objectNameSingular: string;
@@ -35,22 +39,43 @@ export const useOpenMergeRecordsPageInCommandMenu = ({
},
});
- const openMergeRecordsPageInCommandMenu = async () => {
- await updateCommandMenuNavigationMorphItemsByPage({
- pageId: CommandMenuPages.MergeRecords,
- objectMetadataId: objectMetadataItem.id,
- objectRecordIds,
- });
- const { records } = await findManyRecordsLazy();
- upsertRecordsInStore(records ?? []);
+ const openMergeRecordsPageInCommandMenu = useRecoilCallback(
+ ({ set }) => {
+ return async () => {
+ const pageId = v4();
- navigateCommandMenu({
- page: CommandMenuPages.MergeRecords,
- pageTitle: t(msg`Merge records`),
- pageIcon: IconArrowMerge,
- pageId: CommandMenuPages.MergeRecords,
- });
- };
+ set(
+ contextStoreCurrentObjectMetadataItemIdComponentState.atomFamily({
+ instanceId: pageId,
+ }),
+ objectMetadataItem.id,
+ );
+
+ await updateCommandMenuNavigationMorphItemsByPage({
+ pageId,
+ objectMetadataId: objectMetadataItem.id,
+ objectRecordIds,
+ });
+ const { records } = await findManyRecordsLazy();
+ upsertRecordsInStore(records ?? []);
+
+ navigateCommandMenu({
+ page: CommandMenuPages.MergeRecords,
+ pageTitle: t(msg`Merge records`),
+ pageIcon: IconArrowMerge,
+ pageId,
+ });
+ };
+ },
+ [
+ objectMetadataItem.id,
+ objectRecordIds,
+ findManyRecordsLazy,
+ upsertRecordsInStore,
+ navigateCommandMenu,
+ updateCommandMenuNavigationMorphItemsByPage,
+ ],
+ );
return {
openMergeRecordsPageInCommandMenu,
diff --git a/packages/twenty-front/src/modules/command-menu/pages/record-page/components/CommandMenuMergeRecordPage.tsx b/packages/twenty-front/src/modules/command-menu/pages/record-page/components/CommandMenuMergeRecordPage.tsx
index ea97c77ab6..7a084f8386 100644
--- a/packages/twenty-front/src/modules/command-menu/pages/record-page/components/CommandMenuMergeRecordPage.tsx
+++ b/packages/twenty-front/src/modules/command-menu/pages/record-page/components/CommandMenuMergeRecordPage.tsx
@@ -1,6 +1,7 @@
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
+import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper';
import { MergeRecordsContainer } from '@/object-record/record-merge/components/MergeRecordsContainer';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
@@ -20,12 +21,14 @@ const StyledRightDrawerRecord = styled.div<{
export const CommandMenuMergeRecordPage = () => {
const isMobile = useIsMobile();
- const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
-
const commandMenuPageInstanceId = useComponentInstanceStateContext(
CommandMenuPageComponentInstanceContext,
)?.instanceId;
+ const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow(
+ commandMenuPageInstanceId,
+ );
+
if (!commandMenuPageInstanceId) {
throw new Error('Command menu page instance id is not defined');
}
@@ -34,15 +37,21 @@ export const CommandMenuMergeRecordPage = () => {
-
-
-
-
-
+
+
+
+
+
+
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-merge/components/MergePreviewTab.tsx b/packages/twenty-front/src/modules/object-record/record-merge/components/MergePreviewTab.tsx
index af5c92a154..2025be24ef 100644
--- a/packages/twenty-front/src/modules/object-record/record-merge/components/MergePreviewTab.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-merge/components/MergePreviewTab.tsx
@@ -1,4 +1,4 @@
-import { useMergePreview } from '@/object-record/record-merge/hooks/useMergePreview';
+import { usePerformMergePreview } from '@/object-record/record-merge/hooks/usePerformMergePreview';
import { SummaryCard } from '@/object-record/record-show/components/SummaryCard';
import { CardType } from '@/object-record/record-show/types/CardType';
import { getCardComponent } from '@/object-record/record-show/utils/getCardComponent';
@@ -14,7 +14,7 @@ type MergePreviewTabProps = {
export const MergePreviewTab = ({
objectNameSingular,
}: MergePreviewTabProps) => {
- const { mergePreviewRecord, isGeneratingPreview } = useMergePreview({
+ const { mergePreviewRecord, isGeneratingPreview } = usePerformMergePreview({
objectNameSingular,
});
diff --git a/packages/twenty-front/src/modules/object-record/record-merge/components/MergeRecordsContainer.tsx b/packages/twenty-front/src/modules/object-record/record-merge/components/MergeRecordsContainer.tsx
index 2c10579cd3..28a1edc635 100644
--- a/packages/twenty-front/src/modules/object-record/record-merge/components/MergeRecordsContainer.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-merge/components/MergeRecordsContainer.tsx
@@ -8,7 +8,7 @@ import { TabListComponentInstanceContext } from '@/ui/layout/tab-list/states/con
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
-import { useMergePreview } from '@/object-record/record-merge/hooks/useMergePreview';
+import { useMergeRecordsSelectedRecords } from '@/object-record/record-merge/hooks/useMergeRecordsSelectedRecords';
import { MergeRecordsTabId } from '@/object-record/record-merge/types/MergeRecordsTabId';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useMergeRecordsContainerTabs } from '../hooks/useMergeRecordsContainerTabs';
@@ -45,9 +45,7 @@ type MergeRecordsContainerProps = {
export const MergeRecordsContainer = ({
objectNameSingular,
}: MergeRecordsContainerProps) => {
- const { selectedRecords } = useMergePreview({
- objectNameSingular,
- });
+ const { selectedRecords } = useMergeRecordsSelectedRecords();
const { tabs } = useMergeRecordsContainerTabs(selectedRecords);
@@ -76,9 +74,7 @@ export const MergeRecordsContainer = ({
{activeTabId === MergeRecordsTabId.MERGE_PREVIEW && (
)}
- {activeTabId === MergeRecordsTabId.SETTINGS && (
-
- )}
+ {activeTabId === MergeRecordsTabId.SETTINGS && }
{selectedRecords.some((record) => record.id === activeTabId) && (
{
+export const MergeSettingsTab = () => {
const { mergeSettings, updatePriorityRecordIndex } =
useMergeRecordsSettings();
- const { selectedRecords } = useMergePreview({
- objectNameSingular,
- });
+ const { selectedRecords } = useMergeRecordsSelectedRecords();
const priorityOptions = selectedRecords.map((_, index) => ({
value: index,
diff --git a/packages/twenty-front/src/modules/object-record/record-merge/hooks/useMergeRecordsActions.ts b/packages/twenty-front/src/modules/object-record/record-merge/hooks/useMergeRecordsActions.ts
index 7c6b10f59b..28f88be4e3 100644
--- a/packages/twenty-front/src/modules/object-record/record-merge/hooks/useMergeRecordsActions.ts
+++ b/packages/twenty-front/src/modules/object-record/record-merge/hooks/useMergeRecordsActions.ts
@@ -3,7 +3,7 @@ import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { useMergeManyRecords } from '@/object-record/hooks/useMergeManyRecords';
-import { useMergePreview } from '@/object-record/record-merge/hooks/useMergePreview';
+import { useMergeRecordsSelectedRecords } from '@/object-record/record-merge/hooks/useMergeRecordsSelectedRecords';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { AppPath } from 'twenty-shared/types';
import { useNavigateApp } from '~/hooks/useNavigateApp';
@@ -19,9 +19,7 @@ export const useMergeRecordsActions = ({
}: UseMergeRecordsActionsProps) => {
const mergeSettings = useRecoilValue(mergeSettingsState);
- const { selectedRecords } = useMergePreview({
- objectNameSingular,
- });
+ const { selectedRecords } = useMergeRecordsSelectedRecords();
const { mergeManyRecords, loading: isMerging } = useMergeManyRecords({
objectNameSingular,
diff --git a/packages/twenty-front/src/modules/object-record/record-merge/hooks/useMergeRecordsSelectedRecords.ts b/packages/twenty-front/src/modules/object-record/record-merge/hooks/useMergeRecordsSelectedRecords.ts
new file mode 100644
index 0000000000..fdc7a69afe
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-merge/hooks/useMergeRecordsSelectedRecords.ts
@@ -0,0 +1,30 @@
+import { commandMenuNavigationMorphItemsByPageState } from '@/command-menu/states/commandMenuNavigationMorphItemsByPageState';
+import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
+import { recordStoreRecordsSelector } from '@/object-record/record-store/states/selectors/recordStoreRecordsSelector';
+import { useComponentInstanceStateContext } from '@/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext';
+import { useRecoilValue } from 'recoil';
+
+export const useMergeRecordsSelectedRecords = () => {
+ const mergeRecordsPageInstanceId = useComponentInstanceStateContext(
+ CommandMenuPageComponentInstanceContext,
+ )?.instanceId;
+
+ const commandMenuNavigationMorphItemsByPage = useRecoilValue(
+ commandMenuNavigationMorphItemsByPageState,
+ );
+
+ const selectedRecordIds =
+ commandMenuNavigationMorphItemsByPage
+ .get(mergeRecordsPageInstanceId ?? '')
+ ?.map((morphItem) => morphItem.recordId) ?? [];
+
+ const selectedRecords = useRecoilValue(
+ recordStoreRecordsSelector({
+ recordIds: selectedRecordIds,
+ }),
+ );
+
+ return {
+ selectedRecords,
+ };
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-merge/hooks/useMergePreview.ts b/packages/twenty-front/src/modules/object-record/record-merge/hooks/usePerformMergePreview.ts
similarity index 73%
rename from packages/twenty-front/src/modules/object-record/record-merge/hooks/useMergePreview.ts
rename to packages/twenty-front/src/modules/object-record/record-merge/hooks/usePerformMergePreview.ts
index a9b634952e..6f41bd6f5e 100644
--- a/packages/twenty-front/src/modules/object-record/record-merge/hooks/useMergePreview.ts
+++ b/packages/twenty-front/src/modules/object-record/record-merge/hooks/usePerformMergePreview.ts
@@ -1,9 +1,7 @@
-import { commandMenuNavigationMorphItemsByPageState } from '@/command-menu/states/commandMenuNavigationMorphItemsByPageState';
-import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
import { useMergeManyRecords } from '@/object-record/hooks/useMergeManyRecords';
+import { useMergeRecordsSelectedRecords } from '@/object-record/record-merge/hooks/useMergeRecordsSelectedRecords';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
-import { recordStoreRecordsSelector } from '@/object-record/record-store/states/selectors/recordStoreRecordsSelector';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { useEffect, useState } from 'react';
import { useRecoilValue } from 'recoil';
@@ -14,7 +12,7 @@ type UseMergePreviewProps = {
objectNameSingular: string;
};
-export const useMergePreview = ({
+export const usePerformMergePreview = ({
objectNameSingular,
}: UseMergePreviewProps) => {
const [mergePreviewRecord, setMergePreviewRecord] =
@@ -29,26 +27,20 @@ export const useMergePreview = ({
objectNameSingular,
});
- const commandMenuNavigationMorphItemsByPage = useRecoilValue(
- commandMenuNavigationMorphItemsByPageState,
- );
-
- const selectedRecordIds =
- commandMenuNavigationMorphItemsByPage
- .get(CommandMenuPages.MergeRecords)
- ?.map((morphItem) => morphItem.recordId) ?? [];
- const selectedRecords = useRecoilValue(
- recordStoreRecordsSelector({
- recordIds: selectedRecordIds,
- }),
- );
+ const { selectedRecords } = useMergeRecordsSelectedRecords();
const { upsertRecordsInStore } = useUpsertRecordsInStore();
useEffect(() => {
const fetchPreview = async () => {
- if (selectedRecords.length < 2 || isMergeInProgress || isInitialized)
+ if (
+ selectedRecords.length < 2 ||
+ isMergeInProgress ||
+ isInitialized ||
+ isGeneratingPreview
+ ) {
return;
+ }
setIsGeneratingPreview(true);
try {
@@ -83,13 +75,13 @@ export const useMergePreview = ({
selectedRecords,
mergeSettings,
isMergeInProgress,
+ isGeneratingPreview,
mergeManyRecords,
upsertRecordsInStore,
isInitialized,
]);
return {
- selectedRecords,
mergePreviewRecord,
isGeneratingPreview: isGeneratingPreview,
};
diff --git a/packages/twenty-server/src/engine/api/common/common-query-runners/common-merge-many-query-runner.service.ts b/packages/twenty-server/src/engine/api/common/common-query-runners/common-merge-many-query-runner.service.ts
index 9ddbd566f3..72b839353a 100644
--- a/packages/twenty-server/src/engine/api/common/common-query-runners/common-merge-many-query-runner.service.ts
+++ b/packages/twenty-server/src/engine/api/common/common-query-runners/common-merge-many-query-runner.service.ts
@@ -5,10 +5,10 @@ import {
QUERY_MAX_RECORDS,
} from 'twenty-shared/constants';
import {
+ FieldMetadataRelationSettings,
FieldMetadataType,
ObjectRecord,
RelationType,
- FieldMetadataRelationSettings,
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { FindOptionsRelations, In, ObjectLiteral } from 'typeorm';
@@ -95,7 +95,7 @@ export class CommonMergeManyQueryRunnerService extends CommonBaseQueryRunnerServ
});
await queryBuilder
- .softDelete()
+ .delete()
.whereInIds(idsToDelete)
.returning(columnsToReturn)
.execute();