Implement different DTOs for users and admins (#644)

* Implement different DTOs for users and admins
* Fix performance by not creating unnecessary websocket connections
This commit is contained in:
Simon
2025-07-22 14:52:59 +02:00
committed by GitHub
parent 2e596bf7a3
commit 791ddf8ce2
39 changed files with 516 additions and 353 deletions
@@ -10,7 +10,7 @@ export default function SearchBar() {
const navigate = useNavigate();
const state = useSnapshot(gameState);
const games = state.recentlyUpdated as GameDto[];
const games = state.games as GameDto[];
return <Autocomplete
aria-label="Search for games"
@@ -1,5 +1,4 @@
import {Button, Card, Chip, Tooltip} from "@heroui/react";
import LibraryDto from "Frontend/generated/org/gameyfin/app/libraries/dto/LibraryDto";
import GameDto from "Frontend/generated/org/gameyfin/app/games/dto/GameDto";
import React from "react";
import {LibraryEndpoint} from "Frontend/generated/endpoints";
@@ -10,9 +9,10 @@ import {useNavigate} from "react-router";
import {useSnapshot} from "valtio/react";
import {gameState} from "Frontend/state/GameState";
import IconBackgroundPattern from "Frontend/components/general/IconBackgroundPattern";
import LibraryAdminDto from "Frontend/generated/org/gameyfin/app/libraries/dto/LibraryAdminDto";
interface LibraryOverviewCardProps {
library: LibraryDto;
library: LibraryAdminDto;
}
export function LibraryOverviewCard({library}: LibraryOverviewCardProps) {
@@ -28,7 +28,7 @@ export function LibraryOverviewCard({library}: LibraryOverviewCardProps) {
}
async function triggerScan(scanType: ScanType) {
await LibraryEndpoint.triggerScan(scanType, [library]);
await LibraryEndpoint.triggerScan(scanType, [library.id]);
}
return (
@@ -25,6 +25,7 @@ import GameUpdateDto from "Frontend/generated/org/gameyfin/app/games/dto/GameUpd
import {useMemo, useState} from "react";
import EditGameMetadataModal from "Frontend/components/general/modals/EditGameMetadataModal";
import MatchGameModal from "Frontend/components/general/modals/MatchGameModal";
import {GameAdminDto} from "Frontend/dtos/GameDtos";
interface LibraryManagementGamesProps {
library: LibraryDto;
@@ -34,12 +35,12 @@ export default function LibraryManagementGames({library}: LibraryManagementGames
const rowsPerPage = 25;
const state = useSnapshot(gameState);
const games = state.gamesByLibraryId[library.id] ? state.gamesByLibraryId[library.id] as GameDto[] : [];
const games = state.gamesByLibraryId[library.id] ? state.gamesByLibraryId[library.id] as GameAdminDto[] : [];
const [searchTerm, setSearchTerm] = useState("");
const [filter, setFilter] = useState<"all" | "confirmed" | "nonConfirmed">("all");
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({column: "title", direction: "ascending"});
const [selectedGame, setSelectedGame] = useState<GameDto>(games[0]);
const [selectedGame, setSelectedGame] = useState<GameAdminDto>(games[0]);
const editGameModal = useDisclosure();
const matchGameModal = useDisclosure();
@@ -53,7 +54,7 @@ export default function LibraryManagementGames({library}: LibraryManagementGames
}, [games, filter, searchTerm]);
const sortedItems = useMemo(() => {
return filteredItems.slice().sort((a, b) => {
return (filteredItems as GameAdminDto[]).slice().sort((a, b) => {
let cmp: number;
switch (sortDescriptor.column) {
@@ -86,7 +87,7 @@ export default function LibraryManagementGames({library}: LibraryManagementGames
function getFilteredGames() {
let filteredGames = games.filter((game) =>
let filteredGames = (games as GameAdminDto[]).filter((game) =>
game.metadata.path!!.toLowerCase().includes(searchTerm.toLowerCase()) ||
game.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
game.publishers?.some(publisher => publisher.toLowerCase().includes(searchTerm.toLowerCase())) ||
@@ -102,7 +103,7 @@ export default function LibraryManagementGames({library}: LibraryManagementGames
return filteredGames;
}
async function toggleMatchConfirmed(game: GameDto) {
async function toggleMatchConfirmed(game: GameAdminDto) {
await GameEndpoint.updateGame(
{
id: game.id,
@@ -163,13 +164,13 @@ export default function LibraryManagementGames({library}: LibraryManagementGames
<TableColumn width={1}>Actions</TableColumn>
</TableHeader>
<TableBody emptyContent="Your filter did not match any games." items={pagedItems}>
{(item) => (
{(item: GameAdminDto) => (
<TableRow key={item.id}>
<TableCell>
<Link href={`/game/${item.id}`}
color="foreground"
className="text-sm"
underline="hover">{item.title} ({item.release !== undefined ? new Date(item.release).getFullYear() : "unknown"})
underline="hover">{item.title} ({item.release ? new Date(item.release).getFullYear() : "unknown"})
</Link>
</TableCell>
<TableCell>
@@ -1,4 +1,3 @@
import LibraryDto from "Frontend/generated/org/gameyfin/app/libraries/dto/LibraryDto";
import {
Button,
Input,
@@ -19,9 +18,10 @@ import {useMemo, useState} from "react";
import LibraryUpdateDto from "Frontend/generated/org/gameyfin/app/libraries/dto/LibraryUpdateDto";
import {fileNameFromPath, hashCode} from "Frontend/util/utils";
import MatchGameModal from "Frontend/components/general/modals/MatchGameModal";
import LibraryAdminDto from "Frontend/generated/org/gameyfin/app/libraries/dto/LibraryAdminDto";
interface LibraryManagementUnmatchedPathsProps {
library: LibraryDto;
library: LibraryAdminDto;
}
export default function LibraryManagementUnmatchedPaths({library}: LibraryManagementUnmatchedPathsProps) {
@@ -6,6 +6,7 @@ import {LibraryEndpoint} from "Frontend/generated/endpoints";
import Input from "Frontend/components/general/input/Input";
import * as Yup from "yup";
import DirectoryMappingInput from "Frontend/components/general/input/DirectoryMappingInput";
import LibraryAdminDto from "Frontend/generated/org/gameyfin/app/libraries/dto/LibraryAdminDto";
interface LibraryCreationModalProps {
libraries: LibraryDto[];
@@ -23,7 +24,7 @@ export default function LibraryCreationModal({
const [scanAfterCreation, setScanAfterCreation] = useState<boolean>(true);
async function createLibrary(library: LibraryDto) {
await LibraryEndpoint.createLibrary(library as LibraryDto, scanAfterCreation);
await LibraryEndpoint.createLibrary(library as LibraryAdminDto, scanAfterCreation);
addToast({
title: "New library created",
@@ -15,7 +15,6 @@ export default function PluginIcon({
blurred = false,
showTooltip = true
}: PluginIconProps) {
const icon = plugin.hasLogo
?
<Image isBlurred={blurred} src={`/images/plugins/${plugin.id}/logo`} width={size} height={size} radius="none"/>