debian-mirror-gitlab/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue

137 lines
3.4 KiB
Vue
Raw Normal View History

2020-05-24 23:13:21 +05:30
<script>
import 'codemirror/lib/codemirror.css';
import '@toast-ui/editor/dist/toastui-editor.css';
2020-06-23 00:09:42 +05:30
import AddImageModal from './modals/add_image_modal.vue';
import {
EDITOR_OPTIONS,
EDITOR_TYPES,
EDITOR_HEIGHT,
EDITOR_PREVIEW_STYLE,
CUSTOM_EVENTS,
} from './constants';
import {
addCustomEventListener,
removeCustomEventListener,
addImage,
getMarkdown,
} from './editor_service';
2020-05-24 23:13:21 +05:30
export default {
components: {
ToastEditor: () =>
import(/* webpackChunkName: 'toast_editor' */ '@toast-ui/vue-editor').then(
toast => toast.Editor,
),
2020-06-23 00:09:42 +05:30
AddImageModal,
2020-05-24 23:13:21 +05:30
},
props: {
value: {
type: String,
required: true,
},
options: {
type: Object,
required: false,
default: () => EDITOR_OPTIONS,
},
initialEditType: {
type: String,
required: false,
default: EDITOR_TYPES.wysiwyg,
},
height: {
type: String,
required: false,
default: EDITOR_HEIGHT,
},
previewStyle: {
type: String,
required: false,
default: EDITOR_PREVIEW_STYLE,
},
},
2020-06-23 00:09:42 +05:30
data() {
return {
editorApi: null,
previousMode: null,
};
},
2020-05-24 23:13:21 +05:30
computed: {
editorOptions() {
return { ...EDITOR_OPTIONS, ...this.options };
},
2020-06-23 00:09:42 +05:30
editorInstance() {
return this.$refs.editor;
},
},
watch: {
value(newVal) {
const isSameMode = this.previousMode === this.editorApi.currentMode;
if (!isSameMode) {
/*
The ToastUI Editor consumes its content via the `initial-value` prop and then internally
manages changes. If we desire the `v-model` to work as expected, we need to manually call
`setMarkdown`. However, if we do this in each v-model change we'll continually prevent
the editor from internally managing changes. Thus we use the `previousMode` flag as
confirmation to actually update its internals. This is initially designed so that front
matter is excluded from editing in wysiwyg mode, but included in markdown mode.
*/
this.editorInstance.invoke('setMarkdown', newVal);
this.previousMode = this.editorApi.currentMode;
}
},
},
beforeDestroy() {
removeCustomEventListener(
this.editorApi,
CUSTOM_EVENTS.openAddImageModal,
this.onOpenAddImageModal,
);
this.editorApi.eventManager.removeEventHandler('changeMode', this.onChangeMode);
2020-05-24 23:13:21 +05:30
},
methods: {
onContentChanged() {
2020-06-23 00:09:42 +05:30
this.$emit('input', getMarkdown(this.editorInstance));
},
onLoad(editorApi) {
this.editorApi = editorApi;
addCustomEventListener(
this.editorApi,
CUSTOM_EVENTS.openAddImageModal,
this.onOpenAddImageModal,
);
this.editorApi.eventManager.listen('changeMode', this.onChangeMode);
},
onOpenAddImageModal() {
this.$refs.addImageModal.show();
},
onAddImage(image) {
addImage(this.editorInstance, image);
2020-05-24 23:13:21 +05:30
},
2020-06-23 00:09:42 +05:30
onChangeMode(newMode) {
this.$emit('modeChange', newMode);
2020-05-24 23:13:21 +05:30
},
},
};
</script>
<template>
2020-06-23 00:09:42 +05:30
<div>
<toast-editor
ref="editor"
:initial-value="value"
:options="editorOptions"
:preview-style="previewStyle"
:initial-edit-type="initialEditType"
:height="height"
@change="onContentChanged"
@load="onLoad"
/>
<add-image-modal ref="addImageModal" @addImage="onAddImage" />
</div>
2020-05-24 23:13:21 +05:30
</template>