NGPixel 7 роки тому
батько
коміт
0ccdf10c9d

+ 3 - 0
client/app.js

@@ -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 - 0
client/components/admin-dashboard.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>

+ 38 - 0
client/components/admin-general.vue

@@ -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 - 0
client/components/admin.vue

@@ -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>

+ 50 - 10
client/components/editor-code.vue

@@ -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>

+ 2 - 2
client/components/editor.vue

@@ -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 {

+ 11 - 22
client/scss/base/base.scss

@@ -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 {

+ 1 - 0
package.json

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

+ 7 - 0
server/controllers/common.js

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

+ 6 - 0
server/views/main/admin.pug

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

+ 4 - 0
yarn.lock

@@ -10412,6 +10412,10 @@ vue-loader@14.1.1:
     vue-style-loader "^4.0.1"
     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:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/vue-simple-breakpoints/-/vue-simple-breakpoints-1.0.3.tgz#0ae5b77af4cdbd948b514d2f485686174dc5ff5d"