feat: admin component
This commit is contained in:
		@@ -5,6 +5,7 @@
 | 
			
		||||
import CONSTANTS from './constants'
 | 
			
		||||
 | 
			
		||||
import Vue from 'vue'
 | 
			
		||||
import VueRouter from 'vue-router'
 | 
			
		||||
import VueClipboards from 'vue-clipboards'
 | 
			
		||||
import VueSimpleBreakpoints from 'vue-simple-breakpoints'
 | 
			
		||||
import VeeValidate from 'vee-validate'
 | 
			
		||||
@@ -79,6 +80,7 @@ window.graphQL = new ApolloClient({
 | 
			
		||||
// Initialize Vue Modules
 | 
			
		||||
// ====================================
 | 
			
		||||
 | 
			
		||||
Vue.use(VueRouter)
 | 
			
		||||
Vue.use(VueClipboards)
 | 
			
		||||
Vue.use(VueSimpleBreakpoints)
 | 
			
		||||
Vue.use(localization.VueI18Next)
 | 
			
		||||
@@ -102,6 +104,7 @@ Vue.prototype.Velocity = Velocity
 | 
			
		||||
// Register Vue Components
 | 
			
		||||
// ====================================
 | 
			
		||||
 | 
			
		||||
Vue.component('admin', () => import(/* webpackChunkName: "admin" */ './components/admin.vue'))
 | 
			
		||||
Vue.component('editor', () => import(/* webpackChunkName: "editor" */ './components/editor.vue'))
 | 
			
		||||
Vue.component('login', () => import(/* webpackMode: "eager" */ './components/login.vue'))
 | 
			
		||||
Vue.component('navigator', () => import(/* webpackMode: "eager" */ './components/navigator.vue'))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								client/components/admin-dashboard.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								client/components/admin-dashboard.vue
									
									
									
									
									
										Normal file
									
								
							@@ -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>
 | 
			
		||||
							
								
								
									
										38
									
								
								client/components/admin-general.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								client/components/admin-general.vue
									
									
									
									
									
										Normal file
									
								
							@@ -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>
 | 
			
		||||
							
								
								
									
										115
									
								
								client/components/admin.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								client/components/admin.vue
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
    .editor-code-toolbar
 | 
			
		||||
      .editor-code-toolbar-group
 | 
			
		||||
        .editor-code-toolbar-item
 | 
			
		||||
        .editor-code-toolbar-item(@click='toggleAround("**", "**")')
 | 
			
		||||
          svg.icons.is-18(role='img')
 | 
			
		||||
            title Bold
 | 
			
		||||
            use(xlink:href='#fa-bold')
 | 
			
		||||
@@ -90,6 +90,11 @@
 | 
			
		||||
<script>
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
 | 
			
		||||
// ========================================
 | 
			
		||||
// IMPORTS
 | 
			
		||||
// ========================================
 | 
			
		||||
 | 
			
		||||
// Code Mirror
 | 
			
		||||
import { codemirror } from 'vue-codemirror'
 | 
			
		||||
import 'codemirror/lib/codemirror.css'
 | 
			
		||||
 | 
			
		||||
@@ -120,6 +125,14 @@ import mdImsize from 'markdown-it-imsize'
 | 
			
		||||
// Prism (Syntax Highlighting)
 | 
			
		||||
import Prism from '../libs/prism/prism.js'
 | 
			
		||||
 | 
			
		||||
// ========================================
 | 
			
		||||
// INIT
 | 
			
		||||
// ========================================
 | 
			
		||||
 | 
			
		||||
// Platform detection
 | 
			
		||||
const CtrlKey = /Mac/.test(navigator.platform) ? 'Cmd' : 'Ctrl'
 | 
			
		||||
 | 
			
		||||
// Markdown Instance
 | 
			
		||||
const md = new MarkdownIt({
 | 
			
		||||
  html: true,
 | 
			
		||||
  breaks: true,
 | 
			
		||||
@@ -138,6 +151,10 @@ const md = new MarkdownIt({
 | 
			
		||||
  .use(mdMark)
 | 
			
		||||
  .use(mdImsize)
 | 
			
		||||
 | 
			
		||||
// ========================================
 | 
			
		||||
// HELPER FUNCTIONS
 | 
			
		||||
// ========================================
 | 
			
		||||
 | 
			
		||||
// Inject line numbers for preview scroll sync
 | 
			
		||||
let linesMap = []
 | 
			
		||||
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.heading_open = injectLineNumbers
 | 
			
		||||
 | 
			
		||||
// ========================================
 | 
			
		||||
// Vue Component
 | 
			
		||||
// ========================================
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: {
 | 
			
		||||
    codemirror
 | 
			
		||||
@@ -192,19 +213,24 @@ export default {
 | 
			
		||||
  methods: {
 | 
			
		||||
    onCmReady(cm) {
 | 
			
		||||
      let self = this
 | 
			
		||||
      cm.setSize(null, 'calc(100vh - 100px)')
 | 
			
		||||
      cm.setOption('extraKeys', {
 | 
			
		||||
        'F11'(cm) {
 | 
			
		||||
      const keyBindings = {
 | 
			
		||||
        'F11' (cm) {
 | 
			
		||||
          cm.setOption('fullScreen', !cm.getOption('fullScreen'))
 | 
			
		||||
        },
 | 
			
		||||
        'Esc'(cm) {
 | 
			
		||||
        'Esc' (cm) {
 | 
			
		||||
          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)
 | 
			
		||||
    },
 | 
			
		||||
    onCmInput: _.debounce(function (newContent) {
 | 
			
		||||
@@ -215,6 +241,17 @@ export default {
 | 
			
		||||
        this.scrollSync(this.cm)
 | 
			
		||||
      })
 | 
			
		||||
    }, 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
 | 
			
		||||
     */
 | 
			
		||||
@@ -232,7 +269,10 @@ export default {
 | 
			
		||||
          this.Velocity(destElm, 'scroll', { offset: '-100', duration: 1000, container: this.$refs.editorPreview })
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }, 500)
 | 
			
		||||
    }, 500),
 | 
			
		||||
    toggleAround (before, after) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -16,8 +16,8 @@ import _ from 'lodash'
 | 
			
		||||
export default {
 | 
			
		||||
  components: {
 | 
			
		||||
    editorCode: () => import(/* webpackChunkName: "editor-code" */ './editor-code.vue'),
 | 
			
		||||
    editorModalAccess: () => import(/* webpackChunkName: "editor-common" */ './editor-modal-access.vue'),
 | 
			
		||||
    editorModalProperties: () => import(/* webpackChunkName: "editor-common" */ './editor-modal-properties.vue')
 | 
			
		||||
    editorModalAccess: () => import(/* webpackChunkName: "editor" */ './editor-modal-access.vue'),
 | 
			
		||||
    editorModalProperties: () => import(/* webpackChunkName: "editor" */ './editor-modal-properties.vue')
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,28 +20,17 @@ html {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
	background-color: lighten(mc('blue-grey','50'), 5%);
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main {
 | 
			
		||||
  background-color: mc('blue','500');
 | 
			
		||||
  background-image: linear-gradient(to bottom, mc('blue', '700') 0%, mc('blue', '500') 100%);
 | 
			
		||||
  padding: 50px;
 | 
			
		||||
  min-height: 100vh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
	color: mc('indigo', '600');
 | 
			
		||||
	text-decoration: none;
 | 
			
		||||
 | 
			
		||||
	&:hover {
 | 
			
		||||
		color: mc('indigo', '700');
 | 
			
		||||
		text-decoration: underline;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
// body {
 | 
			
		||||
// 	background-color: lighten(mc('blue-grey','50'), 5%);
 | 
			
		||||
//   height: 100%;
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// main {
 | 
			
		||||
//   background-color: mc('blue','500');
 | 
			
		||||
//   background-image: linear-gradient(to bottom, mc('blue', '700') 0%, mc('blue', '500') 100%);
 | 
			
		||||
//   padding: 50px;
 | 
			
		||||
//   min-height: 100vh;
 | 
			
		||||
// }
 | 
			
		||||
// Container
 | 
			
		||||
 | 
			
		||||
.container {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user