diff --git a/web/.eslintrc.js b/web/.eslintrc.js index de835a91..4a5210a1 100644 --- a/web/.eslintrc.js +++ b/web/.eslintrc.js @@ -1,5 +1,4 @@ module.exports = { - extends: [ - '@nuxtjs/eslint-config-typescript' - ] + root: true, + extends: ['@nuxt/eslint-config', '@nuxtjs/eslint-config-typescript'] } diff --git a/web/.gitignore b/web/.gitignore index 0e1bdb51..4a7f73a2 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -1,87 +1,24 @@ -# Created by .ignore support plugin (hsz.mobi) -### Node template -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output +# Nuxt dev/build outputs +.output +.data .nuxt - -# Nuxt generate +.nitro +.cache dist -# vuepress build output -.vuepress/dist +# Node dependencies +node_modules -# Serverless directories -.serverless +# Logs +logs +*.log -# IDE +# Misc +.DS_Store +.fleet .idea -# Service worker -sw.* - - -static/prism-schema.ttl +# Local env files +.env +.env.* +!.env.example diff --git a/web/Dockerfile b/web/Dockerfile index 5494915b..1b3bf0a6 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -14,4 +14,4 @@ ENV NODE_ENV=production ENV HOST 0.0.0.0 ENV PORT 8080 -CMD ["npm", "start"] +CMD ["node", ".output/server/index.mjs"] diff --git a/web/api/middleware/sparql.ts b/web/api/middleware/sparql.ts deleted file mode 100644 index 2d226f0c..00000000 --- a/web/api/middleware/sparql.ts +++ /dev/null @@ -1,90 +0,0 @@ -import axios from 'axios' -import { KeyValue } from './util' - -interface Binding { - [key: string]: { - datatype: string - value: string - } -} - -interface QueryResult { - head: { - vars: string[] - } - results: { - bindings: Binding[] - } -} - -const schemaUri = `https://prismdb.takanakahiko.me/prism-schema.ttl#` -const typePredUri = `http://www.w3.org/1999/02/22-rdf-syntax-ns#type` -const uri2schema = (uri:string) => uri.replace(/https:\/\/prismdb\.takanakahiko\.me\/prism-schema\.ttl#.+?/, "") -const schema2uri = (schema:string) => `${schemaUri}${schema}` -const uri2key = (uri:string) => uri.replace(/https:\/\/prismdb\.takanakahiko\.me\/rdfs\/.+?\//, "") -const classBaseUri = (className:string) => `https://prismdb.takanakahiko.me/rdfs/${className.toLowerCase()}/` - -const bindings2object = ( - bindings: Binding[], - arrayParameters: { [_: string]: string } = {} -) => { - const ret: KeyValue = {} - Object.keys(arrayParameters).forEach(predicateName => { - const parameterName = arrayParameters[predicateName] - ret[parameterName] = [] - }) - bindings.forEach(b => { - const pred = b["pred"].value - if (!pred.includes(schemaUri)) return - const predicateName = pred.replace(schemaUri, "") - let value = uri2key(b["obj"].value) as any - switch (b["obj"].datatype) { - case "http://www.w3.org/2001/XMLSchema#integer": - value = parseInt(value) - break - } - if (arrayParameters && (predicateName in arrayParameters)) { - const parameterName = arrayParameters[predicateName] - ret[parameterName].push(value) - } else { - ret[predicateName] = value - } - }) - return ret -} - -export default class { - static async getKeys(className: string) { - const query = `SELECT ?sub WHERE { ?sub <${typePredUri}> <${schema2uri(className)}> }` - const resp = await this.q(query) - const subjectUris = resp.results.bindings.map(b => b["sub"].value) - const ret = subjectUris.map(uri2key) - return ret - } - static async getInstanceList(className: string, arrayParameters?: { [_: string]: string }) { - const classUrl = schema2uri(className) - const query = `SELECT ?sub ?pred ?obj WHERE { ?sub <${typePredUri}> <${classUrl}>; ?pred ?obj. }` - const resp = await this.q(query) - const subjectUris = resp.results.bindings.map(b => b["sub"].value) - const uniqueSubjectUris = subjectUris.filter((x, i, self) => self.indexOf(x) === i) - return uniqueSubjectUris.map(subjectUri => { - const targetBindings = resp.results.bindings.filter(b => b["sub"].value == subjectUri) - const instance = bindings2object(targetBindings, arrayParameters) - instance["_key"] = uri2key(subjectUri) - return instance - }); - } - static async getInstance(className: string, key: string, arrayParameters?: { [_: string]: string }) { - const subject = `${classBaseUri(className)}${key}` - const query = `SELECT ?pred ?obj WHERE { <${subject}> ?pred ?obj }` - const resp = await this.q(query) - return bindings2object(resp.results.bindings, arrayParameters) - } - static async q(query: string) { - const response = await axios.get(process.env.SPARQL_ENDPOINT_URL!, { - params: { query }, - headers: { 'Content-Type': 'application/sparql-query+json' } - }) - return response.data as QueryResult - } -} \ No newline at end of file diff --git a/web/api/middleware/util.ts b/web/api/middleware/util.ts deleted file mode 100644 index 5fd5fd69..00000000 --- a/web/api/middleware/util.ts +++ /dev/null @@ -1,20 +0,0 @@ -export type KeyValue = { [key: string]: any; } - -export const sortInstanceList = (instanceList: KeyValue[], keysForSort: string[]) => { - return instanceList.sort( (a, b) => { - for(const key of keysForSort){ - if (a[key] < b[key]) return -1; - if (a[key] > b[key]) return 1; - } - return 0; - }); -} - -export const filterInstanceList = (instanceList: KeyValue[], params:KeyValue = {}) => { - let ret:KeyValue[] = [...instanceList] //deep copy - console.log(params) - Object.keys(params).forEach( key => { - ret = ret.filter( instance => instance[key].toString() === params[key] ) - }) - return ret -} \ No newline at end of file diff --git a/web/api/routes/character.ts b/web/api/routes/character.ts deleted file mode 100644 index 44856df2..00000000 --- a/web/api/routes/character.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Router } from "express"; -import Sparql from "../middleware/sparql" -import { sortInstanceList, filterInstanceList } from '../middleware/util' - -const router = Router(); - -const className = `Character` -const arrayParameters = {} -const sortBy = [ "episodeOfSeries", "話数" ] - -router.get("/", async (req, res) => { - const results = await Sparql.getInstanceList(className, arrayParameters) - const filterdResult= filterInstanceList(results, req.query) - const sortedResults = sortInstanceList(filterdResult, sortBy) - res.json({ - results: sortedResults - }) -}) - -router.get("/:key", async (req, res) => { - const key = req.params.key - const properties = await Sparql.getInstance(className, key, arrayParameters) - res.json(properties) -}) - -export default router; diff --git a/web/api/routes/episode.ts b/web/api/routes/episode.ts deleted file mode 100644 index fb6e38bc..00000000 --- a/web/api/routes/episode.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Router } from "express"; -import Sparql from "../middleware/sparql" -import { sortInstanceList, filterInstanceList } from '../middleware/util' - -const router = Router(); - -const className = `Episode` -const arrayParameters = { - 'livePerformed': 'lives' -} -const sortBy = [ "episodeOfSeries", "話数" ] - -router.get("/", async (req, res) => { - const results = await Sparql.getInstanceList(className, arrayParameters) - const filterdResult= filterInstanceList(results, req.query) - const sortedResults = sortInstanceList(filterdResult, sortBy) - res.json({ - results: sortedResults - }) -}) - -router.get("/:key", async (req, res) => { - const key = req.params.key - const properties = await Sparql.getInstance(className, key, arrayParameters) - res.json(properties) -}) - -export default router; diff --git a/web/api/routes/index.ts b/web/api/routes/index.ts deleted file mode 100644 index acc426fa..00000000 --- a/web/api/routes/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Router, Request, Response } from "express"; -import character from "./character"; -import episode from "./episode"; -import song from "./song"; -import live from "./live"; -import series from "./series"; -import shop from "./shop"; - -const routes = Router(); - -routes.use("/character", character); -routes.use("/episode", episode); -routes.use("/song", song); -routes.use("/live", live); -routes.use("/series", series); -routes.use("/shop", shop); - -export default routes; \ No newline at end of file diff --git a/web/api/routes/live.ts b/web/api/routes/live.ts deleted file mode 100644 index 7ad22ff8..00000000 --- a/web/api/routes/live.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Router } from "express"; -import Sparql from "../middleware/sparql" -import { sortInstanceList, filterInstanceList } from '../middleware/util' - -const router = Router(); - -const className = `Live` -const arrayParameters = {} -const sortBy:string[] = [] - -router.get("/", async (req, res) => { - const results = await Sparql.getInstanceList(className, arrayParameters) - const filterdResult= filterInstanceList(results, req.query) - const sortedResults = sortInstanceList(filterdResult, sortBy) - res.json({ - results: sortedResults - }) -}) - -router.get("/:key", async (req, res) => { - const key = req.params.key - const properties = await Sparql.getInstance(className, key, arrayParameters) - res.json(properties) -}) - -export default router; diff --git a/web/api/routes/series.ts b/web/api/routes/series.ts deleted file mode 100644 index 46fc0eb8..00000000 --- a/web/api/routes/series.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Router } from "express"; -import Sparql from "../middleware/sparql" -import { sortInstanceList, filterInstanceList } from '../middleware/util' - -const router = Router(); - -const className = `Series` -const arrayParameters = { - 'hasEpisode': 'episodes' -} -const sortBy:string[] = [] - -router.get("/", async (req, res) => { - const results = await Sparql.getInstanceList(className, arrayParameters) - const filterdResult= filterInstanceList(results, req.query) - const sortedResults = sortInstanceList(filterdResult, sortBy) - res.json({ - results: sortedResults - }) -}) - -router.get("/:key", async (req, res) => { - const key = req.params.key - const properties = await Sparql.getInstance(className, key, arrayParameters) - res.json(properties) -}) - -export default router; diff --git a/web/api/routes/shop.ts b/web/api/routes/shop.ts deleted file mode 100644 index e3b876e9..00000000 --- a/web/api/routes/shop.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Router } from "express"; -import Sparql from "../middleware/sparql" -import { sortInstanceList, filterInstanceList } from '../middleware/util' - -const router = Router(); - -const className = `Shop` -const arrayParameters = {} -const sortBy:string[] = [] - -router.get("/", async (req, res) => { - const results = await Sparql.getInstanceList(className, arrayParameters) - const filterdResult= filterInstanceList(results, req.query) - const sortedResults = sortInstanceList(filterdResult, sortBy) - res.json({ - results: sortedResults - }) -}) - -router.get("/:key", async (req, res) => { - const key = req.params.key - const properties = await Sparql.getInstance(className, key, arrayParameters) - res.json(properties) -}) - -export default router; diff --git a/web/api/routes/song.ts b/web/api/routes/song.ts deleted file mode 100644 index 6d871a33..00000000 --- a/web/api/routes/song.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Router } from "express"; -import Sparql from "../middleware/sparql" -import { sortInstanceList, filterInstanceList } from '../middleware/util' - -const router = Router(); - -const className = `Song` -const arrayParameters = { - 'performedInLive': 'lives' -} -const sortBy:string[] = [] - -router.get("/", async (req, res) => { - const results = await Sparql.getInstanceList(className, arrayParameters) - const filterdResult= filterInstanceList(results, req.query) - const sortedResults = sortInstanceList(filterdResult, sortBy) - res.json({ - results: sortedResults - }) -}) - -router.get("/:key", async (req, res) => { - const key = req.params.key - const properties = await Sparql.getInstance(className, key, arrayParameters) - res.json(properties) -}) - -export default router; diff --git a/web/app.vue b/web/app.vue new file mode 100644 index 00000000..f8eacfa7 --- /dev/null +++ b/web/app.vue @@ -0,0 +1,5 @@ + diff --git a/web/assets/buefy-like.scss b/web/assets/buefy-like.scss new file mode 100644 index 00000000..6c9bbbb4 --- /dev/null +++ b/web/assets/buefy-like.scss @@ -0,0 +1,42 @@ +// from https://github.com/buefy/buefy/blob/8f3d72b310dc5c142f46f4e26e3ab7e22f0cceec/docs/assets/scss/_variables.scss + +@import "bulma/sass/utilities/_all"; + +$primary: #7957d5; +$primary-dark: findLightColor(#7957d5); +$primary-light: findDarkColor(#7957d5); +$twitter: #4099FF; +$discord: #7289DA; +$bulma: #00D1B2; +$vuetelemetry: #0bdca0; + +$colors: ( + "white": ($white, $black), + "black": ($black, $white), + "light": ($light, $light-invert), + "grey": ($grey, $light-invert), + "dark": ($dark, $dark-invert), + "primary": ($primary, $white, $primary-dark, $primary-light), + "info": ($info, $info-invert, $info-light, $info-dark), + "success": ($success, $success-invert, $success-light, $success-dark), + "warning": ($warning, $warning-invert, $warning-light, $warning-dark), + "danger": ($danger, $danger-invert, $danger-light, $danger-dark), + "link": ($link, $link-invert, $link-light, $link-dark), + "twitter": ($twitter, $white, findLightColor($twitter), findDarkColor($twitter)), + "discord": ($discord, $white, findLightColor($discord), findDarkColor($discord)), + "bulma": ($bulma, $white, findLightColor($bulma), findDarkColor($bulma)), + "vuetelemetry": ($vuetelemetry, $white, findLightColor($vuetelemetry), findDarkColor($vuetelemetry)) +); + +$navbar-height: 3.25rem; +$navbar-item-active-color: $primary; + +$menu-item-active-background-color: $primary; +$menu-item-hover-background-color: $grey-lighter; + +$link: $primary; +$link-invert: $primary-invert; +$link-visited: $grey; +$link-focus-border: $primary; + +@import "bulma/bulma"; diff --git a/web/components/Gist.vue b/web/components/Gist.vue deleted file mode 100644 index c426756d..00000000 --- a/web/components/Gist.vue +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - diff --git a/web/components/GistItem.vue b/web/components/GistItem.vue new file mode 100644 index 00000000..20f9e3d5 --- /dev/null +++ b/web/components/GistItem.vue @@ -0,0 +1,81 @@ + + + + + + + diff --git a/web/components/SparqlResponseTable.vue b/web/components/SparqlResponseTable.vue index 8f28a1e8..8b72a1ac 100644 --- a/web/components/SparqlResponseTable.vue +++ b/web/components/SparqlResponseTable.vue @@ -1,51 +1,52 @@ + + - -