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:
@ -2,13 +2,13 @@ import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMeta
|
||||
import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector';
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { useUpsertCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useUpsertCombinedViewFilterGroup';
|
||||
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
|
||||
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
|
||||
import { ViewFilterGroup } from '@/views/types/ViewFilterGroup';
|
||||
import { ViewFilterGroupLogicalOperator } from '@/views/types/ViewFilterGroupLogicalOperator';
|
||||
import { useCallback } from 'react';
|
||||
@ -31,7 +31,7 @@ export const AdvancedFilterAddFilterRuleSelect = ({
|
||||
const { currentViewId } = useGetCurrentView();
|
||||
|
||||
const { upsertCombinedViewFilterGroup } = useUpsertCombinedViewFilterGroup();
|
||||
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters();
|
||||
const { upsertRecordFilter } = useUpsertRecordFilter();
|
||||
|
||||
const newPositionInViewFilterGroup = lastChildPosition + 1;
|
||||
|
||||
@ -86,7 +86,7 @@ export const AdvancedFilterAddFilterRuleSelect = ({
|
||||
defaultFieldMetadataItem.type,
|
||||
);
|
||||
|
||||
upsertCombinedViewFilter({
|
||||
upsertRecordFilter({
|
||||
id: v4(),
|
||||
fieldMetadataId: defaultFieldMetadataItem.id,
|
||||
type: filterType,
|
||||
@ -124,7 +124,7 @@ export const AdvancedFilterAddFilterRuleSelect = ({
|
||||
defaultFieldMetadataItem.type,
|
||||
);
|
||||
|
||||
upsertCombinedViewFilter({
|
||||
upsertRecordFilter({
|
||||
id: v4(),
|
||||
fieldMetadataId: defaultFieldMetadataItem.id,
|
||||
type: filterType,
|
||||
|
||||
@ -49,7 +49,7 @@ export const AdvancedFilterRootLevelViewFilterGroup = ({
|
||||
return (
|
||||
<StyledContainer>
|
||||
{childViewFiltersAndViewFilterGroups.map((child, i) =>
|
||||
child.__typename === 'ViewFilterGroup' ? (
|
||||
(child as any).__typename === 'ViewFilterGroup' ? (
|
||||
<StyledRow key={child.id}>
|
||||
<AdvancedFilterLogicalOperatorCell
|
||||
index={i}
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
import { AdvancedFilterRuleOptionsDropdownButton } from '@/object-record/advanced-filter/components/AdvancedFilterRuleOptionsDropdownButton';
|
||||
import { useCurrentViewFilter } from '@/object-record/advanced-filter/hooks/useCurrentViewFilter';
|
||||
|
||||
import { useCurrentViewViewFilterGroup } from '@/object-record/advanced-filter/hooks/useCurrentViewViewFilterGroup';
|
||||
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 { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { MenuItem } from 'twenty-ui';
|
||||
|
||||
@ -25,7 +28,7 @@ export const AdvancedFilterRuleOptionsDropdown = ({
|
||||
}: AdvancedFilterRuleOptionsDropdownProps) => {
|
||||
const dropdownId = `advanced-filter-rule-options-${viewFilterId ?? viewFilterGroupId}`;
|
||||
|
||||
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
||||
const { removeRecordFilter } = useRemoveRecordFilter();
|
||||
const { deleteCombinedViewFilterGroup } = useDeleteCombinedViewFilterGroup();
|
||||
|
||||
const { currentViewFilterGroup, childViewFiltersAndViewFilterGroups } =
|
||||
@ -33,32 +36,37 @@ export const AdvancedFilterRuleOptionsDropdown = ({
|
||||
viewFilterGroupId,
|
||||
});
|
||||
|
||||
const currentViewFilter = useCurrentViewFilter({
|
||||
viewFilterId,
|
||||
});
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const currentRecordFilter = currentRecordFilters.find(
|
||||
(recordFilter) => recordFilter.id === viewFilterId,
|
||||
);
|
||||
|
||||
const handleRemove = async () => {
|
||||
if (isDefined(viewFilterId)) {
|
||||
deleteCombinedViewFilter(viewFilterId);
|
||||
removeRecordFilter(viewFilterId);
|
||||
|
||||
const isOnlyViewFilterInGroup =
|
||||
childViewFiltersAndViewFilterGroups.length === 1;
|
||||
|
||||
if (
|
||||
isOnlyViewFilterInGroup &&
|
||||
isDefined(currentViewFilter?.viewFilterGroupId)
|
||||
isDefined(currentRecordFilter?.viewFilterGroupId)
|
||||
) {
|
||||
deleteCombinedViewFilterGroup(currentViewFilter.viewFilterGroupId);
|
||||
deleteCombinedViewFilterGroup(currentRecordFilter.viewFilterGroupId);
|
||||
}
|
||||
} else if (isDefined(currentViewFilterGroup)) {
|
||||
deleteCombinedViewFilterGroup(currentViewFilterGroup.id);
|
||||
|
||||
// TODO: This is a temporary fix view filter group will be removed soon.
|
||||
const childViewFilters = childViewFiltersAndViewFilterGroups.filter(
|
||||
(child) => child.__typename === 'ViewFilter',
|
||||
(child) => (child as any).__typename === 'ViewFilter',
|
||||
);
|
||||
|
||||
for (const childViewFilter of childViewFilters) {
|
||||
await deleteCombinedViewFilter(childViewFilter.id);
|
||||
removeRecordFilter(childViewFilter.id);
|
||||
}
|
||||
} else {
|
||||
throw new Error('No view filter or view filter group to remove');
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
import { AdvancedFilterViewFilterFieldSelect } from '@/object-record/advanced-filter/components/AdvancedFilterViewFilterFieldSelect';
|
||||
import { AdvancedFilterViewFilterOperandSelect } from '@/object-record/advanced-filter/components/AdvancedFilterViewFilterOperandSelect';
|
||||
import { AdvancedFilterViewFilterValueInput } from '@/object-record/advanced-filter/components/AdvancedFilterViewFilterValueInput';
|
||||
import { useCurrentViewFilter } from '@/object-record/advanced-filter/hooks/useCurrentViewFilter';
|
||||
|
||||
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
|
||||
import { configurableViewFilterOperands } from '@/object-record/object-filter-dropdown/utils/configurableViewFilterOperands';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import styled from '@emotion/styled';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
const StyledValueDropdownContainer = styled.div`
|
||||
flex: 3;
|
||||
@ -25,22 +28,30 @@ type AdvancedFilterViewFilterProps = {
|
||||
export const AdvancedFilterViewFilter = ({
|
||||
viewFilterId,
|
||||
}: AdvancedFilterViewFilterProps) => {
|
||||
const filter = useCurrentViewFilter({ viewFilterId });
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
if (!filter) {
|
||||
const recordFilter = currentRecordFilters.find(
|
||||
(recordFilter) => recordFilter.id === viewFilterId,
|
||||
);
|
||||
|
||||
if (!isDefined(recordFilter)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ObjectFilterDropdownComponentInstanceContext.Provider
|
||||
value={{ instanceId: filter.id }}
|
||||
value={{ instanceId: recordFilter.id }}
|
||||
>
|
||||
<StyledRow>
|
||||
<AdvancedFilterViewFilterFieldSelect viewFilterId={filter.id} />
|
||||
<AdvancedFilterViewFilterOperandSelect viewFilterId={filter.id} />
|
||||
<AdvancedFilterViewFilterFieldSelect viewFilterId={recordFilter.id} />
|
||||
<AdvancedFilterViewFilterOperandSelect viewFilterId={recordFilter.id} />
|
||||
<StyledValueDropdownContainer>
|
||||
{configurableViewFilterOperands.has(filter.operand) && (
|
||||
<AdvancedFilterViewFilterValueInput viewFilterId={filter.id} />
|
||||
{configurableViewFilterOperands.has(recordFilter.operand) && (
|
||||
<AdvancedFilterViewFilterValueInput
|
||||
viewFilterId={recordFilter.id}
|
||||
/>
|
||||
)}
|
||||
</StyledValueDropdownContainer>
|
||||
</StyledRow>
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
|
||||
import { useCurrentViewFilter } from '@/object-record/advanced-filter/hooks/useCurrentViewFilter';
|
||||
|
||||
import { ObjectFilterDropdownFilterSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect';
|
||||
import { ObjectFilterDropdownFilterSelectCompositeFieldSubMenu } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectCompositeFieldSubMenu';
|
||||
import { advancedFilterViewFilterGroupIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterGroupIdComponentState';
|
||||
import { advancedFilterViewFilterIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterIdComponentState';
|
||||
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { SelectControl } from '@/ui/input/components/SelectControl';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
|
||||
import styled from '@emotion/styled';
|
||||
@ -25,7 +27,13 @@ export const AdvancedFilterViewFilterFieldSelect = ({
|
||||
}: AdvancedFilterViewFilterFieldSelectProps) => {
|
||||
const { advancedFilterDropdownId } = useAdvancedFilterDropdown(viewFilterId);
|
||||
|
||||
const recordFilter = useCurrentViewFilter({ viewFilterId });
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const recordFilter = currentRecordFilters.find(
|
||||
(recordFilter) => recordFilter.id === viewFilterId,
|
||||
);
|
||||
|
||||
const selectedFieldLabel = recordFilter?.label ?? '';
|
||||
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById';
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { useCurrentViewFilter } from '@/object-record/advanced-filter/hooks/useCurrentViewFilter';
|
||||
|
||||
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
|
||||
import { getOperandLabel } from '@/object-record/object-filter-dropdown/utils/getOperandLabel';
|
||||
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||
import { SelectControl } from '@/ui/input/components/SelectControl';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
|
||||
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import styled from '@emotion/styled';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
@ -28,7 +30,13 @@ export const AdvancedFilterViewFilterOperandSelect = ({
|
||||
}: AdvancedFilterViewFilterOperandSelectProps) => {
|
||||
const dropdownId = `advanced-filter-view-filter-operand-${viewFilterId}`;
|
||||
|
||||
const filter = useCurrentViewFilter({ viewFilterId });
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const filter = currentRecordFilters.find(
|
||||
(recordFilter) => recordFilter.id === viewFilterId,
|
||||
);
|
||||
|
||||
const { getFieldMetadataItemById } = useGetFieldMetadataItemById();
|
||||
|
||||
@ -36,7 +44,7 @@ export const AdvancedFilterViewFilterOperandSelect = ({
|
||||
|
||||
const { closeDropdown } = useDropdown(dropdownId);
|
||||
|
||||
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters();
|
||||
const { upsertRecordFilter } = useUpsertRecordFilter();
|
||||
|
||||
const handleOperandChange = (operand: ViewFilterOperand) => {
|
||||
closeDropdown();
|
||||
@ -60,7 +68,7 @@ export const AdvancedFilterViewFilterOperandSelect = ({
|
||||
filter.displayValue,
|
||||
);
|
||||
|
||||
upsertCombinedViewFilter({
|
||||
upsertRecordFilter({
|
||||
...filter,
|
||||
operand,
|
||||
value,
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { useCurrentViewFilter } from '@/object-record/advanced-filter/hooks/useCurrentViewFilter';
|
||||
import { ObjectFilterDropdownFilterInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput';
|
||||
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
||||
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { SelectControl } from '@/ui/input/components/SelectControl';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
|
||||
|
||||
@ -18,7 +19,13 @@ export const AdvancedFilterViewFilterValueInput = ({
|
||||
}: AdvancedFilterViewFilterValueInputProps) => {
|
||||
const dropdownId = `advanced-filter-view-filter-value-input-${viewFilterId}`;
|
||||
|
||||
const filter = useCurrentViewFilter({ viewFilterId });
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const filter = currentRecordFilters.find(
|
||||
(recordFilter) => recordFilter.id === viewFilterId,
|
||||
);
|
||||
|
||||
const isDisabled = !filter?.fieldMetadataId || !filter.operand;
|
||||
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
||||
|
||||
export const useCurrentViewFilter = ({
|
||||
viewFilterId,
|
||||
}: {
|
||||
viewFilterId?: string;
|
||||
}) => {
|
||||
const { filterableFieldMetadataItems } =
|
||||
useFilterableFieldMetadataItemsInRecordIndexContext();
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||
|
||||
const viewFilter = currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
||||
(viewFilter) => viewFilter.id === viewFilterId,
|
||||
);
|
||||
|
||||
if (!viewFilter) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const [filter] = mapViewFiltersToFilters(
|
||||
[viewFilter],
|
||||
filterableFieldMetadataItems,
|
||||
);
|
||||
|
||||
return filter;
|
||||
};
|
||||
@ -1,3 +1,5 @@
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||
import { ViewFilterGroup } from '@/views/types/ViewFilterGroup';
|
||||
@ -10,6 +12,10 @@ export const useCurrentViewViewFilterGroup = ({
|
||||
}) => {
|
||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const viewFilterGroup =
|
||||
currentViewWithCombinedFiltersAndSorts?.viewFilterGroups.find(
|
||||
(viewFilterGroup) => viewFilterGroup.id === viewFilterGroupId,
|
||||
@ -25,11 +31,10 @@ export const useCurrentViewViewFilterGroup = ({
|
||||
};
|
||||
}
|
||||
|
||||
const childViewFilters =
|
||||
currentViewWithCombinedFiltersAndSorts?.viewFilters.filter(
|
||||
(viewFilterToFilter) =>
|
||||
viewFilterToFilter.viewFilterGroupId === viewFilterGroup.id,
|
||||
);
|
||||
const childRecordFilters = currentRecordFilters.filter(
|
||||
(recordFilterToFilter) =>
|
||||
recordFilterToFilter.viewFilterGroupId === viewFilterGroup.id,
|
||||
);
|
||||
|
||||
const childViewFilterGroups =
|
||||
currentViewWithCombinedFiltersAndSorts?.viewFilterGroups.filter(
|
||||
@ -39,7 +44,7 @@ export const useCurrentViewViewFilterGroup = ({
|
||||
|
||||
const childViewFiltersAndViewFilterGroups = [
|
||||
...(childViewFilterGroups ?? []),
|
||||
...(childViewFilters ?? []),
|
||||
...(childRecordFilters ?? []),
|
||||
].sort((a, b) => {
|
||||
const positionA = a.positionInViewFilterGroup ?? 0;
|
||||
const positionB = b.positionInViewFilterGroup ?? 0;
|
||||
|
||||
@ -3,12 +3,12 @@ import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-met
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { useUpsertCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useUpsertCombinedViewFilterGroup';
|
||||
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
|
||||
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
|
||||
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
|
||||
import { ViewFilterGroupLogicalOperator } from '@/views/types/ViewFilterGroupLogicalOperator';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
@ -59,7 +59,7 @@ export const AdvancedFilterButton = () => {
|
||||
|
||||
const { upsertCombinedViewFilterGroup } = useUpsertCombinedViewFilterGroup();
|
||||
|
||||
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters();
|
||||
const { upsertRecordFilter } = useUpsertRecordFilter();
|
||||
|
||||
const objectMetadataId =
|
||||
currentViewWithCombinedFiltersAndSorts?.objectMetadataId;
|
||||
@ -115,7 +115,7 @@ export const AdvancedFilterButton = () => {
|
||||
filterType,
|
||||
})[0];
|
||||
|
||||
upsertCombinedViewFilter({
|
||||
upsertRecordFilter({
|
||||
id: v4(),
|
||||
fieldMetadataId: defaultFieldMetadataItem.id,
|
||||
operand: firstOperand,
|
||||
|
||||
@ -11,13 +11,14 @@ import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-re
|
||||
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
|
||||
import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown';
|
||||
import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect';
|
||||
import { SelectableItem } from '@/object-record/select/types/SelectableItem';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { RelationFilterValue } from '@/views/view-filter-value/types/RelationFilterValue';
|
||||
import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/jsonRelationFilterValueSchema';
|
||||
import { simpleRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/simpleRelationFilterValueSchema';
|
||||
@ -59,10 +60,11 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
objectFilterDropdownSelectedRecordIdsComponentState,
|
||||
);
|
||||
|
||||
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
|
||||
const setObjectFilterDropdownSelectedRecordIds = useSetRecoilComponentStateV2(
|
||||
objectFilterDropdownSelectedRecordIdsComponentState,
|
||||
);
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } =
|
||||
useGetCurrentView(viewComponentId);
|
||||
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
|
||||
|
||||
const { isCurrentWorkspaceMemberSelected } = jsonRelationFilterValueSchema
|
||||
.catch({
|
||||
@ -121,6 +123,10 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
.includes(objectFilterDropdownSearchInput.toLowerCase()),
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const handleMultipleRecordSelectChange = (
|
||||
itemToSelect: SelectableItem,
|
||||
isNewSelectedValue: boolean,
|
||||
@ -136,6 +142,7 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
...objectFilterDropdownSelectedRecordIds,
|
||||
itemToSelect.id,
|
||||
];
|
||||
|
||||
const selectedRecordIdsWithRemovedRecord =
|
||||
objectFilterDropdownSelectedRecordIds.filter(
|
||||
(id) => id !== itemToSelect.id,
|
||||
@ -187,14 +194,15 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
} satisfies RelationFilterValue)
|
||||
: '';
|
||||
|
||||
const viewFilter =
|
||||
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
||||
(viewFilter) =>
|
||||
viewFilter.fieldMetadataId ===
|
||||
fieldMetadataItemUsedInFilterDropdown.id,
|
||||
);
|
||||
const recordFilterInDropdown = currentRecordFilters.find(
|
||||
(recordFilter) =>
|
||||
recordFilter.fieldMetadataId ===
|
||||
fieldMetadataItemUsedInFilterDropdown.id,
|
||||
);
|
||||
|
||||
const filterId = viewFilter?.id ?? v4();
|
||||
setObjectFilterDropdownSelectedRecordIds(newSelectedRecordIds);
|
||||
|
||||
const filterId = recordFilterInDropdown?.id ?? v4();
|
||||
|
||||
applyRecordFilter({
|
||||
id: selectedFilter?.id ? selectedFilter.id : filterId,
|
||||
|
||||
@ -11,13 +11,12 @@ import { selectedOperandInDropdownComponentState } from '@/object-record/object-
|
||||
import { getActorSourceMultiSelectOptions } from '@/object-record/object-filter-dropdown/utils/getActorSourceMultiSelectOptions';
|
||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
|
||||
import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown';
|
||||
import { SelectableItem } from '@/object-record/select/types/SelectableItem';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
@ -57,12 +56,6 @@ export const ObjectFilterDropdownSourceSelect = ({
|
||||
|
||||
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
|
||||
|
||||
const { deleteCombinedViewFilter } =
|
||||
useDeleteCombinedViewFilters(viewComponentId);
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } =
|
||||
useGetCurrentView(viewComponentId);
|
||||
|
||||
// TODO: this should be removed as it is not consistent across re-renders
|
||||
const [fieldId] = useState(v4());
|
||||
|
||||
@ -78,6 +71,10 @@ export const ObjectFilterDropdownSourceSelect = ({
|
||||
|
||||
const { removeRecordFilter } = useRemoveRecordFilter();
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const handleMultipleItemSelectChange = (
|
||||
itemToSelect: SelectableItem,
|
||||
newSelectedValue: boolean,
|
||||
@ -97,7 +94,7 @@ export const ObjectFilterDropdownSourceSelect = ({
|
||||
if (newSelectedItemIds.length === 0) {
|
||||
emptyRecordFilter();
|
||||
removeRecordFilter(fieldMetadataItemUsedInFilterDropdown.id);
|
||||
deleteCombinedViewFilter(fieldId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -121,14 +118,13 @@ export const ObjectFilterDropdownSourceSelect = ({
|
||||
? JSON.stringify(newSelectedItemIds)
|
||||
: EMPTY_FILTER_VALUE;
|
||||
|
||||
const viewFilter =
|
||||
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
||||
(viewFilter) =>
|
||||
viewFilter.fieldMetadataId ===
|
||||
fieldMetadataItemUsedInFilterDropdown.id,
|
||||
);
|
||||
const recordFilter = currentRecordFilters.find(
|
||||
(recordFilter) =>
|
||||
recordFilter.fieldMetadataId ===
|
||||
fieldMetadataItemUsedInFilterDropdown.id,
|
||||
);
|
||||
|
||||
const filterId = viewFilter?.id ?? fieldId;
|
||||
const filterId = recordFilter?.id ?? fieldId;
|
||||
|
||||
applyRecordFilter({
|
||||
id: selectedFilter?.id ? selectedFilter.id : filterId,
|
||||
|
||||
@ -10,9 +10,9 @@ import { useResetSortDropdown } from '@/object-record/object-sort-dropdown/hooks
|
||||
import { useToggleSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useToggleSortDropdown';
|
||||
import { isRecordSortDirectionDropdownMenuUnfoldedComponentState } from '@/object-record/object-sort-dropdown/states/isRecordSortDirectionDropdownMenuUnfoldedComponentState';
|
||||
import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState';
|
||||
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
|
||||
import { selectedRecordSortDirectionComponentState } from '@/object-record/object-sort-dropdown/states/selectedRecordSortDirectionComponentState';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort';
|
||||
import {
|
||||
RECORD_SORT_DIRECTIONS,
|
||||
RecordSortDirection,
|
||||
@ -159,12 +159,12 @@ export const ObjectSortDropdownButton = ({
|
||||
|
||||
const { closeSortDropdown } = useCloseSortDropdown();
|
||||
|
||||
const onSortSelect = useRecoilComponentValueV2(onSortSelectComponentState);
|
||||
const { upsertRecordSort } = useUpsertRecordSort();
|
||||
|
||||
const handleAddSort = (fieldMetadataItem: FieldMetadataItem) => {
|
||||
setObjectSortDropdownSearchInput('');
|
||||
closeSortDropdown();
|
||||
onSortSelect?.({
|
||||
upsertRecordSort({
|
||||
id: v4(),
|
||||
fieldMetadataId: fieldMetadataItem.id,
|
||||
direction: selectedRecordSortDirection,
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const isRecordSortSelectedComponentState =
|
||||
createComponentStateV2<boolean>({
|
||||
key: 'isRecordSortSelectedComponentState',
|
||||
defaultValue: false,
|
||||
componentInstanceContext: ObjectSortDropdownComponentInstanceContext,
|
||||
});
|
||||
@ -1,11 +0,0 @@
|
||||
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
|
||||
import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const onSortSelectComponentState = createComponentStateV2<
|
||||
((sort: RecordSort) => void) | undefined
|
||||
>({
|
||||
key: 'onSortSelectComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: ObjectSortDropdownComponentInstanceContext,
|
||||
});
|
||||
@ -2,12 +2,11 @@ import { selectedFilterComponentState } from '@/object-record/object-filter-drop
|
||||
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
|
||||
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
|
||||
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const useApplyRecordFilter = (componentInstanceId?: string) => {
|
||||
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters();
|
||||
const selectedFilterCallbackState = useRecoilComponentCallbackStateV2(
|
||||
selectedFilterComponentState,
|
||||
componentInstanceId,
|
||||
@ -21,11 +20,10 @@ export const useApplyRecordFilter = (componentInstanceId?: string) => {
|
||||
set(selectedFilterCallbackState, filter);
|
||||
|
||||
if (isDefined(filter)) {
|
||||
upsertCombinedViewFilter(filter);
|
||||
upsertRecordFilter(filter);
|
||||
}
|
||||
},
|
||||
[selectedFilterCallbackState, upsertCombinedViewFilter, upsertRecordFilter],
|
||||
[selectedFilterCallbackState, upsertRecordFilter],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@ -51,7 +51,7 @@ export const RecordIndexBoardContainer = ({
|
||||
}}
|
||||
>
|
||||
<RecordBoard />
|
||||
<RecordIndexRemoveSortingModal recordIndexId={recordBoardId} />
|
||||
<RecordIndexRemoveSortingModal />
|
||||
</RecordBoardContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,33 +1,26 @@
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { useRemoveRecordSort } from '@/object-record/record-sort/hooks/useRemoveRecordSort';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useDeleteCombinedViewSorts } from '@/views/hooks/useDeleteCombinedViewSorts';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const RecordIndexRemoveSortingModal = ({
|
||||
recordIndexId,
|
||||
}: {
|
||||
recordIndexId: string;
|
||||
}) => {
|
||||
const { currentViewWithCombinedFiltersAndSorts } =
|
||||
useGetCurrentView(recordIndexId);
|
||||
export const RecordIndexRemoveSortingModal = () => {
|
||||
const currentRecordSorts = useRecoilComponentValueV2(
|
||||
currentRecordSortsComponentState,
|
||||
);
|
||||
|
||||
const viewSorts = currentViewWithCombinedFiltersAndSorts?.viewSorts || [];
|
||||
const fieldMetadataIds = viewSorts.map(
|
||||
const fieldMetadataIds = currentRecordSorts.map(
|
||||
(viewSort) => viewSort.fieldMetadataId,
|
||||
);
|
||||
const [isRemoveSortingModalOpen, setIsRemoveSortingModalOpen] =
|
||||
useRecoilState(isRemoveSortingModalOpenState);
|
||||
|
||||
const { deleteCombinedViewSort } = useDeleteCombinedViewSorts(recordIndexId);
|
||||
|
||||
const { removeRecordSort } = useRemoveRecordSort();
|
||||
|
||||
const handleRemoveClick = () => {
|
||||
fieldMetadataIds.forEach((id) => {
|
||||
deleteCombinedViewSort(id);
|
||||
removeRecordSort(id);
|
||||
});
|
||||
};
|
||||
|
||||
@ -34,7 +34,7 @@ export const RecordIndexTableContainer = ({
|
||||
viewBarId={viewBarId}
|
||||
updateRecordMutation={updateEntity}
|
||||
/>
|
||||
<RecordIndexRemoveSortingModal recordIndexId={recordTableId} />
|
||||
<RecordIndexRemoveSortingModal />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -9,7 +9,7 @@ import { useSetRecordIndexEntityCount } from '@/object-record/record-index/hooks
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
|
||||
import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { ViewField } from '@/views/types/ViewField';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
@ -48,10 +48,9 @@ export const RecordIndexTableContainerEffect = () => {
|
||||
|
||||
const handleToggleColumnSort = useHandleToggleColumnSort({
|
||||
objectNameSingular,
|
||||
viewBarId,
|
||||
});
|
||||
|
||||
const { currentViewWithSavedFiltersAndSorts } = useGetCurrentView();
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
|
||||
useEffect(() => {
|
||||
setOnToggleColumnFilter(
|
||||
@ -115,13 +114,10 @@ export const RecordIndexTableContainerEffect = () => {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
currentViewWithSavedFiltersAndSorts?.viewFields.forEach((viewField) => {
|
||||
currentView?.viewFields.forEach((viewField) => {
|
||||
setViewFieldAggregateOperation(viewField);
|
||||
});
|
||||
}, [
|
||||
currentViewWithSavedFiltersAndSorts?.viewFields,
|
||||
setViewFieldAggregateOperation,
|
||||
]);
|
||||
}, [currentView, setViewFieldAggregateOperation]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
@ -5,10 +5,9 @@ import { currentRecordFiltersComponentState } from '@/object-record/record-filte
|
||||
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { useCurrentRecordGroupDefinition } from '@/object-record/record-group/hooks/useCurrentRecordGroupDefinition';
|
||||
import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useRecordGroupFilter';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { tableViewFilterGroupsComponentState } from '@/object-record/record-table/states/tableViewFilterGroupsComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
|
||||
|
||||
export const useFindManyRecordIndexTableParams = (
|
||||
objectNameSingular: string,
|
||||
@ -29,12 +28,9 @@ export const useFindManyRecordIndexTableParams = (
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } =
|
||||
useGetCurrentView(recordTableId);
|
||||
|
||||
const viewSorts = currentViewWithCombinedFiltersAndSorts?.viewSorts ?? [];
|
||||
|
||||
const sorts = mapViewSortsToSorts(viewSorts);
|
||||
const currentRecordSorts = useRecoilComponentValueV2(
|
||||
currentRecordSortsComponentState,
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
@ -49,7 +45,7 @@ export const useFindManyRecordIndexTableParams = (
|
||||
tableViewFilterGroups,
|
||||
);
|
||||
|
||||
const orderBy = turnSortsIntoOrderBy(objectMetadataItem, sorts);
|
||||
const orderBy = turnSortsIntoOrderBy(objectMetadataItem, currentRecordSorts);
|
||||
|
||||
return {
|
||||
objectNameSingular,
|
||||
|
||||
@ -9,14 +9,14 @@ import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldM
|
||||
|
||||
import { useSelectFilterUsedInDropdown } from '@/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown';
|
||||
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||
import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
|
||||
import { useRecoilCallback, useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
@ -36,7 +36,6 @@ export const useHandleToggleColumnFilter = ({
|
||||
const { columnDefinitions } =
|
||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||
|
||||
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(viewBarId);
|
||||
const { upsertRecordFilter } = useUpsertRecordFilter();
|
||||
|
||||
const { setActiveDropdownFocusIdAndMemorizePrevious } =
|
||||
@ -70,11 +69,13 @@ export const useHandleToggleColumnFilter = ({
|
||||
}),
|
||||
);
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||
|
||||
const { selectFilterUsedInDropdown } =
|
||||
useSelectFilterUsedInDropdown(viewBarId);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const handleToggleColumnFilter = useCallback(
|
||||
async (fieldMetadataId: string) => {
|
||||
const correspondingColumnDefinition = columnDefinitions.find(
|
||||
@ -86,12 +87,11 @@ export const useHandleToggleColumnFilter = ({
|
||||
|
||||
const newFilterId = v4();
|
||||
|
||||
const existingViewFilter =
|
||||
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
||||
(viewFilter) => viewFilter.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
const existingRecordFilter = currentRecordFilters.find(
|
||||
(recordFilter) => recordFilter.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
|
||||
if (!existingViewFilter) {
|
||||
if (!isDefined(existingRecordFilter)) {
|
||||
const fieldMetadataItem = availableFieldMetadataItemsForFilter.find(
|
||||
(fieldMetadataItemToFind) =>
|
||||
fieldMetadataItemToFind.id === fieldMetadataId,
|
||||
@ -121,19 +121,16 @@ export const useHandleToggleColumnFilter = ({
|
||||
|
||||
upsertRecordFilter(newFilter);
|
||||
|
||||
await upsertCombinedViewFilter(newFilter);
|
||||
|
||||
selectFilterUsedInDropdown({ fieldMetadataItemId: fieldMetadataId });
|
||||
}
|
||||
|
||||
openDropdown(existingViewFilter?.id ?? newFilterId);
|
||||
openDropdown(existingRecordFilter?.id ?? newFilterId);
|
||||
},
|
||||
[
|
||||
openDropdown,
|
||||
columnDefinitions,
|
||||
upsertCombinedViewFilter,
|
||||
selectFilterUsedInDropdown,
|
||||
currentViewWithCombinedFiltersAndSorts,
|
||||
currentRecordFilters,
|
||||
availableFieldMetadataItemsForFilter,
|
||||
upsertRecordFilter,
|
||||
],
|
||||
|
||||
@ -4,17 +4,14 @@ import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/u
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort';
|
||||
import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
|
||||
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
type UseHandleToggleColumnSortProps = {
|
||||
objectNameSingular: string;
|
||||
viewBarId: string;
|
||||
};
|
||||
|
||||
export const useHandleToggleColumnSort = ({
|
||||
viewBarId,
|
||||
objectNameSingular,
|
||||
}: UseHandleToggleColumnSortProps) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
@ -24,8 +21,6 @@ export const useHandleToggleColumnSort = ({
|
||||
const { columnDefinitions } =
|
||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||
|
||||
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts(viewBarId);
|
||||
|
||||
const { upsertRecordSort } = useUpsertRecordSort();
|
||||
|
||||
const handleToggleColumnSort = useCallback(
|
||||
@ -44,10 +39,8 @@ export const useHandleToggleColumnSort = ({
|
||||
};
|
||||
|
||||
upsertRecordSort(newSort);
|
||||
|
||||
await upsertCombinedViewSort(newSort);
|
||||
},
|
||||
[columnDefinitions, upsertCombinedViewSort, upsertRecordSort],
|
||||
[columnDefinitions, upsertRecordSort],
|
||||
);
|
||||
|
||||
return handleToggleColumnSort;
|
||||
|
||||
@ -8,7 +8,7 @@ import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUp
|
||||
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
|
||||
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
@ -29,8 +29,6 @@ export const useHandleToggleTrashColumnFilter = ({
|
||||
const { columnDefinitions } =
|
||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||
|
||||
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(viewBarId);
|
||||
|
||||
const isSoftDeleteFilterActiveComponentRecoilState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
isSoftDeleteFilterActiveComponentState,
|
||||
@ -68,13 +66,7 @@ export const useHandleToggleTrashColumnFilter = ({
|
||||
};
|
||||
|
||||
upsertRecordFilter(newFilter);
|
||||
upsertCombinedViewFilter(newFilter);
|
||||
}, [
|
||||
columnDefinitions,
|
||||
objectMetadataItem,
|
||||
upsertCombinedViewFilter,
|
||||
upsertRecordFilter,
|
||||
]);
|
||||
}, [columnDefinitions, objectMetadataItem, upsertRecordFilter]);
|
||||
|
||||
const toggleSoftDeleteFilterState = useRecoilCallback(
|
||||
({ set }) =>
|
||||
|
||||
@ -8,16 +8,13 @@ import { useRecordTableContextOrThrow } from '@/object-record/record-table/conte
|
||||
import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay';
|
||||
import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const RecordTableEmptyStateSoftDelete = () => {
|
||||
const { objectMetadataItem, objectNameSingular, recordTableId } =
|
||||
useRecordTableContextOrThrow();
|
||||
|
||||
const { deleteCombinedViewFilter } =
|
||||
useDeleteCombinedViewFilters(recordTableId);
|
||||
|
||||
const tableFilters = useRecoilComponentValueV2(
|
||||
tableFiltersComponentState,
|
||||
recordTableId,
|
||||
@ -40,7 +37,6 @@ export const RecordTableEmptyStateSoftDelete = () => {
|
||||
}
|
||||
|
||||
removeRecordFilter(deletedFilter.fieldMetadataId);
|
||||
deleteCombinedViewFilter(deletedFilter.id);
|
||||
|
||||
toggleSoftDeleteFilterState(false);
|
||||
};
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { useAggregateRecords } from '@/object-record/hooks/useAggregateRecords';
|
||||
import { computeAggregateValueAndLabel } from '@/object-record/record-board/record-board-column/utils/computeAggregateValueAndLabel';
|
||||
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useRecordGroupFilter';
|
||||
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
|
||||
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
|
||||
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
@ -11,6 +11,7 @@ import { RecordTableColumnAggregateFooterCellContext } from '@/object-record/rec
|
||||
import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
|
||||
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
|
||||
import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { UserContext } from '@/users/contexts/UserContext';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
@ -26,13 +27,15 @@ export const useAggregateRecordsForRecordTableColumnFooter = (
|
||||
recordIndexViewFilterGroupsState,
|
||||
);
|
||||
|
||||
const recordIndexFilters = useRecoilValue(recordIndexFiltersState);
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const { filterValueDependencies } = useFilterValueDependencies();
|
||||
|
||||
const requestFilters = computeViewRecordGqlOperationFilter(
|
||||
filterValueDependencies,
|
||||
recordIndexFilters,
|
||||
currentRecordFilters,
|
||||
objectMetadataItem.fields,
|
||||
recordIndexViewFilterGroups,
|
||||
);
|
||||
|
||||
@ -3,7 +3,7 @@ import { viewFieldAggregateOperationState } from '@/object-record/record-table/r
|
||||
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
|
||||
import { convertExtendedAggregateOperationToAggregateOperation } from '@/object-record/utils/convertExtendedAggregateOperationToAggregateOperation';
|
||||
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
@ -11,12 +11,11 @@ export const useViewFieldAggregateOperation = () => {
|
||||
const { fieldMetadataId } = useContext(
|
||||
RecordTableColumnAggregateFooterDropdownContext,
|
||||
);
|
||||
const { currentViewWithSavedFiltersAndSorts } = useGetCurrentView();
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
|
||||
const currentViewField =
|
||||
currentViewWithSavedFiltersAndSorts?.viewFields?.find(
|
||||
(viewField) => viewField.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
const currentViewField = currentView?.viewFields?.find(
|
||||
(viewField) => viewField.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
const { updateViewFieldRecords } = usePersistViewFieldRecords();
|
||||
const updateViewFieldAggregateOperation = (
|
||||
aggregateOperation: ExtendedAggregateOperations | null,
|
||||
|
||||
@ -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 <></>;
|
||||
};
|
||||
@ -2,23 +2,26 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
||||
import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
|
||||
import { usePersistViewFilterGroupRecords } from '@/views/hooks/internal/usePersistViewFilterGroupRecords';
|
||||
import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords';
|
||||
import { usePersistViewGroupRecords } from '@/views/hooks/internal/usePersistViewGroupRecords';
|
||||
import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords';
|
||||
import { useGetViewFilterGroupsCombined } from '@/views/hooks/useGetCombinedViewFilterGroups';
|
||||
import { useGetViewFiltersCombined } from '@/views/hooks/useGetCombinedViewFilters';
|
||||
import { useGetViewSortsCombined } from '@/views/hooks/useGetCombinedViewSorts';
|
||||
import { isPersistingViewFieldsState } from '@/views/states/isPersistingViewFieldsState';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { View } from '@/views/types/View';
|
||||
import { ViewGroup } from '@/views/types/ViewGroup';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { mapRecordFilterToViewFilter } from '@/views/utils/mapRecordFilterToViewFilter';
|
||||
import { mapRecordSortToViewSort } from '@/views/utils/mapRecordSortToViewSort';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { v4 } from 'uuid';
|
||||
@ -36,9 +39,6 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
|
||||
const { createViewFieldRecords } = usePersistViewFieldRecords();
|
||||
|
||||
const { getViewSortsCombined } = useGetViewSortsCombined(viewBarComponentId);
|
||||
const { getViewFiltersCombined } =
|
||||
useGetViewFiltersCombined(viewBarComponentId);
|
||||
const { getViewFilterGroupsCombined } =
|
||||
useGetViewFilterGroupsCombined(viewBarComponentId);
|
||||
|
||||
@ -57,6 +57,14 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
|
||||
const currentRecordSorts = useRecoilComponentValueV2(
|
||||
currentRecordSortsComponentState,
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const createViewFromCurrentView = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (
|
||||
@ -160,13 +168,16 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
const sourceViewCombinedFilterGroups = getViewFilterGroupsCombined(
|
||||
sourceView.id,
|
||||
);
|
||||
const sourceViewCombinedFilters = getViewFiltersCombined(
|
||||
sourceView.id,
|
||||
);
|
||||
const sourceViewCombinedSorts = getViewSortsCombined(sourceView.id);
|
||||
|
||||
await createViewSortRecords(sourceViewCombinedSorts, newView);
|
||||
await createViewFilterRecords(sourceViewCombinedFilters, newView);
|
||||
const viewSortsToCreate = currentRecordSorts.map(
|
||||
mapRecordSortToViewSort,
|
||||
);
|
||||
const viewFiltersToCreate = currentRecordFilters.map(
|
||||
mapRecordFilterToViewFilter,
|
||||
);
|
||||
|
||||
await createViewSortRecords(viewSortsToCreate, newView);
|
||||
await createViewFilterRecords(viewFiltersToCreate, newView);
|
||||
await createViewFilterGroupRecords(
|
||||
sourceViewCombinedFilterGroups,
|
||||
newView,
|
||||
@ -182,13 +193,13 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
createViewFieldRecords,
|
||||
findManyRecords,
|
||||
objectMetadataItem.fields,
|
||||
createViewGroupRecords,
|
||||
getViewFilterGroupsCombined,
|
||||
getViewFiltersCombined,
|
||||
getViewSortsCombined,
|
||||
createViewGroupRecords,
|
||||
createViewSortRecords,
|
||||
createViewFilterRecords,
|
||||
createViewFilterGroupRecords,
|
||||
currentRecordFilters,
|
||||
currentRecordSorts,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@ -1,101 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => {
|
||||
const unsavedToUpsertViewFiltersCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
|
||||
|
||||
const deleteCombinedViewFilter = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (fieldId: string) => {
|
||||
const currentViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
currentViewIdCallbackState,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewFilterIdsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentView = await getViewFromPrefetchState(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingFilterInCurrentView = currentView.viewFilters.find(
|
||||
(viewFilter) => viewFilter.id === fieldId,
|
||||
);
|
||||
|
||||
const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find(
|
||||
(viewFilter) => viewFilter.id === fieldId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingFilterInUnsavedFilters)) {
|
||||
set(
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
unsavedToUpsertViewFilters.filter(
|
||||
(viewFilter) => viewFilter.id !== fieldId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (isDefined(matchingFilterInCurrentView)) {
|
||||
set(
|
||||
unsavedToDeleteViewFilterIdsCallbackState({
|
||||
viewId: currentViewId,
|
||||
}),
|
||||
[
|
||||
...new Set([
|
||||
...unsavedToDeleteViewFilterIds,
|
||||
matchingFilterInCurrentView.id,
|
||||
]),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
getViewFromPrefetchState,
|
||||
unsavedToDeleteViewFilterIdsCallbackState,
|
||||
unsavedToUpsertViewFiltersCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
deleteCombinedViewFilter,
|
||||
};
|
||||
};
|
||||
@ -1,99 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSortsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
|
||||
|
||||
const deleteCombinedViewSort = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (fieldMetadataId: string) => {
|
||||
const currentViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
currentViewIdCallbackState,
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unsavedToUpsertViewSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
const currentView = await getViewFromPrefetchState(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingSortInCurrentView = currentView.viewSorts.find(
|
||||
(viewSort) => viewSort.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
|
||||
const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find(
|
||||
(viewSort) => viewSort.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingSortInUnsavedSorts)) {
|
||||
set(
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
|
||||
unsavedToUpsertViewSorts.filter(
|
||||
(viewSort) => viewSort.fieldMetadataId !== fieldMetadataId,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(matchingSortInCurrentView)) {
|
||||
set(
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
|
||||
[
|
||||
...new Set([
|
||||
...unsavedToDeleteViewSortIds,
|
||||
matchingSortInCurrentView.id,
|
||||
]),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
getViewFromPrefetchState,
|
||||
unsavedToDeleteViewSortIdsCallbackState,
|
||||
unsavedToUpsertViewSortsCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
deleteCombinedViewSort,
|
||||
};
|
||||
};
|
||||
@ -1,68 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const useGetViewFiltersCombined = (viewBarComponentId?: string) => {
|
||||
const unsavedToUpsertViewFiltersCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const getViewFiltersCombined = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(viewId: string) => {
|
||||
const view = snapshot
|
||||
.getLoadable(
|
||||
prefetchViewFromViewIdFamilySelector({
|
||||
viewId,
|
||||
}),
|
||||
)
|
||||
.getValue();
|
||||
|
||||
if (!isDefined(view)) {
|
||||
throw new Error(
|
||||
`Cannot get view with id ${viewId}, because it cannot be found in client cache data.`,
|
||||
);
|
||||
}
|
||||
|
||||
const unsavedToUpsertViewFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: view.id }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewFilterIdsCallbackState({ viewId: view.id }),
|
||||
);
|
||||
|
||||
const combinedViewFilters = getCombinedViewFilters(
|
||||
view.viewFilters,
|
||||
unsavedToUpsertViewFilters,
|
||||
unsavedToDeleteViewFilterIds,
|
||||
);
|
||||
|
||||
return combinedViewFilters;
|
||||
},
|
||||
[
|
||||
unsavedToDeleteViewFilterIdsCallbackState,
|
||||
unsavedToUpsertViewFiltersCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
getViewFiltersCombined,
|
||||
};
|
||||
};
|
||||
@ -1,69 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
// TODO: fix naming
|
||||
export const useGetViewSortsCombined = (viewBarComponentId?: string) => {
|
||||
const unsavedToUpsertViewSortsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const getViewSortsCombined = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(viewId: string) => {
|
||||
const view = snapshot
|
||||
.getLoadable(
|
||||
prefetchViewFromViewIdFamilySelector({
|
||||
viewId,
|
||||
}),
|
||||
)
|
||||
.getValue();
|
||||
|
||||
if (!isDefined(view)) {
|
||||
throw new Error(
|
||||
`Cannot get view with id ${viewId}, because it cannot be found in client cache data.`,
|
||||
);
|
||||
}
|
||||
|
||||
const unsavedToUpsertViewSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: view.id }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId: view.id }),
|
||||
);
|
||||
|
||||
const combinedViewSorts = getCombinedViewSorts(
|
||||
view.viewSorts,
|
||||
unsavedToUpsertViewSorts,
|
||||
unsavedToDeleteViewSortIds,
|
||||
);
|
||||
|
||||
return combinedViewSorts;
|
||||
},
|
||||
[
|
||||
unsavedToDeleteViewSortIdsCallbackState,
|
||||
unsavedToUpsertViewSortsCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
getViewSortsCombined,
|
||||
};
|
||||
};
|
||||
@ -12,14 +12,8 @@ import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-sta
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState';
|
||||
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { getCombinedViewFilterGroups } from '@/views/utils/getCombinedViewFilterGroups';
|
||||
import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters';
|
||||
import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
@ -71,42 +65,18 @@ export const useGetCurrentView = (viewBarInstanceId?: string) => {
|
||||
}),
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilters = useRecoilComponentFamilyValueV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
{ viewId },
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilterGroups = useRecoilComponentFamilyValueV2(
|
||||
unsavedToUpsertViewFilterGroupsComponentFamilyState,
|
||||
{ viewId },
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSorts = useRecoilComponentFamilyValueV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
{ viewId },
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIds = useRecoilComponentFamilyValueV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
{ viewId },
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterGroupIds = useRecoilComponentFamilyValueV2(
|
||||
unsavedToDeleteViewFilterGroupIdsComponentFamilyState,
|
||||
{ viewId },
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIds = useRecoilComponentFamilyValueV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
{ viewId },
|
||||
instanceId,
|
||||
);
|
||||
|
||||
if (!isDefined(currentView)) {
|
||||
return {
|
||||
instanceId,
|
||||
@ -118,26 +88,15 @@ export const useGetCurrentView = (viewBarInstanceId?: string) => {
|
||||
|
||||
const currentViewWithCombinedFiltersAndSorts = {
|
||||
...currentView,
|
||||
viewFilters: getCombinedViewFilters(
|
||||
currentView.viewFilters,
|
||||
unsavedToUpsertViewFilters,
|
||||
unsavedToDeleteViewFilterIds,
|
||||
),
|
||||
viewFilterGroups: getCombinedViewFilterGroups(
|
||||
currentView.viewFilterGroups ?? [],
|
||||
unsavedToUpsertViewFilterGroups,
|
||||
unsavedToDeleteViewFilterGroupIds,
|
||||
),
|
||||
viewSorts: getCombinedViewSorts(
|
||||
currentView.viewSorts,
|
||||
unsavedToUpsertViewSorts,
|
||||
unsavedToDeleteViewSortIds,
|
||||
),
|
||||
};
|
||||
|
||||
return {
|
||||
instanceId,
|
||||
currentViewWithSavedFiltersAndSorts: currentView,
|
||||
currentViewWithCombinedFiltersAndSorts,
|
||||
viewsOnCurrentObject: viewsOnCurrentObject ?? [],
|
||||
currentViewId,
|
||||
|
||||
@ -1,43 +1,15 @@
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
export const useResetUnsavedViewStates = (viewBarInstanceId?: string) => {
|
||||
const setUnsavedToDeleteViewFilterIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const setUnsavedToDeleteViewSortIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterGroupIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterGroupIdsComponentFamilyState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const setUnsavedToUpsertViewFiltersCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSortsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilterGroupsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFilterGroupsComponentFamilyState,
|
||||
@ -48,18 +20,10 @@ export const useResetUnsavedViewStates = (viewBarInstanceId?: string) => {
|
||||
({ set }) =>
|
||||
(viewId: string) => {
|
||||
set(unsavedToDeleteViewFilterGroupIdsCallbackState({ viewId }), []);
|
||||
set(setUnsavedToDeleteViewFilterIdsCallbackState({ viewId }), []);
|
||||
set(setUnsavedToDeleteViewSortIdsCallbackState({ viewId }), []);
|
||||
set(unsavedToUpsertViewFilterGroupsCallbackState({ viewId }), []);
|
||||
set(setUnsavedToUpsertViewFiltersCallbackState({ viewId }), []);
|
||||
set(unsavedToUpsertViewSortsCallbackState({ viewId }), []);
|
||||
},
|
||||
[
|
||||
unsavedToUpsertViewSortsCallbackState,
|
||||
setUnsavedToUpsertViewFiltersCallbackState,
|
||||
unsavedToUpsertViewFilterGroupsCallbackState,
|
||||
setUnsavedToDeleteViewSortIdsCallbackState,
|
||||
setUnsavedToDeleteViewFilterIdsCallbackState,
|
||||
unsavedToDeleteViewFilterGroupIdsCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
@ -1,132 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||
import { shouldReplaceFilter } from '@/views/utils/shouldReplaceFilter';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => {
|
||||
const unsavedToUpsertViewFiltersCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
|
||||
|
||||
const upsertCombinedViewFilter = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (upsertedFilter: RecordFilter) => {
|
||||
const currentViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
currentViewIdCallbackState,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewFilterIdsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentView = await getViewFromPrefetchState(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingFilterInCurrentView = currentView.viewFilters.find(
|
||||
(viewFilter) => shouldReplaceFilter(viewFilter, upsertedFilter),
|
||||
);
|
||||
|
||||
const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find(
|
||||
(viewFilter) => shouldReplaceFilter(viewFilter, upsertedFilter),
|
||||
);
|
||||
|
||||
if (isDefined(matchingFilterInUnsavedFilters)) {
|
||||
const updatedFilters = unsavedToUpsertViewFilters.map((viewFilter) =>
|
||||
shouldReplaceFilter(viewFilter, matchingFilterInUnsavedFilters)
|
||||
? { ...viewFilter, ...upsertedFilter, id: viewFilter.id }
|
||||
: viewFilter,
|
||||
);
|
||||
|
||||
set(
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
updatedFilters,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(matchingFilterInCurrentView)) {
|
||||
set(
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
[
|
||||
...unsavedToUpsertViewFilters,
|
||||
{
|
||||
...matchingFilterInCurrentView,
|
||||
...upsertedFilter,
|
||||
id: matchingFilterInCurrentView.id,
|
||||
},
|
||||
],
|
||||
);
|
||||
set(
|
||||
unsavedToDeleteViewFilterIdsCallbackState({
|
||||
viewId: currentViewId,
|
||||
}),
|
||||
unsavedToDeleteViewFilterIds.filter(
|
||||
(id) => id !== matchingFilterInCurrentView.id,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const newValue = [
|
||||
...unsavedToUpsertViewFilters,
|
||||
{
|
||||
...upsertedFilter,
|
||||
id: upsertedFilter.id,
|
||||
__typename: 'ViewFilter',
|
||||
} satisfies ViewFilter,
|
||||
] satisfies ViewFilter[];
|
||||
|
||||
set(
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
newValue,
|
||||
);
|
||||
},
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
getViewFromPrefetchState,
|
||||
unsavedToDeleteViewFilterIdsCallbackState,
|
||||
unsavedToUpsertViewFiltersCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
upsertCombinedViewFilter,
|
||||
};
|
||||
};
|
||||
@ -1,120 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { ViewSort } from '@/views/types/ViewSort';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSortsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
|
||||
|
||||
const upsertCombinedViewSort = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (upsertedSort: RecordSort) => {
|
||||
const currentViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
currentViewIdCallbackState,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentView = await getViewFromPrefetchState(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingSortInCurrentView = currentView.viewSorts.find(
|
||||
(viewSort) =>
|
||||
viewSort.fieldMetadataId === upsertedSort.fieldMetadataId,
|
||||
);
|
||||
|
||||
const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find(
|
||||
(viewSort) =>
|
||||
viewSort.fieldMetadataId === upsertedSort.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingSortInUnsavedSorts)) {
|
||||
const updatedSorts = unsavedToUpsertViewSorts.map((viewSort) =>
|
||||
viewSort.id === matchingSortInUnsavedSorts.id
|
||||
? { ...viewSort, ...upsertedSort }
|
||||
: viewSort,
|
||||
);
|
||||
|
||||
set(
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
|
||||
updatedSorts,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(matchingSortInCurrentView)) {
|
||||
set(
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
|
||||
[
|
||||
...unsavedToUpsertViewSorts,
|
||||
{ ...matchingSortInCurrentView, ...upsertedSort },
|
||||
],
|
||||
);
|
||||
set(
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
|
||||
unsavedToDeleteViewSortIds.filter(
|
||||
(id) => id !== matchingSortInCurrentView.id,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
set(unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }), [
|
||||
...unsavedToUpsertViewSorts,
|
||||
{
|
||||
...upsertedSort,
|
||||
__typename: 'ViewSort',
|
||||
} satisfies ViewSort,
|
||||
]);
|
||||
},
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
getViewFromPrefetchState,
|
||||
unsavedToDeleteViewSortIdsCallbackState,
|
||||
unsavedToUpsertViewSortsCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
upsertCombinedViewSort,
|
||||
};
|
||||
};
|
||||
@ -1,28 +0,0 @@
|
||||
import { createComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
|
||||
export const areViewSortsDifferentFromRecordSortsSelector =
|
||||
createComponentFamilySelectorV2<boolean, { viewId?: string }>({
|
||||
key: 'areViewSortsDifferentFromRecordSortsSelector',
|
||||
get:
|
||||
({ familyKey, instanceId }) =>
|
||||
({ get }) => {
|
||||
return (
|
||||
get(
|
||||
unsavedToUpsertViewSortsComponentFamilyState.atomFamily({
|
||||
familyKey,
|
||||
instanceId,
|
||||
}),
|
||||
).length > 0 ||
|
||||
get(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState.atomFamily({
|
||||
familyKey,
|
||||
instanceId,
|
||||
}),
|
||||
).length > 0
|
||||
);
|
||||
},
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,9 +0,0 @@
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const unsavedToDeleteViewFilterIdsComponentFamilyState =
|
||||
createComponentFamilyStateV2<string[], { viewId?: string }>({
|
||||
key: 'unsavedToDeleteViewFilterIdsComponentFamilyState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,9 +0,0 @@
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const unsavedToDeleteViewSortIdsComponentFamilyState =
|
||||
createComponentFamilyStateV2<string[], { viewId?: string }>({
|
||||
key: 'unsavedToDeleteViewSortIdsComponentFamilyState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,10 +0,0 @@
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||
|
||||
export const unsavedToUpsertViewFiltersComponentFamilyState =
|
||||
createComponentFamilyStateV2<ViewFilter[], { viewId?: string }>({
|
||||
key: 'unsavedToUpsertViewFiltersComponentFamilyState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,10 +0,0 @@
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { ViewSort } from '../types/ViewSort';
|
||||
|
||||
export const unsavedToUpsertViewSortsComponentFamilyState =
|
||||
createComponentFamilyStateV2<ViewSort[], { viewId?: string }>({
|
||||
key: 'unsavedToUpsertViewSortsComponentFamilyState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,112 +0,0 @@
|
||||
// Generate test for getCombinedViewFilters
|
||||
|
||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import { getCombinedViewFilters } from '../getCombinedViewFilters';
|
||||
|
||||
describe('getCombinedViewFilters', () => {
|
||||
it('should return expected combined view filters when additional filters are present', () => {
|
||||
const viewFilters: ViewFilter[] = [
|
||||
{
|
||||
__typename: 'ViewFilter',
|
||||
id: 'id',
|
||||
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
|
||||
value: 'testValue',
|
||||
displayValue: 'Test Display Value',
|
||||
operand: ViewFilterOperand.Is,
|
||||
},
|
||||
];
|
||||
const toUpsertViewFilters: ViewFilter[] = [
|
||||
{
|
||||
__typename: 'ViewFilter',
|
||||
id: 'id',
|
||||
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
|
||||
value: 'testValue',
|
||||
displayValue: 'Test Display Value',
|
||||
operand: ViewFilterOperand.Is,
|
||||
},
|
||||
];
|
||||
const toDeleteViewFilterIds: string[] = [];
|
||||
|
||||
expect(
|
||||
getCombinedViewFilters(
|
||||
viewFilters,
|
||||
toUpsertViewFilters,
|
||||
toDeleteViewFilterIds,
|
||||
),
|
||||
).toEqual([
|
||||
{
|
||||
__typename: 'ViewFilter',
|
||||
id: 'id',
|
||||
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
|
||||
value: 'testValue',
|
||||
displayValue: 'Test Display Value',
|
||||
operand: ViewFilterOperand.Is,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return expected combined view filters when additional filters are not present', () => {
|
||||
const viewFilters: ViewFilter[] = [
|
||||
{
|
||||
__typename: 'ViewFilter',
|
||||
id: 'id',
|
||||
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
|
||||
value: 'testValue',
|
||||
displayValue: 'Test Display Value',
|
||||
operand: ViewFilterOperand.Is,
|
||||
},
|
||||
];
|
||||
const toUpsertViewFilters: ViewFilter[] = [];
|
||||
const toDeleteViewFilterIds: string[] = [];
|
||||
|
||||
expect(
|
||||
getCombinedViewFilters(
|
||||
viewFilters,
|
||||
toUpsertViewFilters,
|
||||
toDeleteViewFilterIds,
|
||||
),
|
||||
).toEqual([
|
||||
{
|
||||
__typename: 'ViewFilter',
|
||||
id: 'id',
|
||||
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
|
||||
value: 'testValue',
|
||||
displayValue: 'Test Display Value',
|
||||
operand: ViewFilterOperand.Is,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return expected combined view filters when additional filters are present and some filters are to be deleted', () => {
|
||||
const viewFilters: ViewFilter[] = [
|
||||
{
|
||||
__typename: 'ViewFilter',
|
||||
id: 'id',
|
||||
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
|
||||
value: 'testValue',
|
||||
displayValue: 'Test Display Value',
|
||||
operand: ViewFilterOperand.Is,
|
||||
},
|
||||
];
|
||||
const toUpsertViewFilters: ViewFilter[] = [
|
||||
{
|
||||
__typename: 'ViewFilter',
|
||||
id: 'id',
|
||||
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
|
||||
value: 'testValue',
|
||||
displayValue: 'Test Display Value',
|
||||
operand: ViewFilterOperand.Is,
|
||||
},
|
||||
];
|
||||
const toDeleteViewFilterIds: string[] = ['id'];
|
||||
|
||||
expect(
|
||||
getCombinedViewFilters(
|
||||
viewFilters,
|
||||
toUpsertViewFilters,
|
||||
toDeleteViewFilterIds,
|
||||
),
|
||||
).toEqual([]);
|
||||
});
|
||||
});
|
||||
@ -1,33 +0,0 @@
|
||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||
|
||||
export const getCombinedViewFilters = (
|
||||
viewFilters: ViewFilter[],
|
||||
toUpsertViewFilters: ViewFilter[],
|
||||
toDeleteViewFilterIds: string[],
|
||||
): ViewFilter[] => {
|
||||
const toCreateViewFilters = toUpsertViewFilters.filter(
|
||||
(toUpsertViewFilter) =>
|
||||
!viewFilters.some(
|
||||
(viewFilter) => viewFilter.id === toUpsertViewFilter.id,
|
||||
),
|
||||
);
|
||||
|
||||
const toUpdateViewFilters = toUpsertViewFilters.filter((toUpsertViewFilter) =>
|
||||
viewFilters.some((viewFilter) => viewFilter.id === toUpsertViewFilter.id),
|
||||
);
|
||||
|
||||
const combinedViewFilters = viewFilters
|
||||
.filter((viewFilter) => !toDeleteViewFilterIds.includes(viewFilter.id))
|
||||
.map((viewFilter) => {
|
||||
const toUpdateViewFilter = toUpdateViewFilters.find(
|
||||
(toUpdateViewFilter) => toUpdateViewFilter.id === viewFilter.id,
|
||||
);
|
||||
|
||||
return toUpdateViewFilter ?? viewFilter;
|
||||
})
|
||||
.concat(toCreateViewFilters);
|
||||
|
||||
return Object.values(
|
||||
combinedViewFilters.reduce((acc, obj) => ({ ...acc, [obj.id]: obj }), {}),
|
||||
);
|
||||
};
|
||||
@ -1,34 +0,0 @@
|
||||
import { ViewSort } from '@/views/types/ViewSort';
|
||||
|
||||
export const getCombinedViewSorts = (
|
||||
viewSort: ViewSort[],
|
||||
toUpsertViewSorts: ViewSort[],
|
||||
toDeleteViewSortIds: string[],
|
||||
): ViewSort[] => {
|
||||
const toCreateViewSorts = toUpsertViewSorts.filter(
|
||||
(toUpsertViewSort) =>
|
||||
!viewSort.some((viewSort) => viewSort.id === toUpsertViewSort.id),
|
||||
);
|
||||
|
||||
const toUpdateViewSorts = toUpsertViewSorts.filter((toUpsertViewSort) =>
|
||||
viewSort.some((viewSort) => viewSort.id === toUpsertViewSort.id),
|
||||
);
|
||||
|
||||
const combinedViewSorts = viewSort
|
||||
.filter((viewSort) => !toDeleteViewSortIds.includes(viewSort.id))
|
||||
.map((viewSort) => {
|
||||
const toUpdateViewSort = toUpdateViewSorts.find(
|
||||
(toUpdateViewSort) => toUpdateViewSort.id === viewSort.id,
|
||||
);
|
||||
|
||||
return toUpdateViewSort ?? viewSort;
|
||||
})
|
||||
.concat(toCreateViewSorts);
|
||||
|
||||
return Object.values(
|
||||
combinedViewSorts.reduce(
|
||||
(acc, obj) => ({ ...acc, [obj.fieldMetadataId]: obj }),
|
||||
{},
|
||||
),
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user