Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue')
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue97
1 files changed, 84 insertions, 13 deletions
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue b/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
index ba3696c8ad1..5c310fc059b 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
@@ -2,7 +2,21 @@
import 'codemirror/lib/codemirror.css';
import '@toast-ui/editor/dist/toastui-editor.css';
-import { EDITOR_OPTIONS, EDITOR_TYPES, EDITOR_HEIGHT, EDITOR_PREVIEW_STYLE } from './constants';
+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';
export default {
components: {
@@ -10,6 +24,7 @@ export default {
import(/* webpackChunkName: 'toast_editor' */ '@toast-ui/vue-editor').then(
toast => toast.Editor,
),
+ AddImageModal,
},
props: {
value: {
@@ -37,29 +52,85 @@ export default {
default: EDITOR_PREVIEW_STYLE,
},
},
+ data() {
+ return {
+ editorApi: null,
+ previousMode: null,
+ };
+ },
computed: {
editorOptions() {
return { ...EDITOR_OPTIONS, ...this.options };
},
+ 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);
},
methods: {
onContentChanged() {
- this.$emit('input', this.getMarkdown());
+ 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);
},
- getMarkdown() {
- return this.$refs.editor.invoke('getMarkdown');
+ onChangeMode(newMode) {
+ this.$emit('modeChange', newMode);
},
},
};
</script>
<template>
- <toast-editor
- ref="editor"
- :initial-value="value"
- :options="editorOptions"
- :preview-style="previewStyle"
- :initial-edit-type="initialEditType"
- :height="height"
- @change="onContentChanged"
- />
+ <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>
</template>