Compare commits

...

2 Commits

Author SHA1 Message Date
monoid
e83a6bbe2b add: comic reader page up/down btn 2023-06-01 23:07:58 +09:00
monoid
d961e8166d add: overflow tag hidden 2023-06-01 21:48:10 +09:00
13 changed files with 699 additions and 712 deletions

File diff suppressed because it is too large Load Diff

View File

@ -90,7 +90,8 @@ export const ContentInfo = (props: {
<Paper
sx={{
display: "flex",
height: "400px",
height: props.short ? "400px" : "auto",
overflow: "hidden",
[theme.breakpoints.down("sm")]: {
flexDirection: "column",
alignItems: "center",
@ -128,8 +129,7 @@ export const ContentInfo = (props: {
path={document.basepath + "/" + document.filename}
createdAt={document.created_at}
deletedAt={document.deleted_at != null ? document.deleted_at : undefined}
>
</ComicDetailTag>
/>
)}
</Box>
{document.deleted_at != null
@ -138,9 +138,7 @@ export const ContentInfo = (props: {
onClick={() => {
documentDelete(document.id);
}}
>
Delete
</Button>
>Delete</Button>
)}
</Box>
</Paper>

View File

@ -198,8 +198,7 @@ export const Headline = (prop: {
}
}}
value={search}
>
</StyledInputBase>
/>
</StyledSearchBar>
{isLogin
? (
@ -250,12 +249,10 @@ export const Headline = (prop: {
display: "flex",
flexFlow: "column",
flexGrow: 1,
padding: theme.spacing(3),
marginTop: theme.spacing(6),
padding: "0px",
marginTop: "64px",
}}
>
<div style={{}}></div>
{prop.children}
>{prop.children}
</main>
</div>
);

View File

@ -0,0 +1,5 @@
import { styled } from "@mui/material";
export const PagePad = styled("div")(({theme})=>({
padding: theme.spacing(3)
}))

View File

@ -2,12 +2,15 @@ import { ArrowBack as ArrowBackIcon } from "@mui/icons-material";
import { Typography } from "@mui/material";
import React from "react";
import { BackItem, CommonMenuList, Headline, NavList } from "../component/mod";
import { PagePad } from "../component/pagepad";
export const NotFoundPage = () => {
const menu = CommonMenuList();
return (
<Headline menu={menu}>
<Typography variant="h2">404 Not Found</Typography>
<PagePad>
<Typography variant="h2">404 Not Found</Typography>
</PagePad>
</Headline>
);
};

View File

@ -6,6 +6,7 @@ import { LoadingCircle } from "../component/loading";
import { CommonMenuList, ContentInfo, Headline } from "../component/mod";
import { NotFoundPage } from "./404";
import { getPresenter } from "./reader/reader";
import { PagePad } from "../component/pagepad";
export const makeContentInfoUrl = (id: number) => `/doc/${id}`;
export const makeComicReaderUrl = (id: number) => `/doc/${id}/reader`;
@ -79,7 +80,7 @@ export const DocumentAbout = (prop?: {}) => {
if (match == null) {
throw new Error("unreachable");
}
const id = Number.parseInt(match.id);
const id = Number.parseInt(match.id ?? "NaN");
const [info, setInfo] = useState<DocumentState>({ doc: undefined, notfound: false });
const menu_list = (link?: string) => <CommonMenuList url={link}></CommonMenuList>;
@ -95,25 +96,33 @@ export const DocumentAbout = (prop?: {}) => {
if (isNaN(id)) {
return (
<Headline menu={menu_list()}>
<PagePad>
<Typography variant="h2">Oops. Invalid ID</Typography>
</PagePad>
</Headline>
);
} else if (info.notfound) {
return (
<Headline menu={menu_list()}>
<PagePad>
<Typography variant="h2">Content has been removed.</Typography>
</PagePad>
</Headline>
);
} else if (info.doc === undefined) {
return (
<Headline menu={menu_list()}>
<PagePad>
<LoadingCircle />
</PagePad>
</Headline>
);
} else {
return (
<Headline menu={menu_list()}>
<PagePad>
<ContentInfo document={info.doc}></ContentInfo>
</PagePad>
</Headline>
);
}

View File

@ -3,6 +3,7 @@ import { Stack } from "@mui/material";
import React, { useContext, useEffect, useState } from "react";
import { CommonMenuList, Headline } from "../component/mod";
import { UserContext } from "../state";
import { PagePad } from "../component/pagepad";
const useStyles = (theme: Theme) => ({
paper: {
@ -127,6 +128,7 @@ export function DifferencePage() {
const menu = CommonMenuList();
return (
<Headline menu={menu}>
<PagePad>
{(ctx.username == "admin")
? (
<div>
@ -136,6 +138,7 @@ export function DifferencePage() {
</div>
)
: <Typography variant="h2">Not Allowed : please login as an admin</Typography>}
</PagePad>
</Headline>
);
}

View File

@ -8,6 +8,7 @@ import { toQueryString } from "../accessor/util";
import { useLocation } from "react-router-dom";
import { QueryStringToMap } from "../accessor/util";
import { useIsElementInViewport } from "./reader/reader";
import { PagePad } from "../component/pagepad";
export type GalleryProp = {
option?: QueryListOption;
@ -70,8 +71,7 @@ export const GalleryInfo = (props: GalleryProp) => {
)}
{props.option.allow_tag !== undefined
&& props.option.allow_tag.map(x => (
<TagChip key={x} tagname={decodeURIComponent(x)} label={decodeURIComponent(x)}>
</TagChip>
<TagChip key={x} tagname={decodeURIComponent(x)} label={decodeURIComponent(x)}/>
))}
</Box>
)}
@ -126,7 +126,9 @@ export const Gallery = () => {
option.limit = typeof query["limit"] === "string" ? parseInt(query["limit"]) : undefined;
return (
<Headline menu={menu_list}>
<PagePad>
<GalleryInfo diff={location.search} option={query}></GalleryInfo>
</PagePad>
</Headline>
);
};

View File

@ -16,6 +16,7 @@ import { useNavigate } from "react-router-dom";
import { CommonMenuList, Headline } from "../component/mod";
import { UserContext } from "../state";
import { doLogin as doSessionLogin } from "../state";
import { PagePad } from "../component/pagepad";
export const LoginPage = () => {
const theme = useTheme();
@ -48,39 +49,41 @@ export const LoginPage = () => {
const menu = CommonMenuList();
return (
<Headline menu={menu}>
<Paper style={{ width: theme.spacing(40), padding: theme.spacing(4), alignSelf: "center" }}>
<Typography variant="h4">Login</Typography>
<div style={{ minHeight: theme.spacing(2) }}></div>
<form style={{ display: "flex", flexFlow: "column", alignItems: "stretch" }}>
<TextField
label="username"
onChange={(e) => setUserLoginInfo({ ...userLoginInfo, username: e.target.value ?? "" })}
>
</TextField>
<TextField
label="password"
type="password"
onKeyDown={(e) => {
if (e.key === "Enter") doLogin();
}}
onChange={(e) => setUserLoginInfo({ ...userLoginInfo, password: e.target.value ?? "" })}
/>
<PagePad>
<Paper style={{ width: theme.spacing(40), padding: theme.spacing(4), alignSelf: "center" }}>
<Typography variant="h4">Login</Typography>
<div style={{ minHeight: theme.spacing(2) }}></div>
<div style={{ display: "flex" }}>
<Button onClick={doLogin}>login</Button>
<Button>signin</Button>
</div>
</form>
</Paper>
<Dialog open={openDialog.open} onClose={handleDialogClose}>
<DialogTitle>Login Failed</DialogTitle>
<DialogContent>
<DialogContentText>detail : {openDialog.message}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleDialogClose} color="primary" autoFocus>Close</Button>
</DialogActions>
</Dialog>
<form style={{ display: "flex", flexFlow: "column", alignItems: "stretch" }}>
<TextField
label="username"
onChange={(e) => setUserLoginInfo({ ...userLoginInfo, username: e.target.value ?? "" })}
>
</TextField>
<TextField
label="password"
type="password"
onKeyDown={(e) => {
if (e.key === "Enter") doLogin();
}}
onChange={(e) => setUserLoginInfo({ ...userLoginInfo, password: e.target.value ?? "" })}
/>
<div style={{ minHeight: theme.spacing(2) }}></div>
<div style={{ display: "flex" }}>
<Button onClick={doLogin}>login</Button>
<Button>signin</Button>
</div>
</form>
</Paper>
<Dialog open={openDialog.open} onClose={handleDialogClose}>
<DialogTitle>Login Failed</DialogTitle>
<DialogContent>
<DialogContentText>detail : {openDialog.message}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleDialogClose} color="primary" autoFocus>Close</Button>
</DialogActions>
</Dialog>
</PagePad>
</Headline>
);
};

View File

@ -16,6 +16,7 @@ import {
import React, { useContext, useState } from "react";
import { CommonMenuList, Headline } from "../component/mod";
import { UserContext } from "../state";
import { PagePad } from "../component/pagepad";
const useStyles = (theme: Theme) => ({
paper: {
@ -77,71 +78,74 @@ export function ProfilePage() {
};
return (
<Headline menu={menu}>
<Paper /*className={classes.paper}*/>
<Grid container direction="column" alignItems="center">
<Grid item>
<Typography variant="h4">{userctx.username}</Typography>
<PagePad>
<Paper /*className={classes.paper}*/>
<Grid container direction="column" alignItems="center">
<Grid item>
<Typography variant="h4">{userctx.username}</Typography>
</Grid>
<Divider></Divider>
<Grid item>
Permission
</Grid>
<Grid item>
{permission_list.length == 0 ? "-" : permission_list}
</Grid>
<Grid item>
<Button onClick={handle_open}>Password Reset</Button>
</Grid>
</Grid>
<Divider></Divider>
<Grid item>
Permission
</Grid>
<Grid item>
{permission_list.length == 0 ? "-" : permission_list}
</Grid>
<Grid item>
<Button onClick={handle_open}>Password Reset</Button>
</Grid>
</Grid>
</Paper>
<Dialog open={pw_open} onClose={handle_close}>
<DialogTitle>Password Reset</DialogTitle>
<DialogContent>
<Typography>type the old and new password</Typography>
<div /*className={classes.formfield}*/>
{(!isElectronContent) && (
</Paper>
<Dialog open={pw_open} onClose={handle_close}>
<DialogTitle>Password Reset</DialogTitle>
<DialogContent>
<Typography>type the old and new password</Typography>
<div /*className={classes.formfield}*/>
{(!isElectronContent) && (
<TextField
autoFocus
margin="dense"
type="password"
label="old password"
value={oldpw}
onChange={(e) => setOldpw(e.target.value)}
>
</TextField>
)}
<TextField
autoFocus
margin="dense"
type="password"
label="old password"
value={oldpw}
onChange={(e) => setOldpw(e.target.value)}
label="new password"
value={newpw}
onChange={e => setNewpw(e.target.value)}
>
</TextField>
)}
<TextField
margin="dense"
type="password"
label="new password"
value={newpw}
onChange={e => setNewpw(e.target.value)}
>
</TextField>
<TextField
margin="dense"
type="password"
label="new password check"
value={newpwch}
onChange={e => setNewpwch(e.target.value)}
>
</TextField>
</div>
</DialogContent>
<DialogActions>
<Button onClick={handle_close} color="primary">Cancel</Button>
<Button onClick={handle_ok} color="primary">Ok</Button>
</DialogActions>
</Dialog>
<Dialog open={msg_dialog.opened} onClose={() => set_msg_dialog({ opened: false, msg: "" })}>
<DialogTitle>Alert!</DialogTitle>
<DialogContent>
<DialogContentText>{msg_dialog.msg}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => set_msg_dialog({ opened: false, msg: "" })} color="primary">Close</Button>
</DialogActions>
</Dialog>
<TextField
margin="dense"
type="password"
label="new password check"
value={newpwch}
onChange={e => setNewpwch(e.target.value)}
>
</TextField>
</div>
</DialogContent>
<DialogActions>
<Button onClick={handle_close} color="primary">Cancel</Button>
<Button onClick={handle_ok} color="primary">Ok</Button>
</DialogActions>
</Dialog>
<Dialog open={msg_dialog.opened} onClose={() => set_msg_dialog({ opened: false, msg: "" })}>
<DialogTitle>Alert!</DialogTitle>
<DialogContent>
<DialogContentText>{msg_dialog.msg}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => set_msg_dialog({ opened: false, msg: "" })} color="primary">Close</Button>
</DialogActions>
</Dialog>
</PagePad>
</Headline>
);
}

View File

@ -1,4 +1,4 @@
import { Typography, useTheme } from "@mui/material";
import { Typography, styled } from "@mui/material";
import React, { useEffect, useState } from "react";
import { Document } from "../../accessor/document";
@ -13,6 +13,21 @@ export type PresentableTag = {
tags: string[];
};
const ViewMain = styled("div")(({ theme }) => ({
overflow: "hidden",
width: "100%",
height: "calc(100vh - 64px)",
position: "relative",
}));
const CurrentView = styled("img")(({theme})=>({
maxWidth: "100%",
maxHeight: "100%",
top:"50%",
left:"50%",
transform: "translate(-50%,-50%)",
position: "absolute"
}));
export const ComicReader = (props: { doc: Document }) => {
const additional = props.doc.additional;
const [curPage, setCurPage] = useState(0);
@ -21,13 +36,13 @@ export const ComicReader = (props: { doc: Document }) => {
return <Typography>Error. DB error. page restriction</Typography>;
}
const PageDown = () => setCurPage(Math.max(curPage - 1, 0));
const PageUP = () => setCurPage(Math.min(curPage + 1, page - 1));
const PageUp = () => setCurPage(Math.min(curPage + 1, page - 1));
const page: number = additional["page"] as number;
const onKeyUp = (e: KeyboardEvent) => {
if (e.code === "ArrowLeft") {
PageDown();
} else if (e.code === "ArrowRight") {
PageUP();
PageUp();
}
};
useEffect(() => {
@ -38,14 +53,14 @@ export const ComicReader = (props: { doc: Document }) => {
});
// theme.mixins.toolbar.minHeight;
return (
<div style={{ overflow: "hidden", alignSelf: "center" }}>
<img
onClick={PageUP}
<ViewMain>
<div onClick={PageDown} style={{left:"0", width: "50%", position:"absolute", height: "100%", zIndex:100}}></div>
<CurrentView
onClick={PageUp}
src={`/api/doc/${props.doc.id}/comic/${curPage}`}
style={{ maxWidth: "100%", maxHeight: "calc(100vh - 64px)" }}
>
</img>
</div>
></CurrentView>
<div onClick={PageUp} style={{right:"0", width: "50%", position:"absolute", height: "100%", zIndex:100}}></div>
</ViewMain>
);
};

View File

@ -2,14 +2,17 @@ import { ArrowBack as ArrowBackIcon } from "@mui/icons-material";
import { Paper, Typography } from "@mui/material";
import React from "react";
import { BackItem, CommonMenuList, Headline, NavList } from "../component/mod";
import { PagePad } from "../component/pagepad";
export const SettingPage = () => {
const menu = CommonMenuList();
return (
<Headline menu={menu}>
<Paper>
<Typography variant="h2">Setting</Typography>
</Paper>
<PagePad>
<Paper>
<Typography variant="h2">Setting</Typography>
</Paper>
</PagePad>
</Headline>
);
};

View File

@ -3,6 +3,7 @@ import { DataGrid, GridColDef } from "@mui/x-data-grid";
import React, { useEffect, useState } from "react";
import { LoadingCircle } from "../component/loading";
import { CommonMenuList, Headline } from "../component/mod";
import { PagePad } from "../component/pagepad";
type TagCount = {
tag_name: string;
@ -67,7 +68,9 @@ export const TagsPage = () => {
const menu = CommonMenuList();
return (
<Headline menu={menu}>
<TagTable></TagTable>
<PagePad>
<TagTable></TagTable>
</PagePad>
</Headline>
);
};