Use gql for "categories"
This commit is contained in:
@@ -24,11 +24,11 @@ import DialogTitle from '@mui/material/DialogTitle';
|
||||
import Checkbox from '@mui/material/Checkbox';
|
||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ICategory } from '@/typings';
|
||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||
import StrictModeDroppable from '@/lib/StrictModeDroppable';
|
||||
import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab';
|
||||
import NavbarContext, { useSetDefaultBackTo } from '@/components/context/NavbarContext';
|
||||
import { CategoryType } from '@/lib/graphql/generated/graphql.ts';
|
||||
|
||||
const getItemStyle = (
|
||||
isDragging: boolean,
|
||||
@@ -52,13 +52,13 @@ export default function Categories() {
|
||||
setAction(null);
|
||||
}, [t]);
|
||||
|
||||
const { data, mutate } = requestManager.useGetCategories();
|
||||
const { data } = requestManager.useGetCategories();
|
||||
const categories = useMemo(() => {
|
||||
const res = [...(data ?? [])];
|
||||
const res = [...(data?.categories.nodes ?? [])];
|
||||
if (res.length > 0 && res[0].name === 'Default') {
|
||||
res.shift();
|
||||
}
|
||||
return res;
|
||||
return res as CategoryType[];
|
||||
}, [data]);
|
||||
|
||||
const [categoryToEdit, setCategoryToEdit] = useState<number>(-1); // -1 means new category
|
||||
@@ -69,13 +69,15 @@ export default function Categories() {
|
||||
|
||||
useSetDefaultBackTo('settings');
|
||||
|
||||
const categoryReorder = (list: ICategory[], from: number, to: number) => {
|
||||
const categoryReorder = (list: CategoryType[], from: number, to: number) => {
|
||||
const reorderedCategory = list[from];
|
||||
const newData = [...list];
|
||||
const [removed] = newData.splice(from, 1);
|
||||
newData.splice(to, 0, removed);
|
||||
mutate(newData, { revalidate: false });
|
||||
// TODO - update cache immediately
|
||||
// mutate(categoriesEndpoint, newData, { revalidate: false });
|
||||
|
||||
requestManager.reorderCategory(from + 1, to + 1).response.finally(() => mutate());
|
||||
requestManager.reorderCategory(reorderedCategory.id, to + 1);
|
||||
};
|
||||
|
||||
const onDragEnd = (result: DropResult) => {
|
||||
@@ -113,18 +115,16 @@ export default function Categories() {
|
||||
setDialogOpen(false);
|
||||
|
||||
if (categoryToEdit === -1) {
|
||||
requestManager.createCategory(dialogName).response.finally(() => mutate());
|
||||
requestManager.createCategory({ name: dialogName, default: dialogDefault });
|
||||
} else {
|
||||
const category = categories[categoryToEdit];
|
||||
requestManager
|
||||
.updateCategory(category.id, { name: dialogName, default: dialogDefault })
|
||||
.response.finally(() => mutate());
|
||||
requestManager.updateCategory(category.id, { name: dialogName, default: dialogDefault });
|
||||
}
|
||||
};
|
||||
|
||||
const deleteCategory = (index: number) => {
|
||||
const category = categories[index];
|
||||
requestManager.deleteCategory(category.id).response.finally(() => mutate());
|
||||
requestManager.deleteCategory(category.id);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -20,12 +20,12 @@ import DialogTitle from '@mui/material/DialogTitle';
|
||||
import { styled } from '@mui/material';
|
||||
import { t as translate } from 'i18next';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ICategory, IncludeInGlobalUpdate } from '@/typings';
|
||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
||||
import makeToast from '@/components/util/Toast';
|
||||
import ThreeStateCheckboxInput from '@/components/atoms/ThreeStateCheckboxInput';
|
||||
import NavbarContext, { useSetDefaultBackTo } from '@/components/context/NavbarContext';
|
||||
import SearchSettings from '@/screens/settings/SearchSettings';
|
||||
import { CategoryType, IncludeInUpdate } from '@/lib/graphql/generated/graphql.ts';
|
||||
|
||||
const CategoriesDiv = styled('div')({
|
||||
display: 'flex',
|
||||
@@ -34,16 +34,35 @@ const CategoriesDiv = styled('div')({
|
||||
overflow: 'auto',
|
||||
});
|
||||
|
||||
const includeInUpdateStatusToBoolean = (status: IncludeInGlobalUpdate) => {
|
||||
if (status === IncludeInGlobalUpdate.UNSET) {
|
||||
return null;
|
||||
const booleanToIncludeInStatus = (status: boolean | null | undefined): IncludeInUpdate => {
|
||||
switch (status) {
|
||||
case false:
|
||||
return IncludeInUpdate.Exclude;
|
||||
case true:
|
||||
return IncludeInUpdate.Include;
|
||||
case null:
|
||||
case undefined:
|
||||
return IncludeInUpdate.Unset;
|
||||
default:
|
||||
throw new Error(`booleanToIncludeInStatus: unexpected IncludeInUpdate status "${status}"`);
|
||||
}
|
||||
};
|
||||
|
||||
return !!status;
|
||||
const includeInUpdateStatusToBoolean = (status: IncludeInUpdate): boolean | null => {
|
||||
switch (status) {
|
||||
case IncludeInUpdate.Exclude:
|
||||
return false;
|
||||
case IncludeInUpdate.Include:
|
||||
return true;
|
||||
case IncludeInUpdate.Unset:
|
||||
return null;
|
||||
default:
|
||||
throw new Error(`includeInUpdateStatusToBoolean: unexpected IncludeInUpdate status "${status}"`);
|
||||
}
|
||||
};
|
||||
|
||||
const getCategoryUpdateInfo = (
|
||||
categories: ICategory[],
|
||||
categories: CategoryType[],
|
||||
areIncluded: boolean,
|
||||
unsetCategories: number,
|
||||
allCategories: number,
|
||||
@@ -80,20 +99,21 @@ export default function LibrarySettings() {
|
||||
|
||||
useSetDefaultBackTo('settings');
|
||||
|
||||
const { data: categories = [], error: requestError, mutate } = requestManager.useGetCategories();
|
||||
const [dialogCategories, setDialogCategories] = useState<ICategory[]>(categories);
|
||||
const { data, error: requestError } = requestManager.useGetCategories();
|
||||
const categories = (data?.categories.nodes ?? []) as CategoryType[];
|
||||
const [dialogCategories, setDialogCategories] = useState<CategoryType[]>(categories);
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setDialogCategories(categories);
|
||||
}, [categories]);
|
||||
|
||||
const unsetCategories: ICategory[] =
|
||||
categories?.filter((category) => category.includeInUpdate === IncludeInGlobalUpdate.UNSET) ?? [];
|
||||
const excludedCategories: ICategory[] =
|
||||
categories?.filter((category) => category.includeInUpdate === IncludeInGlobalUpdate.EXCLUDE) ?? [];
|
||||
const includedCategories: ICategory[] =
|
||||
categories?.filter((category) => category.includeInUpdate === IncludeInGlobalUpdate.INCLUDE) ?? [];
|
||||
const unsetCategories: CategoryType[] =
|
||||
categories?.filter((category) => category.includeInUpdate === IncludeInUpdate.Unset) ?? [];
|
||||
const excludedCategories: CategoryType[] =
|
||||
categories?.filter((category) => category.includeInUpdate === IncludeInUpdate.Exclude) ?? [];
|
||||
const includedCategories: CategoryType[] =
|
||||
categories?.filter((category) => category.includeInUpdate === IncludeInUpdate.Include) ?? [];
|
||||
const excludedCategoriesText = getCategoryUpdateInfo(
|
||||
excludedCategories,
|
||||
false,
|
||||
@@ -109,7 +129,7 @@ export default function LibrarySettings() {
|
||||
requestError,
|
||||
);
|
||||
|
||||
const updateCategory = (category: ICategory) =>
|
||||
const updateCategory = (category: CategoryType) =>
|
||||
requestManager.updateCategory(category.id, { includeInUpdate: category.includeInUpdate }).response;
|
||||
|
||||
const updateCategories = async () => {
|
||||
@@ -127,10 +147,11 @@ export default function LibrarySettings() {
|
||||
|
||||
try {
|
||||
await Promise.all(categoriesToUpdate.map((category) => updateCategory(category)));
|
||||
mutate([...dialogCategories], { revalidate: false });
|
||||
// TODO - update cache immediately
|
||||
// mutate(categoriesEndpoint, [...dialogCategories], { revalidate: false });
|
||||
} catch (error) {
|
||||
makeToast(t('global.error.label.failed_to_save_changes'), 'error');
|
||||
mutate([...categories]);
|
||||
// mutate(categoriesEndpoint, [...categories]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -192,13 +213,12 @@ export default function LibrarySettings() {
|
||||
label={category.name}
|
||||
checked={includeInUpdateStatusToBoolean(category.includeInUpdate)}
|
||||
onChange={(checked) => {
|
||||
const newIncludeState: IncludeInGlobalUpdate =
|
||||
checked == null ? IncludeInGlobalUpdate.UNSET : Number(checked);
|
||||
const newIncludeState = booleanToIncludeInStatus(checked);
|
||||
|
||||
const categoryIndex = dialogCategories.findIndex(
|
||||
(category_) => category_ === category,
|
||||
);
|
||||
const updatedDialogCategories: ICategory[] = [
|
||||
const updatedDialogCategories: CategoryType[] = [
|
||||
...dialogCategories.slice(0, categoryIndex),
|
||||
{
|
||||
...category,
|
||||
|
||||
Reference in New Issue
Block a user