Ver código fonte

refactor: editor + discard edits + save -> vue components

NGPixel 8 anos atrás
pai
commit
99ff1120c1

+ 4 - 0
client/js/app.js

@@ -33,6 +33,7 @@ import colorPickerComponent from './components/color-picker.vue'
 import loadingSpinnerComponent from './components/loading-spinner.vue'
 import loadingSpinnerComponent from './components/loading-spinner.vue'
 import modalCreatePageComponent from './components/modal-create-page.vue'
 import modalCreatePageComponent from './components/modal-create-page.vue'
 import modalCreateUserComponent from './components/modal-create-user.vue'
 import modalCreateUserComponent from './components/modal-create-user.vue'
+import modalDiscardPageComponent from './components/modal-discard-page.vue'
 import modalMovePageComponent from './components/modal-move-page.vue'
 import modalMovePageComponent from './components/modal-move-page.vue'
 import pageLoaderComponent from './components/page-loader.vue'
 import pageLoaderComponent from './components/page-loader.vue'
 import searchComponent from './components/search.vue'
 import searchComponent from './components/search.vue'
@@ -41,6 +42,7 @@ import treeComponent from './components/tree.vue'
 import adminProfileComponent from './pages/admin-profile.component.js'
 import adminProfileComponent from './pages/admin-profile.component.js'
 import adminSettingsComponent from './pages/admin-settings.component.js'
 import adminSettingsComponent from './pages/admin-settings.component.js'
 import contentViewComponent from './pages/content-view.component.js'
 import contentViewComponent from './pages/content-view.component.js'
+import editorComponent from './components/editor.component.js'
 import sourceViewComponent from './pages/source-view.component.js'
 import sourceViewComponent from './pages/source-view.component.js'
 
 
 // ====================================
 // ====================================
