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 @@
+
+
-
-
-
+
+
+
+ {{ colName }}
+ |
+
+
+
+
- {{ props.row[col].value
- .replace('https://prismdb.takanakahiko.me/prism-schema.ttl#', 'prism:')
- .replace('http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdf:')
- .replace('http://www.w3.org/2000/01/rdf-schema#', 'rdfs:')
- .replace('https://prismdb.takanakahiko.me', '')
- }}
- {{ props.row[col].value }}
-
-
-
-
-
-
+
+ {{ term.value
+ .replace('https://prismdb.takanakahiko.me/prism-schema.ttl#', 'prism:')
+ .replace('http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdf:')
+ .replace('http://www.w3.org/2000/01/rdf-schema#', 'rdfs:')
+ .replace('https://prismdb.takanakahiko.me', '')
+ }}
+ {{ term.value }}
+ |
+
+
+
-
-