simple search
This commit is contained in:
		
							parent
							
								
									7a3fdce4dc
								
							
						
					
					
						commit
						1eba3e43e7
					
				
					 7 changed files with 89 additions and 35 deletions
				
			
		| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
import React, { createContext, useEffect, useRef, useState } from 'react';
 | 
					import React, { createContext, useEffect, useRef, useState } from 'react';
 | 
				
			||||||
import ReactDom from 'react-dom';
 | 
					import ReactDom from 'react-dom';
 | 
				
			||||||
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
 | 
					import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
 | 
				
			||||||
import { Gallery, DocumentAbout, LoginPage, NotFoundPage, ProfilePage, DifferencePage, SettingPage } from './page/mod';
 | 
					import { Gallery, DocumentAbout, LoginPage, NotFoundPage, ProfilePage, DifferencePage, SettingPage, ReaderPage } from './page/mod';
 | 
				
			||||||
import { getInitialValue, UserContext } from './state';
 | 
					import { getInitialValue, UserContext } from './state';
 | 
				
			||||||
import { ThemeProvider, createTheme } from '@mui/material';
 | 
					import { ThemeProvider, createTheme } from '@mui/material';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,8 @@ const App = () => {
 | 
				
			||||||
                    <Routes>
 | 
					                    <Routes>
 | 
				
			||||||
                        <Route path="/" element={<Navigate replace to='/search?' />} />
 | 
					                        <Route path="/" element={<Navigate replace to='/search?' />} />
 | 
				
			||||||
                        <Route path="/search" element={<Gallery />} />
 | 
					                        <Route path="/search" element={<Gallery />} />
 | 
				
			||||||
                        <Route path="/doc" element={<DocumentAbout />}></Route>
 | 
					                        <Route path="/doc/:id" element={<DocumentAbout />}></Route>
 | 
				
			||||||
 | 
					                        <Route path="/doc/:id/reader" element={<ReaderPage />}></Route>
 | 
				
			||||||
                        <Route path="/login" element={<LoginPage></LoginPage>} />
 | 
					                        <Route path="/login" element={<LoginPage></LoginPage>} />
 | 
				
			||||||
                        <Route path="/profile" element={<ProfilePage />}></Route>
 | 
					                        <Route path="/profile" element={<ProfilePage />}></Route>
 | 
				
			||||||
                        <Route path="/difference" element={<DifferencePage />}></Route>
 | 
					                        <Route path="/difference" element={<DifferencePage />}></Route>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,6 @@ export const ContentInfo = (props: {
 | 
				
			||||||
    //const classes = useStyles();
 | 
					    //const classes = useStyles();
 | 
				
			||||||
    const theme = useTheme();
 | 
					    const theme = useTheme();
 | 
				
			||||||
    const document = props.document;
 | 
					    const document = props.document;
 | 
				
			||||||
    const propclasses = props.classes ?? {};
 | 
					 | 
				
			||||||
    /*const rootName = props.short ? classes.short_root : classes.root;
 | 
					    /*const rootName = props.short ? classes.short_root : classes.root;
 | 
				
			||||||
    const thumbnail_anchor = props.short ? classes.short_thumbnail_anchor : "";
 | 
					    const thumbnail_anchor = props.short ? classes.short_thumbnail_anchor : "";
 | 
				
			||||||
    const thumbnail_content = props.short ? classes.short_thumbnail_content :
 | 
					    const thumbnail_content = props.short ? classes.short_thumbnail_content :
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ import {
 | 
				
			||||||
    ChevronLeft, ChevronRight, Menu as MenuIcon, Search as SearchIcon, AccountCircle
 | 
					    ChevronLeft, ChevronRight, Menu as MenuIcon, Search as SearchIcon, AccountCircle
 | 
				
			||||||
} from '@mui/icons-material';
 | 
					} from '@mui/icons-material';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Link as RouterLink } from 'react-router-dom';
 | 
					import { Link as RouterLink, useNavigate } from 'react-router-dom';
 | 
				
			||||||
import { doLogout, UserContext } from '../state';
 | 
					import { doLogout, UserContext } from '../state';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const drawerWidth = 270;
 | 
					const drawerWidth = 270;
 | 
				
			||||||
| 
						 | 
					@ -80,6 +80,8 @@ export const Headline = (prop: {
 | 
				
			||||||
    const menuId = 'primary-search-account-menu';
 | 
					    const menuId = 'primary-search-account-menu';
 | 
				
			||||||
    const user_ctx = useContext(UserContext);
 | 
					    const user_ctx = useContext(UserContext);
 | 
				
			||||||
    const isLogin = user_ctx.username !== "";
 | 
					    const isLogin = user_ctx.username !== "";
 | 
				
			||||||
 | 
					    const navigate = useNavigate();
 | 
				
			||||||
 | 
					    const [search, setSearch] = useState("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const renderProfileMenu = (<Menu
 | 
					    const renderProfileMenu = (<Menu
 | 
				
			||||||
        anchorEl={anchorEl}
 | 
					        anchorEl={anchorEl}
 | 
				
			||||||
| 
						 | 
					@ -139,9 +141,21 @@ export const Headline = (prop: {
 | 
				
			||||||
                        alignItems: 'center',
 | 
					                        alignItems: 'center',
 | 
				
			||||||
                        justifyContent: 'center'
 | 
					                        justifyContent: 'center'
 | 
				
			||||||
                    }}>
 | 
					                    }}>
 | 
				
			||||||
                        <SearchIcon />
 | 
					                        <SearchIcon onClick={() => navigate(`/search?word=${encodeURIComponent(search)}`)} />
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                    <StyledInputBase placeholder="search"></StyledInputBase>
 | 
					                    <StyledInputBase placeholder="search"
 | 
				
			||||||
 | 
					                        onChange={(e) => setSearch(e.target.value)}
 | 
				
			||||||
 | 
					                        onKeyUp={(e) => {
 | 
				
			||||||
 | 
					                            if (e.key === "Enter") {
 | 
				
			||||||
 | 
					                                let words = search.includes("&") ? search.split("&") : [search];
 | 
				
			||||||
 | 
					                                words = words.map(w => w.trim())
 | 
				
			||||||
 | 
					                                    .map(w => w.includes(":") ? 
 | 
				
			||||||
 | 
					                                        `allow_tag=${w}` 
 | 
				
			||||||
 | 
					                                        : `word=${encodeURIComponent(w)}`);
 | 
				
			||||||
 | 
					                                navigate(`/search?${words.join("&")}`);               
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }}
 | 
				
			||||||
 | 
					                        value={search}></StyledInputBase>
 | 
				
			||||||
                </StyledSearchBar>
 | 
					                </StyledSearchBar>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    isLogin ?
 | 
					                    isLogin ?
 | 
				
			||||||
| 
						 | 
					@ -159,7 +173,7 @@ export const Headline = (prop: {
 | 
				
			||||||
            </Toolbar>
 | 
					            </Toolbar>
 | 
				
			||||||
        </AppBar>
 | 
					        </AppBar>
 | 
				
			||||||
        {renderProfileMenu}
 | 
					        {renderProfileMenu}
 | 
				
			||||||
        <nav>
 | 
					        <nav style={{ width: theme.spacing(7) }}>
 | 
				
			||||||
            <Hidden smUp implementation="css">
 | 
					            <Hidden smUp implementation="css">
 | 
				
			||||||
                <StyledDrawer variant="temporary" anchor='left' open={v} onClose={toggleV}
 | 
					                <StyledDrawer variant="temporary" anchor='left' open={v} onClose={toggleV}
 | 
				
			||||||
                    sx={{
 | 
					                    sx={{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ const styles = ((theme:Theme)=>({
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const DocumentAbout = (prop?: {}) => {
 | 
					export function ReaderPage(props?: {}) {
 | 
				
			||||||
    const location = useLocation();
 | 
					    const location = useLocation();
 | 
				
			||||||
    const match = useParams<{ id: string }>();
 | 
					    const match = useParams<{ id: string }>();
 | 
				
			||||||
    if (match == null) {
 | 
					    if (match == null) {
 | 
				
			||||||
| 
						 | 
					@ -68,20 +68,55 @@ export const DocumentAbout = (prop?: {}) => {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        const ReaderPage = getPresenter(info.doc);
 | 
					        const ReaderPage = getPresenter(info.doc);
 | 
				
			||||||
        return (<Routes>
 | 
					        return <Headline menu={menu_list(location.pathname)}>
 | 
				
			||||||
        <Route path={`:id`}>
 | 
					            <ReaderPage doc={info.doc}></ReaderPage>
 | 
				
			||||||
 | 
					        </Headline>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const DocumentAbout = (prop?: {}) => {
 | 
				
			||||||
 | 
					    const match = useParams<{ id: string }>();
 | 
				
			||||||
 | 
					    if (match == null) {
 | 
				
			||||||
 | 
					        throw new Error("unreachable");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const id = Number.parseInt(match.id);
 | 
				
			||||||
 | 
					    const [info, setInfo] = useState<DocumentState>({ doc: undefined, notfound: false });
 | 
				
			||||||
 | 
					    const menu_list = (link?: string) => <CommonMenuList url={link}></CommonMenuList>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        (async () => {
 | 
				
			||||||
 | 
					            if (!isNaN(id)) {
 | 
				
			||||||
 | 
					                const c = await DocumentAccessor.findById(id);
 | 
				
			||||||
 | 
					                setInfo({ doc: c, notfound: c === undefined });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })();
 | 
				
			||||||
 | 
					    }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (isNaN(id)) {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <Headline menu={menu_list()}>
 | 
				
			||||||
 | 
					                <Typography variant='h2'>Oops. Invalid ID</Typography>
 | 
				
			||||||
 | 
					            </Headline>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (info.notfound) {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <Headline menu={menu_list()}>
 | 
				
			||||||
 | 
					                <Typography variant='h2'>Content has been removed.</Typography>
 | 
				
			||||||
 | 
					            </Headline>
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (info.doc === undefined) {
 | 
				
			||||||
 | 
					        return (<Headline menu={menu_list()}>
 | 
				
			||||||
 | 
					            <LoadingCircle />
 | 
				
			||||||
 | 
					        </Headline>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
            <Headline menu={menu_list()}>
 | 
					            <Headline menu={menu_list()}>
 | 
				
			||||||
                <ContentInfo document={info.doc}></ContentInfo>
 | 
					                <ContentInfo document={info.doc}></ContentInfo>
 | 
				
			||||||
            </Headline>
 | 
					            </Headline>
 | 
				
			||||||
        </Route>
 | 
					        );
 | 
				
			||||||
        <Route path={`:id/reader`}>
 | 
					 | 
				
			||||||
            <Headline menu={menu_list(location.pathname)}>
 | 
					 | 
				
			||||||
                <ReaderPage doc={info.doc}></ReaderPage>
 | 
					 | 
				
			||||||
            </Headline>
 | 
					 | 
				
			||||||
        </Route>
 | 
					 | 
				
			||||||
        <Route>
 | 
					 | 
				
			||||||
            <NotFoundPage></NotFoundPage>
 | 
					 | 
				
			||||||
        </Route>
 | 
					 | 
				
			||||||
    </Routes>);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
import React, { useContext, useEffect, useState } from 'react';
 | 
					import React, { useContext, useEffect, useState } from 'react';
 | 
				
			||||||
import { Headline, CommonMenuList,LoadingCircle, ContentInfo, NavList, NavItem, TagChip } from '../component/mod';
 | 
					import { Headline, CommonMenuList,LoadingCircle, ContentInfo, NavList, NavItem, TagChip } from '../component/mod';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Box, Typography, Chip } from '@mui/material';
 | 
					import { Box, Typography, Chip, Pagination } from '@mui/material';
 | 
				
			||||||
import ContentAccessor,{QueryListOption, Document} from '../accessor/document';
 | 
					import ContentAccessor,{QueryListOption, Document} from '../accessor/document';
 | 
				
			||||||
import {toQueryString} from '../accessor/util';
 | 
					import {toQueryString} from '../accessor/util';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,5 +62,6 @@ export const Gallery = ()=>{
 | 
				
			||||||
    option.limit = typeof query['limit'] === "string" ? parseInt(query['limit']) : undefined;
 | 
					    option.limit = typeof query['limit'] === "string" ? parseInt(query['limit']) : undefined;
 | 
				
			||||||
    return (<Headline menu={menu_list}>
 | 
					    return (<Headline menu={menu_list}>
 | 
				
			||||||
        <GalleryInfo diff={location.search} option={query}></GalleryInfo>
 | 
					        <GalleryInfo diff={location.search} option={query}></GalleryInfo>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
    </Headline>)
 | 
					    </Headline>)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ import React, {useState, useEffect} from 'react';
 | 
				
			||||||
import {  Typography, useTheme } from '@mui/material';
 | 
					import {  Typography, useTheme } from '@mui/material';
 | 
				
			||||||
import { Document } from '../../accessor/document';
 | 
					import { Document } from '../../accessor/document';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ComicType = "comic"|"artist cg"|"donjinshi"|"western"
 | 
					type ComicType = "comic"|"artist cg"|"donjinshi"|"western";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type PresentableTag = {
 | 
					export type PresentableTag = {
 | 
				
			||||||
    artist:string[],
 | 
					    artist:string[],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,11 @@ class KnexDocumentAccessor implements DocumentAccessor{
 | 
				
			||||||
        this.tagController = createKnexTagController(knex);
 | 
					        this.tagController = createKnexTagController(knex);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    async search(search_word: string): Promise<Document[]>{
 | 
					    async search(search_word: string): Promise<Document[]>{
 | 
				
			||||||
        throw new Error("Not implemented");
 | 
					        throw new Error("Method not implemented.");
 | 
				
			||||||
 | 
					        const sw = `%${search_word}%`;
 | 
				
			||||||
 | 
					        const docs = await this.knex.select("*").from("document")
 | 
				
			||||||
 | 
					            .where("title","like",sw);
 | 
				
			||||||
 | 
					        return docs;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    async addList(content_list: DocumentBody[]):Promise<number[]>{
 | 
					    async addList(content_list: DocumentBody[]):Promise<number[]>{
 | 
				
			||||||
        return await this.knex.transaction(async (trx)=>{
 | 
					        return await this.knex.transaction(async (trx)=>{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue