Compare commits

..

6 Commits

Author SHA1 Message Date
d6eeae4021 Add "/api" to default apiUriStr 2025-06-17 16:25:07 +02:00
6b05c4fb00 Fix MangaList Overflow, top-position 2025-06-17 15:40:25 +02:00
d785b6e078 Add ToolTip with Text-ReleaseStatus to Manga-Badge 2025-06-17 15:34:02 +02:00
e64f325022 Reorder Header items.
Center Logo
Move Settings/Jobs buttons to left side
2025-06-17 15:31:57 +02:00
486f6f60fb Add Links to useful ressources (GitHub, Swagger Doc) 2025-06-17 15:30:37 +02:00
01c732f6a8 Make header sticky to the top 2025-06-17 15:20:59 +02:00
7 changed files with 21 additions and 13 deletions

View File

@@ -8,8 +8,6 @@
.app-content { .app-content {
position: absolute; position: absolute;
height: calc(100% - 60px);
top: 60px;
width: 100%; width: 100%;
left: 0; left: 0;
} }

View File

@@ -25,7 +25,7 @@ export default function App () {
const [showJobs, setShowJobs] = useState<boolean>(false); const [showJobs, setShowJobs] = useState<boolean>(false);
const [apiConnected, setApiConnected] = useState<boolean>(false); const [apiConnected, setApiConnected] = useState<boolean>(false);
const apiUriStr = localStorage.getItem("apiUri") ?? window.location.href.substring(0, window.location.href.lastIndexOf("/")); const apiUriStr = localStorage.getItem("apiUri") ?? window.location.href.substring(0, window.location.href.lastIndexOf("/")) + "/api";
const [apiUri, setApiUri] = useState<string>(apiUriStr); const [apiUri, setApiUri] = useState<string>(apiUriStr);
const [mangas, setMangas] = useState<IManga[]>([]); const [mangas, setMangas] = useState<IManga[]>([]);

View File

@@ -1,4 +1,4 @@
import {Badge, Box, Card, CardContent, CardCover, Skeleton, Typography,} from "@mui/joy"; import {Badge, Box, Card, CardContent, CardCover, Skeleton, Tooltip, Typography,} from "@mui/joy";
import IManga from "../api/types/IManga.ts"; import IManga from "../api/types/IManga.ts";
import {CSSProperties, ReactElement, useCallback, useContext, useEffect, useRef, useState} from "react"; import {CSSProperties, ReactElement, useCallback, useContext, useEffect, useRef, useState} from "react";
import {GetMangaCoverImageUrl} from "../api/Manga.tsx"; import {GetMangaCoverImageUrl} from "../api/Manga.tsx";
@@ -31,7 +31,7 @@ export function MangaFromId({mangaId, children} : { mangaId: string, children?:
return ( return (
manga === undefined ? manga === undefined ?
<Badge sx={{margin:"8px !important"}} badgeContent={<Skeleton><img width={"24pt"} height={"24pt"} src={"/blahaj.png"} /></Skeleton>} color={ReleaseStatusToPalette(MangaReleaseStatus.Completed)} size={"lg"}> <Badge sx={{margin:"8px !important"}} badgeContent={<Skeleton><Tooltip title={"Loading"}><img width={"24pt"} height={"24pt"} src={"/blahaj.png"} /></Tooltip></Skeleton>} color={ReleaseStatusToPalette(MangaReleaseStatus.Completed)} size={"lg"}>
<Card sx={{height:"fit-content",width:"fit-content"}}> <Card sx={{height:"fit-content",width:"fit-content"}}>
<CardCover> <CardCover>
<img style={coverCss} src={"/blahaj.png"} alt="Manga Cover"/> <img style={coverCss} src={"/blahaj.png"} alt="Manga Cover"/>
@@ -87,7 +87,7 @@ export function Manga({manga: manga, children} : { manga: IManga, children?: Rea
const mangaName = manga.name.length > maxLength ? manga.name.substring(0, maxLength-3) + "..." : manga.name; const mangaName = manga.name.length > maxLength ? manga.name.substring(0, maxLength-3) + "..." : manga.name;
return ( return (
<Badge sx={{margin:"8px !important"}} badgeContent={mangaConnector ? <img width={"24pt"} height={"24pt"} src={mangaConnector.iconUrl} /> : manga.mangaConnectorName} color={ReleaseStatusToPalette(manga.releaseStatus)} size={"lg"}> <Badge sx={{margin:"8px !important"}} badgeContent={mangaConnector ? <Tooltip color={ReleaseStatusToPalette(manga.releaseStatus)} title={manga.releaseStatus}><img width={"24pt"} height={"24pt"} src={mangaConnector.iconUrl} /></Tooltip> : manga.mangaConnectorName} color={ReleaseStatusToPalette(manga.releaseStatus)} size={"lg"}>
<Card sx={{height:"fit-content",width:"fit-content"}} onClick={(e) => { <Card sx={{height:"fit-content",width:"fit-content"}} onClick={(e) => {
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
if(interactiveElements.find(x => x == target.localName) == undefined) if(interactiveElements.find(x => x == target.localName) == undefined)

View File

@@ -53,7 +53,7 @@ export default function MangaList({connected, setShowSearch}: {connected: boolea
} }
return( return(
<Stack direction="row" spacing={1} flexWrap={"wrap"}> <Stack direction="row" spacing={1} flexWrap={"wrap"} sx={{overflowX: 'hidden', overflowY: 'auto' /* Badge overflow */}} paddingTop={"6px" /* Badge overflow */}>
<Badge invisible sx={{margin: "8px !important"}}> <Badge invisible sx={{margin: "8px !important"}}>
<Card onClick={() => setShowSearch(true)} sx={{height:"fit-content",width:"fit-content"}}> <Card onClick={() => setShowSearch(true)} sx={{height:"fit-content",width:"fit-content"}}>
<CardCover sx={{margin:"var(--Card-padding)"}}> <CardCover sx={{margin:"var(--Card-padding)"}}>

View File

@@ -1,5 +1,6 @@
.header { .header {
position: static !important; position: sticky !important;
z-index: 1000;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;

View File

@@ -1,14 +1,17 @@
import Sheet from "@mui/joy/Sheet"; import Sheet from "@mui/joy/Sheet";
import {Box, Stack, Typography} from "@mui/joy"; import {Box, Link, Stack, Typography} from "@mui/joy";
import {ReactElement} from "react"; import {ReactElement} from "react";
import './Header.css'; import './Header.css';
import { GitHub } from "@mui/icons-material";
export default function Header({children} : {children? : ReactElement<any, any> | ReactElement<any,any>[] | undefined}) : ReactElement { export default function Header({children} : {children? : ReactElement<any, any> | ReactElement<any,any>[] | undefined}) : ReactElement {
return ( return (
<Sheet className={"header"}> <Sheet className={"header"}>
<Stack direction={"row"} spacing={2} sx={{width: "100%"}}> <Stack direction={"row"} spacing={2} sx={{width: "100%", alignItems: "center"}}>
<img src={"/blahaj.png"} style={{cursor: "grab"}}/> {children}
<Box sx={{flexGrow: 1}} />
<img src={"/blahaj.png"} style={{cursor: "grab", maxHeight: "100%"}}/>
<Typography level={"h2"} sx={{ <Typography level={"h2"} sx={{
background: "linear-gradient(110deg, var(--joy-palette-primary-solidBg), var(--joy-palette-success-400))", background: "linear-gradient(110deg, var(--joy-palette-primary-solidBg), var(--joy-palette-success-400))",
WebkitBackgroundClip: "text", WebkitBackgroundClip: "text",
@@ -17,7 +20,8 @@ export default function Header({children} : {children? : ReactElement<any, any>
cursor: "default" cursor: "default"
}}>Tranga</Typography> }}>Tranga</Typography>
<Box sx={{flexGrow: 1}} /> <Box sx={{flexGrow: 1}} />
{children} <Link href={"https://github.com/C9Glax/tranga"} color={"neutral"} height={"min-content"} ><GitHub /> Server</Link>
<Link href={"https://github.com/C9Glax/tranga-website"} color={"neutral"} height={"min-content"} ><GitHub /> Website</Link>
</Stack> </Stack>
</Sheet> </Sheet>
); );

View File

@@ -6,7 +6,8 @@ import {
AccordionGroup, AccordionGroup,
AccordionSummary, CircularProgress, ColorPaletteProp, AccordionSummary, CircularProgress, ColorPaletteProp,
DialogContent, DialogContent,
DialogTitle, Input DialogTitle, Input,
Link, Stack
} from "@mui/joy"; } from "@mui/joy";
import './Settings.css'; import './Settings.css';
import * as React from "react"; import * as React from "react";
@@ -20,6 +21,7 @@ import ChapterNamingScheme from "./Components/Settings/ChapterNamingScheme.tsx";
import AprilFoolsMode from './Components/Settings/AprilFoolsMode.tsx'; import AprilFoolsMode from './Components/Settings/AprilFoolsMode.tsx';
import RequestLimits from "./Components/Settings/RequestLimits.tsx"; import RequestLimits from "./Components/Settings/RequestLimits.tsx";
import FlareSolverr from "./Components/Settings/FlareSolverr.tsx"; import FlareSolverr from "./Components/Settings/FlareSolverr.tsx";
import {Article} from '@mui/icons-material';
const checkConnection = async (apiUri: string): Promise<boolean> =>{ const checkConnection = async (apiUri: string): Promise<boolean> =>{
return fetch(`${apiUri}/swagger/v2/swagger.json`, return fetch(`${apiUri}/swagger/v2/swagger.json`,
@@ -116,6 +118,9 @@ export default function Settings({open, setOpen, setApiUri, setConnected}:{open:
<RequestLimits backendSettings={backendSettings} /> <RequestLimits backendSettings={backendSettings} />
<FlareSolverr backendSettings={backendSettings} /> <FlareSolverr backendSettings={backendSettings} />
</AccordionGroup> </AccordionGroup>
<Stack spacing={2} direction="row">
<Link href={apiUri + "/swagger"}><Article />Swagger Doc</Link>
</Stack>
</DialogContent> </DialogContent>
</Drawer> </Drawer>
); );