add tag link
This commit is contained in:
parent
64f5c82c8c
commit
e63e82fde9
@ -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);
|
||||
const pv = param[k];
|
||||
if(pv === undefined){
|
||||
param[k] = v;
|
||||
}
|
||||
else if(typeof pv === "string"){
|
||||
param[k] = [pv,v];
|
||||
}
|
||||
else{
|
||||
param[k] = [v];
|
||||
pv.push(v);
|
||||
}
|
||||
}
|
||||
else param[k] = v;
|
||||
});
|
||||
return param;
|
||||
}
|
@ -117,7 +117,7 @@ export const ContentInfo = (props: {
|
||||
</Link>
|
||||
<Box className={propclasses.subinfoContainer || subinfoContainer}>
|
||||
{props.short ? (<Box className={propclasses.tag_list || classes.tag_list}>{document.tags.map(x =>
|
||||
(<TagChip key={x} label={x} clickable={true} tagname={x} size="small"></TagChip>)
|
||||
(<TagChip key={x} label={x} clickable tagname={x} size="small"></TagChip>)
|
||||
)}</Box>) : (
|
||||
<>
|
||||
<Typography variant='subtitle1'>Artist</Typography>
|
||||
@ -125,7 +125,7 @@ export const ContentInfo = (props: {
|
||||
<Typography variant='subtitle1'>Tags</Typography>
|
||||
<Box className={propclasses.tag_list || classes.tag_list}>
|
||||
{allTag.map(x => {
|
||||
return (<TagChip key={x} label={x} clickable={true} tagname={x} size="small"></TagChip>);
|
||||
return (<TagChip key={x} label={x} clickable tagname={x} size="small"></TagChip>);
|
||||
})}
|
||||
</Box>
|
||||
</>)
|
||||
|
@ -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<ChipProps,"color"> & {color: string})=>{
|
||||
|
||||
type ColorChipProp = Omit<ChipTypeMap['props'],"color"> & TagChipStyleProp & {
|
||||
component?: React.ElementType,
|
||||
to?: string
|
||||
}
|
||||
|
||||
export const ColorChip = (props:ColorChipProp)=>{
|
||||
const {color,...rest} = props;
|
||||
const classes = useTagStyles({color : color !== "default" ? color : "#000"});
|
||||
return <Chip color="default" classes={{
|
||||
@ -58,8 +65,12 @@ export const ColorChip = (props:Omit<ChipProps,"color"> & {color: string})=>{
|
||||
}} {...rest}></Chip>;
|
||||
}
|
||||
|
||||
export const TagChip = (props:Omit<ChipProps,"color"> & {tagname: string})=>{
|
||||
const {tagname,label,...rest} = props;
|
||||
type TagChipProp = Omit<ChipTypeMap['props'],"color"> & {
|
||||
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<ChipProps,"color"> & {tagname: string})=>{
|
||||
newlabel = "♂ "+label.slice(5);
|
||||
}
|
||||
}
|
||||
return <ColorChip color={getTagColorName(tagname)} label={newlabel||label} {...rest}></ColorChip>;
|
||||
const inner = clickable ?
|
||||
(<ColorChip color={getTagColorName(tagname)} clickable={clickable} label={newlabel||label} {...rest}
|
||||
component={RouterLink} to={`/search?allow_tag=${tagname}`}></ColorChip>):
|
||||
(<ColorChip color={getTagColorName(tagname)} clickable={clickable} label={newlabel||label} {...rest}></ColorChip>);
|
||||
return inner;
|
||||
}
|
@ -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");
|
||||
|
@ -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.");
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user