catchall route handler with clean paths

This commit is contained in:
Jonathan Shook
2020-07-28 21:35:31 -05:00
parent 9a6ed2cf45
commit 5bf3df6672
9 changed files with 276 additions and 212 deletions

View File

@@ -3,7 +3,6 @@
<div class="menu">
<!-- active_category: {{active_category}} active_topic: {{active_topic}}-->
<!-- Use active_category and active_topic to select inactive -->
<v-list nav dense>
@@ -19,21 +18,15 @@
<!-- by category -->
<v-list-group v-for="(category,c) in categories" :key="c"
:value="active_category === category.category" active-class="isactive">
<!-- <nuxt-link :to="{path: category.category}">foo</nuxt-link>-->
<!-- <router-link :to="{path: category.category+'.html'}">-->
<template v-slot:activator>
<v-list-item-content>
<v-list-item-title @click="$nuxt.$router.push({path: category.category})">
<v-list-item-title @click="$nuxt.$router.push({path: category.categoryPath})">
{{category.categoryName}}
</v-list-item-title>
</v-list-item-content>
</template>
<!-- </router-link>-->
<v-list-item v-for="(doc, i) in category.docs" :key="i" link :to="doc.filename">
<!-- <router-link :to="{ name: 'docs-slug', params: {lockmenu:lockmenu}}">-->
<!-- <router-link :to="{ path: doc.filename}">-->
<v-list-item-title @click="$nuxt.$router.push({path: doc.filename})">{{doc.attributes.title}}</v-list-item-title>
<!-- </router-link>-->
<v-list-item-title @click="$nuxt.$router.push({path: doc.filename})">{{doc.attributes.title}}</v-list-item-title>
</v-list-item>
</v-list-group>

View File

@@ -51,6 +51,9 @@
code::before {
content: '';
}
code:after {
content: '';
}
pre {
padding: 5px;
@@ -60,9 +63,6 @@
padding-bottom: 10px;
}
code:after {
content: '';
}
code::after {
content: '';
}

View File

