diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-31 09:16:45 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-31 09:16:45 +0300 |
commit | e4805b324cb9e620788bb2d625f633f2be20091d (patch) | |
tree | fcd95b7b35572e6a06e71178d791350467875c38 /app/assets/javascripts/vue_shared/components/markdown | |
parent | 95cb5e20a13cbea5e57c25df47aba1e2c9035466 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/markdown')
-rw-r--r-- | app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue | 42 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js | 100 |
2 files changed, 141 insertions, 1 deletions
diff --git a/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue b/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue index 5bfc4e3c7b5..420d7ebe7d6 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue @@ -20,6 +20,11 @@ export default { type: String, required: true, }, + setFacade: { + type: Function, + required: false, + default: null, + }, renderMarkdownPath: { type: String, required: true, @@ -44,6 +49,16 @@ export default { required: false, default: false, }, + enableAutocomplete: { + type: Boolean, + required: false, + default: true, + }, + autocompleteDataSources: { + type: Object, + required: false, + default: () => ({}), + }, supportsQuickActions: { type: Boolean, required: false, @@ -54,6 +69,11 @@ export default { required: false, default: null, }, + markdownDocsPath: { + type: String, + required: false, + default: '', + }, quickActionsDocsPath: { type: String, required: false, @@ -99,8 +119,23 @@ export default { this.$emit('input', this.markdown); this.saveDraft(); + + this.setFacade?.({ + getValue: () => this.getValue(), + setValue: (val) => this.setValue(val), + }); }, methods: { + getValue() { + return this.markdown; + }, + setValue(value) { + this.markdown = value; + this.$emit('input', value); + + this.saveDraft(); + this.autosizeTextarea(); + }, updateMarkdownFromContentEditor({ markdown }) { this.markdown = markdown; this.$emit('input', markdown); @@ -162,7 +197,7 @@ export default { <div> <local-storage-sync v-model="editingMode" - storage-key="gl-wiki-content-editor-enabled" + storage-key="gl-content-editor-enabled" @input="onEditingModeRestored" /> <markdown-field @@ -174,6 +209,9 @@ export default { can-attach-file :textarea-value="markdown" :uploads-path="uploadsPath" + :enable-autocomplete="enableAutocomplete" + :autocomplete-data-sources="autocompleteDataSources" + :markdown-docs-path="markdownDocsPath" :quick-actions-docs-path="quickActionsDocsPath" :show-content-editor-switcher="enableContentEditor" :drawio-enabled="drawioEnabled" @@ -206,6 +244,8 @@ export default { :autofocus="contentEditorAutofocused" :placeholder="formFieldProps.placeholder" :drawio-enabled="drawioEnabled" + :enable-autocomplete="enableAutocomplete" + :autocomplete-data-sources="autocompleteDataSources" :editable="!disabled" @initialized="setEditorAsAutofocused" @change="updateMarkdownFromContentEditor" diff --git a/app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js b/app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js new file mode 100644 index 00000000000..bf9f1948de2 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js @@ -0,0 +1,100 @@ +import Vue from 'vue'; +import { queryToObject, objectToQuery } from '~/lib/utils/url_utility'; +import MarkdownEditor from './markdown_editor.vue'; + +const MR_SOURCE_BRANCH = 'merge_request[source_branch]'; +const MR_TARGET_BRANCH = 'merge_request[target_branch]'; + +function organizeQuery(obj, isFallbackKey = false) { + if (!obj[MR_SOURCE_BRANCH] && !obj[MR_TARGET_BRANCH]) { + return obj; + } + + if (isFallbackKey) { + return { + [MR_SOURCE_BRANCH]: obj[MR_SOURCE_BRANCH], + }; + } + + return { + [MR_SOURCE_BRANCH]: obj[MR_SOURCE_BRANCH], + [MR_TARGET_BRANCH]: obj[MR_TARGET_BRANCH], + }; +} + +function format(searchTerm, isFallbackKey = false) { + const queryObject = queryToObject(searchTerm, { legacySpacesDecode: true }); + const organizeQueryObject = organizeQuery(queryObject, isFallbackKey); + const formattedQuery = objectToQuery(organizeQueryObject); + + return formattedQuery; +} + +function getSearchTerm(newIssuePath) { + const { search, pathname } = document.location; + return newIssuePath === pathname ? '' : format(search); +} + +export function mountMarkdownEditor() { + const el = document.querySelector('.js-markdown-editor'); + + if (!el) { + return null; + } + + const { + renderMarkdownPath, + markdownDocsPath, + quickActionsDocsPath, + enableContentEditor, + formFieldPlaceholder, + formFieldClasses, + qaSelector, + newIssuePath, + } = el.dataset; + + const hiddenInput = el.querySelector('input[type="hidden"]'); + const formFieldName = hiddenInput.getAttribute('name'); + const formFieldId = hiddenInput.getAttribute('id'); + const formFieldValue = hiddenInput.value; + + const searchTerm = getSearchTerm(newIssuePath); + const facade = { + setValue() {}, + getValue() {}, + focus() {}, + }; + + const setFacade = (props) => Object.assign(facade, props); + + // eslint-disable-next-line no-new + new Vue({ + el, + render(h) { + return h(MarkdownEditor, { + props: { + setFacade, + enableContentEditor: Boolean(enableContentEditor), + value: formFieldValue, + renderMarkdownPath, + markdownDocsPath, + quickActionsDocsPath, + formFieldProps: { + placeholder: formFieldPlaceholder, + id: formFieldId, + name: formFieldName, + class: formFieldClasses, + 'data-qa-selector': qaSelector, + }, + autosaveKey: `autosave/${document.location.pathname}/${searchTerm}/description`, + enableAutocomplete: true, + autocompleteDataSources: gl.GfmAutoComplete?.dataSources, + supportsQuickActions: true, + autofocus: true, + }, + }); + }, + }); + + return facade; +} |