diff options
Diffstat (limited to 'app/assets/javascripts/content_editor/components/content_editor.vue')
-rw-r--r-- | app/assets/javascripts/content_editor/components/content_editor.vue | 84 |
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> |