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:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-31 09:16:45 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-31 09:16:45 +0300
commite4805b324cb9e620788bb2d625f633f2be20091d (patch)
treefcd95b7b35572e6a06e71178d791350467875c38 /app/assets/javascripts/vue_shared/components/markdown
parent95cb5e20a13cbea5e57c25df47aba1e2c9035466 (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.vue42
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js100
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;
+}