diff --git a/app/assets/javascripts/content_editor/components/content_editor.vue b/app/assets/javascripts/content_editor/components/content_editor.vue index 09a5bab8d374ce92260127c097a49ba13c919e91..9e08a257abff865de191f139be758e1d80c6dc26 100644 --- a/app/assets/javascripts/content_editor/components/content_editor.vue +++ b/app/assets/javascripts/content_editor/components/content_editor.vue @@ -56,6 +56,11 @@ export default { required: false, default: '', }, + placeholder: { + type: String, + required: false, + default: '', + }, autofocus: { type: [String, Boolean], required: false, @@ -67,6 +72,16 @@ export default { required: false, default: '', }, + drawioEnabled: { + type: Boolean, + required: false, + default: false, + }, + editable: { + type: Boolean, + required: false, + default: true, + }, }, data() { return { @@ -81,9 +96,20 @@ export default { this.setSerializedContent(markdown); } }, + editable(value) { + this.contentEditor.setEditable(value); + }, }, created() { - const { renderMarkdown, uploadsPath, extensions, serializerConfig, autofocus } = this; + const { + renderMarkdown, + uploadsPath, + extensions, + serializerConfig, + autofocus, + drawioEnabled, + editable, + } = this; // This is a non-reactive attribute intentionally since this is a complex object. this.contentEditor = createContentEditor({ @@ -91,8 +117,10 @@ export default { uploadsPath, extensions, serializerConfig, + drawioEnabled, tiptapOptions: { autofocus, + editable, }, }); }, @@ -109,10 +137,10 @@ export default { try { await this.contentEditor.setSerializedContent(markdown); - this.contentEditor.setEditable(true); this.notifyLoadingSuccess(); this.latestMarkdown = markdown; } catch { + this.contentEditor.setEditable(false); this.contentEditor.eventHub.$emit(ALERT_EVENT, { message: __( 'An error occurred while trying to render the content editor. Please try again.', @@ -120,10 +148,10 @@ export default { variant: VARIANT_DANGER, actionLabel: __('Retry'), action: () => { + this.contentEditor.setEditable(true); this.setSerializedContent(markdown); }, }); - this.contentEditor.setEditable(false); this.notifyLoadingError(); } }, @@ -189,6 +217,9 @@ export default { +
+ {{ placeholder }} +
this.insert('diagram', { language: 'plantuml' }), }, - { - text: __('Create or edit diagram'), - action: () => this.execute('createOrEditDiagram', 'drawioDiagram'), - }, + ...(this.contentEditor.drawioEnabled + ? [ + { + text: __('Create or edit diagram'), + action: () => this.execute('createOrEditDiagram', 'drawioDiagram'), + }, + ] + : []), { text: __('Table of contents'), action: () => this.execute('insertTableOfContents', 'tableOfContents'), diff --git a/app/assets/javascripts/content_editor/services/content_editor.js b/app/assets/javascripts/content_editor/services/content_editor.js index 514ab9699bc730412d15925797cabd5593bbe639..a988e1df2a6b20ea0f5a36a5845fadc3abffd3cd 100644 --- a/app/assets/javascripts/content_editor/services/content_editor.js +++ b/app/assets/javascripts/content_editor/services/content_editor.js @@ -1,12 +1,14 @@ /* eslint-disable no-underscore-dangle */ export class ContentEditor { - constructor({ tiptapEditor, serializer, deserializer, assetResolver, eventHub }) { + constructor({ tiptapEditor, serializer, deserializer, assetResolver, eventHub, drawioEnabled }) { this._tiptapEditor = tiptapEditor; this._serializer = serializer; this._deserializer = deserializer; this._eventHub = eventHub; this._assetResolver = assetResolver; this._pristineDoc = null; + + this.drawioEnabled = drawioEnabled; } get tiptapEditor() { diff --git a/app/assets/javascripts/content_editor/services/create_content_editor.js b/app/assets/javascripts/content_editor/services/create_content_editor.js index b9740894b2c6d38488d388d290bff08306d0dad8..9d536793287122cb24f5291a663b7aeadcf31992 100644 --- a/app/assets/javascripts/content_editor/services/create_content_editor.js +++ b/app/assets/javascripts/content_editor/services/create_content_editor.js @@ -87,6 +87,7 @@ export const createContentEditor = ({ extensions = [], serializerConfig = { marks: {}, nodes: {} }, tiptapOptions, + drawioEnabled = false, } = {}) => { if (!isFunction(renderMarkdown)) { throw new Error(PROVIDE_SERIALIZER_OR_RENDERER_ERROR); @@ -110,7 +111,6 @@ export const createContentEditor = ({ DetailsContent, Document, Diagram, - DrawioDiagram.configure({ uploadsPath, renderMarkdown }), Dropcursor, Emoji, Figure, @@ -159,6 +159,9 @@ export const createContentEditor = ({ ]; const allExtensions = [...builtInContentEditorExtensions, ...extensions]; + + if (drawioEnabled) allExtensions.push(DrawioDiagram.configure({ uploadsPath, renderMarkdown })); + const trackedExtensions = allExtensions.map(trackInputRulesAndShortcuts); const tiptapEditor = createTiptapEditor({ extensions: trackedExtensions, ...tiptapOptions }); const serializer = createMarkdownSerializer({ serializerConfig }); @@ -175,5 +178,6 @@ export const createContentEditor = ({ eventHub, deserializer, assetResolver, + drawioEnabled, }); }; diff --git a/app/assets/javascripts/content_editor/services/gl_api_markdown_deserializer.js b/app/assets/javascripts/content_editor/services/gl_api_markdown_deserializer.js index e65644d2c5c5b451eea075b5bf46dd062f651268..91f8aaf632431c898d49cd91dd94279b9fcd4a33 100644 --- a/app/assets/javascripts/content_editor/services/gl_api_markdown_deserializer.js +++ b/app/assets/javascripts/content_editor/services/gl_api_markdown_deserializer.js @@ -18,10 +18,7 @@ export default ({ render }) => { */ return { deserialize: async ({ schema, markdown }) => { - const html = await render(markdown); - - if (!html) return {}; - + const html = markdown ? await render(markdown) : '

'; const parser = new DOMParser(); const { body } = parser.parseFromString(`${html}`, 'text/html'); diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index 434e199a5e66170773b08412074a7f61b09bf85f..177854d9475b4a962766095a29557c6a8fb5b15a 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -1,9 +1,7 @@ @@ -362,35 +351,24 @@ export default { :noteable-type="noteableType" :contains-link="containsLink" > - - - + :quick-actions-docs-path="quickActionsDocsPath" + :form-field-props="formFieldProps" + :autosave-key="autosaveKey" + :disabled="isSubmitting" + supports-quick-actions + autofocus + @keydown.up="editCurrentUserLastNote()" + @keydown.meta.enter="handleEnter()" + @keydown.ctrl.enter="handleEnter()" + @input="onInput" + />