summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js
blob: b0e609e2433908fc67f23c68e41af3eac38a7044 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import Vue from 'vue';
import { queryToObject, objectToQuery } from '~/lib/utils/url_utility';
import { CLEAR_AUTOSAVE_ENTRY_EVENT } from '../../constants';
import MarkdownEditor from './markdown_editor.vue';
import eventHub from './eventhub';

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);
}

function mountAutosaveClearOnSubmit(autosaveKey) {
  const resetAutosaveButtons = document.querySelectorAll('.js-reset-autosave');
  if (resetAutosaveButtons.length === 0) {
    return;
  }

  for (const resetAutosaveButton of resetAutosaveButtons) {
    resetAutosaveButton.addEventListener('click', () => {
      eventHub.$emit(CLEAR_AUTOSAVE_ENTRY_EVENT, autosaveKey);
    });
  }
}

export function mountMarkdownEditor() {
  const el = document.querySelector('.js-markdown-editor');

  if (!el) {
    return null;
  }

  const {
    renderMarkdownPath,
    markdownDocsPath,
    quickActionsDocsPath,
    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);
  const autosaveKey = `autosave/${document.location.pathname}/${searchTerm}/description`;

  // eslint-disable-next-line no-new
  new Vue({
    el,
    render(h) {
      return h(MarkdownEditor, {
        props: {
          setFacade,
          enableContentEditor: Boolean(gon.features?.contentEditorOnIssues),
          value: formFieldValue,
          renderMarkdownPath,
          markdownDocsPath,
          quickActionsDocsPath,
          formFieldProps: {
            placeholder: formFieldPlaceholder,
            id: formFieldId,
            name: formFieldName,
            class: formFieldClasses,
            'data-qa-selector': qaSelector,
          },
          autosaveKey,
          enableAutocomplete: true,
          autocompleteDataSources: gl.GfmAutoComplete?.dataSources,
          supportsQuickActions: true,
          autofocus: true,
        },
      });
    },
  });

  mountAutosaveClearOnSubmit(autosaveKey);

  return facade;
}