frontend mockup

This commit is contained in:
Chris Sexton 2019-11-01 13:09:17 -04:00
parent 92b13fa3d8
commit 9b4e482e3a
23 changed files with 435 additions and 891 deletions

View File

@ -1,5 +0,0 @@
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

View File

@ -5,14 +5,13 @@ module.exports = {
}, },
'extends': [ 'extends': [
'plugin:vue/essential', 'plugin:vue/essential',
'@vue/standard', 'eslint:recommended'
'@vue/typescript'
], ],
rules: { rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}, },
parserOptions: { parserOptions: {
parser: '@typescript-eslint/parser' parser: 'babel-eslint'
} }
} }

View File

@ -8,35 +8,24 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"bootstrap": "^4.3.1",
"bootstrap-vue": "^2.0.4",
"core-js": "^3.3.2", "core-js": "^3.3.2",
"vue": "^2.6.10", "vue": "^2.6.10",
"vue-class-component": "^7.0.2",
"vue-property-decorator": "^8.3.0",
"vue-router": "^3.1.3", "vue-router": "^3.1.3",
"vuex": "^3.0.1" "vue2-ace-editor": "^0.0.15",
"vuex": "^3.0.1",
"brace": "latest"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^4.0.0", "@vue/cli-plugin-babel": "^4.0.0",
"@vue/cli-plugin-eslint": "^4.0.0", "@vue/cli-plugin-eslint": "^4.0.0",
"@vue/cli-plugin-router": "^4.0.0", "@vue/cli-plugin-router": "^4.0.0",
"@vue/cli-plugin-typescript": "^4.0.0",
"@vue/cli-plugin-vuex": "^4.0.0", "@vue/cli-plugin-vuex": "^4.0.0",
"@vue/cli-service": "^4.0.0", "@vue/cli-service": "^4.0.0",
"@vue/eslint-config-standard": "^4.0.0", "babel-eslint": "^10.0.3",
"@vue/eslint-config-typescript": "^4.0.0",
"eslint": "^5.16.0", "eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0", "eslint-plugin-vue": "^5.0.0",
"lint-staged": "^9.4.2",
"typescript": "~3.5.3",
"vue-template-compiler": "^2.6.10" "vue-template-compiler": "^2.6.10"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,vue,ts}": [
"vue-cli-service lint",
"git add"
]
} }
} }

View File

@ -1,9 +1,13 @@
<template> <template>
<div id="app"> <div id="app">
<div id="nav"> <b-navbar type="dark" variant="dark">
<router-link to="/">Home</router-link> | <b-navbar-brand>Cabinet</b-navbar-brand>
<router-link to="/about">About</router-link> <b-navbar-nav>
</div> <b-nav-item to="/">Home</b-nav-item>
<b-nav-item to="/console">Console</b-nav-item>
<b-nav-item to="/about">About</b-nav-item>
</b-navbar-nav>
</b-navbar>
<router-view/> <router-view/>
</div> </div>
</template> </template>
@ -13,7 +17,6 @@
font-family: 'Avenir', Helvetica, Arial, sans-serif; font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50; color: #2c3e50;
} }

View File

@ -0,0 +1,38 @@
<template>
<div>
<editor v-model="text" @init="editorInit" lang="asciidoc" theme="github" width="100%" height="500" />
</div>
</template>
<script>
export default {
name: "Editor",
data: function () {
return {
text: ''
}
},
props: {
content: String
},
components: {
editor: require('vue2-ace-editor')
},
watch: {
content: function(newValue) {
this.text = newValue
}
},
methods: {
editorInit: function () {
require('brace/ext/language_tools') //language extension prerequsite...
require('brace/mode/asciidoc') //language
require('brace/theme/github')
}
}
}
</script>
<style scoped>
</style>

View File

@ -9,7 +9,6 @@
<h3>Installed CLI Plugins</h3> <h3>Installed CLI Plugins</h3>
<ul> <ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li> <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li> <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li> <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li> <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
@ -33,12 +32,12 @@
</div> </div>
</template> </template>
<script lang="ts"> <script>
import { Component, Prop, Vue } from 'vue-property-decorator' export default {
name: 'HelloWorld',
@Component props: {
export default class HelloWorld extends Vue { msg: String
@Prop() private msg!: string; }
} }
</script> </script>

View File