@@ -1,188 +1,219 @@
// asyncData in multiple mixins seems to be broken, or worse, working as designed
export default {
async asyncData(context) {
async asyncData(context) {
function fetchStatusHandler(response) {
if (response.status === 200) {
return response;
} else {
throw new Error(response.statusText);
}
function fetchStatusHandler(response) {
if (response.status === 200) {
return response;
} else {
throw new Error(response.statusText);
}
}
if (context.req) {
console.log("avoiding server-side async");
return;
}
let baseurl = document.location.href.split('/').slice(0, 3).join('/');
if (context.isDev && baseurl.includes(":3000")) {
console.log("Dev mode: remapping 3000 to 12345 for split dev environment.");
baseurl = baseurl.replace("3000", "12345");
}
let services = baseurl + "/services";
console.log("async loading get_categories data: context: " + context);
var fm = require('front-matter');
let paths = await fetch(services + "/docs/markdown.csv")
.then(res => {
return res.text()
})
.then(body => {
return body.split("\n")
})
.catch(err => {
console.log("error:" + err)
});
let imports = [];
let promises = [];
for (let index in paths) {
let key = paths[index];
if (key == null || key == "") {
continue
}
const [, name] = key.match(/(.+)\.md$/);
let detailName = key.split("/").filter(x => x.includes(".md"))[0];
detailName = detailName.substr(0, detailName.length - 3);
let categories = key.split("/").filter(x => !x.includes("."))
//const mdMeta = resolve(key);
promises.push(fetch(services + "/docs/markdown/" + key)
.then(res => res.text())
.then(body => {
return {
"rawMD": body,
"detailName": detailName,
"categories": categories,
"name": name
}
}));
}
var mdData = await Promise.all(
promises
);
for (var data of mdData) {
let rawMD = data.rawMD;
var mdMeta = fm(rawMD);
if (mdMeta.attributes == null || mdMeta.attributes.title == null) {
mdMeta.attributes.title = data.detailName;
}
if (typeof mdMeta.attributes.weight === 'undefined') {
mdMeta.attributes.weight = 0;
}
mdMeta.categories = data.categories;
// mdMeta.filename = encodeURIComponent(data.name);
console.log("data.name="+data.name);
mdMeta.filename = "/docs/"+data.name;
console.log("mdMeta.filename="+mdMeta.filename);
// console.log("mdMeta:" + JSON.stringify(mdMeta));
imports.push(mdMeta);
}
const categorySet = new Set();
imports.forEach(x => {
categorySet.add(x.categories.toString())
});
const categories = Array.from(categorySet).map(category => {
let docs = imports.filter(x => x.categories.toString() === category);
let summarydoc = docs.find(x => x.filename.endsWith('index'));
docs = docs.filter(x => !x.filename.endsWith('index'));
docs.forEach(d => delete d.body);
docs.sort((a, b) => a.attributes.weight - b.attributes.weight);
let weight = summarydoc ? summarydoc.attributes.weight : 0;
let categoryName = summarydoc ? (summarydoc.attributes.title ? summarydoc.attributes.title : category) : category;
let categoryPath = "/docs/" + category;
let entry = {category, categoryName, docs, summarydoc, weight, categoryPath}
console.log("category=> " + category);
return entry;
}
).sort((c1, c2) => c1.weight - c2.weight);
let active_category = '';
let active_category_name = '';
let active_topic = '';
// IFF no category was active, then make the first category active.
// fullPath: "/docs/designing_workloads%2F00_yaml_org"
// hash: ""
// name: "docs-all"
// params.pathMatch: "designing_workloads/00_yaml_org"
// path: "/docs/designing_workloads%2F00_yaml_org"
// query:
if (!context.params.slug && !context.route.path) {
console.log("params.slug was not defined");
active_category = categories[0].category;
active_category_name = categories[0].categoryName;
if (categories[0].summarydoc == null && categories[0].docs.length > 0) {
active_topic = categories[0].docs[0].filename;
}
} else if (context.route.path.startsWith("/docs/")) {
console.log("context.path docs path was defined:" + context.route.path)
let docpath = context.route.path.replace(/^(\/docs\/)/,"");
let parts = docpath.split(/\/|%2F/,2);
if (docpath==="") {
active_category = categories[0].category;
active_category_name = categories[0].categoryName;
} else {
active_category = parts[0];
console.log("==> docpath[" + docpath + "] active_category[" + active_category + "]");
active_topic = parts.length > 1 ? parts[1] : null;
}
} else {
let parts = context.params.slug.split("/", 2);
active_category = parts[0];
console.log("==> params.slug[" + context.params.slug + "] active_category[" + active_category + "]");
active_topic = parts.length > 1 ? parts[1] : null;
}
if (active_topic !== null && active_topic.endsWith(".html")) {
active_topic = active_topic.substr(0, active_topic.length - 5);
}
if (active_topic !== null && active_topic.endsWith(".md")) {
active_topic = active_topic.substr(0, active_topic.length - 3);
}
if (active_category !== null && active_category.endsWith(".html")) {
active_category = active_category.substr(0, active_category.length - 5);
}
if (active_category !== null && active_category.endsWith(".md")) {
active_category = active_category.substr(0, active_category.length - 3);
}
let foundCategory = categories.find(c => c.category === active_category);
if (foundCategory != undefined) {
active_category_name = categories.find(c => c.category === active_category).categoryName;
}
console.log("==> active category[" + active_category + "] topic[" + active_topic + "]");
// At this point, we have an active category or even a topic.
// We're all in on loading markdown, but which one?
let docname = active_category;
console.log("docname (active_category only): " + docname);
if (active_topic) {
docname += '/' + active_topic + '.md';
} else {
docname += '/' + 'index.md';
}
console.log("docname: " + docname);
var fm = require('front-matter');
let docbody = "";
let mdPath = services + '/docs/markdown/' + docname;
let rawMD = await fetch(services + "/docs/markdown/" + docname)
.then(fetchStatusHandler)
.then(res => res.text())
.then(body => docbody = body)
.catch(function (error) {
console.log(error);
});
;
var markdown = fm(rawMD);
// console.log("markdown_body:\n" + markdown.body);
let mydata = {
markdown_attr: markdown.attributes,
markdown_body: markdown.body,
categories: categories,
active_category: active_category,
active_category_name: active_category_name,
active_topic: active_topic
};
return mydata;
}
if (context.req) {
console.log("avoiding server-side async");
return;
}
let baseurl = document.location.href.split('/').slice(0,3).join('/');
if (context.isDev && baseurl.includes(":3000")) {
console.log("Dev mode: remapping 3000 to 12345 for split dev environment.");
baseurl = baseurl.replace("3000","12345");
}
let services = baseurl + "/services";
console.log("async loading get_categories data: context: " + context);
var fm = require('front-matter');
let paths = await fetch(services+"/docs/markdown.csv")
.then(res => {
return res.text()
})
.then(body => {
return body.split("\n")
})
.catch(err => {
console.log("error:" + err)
});
let imports = [];
let promises = [];
for (let index in paths) {
let key = paths[index];
if (key == null || key == "") {
continue
}
const [, name] = key.match(/(.+)\.md$/);
let detailName = key.split("/").filter(x => x.includes(".md"))[0];
detailName = detailName.substr(0, detailName.length - 3);
let categories = key.split("/").filter(x => !x.includes("."))
//const mdMeta = resolve(key);
promises.push(fetch(services + "/docs/markdown/" + key)
.then(res => res.text())
.then(body => {
return {
"rawMD": body,
"detailName": detailName,
"categories": categories,
"name": name
}
}));
}
var mdData = await Promise.all(
promises
);
for(var data of mdData){
let rawMD = data.rawMD;
var mdMeta = fm(rawMD);
if (mdMeta.attributes == null || mdMeta.attributes.title == null) {
mdMeta.attributes.title = data.detailName;
}
if (typeof mdMeta.attributes.weight === 'undefined') {
mdMeta.attributes.weight = 0;
}
mdMeta.categories = data.categories;
mdMeta.filename = encodeURIComponent(data.name);
//console.log("mdMeta:" + JSON.stringify(mdMeta));
imports.push(mdMeta);
}
const categorySet = new Set();
imports.forEach(x => {
categorySet.add(x.categories.toString())
});
const categories = Array.from(categorySet).map(category => {
let docs = imports.filter(x => x.categories.toString() === category);
let summarydoc = docs.find(x => x.filename.endsWith('index'));
docs = docs.filter(x=>!x.filename.endsWith('index'));
docs.forEach(d => delete d.body);
docs.sort((a, b) => a.attributes.weight - b.attributes.weight);
let weight = summarydoc ? summarydoc.attributes.weight : 0;
let categoryName = summarydoc ? ( summarydoc.attributes.title ? summarydoc.attributes.title : category ) : category;
return {category, categoryName, docs, summarydoc, weight}
}
).sort((c1,c2) => c1.weight - c2.weight);
let active_category='';
let active_category_name='';
let active_topic='';
// IFF no category was active, then make the first category active.
if (!context.params.slug) {
console.log("params.slug was not defined");
active_category=categories[0].category;
active_category_name=categories[0].categoryName;
if (categories[0].summarydoc == null && categories[0].docs.length>0) {
active_topic = categories[0].docs[0].filename;
}
} else {
let parts = context.params.slug.split("/",2);
active_category=parts[0];
console.log("==> params.slug[" + context.params.slug + "] active_category[" + active_category + "]");
active_topic = parts.length>1 ? parts[1] : null;
}
if (active_topic !== null && active_topic.endsWith(".html")) {
active_topic = active_topic.substr(0,active_topic.length-5);
}
if (active_topic !== null && active_topic.endsWith(".md")) {
active_topic = active_topic.substr(0,active_topic.length-3);
}
if (active_category !== null && active_category.endsWith(".html")) {
active_category = active_category.substr(0,active_category.length-5);
}
if (active_category !== null && active_category.endsWith(".md")) {
active_category = active_category.substr(0,active_category.length-3);
}
let foundCategory = categories.find(c => c.category === active_category);
if (foundCategory != undefined){
active_category_name = categories.find(c => c.category === active_category).categoryName;
}
console.log("==> active category[" + active_category + "] topic["+ active_topic +"]");
// At this point, we have an active category or even a topic.
// We're all in on loading markdown, but which one?
let docname = active_category;
if (active_topic) {
docname += '/' + active_topic + '.md';
} else {
docname += '/' + 'index.md';
}
console.log("docname: " + docname);
var fm = require('front-matter');
let docbody = "";
let mdPath = services + '/docs/markdown/' + docname;
let rawMD = await fetch(services + "/docs/markdown/" + docname)
.then(fetchStatusHandler)
.then(res => res.text())
.then(body => docbody = body)
.catch(function(error) {
console.log(error);
});;
var markdown = fm(rawMD);
// console.log("markdown_body:\n" + markdown.body);
let mydata = {
markdown_attr: markdown.attributes,
markdown_body: markdown.body,
categories: categories,
active_category: active_category,
active_category_name : active_category_name,
active_topic: active_topic
};
return mydata;
}
}

View File

@@ -4,6 +4,7 @@ var glob = require('glob');
var path = require('path');
export default {
// target: 'static',
mode: 'spa',
/*
** Headers of the page
@@ -97,6 +98,9 @@ export default {
** Build configuration
*/
build: {
html: {
minify: false
},
// analyze: {
// analyzerMode: 'static'
// },
@@ -117,8 +121,8 @@ export default {
}
var dynamicRoutes = getDynamicPaths({
'/docs': 'docs/*.md',
'/#/docs': '/#/docs/*.md'
// '/docs': 'docs/*.md',
// '/#/docs': '/#/docs/*.md'
});
function getDynamicPaths(urlFilepathTable) {

View File

@@ -15,8 +15,9 @@
"@nuxtjs/vuetify": "^1.11.0",
"front-matter": "^3.1.0",
"markdown-it-smartarrows": "^1.0.1",
"markdown-it-vue": "^1.0.11",
"markdown-it-vue": "^1.1.3",
"markdown-it-highlight": "^0.2.0",
"node-fetch": "^2.6.0",
"nuxt": "^2.12.0"
"nuxt": "^2.14.0"
}
}

View File

@@ -16,9 +16,9 @@
</v-app-bar>
<v-content>
<v-main>
<v-container>
<v-row align="stretch">
<v-row align-content="start" align="start" justify="start">
<div>{{testdata}}</div>
<div class="Doc">
@@ -32,7 +32,7 @@
</v-row>
</v-container>
</v-content>
</v-main>
<v-footer app dark color="secondary">
<span>&copy; 2020</span>
@@ -91,3 +91,37 @@
}
}
</script>
<style>
.container {
margin: 0 auto;
min-height: 60vh;
display: flex;
justify-content: flex-start;
align-items: flex-start;
text-align: start;
margin-left: 15px;
}
.title {
font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
display: block;
font-weight: 300;
font-size: 100px;
color: #35495e;
letter-spacing: 1px;
}
.subtitle {
font-weight: 300;
font-size: 42px;
color: #526488;
word-spacing: 5px;
padding-bottom: 15px;
}
.links {
padding-top: 15px;
}
</style>

