back link feature

This commit is contained in:
monoid 2021-01-08 17:26:38 +09:00
parent 5002bc22f9
commit 714ba9aae7
7 changed files with 77 additions and 26 deletions

View File

@ -14,4 +14,22 @@ export const toQueryString = (obj:ToQueryStringA)=> {
? e[1].map(f=>`${e[0]}[]=${encodeURIComponent(f)}`).join('&')
: `${e[0]}=${encodeURIComponent(e[1])}`)
.join('&');
}
export const QueryStringToMap = (query:string) =>{
const keyValue = query.slice(query.indexOf("?")+1).split("&");
const param:{[k:string]:string|string[]} = {};
keyValue.forEach((p)=>{
const [k,v] = p.split("=");
if(k.endsWith("[]")){
let arr = param[k];
if(arr instanceof Array){
arr.push(v);
}
else{
param[k] = [v];
}
}
else param[k] = v;
});
return param;
}

View File

@ -1,23 +1,28 @@
import React, { useRef, useState } from 'react';
import React, { createContext, useRef, useState } from 'react';
import ReactDom from 'react-dom';
import {BrowserRouter, Route, Switch as RouterSwitch} from 'react-router-dom';
import { Gallery, ContentAbout} from './page/mod';
import {BackLinkContext} from './state';
import './css/style.css';
const FooProfile = ()=><div>test profile</div>;
const App = () => {
return (<BrowserRouter>
<RouterSwitch>
<Route path="/" exact render={()=><Gallery />}></Route>
<Route path="/search" render={()=><Gallery />}></Route>
<Route path="/doc" render={(prop)=><ContentAbout {...prop}/>}></Route>
<Route path="/profile" component={FooProfile}></Route>
<Route>
<div>404 Not Found</div>
</Route>
</RouterSwitch>
</BrowserRouter>);
const [path,setPath] = useState("/");
return (
<BackLinkContext.Provider value={{path:path,setPath:setPath}}>
<BrowserRouter>
<RouterSwitch>
<Route path="/" exact render={()=><Gallery />}></Route>
<Route path="/search" render={()=><Gallery />}></Route>
<Route path="/doc" render={(prop)=><ContentAbout {...prop}/>}></Route>
<Route path="/profile" component={FooProfile}></Route>
<Route>
<div>404 Not Found</div>
</Route>
</RouterSwitch>
</BrowserRouter>
</BackLinkContext.Provider>);
};
ReactDom.render(

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useContext } from 'react';
import { Redirect, Route, Switch, useHistory, useRouteMatch, match as MatchType, Link as RouterLink, useParams, useLocation } from 'react-router-dom';
import ContentAccessor, { Content } from '../accessor/contents';
import { LoadingCircle } from '../component/loading';
@ -6,6 +6,7 @@ import { Link, Paper, makeStyles, Theme, Box, useTheme, Typography } from '@mate
import {ArrowBack as ArrowBackIcon } from '@material-ui/icons';
import { MangaReader } from './reader/manga';
import { ContentInfo, Headline, NavItem, NavList } from '../component/mod';
import {BackLinkContext} from '../state';
export const makeContentInfoUrl = (id: number) => `/doc/${id}`;
export const makeMangaReaderUrl = (id: number) => `/doc/${id}/reader`;
@ -24,9 +25,15 @@ export const ContentAbout = (prop: { match: MatchType }) => {
const [info, setInfo] = useState<ContentState>({ content: undefined, notfound:false });
const location = useLocation();
console.log("state : "+location.state);
const menu_list = (
const menu_list = (link?:string)=>(
<NavList>
<NavItem name="Back" to="/" icon={<ArrowBackIcon/>}></NavItem>
<BackLinkContext.Consumer>
{
(ctx) => link === undefined ?
<NavItem name="Back" to={ctx.path} icon={<ArrowBackIcon/>}/>
: <NavItem name="Back" to={link} icon={<ArrowBackIcon/>}/>
}
</BackLinkContext.Consumer>
</NavList>
);
@ -42,39 +49,43 @@ export const ContentAbout = (prop: { match: MatchType }) => {
}, []);
if (isNaN(id)) {
return (
<Headline menu={menu_list}>
<Headline menu={menu_list()}>
<Typography variant='h2'>Oops. Invalid ID</Typography>
</Headline>
);
}
else if(info.notfound){
return (
<Headline menu={menu_list}>
<Headline menu={menu_list()}>
<Typography variant='h2'>Content has been removed.</Typography>
</Headline>
)
}
else if (info.content === undefined) {
return (<Headline menu={menu_list}>
return (<Headline menu={menu_list()}>
<LoadingCircle />
</Headline>
);
}
else return (<Switch>
else{
return (<Switch>
<Route exact path={`${prop.match.path}/:id`}>
<Headline menu={menu_list}>
<Headline menu={menu_list()}>
<ContentInfo content={info.content}></ContentInfo>
</Headline>
</Route>
<Route exact path={`${prop.match.path}/:id/reader`}>
<Headline menu={menu_list}>
<Headline menu={menu_list(`${prop.match.path}/${id}`)}>
<MangaReader content={info.content}></MangaReader>
</Headline>
</Route>
<Route>
<Headline menu={menu_list}>
<Headline menu={menu_list()}>
<div>404 Not Found invalid url : {prop.match.path}</div>
</Headline>
</Route>
</Switch>);
}
}

View File

@ -1,14 +1,22 @@
import React from 'react';
import React, { useContext } from 'react';
import { NavList, NavItem, Headline } from '../component/mod';
import {ArrowBack as ArrowBackIcon} from '@material-ui/icons';
import {GalleryInfo} from '../component/mod';
import {BackLinkContext} from '../state';
import {useLocation} from 'react-router-dom';
import { QueryStringToMap } from '../accessor/util';
export const Gallery = ()=>{
const location = useLocation();
const backctx = useContext(BackLinkContext);
backctx.setPath("/");
const query = QueryStringToMap(location.search);
const menu_list = (<NavList>
<NavItem name="Back" to="" icon={<ArrowBackIcon></ArrowBackIcon>}></NavItem>
{Object.keys(query).length !== 0 && <NavItem name="Back" to="/" icon={<ArrowBackIcon></ArrowBackIcon>}></NavItem>}
</NavList>);
return (<Headline menu={menu_list}>
<GalleryInfo></GalleryInfo>
<GalleryInfo option={query}></GalleryInfo>
</Headline>)
}

View File

@ -22,7 +22,7 @@ export const MangaReader = (props:{content:Content})=>{
return <Typography>Error. DB error. page restriction</Typography>
}
const page:number = additional['page'] as number;
return (<div>{[...Array(page).keys()].map(x=>(<img src={`/content/${props.content.id}/manga/${x}`} style={{maxHeight:'100%',maxWidth:'100%'}}></img>))}</div>);
return (<div>{[...Array(page).keys()].map(x=>(<img src={`/content/${props.content.id}/manga/${x}`} key={x} style={{maxHeight:'100%',maxWidth:'100%'}}></img>))}</div>);
}
export default MangaReader;

3
src/client/state.tsx Normal file
View File

@ -0,0 +1,3 @@
import React, { createContext, useRef, useState } from 'react';
export const BackLinkContext = createContext({path:"",setPath:(s:string)=>{}});

View File

@ -47,6 +47,12 @@ async function main(){
ctx.body = index_html;
}
);
router.get('/search'
,async (ctx,next)=>{
ctx.type = "html";
ctx.body = index_html;
}
);
let content_router = getContentRouter(createKnexContentsAccessor(db));
router.use('/content',content_router.routes());
router.use('/content',content_router.allowedMethods());