summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/content_editor/components/content_editor.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/content_editor/components/content_editor.vue')
-rw-r--r--app/assets/javascripts/content_editor/components/content_editor.vue84
1 files changed, 69 insertions, 15 deletions
diff --git a/app/assets/javascripts/content_editor/components/content_editor.vue b/app/assets/javascripts/content_editor/components/content_editor.vue
index c3c881d9135..659c447e861 100644
--- a/app/assets/javascripts/content_editor/components/content_editor.vue
+++ b/app/assets/javascripts/content_editor/components/content_editor.vue
@@ -1,13 +1,16 @@
<script>
import { EditorContent as TiptapEditorContent } from '@tiptap/vue-2';
+import { __ } from '~/locale';
+import { VARIANT_DANGER } from '~/flash';
import { createContentEditor } from '../services/create_content_editor';
+import { ALERT_EVENT } from '../constants';
import ContentEditorAlert from './content_editor_alert.vue';
import ContentEditorProvider from './content_editor_provider.vue';
import EditorStateObserver from './editor_state_observer.vue';
-import FormattingBubbleMenu from './bubble_menus/formatting.vue';
-import CodeBlockBubbleMenu from './bubble_menus/code_block.vue';
-import LinkBubbleMenu from './bubble_menus/link.vue';
-import MediaBubbleMenu from './bubble_menus/media.vue';
+import FormattingBubbleMenu from './bubble_menus/formatting_bubble_menu.vue';
+import CodeBlockBubbleMenu from './bubble_menus/code_block_bubble_menu.vue';
+import LinkBubbleMenu from './bubble_menus/link_bubble_menu.vue';
+import MediaBubbleMenu from './bubble_menus/media_bubble_menu.vue';
import TopToolbar from './top_toolbar.vue';
import LoadingIndicator from './loading_indicator.vue';
@@ -43,12 +46,26 @@ export default {
required: false,
default: () => {},
},
+ markdown: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
return {
focused: false,
+ isLoading: false,
+ latestMarkdown: null,
};
},
+ watch: {
+ markdown(markdown) {
+ if (markdown !== this.latestMarkdown) {
+ this.setSerializedContent(markdown);
+ }
+ },
+ },
created() {
const { renderMarkdown, uploadsPath, extensions, serializerConfig } = this;
@@ -61,21 +78,61 @@ export default {
});
},
mounted() {
- this.$emit('initialized', this.contentEditor);
+ this.$emit('initialized');
+ this.setSerializedContent(this.markdown);
},
beforeDestroy() {
this.contentEditor.dispose();
},
methods: {
+ async setSerializedContent(markdown) {
+ this.notifyLoading();
+
+ try {
+ await this.contentEditor.setSerializedContent(markdown);
+ this.contentEditor.setEditable(true);
+ this.notifyLoadingSuccess();
+ this.latestMarkdown = markdown;
+ } catch {
+ this.contentEditor.eventHub.$emit(ALERT_EVENT, {
+ message: __(
+ 'An error occurred while trying to render the content editor. Please try again.',
+ ),
+ variant: VARIANT_DANGER,
+ actionLabel: __('Retry'),
+ action: () => {
+ this.setSerializedContent(markdown);
+ },
+ });
+ this.contentEditor.setEditable(false);
+ this.notifyLoadingError();
+ }
+ },
focus() {
this.focused = true;
},
blur() {
this.focused = false;
},
+ notifyLoading() {
+ this.isLoading = true;
+ this.$emit('loading');
+ },
+ notifyLoadingSuccess() {
+ this.isLoading = false;
+ this.$emit('loadingSuccess');
+ },
+ notifyLoadingError(error) {
+ this.isLoading = false;
+ this.$emit('loadingError', error);
+ },
notifyChange() {
+ this.latestMarkdown = this.contentEditor.getSerializedContent();
+
this.$emit('change', {
empty: this.contentEditor.empty,
+ changed: this.contentEditor.changed,
+ markdown: this.latestMarkdown,
});
},
},
@@ -84,14 +141,7 @@ export default {
<template>
<content-editor-provider :content-editor="contentEditor">
<div>
- <editor-state-observer
- @docUpdate="notifyChange"
- @focus="focus"
- @blur="blur"
- @loading="$emit('loading')"
- @loadingSuccess="$emit('loadingSuccess')"
- @loadingError="$emit('loadingError')"
- />
+ <editor-state-observer @docUpdate="notifyChange" @focus="focus" @blur="blur" />
<content-editor-alert />
<div
data-testid="content-editor"
@@ -105,8 +155,12 @@ export default {
<code-block-bubble-menu />
<link-bubble-menu />
<media-bubble-menu />
- <tiptap-editor-content class="md" :editor="contentEditor.tiptapEditor" />
- <loading-indicator />
+ <tiptap-editor-content
+ class="md"
+ data-testid="content_editor_editablebox"
+ :editor="contentEditor.tiptapEditor"
+ />
+ <loading-indicator v-if="isLoading" />
</div>
</div>
</div>