feat: admin component

pull/621/head
NGPixel 7 years ago
parent a4f00e795c
commit 0ccdf10c9d

@ -5,6 +5,7 @@
import CONSTANTS from './constants' import CONSTANTS from './constants'
import Vue from 'vue' import Vue from 'vue'
import VueRouter from 'vue-router'
import VueClipboards from 'vue-clipboards' import VueClipboards from 'vue-clipboards'
import VueSimpleBreakpoints from 'vue-simple-breakpoints' import VueSimpleBreakpoints from 'vue-simple-breakpoints'
import VeeValidate from 'vee-validate' import VeeValidate from 'vee-validate'
@ -79,6 +80,7 @@ window.graphQL = new ApolloClient({
// Initialize Vue Modules // Initialize Vue Modules
// ==================================== // ====================================
Vue.use(VueRouter)
Vue.use(VueClipboards) Vue.use(VueClipboards)
Vue.use(VueSimpleBreakpoints) Vue.use(VueSimpleBreakpoints)
Vue.use(localization.VueI18Next) Vue.use(localization.VueI18Next)
@ -102,6 +104,7 @@ Vue.prototype.Velocity = Velocity
// Register Vue Components // Register Vue Components
// ==================================== // ====================================
Vue.component('admin', () => import(/* webpackChunkName: "admin" */ './components/admin.vue'))
Vue.component('editor', () => import(/* webpackChunkName: "editor" */ './components/editor.vue')) Vue.component('editor', () => import(/* webpackChunkName: "editor" */ './components/editor.vue'))
Vue.component('login', () => import(/* webpackMode: "eager" */ './components/login.vue')) Vue.component('login', () => import(/* webpackMode: "eager" */ './components/login.vue'))
Vue.component('navigator', () => import(/* webpackMode: "eager" */ './components/navigator.vue')) Vue.component('navigator', () => import(/* webpackMode: "eager" */ './components/navigator.vue'))

@ -0,0 +1,19 @@
<template lang='pug'>
v-container(fluid, fill-height)
v-layout(row wrap)
v-flex(xs12)
.headline.blue--text.text--darken-2 Dashboard
.subheading.grey--text Coming soon
</template>
<script>
export default {
data() {
return {}
}
}
</script>
<style lang='scss'>
</style>

@ -0,0 +1,38 @@
<template lang='pug'>
v-container(fluid, fill-height, grid-list-lg)
v-layout(row wrap)
v-flex(xs12)
.headline.blue--text.text--darken-2 General
.subheading.grey--text Main settings of your wiki
v-form.pt-3
v-layout(row wrap)
v-flex(lg6 xs12)
v-card
v-toolbar(color='blue', dark, dense, flat)
v-toolbar-title
.subheading Site Info
v-card-text
v-text-field(label='Site Title', required, :counter='50')
v-text-field(label='Site Description', :counter='255')
v-flex(lg6 xs12)
v-card
v-toolbar(color='blue', dark, dense, flat)
v-toolbar-title
.subheading Site Branding
v-card-text
v-text-field(label='Site Title', required, :counter='50')
v-text-field(label='Site Description', :counter='255')
</template>
<script>
export default {
data() {
return {}
}
}
</script>
<style lang='scss'>
</style>

@ -0,0 +1,115 @@
<template lang='pug'>
v-app.admin
v-toolbar(color='black', dark, app, clipped-left, fixed, flat)
v-toolbar-side-icon(@click.native='')
v-toolbar-title
span.subheading Wiki.js
v-spacer
v-btn(icon)
v-icon(color='grey') search
v-btn(icon, @click.native='darkTheme = !darkTheme')
v-icon(color='grey') settings
v-menu(offset-y, min-width='300')
v-btn(icon, slot='activator')
v-icon(color='grey') account_circle
v-list.py-0
v-list-tile.py-3(avatar)
v-list-tile-avatar
v-avatar.red(:size='40'): span.white--text.subheading JD
v-list-tile-content
v-list-tile-title John Doe
v-list-tile-sub-title john.doe@example.com
v-divider.my-0
v-list-tile(@click='')
v-list-tile-action: v-icon(color='red') exit_to_app
v-list-tile-title Logout
v-navigation-drawer.pb-0(v-model='adminDrawerShown', app, fixed, clipped, left, permanent)
v-list(dense)
v-list-tile.pt-2(to='/dashboard')
v-list-tile-action: v-icon dashboard
v-list-tile-title Dashboard
v-divider.my-2
v-subheader Site
v-list-tile(to='/general')
v-list-tile-action: v-icon widgets
v-list-tile-title General
v-list-tile(to='/locale')
v-list-tile-action: v-icon language
v-list-tile-title Locale
v-list-tile(to='/stats')
v-list-tile-action: v-icon show_chart
v-list-tile-title Statistics
v-list-tile(to='/theme')
v-list-tile-action: v-icon palette
v-list-tile-title Theme
v-divider.my-2
v-subheader Users
v-list-tile(to='/groups')
v-list-tile-action: v-icon people
v-list-tile-title Groups
v-list-tile(to='/users')
v-list-tile-action: v-icon perm_identity
v-list-tile-title Users
v-divider.my-2
v-subheader Modules
v-list-tile(to='/auth')
v-list-tile-action: v-icon lock_outline
v-list-tile-title Authentication
v-list-tile(to='/rendering')
v-list-tile-action: v-icon system_update_alt
v-list-tile-title Content Rendering
v-list-tile(to='/editor')
v-list-tile-action: v-icon transform
v-list-tile-title Editor
v-list-tile(to='/logging')
v-list-tile-action: v-icon graphic_eq
v-list-tile-title Logging
v-list-tile(to='/storage')
v-list-tile-action: v-icon storage
v-list-tile-title Storage
v-divider.my-2
v-subheader System
v-list-tile(to='/system')
v-list-tile-action: v-icon tune
v-list-tile-title System Info
v-list-tile(to='/utilities')
v-list-tile-action: v-icon build
v-list-tile-title Utilities
v-list-tile(to='/dev')
v-list-tile-action: v-icon weekend
v-list-tile-title Developer Tools
v-content
router-view
v-footer.py-2.justify-center(app, fixed, color='grey lighten-3', inset, height='auto')
.caption.grey--text.text--darken-1 Powered by Wiki.js
</template>
<script>
import VueRouter from 'vue-router'
const router = new VueRouter({
mode: 'history',
base: '/a',
routes: [
{ path: '/', redirect: '/dashboard' },
{ path: '/dashboard', component: () => import(/* webpackChunkName: "admin" */ './admin-dashboard.vue') },
{ path: '/general', component: () => import(/* webpackChunkName: "admin" */ './admin-general.vue') }
]
})
export default {
data() {
return {
adminDrawerShown: true
}
},
router
}
</script>
<style lang='scss'>
</style>

@ -5,7 +5,7 @@
v-toolbar-title.white--text Sample Page v-toolbar-title.white--text Sample Page
.editor-code-toolbar .editor-code-toolbar
.editor-code-toolbar-group .editor-code-toolbar-group
.editor-code-toolbar-item .editor-code-toolbar-item(@click='toggleAround("**", "**")')
svg.icons.is-18(role='img') svg.icons.is-18(role='img')
title Bold title Bold
use(xlink:href='#fa-bold') use(xlink:href='#fa-bold')
@ -90,6 +90,11 @@
<script> <script>
import _ from 'lodash' import _ from 'lodash'
// ========================================
// IMPORTS
// ========================================
// Code Mirror
import { codemirror } from 'vue-codemirror' import { codemirror } from 'vue-codemirror'
import 'codemirror/lib/codemirror.css' import 'codemirror/lib/codemirror.css'
@ -120,6 +125,14 @@ import mdImsize from 'markdown-it-imsize'
// Prism (Syntax Highlighting) // Prism (Syntax Highlighting)
import Prism from '../libs/prism/prism.js' import Prism from '../libs/prism/prism.js'
// ========================================
// INIT
// ========================================
// Platform detection
const CtrlKey = /Mac/.test(navigator.platform) ? 'Cmd' : 'Ctrl'
// Markdown Instance
const md = new MarkdownIt({ const md = new MarkdownIt({
html: true, html: true,
breaks: true, breaks: true,
@ -138,6 +151,10 @@ const md = new MarkdownIt({
.use(mdMark) .use(mdMark)
.use(mdImsize) .use(mdImsize)
// ========================================
// HELPER FUNCTIONS
// ========================================
// Inject line numbers for preview scroll sync // Inject line numbers for preview scroll sync
let linesMap = [] let linesMap = []
function injectLineNumbers (tokens, idx, options, env, slf) { function injectLineNumbers (tokens, idx, options, env, slf) {
@ -153,6 +170,10 @@ function injectLineNumbers (tokens, idx, options, env, slf) {
md.renderer.rules.paragraph_open = injectLineNumbers md.renderer.rules.paragraph_open = injectLineNumbers
md.renderer.rules.heading_open = injectLineNumbers md.renderer.rules.heading_open = injectLineNumbers
// ========================================
// Vue Component
// ========================================
export default { export default {
components: { components: {
codemirror codemirror
@ -192,19 +213,24 @@ export default {
methods: { methods: {
onCmReady(cm) { onCmReady(cm) {
let self = this let self = this
cm.setSize(null, 'calc(100vh - 100px)') const keyBindings = {
cm.setOption('extraKeys', { 'F11' (cm) {
'F11'(cm) {
cm.setOption('fullScreen', !cm.getOption('fullScreen')) cm.setOption('fullScreen', !cm.getOption('fullScreen'))
}, },
'Esc'(cm) { 'Esc' (cm) {
if (cm.getOption('fullScreen')) cm.setOption('fullScreen', false) if (cm.getOption('fullScreen')) cm.setOption('fullScreen', false)
},
'Ctrl-S'(cm) {
self.$parent.save()
} }
}
_.set(keyBindings, `${CtrlKey}-S`, cm => {
self.$parent.save()
})
cm.setSize(null, 'calc(100vh - 100px)')
cm.setOption('extraKeys', keyBindings)
cm.on('cursorActivity', cm => {
this.toolbarSync(cm)
this.scrollSync(cm)
}) })
cm.on('cursorActivity', this.scrollSync)
this.onCmInput(this.code) this.onCmInput(this.code)
}, },
onCmInput: _.debounce(function (newContent) { onCmInput: _.debounce(function (newContent) {
@ -215,6 +241,17 @@ export default {
this.scrollSync(this.cm) this.scrollSync(this.cm)
}) })
}, 500), }, 500),
/**
* Update toolbar state
*/
toolbarSync(cm) {
const pos = cm.getCursor('start')
const token = cm.getTokenAt(pos)
if (!token.type) { return }
console.info(token)
},
/** /**
* Update scroll sync * Update scroll sync
*/ */
@ -232,7 +269,10 @@ export default {
this.Velocity(destElm, 'scroll', { offset: '-100', duration: 1000, container: this.$refs.editorPreview }) this.Velocity(destElm, 'scroll', { offset: '-100', duration: 1000, container: this.$refs.editorPreview })
} }
} }
}, 500) }, 500),
toggleAround (before, after) {
}
} }
} }
</script> </script>

@ -16,8 +16,8 @@ import _ from 'lodash'
export default { export default {
components: { components: {
editorCode: () => import(/* webpackChunkName: "editor-code" */ './editor-code.vue'), editorCode: () => import(/* webpackChunkName: "editor-code" */ './editor-code.vue'),
editorModalAccess: () => import(/* webpackChunkName: "editor-common" */ './editor-modal-access.vue'), editorModalAccess: () => import(/* webpackChunkName: "editor" */ './editor-modal-access.vue'),
editorModalProperties: () => import(/* webpackChunkName: "editor-common" */ './editor-modal-properties.vue') editorModalProperties: () => import(/* webpackChunkName: "editor" */ './editor-modal-properties.vue')
}, },
data() { data() {
return { return {

@ -20,28 +20,17 @@ html {
} }
} }
body { // body {
background-color: lighten(mc('blue-grey','50'), 5%); // background-color: lighten(mc('blue-grey','50'), 5%);
height: 100%; // height: 100%;
} // }
main { // main {
background-color: mc('blue','500'); // background-color: mc('blue','500');
background-image: linear-gradient(to bottom, mc('blue', '700') 0%, mc('blue', '500') 100%); // background-image: linear-gradient(to bottom, mc('blue', '700') 0%, mc('blue', '500') 100%);
padding: 50px; // padding: 50px;
min-height: 100vh; // min-height: 100vh;
} // }
a {
color: mc('indigo', '600');
text-decoration: none;
&:hover {
color: mc('indigo', '700');
text-decoration: underline;
}
}
// Container // Container
.container { .container {

@ -201,6 +201,7 @@
"vue-codemirror": "4.0.3", "vue-codemirror": "4.0.3",
"vue-hot-reload-api": "2.2.4", "vue-hot-reload-api": "2.2.4",
"vue-loader": "14.1.1", "vue-loader": "14.1.1",
"vue-router": "3.0.1",
"vue-simple-breakpoints": "1.0.3", "vue-simple-breakpoints": "1.0.3",
"vue-template-compiler": "2.5.13", "vue-template-compiler": "2.5.13",
"vuetify": "1.0.1", "vuetify": "1.0.1",

@ -8,6 +8,13 @@ router.get('/e/*', (req, res, next) => {
res.render('main/editor') res.render('main/editor')
}) })
/**
* Administration
*/
router.get(['/a', '/a/*'], (req, res, next) => {
res.render('main/admin')
})
/** /**
* View document * View document
*/ */

@ -0,0 +1,6 @@
extends ../master.pug
block body
body
#app
admin

@ -10412,6 +10412,10 @@ vue-loader@14.1.1:
vue-style-loader "^4.0.1" vue-style-loader "^4.0.1"
vue-template-es2015-compiler "^1.6.0" vue-template-es2015-compiler "^1.6.0"
vue-router@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.1.tgz#d9b05ad9c7420ba0f626d6500d693e60092cc1e9"
vue-simple-breakpoints@1.0.3: vue-simple-breakpoints@1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/vue-simple-breakpoints/-/vue-simple-breakpoints-1.0.3.tgz#0ae5b77af4cdbd948b514d2f485686174dc5ff5d" resolved "https://registry.yarnpkg.com/vue-simple-breakpoints/-/vue-simple-breakpoints-1.0.3.tgz#0ae5b77af4cdbd948b514d2f485686174dc5ff5d"

Loading…
Cancel
Save