From e63e82fde92362cfa14f06ccfac8d3397441b25c Mon Sep 17 00:00:00 2001 From: monoid Date: Sun, 17 Jan 2021 01:33:45 +0900 Subject: [PATCH] add tag link --- src/client/accessor/util.ts | 22 +++++++++++----------- src/client/component/contentinfo.tsx | 4 ++-- src/client/component/tagchip.tsx | 27 +++++++++++++++++++++------ src/db/doc.ts | 12 ++++++++---- src/route/contents.ts | 12 ++++++------ src/route/util.ts | 6 +++++- 6 files changed, 53 insertions(+), 30 deletions(-) diff --git a/src/client/accessor/util.ts b/src/client/accessor/util.ts index f9bd1ad..61c66f8 100644 --- a/src/client/accessor/util.ts +++ b/src/client/accessor/util.ts @@ -11,8 +11,8 @@ export const toQueryString = (obj:ToQueryStringA)=> { e[1] !== undefined) .map(e => e[1] instanceof Array - ? e[1].map(f=>`${e[0]}[]=${encodeURIComponent(f)}`).join('&') - : `${e[0]}=${encodeURIComponent(e[1])}`) + ? e[1].map(f=>`${e[0]}=${(f)}`).join('&') + : `${e[0]}=${(e[1])}`) .join('&'); } export const QueryStringToMap = (query:string) =>{ @@ -20,16 +20,16 @@ export const QueryStringToMap = (query:string) =>{ 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]; - } + const pv = param[k]; + if(pv === undefined){ + param[k] = v; + } + else if(typeof pv === "string"){ + param[k] = [pv,v]; + } + else{ + pv.push(v); } - else param[k] = v; }); return param; } \ No newline at end of file diff --git a/src/client/component/contentinfo.tsx b/src/client/component/contentinfo.tsx index de8452a..a88c61f 100644 --- a/src/client/component/contentinfo.tsx +++ b/src/client/component/contentinfo.tsx @@ -117,7 +117,7 @@ export const ContentInfo = (props: { {props.short ? ({document.tags.map(x => - () + () )}) : ( <> Artist @@ -125,7 +125,7 @@ export const ContentInfo = (props: { Tags {allTag.map(x => { - return (); + return (); })} ) diff --git a/src/client/component/tagchip.tsx b/src/client/component/tagchip.tsx index 62094ab..f2cd2cf 100644 --- a/src/client/component/tagchip.tsx +++ b/src/client/component/tagchip.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import {ChipProps} from '@material-ui/core/Chip'; +import {ChipTypeMap} from '@material-ui/core/Chip'; import { Chip, colors } from '@material-ui/core'; import {useTheme, makeStyles, Theme, emphasize, fade} from '@material-ui/core/styles'; +import {Link as RouterLink} from 'react-router-dom'; type TagChipStyleProp = { color: string @@ -43,14 +44,20 @@ const useTagStyles = makeStyles((theme:Theme)=>({ const {blue, pink} = colors; const getTagColorName = (tagname :string):string=>{ if(tagname.startsWith("female")){ - return pink['700']; + return pink[600]; } else if(tagname.startsWith("male")){ return blue[600]; } else return "default"; } -export const ColorChip = (props:Omit & {color: string})=>{ + +type ColorChipProp = Omit & TagChipStyleProp & { + component?: React.ElementType, + to?: string +} + +export const ColorChip = (props:ColorChipProp)=>{ const {color,...rest} = props; const classes = useTagStyles({color : color !== "default" ? color : "#000"}); return & {color: string})=>{ }} {...rest}>; } -export const TagChip = (props:Omit & {tagname: string})=>{ - const {tagname,label,...rest} = props; +type TagChipProp = Omit & { + tagname:string +} + +export const TagChip = (props:TagChipProp)=>{ + const {tagname,label,clickable,...rest} = props; let newlabel:string|undefined = undefined; if(typeof label === "string"){ if(label.startsWith("female:")){ @@ -69,5 +80,9 @@ export const TagChip = (props:Omit & {tagname: string})=>{ newlabel = "♂ "+label.slice(5); } } - return ; + const inner = clickable ? + (): + (); + return inner; } \ No newline at end of file diff --git a/src/db/doc.ts b/src/db/doc.ts index d60ea47..4448352 100644 --- a/src/db/doc.ts +++ b/src/db/doc.ts @@ -80,12 +80,16 @@ class KnexDocumentAccessor implements DocumentAccessor{ const cursor = option.cursor; const buildquery = ()=>{ - let query = this.knex.select("*"); + let query = this.knex.select("document.*"); if(allow_tag.length > 0){ - query = query.from("doc_tag_relation").innerJoin("document","doc_tag_relation.doc_id","document.id"); - for(const tag of allow_tag){ - query = query.where({tag_name:tag}); + query = query.from("doc_tag_relation as tags_0"); + query = query.where("tags_0.tag_name","=",allow_tag[0]); + for (let index = 1; index < allow_tag.length; index++) { + const element = allow_tag[index]; + query = query.innerJoin(`doc_tag_relation as tags_${index}`,`tags_${index}.doc_id`,"tags_0.doc_id"); + query = query.where(`tags_${index}.tag_name`,'=',element); } + query = query.innerJoin("document","tags_0.doc_id","document.id"); } else{ query = query.from("document"); diff --git a/src/route/contents.ts b/src/route/contents.ts index 7561f4a..43a8bb7 100644 --- a/src/route/contents.ts +++ b/src/route/contents.ts @@ -2,7 +2,7 @@ import { Context, Next } from 'koa'; import Router from 'koa-router'; import {Document, DocumentAccessor, isDocBody} from '../model/doc'; import {QueryListOption} from '../model/doc'; -import {ParseQueryNumber, ParseQueryArray, ParseQueryBoolean} from './util' +import {ParseQueryNumber, ParseQueryArray, ParseQueryBoolean, ParseQueryArgString} from './util' import {sendError} from './error_handler'; import { join } from 'path'; import {AllContentRouter} from './all'; @@ -31,14 +31,14 @@ const ContentTagIDHandler = (controller: DocumentAccessor) => async (ctx: Contex const ContentQueryHandler = (controller : DocumentAccessor) => async (ctx: Context,next: Next)=>{ const limit = ParseQueryNumber(ctx.query['limit']); const cursor = ParseQueryNumber(ctx.query['cursor']); - const word: string|undefined = ctx.query['word']; - const content_type:string|undefined = ctx.query['content_type']; + const word = ParseQueryArgString(ctx.query['word']); + const content_type = ParseQueryArgString(ctx.query['content_type']); const offset = ParseQueryNumber(ctx.query['offset']); if(limit === NaN || cursor === NaN || offset === NaN){ return sendError(400,"parameter limit, cursor or offset is not a number"); } - const allow_tag = ParseQueryArray(ctx.query['allow_tag[]']); - let [ok,use_offset] = ParseQueryBoolean(ctx.query['use_offset']); + const allow_tag = ParseQueryArray(ctx.query['allow_tag']); + const [ok,use_offset] = ParseQueryBoolean(ctx.query['use_offset']); if(!ok){ return sendError(400,"use_offset must be true or false."); } @@ -50,7 +50,7 @@ const ContentQueryHandler = (controller : DocumentAccessor) => async (ctx: Conte eager_loading: true, offset: offset, use_offset: use_offset, - content_type:content_type, + content_type: content_type, }; let document = await controller.findList(option); ctx.body = document; diff --git a/src/route/util.ts b/src/route/util.ts index 9e4892e..a7aa7e3 100644 --- a/src/route/util.ts +++ b/src/route/util.ts @@ -8,7 +8,11 @@ export function ParseQueryNumber(s: string|undefined): number| undefined{ } export function ParseQueryArray(s: string[]|string|undefined){ s = s || []; - return s instanceof Array ? s : [s]; + const r = s instanceof Array ? s : [s]; + return r.map(x=>decodeURIComponent(x)); +} +export function ParseQueryArgString(s: string|undefined){ + return s === undefined ? s : decodeURIComponent(s); } export function ParseQueryBoolean(s: string|undefined): [boolean,boolean|undefined]{ let value:boolean|undefined;