Update frontend after library deletion

This commit is contained in:
grimsi
2025-05-11 15:42:01 +02:00
parent 8adfd4b444
commit 0bf1d68d9f
3 changed files with 82 additions and 42 deletions
@@ -3,7 +3,7 @@ import ConfigFormField from "Frontend/components/administration/ConfigFormField"
import withConfigPage from "Frontend/components/administration/withConfigPage";
import Section from "Frontend/components/general/Section";
import * as Yup from 'yup';
import {Button, Divider, Tooltip, useDisclosure} from "@heroui/react";
import {addToast, Button, Divider, Tooltip, useDisclosure} from "@heroui/react";
import {Plus} from "@phosphor-icons/react";
import {LibraryEndpoint} from "Frontend/generated/endpoints";
import {LibraryOverviewCard} from "Frontend/components/general/cards/LibraryOverviewCard";
@@ -41,6 +41,24 @@ function LibraryManagementLayout({getConfig, formik}: any) {
}
return [...prevLibraries, updatedLibrary];
});
addToast({
title: "Library updated",
description: `Library ${library.name} has been updated.`,
color: "success"
})
}
async function removeLibrary(library: LibraryDto) {
await LibraryEndpoint.removeLibrary(library.id);
setLibraries((prevLibraries) => {
return prevLibraries.filter((l) => l.id !== library.id);
});
addToast({
title: "Library removed",
description: `Library ${library.name} has been removed.`,
color: "success"
})
}
return (
@@ -72,7 +90,8 @@ function LibraryManagementLayout({getConfig, formik}: any) {
// Aspect ratio of cover = 12/17 -> 5 covers = 60/17 -> 353px * 100px
<div id="library-cards" className="grid gap-4 grid-cols-[repeat(auto-fill,minmax(353px,1fr))]">
{libraries.map((library) =>
<LibraryOverviewCard library={library} updateLibrary={updateLibrary} key={library.name}/>
<LibraryOverviewCard library={library} updateLibrary={updateLibrary}
removeLibrary={removeLibrary} key={library.name}/>
)}
</div> :
"No libraries configured. Add your first library!"
@@ -25,9 +25,10 @@ import LibraryUpdateDto from "Frontend/generated/de/grimsi/gameyfin/libraries/dt
import ScanType from "Frontend/generated/de/grimsi/gameyfin/libraries/enums/ScanType";
import {randomGamesFromLibrary} from "Frontend/util/utils";
export function LibraryOverviewCard({library, updateLibrary}: {
export function LibraryOverviewCard({library, updateLibrary, removeLibrary}: {
library: LibraryDto,
updateLibrary: (library: LibraryUpdateDto) => void
updateLibrary: (library: LibraryUpdateDto) => Promise<void>,
removeLibrary: (library: LibraryDto) => Promise<void>
}) {
const MAX_COVER_COUNT = 5;
@@ -103,6 +104,7 @@ export function LibraryOverviewCard({library, updateLibrary}: {
isOpen={libraryDetailsModal.isOpen}
onOpenChange={libraryDetailsModal.onOpenChange}
updateLibrary={updateLibrary}
removeLibrary={removeLibrary}
/>
</>
);
@@ -2,56 +2,75 @@ import React from "react";
import {Button, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader} from "@heroui/react";
import {Form, Formik} from "formik";
import Input from "Frontend/components/general/input/Input";
import {LibraryEndpoint} from "Frontend/generated/endpoints";
import LibraryUpdateDto from "Frontend/generated/de/grimsi/gameyfin/libraries/dto/LibraryUpdateDto";
import LibraryDto from "Frontend/generated/de/grimsi/gameyfin/libraries/dto/LibraryDto";
import Section from "Frontend/components/general/Section";
interface LibraryDetailsModalProps {
library: LibraryDto;
isOpen: boolean;
onOpenChange: () => void;
updateLibrary: (library: LibraryUpdateDto) => void;
updateLibrary: (library: LibraryUpdateDto) => Promise<void>;
removeLibrary: (library: LibraryDto) => Promise<void>;
}
export default function LibraryDetailsModal({library, isOpen, onOpenChange, updateLibrary}: LibraryDetailsModalProps) {
export default function LibraryDetailsModal({
library,
isOpen,
onOpenChange,
updateLibrary,
removeLibrary
}: LibraryDetailsModalProps) {
return (
<Modal isOpen={isOpen} onOpenChange={onOpenChange} backdrop="opaque" size="lg">
<ModalContent>
{(onClose) => (
<Formik initialValues={library}
enableReinitialize={true}
onSubmit={async (values: LibraryUpdateDto) => {
updateLibrary(values);
onClose();
}}
>
{(formik: { isSubmitting: any; }) => (
<Form>
<ModalHeader className="flex flex-col gap-1">
Edit library
</ModalHeader>
<ModalBody>
<Input key="name" name="name" label="Name"/>
<Button onPress={() => LibraryEndpoint.removeLibrary(library.id)}
color="danger">Delete</Button>
</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onClose}>
Cancel
</Button>
<Button
color="primary"
isLoading={formik.isSubmitting}
disabled={formik.isSubmitting}
type="submit"
>
{formik.isSubmitting ? "" : "Save"}
</Button>
</ModalFooter>
</Form>
)}
</Formik>
)}
{(onClose) => {
async function update(values: LibraryUpdateDto) {
await updateLibrary(values);
onClose();
}
async function remove(library: LibraryDto) {
await removeLibrary(library);
onClose();
}
return (
<Formik initialValues={library}
enableReinitialize={true}
onSubmit={(values) => update(values)}
>
{(formik: { isSubmitting: any; }) => (
<Form>
<ModalHeader className="flex flex-col gap-1">
Edit library
</ModalHeader>
<ModalBody>
<Input key="name" name="name" label="Name"/>
<Section title="Danger zone"/>
<Button onPress={() => remove(library)} color="danger">
Delete this library
</Button>
</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onClose}>
Cancel
</Button>
<Button
color="primary"
isLoading={formik.isSubmitting}
disabled={formik.isSubmitting}
type="submit"
>
{formik.isSubmitting ? "" : "Save"}
</Button>
</ModalFooter>
</Form>
)}
</Formik>
)
}}
</ModalContent>
</Modal>
);