Implements new record sort CRUD (#10448)
This PR implements new record sorts CRUD as already done on record filters, which is based on record sorts state instead of combined view sorts. It implements a new useSaveRecordSortsToViewSorts with its underlying utils, to compute diff between two view sorts array. The associated unit tests have also been written. This PR also fixes the bug where the view bar disappeared when deleting the already saved record sort of a view.
This commit is contained in:
@ -1,14 +1,46 @@
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { areViewSortsDifferentFromRecordSortsSelector } from '@/views/states/selectors/areViewSortsDifferentFromRecordSortsFamilySelector';
|
||||
import { getViewSortsToCreate } from '@/views/utils/getViewSortsToCreate';
|
||||
import { getViewSortsToDelete } from '@/views/utils/getViewSortsToDelete';
|
||||
import { getViewSortsToUpdate } from '@/views/utils/getViewSortsToUpdate';
|
||||
import { mapRecordSortToViewSort } from '@/views/utils/mapRecordSortToViewSort';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useAreViewSortsDifferentFromRecordSorts = () => {
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
|
||||
const viewSortsAreDifferentFromRecordSorts = useRecoilComponentFamilyValueV2(
|
||||
areViewSortsDifferentFromRecordSortsSelector,
|
||||
{ viewId: currentView?.id },
|
||||
const currentRecordSorts = useRecoilComponentValueV2(
|
||||
currentRecordSortsComponentState,
|
||||
);
|
||||
|
||||
const viewSortsAreDifferentFromRecordSorts = useMemo(() => {
|
||||
const currentViewSorts = currentView?.viewSorts ?? [];
|
||||
const viewSortsFromCurrentRecordSorts = currentRecordSorts.map(
|
||||
mapRecordSortToViewSort,
|
||||
);
|
||||
|
||||
const viewSortsToCreate = getViewSortsToCreate(
|
||||
currentViewSorts,
|
||||
viewSortsFromCurrentRecordSorts,
|
||||
);
|
||||
|
||||
const viewSortsToDelete = getViewSortsToDelete(
|
||||
currentViewSorts,
|
||||
viewSortsFromCurrentRecordSorts,
|
||||
);
|
||||
|
||||
const viewSortsToUpdate = getViewSortsToUpdate(
|
||||
currentViewSorts,
|
||||
viewSortsFromCurrentRecordSorts,
|
||||
);
|
||||
|
||||
const sortsHaveChanged =
|
||||
viewSortsToCreate.length > 0 ||
|
||||
viewSortsToDelete.length > 0 ||
|
||||
viewSortsToUpdate.length > 0;
|
||||
|
||||
return sortsHaveChanged;
|
||||
}, [currentRecordSorts, currentView]);
|
||||
|
||||
return { viewSortsAreDifferentFromRecordSorts };
|
||||
};
|
||||
|
||||
@ -4,14 +4,12 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/
|
||||
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 { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords';
|
||||
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
|
||||
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
|
||||
import { useSaveRecordFiltersToViewFilters } from '@/views/hooks/useSaveRecordFiltersToViewFilters';
|
||||
import { useSaveRecordSortsToViewSorts } from '@/views/hooks/useSaveRecordSortsToViewSorts';
|
||||
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
@ -25,18 +23,6 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSortsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilterGroupsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFilterGroupsComponentFamilyState,
|
||||
@ -49,12 +35,6 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const {
|
||||
createViewSortRecords,
|
||||
updateViewSortRecords,
|
||||
deleteViewSortRecords,
|
||||
} = usePersistViewSortRecords();
|
||||
|
||||
const {
|
||||
createViewFilterGroupRecords,
|
||||
deleteViewFilterGroupRecords,
|
||||
@ -64,52 +44,6 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
const { resetUnsavedViewStates } =
|
||||
useResetUnsavedViewStates(viewBarComponentId);
|
||||
|
||||
const saveViewSorts = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (viewId: string) => {
|
||||
const unsavedToDeleteViewSortIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId }),
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId }),
|
||||
);
|
||||
|
||||
const view = await getViewFromPrefetchState(viewId);
|
||||
|
||||
if (isUndefinedOrNull(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const viewSortsToCreate = unsavedToUpsertViewSorts.filter(
|
||||
(viewSort) =>
|
||||
!view.viewSorts.some(
|
||||
(vs) => vs.fieldMetadataId === viewSort.fieldMetadataId,
|
||||
),
|
||||
);
|
||||
|
||||
const viewSortsToUpdate = unsavedToUpsertViewSorts.filter((viewSort) =>
|
||||
view.viewSorts.some(
|
||||
(vs) => vs.fieldMetadataId === viewSort.fieldMetadataId,
|
||||
),
|
||||
);
|
||||
|
||||
await createViewSortRecords(viewSortsToCreate, view);
|
||||
await updateViewSortRecords(viewSortsToUpdate);
|
||||
await deleteViewSortRecords(unsavedToDeleteViewSortIds);
|
||||
},
|
||||
[
|
||||
createViewSortRecords,
|
||||
deleteViewSortRecords,
|
||||
getViewFromPrefetchState,
|
||||
unsavedToDeleteViewSortIdsCallbackState,
|
||||
unsavedToUpsertViewSortsCallbackState,
|
||||
updateViewSortRecords,
|
||||
],
|
||||
);
|
||||
|
||||
const saveViewFilterGroups = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (viewId: string) => {
|
||||
@ -162,6 +96,8 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
const { saveRecordFiltersToViewFilters } =
|
||||
useSaveRecordFiltersToViewFilters();
|
||||
|
||||
const { saveRecordSortsToViewSorts } = useSaveRecordSortsToViewSorts();
|
||||
|
||||
const saveCurrentViewFilterAndSorts = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (viewIdFromProps?: string) => {
|
||||
@ -176,8 +112,8 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
const viewId = viewIdFromProps ?? currentViewId;
|
||||
|
||||
await saveViewFilterGroups(viewId);
|
||||
await saveViewSorts(viewId);
|
||||
|
||||
await saveRecordSortsToViewSorts();
|
||||
await saveRecordFiltersToViewFilters();
|
||||
|
||||
resetUnsavedViewStates(viewId);
|
||||
@ -185,9 +121,9 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
resetUnsavedViewStates,
|
||||
saveViewSorts,
|
||||
saveViewFilterGroups,
|
||||
saveRecordFiltersToViewFilters,
|
||||
saveRecordSortsToViewSorts,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { getViewSortsToCreate } from '@/views/utils/getViewSortsToCreate';
|
||||
import { getViewSortsToDelete } from '@/views/utils/getViewSortsToDelete';
|
||||
import { getViewSortsToUpdate } from '@/views/utils/getViewSortsToUpdate';
|
||||
import { mapRecordSortToViewSort } from '@/views/utils/mapRecordSortToViewSort';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
export const useSaveRecordSortsToViewSorts = () => {
|
||||
const {
|
||||
createViewSortRecords,
|
||||
updateViewSortRecords,
|
||||
deleteViewSortRecords,
|
||||
} = usePersistViewSortRecords();
|
||||
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
|
||||
const currentRecordSortsCallbackState = useRecoilComponentCallbackStateV2(
|
||||
currentRecordSortsComponentState,
|
||||
);
|
||||
|
||||
const saveRecordSortsToViewSorts = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async () => {
|
||||
if (!isDefined(currentView)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentViewSorts = currentView?.viewSorts ?? [];
|
||||
|
||||
const currentRecordSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
currentRecordSortsCallbackState,
|
||||
);
|
||||
|
||||
const newViewSorts = currentRecordSorts.map(mapRecordSortToViewSort);
|
||||
|
||||
const viewSortsToCreate = getViewSortsToCreate(
|
||||
currentViewSorts,
|
||||
newViewSorts,
|
||||
);
|
||||
|
||||
const viewSortsToDelete = getViewSortsToDelete(
|
||||
currentViewSorts,
|
||||
newViewSorts,
|
||||
);
|
||||
|
||||
const viewSortsToUpdate = getViewSortsToUpdate(
|
||||
currentViewSorts,
|
||||
newViewSorts,
|
||||
);
|
||||
|
||||
const viewSortIdsToDelete = viewSortsToDelete.map(
|
||||
(viewSort) => viewSort.id,
|
||||
);
|
||||
|
||||
await createViewSortRecords(viewSortsToCreate, currentView);
|
||||
await updateViewSortRecords(viewSortsToUpdate);
|
||||
await deleteViewSortRecords(viewSortIdsToDelete);
|
||||
},
|
||||
[
|
||||
createViewSortRecords,
|
||||
deleteViewSortRecords,
|
||||
updateViewSortRecords,
|
||||
currentRecordSortsCallbackState,
|
||||
currentView,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
saveRecordSortsToViewSorts,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user