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/content_editor/components/content_editor.vue')
-rw-r--r--app/assets/javascripts/content_editor/components/content_editor.vue108
1 files changed, 87 insertions, 21 deletions
diff --git a/app/assets/javascripts/content_editor/components/content_editor.vue b/app/assets/javascripts/content_editor/components/content_editor.vue
index 9a51def7075..a372233e543 100644
--- a/app/assets/javascripts/content_editor/components/content_editor.vue
+++ b/app/assets/javascripts/content_editor/components/content_editor.vue
@@ -1,45 +1,111 @@
<script>
-import { GlAlert } from '@gitlab/ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import { EditorContent as TiptapEditorContent } from '@tiptap/vue-2';
-import { ContentEditor } from '../services/content_editor';
+import { LOADING_CONTENT_EVENT, LOADING_SUCCESS_EVENT, LOADING_ERROR_EVENT } from '../constants';
+import { createContentEditor } from '../services/create_content_editor';
+import ContentEditorError from './content_editor_error.vue';
+import ContentEditorProvider from './content_editor_provider.vue';
+import EditorStateObserver from './editor_state_observer.vue';
+import FormattingBubbleMenu from './formatting_bubble_menu.vue';
import TopToolbar from './top_toolbar.vue';
export default {
components: {
- GlAlert,
+ GlLoadingIcon,
+ ContentEditorError,
+ ContentEditorProvider,
TiptapEditorContent,
TopToolbar,
+ FormattingBubbleMenu,
+ EditorStateObserver,
},
props: {
- contentEditor: {
- type: ContentEditor,
+ renderMarkdown: {
+ type: Function,
required: true,
},
+ uploadsPath: {
+ type: String,
+ required: true,
+ },
+ extensions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ serializerConfig: {
+ type: Object,
+ required: false,
+ default: () => {},
+ },
},
data() {
return {
- error: '',
+ isLoadingContent: false,
+ focused: false,
};
},
- mounted() {
- this.contentEditor.tiptapEditor.on('error', (error) => {
- this.error = error;
+ created() {
+ const { renderMarkdown, uploadsPath, extensions, serializerConfig } = this;
+
+ // This is a non-reactive attribute intentionally since this is a complex object.
+ this.contentEditor = createContentEditor({
+ renderMarkdown,
+ uploadsPath,
+ extensions,
+ serializerConfig,
});
+
+ this.contentEditor.on(LOADING_CONTENT_EVENT, this.displayLoadingIndicator);
+ this.contentEditor.on(LOADING_SUCCESS_EVENT, this.hideLoadingIndicator);
+ this.contentEditor.on(LOADING_ERROR_EVENT, this.hideLoadingIndicator);
+ this.$emit('initialized', this.contentEditor);
+ },
+ beforeDestroy() {
+ this.contentEditor.dispose();
+ this.contentEditor.off(LOADING_CONTENT_EVENT, this.displayLoadingIndicator);
+ this.contentEditor.off(LOADING_SUCCESS_EVENT, this.hideLoadingIndicator);
+ this.contentEditor.off(LOADING_ERROR_EVENT, this.hideLoadingIndicator);
+ },
+ methods: {
+ displayLoadingIndicator() {
+ this.isLoadingContent = true;
+ },
+ hideLoadingIndicator() {
+ this.isLoadingContent = false;
+ },
+ focus() {
+ this.focused = true;
+ },
+ blur() {
+ this.focused = false;
+ },
+ notifyChange() {
+ this.$emit('change', {
+ empty: this.contentEditor.empty,
+ });
+ },
},
};
</script>
<template>
- <div>
- <gl-alert v-if="error" class="gl-mb-6" variant="danger" @dismiss="error = ''">
- {{ error }}
- </gl-alert>
- <div
- data-testid="content-editor"
- class="md-area"
- :class="{ 'is-focused': contentEditor.tiptapEditor.isFocused }"
- >
- <top-toolbar ref="toolbar" class="gl-mb-4" :content-editor="contentEditor" />
- <tiptap-editor-content class="md" :editor="contentEditor.tiptapEditor" />
+ <content-editor-provider :content-editor="contentEditor">
+ <div>
+ <editor-state-observer @docUpdate="notifyChange" @focus="focus" @blur="blur" />
+ <content-editor-error />
+ <div
+ data-testid="content-editor"
+ data-qa-selector="content_editor_container"
+ class="md-area"
+ :class="{ 'is-focused': focused }"
+ >
+ <top-toolbar ref="toolbar" class="gl-mb-4" />
+ <formatting-bubble-menu />
+ <div v-if="isLoadingContent" class="gl-w-full gl-display-flex gl-justify-content-center">
+ <gl-loading-icon size="sm" />
+ </div>
+ <tiptap-editor-content v-else class="md" :editor="contentEditor.tiptapEditor" />
+ </div>
</div>
- </div>
+ </content-editor-provider>
</template>