Browse Source

feat: editor page props UI improvements + codemirror fix

Nick 5 years ago
parent
commit
8e80b7471d

+ 14 - 12
client/components/admin/admin-dashboard.vue

@@ -56,7 +56,7 @@
         v-card.radius-7.animated.fadeInUp.wait-p2s
           v-toolbar(:color='$vuetify.theme.dark ? `grey darken-2` : `grey lighten-5`', dense, flat)
             v-spacer
-            .overline Recent Pages
+            .overline {{$t('admin:dashboard.recentPages')}}
             v-spacer
           v-data-table.pb-2(
             :items='recentPages'
@@ -72,27 +72,28 @@
                 td.admin-pages-path
                   v-chip(label, small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`') {{ props.item.locale }}
                   span.ml-2.grey--text(:class='$vuetify.theme.dark ? `text--lighten-1` : `text--darken-2`') / {{ props.item.path }}
-                td.text-right(width='250') {{ props.item.updatedAt | moment('calendar') }}
+                td.text-right.caption(width='250') {{ props.item.updatedAt | moment('calendar') }}
       v-flex(xs12, xl6)
         v-card.radius-7.animated.fadeInUp.wait-p4s
           v-toolbar(:color='$vuetify.theme.dark ? `grey darken-2` : `grey lighten-5`', dense, flat)
             v-spacer
-            .overline Most Popular Pages
+            .overline {{$t('admin:dashboard.mostPopularPages')}}
             v-spacer
           v-data-table.pb-2(
             :items='popularPages'
+            :headers='headers'
+            :loading='popularPagesLoading'
             hide-default-footer
             hide-default-header
             )
-            template(slot='items' slot-scope='props')
-              td(width='20', style='padding-right: 0;'): v-icon insert_drive_file
-              td
-                .body-2.primary--text {{ props.item.title }}
-                .caption.grey--text.text--darken-2 {{ props.item.description }}
-              td.caption /{{ props.item.path }}
-              td.grey--text.text--darken-2(width='250')
-                .caption: strong Updated {{ props.item.updatedAt | moment('from') }}
-                .caption Created {{ props.item.createdAt | moment('calendar') }}
+            template(slot='item', slot-scope='props')
+              tr.is-clickable(:active='props.selected', @click='$router.push(`/pages/` + props.item.id)')
+                td
+                  .body-2: strong {{ props.item.title }}
+                td.admin-pages-path
+                  v-chip(label, small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`') {{ props.item.locale }}
+                  span.ml-2.grey--text(:class='$vuetify.theme.dark ? `text--lighten-1` : `text--darken-2`') / {{ props.item.path }}
+                td.text-right.caption(width='250') {{ props.item.updatedAt | moment('calendar') }}
 
       v-flex(xs12)
         v-card.dashboard-contribute.animated.fadeInUp.wait-p4s
@@ -123,6 +124,7 @@ export default {
       recentPages: [],
       recentPagesLoading: false,
       popularPages: [],
+      popularPagesLoading: false,
       headers: [
         { text: 'ID', value: 'id', width: 80 },
         { text: 'Title', value: 'title' },

+ 1 - 4
client/components/editor/editor-code.vue

@@ -13,7 +13,7 @@ import _ from 'lodash'
 // ========================================
 
 // Code Mirror
-import { codemirror } from 'vue-codemirror'
+import CodeMirror from 'codemirror'
 import 'codemirror/lib/codemirror.css'
 
 // Language
@@ -41,9 +41,6 @@ const CtrlKey = /Mac/.test(navigator.platform) ? 'Cmd' : 'Ctrl'
 // ========================================
 
 export default {
-  components: {
-    codemirror
-  },
   data() {
     return {
       code: '<h1>Title</h1>\n\n<p>Some text here</p>',

+ 92 - 72
client/components/editor/editor-markdown.vue

@@ -160,7 +160,7 @@
                 v-icon(:color='helpShown ? `teal` : ``') mdi-help-circle
             span {{$t('editor:markup.markdownFormattingHelp')}}
       .editor-markdown-editor
-        codemirror(ref='cm', v-model='code', :options='cmOptions', @ready='onCmReady', @input='onCmInput')
+        textarea(ref='cm')
       transition(name='editor-markdown-preview')
         .editor-markdown-preview(v-if='previewShown')
           .editor-markdown-preview-content.contents(ref='editorPreviewContainer')
@@ -188,7 +188,7 @@ import markdownHelp from './markdown/help.vue'
 // ========================================
 
 // Code Mirror
-import { codemirror } from 'vue-codemirror'
+import CodeMirror from 'codemirror'
 import 'codemirror/lib/codemirror.css'
 
 // Language
@@ -261,6 +261,7 @@ function injectLineNumbers (tokens, idx, options, env, slf) {
 }
 md.renderer.rules.paragraph_open = injectLineNumbers
 md.renderer.rules.heading_open = injectLineNumbers
+md.renderer.rules.blockquote_open = injectLineNumbers
 
 // ========================================
 // Vue Component
@@ -268,7 +269,6 @@ md.renderer.rules.heading_open = injectLineNumbers
 
 export default {
   components: {
-    codemirror,
     markdownHelp
   },
   props: {
@@ -280,22 +280,7 @@ export default {
   data() {
     return {
       fabInsertMenu: false,
-      code: this.$store.get('editor/content'),
-      cmOptions: {
-        tabSize: 2,
-        mode: 'text/markdown',
-        theme: 'wikijs-dark',
-        lineNumbers: true,
-        lineWrapping: true,
-        line: true,
-        styleActiveLine: true,
-        highlightSelectionMatches: {
-          annotateScrollbar: true
-        },
-        viewportMargin: 50,
-        inputStyle: 'contenteditable',
-        allowDropFileTypes: ['image/jpg', 'image/png', 'image/svg', 'image/jpeg', 'image/gif']
-      },
+      cm: null,
       cursorPos: { ch: 0, line: 1 },
       previewShown: true,
       previewHTML: '',
@@ -303,9 +288,6 @@ export default {
     }
   },
   computed: {
-    cm() {
-      return this.$refs.cm.codemirror
-    },
     isMobile() {
       return this.$vuetify.breakpoint.smAndDown
     },
@@ -325,53 +307,6 @@ export default {
       this.activeModal = ''
       this.helpShown = false
     },
-    onCmReady(cm) {
-      const keyBindings = {
-        'F11' (cm) {
-          cm.setOption('fullScreen', !cm.getOption('fullScreen'))
-        },
-        'Esc' (cm) {
-          if (cm.getOption('fullScreen')) cm.setOption('fullScreen', false)
-        }
-      }
-      _.set(keyBindings, `${CtrlKey}-S`, cm => {
-        this.save()
-        return false
-      })
-      _.set(keyBindings, `${CtrlKey}-B`, cm => {
-        this.toggleMarkup({ start: `**` })
-        return false
-      })
-      _.set(keyBindings, `${CtrlKey}-I`, cm => {
-        this.toggleMarkup({ start: `*` })
-        return false
-      })
-      _.set(keyBindings, `${CtrlKey}-Alt-Right`, cm => {
-        let lvl = this.getHeaderLevel(cm)
-        if (lvl >= 6) { lvl = 5 }
-        this.setHeaderLine(lvl + 1)
-        return false
-      })
-      _.set(keyBindings, `${CtrlKey}-Alt-Left`, cm => {
-        let lvl = this.getHeaderLevel(cm)
-        if (lvl <= 1) { lvl = 2 }
-        this.setHeaderLine(lvl - 1)
-        return false
-      })
-
-      if (this.$vuetify.breakpoint.mdAndUp) {
-        cm.setSize(null, 'calc(100vh - 112px - 24px)')
-      } else {
-        cm.setSize(null, 'calc(100vh - 112px - 16px)')
-      }
-      cm.setOption('extraKeys', keyBindings)
-      cm.on('cursorActivity', cm => {
-        this.positionSync(cm)
-        this.scrollSync(cm)
-      })
-      cm.on('paste', this.onCmPaste)
-      this.onCmInput(this.code)
-    },
     onCmInput: _.debounce(function (newContent) {
       linesMap = []
       this.$store.set('editor/content', newContent)
@@ -497,7 +432,7 @@ export default {
       let currentLine = cm.getCursor().line
       if (currentLine < 3) {
         this.Velocity(this.$refs.editorPreview, 'stop', true)
-        this.Velocity(this.$refs.editorPreview.firstChild, 'scroll', { offset: '-50', duration: 1000, container: this.$refs.editorPreview })
+        this.Velocity(this.$refs.editorPreview.firstChild, 'scroll', { offset: '-50', duration: 1000, container: this.$refs.editorPreviewContainer })
       } else {
         let closestLine = _.findLast(linesMap, n => n <= currentLine)
         let destElm = this.$refs.editorPreview.querySelector(`[data-line='${closestLine}']`)
@@ -513,9 +448,94 @@ export default {
     },
     toggleFullscreen () {
       this.cm.setOption('fullScreen', true)
+    },
+    refresh() {
+      this.$nextTick(() => {
+        this.cm.refresh()
+      })
     }
   },
   mounted() {
+    // Initialize CodeMirror
+
+    this.cm = CodeMirror.fromTextArea(this.$refs.cm, {
+      tabSize: 2,
+      mode: 'text/markdown',
+      theme: 'wikijs-dark',
+      lineNumbers: true,
+      lineWrapping: true,
+      line: true,
+      styleActiveLine: true,
+      highlightSelectionMatches: {
+        annotateScrollbar: true
+      },
+      viewportMargin: 50,
+      inputStyle: 'contenteditable',
+      allowDropFileTypes: ['image/jpg', 'image/png', 'image/svg', 'image/jpeg', 'image/gif']
+    })
+    this.cm.setValue(this.$store.get('editor/content'))
+    this.cm.on('change', c => {
+      this.$store.set('editor/content', c.getValue())
+      this.onCmInput(this.$store.get('editor/content'))
+    })
+    if (this.$vuetify.breakpoint.mdAndUp) {
+      this.cm.setSize(null, 'calc(100vh - 112px - 24px)')
+    } else {
+      this.cm.setSize(null, 'calc(100vh - 112px - 16px)')
+    }
+
+    // Set Keybindings
+
+    const keyBindings = {
+      'F11' (c) {
+        c.setOption('fullScreen', !c.getOption('fullScreen'))
+      },
+      'Esc' (c) {
+        if (c.getOption('fullScreen')) c.setOption('fullScreen', false)
+      }
+    }
+    _.set(keyBindings, `${CtrlKey}-S`, c => {
+      this.save()
+      return false
+    })
+    _.set(keyBindings, `${CtrlKey}-B`, c => {
+      this.toggleMarkup({ start: `**` })
+      return false
+    })
+    _.set(keyBindings, `${CtrlKey}-I`, c => {
+      this.toggleMarkup({ start: `*` })
+      return false
+    })
+    _.set(keyBindings, `${CtrlKey}-Alt-Right`, c => {
+      let lvl = this.getHeaderLevel(c)
+      if (lvl >= 6) { lvl = 5 }
+      this.setHeaderLine(lvl + 1)
+      return false
+    })
+    _.set(keyBindings, `${CtrlKey}-Alt-Left`, c => {
+      let lvl = this.getHeaderLevel(c)
+      if (lvl <= 1) { lvl = 2 }
+      this.setHeaderLine(lvl - 1)
+      return false
+    })
+    this.cm.setOption('extraKeys', keyBindings)
+
+    // Handle cursor movement
+
+    this.cm.on('cursorActivity', c => {
+      this.positionSync(c)
+      this.scrollSync(c)
+    })
+
+    // Handle special paste
+
+    this.cm.on('paste', this.onCmPaste)
+
+    // Render initial preview
+
+    this.onCmInput(this.$store.get('editor/content'))
+    this.refresh()
+
     this.$root.$on('editorInsert', opts => {
       switch (opts.kind) {
         case 'IMAGE':
@@ -718,10 +738,10 @@ $editor-height-mobile: calc(100vh - 112px - 16px);
     background: mc('blue','800');
   }
   .cm-s-wikijs-dark .CodeMirror-line::selection, .cm-s-wikijs-dark .CodeMirror-line > span::selection, .cm-s-wikijs-dark .CodeMirror-line > span > span::selection {
-    background: mc('red', '500');
+    background: mc('amber', '500');
   }
   .cm-s-wikijs-dark .CodeMirror-line::-moz-selection, .cm-s-wikijs-dark .CodeMirror-line > span::-moz-selection, .cm-s-wikijs-dark .CodeMirror-line > span > span::-moz-selection {
-    background: mc('red', '500');
+    background: mc('amber', '500');
   }
   .cm-s-wikijs-dark .CodeMirror-gutters {
     background: darken(mc('grey','900'), 6%);

+ 9 - 9
client/components/editor/editor-modal-media.vue

@@ -66,15 +66,15 @@
                     @click.right.prevent=''
                     :class='currentFileId === props.item.id ? ($vuetify.theme.dark ? `grey darken-3-d5` : `teal lighten-5`) : ``'
                     )
-                    td.text-xs-right(v-if='$vuetify.breakpoint.smAndUp') {{ props.item.id }}
+                    td.caption(v-if='$vuetify.breakpoint.smAndUp') {{ props.item.id }}
                     td
-                      .body-2(:class='currentFileId === props.item.id ? `teal--text` : ``') {{ props.item.filename }}
+                      .body-2: strong(:class='currentFileId === props.item.id ? `teal--text` : ``') {{ props.item.filename }}
                       .caption.grey--text {{ props.item.description }}
                     td.text-xs-center(v-if='$vuetify.breakpoint.lgAndUp')
-                      v-chip.ma-0(small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`')
-                        .caption {{props.item.ext.toUpperCase().substring(1)}}
-                    td(v-if='$vuetify.breakpoint.mdAndUp') {{ props.item.fileSize | prettyBytes }}
-                    td(v-if='$vuetify.breakpoint.mdAndUp') {{ props.item.createdAt | moment('from') }}
+                      v-chip.ma-0(x-small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`')
+                        .overline {{props.item.ext.toUpperCase().substring(1)}}
+                    td.caption(v-if='$vuetify.breakpoint.mdAndUp') {{ props.item.fileSize | prettyBytes }}
+                    td.caption(v-if='$vuetify.breakpoint.mdAndUp') {{ props.item.createdAt | moment('from') }}
                     td(v-if='$vuetify.breakpoint.smAndUp')
                       v-menu(offset-x, min-width='200')
                         template(v-slot:activator='{ on }')
@@ -293,12 +293,12 @@ export default {
     },
     headers() {
       return _.compact([
-        this.$vuetify.breakpoint.smAndUp && { text: this.$t('editor:assets.headerId'), value: 'id', width: 50, align: 'right' },
+        this.$vuetify.breakpoint.smAndUp && { text: this.$t('editor:assets.headerId'), value: 'id', width: 80 },
         { text: this.$t('editor:assets.headerFilename'), value: 'filename' },
-        this.$vuetify.breakpoint.lgAndUp && { text: this.$t('editor:assets.headerType'), value: 'ext', width: 50 },
+        this.$vuetify.breakpoint.lgAndUp && { text: this.$t('editor:assets.headerType'), value: 'ext', width: 90 },
         this.$vuetify.breakpoint.mdAndUp && { text: this.$t('editor:assets.headerFileSize'), value: 'fileSize', width: 110 },
         this.$vuetify.breakpoint.mdAndUp && { text: this.$t('editor:assets.headerAdded'), value: 'createdAt', width: 175 },
-        this.$vuetify.breakpoint.smAndUp && { text: this.$t('editor:assets.headerActions'), value: '', width: 40, sortable: false, align: 'right' }
+        this.$vuetify.breakpoint.smAndUp && { text: this.$t('editor:assets.headerActions'), value: '', width: 80, sortable: false, align: 'right' }
       ])
     },
     isFolderNameValid() {

+ 191 - 146
client/components/editor/editor-modal-properties.vue

@@ -2,7 +2,7 @@
   v-dialog(
     v-model='isShown'
     persistent
-    width='1100'
+    width='1000'
     :fullscreen='$vuetify.breakpoint.smAndDown'
     )
     .dialog-header
@@ -17,159 +17,204 @@
         v-icon(left) mdi-check
         span {{ $t('common:actions.ok') }}
     v-card(tile)
-      v-card-text.pt-5
-        .overline.pb-5 {{$t('editor:props.pageInfo')}}
-        v-text-field(
-          ref='iptTitle'
-          outlined
-          :label='$t(`editor:props.title`)'
-          counter='255'
-          v-model='title'
-          )
-        v-text-field(
-          outlined
-          :label='$t(`editor:props.shortDescription`)'
-          counter='255'
-          v-model='description'
-          persistent-hint
-          :hint='$t(`editor:props.shortDescriptionHint`)'
-          )
-      v-divider
-      v-card-text.grey.pt-5(:class='darkMode ? `darken-3-d3` : `lighten-5`')
-        .overline.pb-5 {{$t('editor:props.pathCategorization')}}
-        v-container.pa-0(fluid, grid-list-lg)
-          v-layout(row, wrap)
-            v-flex(xs12, md2)
-              v-select(
-                outlined
-                :label='$t(`editor:props.locale`)'
-                suffix='/'
-                :items='namespaces'
-                v-model='locale'
-                hide-details
-                :disabled='mode !== "create"'
+      v-tabs(color='white', background-color='blue darken-1', dark, centered)
+        v-tab {{$t('editor:props.info')}}
+        v-tab {{$t('editor:props.scheduling')}}
+        v-tab {{$t('editor:props.social')}}
+        v-tab-item
+          v-card-text.pt-5
+            .overline.pb-5 {{$t('editor:props.pageInfo')}}
+            v-text-field(
+              ref='iptTitle'
+              outlined
+              :label='$t(`editor:props.title`)'
+              counter='255'
+              v-model='title'
               )
-            v-flex(xs12, md10)
-              v-text-field(
-                outlined
-                :label='$t(`editor:props.path`)'
-                append-icon='mdi-folder-search'
-                v-model='path'
-                :hint='$t(`editor:props.pathHint`)'
-                persistent-hint
-                @click:append='showPathSelector'
-                :disabled='mode !== "create"'
-                )
-        v-combobox(
-          chips
-          deletable-chips
-          :label='$t(`editor:props.tags`)'
-          outlined
-          multiple
-          v-model='tags'
-          single-line
-          :hint='`COMING SOON - ` + $t(`editor:props.tagsHint`)'
-          persistent-hint
-          disabled
-          )
-      v-divider
-      v-card-text.py-5.grey(:class='darkMode ? `darken-3-d5` : `lighten-4`')
-        .overline.pb-5 {{$t('editor:props.publishState')}} #[v-chip.ml-3(label, color='grey', small, outlined).white--text coming soon]
-        v-container.pa-0(fluid, grid-list-lg)
-          v-layout(row, wrap)
-            v-flex(xs12, md4)
-              v-switch(
-                :label='$t(`editor:props.publishToggle`)'
-                v-model='isPublished'
-                color='primary'
-                :hint='$t(`editor:props.publishToggleHint`)'
-                persistent-hint
-                disabled
-                )
-            v-flex(xs12, md4)
-              v-dialog(
-                ref='menuPublishStart'
-                :close-on-content-click='false'
-                v-model='isPublishStartShown'
-                :return-value.sync='publishStartDate'
-                full-width
-                width='460px'
-                :disabled='!isPublished || true'
-                )
-                template(v-slot:activator='{ on }')
-                  v-text-field(
-                    v-on='on'
-                    :label='$t(`editor:props.publishStart`)'
-                    v-model='publishStartDate'
-                    prepend-icon='mdi-calendar-check'
-                    readonly
+            v-text-field(
+              outlined
+              :label='$t(`editor:props.shortDescription`)'
+              counter='255'
+              v-model='description'
+              persistent-hint
+              :hint='$t(`editor:props.shortDescriptionHint`)'
+              )
+          v-divider
+          v-card-text.grey.pt-5(:class='darkMode ? `darken-3-d3` : `lighten-5`')
+            .overline.pb-5 {{$t('editor:props.path')}}
+            v-container.pa-0(fluid, grid-list-lg)
+              v-layout(row, wrap)
+                v-flex(xs12, md2)
+                  v-select(
                     outlined
-                    clearable
-                    :hint='$t(`editor:props.publishStartHint`)'
-                    persistent-hint
-                    :disabled='!isPublished || true'
-                    )
-                v-date-picker(
-                  v-model='publishStartDate'
-                  :min='(new Date()).toISOString().substring(0, 10)'
-                  color='primary'
-                  reactive
-                  scrollable
-                  landscape
+                    :label='$t(`editor:props.locale`)'
+                    suffix='/'
+                    :items='namespaces'
+                    v-model='locale'
+                    hide-details
+                    :disabled='mode !== "create"'
                   )
-                  v-spacer
-                  v-btn(
-                    flat=''
-                    color='primary'
-                    @click='isPublishStartShown = false'
-                    ) {{$t('common:actions.cancel')}}
-                  v-btn(
-                    flat=''
-                    color='primary'
-                    @click='$refs.menuPublishStart.save(publishStartDate)'
-                    ) {{$t('common:actions.ok')}}
-            v-flex(xs12, md4)
-              v-dialog(
-                ref='menuPublishEnd'
-                :close-on-content-click='false'
-                v-model='isPublishEndShown'
-                :return-value.sync='publishEndDate'
-                full-width
-                width='460px'
-                :disabled='!isPublished || true'
-                )
-                template(v-slot:activator='{ on }')
+                v-flex(xs12, md10)
                   v-text-field(
-                    v-on='on'
-                    :label='$t(`editor:props.publishEnd`)'
-                    v-model='publishEndDate'
-                    prepend-icon='mdi-calendar-remove'
-                    readonly
                     outlined
-                    clearable
-                    :hint='$t(`editor:props.publishEndHint`)'
+                    :label='$t(`editor:props.path`)'
+                    append-icon='mdi-folder-search'
+                    v-model='path'
+                    :hint='$t(`editor:props.pathHint`)'
                     persistent-hint
+                    @click:append='showPathSelector'
+                    :disabled='mode !== "create"'
+                    )
+          v-divider
+          v-card-text.grey.pt-5(:class='darkMode ? `darken-3-d5` : `lighten-4`')
+            .overline.pb-5 {{$t('editor:props.categorization')}}
+            v-combobox(
+              chips
+              deletable-chips
+              :label='$t(`editor:props.tags`)'
+              outlined
+              multiple
+              v-model='tags'
+              :hint='$t(`editor:props.tagsHint`)'
+              persistent-hint
+              clearable
+              height='130'
+              )
+        v-tab-item
+          v-card-text
+            .overline.pb-5 {{$t('editor:props.publishState')}} #[v-chip.ml-3(label, color='grey', small, outlined).white--text coming soon]
+            v-switch(
+              :label='$t(`editor:props.publishToggle`)'
+              v-model='isPublished'
+              color='primary'
+              :hint='$t(`editor:props.publishToggleHint`)'
+              persistent-hint
+              disabled
+              )
+          v-divider
+          v-card-text.grey.pt-5(:class='darkMode ? `darken-3-d3` : `lighten-5`')
+            v-container.pa-0(fluid, grid-list-lg)
+              v-row
+                v-col(cols='6')
+                  v-dialog(
+                    ref='menuPublishStart'
+                    :close-on-content-click='false'
+                    v-model='isPublishStartShown'
+                    :return-value.sync='publishStartDate'
+                    full-width
+                    width='460px'
                     :disabled='!isPublished || true'
                     )
-                v-date-picker(
-                  v-model='publishEndDate'
-                  :min='(new Date()).toISOString().substring(0, 10)'
-                  color='primary'
-                  reactive
-                  scrollable
-                  landscape
-                  )
-                  v-spacer
-                  v-btn(
-                    flat=''
-                    color='primary'
-                    @click='isPublishEndShown = false'
-                    ) {{$t('common:actions.cancel')}}
-                  v-btn(
-                    flat=''
-                    color='primary'
-                    @click='$refs.menuPublishEnd.save(publishEndDate)'
-                    ) {{$t('common:actions.ok')}}
+                    template(v-slot:activator='{ on }')
+                      v-text-field(
+                        v-on='on'
+                        :label='$t(`editor:props.publishStart`)'
+                        v-model='publishStartDate'
+                        prepend-icon='mdi-calendar-check'
+                        readonly
+                        outlined
+                        clearable
+                        :hint='$t(`editor:props.publishStartHint`)'
+                        persistent-hint
+                        :disabled='!isPublished || true'
+                        )
+                    v-date-picker(
+                      v-model='publishStartDate'
+                      :min='(new Date()).toISOString().substring(0, 10)'
+                      color='primary'
+                      reactive
+                      scrollable
+                      landscape
+                      )
+                      v-spacer
+                      v-btn(
+                        flat=''
+                        color='primary'
+                        @click='isPublishStartShown = false'
+                        ) {{$t('common:actions.cancel')}}
+                      v-btn(
+                        flat=''
+                        color='primary'
+                        @click='$refs.menuPublishStart.save(publishStartDate)'
+                        ) {{$t('common:actions.ok')}}
+                v-col(cols='6')
+                  v-dialog(
+                    ref='menuPublishEnd'
+                    :close-on-content-click='false'
+                    v-model='isPublishEndShown'
+                    :return-value.sync='publishEndDate'
+                    full-width
+                    width='460px'
+                    :disabled='!isPublished || true'
+                    )
+                    template(v-slot:activator='{ on }')
+                      v-text-field(
+                        v-on='on'
+                        :label='$t(`editor:props.publishEnd`)'
+                        v-model='publishEndDate'
+                        prepend-icon='mdi-calendar-remove'
+                        readonly
+                        outlined
+                        clearable
+                        :hint='$t(`editor:props.publishEndHint`)'
+                        persistent-hint
+                        :disabled='!isPublished || true'
+                        )
+                    v-date-picker(
+                      v-model='publishEndDate'
+                      :min='(new Date()).toISOString().substring(0, 10)'
+                      color='primary'
+                      reactive
+                      scrollable
+                      landscape
+                      )
+                      v-spacer
+                      v-btn(
+                        flat=''
+                        color='primary'
+                        @click='isPublishEndShown = false'
+                        ) {{$t('common:actions.cancel')}}
+                      v-btn(
+                        flat=''
+                        color='primary'
+                        @click='$refs.menuPublishEnd.save(publishEndDate)'
+                        ) {{$t('common:actions.ok')}}
+
+        v-tab-item
+          v-card-text
+            .overline.pb-5 {{$t('editor:props.socialFeatures')}} #[v-chip.ml-3(label, color='grey', small, outlined).white--text coming soon]
+            v-switch(
+              :label='$t(`editor:props.allowComments`)'
+              v-model='isPublished'
+              color='primary'
+              :hint='$t(`editor:props.allowCommentsHint`)'
+              persistent-hint
+              disabled
+              )
+            v-switch(
+              :label='$t(`editor:props.allowRatings`)'
+              v-model='isPublished'
+              color='primary'
+              :hint='$t(`editor:props.allowRatingsHint`)'
+              persistent-hint
+              disabled
+              )
+            v-switch(
+              :label='$t(`editor:props.displayAuthor`)'
+              v-model='isPublished'
+              color='primary'
+              :hint='$t(`editor:props.displayAuthorHint`)'
+              persistent-hint
+              disabled
+              )
+            v-switch(
+              :label='$t(`editor:props.displaySharingBar`)'
+              v-model='isPublished'
+              color='primary'
+              :hint='$t(`editor:props.displaySharingBarHint`)'
+              persistent-hint
+              disabled
+              )
 
     page-selector(mode='create', v-model='pageSelectorShown', :path='path', :locale='locale', :open-handler='setPath')
     v-tour(name='editorPropertiesTour', :steps='tourSteps')

+ 1 - 1
package.json

@@ -206,6 +206,7 @@
     "cache-loader": "4.1.0",
     "chart.js": "2.8.0",
     "clean-webpack-plugin": "3.0.0",
+    "codemirror": "5.48.4",
     "copy-webpack-plugin": "5.0.4",
     "core-js": "3.2.1",
     "css-loader": "3.2.0",
@@ -274,7 +275,6 @@
     "vue-apollo": "3.0.0-rc.2",
     "vue-chartjs": "3.4.2",
     "vue-clipboards": "1.3.0",
-    "vue-codemirror": "4.0.6",
     "vue-filepond": "5.1.3",
     "vue-hot-reload-api": "2.3.3",
     "vue-loader": "15.7.1",

+ 4 - 17
yarn.lock

@@ -4250,10 +4250,10 @@ codemirror-graphql@^0.9.0:
     graphql-language-service-interface "^2.1.0"
     graphql-language-service-parser "^1.3.0"
 
-codemirror@^5.41.0:
-  version "5.43.0"
-  resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.43.0.tgz#2454b5e0f7005dc9945ab7b0d9594ccf233da040"
-  integrity sha512-mljwQWUaWIf85I7QwTBryF2ASaIvmYAL4s5UCanCJFfKeXOKhrqdHWdHiZWAMNT+hjLTCnVx2S/SYTORIgxsgA==
+codemirror@5.48.4:
+  version "5.48.4"
+  resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.48.4.tgz#4210fbe92be79a88f0eea348fab3ae78da85ce47"
+  integrity sha512-pUhZXDQ6qXSpWdwlgAwHEkd4imA0kf83hINmUEzJpmG80T/XLtDDEzZo8f6PQLuRCcUQhmzqqIo3ZPTRaWByRA==
 
 codemirror@^5.47.0:
   version "5.48.0"
@@ -5283,11 +5283,6 @@ dicer@0.3.0:
   dependencies:
     streamsearch "0.1.2"
 
-diff-match-patch@^1.0.0:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1"
-  integrity sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==
-
 diff-sequences@^24.9.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
@@ -15030,14 +15025,6 @@ vue-clipboards@1.3.0:
   dependencies:
     clipboard "^1.7.1"
 
-vue-codemirror@4.0.6:
-  version "4.0.6"
-  resolved "https://registry.yarnpkg.com/vue-codemirror/-/vue-codemirror-4.0.6.tgz#b786bb80d8d762a93aab8e46f79a81006f0437c4"
-  integrity sha512-ilU7Uf0mqBNSSV3KT7FNEeRIxH4s1fmpG4TfHlzvXn0QiQAbkXS9lLfwuZpaBVEnpP5CSE62iGJjoliTuA8poQ==
-  dependencies:
-    codemirror "^5.41.0"
-    diff-match-patch "^1.0.0"
-
 vue-eslint-parser@^5.0.0:
   version "5.0.0"
   resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-5.0.0.tgz#00f4e4da94ec974b821a26ff0ed0f7a78402b8a1"