diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig.tsx
index 31779f2fa59..28b4c9af685 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig.tsx
+++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig.tsx
@@ -74,8 +74,9 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
position: 0,
isPinned: true,
Icon: IconPlus,
- shouldBeRegistered: ({ objectPermissions, isSoftDeleteFilterActive }) =>
- (objectPermissions.canUpdateObjectRecords && !isSoftDeleteFilterActive) ??
+ shouldBeRegistered: ({ objectPermissions, hasAnySoftDeleteFilterOnView }) =>
+ (objectPermissions.canUpdateObjectRecords &&
+ !hasAnySoftDeleteFilterOnView) ??
false,
availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
component: ,
@@ -108,12 +109,12 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
shouldBeRegistered: ({
selectedRecord,
isFavorite,
- isSoftDeleteFilterActive,
+ hasAnySoftDeleteFilterOnView,
}) =>
!selectedRecord?.isRemote &&
!isFavorite &&
!isDefined(selectedRecord?.deletedAt) &&
- !isSoftDeleteFilterActive,
+ !hasAnySoftDeleteFilterOnView,
availableOn: [
ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
ActionViewType.SHOW_PAGE,
@@ -132,14 +133,14 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
shouldBeRegistered: ({
selectedRecord,
isFavorite,
- isSoftDeleteFilterActive,
+ hasAnySoftDeleteFilterOnView,
}) =>
isDefined(selectedRecord) &&
!selectedRecord?.isRemote &&
isDefined(isFavorite) &&
isFavorite &&
!isDefined(selectedRecord?.deletedAt) &&
- !isSoftDeleteFilterActive,
+ !hasAnySoftDeleteFilterOnView,
availableOn: [
ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
ActionViewType.SHOW_PAGE,
@@ -231,8 +232,8 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
Icon: IconFileImport,
accent: 'default',
isPinned: false,
- shouldBeRegistered: ({ isSoftDeleteFilterActive }) =>
- !isSoftDeleteFilterActive,
+ shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
+ !hasAnySoftDeleteFilterOnView,
availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
component: ,
requiredPermissionFlag: PermissionFlagType.IMPORT_CSV,
@@ -264,12 +265,12 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
isPinned: true,
shouldBeRegistered: ({
selectedRecord,
- isSoftDeleteFilterActive,
+ hasAnySoftDeleteFilterOnView,
objectPermissions,
}) =>
(isDefined(selectedRecord) &&
!selectedRecord.isRemote &&
- !isSoftDeleteFilterActive &&
+ !hasAnySoftDeleteFilterOnView &&
objectPermissions.canSoftDeleteObjectRecords &&
!isDefined(selectedRecord?.deletedAt)) ??
false,
@@ -292,12 +293,12 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
shouldBeRegistered: ({
objectPermissions,
isRemote,
- isSoftDeleteFilterActive,
+ hasAnySoftDeleteFilterOnView,
numberOfSelectedRecords,
}) =>
(objectPermissions.canSoftDeleteObjectRecords &&
!isRemote &&
- !isSoftDeleteFilterActive &&
+ !hasAnySoftDeleteFilterOnView &&
isDefined(numberOfSelectedRecords) &&
numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT) ??
false,
@@ -314,8 +315,8 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
Icon: IconRotate2,
accent: 'default',
isPinned: false,
- shouldBeRegistered: ({ isSoftDeleteFilterActive }) =>
- !isSoftDeleteFilterActive,
+ shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
+ !hasAnySoftDeleteFilterOnView,
availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
component: ,
},
@@ -329,8 +330,8 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
Icon: IconLayout,
accent: 'default',
isPinned: false,
- shouldBeRegistered: ({ isSoftDeleteFilterActive }) =>
- !isSoftDeleteFilterActive,
+ shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
+ !hasAnySoftDeleteFilterOnView,
availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
component: ,
},
@@ -344,8 +345,8 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
Icon: IconEyeOff,
accent: 'default',
isPinned: false,
- shouldBeRegistered: ({ isSoftDeleteFilterActive }) =>
- isDefined(isSoftDeleteFilterActive) && isSoftDeleteFilterActive,
+ shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
+ isDefined(hasAnySoftDeleteFilterOnView) && hasAnySoftDeleteFilterOnView,
availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
component: ,
},
@@ -407,13 +408,13 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
shouldBeRegistered: ({
objectPermissions,
isRemote,
- isSoftDeleteFilterActive,
+ hasAnySoftDeleteFilterOnView,
numberOfSelectedRecords,
}) =>
(objectPermissions.canDestroyObjectRecords &&
!isRemote &&
- isDefined(isSoftDeleteFilterActive) &&
- isSoftDeleteFilterActive &&
+ isDefined(hasAnySoftDeleteFilterOnView) &&
+ hasAnySoftDeleteFilterOnView &&
isDefined(numberOfSelectedRecords) &&
numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT) ??
false,
@@ -435,13 +436,14 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
objectPermissions,
isRemote,
isShowPage,
- isSoftDeleteFilterActive,
+ hasAnySoftDeleteFilterOnView,
}) =>
(!isRemote &&
isDefined(selectedRecord?.deletedAt) &&
objectPermissions.canSoftDeleteObjectRecords &&
((isDefined(isShowPage) && isShowPage) ||
- (isDefined(isSoftDeleteFilterActive) && isSoftDeleteFilterActive))) ??
+ (isDefined(hasAnySoftDeleteFilterOnView) &&
+ hasAnySoftDeleteFilterOnView))) ??
false,
availableOn: [
ActionViewType.SHOW_PAGE,
@@ -462,13 +464,13 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
shouldBeRegistered: ({
objectPermissions,
isRemote,
- isSoftDeleteFilterActive,
+ hasAnySoftDeleteFilterOnView,
numberOfSelectedRecords,
}) =>
(objectPermissions.canSoftDeleteObjectRecords &&
!isRemote &&
- isDefined(isSoftDeleteFilterActive) &&
- isSoftDeleteFilterActive &&
+ isDefined(hasAnySoftDeleteFilterOnView) &&
+ hasAnySoftDeleteFilterOnView &&
isDefined(numberOfSelectedRecords) &&
numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT) ??
false,
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.tsx
index 79338014865..8058d507050 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.tsx
+++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.tsx
@@ -202,8 +202,8 @@ export const WORKFLOW_ACTIONS_CONFIG = inheritActionsFromDefaultConfig({
Icon: IconHistoryToggle,
accent: 'default',
isPinned: true,
- shouldBeRegistered: ({ isSoftDeleteFilterActive }) =>
- !isSoftDeleteFilterActive,
+ shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
+ !hasAnySoftDeleteFilterOnView,
availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
component: (
{
viewBarId: recordIndexId,
});
- const { checkIsSoftDeleteFilter } = useCheckIsSoftDeleteFilter();
+ const { isRecordFilterAboutSoftDelete } = useCheckIsSoftDeleteFilter();
const currentRecordFilters = useRecoilComponentValue(
currentRecordFiltersComponentState,
recordIndexId,
);
- const deletedFilter = currentRecordFilters.find(checkIsSoftDeleteFilter);
+ const deletedFilter = currentRecordFilters.find(
+ isRecordFilterAboutSoftDelete,
+ );
const { removeRecordFilter } = useRemoveRecordFilter();
diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts b/packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts
index 0567448a21d..4f4aa8fd492 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts
+++ b/packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts
@@ -10,7 +10,7 @@ export type ShouldBeRegisteredFunctionParams = {
objectPermissions: ObjectPermissions;
recordFilters?: RecordFilter[];
isShowPage?: boolean;
- isSoftDeleteFilterActive?: boolean;
+ hasAnySoftDeleteFilterOnView?: boolean;
isInRightDrawer?: boolean;
isFavorite?: boolean;
isRemote?: boolean;
diff --git a/packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts b/packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts
index c7600e6c00c..6ecb29f9d38 100644
--- a/packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts
+++ b/packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts
@@ -10,8 +10,8 @@ import { useFavorites } from '@/favorites/hooks/useFavorites';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
+import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
-import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useContext } from 'react';
import { useRecoilCallback, useRecoilValue } from 'recoil';
@@ -51,8 +51,8 @@ export const useShouldActionBeRegisteredParams = ({
const { isInRightDrawer } = useContext(ActionMenuContext);
- const isSoftDeleteFilterActive = useRecoilComponentValue(
- isSoftDeleteFilterActiveComponentState,
+ const hasAnySoftDeleteFilterOnView = useRecoilComponentValue(
+ hasAnySoftDeleteFilterOnViewComponentSelector,
);
const isShowPage =
@@ -106,7 +106,7 @@ export const useShouldActionBeRegisteredParams = ({
objectPermissions,
isNoteOrTask,
isInRightDrawer,
- isSoftDeleteFilterActive,
+ hasAnySoftDeleteFilterOnView,
isShowPage,
selectedRecord,
numberOfSelectedRecords,
diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx
index b7fd2b506e9..7b6301466d2 100644
--- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx
@@ -7,10 +7,12 @@ import { RecordBoardColumnDropdownMenu } from '@/object-record/record-board/reco
import { RecordBoardColumnHeaderAggregateDropdown } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdown';
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
import { useAggregateRecordsForRecordBoardColumn } from '@/object-record/record-board/record-board-column/hooks/useAggregateRecordsForRecordBoardColumn';
+import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView';
import { RecordGroupDefinitionType } from '@/object-record/record-group/types/RecordGroupDefinition';
import { useCreateNewIndexRecord } from '@/object-record/record-table/hooks/useCreateNewIndexRecord';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useToggleDropdown } from '@/ui/layout/dropdown/hooks/useToggleDropdown';
+import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { Tag } from 'twenty-ui/components';
import { IconDotsVertical, IconPlus } from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
@@ -80,6 +82,10 @@ export const RecordBoardColumnHeader = () => {
const hasObjectUpdatePermissions = objectPermissions.canUpdateObjectRecords;
+ const hasAnySoftDeleteFilterOnView = useRecoilComponentValue(
+ hasAnySoftDeleteFilterOnViewComponentSelector,
+ );
+
const { createNewIndexRecord } = useCreateNewIndexRecord({
objectMetadataItem: objectMetadataItem,
});
@@ -145,18 +151,20 @@ export const RecordBoardColumnHeader = () => {
});
}}
/>
- {hasObjectUpdatePermissions && (
- {
- createNewIndexRecord({
- position: 'first',
- [selectFieldMetadataItem.name]: columnDefinition.value,
- });
- }}
- />
- )}
+ {hasObjectUpdatePermissions &&
+ !hasAnySoftDeleteFilterOnView && (
+ {
+ createNewIndexRecord({
+ position: 'first',
+ [selectFieldMetadataItem.name]:
+ columnDefinition.value,
+ });
+ }}
+ />
+ )}
)}
diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewRecordButton.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewRecordButton.tsx
index 34079091313..ce62e0b46b6 100644
--- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewRecordButton.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewRecordButton.tsx
@@ -1,7 +1,9 @@
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
+import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView';
import { useCreateNewIndexRecord } from '@/object-record/record-table/hooks/useCreateNewIndexRecord';
+import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useContext } from 'react';
@@ -32,6 +34,10 @@ export const RecordBoardColumnNewRecordButton = () => {
const { columnDefinition } = useContext(RecordBoardColumnContext);
+ const hasAnySoftDeleteFilterOnView = useRecoilComponentValue(
+ hasAnySoftDeleteFilterOnViewComponentSelector,
+ );
+
const objectPermissions = useObjectPermissionsForObject(
objectMetadataItem.id,
);
@@ -46,6 +52,10 @@ export const RecordBoardColumnNewRecordButton = () => {
return null;
}
+ if (hasAnySoftDeleteFilterOnView) {
+ return null;
+ }
+
return (
{
diff --git a/packages/twenty-front/src/modules/object-record/record-filter/hooks/useCheckIsSoftDeleteFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/hooks/useCheckIsSoftDeleteFilter.ts
index 4280974cb52..2ab17935a85 100644
--- a/packages/twenty-front/src/modules/object-record/record-filter/hooks/useCheckIsSoftDeleteFilter.ts
+++ b/packages/twenty-front/src/modules/object-record/record-filter/hooks/useCheckIsSoftDeleteFilter.ts
@@ -2,39 +2,33 @@ import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadat
import { SOFT_DELETE_FILTER_FIELD_NAME } from '@/object-record/record-filter/constants/SoftDeleteFilterFieldName';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
-import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState';
-import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
-import { isDefined } from 'twenty-shared/utils';
+import { getRecordFilterFieldMetadataItem } from '@/object-record/record-filter/utils/getRecordFilterFieldMetadataItem';
+import { isRecordFilterAboutSoftDelete as isRecordFilterAboutSoftDeleteUtil } from '@/object-record/record-filter/utils/isRecordFilterAboutSoftDelete';
export const useCheckIsSoftDeleteFilter = () => {
const { objectMetadataItems } = useObjectMetadataItems();
- const isSoftDeleteFilterActive = useRecoilComponentValue(
- isSoftDeleteFilterActiveComponentState,
- );
+ const isRecordFilterAboutSoftDelete = (recordFilter: RecordFilter) => {
+ return isRecordFilterAboutSoftDeleteUtil({
+ recordFilter,
+ objectMetadataItems,
+ });
+ };
- const checkIsSoftDeleteFilter = (recordFilter: RecordFilter) => {
- const allFieldMetadataItems = objectMetadataItems.flatMap(
- (objectMetadataItem) => objectMetadataItem.fields,
- );
+ const isSeeDeletedRecordsFilter = (recordFilter: RecordFilter) => {
+ const foundFieldMetadataItem = getRecordFilterFieldMetadataItem({
+ recordFilter,
+ objectMetadataItems,
+ });
- const foundFieldMetadataItem = allFieldMetadataItems.find(
- (fieldMetadataItem) =>
- fieldMetadataItem.id === recordFilter.fieldMetadataId,
- );
-
- if (!isDefined(foundFieldMetadataItem)) {
- throw new Error(
- `Field metadata item not found for field metadata id: ${recordFilter.fieldMetadataId}`,
- );
- }
+ const isNotEmptyFilter =
+ recordFilter.operand === RecordFilterOperand.IsNotEmpty;
return (
foundFieldMetadataItem.name === SOFT_DELETE_FILTER_FIELD_NAME &&
- isSoftDeleteFilterActive &&
- recordFilter.operand === RecordFilterOperand.IsNotEmpty
+ isNotEmptyFilter
);
};
- return { checkIsSoftDeleteFilter };
+ return { isRecordFilterAboutSoftDelete, isSeeDeletedRecordsFilter };
};
diff --git a/packages/twenty-front/src/modules/object-record/record-filter/states/hasAnySoftDeleteFilterOnView.ts b/packages/twenty-front/src/modules/object-record/record-filter/states/hasAnySoftDeleteFilterOnView.ts
new file mode 100644
index 00000000000..0b223812e8a
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-filter/states/hasAnySoftDeleteFilterOnView.ts
@@ -0,0 +1,29 @@
+import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
+import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext';
+import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
+import { isRecordFilterAboutSoftDelete } from '@/object-record/record-filter/utils/isRecordFilterAboutSoftDelete';
+import { createComponentSelector } from '@/ui/utilities/state/component-state/utils/createComponentSelector';
+
+export const hasAnySoftDeleteFilterOnViewComponentSelector =
+ createComponentSelector({
+ key: 'hasAnySoftDeleteFilterOnViewComponentSelector',
+ componentInstanceContext: RecordFiltersComponentInstanceContext,
+ get:
+ ({ instanceId }) =>
+ ({ get }) => {
+ const objectMetadataItems = get(objectMetadataItemsState);
+ const currentRecordFilters = get(
+ currentRecordFiltersComponentState.atomFamily({ instanceId }),
+ );
+
+ const hasAnySoftDeleteFilterOnView = currentRecordFilters.some(
+ (recordFilter) => {
+ return isRecordFilterAboutSoftDelete({
+ recordFilter,
+ objectMetadataItems,
+ });
+ },
+ );
+ return hasAnySoftDeleteFilterOnView;
+ },
+ });
diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/getRecordFilterFieldMetadataItem.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/getRecordFilterFieldMetadataItem.ts
new file mode 100644
index 00000000000..4757fb6d9de
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/getRecordFilterFieldMetadataItem.ts
@@ -0,0 +1,28 @@
+import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
+import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
+import { isDefined } from 'twenty-shared/utils';
+
+export const getRecordFilterFieldMetadataItem = ({
+ recordFilter,
+ objectMetadataItems,
+}: {
+ recordFilter: RecordFilter;
+ objectMetadataItems: ObjectMetadataItem[];
+}) => {
+ const allFieldMetadataItems = objectMetadataItems.flatMap(
+ (objectMetadataItem) => objectMetadataItem.fields,
+ );
+
+ const foundFieldMetadataItem = allFieldMetadataItems.find(
+ (fieldMetadataItem) =>
+ fieldMetadataItem.id === recordFilter.fieldMetadataId,
+ );
+
+ if (!isDefined(foundFieldMetadataItem)) {
+ throw new Error(
+ `Field metadata item not found for field metadata id: ${recordFilter.fieldMetadataId}`,
+ );
+ }
+
+ return foundFieldMetadataItem;
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordFilterAboutSoftDelete.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordFilterAboutSoftDelete.ts
new file mode 100644
index 00000000000..cb73cddd431
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordFilterAboutSoftDelete.ts
@@ -0,0 +1,29 @@
+import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
+import { SOFT_DELETE_FILTER_FIELD_NAME } from '@/object-record/record-filter/constants/SoftDeleteFilterFieldName';
+import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
+import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
+import { getRecordFilterFieldMetadataItem } from '@/object-record/record-filter/utils/getRecordFilterFieldMetadataItem';
+import isEmpty from 'lodash.isempty';
+
+export const isRecordFilterAboutSoftDelete = ({
+ recordFilter,
+ objectMetadataItems,
+}: {
+ recordFilter: RecordFilter;
+ objectMetadataItems: ObjectMetadataItem[];
+}) => {
+ const foundFieldMetadataItem = getRecordFilterFieldMetadataItem({
+ recordFilter,
+ objectMetadataItems,
+ });
+
+ const valueIsNotEmptyFilter =
+ (recordFilter.operand === RecordFilterOperand.Is &&
+ !isEmpty(recordFilter.value)) ||
+ recordFilter.operand === RecordFilterOperand.IsNotEmpty;
+
+ return (
+ foundFieldMetadataItem.name === SOFT_DELETE_FILTER_FIELD_NAME &&
+ valueIsNotEmptyFilter
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableAddNew.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableAddNew.tsx
index ba4f500f548..26202638540 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableAddNew.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableAddNew.tsx
@@ -1,4 +1,5 @@
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
+import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView';
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
import { useCreateNewIndexRecord } from '@/object-record/record-table/hooks/useCreateNewIndexRecord';
import { RecordTableActionRow } from '@/object-record/record-table/record-table-row/components/RecordTableActionRow';
@@ -24,6 +25,14 @@ export const RecordTableAddNew = () => {
const hasObjectUpdatePermissions = objectPermissions.canUpdateObjectRecords;
+ const hasAnySoftDeleteFilterOnView = useRecoilComponentValue(
+ hasAnySoftDeleteFilterOnViewComponentSelector,
+ );
+
+ if (hasAnySoftDeleteFilterOnView) {
+ return null;
+ }
+
if (!hasObjectUpdatePermissions || !hasRecordTableFetchedAllRecords) {
return null;
}
diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx
index acd024b12be..d9d5eb3064c 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx
@@ -1,6 +1,8 @@
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
+import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView';
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
+import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { type IconComponent } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import {
@@ -44,6 +46,10 @@ export const RecordTableEmptyStateDisplay = (
objectMetadataItem,
});
+ const hasAnySoftDeleteFilterOnView = useRecoilComponentValue(
+ hasAnySoftDeleteFilterOnViewComponentSelector,
+ );
+
return (
@@ -56,15 +62,17 @@ export const RecordTableEmptyStateDisplay = (
{'buttonComponent' in props && props.buttonComponent}
- {'buttonTitle' in props && !isReadOnly && (
-
- )}
+ {'buttonTitle' in props &&
+ !isReadOnly &&
+ !hasAnySoftDeleteFilterOnView && (
+
+ )}
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx
index 04374f6b872..d727c7ab58f 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx
@@ -28,10 +28,12 @@ export const RecordTableEmptyStateSoftDelete = () => {
const { removeRecordFilter } = useRemoveRecordFilter();
- const { checkIsSoftDeleteFilter } = useCheckIsSoftDeleteFilter();
+ const { isRecordFilterAboutSoftDelete } = useCheckIsSoftDeleteFilter();
const handleButtonClick = async () => {
- const deletedFilter = currentRecordFilters.find(checkIsSoftDeleteFilter);
+ const deletedFilter = currentRecordFilters.find(
+ isRecordFilterAboutSoftDelete,
+ );
if (!isDefined(deletedFilter)) {
throw new Error('Deleted filter not found');
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderLabelIdentifierCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderLabelIdentifierCell.tsx
index 9bc43b03da0..6b612502403 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderLabelIdentifierCell.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderLabelIdentifierCell.tsx
@@ -3,6 +3,7 @@ import { useState } from 'react';
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
+import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
import { useCreateNewIndexRecord } from '@/object-record/record-table/hooks/useCreateNewIndexRecord';
@@ -124,6 +125,10 @@ export const RecordTableHeaderLabelIdentifierCell = () => {
resizedFieldMetadataIdComponentState,
);
+ const hasAnySoftDeleteFilterOnView = useRecoilComponentValue(
+ hasAnySoftDeleteFilterOnViewComponentSelector,
+ );
+
if (!recordField) {
return <>>;
}
@@ -171,7 +176,8 @@ export const RecordTableHeaderLabelIdentifierCell = () => {
/>
{(isMobile || iconIsVisible) &&
!isReadOnly &&
- hasObjectUpdatePermissions && (
+ hasObjectUpdatePermissions &&
+ !hasAnySoftDeleteFilterOnView && (
theme.spacing(2)};
`;
-const StyledSeperator = styled.div`
+const StyledSeparator = styled.div`
align-self: stretch;
background: ${({ theme }) => theme.background.quaternary};
width: 1px;
@@ -148,19 +148,19 @@ export const ViewBarDetails = ({
const { viewAnyFieldFilterDifferentFromCurrentAnyFieldFilter } =
useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter();
- const { checkIsSoftDeleteFilter } = useCheckIsSoftDeleteFilter();
+ const { isSeeDeletedRecordsFilter } = useCheckIsSoftDeleteFilter();
- const softDeleteFilter = currentRecordFilters.find((recordFilter) =>
- checkIsSoftDeleteFilter(recordFilter),
+ const allSoftDeletedRecordsFilter = currentRecordFilters.find(
+ (recordFilter) => isSeeDeletedRecordsFilter(recordFilter),
);
const recordFilters = useMemo(() => {
return currentRecordFilters.filter(
(recordFilter) =>
!recordFilter.recordFilterGroupId &&
- !checkIsSoftDeleteFilter(recordFilter),
+ !isSeeDeletedRecordsFilter(recordFilter),
);
- }, [currentRecordFilters, checkIsSoftDeleteFilter]);
+ }, [currentRecordFilters, isSeeDeletedRecordsFilter]);
const { applyCurrentViewFilterGroupsToCurrentRecordFilterGroups } =
useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups();
@@ -222,17 +222,17 @@ export const ViewBarDetails = ({
defaultEnableYScroll={false}
>
- {isDefined(softDeleteFilter) && (
+ {isDefined(allSoftDeletedRecordsFilter) && (
)}
- {isDefined(softDeleteFilter) && (
-
-
-
+ {isDefined(allSoftDeletedRecordsFilter) && (
+
+
+
)}
{currentRecordSorts.map((recordSort) => (
-
-
+
+
+
)}
{shouldShowAnyFieldSearchChip && }
{shouldShowAdvancedFilterDropdownButton && (