summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
blob: 6eaabbb3519756e1a5376a1ee36280ad137c1455 (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
// This is a true violation of @gitlab/no-runtime-template-compiler, as it relies on
// app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml
// for its template.
/* eslint-disable no-param-reassign, @gitlab/no-runtime-template-compiler */

import { debounce } from 'lodash';
import Vue from 'vue';
import { deprecatedCreateFlash as flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';

((global) => {
  global.mergeConflicts = global.mergeConflicts || {};

  global.mergeConflicts.diffFileEditor = Vue.extend({
    props: {
      file: {
        type: Object,
        required: true,
      },
      onCancelDiscardConfirmation: {
        type: Function,
        required: true,
      },
      onAcceptDiscardConfirmation: {
        type: Function,
        required: true,
      },
    },
    data() {
      return {
        saved: false,
        fileLoaded: false,
        originalContent: '',
      };
    },
    computed: {
      classObject() {
        return {
          saved: this.saved,
        };
      },
    },
    watch: {
      'file.showEditor': function showEditorWatcher(val) {
        this.resetEditorContent();

        if (!val || this.fileLoaded) {
          return;
        }

        this.loadEditor();
      },
    },
    mounted() {
      if (this.file.loadEditor) {
        this.loadEditor();
      }
    },
    methods: {
      loadEditor() {
        const EditorPromise = import(/* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite');
        const DataPromise = axios.get(this.file.content_path);

        Promise.all([EditorPromise, DataPromise])
          .then(
            ([
              { default: EditorLite },
              {
                data: { content, new_path: path },
              },
            ]) => {
              const contentEl = this.$el.querySelector('.editor');

              this.originalContent = content;
              this.fileLoaded = true;

              this.editor = new EditorLite().createInstance({
                el: contentEl,
                blobPath: path,
                blobContent: content,
              });
              this.editor.onDidChangeModelContent(
                debounce(this.saveDiffResolution.bind(this), 250),
              );
            },
          )
          .catch(() => {
            flash(__('An error occurred while loading the file'));
          });
      },
      saveDiffResolution() {
        this.saved = true;

        // This probably be better placed in the data provider
        /* eslint-disable vue/no-mutating-props */
        this.file.content = this.editor.getValue();
        this.file.resolveEditChanged = this.file.content !== this.originalContent;
        this.file.promptDiscardConfirmation = false;
        /* eslint-enable vue/no-mutating-props */
      },
      resetEditorContent() {
        if (this.fileLoaded) {
          this.editor.setValue(this.originalContent);
        }
      },
      cancelDiscardConfirmation(file) {
        this.onCancelDiscardConfirmation(file);
      },
      acceptDiscardConfirmation(file) {
        this.onAcceptDiscardConfirmation(file);
      },
    },
  });
})(window.gl || (window.gl = {}));