@ -0,0 +1,78 @@
<template>
<div>
<b-container fluid>
<b-row>
<b-col>
<Editor :content="content" />
</b-col>
</b-row>
<b-row>
<b-col cols="10">
<label for="tagList">Tags</label>
</b-col>
</b-row>
<b-row>
<b-col cols="10">
<TagList id="tagList" :tags="tags" />
</b-col>
<b-col cols="1">
<b-button variant="primary">Save</b-button>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script>
import Editor from "./Editor";
import TagList from "./TagList";
export default {
name: "MainEditor",
props: {
slug: String
},
created() {
if (this.$props.slug) {
this.getFile(this.$props.slug)
}
},
data: function () {
return {
file: ''
}
},
computed: {
tags: function() {
if (this.file) {
return this.file.tags
}
return []
},
content: function () {
console.log('file:' + this.file)
if (this.file) {
return this.file.contents
}
return "= Main Editor"
}
},
watch: {
slug: function (newValue) {
this.getFile(newValue)
}
},
methods: {
getFile: function(slug) {
this.$store.dispatch('getFile', slug)
.then(file => {
this.file = file
})
}
},
components: {TagList, Editor}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,15 @@
<template>
<Editor content="= Scratchpad" />
</template>
<script>
import Editor from "./Editor";
export default {
name: "ScratchPad",
components: {Editor}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,35 @@
<template>
<b-container fluid>
<b-row v-for="item in results" v-bind:key="item.id">
<b-col>
<b-link
:to="{ name: 'console-slug', params: { slug: item.slug } }"
>{{item.title}}</b-link>
</b-col>
</b-row>
</b-container>
</template>
<script>
export default {
name: "SearchResults",
data: function() {
return {
results: []
}
},
created() {
this.getResults()
},
methods: {
getResults: function () {
console.log('getResults')
this.$store.dispatch('getSearchResults')
.then(res => {
console.log('then'+res)
this.results = res
})
}
}
}
</script>

View File

@ -0,0 +1,21 @@
<template>
<b-input type="text" placeholder="tags" :value="tagString"/>
</template>
<script>
export default {
name: "TagList",
props: {
tags: Array
},
computed: {
tagString: function() {
return this.tags.join(' ')
}
}
}
</script>
<style scoped>
</style>

View File

@ -3,8 +3,15 @@ import App from './App.vue'
import router from './router' import router from './router'
import store from './store' import store from './store'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.use(BootstrapVue)
new Vue({ new Vue({
router, router,
store, store,

View File

@ -11,6 +11,16 @@ const routes = [
name: 'home', name: 'home',
component: Home component: Home
}, },
{
path: '/console/:slug',
name: 'console-slug',
component: Console
},
{
path: '/console',
name: 'console',
component: Console
},
{ {
path: '/about', path: '/about',
name: 'about', name: 'about',
@ -18,11 +28,6 @@ const routes = [
// this generates a separate chunk (about.[hash].js) for this route // this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited. // which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/console',
name: 'console',
component: Console
} }
] ]

View File

@ -1,13 +0,0 @@
import Vue, { VNode } from 'vue'
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any
}
}
}

View File

@ -1,4 +0,0 @@
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}

View File

@ -0,0 +1,39 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
function getRandomInt(min, max) {
min = Math.ceil(min)
max = Math.floor(max)
return Math.floor(Math.random() * (max - min + 1)) + min
}
var files = {
'test-1': {id: 0, title: 'test 1', contents: '= test 1', slug: 'test-1', tags: ['a']},
'test-2': {id: 1, title: 'test 2', contents: '= test 2', slug: 'test-2', tags: ['b']},
'test-3': {id: 2, title: 'test 3', contents: '= test 3', slug: 'test-3', tags: ['a','b']},
'test-4': {id: 3, title: 'test 4', contents: '= test 4', slug: 'test-4', tags: ['c']}
}
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
getFile: function(_, slug) {
console.log('getFile('+slug+')')
return new Promise(function (resolve) {
setTimeout(() => resolve(files[slug]), getRandomInt(0, 1000))
})
},
getSearchResults: function () {
return new Promise(function (resolve) {
setTimeout(() => resolve(Object.values(files)), getRandomInt(0, 1000))
})
}
},
modules: {
}
})

View File

@ -1,15 +0,0 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})

View File