View File

@@ -15,9 +15,9 @@
</v-toolbar-items>
</v-app-bar>
<v-content>
<v-main>
<v-container>
<v-row align="stretch">
<v-row>
<div>{{testdata}}</div>
<div class="Doc">
@@ -31,7 +31,7 @@
</v-row>
</v-container>
</v-content>
</v-main>
<v-footer app dark color="secondary">
<span>&copy; 2020</span>
@@ -95,9 +95,10 @@
margin: 0 auto;
min-height: 60vh;
display: flex;
justify-content: center;
justify-content: flex-start;
align-items: center;
text-align: center;
margin-left: 15px;
}
.title {

View File

@@ -1,9 +1,9 @@
<template>
<!-- https://github.com/Microsoft/vscode-recipes/tree/master/vuejs-cli -->
<div class="container">
<div class="container" style="justify-content: center; align-content: center; display: flex; width: 100%; margin-left: unset">
<!-- <recursive-menu/>-->
<div>
<logo/>
<div style="justify-content: center" align="middle">
<logo align="middle" style="justify-content: center; align-content: center"></logo>
<h1 class="title">nosqlbench</h1>
<h2 class="subtitle">open source, pluggable, nosql benchmarking suite</h2>
<div class="links">

View File

@@ -13,7 +13,7 @@
justify-center
align-center>
<v-content>
<v-main>
<v-container fluid v-if="enabled">
<v-select
@@ -36,7 +36,7 @@
md="10"
lg="10"
>
<v-card>
<v-card-title>
{{ workloadName }}
@@ -66,8 +66,8 @@
</v-container>
</v-content>
</v-main>
</v-layout>
<v-footer app dark color="secondary">