Refactored record filter saving to view filters (#9844)
This PR refactors the record filter saving to view filters. Before we used states to track the change of view filters, now we just check if there's a difference between the current record filters and the current view filters before saving. We also use this check to show the reset and save buttons. CRUD operations to perform on view filters are computed by utils , and . Also added unit tests on those utils.
This commit is contained in:
@ -0,0 +1,46 @@
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { getViewFiltersToCreate } from '@/views/utils/getViewFiltersToCreate';
|
||||
import { getViewFiltersToDelete } from '@/views/utils/getViewFiltersToDelete';
|
||||
import { getViewFiltersToUpdate } from '@/views/utils/getViewFiltersToUpdate';
|
||||
import { mapRecordFilterToViewFilter } from '@/views/utils/mapRecordFilterToViewFilter';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useAreViewFiltersDifferentFromRecordFilters = () => {
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const viewFiltersAreDifferentFromRecordFilters = useMemo(() => {
|
||||
const currentViewFilters = currentView?.viewFilters ?? [];
|
||||
const viewFiltersFromCurrentRecordFilters = currentRecordFilters.map(
|
||||
mapRecordFilterToViewFilter,
|
||||
);
|
||||
|
||||
const viewFiltersToCreate = getViewFiltersToCreate(
|
||||
currentViewFilters,
|
||||
viewFiltersFromCurrentRecordFilters,
|
||||
);
|
||||
|
||||
const viewFiltersToDelete = getViewFiltersToDelete(
|
||||
currentViewFilters,
|
||||
viewFiltersFromCurrentRecordFilters,
|
||||
);
|
||||
|
||||
const viewFiltersToUpdate = getViewFiltersToUpdate(
|
||||
currentViewFilters,
|
||||
viewFiltersFromCurrentRecordFilters,
|
||||
);
|
||||
|
||||
const filtersHaveChanged =
|
||||
viewFiltersToCreate.length > 0 ||
|
||||
viewFiltersToDelete.length > 0 ||
|
||||
viewFiltersToUpdate.length > 0;
|
||||
|
||||
return filtersHaveChanged;
|
||||
}, [currentRecordFilters, currentView]);
|
||||
|
||||
return { viewFiltersAreDifferentFromRecordFilters };
|
||||
};
|
||||
@ -0,0 +1,14 @@
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { areViewSortsDifferentFromRecordSortsSelector } from '@/views/states/selectors/areViewSortsDifferentFromRecordSortsFamilySelector';
|
||||
|
||||
export const useAreViewSortsDifferentFromRecordSorts = () => {
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
|
||||
const viewSortsAreDifferentFromRecordSorts = useRecoilComponentFamilyValueV2(
|
||||
areViewSortsDifferentFromRecordSortsSelector,
|
||||
{ viewId: currentView?.id },
|
||||
);
|
||||
|
||||
return { viewSortsAreDifferentFromRecordSorts };
|
||||
};
|
||||
@ -0,0 +1,22 @@
|
||||
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { View } from '@/views/types/View';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useGetCurrentViewOnly = () => {
|
||||
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
||||
|
||||
const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
|
||||
|
||||
const currentView = useMemo(
|
||||
() => views.find((view) => view.id === currentViewId),
|
||||
[views, currentViewId],
|
||||
);
|
||||
|
||||
return {
|
||||
currentView,
|
||||
};
|
||||
};
|
||||
@ -3,16 +3,14 @@ import { useRecoilCallback } from 'recoil';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { usePersistViewFilterGroupRecords } from '@/views/hooks/internal/usePersistViewFilterGroupRecords';
|
||||
import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords';
|
||||
import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
|
||||
import { useSaveRecordFiltersToViewFilters } from '@/views/hooks/useSaveRecordFiltersToViewFilters';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
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 { isDefined } from '~/utils/isDefined';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
@ -39,18 +37,6 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFiltersCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilterGroupsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFilterGroupsComponentFamilyState,
|
||||
@ -69,12 +55,6 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
deleteViewSortRecords,
|
||||
} = usePersistViewSortRecords();
|
||||
|
||||
const {
|
||||
createViewFilterRecords,
|
||||
updateViewFilterRecords,
|
||||
deleteViewFilterRecords,
|
||||
} = usePersistViewFilterRecords();
|
||||
|
||||
const {
|
||||
createViewFilterGroupRecords,
|
||||
deleteViewFilterGroupRecords,
|
||||
@ -130,53 +110,6 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
],
|
||||
);
|
||||
|
||||
const saveViewFilters = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (viewId: string) => {
|
||||
const unsavedToDeleteViewFilterIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewFilterIdsCallbackState({ viewId }),
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId }),
|
||||
);
|
||||
|
||||
const view = await getViewFromCache(viewId);
|
||||
|
||||
if (isUndefinedOrNull(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const viewFiltersToCreate = unsavedToUpsertViewFilters.filter(
|
||||
(viewFilter) =>
|
||||
!view.viewFilters.some(
|
||||
(viewFilterToFilter) => viewFilterToFilter.id === viewFilter.id,
|
||||
),
|
||||
);
|
||||
|
||||
const viewFiltersToUpdate = unsavedToUpsertViewFilters.filter(
|
||||
(viewFilter) =>
|
||||
view.viewFilters.some(
|
||||
(viewFilterToFilter) => viewFilterToFilter.id === viewFilter.id,
|
||||
),
|
||||
);
|
||||
|
||||
await createViewFilterRecords(viewFiltersToCreate, view);
|
||||
await updateViewFilterRecords(viewFiltersToUpdate);
|
||||
await deleteViewFilterRecords(unsavedToDeleteViewFilterIds);
|
||||
},
|
||||
[
|
||||
createViewFilterRecords,
|
||||
deleteViewFilterRecords,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewFilterIdsCallbackState,
|
||||
unsavedToUpsertViewFiltersCallbackState,
|
||||
updateViewFilterRecords,
|
||||
],
|
||||
);
|
||||
|
||||
const saveViewFilterGroups = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (viewId: string) => {
|
||||
@ -226,6 +159,9 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
],
|
||||
);
|
||||
|
||||
const { saveRecordFiltersToViewFilters } =
|
||||
useSaveRecordFiltersToViewFilters();
|
||||
|
||||
const saveCurrentViewFilterAndSorts = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (viewIdFromProps?: string) => {
|
||||
@ -240,17 +176,18 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
const viewId = viewIdFromProps ?? currentViewId;
|
||||
|
||||
await saveViewFilterGroups(viewId);
|
||||
await saveViewFilters(viewId);
|
||||
await saveViewSorts(viewId);
|
||||
|
||||
await saveRecordFiltersToViewFilters();
|
||||
|
||||
resetUnsavedViewStates(viewId);
|
||||
},
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
resetUnsavedViewStates,
|
||||
saveViewFilters,
|
||||
saveViewSorts,
|
||||
saveViewFilterGroups,
|
||||
saveRecordFiltersToViewFilters,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@ -0,0 +1,79 @@
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { getViewFiltersToCreate } from '@/views/utils/getViewFiltersToCreate';
|
||||
import { getViewFiltersToDelete } from '@/views/utils/getViewFiltersToDelete';
|
||||
import { getViewFiltersToUpdate } from '@/views/utils/getViewFiltersToUpdate';
|
||||
import { mapRecordFilterToViewFilter } from '@/views/utils/mapRecordFilterToViewFilter';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
|
||||
export const useSaveRecordFiltersToViewFilters = () => {
|
||||
const {
|
||||
createViewFilterRecords,
|
||||
updateViewFilterRecords,
|
||||
deleteViewFilterRecords,
|
||||
} = usePersistViewFilterRecords();
|
||||
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
|
||||
const currentRecordFiltersCallbackState = useRecoilComponentCallbackStateV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const saveRecordFiltersToViewFilters = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async () => {
|
||||
if (!isDefined(currentView)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentViewFilters = currentView?.viewFilters ?? [];
|
||||
|
||||
const currentRecordFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
currentRecordFiltersCallbackState,
|
||||
);
|
||||
|
||||
const newViewFilters = currentRecordFilters.map(
|
||||
mapRecordFilterToViewFilter,
|
||||
);
|
||||
|
||||
const viewFiltersToCreate = getViewFiltersToCreate(
|
||||
currentViewFilters,
|
||||
newViewFilters,
|
||||
);
|
||||
|
||||
const viewFiltersToDelete = getViewFiltersToDelete(
|
||||
currentViewFilters,
|
||||
newViewFilters,
|
||||
);
|
||||
|
||||
const viewFiltersToUpdate = getViewFiltersToUpdate(
|
||||
currentViewFilters,
|
||||
newViewFilters,
|
||||
);
|
||||
|
||||
const viewFilterIdsToDelete = viewFiltersToDelete.map(
|
||||
(viewFilter) => viewFilter.id,
|
||||
);
|
||||
|
||||
await createViewFilterRecords(viewFiltersToCreate, currentView);
|
||||
await updateViewFilterRecords(viewFiltersToUpdate);
|
||||
await deleteViewFilterRecords(viewFilterIdsToDelete);
|
||||
},
|
||||
[
|
||||
createViewFilterRecords,
|
||||
deleteViewFilterRecords,
|
||||
updateViewFilterRecords,
|
||||
currentRecordFiltersCallbackState,
|
||||
currentView,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
saveRecordFiltersToViewFilters,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user