Files
twenty/front/src/modules/views/hooks/useViewSorts.ts
Lucas Bordeau 0a7a0ac6cb Refactor/context and scopes (#1602)
* Put onImport in a context

* Refactored RecoilScopeContexts

* Refactored naming

* Fix tests

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2023-09-15 12:51:46 -07:00

173 lines
5.0 KiB
TypeScript

import { useCallback } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { availableSortsScopedState } from '@/ui/view-bar/states/availableSortsScopedState';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { savedSortsFamilyState } from '@/ui/view-bar/states/savedSortsFamilyState';
import { savedSortsByKeyFamilySelector } from '@/ui/view-bar/states/selectors/savedSortsByKeyFamilySelector';
import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState';
import { Sort } from '@/ui/view-bar/types/Sort';
import {
useCreateViewSortsMutation,
useDeleteViewSortsMutation,
useGetViewSortsQuery,
useUpdateViewSortMutation,
ViewSortDirection,
} from '~/generated/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
export const useViewSorts = ({
RecoilScopeContext,
skipFetch,
}: {
RecoilScopeContext: RecoilScopeContext;
skipFetch?: boolean;
}) => {
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
RecoilScopeContext,
);
const [sorts, setSorts] = useRecoilScopedState(
sortsScopedState,
RecoilScopeContext,
);
const [availableSorts] = useRecoilScopedState(
availableSortsScopedState,
RecoilScopeContext,
);
const [, setSavedSorts] = useRecoilState(
savedSortsFamilyState(currentViewId),
);
const savedSortsByKey = useRecoilValue(
savedSortsByKeyFamilySelector(currentViewId),
);
const { refetch } = useGetViewSortsQuery({
skip: !currentViewId || skipFetch,
variables: {
where: {
viewId: { equals: currentViewId },
},
},
onCompleted: (data) => {
const nextSorts = data.viewSorts
.map((viewSort) => {
const foundCorrespondingSortDefinition = availableSorts.find(
(sort) => sort.key === viewSort.key,
);
if (foundCorrespondingSortDefinition) {
return {
key: viewSort.key,
definition: foundCorrespondingSortDefinition,
direction: viewSort.direction.toLowerCase(),
} as Sort;
} else {
return undefined;
}
})
.filter((sort): sort is Sort => !!sort);
if (!isDeeplyEqual(sorts, nextSorts)) {
setSavedSorts(nextSorts);
setSorts(nextSorts);
}
},
});
const [createViewSortsMutation] = useCreateViewSortsMutation();
const [updateViewSortMutation] = useUpdateViewSortMutation();
const [deleteViewSortsMutation] = useDeleteViewSortsMutation();
const createViewSorts = useCallback(
(sorts: Sort[], viewId = currentViewId) => {
if (!viewId || !sorts.length) return;
return createViewSortsMutation({
variables: {
data: sorts.map((sort) => ({
key: sort.key,
direction: sort.direction as ViewSortDirection,
name: sort.definition.label,
viewId,
})),
},
});
},
[createViewSortsMutation, currentViewId],
);
const updateViewSorts = useCallback(
(sorts: Sort[]) => {
if (!currentViewId || !sorts.length) return;
return Promise.all(
sorts.map((sort) =>
updateViewSortMutation({
variables: {
data: {
direction: sort.direction as ViewSortDirection,
},
where: {
viewId_key: { key: sort.key, viewId: currentViewId },
},
},
}),
),
);
},
[currentViewId, updateViewSortMutation],
);
const deleteViewSorts = useCallback(
(sortKeys: string[]) => {
if (!currentViewId || !sortKeys.length) return;
return deleteViewSortsMutation({
variables: {
where: {
key: { in: sortKeys },
viewId: { equals: currentViewId },
},
},
});
},
[currentViewId, deleteViewSortsMutation],
);
const persistSorts = useCallback(async () => {
if (!currentViewId) return;
const sortsToCreate = sorts.filter((sort) => !savedSortsByKey[sort.key]);
await createViewSorts(sortsToCreate);
const sortsToUpdate = sorts.filter(
(sort) =>
savedSortsByKey[sort.key] &&
savedSortsByKey[sort.key].direction !== sort.direction,
);
await updateViewSorts(sortsToUpdate);
const sortKeys = sorts.map((sort) => sort.key);
const sortKeysToDelete = Object.keys(savedSortsByKey).filter(
(previousSortKey) => !sortKeys.includes(previousSortKey),
);
await deleteViewSorts(sortKeysToDelete);
return refetch();
}, [
currentViewId,
sorts,
createViewSorts,
updateViewSorts,
savedSortsByKey,
deleteViewSorts,
refetch,
]);
return { createViewSorts, persistSorts };
};