@@ -98,9 +100,11 @@ $(() => {
       anchor: anchorComponent,
       anchor: anchorComponent,
       colorPicker: colorPickerComponent,
       colorPicker: colorPickerComponent,
       contentView: contentViewComponent,
       contentView: contentViewComponent,
+      editor: editorComponent,
       loadingSpinner: loadingSpinnerComponent,
       loadingSpinner: loadingSpinnerComponent,
       modalCreatePage: modalCreatePageComponent,
       modalCreatePage: modalCreatePageComponent,
       modalCreateUser: modalCreateUserComponent,
       modalCreateUser: modalCreateUserComponent,
+      modalDiscardPage: modalDiscardPageComponent,
       modalMovePage: modalMovePageComponent,
       modalMovePage: modalMovePageComponent,
       pageLoader: pageLoaderComponent,
       pageLoader: pageLoaderComponent,
       search: searchComponent,
       search: searchComponent,

+ 49 - 53
client/js/components/editor.js → client/js/components/editor.component.js

@@ -1,32 +1,54 @@
 'use strict'
 'use strict'
 
 
-import $ from 'jquery'
-import Vue from 'vue'
-import _ from 'lodash'
-import filesize from 'filesize.js'
 import SimpleMDE from 'simplemde'
 import SimpleMDE from 'simplemde'
-import pageLoader from '../components/page-loader'
-
-// ====================================
-// Markdown Editor
-// ====================================
-
-module.exports = (alerts, pageEntryPath, socket) => {
-  if ($('#mk-editor').length === 1) {
-    Vue.filter('filesize', (v) => {
-      return _.toUpper(filesize(v))
-    })
+import filesize from 'filesize.js'
+import $ from 'jquery'
 
 
-    let mdeModalOpenState = false
-    let vueImage
-    let vueFile
-    let vueVideo
-    let vueCodeBlock
+let mde
 
 
-    let mde = new SimpleMDE({
+export default {
+  name: 'editor',
+  props: ['currentPath'],
+  filters: {
+    filesize(v) {
+      return this._.toUpper(filesize(v))
+    }
+  },
+  data() {
+    return {}
+  },
+  methods: {
+    save() {
+      let self = this
+      this.$http.put(window.location.href, {
+        markdown: mde.value()
+      }).then(resp => {
+        return resp.json()
+      }).then(resp => {
+        if (resp.ok) {
+          window.location.assign('/' + self.currentPath)
+        } else {
+          self.$store.dispatch('alert', {
+            style: 'red',
+            icon: 'square-cross',
+            msg: resp.msg
+          })
+        }
+      }).catch(err => {
+        self.$store.dispatch('alert', {
+          style: 'red',
+          icon: 'square-cross',
+          msg: 'Error: ' + err.body.msg
+        })
+      })
+    }
+  },
+  mounted() {
+    let self = this
+    mde = new SimpleMDE({
       autofocus: true,
       autofocus: true,
       autoDownloadFontAwesome: false,
       autoDownloadFontAwesome: false,
-      element: $('#mk-editor').get(0),
+      element: this.$refs.editorTextArea,
       placeholder: 'Enter Markdown formatted content here...',
       placeholder: 'Enter Markdown formatted content here...',
       spellChecker: false,
       spellChecker: false,
       status: false,
       status: false,
@@ -183,46 +205,20 @@ module.exports = (alerts, pageEntryPath, socket) => {
       }
       }
     })
     })
 
 
-    vueImage = require('./editor-image.js')(alerts, mde, mdeModalOpenState, socket)
-    vueFile = require('./editor-file.js')(alerts, mde, mdeModalOpenState, socket)
-    vueVideo = require('./editor-video.js')(mde, mdeModalOpenState)
-    vueCodeBlock = require('./editor-codeblock.js')(mde, mdeModalOpenState)
-
-    pageLoader.complete()
-
-    // -> Save
-
-    let saveCurrentDocument = (ev) => {
-      $.ajax(window.location.href, {
-        data: {
-          markdown: mde.value()
-        },
-        dataType: 'json',
-        method: 'PUT'
-      }).then((rData, rStatus, rXHR) => {
-        if (rData.ok) {
-          window.location.assign('/' + pageEntryPath) // eslint-disable-line no-undef
-        } else {
-          alerts.pushError('Something went wrong', rData.error)
-        }
-      }, (rXHR, rStatus, err) => {
-        alerts.pushError('Something went wrong', 'Save operation failed.')
-      })
-    }
-
-    $('.btn-edit-save, .btn-create-save').on('click', (ev) => {
-      saveCurrentDocument(ev)
-    })
+    // Save
 
 
+    this.$root.$on('editor-save', this.save)
     $(window).bind('keydown', (ev) => {
     $(window).bind('keydown', (ev) => {
       if (ev.ctrlKey || ev.metaKey) {
       if (ev.ctrlKey || ev.metaKey) {
         switch (String.fromCharCode(ev.which).toLowerCase()) {
         switch (String.fromCharCode(ev.which).toLowerCase()) {
           case 's':
           case 's':
             ev.preventDefault()
             ev.preventDefault()
-            saveCurrentDocument(ev)
+            self.save()
             break
             break
         }
         }
       }
       }
     })
     })
+
+    this.$store.dispatch('pageLoader/complete')
   }
   }
 }
 }

+ 43 - 0
client/js/components/modal-discard-page.vue

@@ -0,0 +1,43 @@
+<template lang="pug">
+  transition(:duration="400")
+    .modal(v-show='isShown', v-cloak)
+      transition(name='modal-background')
+        .modal-background(v-show='isShown')
+      .modal-container
+        transition(name='modal-content')
+          .modal-content(v-show='isShown')
+            header.is-orange Discard?
+            section
+              span(v-if='mode === "create"') Are you sure you want to leave this page and loose anything you wrote so far?
+              span(v-else) Are you sure you want to leave this page and loose any modifications?
+            footer
+              a.button.is-grey.is-outlined(v-on:click='stay') Stay on page
+              a.button.is-orange(v-on:click='discard') Discard
+</template>
+
+<script>
+  export default {
+    name: 'modal-discard-page',
+    props: ['mode', 'currentPath'],
+    data () {
+      return {}
+    },
+    computed: {
+      isShown () {
+        return this.$store.state.modalDiscardPage.shown
+      }
+    },
+    methods: {
+      stay: function () {
+        this.$store.dispatch('modalDiscardPage/close')
+      },
+      discard: function () {
+        if(this.mode === 'create') {
+          window.location.assign('/')
+        } else {
+          window.location.assign('/' + this.currentPath)
+        }
+      }
+    }
+  }
+</script>

+ 1 - 1
client/js/components/tree.vue

@@ -1,5 +1,5 @@
 <template lang="pug">
 <template lang="pug">
-  transition
+  .has-collapsable-nav
     ul.collapsable-nav(v-for='treeItem in tree', :class='{ "has-children": treeItem.hasChildren }', v-cloak)
     ul.collapsable-nav(v-for='treeItem in tree', :class='{ "has-children": treeItem.hasChildren }', v-cloak)
       li(v-for='page in treeItem.pages', :class='{ "is-active": page.isActive }')
       li(v-for='page in treeItem.pages', :class='{ "is-active": page.isActive }')
         a(v-on:click='mainAction(page)')
         a(v-on:click='mainAction(page)')

+ 4 - 0
client/js/store/index.js

@@ -3,8 +3,10 @@ import Vuex from 'vuex'
 
 
 import alert from './modules/alert'
 import alert from './modules/alert'
 import anchor from './modules/anchor'
 import anchor from './modules/anchor'
+import editor from './modules/editor'
 import modalCreatePage from './modules/modal-create-page'
 import modalCreatePage from './modules/modal-create-page'
 import modalCreateUser from './modules/modal-create-user'
 import modalCreateUser from './modules/modal-create-user'
+import modalDiscardPage from './modules/modal-discard-page'
 import modalMovePage from './modules/modal-move-page'
 import modalMovePage from './modules/modal-move-page'
 import pageLoader from './modules/page-loader'
 import pageLoader from './modules/page-loader'
 
 
@@ -25,8 +27,10 @@ export default new Vuex.Store({
   modules: {
   modules: {
     alert,
     alert,
     anchor,
     anchor,
+    editor,
     modalCreatePage,
     modalCreatePage,
     modalCreateUser,
     modalCreateUser,
+    modalDiscardPage,
     modalMovePage,
     modalMovePage,
     pageLoader
     pageLoader
   }
   }

+ 9 - 0
client/js/store/modules/editor.js

@@ -0,0 +1,9 @@
+'use strict'
+
+export default {
+  namespaced: true,
+  state: {},
+  getters: {},
+  mutations: {},
+  actions: {}
+}

+ 16 - 0
client/js/store/modules/modal-discard-page.js

@@ -0,0 +1,16 @@
+'use strict'
+
+export default {
+  namespaced: true,
+  state: {
+    shown: false
+  },
+  getters: {},
+  mutations: {
+    shownChange: (state, shownState) => { state.shown = shownState }
+  },
+  actions: {
+    open({ commit }) { commit('shownChange', true) },
+    close({ commit }) { commit('shownChange', false) }
+  }
+}

+ 7 - 17
server/views/pages/create.pug

@@ -4,29 +4,19 @@ block rootNavCenter
   h2.nav-item= t('header.createdoc')
   h2.nav-item= t('header.createdoc')
 
 
 block rootNavRight
 block rootNavRight
-  i.nav-item#notifload
+  loading-spinner
   span.nav-item
   span.nav-item
-    a.button.is-outlined.btn-create-discard
+    a.button.is-outlined(v-on:click='$store.dispatch("modalDiscardPage/open")')
       i.icon-cross
       i.icon-cross
       span= t('nav.discard')
       span= t('nav.discard')
-    a.button.btn-create-save
+    a.button(v-on:click='$root.$emit("editor-save")')
       i.icon-check
       i.icon-check
       span= t('nav.savedocument')
       span= t('nav.savedocument')
 
 
 block content
 block content
-
-  #page-type-create(data-entrypath=pageData.meta.path)
+  editor(inline-template, current-path=pageData.meta.path, v-cloak)
     .editor-area
     .editor-area
-      textarea#mk-editor= pageData.markdown
-
-  include ../modals/create-discard.pug
-  include ../modals/editor-link.pug
-  include ../modals/editor-image.pug
-  include ../modals/editor-file.pug
-  include ../modals/editor-video.pug
-  include ../modals/editor-codeblock.pug
+      textarea(ref='editorTextArea')= pageData.markdown
 
 
-block outside
-  #page-loader
-    i
-    span= t('loading.editor')
+  modal-discard-page(mode='create', current-path=pageData.meta.path)
+  page-loader(text=t('loading.editor'))

+ 7 - 17
server/views/pages/edit.pug

@@ -4,29 +4,19 @@ block rootNavCenter
   h2.nav-item= pageData.meta.title
   h2.nav-item= pageData.meta.title
 
 
 block rootNavRight
 block rootNavRight
-  i.nav-item#notifload
+  loading-spinner
   span.nav-item
   span.nav-item
-    a.button.is-outlined.btn-edit-discard
+    a.button.is-outlined(v-on:click='$store.dispatch("modalDiscardPage/open")')
       i.icon-cross
       i.icon-cross
       span= t('nav.discard')
       span= t('nav.discard')
-    a.button.btn-edit-save
+    a.button(v-on:click='$root.$emit("editor-save")')
       i.icon-check
       i.icon-check
       span= t('nav.savechanges')
       span= t('nav.savechanges')
 
 
 block content
 block content
-
-  #page-type-edit(data-entrypath=pageData.meta.path)
+  editor(inline-template, current-path=pageData.meta.path, v-cloak)
     .editor-area
     .editor-area
-      textarea#mk-editor= pageData.markdown
-
-  include ../modals/edit-discard.pug
-  include ../modals/editor-link.pug
-  include ../modals/editor-image.pug
-  include ../modals/editor-file.pug
-  include ../modals/editor-video.pug
-  include ../modals/editor-codeblock.pug
+      textarea(ref='editorTextArea')= pageData.markdown
 
 
-block outside
-  #page-loader
-    i
-    span= t('loading.editor')
+  modal-discard-page(mode='edit', current-path=pageData.meta.path)
+  page-loader(text=t('loading.editor'))

+ 1 - 1
server/views/pages/source.pug

@@ -23,7 +23,7 @@ block rootNavRight
 
 
 block content
 block content
 
 
-  source-view(inline-template, data-entrypath=pageData.meta.path, v-cloak)
+  source-view(inline-template, entrypath=pageData.meta.path, v-cloak)
     .ace-container
     .ace-container
       #source-display= pageData.markdown
       #source-display= pageData.markdown