Clean record filter and record sort (#10466)
This PR removes what's left from record filter and record sort previous logic to handle CRUD and state management with view. So everything that is named combinedFilter and combinedSort is removed here. We implement currentRecordFilters and currentRecordSorts everywhere. We also remove the event in a state onSortSelectComponentState. (a pattern we want to avoid)
This commit is contained in:
@ -4,29 +4,35 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
|
||||
import { AdvancedFilterRootLevelViewFilterGroup } from '@/object-record/advanced-filter/components/AdvancedFilterRootLevelViewFilterGroup';
|
||||
import { useDeleteCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup';
|
||||
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { AdvancedFilterChip } from '@/views/components/AdvancedFilterChip';
|
||||
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const AdvancedFilterDropdownButton = () => {
|
||||
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
||||
const { deleteCombinedViewFilterGroup } = useDeleteCombinedViewFilterGroup();
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||
|
||||
const advancedViewFilterIds =
|
||||
currentViewWithCombinedFiltersAndSorts?.viewFilters
|
||||
.filter((viewFilter) => isDefined(viewFilter.viewFilterGroupId))
|
||||
.map((viewFilter) => viewFilter.id);
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const advancedRecordFilterIds = currentRecordFilters
|
||||
.filter((recordFilter) => isDefined(recordFilter.viewFilterGroupId))
|
||||
.map((recordFilter) => recordFilter.id);
|
||||
|
||||
const { removeRecordFilter } = useRemoveRecordFilter();
|
||||
|
||||
const handleDropdownClickOutside = useCallback(() => {}, []);
|
||||
|
||||
const handleDropdownClose = () => {};
|
||||
|
||||
const removeAdvancedFilter = useCallback(async () => {
|
||||
if (!advancedViewFilterIds) {
|
||||
if (!advancedRecordFilterIds) {
|
||||
throw new Error('No advanced view filters to remove');
|
||||
}
|
||||
|
||||
@ -39,12 +45,12 @@ export const AdvancedFilterDropdownButton = () => {
|
||||
await deleteCombinedViewFilterGroup(viewFilterGroupId);
|
||||
}
|
||||
|
||||
for (const viewFilterId of advancedViewFilterIds) {
|
||||
await deleteCombinedViewFilter(viewFilterId);
|
||||
for (const recordFilterId of advancedRecordFilterIds) {
|
||||
removeRecordFilter(recordFilterId);
|
||||
}
|
||||
}, [
|
||||
advancedViewFilterIds,
|
||||
deleteCombinedViewFilter,
|
||||
advancedRecordFilterIds,
|
||||
removeRecordFilter,
|
||||
deleteCombinedViewFilterGroup,
|
||||
currentViewWithCombinedFiltersAndSorts?.viewFilterGroups,
|
||||
]);
|
||||
@ -64,7 +70,7 @@ export const AdvancedFilterDropdownButton = () => {
|
||||
clickableComponent={
|
||||
<AdvancedFilterChip
|
||||
onRemove={removeAdvancedFilter}
|
||||
advancedFilterCount={advancedViewFilterIds?.length}
|
||||
advancedFilterCount={advancedRecordFilterIds?.length}
|
||||
/>
|
||||
}
|
||||
dropdownComponents={
|
||||
|
||||
@ -10,7 +10,6 @@ import { ObjectFilterOperandSelectAndInput } from '@/object-record/object-filter
|
||||
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
|
||||
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
|
||||
import { EditableFilterDropdownButtonEffect } from '@/views/components/EditableFilterDropdownButtonEffect';
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
|
||||
type EditableFilterDropdownButtonProps = {
|
||||
viewFilterDropdownId: string;
|
||||
@ -25,19 +24,16 @@ export const EditableFilterDropdownButton = ({
|
||||
}: EditableFilterDropdownButtonProps) => {
|
||||
const { closeDropdown } = useDropdown(viewFilterDropdownId);
|
||||
|
||||
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
||||
|
||||
const { removeRecordFilter } = useRemoveRecordFilter();
|
||||
|
||||
const handleRemove = () => {
|
||||
closeDropdown();
|
||||
|
||||
deleteCombinedViewFilter(viewFilter.id);
|
||||
removeRecordFilter(viewFilter.fieldMetadataId);
|
||||
};
|
||||
|
||||
const handleDropdownClickOutside = useCallback(() => {
|
||||
const { id: fieldId, value, operand, fieldMetadataId } = viewFilter;
|
||||
const { value, operand, fieldMetadataId } = viewFilter;
|
||||
if (
|
||||
!value &&
|
||||
![
|
||||
@ -49,9 +45,8 @@ export const EditableFilterDropdownButton = ({
|
||||
].includes(operand)
|
||||
) {
|
||||
removeRecordFilter(fieldMetadataId);
|
||||
deleteCombinedViewFilter(fieldId);
|
||||
}
|
||||
}, [viewFilter, deleteCombinedViewFilter, removeRecordFilter]);
|
||||
}, [viewFilter, removeRecordFilter]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@ -5,24 +5,17 @@ import { useRemoveRecordSort } from '@/object-record/record-sort/hooks/useRemove
|
||||
import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort';
|
||||
import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
|
||||
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
|
||||
import { useDeleteCombinedViewSorts } from '@/views/hooks/useDeleteCombinedViewSorts';
|
||||
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
|
||||
|
||||
type EditableSortChipProps = {
|
||||
recordSort: RecordSort;
|
||||
};
|
||||
|
||||
export const EditableSortChip = ({ recordSort }: EditableSortChipProps) => {
|
||||
const { deleteCombinedViewSort } = useDeleteCombinedViewSorts();
|
||||
|
||||
const { removeRecordSort } = useRemoveRecordSort();
|
||||
|
||||
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts();
|
||||
|
||||
const { upsertRecordSort } = useUpsertRecordSort();
|
||||
|
||||
const handleRemoveClick = () => {
|
||||
deleteCombinedViewSort(recordSort.fieldMetadataId);
|
||||
removeRecordSort(recordSort.fieldMetadataId);
|
||||
};
|
||||
|
||||
@ -36,7 +29,6 @@ export const EditableSortChip = ({ recordSort }: EditableSortChipProps) => {
|
||||
direction: recordSort.direction === 'asc' ? 'desc' : 'asc',
|
||||
};
|
||||
|
||||
upsertCombinedViewSort(newSort);
|
||||
upsertRecordSort(newSort);
|
||||
};
|
||||
|
||||
|
||||
@ -1,26 +1,13 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
|
||||
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||
import { useApplyViewFiltersToCurrentRecordFilters } from '@/views/hooks/useApplyViewFiltersToCurrentRecordFilters';
|
||||
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
|
||||
export const QueryParamsFiltersEffect = () => {
|
||||
const { hasFiltersQueryParams, getFiltersFromQueryParams, viewIdQueryParam } =
|
||||
const { hasFiltersQueryParams, getFiltersFromQueryParams } =
|
||||
useViewFromQueryParams();
|
||||
|
||||
const currentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
const setUnsavedViewFilter = useSetRecoilComponentFamilyStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
{ viewId: viewIdQueryParam ?? currentViewId },
|
||||
);
|
||||
|
||||
const { resetUnsavedViewStates } = useResetUnsavedViewStates();
|
||||
|
||||
const { applyViewFiltersToCurrentRecordFilters } =
|
||||
@ -34,7 +21,6 @@ export const QueryParamsFiltersEffect = () => {
|
||||
getFiltersFromQueryParams().then((filtersFromParams) => {
|
||||
if (Array.isArray(filtersFromParams)) {
|
||||
applyViewFiltersToCurrentRecordFilters(filtersFromParams);
|
||||
setUnsavedViewFilter(filtersFromParams);
|
||||
}
|
||||
});
|
||||
}, [
|
||||
@ -42,7 +28,6 @@ export const QueryParamsFiltersEffect = () => {
|
||||
getFiltersFromQueryParams,
|
||||
hasFiltersQueryParams,
|
||||
resetUnsavedViewStates,
|
||||
setUnsavedViewFilter,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
|
||||
@ -4,15 +4,12 @@ import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetada
|
||||
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
|
||||
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
|
||||
type RecordFilterChipProps = {
|
||||
recordFilter: RecordFilter;
|
||||
};
|
||||
|
||||
export const RecordFilterChip = ({ recordFilter }: RecordFilterChipProps) => {
|
||||
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
||||
|
||||
const { fieldMetadataItem } = useFieldMetadataItemById(
|
||||
recordFilter.fieldMetadataId,
|
||||
);
|
||||
@ -24,7 +21,6 @@ export const RecordFilterChip = ({ recordFilter }: RecordFilterChipProps) => {
|
||||
const FieldMetadataItemIcon = getIcon(fieldMetadataItem.icon);
|
||||
|
||||
const handleRemoveClick = () => {
|
||||
deleteCombinedViewFilter(recordFilter.id);
|
||||
removeRecordFilter(recordFilter.fieldMetadataId);
|
||||
};
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
|
||||
type SoftDeleteFilterChipProps = {
|
||||
recordFilter: RecordFilter;
|
||||
@ -16,8 +15,6 @@ export const SoftDeleteFilterChip = ({
|
||||
recordFilter,
|
||||
viewBarId,
|
||||
}: SoftDeleteFilterChipProps) => {
|
||||
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
||||
|
||||
const setIsSoftDeleteFilterActive = useSetRecoilComponentStateV2(
|
||||
isSoftDeleteFilterActiveComponentState,
|
||||
viewBarId,
|
||||
@ -28,7 +25,6 @@ export const SoftDeleteFilterChip = ({
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const handleRemoveClick = () => {
|
||||
deleteCombinedViewFilter(recordFilter.id);
|
||||
removeRecordFilter(recordFilter.fieldMetadataId);
|
||||
|
||||
setIsSoftDeleteFilterActive(false);
|
||||
|
||||
@ -10,7 +10,6 @@ import { QueryParamsFiltersEffect } from '@/views/components/QueryParamsFiltersE
|
||||
import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
|
||||
import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle';
|
||||
import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader';
|
||||
import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect';
|
||||
import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown';
|
||||
|
||||
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
|
||||
@ -51,9 +50,7 @@ export const ViewBar = ({
|
||||
<ViewBarRecordFilterEffect />
|
||||
<ViewBarRecordSortEffect />
|
||||
<ViewBarFilterEffect filterDropdownId={filterDropdownId} />
|
||||
<ViewBarSortEffect />
|
||||
<QueryParamsFiltersEffect />
|
||||
|
||||
<ViewBarPageTitle viewBarId={viewBarId} />
|
||||
<TopBar
|
||||
className={className}
|
||||
|
||||
@ -7,7 +7,7 @@ import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-sta
|
||||
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||
import { objectFilterDropdownSelectedOptionValuesComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState';
|
||||
import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/jsonRelationFilterValueSchema';
|
||||
import { simpleRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/simpleRelationFilterValueSchema';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
@ -19,8 +19,6 @@ type ViewBarFilterEffectProps = {
|
||||
export const ViewBarFilterEffect = ({
|
||||
filterDropdownId,
|
||||
}: ViewBarFilterEffectProps) => {
|
||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||
|
||||
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||
filterDropdownId,
|
||||
@ -37,46 +35,48 @@ export const ViewBarFilterEffect = ({
|
||||
filterDropdownId,
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (fieldMetadataItemUsedInDropdown?.type === 'RELATION') {
|
||||
const viewFilterUsedInDropdown =
|
||||
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
||||
(filter) =>
|
||||
filter.fieldMetadataId === fieldMetadataItemUsedInDropdown?.id,
|
||||
);
|
||||
const recordFilterUsedInDropdown = currentRecordFilters.find(
|
||||
(filter) =>
|
||||
filter.fieldMetadataId === fieldMetadataItemUsedInDropdown?.id,
|
||||
);
|
||||
|
||||
const { selectedRecordIds } = jsonRelationFilterValueSchema
|
||||
.catch({
|
||||
isCurrentWorkspaceMemberSelected: false,
|
||||
selectedRecordIds: simpleRelationFilterValueSchema.parse(
|
||||
viewFilterUsedInDropdown?.value,
|
||||
recordFilterUsedInDropdown?.value,
|
||||
),
|
||||
})
|
||||
.parse(viewFilterUsedInDropdown?.value);
|
||||
.parse(recordFilterUsedInDropdown?.value);
|
||||
|
||||
setObjectFilterDropdownSelectedRecordIds(selectedRecordIds);
|
||||
} else if (
|
||||
isDefined(fieldMetadataItemUsedInDropdown) &&
|
||||
['SELECT', 'MULTI_SELECT'].includes(fieldMetadataItemUsedInDropdown.type)
|
||||
) {
|
||||
const viewFilterUsedInDropdown =
|
||||
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
||||
(filter) =>
|
||||
filter.fieldMetadataId === fieldMetadataItemUsedInDropdown?.id,
|
||||
);
|
||||
const recordFilterUsedInDropdown = currentRecordFilters.find(
|
||||
(filter) =>
|
||||
filter.fieldMetadataId === fieldMetadataItemUsedInDropdown?.id,
|
||||
);
|
||||
|
||||
const viewFilterSelectedRecords = isNonEmptyString(
|
||||
viewFilterUsedInDropdown?.value,
|
||||
const recordFilterSelectedRecords = isNonEmptyString(
|
||||
recordFilterUsedInDropdown?.value,
|
||||
)
|
||||
? JSON.parse(viewFilterUsedInDropdown.value)
|
||||
? JSON.parse(recordFilterUsedInDropdown.value)
|
||||
: [];
|
||||
setObjectFilterDropdownSelectedOptionValues(viewFilterSelectedRecords);
|
||||
setObjectFilterDropdownSelectedOptionValues(recordFilterSelectedRecords);
|
||||
}
|
||||
}, [
|
||||
fieldMetadataItemUsedInDropdown,
|
||||
setObjectFilterDropdownSelectedRecordIds,
|
||||
setObjectFilterDropdownSelectedOptionValues,
|
||||
currentViewWithCombinedFiltersAndSorts,
|
||||
currentRecordFilters,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
|
||||
import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort';
|
||||
import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const ViewBarSortEffect = () => {
|
||||
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts();
|
||||
|
||||
const { upsertRecordSort } = useUpsertRecordSort();
|
||||
|
||||
const setOnSortSelect = useSetRecoilComponentStateV2(
|
||||
onSortSelectComponentState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setOnSortSelect(() => (sort: RecordSort | null) => {
|
||||
if (isDefined(sort)) {
|
||||
upsertCombinedViewSort(sort);
|
||||
upsertRecordSort(sort);
|
||||
}
|
||||
});
|
||||
}, [setOnSortSelect, upsertCombinedViewSort, upsertRecordSort]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
Reference in New Issue
Block a user