Optimistically refresh categories on reordering
This commit is contained in:
@@ -61,8 +61,6 @@ import {
|
|||||||
FilterChangeInput,
|
FilterChangeInput,
|
||||||
GetAboutQuery,
|
GetAboutQuery,
|
||||||
GetAboutQueryVariables,
|
GetAboutQueryVariables,
|
||||||
GetExtensionsFetchMutation,
|
|
||||||
GetExtensionsFetchMutationVariables,
|
|
||||||
GetCategoriesQuery,
|
GetCategoriesQuery,
|
||||||
GetCategoriesQueryVariables,
|
GetCategoriesQueryVariables,
|
||||||
GetCategoryMangasQuery,
|
GetCategoryMangasQuery,
|
||||||
@@ -71,6 +69,8 @@ import {
|
|||||||
GetChapterPagesFetchMutationVariables,
|
GetChapterPagesFetchMutationVariables,
|
||||||
GetChaptersQuery,
|
GetChaptersQuery,
|
||||||
GetChaptersQueryVariables,
|
GetChaptersQueryVariables,
|
||||||
|
GetExtensionsFetchMutation,
|
||||||
|
GetExtensionsFetchMutationVariables,
|
||||||
GetExtensionsQuery,
|
GetExtensionsQuery,
|
||||||
GetExtensionsQueryVariables,
|
GetExtensionsQueryVariables,
|
||||||
GetGlobalMetadatasQuery,
|
GetGlobalMetadatasQuery,
|
||||||
@@ -1407,17 +1407,70 @@ export class RequestManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public reorderCategory(
|
public useReorderCategory(
|
||||||
id: number,
|
options?: MutationHookOptions<UpdateCategoryOrderMutation, UpdateCategoryOrderMutationVariables>,
|
||||||
position: number,
|
): AbortableApolloUseMutationResponse<UpdateCategoryOrderMutation, UpdateCategoryOrderMutationVariables> {
|
||||||
options?: MutationOptions<UpdateCategoryOrderMutation, UpdateCategoryOrderMutationVariables>,
|
const [mutate, result] = this.doRequest<UpdateCategoryOrderMutation, UpdateCategoryOrderMutationVariables>(
|
||||||
): AbortableApolloMutationResponse<UpdateCategoryOrderMutation> {
|
GQLMethod.USE_MUTATION,
|
||||||
return this.doRequest<UpdateCategoryOrderMutation, UpdateCategoryOrderMutationVariables>(
|
|
||||||
GQLMethod.MUTATION,
|
|
||||||
UPDATE_CATEGORY_ORDER,
|
UPDATE_CATEGORY_ORDER,
|
||||||
{ input: { id, position } },
|
undefined,
|
||||||
{ refetchQueries: [GET_CATEGORIES], ...options },
|
options,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const wrappedMutate = (mutateOptions: Parameters<typeof mutate>[0]) => {
|
||||||
|
const variables = mutateOptions?.variables?.input;
|
||||||
|
const cachedCategories = this.graphQLClient.client.readQuery<
|
||||||
|
GetCategoriesQuery,
|
||||||
|
GetCategoriesQueryVariables
|
||||||
|
>({
|
||||||
|
query: GET_CATEGORIES,
|
||||||
|
variables: { orderBy: CategoryOrderBy.Order },
|
||||||
|
})?.categories.nodes;
|
||||||
|
|
||||||
|
if (!variables) {
|
||||||
|
throw new Error('useReorderCategory: no variables passed');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cachedCategories) {
|
||||||
|
throw new Error('useReorderCategory: there are no cached results');
|
||||||
|
}
|
||||||
|
|
||||||
|
const movedIndex = cachedCategories.findIndex((category) => category.id === variables.id);
|
||||||
|
const newData = [...cachedCategories.map((category) => ({ ...category }))];
|
||||||
|
const [removed] = newData.splice(movedIndex, 1);
|
||||||
|
newData.splice(variables.position, 0, removed);
|
||||||
|
removed.order = variables.position;
|
||||||
|
newData[movedIndex].order = movedIndex;
|
||||||
|
|
||||||
|
return mutate({
|
||||||
|
update: (cache) => {
|
||||||
|
cache.updateQuery<GetCategoriesQuery, GetCategoriesQueryVariables>(
|
||||||
|
{
|
||||||
|
id: cache.identify({ __typename: 'CategoryNodeList' }),
|
||||||
|
query: GET_CATEGORIES,
|
||||||
|
variables: { orderBy: CategoryOrderBy.Order },
|
||||||
|
},
|
||||||
|
(data) => ({
|
||||||
|
...data!,
|
||||||
|
categories: {
|
||||||
|
...data!.categories,
|
||||||
|
nodes: newData,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
optimisticResponse: {
|
||||||
|
__typename: 'Mutation',
|
||||||
|
updateCategoryOrder: {
|
||||||
|
__typename: 'UpdateCategoryOrderPayload',
|
||||||
|
categories: newData,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...mutateOptions,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return [wrappedMutate, result];
|
||||||
}
|
}
|
||||||
|
|
||||||
public useGetCategoryMangas(
|
public useGetCategoryMangas(
|
||||||
|
|||||||
@@ -65,19 +65,17 @@ export default function Categories() {
|
|||||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||||
const [dialogName, setDialogName] = useState<string>('');
|
const [dialogName, setDialogName] = useState<string>('');
|
||||||
const [dialogDefault, setDialogDefault] = useState<boolean>(false);
|
const [dialogDefault, setDialogDefault] = useState<boolean>(false);
|
||||||
|
const [reorderCategory, { reset: revertReorder }] = requestManager.useReorderCategory();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
useSetDefaultBackTo('settings');
|
useSetDefaultBackTo('settings');
|
||||||
|
|
||||||
const categoryReorder = (list: TCategory[], from: number, to: number) => {
|
const categoryReorder = (list: TCategory[], from: number, to: number) => {
|
||||||
const reorderedCategory = list[from];
|
const reorderedCategory = list[from];
|
||||||
const newData = [...list];
|
|
||||||
const [removed] = newData.splice(from, 1);
|
|
||||||
newData.splice(to, 0, removed);
|
|
||||||
// TODO - update cache immediately
|
|
||||||
// mutate(categoriesEndpoint, newData, { revalidate: false });
|
|
||||||
|
|
||||||
requestManager.reorderCategory(reorderedCategory.id, to + 1);
|
reorderCategory({ variables: { input: { id: reorderedCategory.id, position: to + 1 } } }).catch(() =>
|
||||||
|
revertReorder(),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDragEnd = (result: DropResult) => {
|
const onDragEnd = (result: DropResult) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user