feat: add views dropdown (list, add & edit views) (#1220)

Closes #1218
This commit is contained in:
Thaïs
2023-08-15 21:08:02 +02:00
committed by GitHub
parent 7a330b4a02
commit 4e654654da
36 changed files with 1037 additions and 212 deletions

View File

@ -0,0 +1,9 @@
import { gql } from '@apollo/client';
export const CREATE_VIEWS = gql`
mutation CreateViews($data: [ViewCreateManyInput!]!) {
createManyView(data: $data) {
count
}
}
`;

View File

@ -0,0 +1,10 @@
import { gql } from '@apollo/client';
export const UPDATE_VIEW = gql`
mutation UpdateView($data: ViewUpdateInput!, $where: ViewWhereUniqueInput!) {
updateOneView(data: $data, where: $where) {
id
name
}
}
`;

View File

@ -0,0 +1,10 @@
import { gql } from '@apollo/client';
export const GET_VIEWS = gql`
query GetViews($where: ViewWhereInput) {
views: findManyView(where: $where) {
id
name
}
}
`;

View File

@ -7,11 +7,13 @@ import {
ViewFieldMetadata,
ViewFieldTextMetadata,
} from '@/ui/editable-field/types/ViewField';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import {
tableColumnsByIdState,
tableColumnsState,
} from '@/ui/table/states/tableColumnsState';
import { currentViewIdState } from '@/views/states/currentViewIdState';
import { currentTableViewIdState } from '@/ui/table/states/tableViewsState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import {
SortOrder,
useCreateViewFieldsMutation,
@ -45,7 +47,10 @@ export const useTableViewFields = ({
objectName: 'company' | 'person';
viewFieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[];
}) => {
const currentViewId = useRecoilValue(currentViewIdState);
const currentViewId = useRecoilScopedValue(
currentTableViewIdState,
TableRecoilScopeContext,
);
const setColumns = useSetRecoilState(tableColumnsState);
const columnsById = useRecoilValue(tableColumnsByIdState);

View File

@ -0,0 +1,109 @@
import { useCallback } from 'react';
import { getOperationName } from '@apollo/client/utilities';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import {
type TableView,
tableViewsByIdState,
tableViewsState,
} from '@/ui/table/states/tableViewsState';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import {
useCreateViewsMutation,
useGetViewsQuery,
useUpdateViewMutation,
ViewType,
} from '~/generated/graphql';
import { GET_VIEWS } from '../graphql/queries/getViews';
export const useTableViews = ({
objectId,
}: {
objectId: 'company' | 'person';
}) => {
const [, setViews] = useRecoilScopedState(
tableViewsState,
TableRecoilScopeContext,
);
const viewsById = useRecoilScopedValue(
tableViewsByIdState,
TableRecoilScopeContext,
);
const [createViewsMutation] = useCreateViewsMutation();
const [updateViewMutation] = useUpdateViewMutation();
const createViews = useCallback(
(views: TableView[]) => {
if (!views.length) return;
return createViewsMutation({
variables: {
data: views.map((view) => ({
...view,
objectId,
type: ViewType.Table,
})),
},
refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
});
},
[createViewsMutation, objectId],
);
const updateViewFields = useCallback(
(views: TableView[]) => {
if (!views.length) return;
return Promise.all(
views.map((view) =>
updateViewMutation({
variables: {
data: { name: view.name },
where: { id: view.id },
},
refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
}),
),
);
},
[updateViewMutation],
);
useGetViewsQuery({
variables: {
where: {
objectId: { equals: objectId },
},
},
onCompleted: (data) => {
setViews(
data.views.map((view) => ({
id: view.id,
name: view.name,
})),
);
},
});
const handleViewsChange = useCallback(
async (nextViews: TableView[]) => {
const viewsToCreate = nextViews.filter(
(nextView) => !viewsById[nextView.id],
);
await createViews(viewsToCreate);
const viewsToUpdate = nextViews.filter(
(nextView) =>
viewsById[nextView.id] &&
viewsById[nextView.id].name !== nextView.name,
);
await updateViewFields(viewsToUpdate);
},
[createViews, updateViewFields, viewsById],
);
return { handleViewsChange };
};

View File

@ -1,6 +1,5 @@
import { Context, useCallback } from 'react';
import { useCallback, useEffect } from 'react';
import { getOperationName } from '@apollo/client/utilities';
import { useRecoilValue } from 'recoil';
import {
sortsByKeyScopedState,
@ -10,9 +9,10 @@ import type {
SelectedSortType,
SortType,
} from '@/ui/filter-n-sort/types/interface';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { currentTableViewIdState } from '@/ui/table/states/tableViewsState';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { currentViewIdState } from '@/views/states/currentViewIdState';
import {
useCreateViewSortsMutation,
useDeleteViewSortsMutation,
@ -25,14 +25,25 @@ import { GET_VIEW_SORTS } from '../graphql/queries/getViewSorts';
export const useViewSorts = <SortField>({
availableSorts,
Context,
}: {
availableSorts: SortType<SortField>[];
Context?: Context<string | null>;
}) => {
const currentViewId = useRecoilValue(currentViewIdState);
const [, setSorts] = useRecoilScopedState(sortScopedState, Context);
const sortsByKey = useRecoilScopedValue(sortsByKeyScopedState, Context);
const currentViewId = useRecoilScopedValue(
currentTableViewIdState,
TableRecoilScopeContext,
);
const [, setSorts] = useRecoilScopedState(
sortScopedState,
TableRecoilScopeContext,
);
const sortsByKey = useRecoilScopedValue(
sortsByKeyScopedState,
TableRecoilScopeContext,
);
useEffect(() => {
if (!currentViewId) setSorts([]);
}, [currentViewId, setSorts]);
useGetViewSortsQuery({
skip: !currentViewId,
@ -44,11 +55,19 @@ export const useViewSorts = <SortField>({
onCompleted: (data) => {
setSorts(
data.viewSorts
.map((viewSort) => ({
...availableSorts.find((sort) => sort.key === viewSort.key),
label: viewSort.name,
order: viewSort.direction.toLowerCase(),
}))
.map((viewSort) => {
const availableSort = availableSorts.find(
(sort) => sort.key === viewSort.key,
);
return availableSort
? {
...availableSort,
label: viewSort.name,
order: viewSort.direction.toLowerCase(),
}
: undefined;
})
.filter((sort): sort is SelectedSortType<SortField> => !!sort),
);
},

View File

@ -1,6 +0,0 @@
import { atom } from 'recoil';
export const currentViewIdState = atom<string | undefined>({
key: 'currentViewIdState',
default: undefined,
});