瀏覽代碼

refactor: editor-video -> vue component + localization

NGPixel 8 年之前
父節點
當前提交
87e780bea7

+ 2 - 0
client/js/app.js

@@ -56,6 +56,7 @@ import alertComponent from './components/alert.vue'
 import anchorComponent from './components/anchor.vue'
 import colorPickerComponent from './components/color-picker.vue'
 import editorCodeblockComponent from './components/editor-codeblock.vue'
+import editorVideoComponent from './components/editor-video.vue'
 import loadingSpinnerComponent from './components/loading-spinner.vue'
 import modalCreatePageComponent from './components/modal-create-page.vue'
 import modalCreateUserComponent from './components/modal-create-user.vue'
@@ -157,6 +158,7 @@ $(() => {
       contentView: contentViewComponent,
       editor: editorComponent,
       editorCodeblock: editorCodeblockComponent,
+      editorVideo: editorVideoComponent,
       loadingSpinner: loadingSpinnerComponent,
       modalCreatePage: modalCreatePageComponent,
       modalCreateUser: modalCreateUserComponent,

+ 2 - 2
client/js/components/editor-codeblock.vue

@@ -88,7 +88,7 @@
               this.$store.dispatch('alert', {
                 style: 'red',
                 icon: 'square-cross',
-                msg: 'Error: Unable to load language syntax.'
+                msg: self.$t('editor.codeblockloadingerror')
               })
             }
           }).catch(err => {
@@ -110,7 +110,7 @@
         this.$store.dispatch('alert', {
           style: 'blue',
           icon: 'inbox',
-          msg: 'Your code block has been inserted.'
+          msg: self.$t('editor.codeblocksuccess')
         })
         this.cancel()
       }

+ 0 - 55
client/js/components/editor-video.js

@@ -1,55 +0,0 @@
-'use strict'
-
-import $ from 'jquery'
-import Vue from 'vue'
-import _ from 'lodash'
-
-const videoRules = {
-  'youtube': new RegExp(/(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|&v(?:i)?=))([^#&?]*).*/, 'i'),
-  'vimeo': new RegExp(/vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^/]*)\/videos\/|album\/(?:\d+)\/video\/|)(\d+)(?:$|\/|\?)/, 'i'),
-  'dailymotion': new RegExp(/(?:dailymotion\.com(?:\/embed)?(?:\/video|\/hub)|dai\.ly)\/([0-9a-z]+)(?:[-_0-9a-zA-Z]+(?:#video=)?([a-z0-9]+)?)?/, 'i')
-}
-
-module.exports = (mde, mdeModalOpenState) => {
-  // Vue Video instance
-
-  let vueVideo = new Vue({
-    el: '#modal-editor-video',
-    data: {
-      link: ''
-    },
-    methods: {
-      open: (ev) => {
-        $('#modal-editor-video').addClass('is-active')
-        $('#modal-editor-video input').focus()
-      },
-      cancel: (ev) => {
-        mdeModalOpenState = false // eslint-disable-line no-undef
-        $('#modal-editor-video').removeClass('is-active')
-        vueVideo.link = ''
-      },
-      insertVideo: (ev) => {
-        if (mde.codemirror.doc.somethingSelected()) {
-          mde.codemirror.execCommand('singleSelection')
-        }
-
-        // Guess video type
-
-        let videoType = _.findKey(videoRules, (vr) => {
-          return vr.test(vueVideo.link)
-        })
-        if (_.isNil(videoType)) {
-          videoType = 'video'
-        }
-
-        // Insert video tag
-
-        let videoText = '[video](' + vueVideo.link + '){.' + videoType + '}\n'
-
-        mde.codemirror.doc.replaceSelection(videoText)
-        vueVideo.cancel()
-      }
-    }
-  })
-  return vueVideo
-}

+ 94 - 0
client/js/components/editor-video.vue

@@ -0,0 +1,94 @@
+<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-green
+              span {{ $t('editor.videotitle') }}
+            section
+              label.label
+              p.control.is-fullwidth
+                input.input(type='text', placeholder='https://www.youtube.com/watch?v=xxxxxxxxxxx', v-model='link', ref='editorVideoInput', @keyup.enter='insertVideo', @keyup.esc='cancel')
+                span.help.is-red(v-show='isInvalid') {{ $t('editor.videonotsupported') }}
+              .note {{ $t('editor.videosupportedtitle') }}
+                ul
+                  li
+                    i.icon-youtube-play
+                    span Youtube
+                  li
+                    i.icon-vimeo
+                    span Vimeo
+                  li
+                    i.icon-film
+                    span Dailymotion
+                  li
+                    i.icon-video
+                    span {{ $t('editor.videoanymp4file') }}
+            footer
+              a.button.is-grey.is-outlined(v-on:click='cancel') {{ $t('editor.discard') }}
+              a.button.is-green(v-on:click='insertVideo') {{ $t('editor.videoinsert') }}
+</template>
+
+<script>
+  const videoRules = {
+    'youtube': new RegExp(/(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|&v(?:i)?=))([^#&?]*).*/, 'i'),
+    'vimeo': new RegExp(/vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^/]*)\/videos\/|album\/(?:\d+)\/video\/|)(\d+)(?:$|\/|\?)/, 'i'),
+    'dailymotion': new RegExp(/(?:dailymotion\.com(?:\/embed)?(?:\/video|\/hub)|dai\.ly)\/([0-9a-z]+)(?:[-_0-9a-zA-Z]+(?:#video=)?([a-z0-9]+)?)?/, 'i')
+  }
+
+  export default {
+    name: 'editor-video',
+    data () {
+      return {
+        link: '',
+        isInvalid: false
+      }
+    },
+    computed: {
+      isShown () {
+        return this.$store.state.editorVideo.shown
+      }
+    },
+    methods: {
+      init () {
+        let self = this
+        self.isInvalid = false
+        self._.delay(() => {
+          self.$refs.editorVideoInput.focus()
+        }, 100)
+      },
+      cancel () {
+        this.$store.dispatch('editorVideo/close')
+      },
+      insertVideo () {
+        let self = this
+
+        if (this._.isEmpty(self.link) || self.link.length < 5) {
+          this.isInvalid = true
+          return
+        }
+
+        let videoType = this._.findKey(videoRules, (vr) => {
+          return vr.test(self.link)
+        })
+        if (this._.isNil(videoType)) {
+          videoType = 'video'
+        }
+        let videoText = '[video](' + this.link + '){.' + videoType + '}\n'
+        this.$store.dispatch('editor/insert', videoText)
+        this.$store.dispatch('alert', {
+          style: 'blue',
+          icon: 'video',
+          msg: self.$t('editor.videosuccess')
+        })
+        this.cancel()
+      }
+    },
+    mounted () {
+      this.$root.$on('editorVideo/init', this.init)
+    }
+  }
+</script>

+ 1 - 3
client/js/components/editor.component.js

@@ -156,9 +156,7 @@ export default {
           {
             name: 'video',
             action: (editor) => {
-              // if (!mdeModalOpenState) {
-              //   vueVideo.open()
-              // }
+              self.$store.dispatch('editorVideo/open')
             },
             className: 'icon-video-camera2',
             title: 'Insert Video Player'

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

@@ -5,6 +5,7 @@ import alert from './modules/alert'
 import anchor from './modules/anchor'
 import editor from './modules/editor'
 import editorCodeblock from './modules/editor-codeblock'
+import editorVideo from './modules/editor-video'
 import modalCreatePage from './modules/modal-create-page'
 import modalCreateUser from './modules/modal-create-user'
 import modalDiscardPage from './modules/modal-discard-page'
@@ -30,6 +31,7 @@ export default new Vuex.Store({
     anchor,
     editor,
     editorCodeblock,
+    editorVideo,
     modalCreatePage,
     modalCreateUser,
     modalDiscardPage,

+ 19 - 0
client/js/store/modules/editor-video.js

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

+ 10 - 1
server/locales/en/browser.json

@@ -4,7 +4,16 @@
     "codeblocktitle": "Insert Code Block",
     "codeblockinsert": "Insert Code Block",
     "codeblocklanguage": "Language",
-    "codeblockloading": "Loading code syntax for {{name}}"
+    "codeblockloading": "Loading code syntax for {{name}}",
+    "codeblockloadingerror": "Error: Unable to load language syntax.",
+    "codeblocksuccess": "Your code block has been inserted.",
+    "videotitle": "Insert Video",
+    "videolinktitle": "Enter the link to the video to be embedded:",
+    "videoinsert": "Insert Video",
+    "videonotsupported": "This URL is invalid or not supported!",
+    "videosupportedtitle": "The following are supported:",
+    "videoanymp4file": "Any standard MP4 file",
+    "videosuccess": "The video code has been inserted."
   },
   "nav": {
     "home": "Home"

+ 0 - 28
server/views/modals/editor-video.pug

@@ -1,28 +0,0 @@
-
-.modal#modal-editor-video
-  .modal-background
-  .modal-container
-    .modal-content
-      header.is-green Insert Video Player
-      section
-        label.label Enter the link to the video to be embedded:
-        p.control.is-fullwidth
-          input.input(type='text', placeholder='https://www.youtube.com/watch?v=xxxxxxxxxxx', v-model='link')
-          span.help.is-red.is-hidden This URL is invalid or not supported!
-        .note The following are supported:
-          ul
-            li
-              i.icon-youtube-play
-              span Youtube
-            li
-              i.icon-vimeo
-              span Vimeo
-            li
-              i.icon-film
-              span Dailymotion
-            li
-              i.icon-video
-              span Any standard MP4 file
-      footer
-        a.button.is-grey.is-outlined(v-on:click='cancel') Discard
-        a.button.is-green(v-on:click='insertVideo') Insert Video

+ 2 - 0
server/views/pages/create.pug

@@ -18,5 +18,7 @@ block content
     .editor-area
       textarea(ref='editorTextArea')= pageData.markdown
 
+  editor-video
+  editor-codeblock
   modal-discard-page(mode='create', current-path=pageData.meta.path)
   page-loader(text=t('loading.editor'))

+ 1 - 0
server/views/pages/edit.pug

@@ -18,6 +18,7 @@ block content
     .editor-area
       textarea(ref='editorTextArea')= pageData.markdown
 
+  editor-video
   editor-codeblock
   modal-discard-page(mode='edit', current-path=pageData.meta.path)
   page-loader(text=t('loading.editor'))