@ -1,18 +1,45 @@
<template> <template>
<div class="home"> <b-container fluid>
<img alt="Vue logo" src="../assets/logo.png"> <b-row>
<HelloWorld msg="Welcome to Your Vue.js App"/> <b-col>
</div> <h1>Console</h1>
</b-col>
</b-row>
<b-row>
<b-col md="5">
<h2>Scratchpad</h2>
<ScratchPad />
</b-col>
<b-col md="5">
<h2>Editor</h2>
<MainEditor :slug="$route.params.slug" />
</b-col>
<b-col md="2">
<h2>Search Results</h2>
<SearchResults />
</b-col>
</b-row>
</b-container>
</template> </template>
<script> <script>
// @ is an alias to /src // @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue' import MainEditor from "../components/MainEditor";
import ScratchPad from "../components/ScratchPad";
import SearchResults from "../components/SearchResults";
export default { export default {
name: 'home', name: 'home',
components: { components: {
HelloWorld SearchResults,
ScratchPad,
MainEditor
} }
} }
</script> </script>
<style scoped>
h2 {
font-size: large;
}
</style>

View File

@ -1,39 +0,0 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}

File diff suppressed because it is too large Load Diff

2
go.mod
View File

@ -4,11 +4,13 @@ go 1.13
require ( require (
github.com/gobuffalo/packr/v2 v2.7.1 github.com/gobuffalo/packr/v2 v2.7.1
github.com/gorilla/handlers v1.4.2
github.com/gorilla/mux v1.7.3 github.com/gorilla/mux v1.7.3
github.com/jmoiron/sqlx v1.2.0 github.com/jmoiron/sqlx v1.2.0
github.com/mattn/go-sqlite3 v1.11.0 github.com/mattn/go-sqlite3 v1.11.0
github.com/rs/zerolog v1.16.0 github.com/rs/zerolog v1.16.0
github.com/speps/go-hashids v2.0.0+incompatible github.com/speps/go-hashids v2.0.0+incompatible
github.com/stretchr/graceful v1.2.15 github.com/stretchr/graceful v1.2.15
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c // indirect
google.golang.org/appengine v1.6.5 // indirect google.golang.org/appengine v1.6.5 // indirect
) )

3
go.sum
View File

@ -15,6 +15,7 @@ github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8z
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@ -71,6 +72,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c h1:S/FtSvpNLtFBgjTqcKsRpsa6aVsI6iztaz1bQd9BJwE=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@ -1,6 +1,8 @@
package web package web
import ( import (
"net/http"
"os"
"time" "time"
"code.chrissexton.org/cws/cabinet/db" "code.chrissexton.org/cws/cabinet/db"
@ -10,6 +12,7 @@ import (
"github.com/speps/go-hashids" "github.com/speps/go-hashids"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/gorilla/handlers"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/stretchr/graceful" "github.com/stretchr/graceful"
) )
@ -36,11 +39,12 @@ func New(addr string, db *db.Database, box *packr.Box) *Web {
return w return w
} }
func (web *Web) routeSetup() *mux.Router { func (web *Web) routeSetup() http.Handler {
r := mux.NewRouter() r := mux.NewRouter()
//api := r.PathPrefix("/v1/").Subrouter() //api := r.PathPrefix("/v1/").Subrouter()
r.PathPrefix("/").HandlerFunc(web.indexHandler("/index.html")) r.PathPrefix("/").HandlerFunc(web.indexHandler("/index.html"))
return r loggedRouter := handlers.LoggingHandler(os.Stdout, r)
return loggedRouter
} }
func (web *Web) Serve() { func (web *Web) Serve() {

View File

@ -5,13 +5,16 @@ import (
"net/http" "net/http"
"path" "path"
"path/filepath" "path/filepath"
"strings"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
func (web *Web) indexHandler(entryPoint string) func(w http.ResponseWriter, r *http.Request) { func (web *Web) indexHandler(entryPoint string) func(w http.ResponseWriter, r *http.Request) {
entryPoint = path.Clean(strings.TrimPrefix(entryPoint, "/"))
fn := func(w http.ResponseWriter, r *http.Request) { fn := func(w http.ResponseWriter, r *http.Request) {
p := path.Clean(r.URL.Path) p := path.Clean(strings.TrimPrefix(r.URL.Path, "/"))
log.Debug().Str("path", p).Msg("requested path")
if web.box.Has(p) && !web.box.HasDir(p) { if web.box.Has(p) && !web.box.HasDir(p) {
f, err := web.box.Find(p) f, err := web.box.Find(p)
@ -32,9 +35,12 @@ func (web *Web) indexHandler(entryPoint string) func(w http.ResponseWriter, r *h
return return
} }
if f, err := web.box.Find(p); err != nil { log.Debug().Str("path", p).Str("entry", entryPoint).Msg("all handlers fell through, giving default")
if f, err := web.box.Find(entryPoint); err == nil {
write(w, f, p) write(w, f, p)
return return
} else {
log.Error().AnErr("err", err).Msgf("could not load any files %s", err)
} }
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)