feat: ckeditor

This commit is contained in:
Nick
2019-09-08 12:01:17 -04:00
parent 04193dbc6f
commit 7634bd266d
13 changed files with 647 additions and 271 deletions

View File

@@ -0,0 +1,187 @@
<template lang='pug'>
.editor-ckeditor
div(ref='toolbarContainer')
div.contents(ref='editor')
v-system-bar.editor-ckeditor-sysbar(dark, status, color='grey darken-3')
.caption.editor-ckeditor-sysbar-locale {{locale.toUpperCase()}}
.caption.px-3 /{{path}}
template(v-if='$vuetify.breakpoint.mdAndUp')
v-spacer
.caption Visual Editor
v-spacer
.caption {{stats.characters}} Chars, {{stats.words}} Words
</template>
<script>
import _ from 'lodash'
import { get, sync } from 'vuex-pathify'
import DecoupledEditor from '@requarks/ckeditor5'
export default {
props: {
save: {
type: Function,
default: () => {}
}
},
data() {
return {
editor: null,
stats: {
characters: 0,
words: 0
},
content: ''
}
},
computed: {
isMobile() {
return this.$vuetify.breakpoint.smAndDown
},
locale: get('page/locale'),
path: get('page/path'),
activeModal: sync('editor/activeModal')
},
methods: {
},
async mounted () {
this.$store.set('editor/editorKey', 'ckeditor')
this.editor = await DecoupledEditor.create(this.$refs.editor, {
placeholder: 'Type the page content here',
wordCount: {
onUpdate: stats => {
this.stats = {
characters: stats.characters,
words: stats.words
}
}
}
})
this.$refs.toolbarContainer.appendChild(this.editor.ui.view.toolbar.element)
if (this.mode !== 'create') {
this.editor.setData(this.$store.get('editor/content'))
}
this.editor.model.document.on('change:data', _.debounce(evt => {
this.$store.set('editor/content', this.editor.getData())
}, 300))
this.$root.$on('editorInsert', opts => {
console.info(opts)
switch (opts.kind) {
case 'IMAGE':
this.editor.execute('imageInsert', {
source: opts.path
})
break
case 'BINARY':
this.insertAtCursor({
content: `[${opts.text}](${opts.path})`
})
break
}
})
},
beforeDestroy () {
if (this.editor) {
this.editor.destroy()
this.editor = null
}
}
}
</script>
<style lang="scss">
$editor-height: calc(100vh - 64px - 24px);
$editor-height-mobile: calc(100vh - 56px - 16px);
.editor-ckeditor {
background-color: mc('grey', '200');
flex: 1 1 50%;
display: flex;
flex-flow: column nowrap;
height: $editor-height;
max-height: $editor-height;
position: relative;
@at-root .theme--dark & {
background-color: mc('grey', '900');
}
@include until($tablet) {
height: $editor-height-mobile;
max-height: $editor-height-mobile;
}
&-sysbar {
padding-left: 0;
&-locale {
background-color: rgba(255,255,255,.25);
display:inline-flex;
padding: 0 12px;
height: 24px;
width: 63px;
justify-content: center;
align-items: center;
}
}
.ck.ck-toolbar {
border: none;
justify-content: center;
background-color: mc('grey', '300');
color: #FFF;
}
> .ck-editor__editable {
background-color: mc('grey', '100');
overflow-y: auto;
overflow-x: hidden;
padding: 2rem;
box-shadow: 0 0 5px hsla(0, 0, 0, .1);
margin: 1rem auto 0;
width: calc(100vw - 256px - 16vw);
min-height: calc(100vh - 64px - 24px - 1rem - 40px);
border-radius: 5px;
@at-root .theme--dark & {
background-color: #303030;
color: #FFF;
}
@include until($widescreen) {
width: calc(100vw - 2rem);
margin: 1rem 1rem 0 1rem;
min-height: calc(100vh - 64px - 24px - 1rem - 40px);
}
@include until($tablet) {
width: 100%;
margin: 0;
min-height: calc(100vh - 56px - 24px - 76px);
}
&.ck.ck-editor__editable:not(.ck-editor__nested-editable).ck-focused {
border-color: #FFF;
box-shadow: 0 0 10px rgba(mc('blue', '700'), .25);
@at-root .theme--dark & {
border-color: #444;
border-bottom: none;
box-shadow: 0 0 10px rgba(#000, .25);
}
}
&.ck .ck-editor__nested-editable.ck-editor__nested-editable_focused,
&.ck .ck-editor__nested-editable:focus,
.ck-widget.table td.ck-editor__nested-editable.ck-editor__nested-editable_focused,
.ck-widget.table th.ck-editor__nested-editable.ck-editor__nested-editable_focused {
background-color: mc('grey', '900');
}
}
}
</style>

View File

@@ -296,6 +296,7 @@ export default {
},
locale: get('page/locale'),
path: get('page/path'),
mode: get('editor/mode'),
activeModal: sync('editor/activeModal')
},
methods: {
@@ -456,6 +457,12 @@ export default {
}
},
mounted() {
this.$store.set('editor/editorKey', 'markdown')
if (this.mode === 'create') {
this.$store.set('editor/content', '# Header\nYour content here')
}
// Initialize CodeMirror
this.cm = CodeMirror.fromTextArea(this.$refs.cm, {

View File

@@ -48,17 +48,27 @@
img(src='/svg/icon-table.svg', alt='Tabular', style='width: 36px;')
.body-2.grey--text.mt-2.text--darken-2 Tabular
.caption.grey--text.text--darken-1 Excel-like
//- v-flex(xs4)
//- v-card.radius-7.grey(
//- hover
//- light
//- ripple
//- disabled
//- )
//- v-card-text.text-center(@click='selectEditor("wysiwyg")')
//- img(src='/svg/icon-open-in-browser.svg', alt='Visual Builder', style='width: 36px;')
//- .body-2.mt-2.grey--text.text--darken-2 Visual Builder
//- .caption.grey--text.text--darken-1 Drag-n-drop
v-flex(xs4)
v-card.radius-7.grey(
v-card.radius-7(
hover
light
ripple
disabled
)
v-card-text.text-center(@click='selectEditor("wysiwyg")')
img(src='/svg/icon-open-in-browser.svg', alt='Visual Builder', style='width: 36px;')
.body-2.mt-2.grey--text.text--darken-2 Visual Builder
.caption.grey--text.text--darken-1 Drag-n-drop
v-card-text.text-center(@click='selectEditor("ckeditor")')
img(src='/svg/icon-open-in-browser.svg', alt='Visual Editor', style='width: 36px;')
.body-2.mt-2.primary--text Visual Editor
.caption.grey--text Rich-text WYSIWYG
v-flex(xs4)
v-card.radius-7.grey(
hover

View File

@@ -144,7 +144,6 @@
:close-on-content-click='false'
v-model='isPublishEndShown'
:return-value.sync='publishEndDate'
full-width
width='460px'
:disabled='!isPublished || true'
)

View File

@@ -2,14 +2,14 @@
v-dialog(v-model='isShown', max-width='550')
v-card.wiki-form
.dialog-header.is-short.is-red
v-icon.mr-2(color='white') warning
v-icon.mr-2(color='white') mdi-alert
span {{$t('editor:unsaved.title')}}
v-card-text
v-card-text.pt-4
.body-2 {{$t('editor:unsaved.body')}}
v-card-chin
v-spacer
v-btn(flat, @click='isShown = false') {{$t('common:actions.cancel')}}
v-btn(color='red', @click='discard', dark) {{$t('common:actions.discardChanges')}}
v-btn(text, @click='isShown = false') {{$t('common:actions.cancel')}}
v-btn.px-4(color='red', @click='discard', dark) {{$t('common:actions.discardChanges')}}
</template>
<script>