summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
blob: 3c2dbfff6e1722169de22f4724dcfe2024f69c9b (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
<script>
import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
import BlobContentEdit from '~/blob/components/blob_edit_content.vue';
import { GlLoadingIcon } from '@gitlab/ui';
import { getBaseURL, joinPaths } from '~/lib/utils/url_utility';
import axios from '~/lib/utils/axios_utils';
import { SNIPPET_BLOB_CONTENT_FETCH_ERROR } from '~/snippets/constants';
import Flash from '~/flash';
import { sprintf } from '~/locale';

function localId() {
  return Math.floor((1 + Math.random()) * 0x10000)
    .toString(16)
    .substring(1);
}

export default {
  components: {
    BlobHeaderEdit,
    BlobContentEdit,
    GlLoadingIcon,
  },
  inheritAttrs: false,
  props: {
    blob: {
      type: Object,
      required: false,
      default: null,
      validator: ({ rawPath }) => Boolean(rawPath),
    },
  },
  data() {
    return {
      id: localId(),
      filePath: this.blob?.path || '',
      previousPath: '',
      originalPath: this.blob?.path || '',
      content: this.blob?.content || '',
      originalContent: '',
      isContentLoading: this.blob,
    };
  },
  watch: {
    filePath(filePath, previousPath) {
      this.previousPath = previousPath;
      this.notifyAboutUpdates({ previousPath });
    },
    content() {
      this.notifyAboutUpdates();
    },
  },
  mounted() {
    if (this.blob) {
      this.fetchBlobContent();
    }
  },
  methods: {
    notifyAboutUpdates(args = {}) {
      const { filePath, previousPath } = args;
      this.$emit('blob-updated', {
        filePath: filePath || this.filePath,
        previousPath: previousPath || this.previousPath,
        content: this.content,
        _constants: {
          originalPath: this.originalPath,
          originalContent: this.originalContent,
          id: this.id,
        },
      });
    },
    fetchBlobContent() {
      const baseUrl = getBaseURL();
      const url = joinPaths(baseUrl, this.blob.rawPath);

      axios
        .get(url)
        .then(res => {
          this.originalContent = res.data;
          this.content = res.data;
        })
        .catch(e => this.flashAPIFailure(e))
        .finally(() => {
          this.isContentLoading = false;
        });
    },
    flashAPIFailure(err) {
      Flash(sprintf(SNIPPET_BLOB_CONTENT_FETCH_ERROR, { err }));
      this.isContentLoading = false;
    },
  },
};
</script>
<template>
  <div class="form-group file-editor">
    <label>{{ s__('Snippets|File') }}</label>
    <div class="file-holder snippet">
      <blob-header-edit v-model="filePath" data-qa-selector="file_name_field" />
      <gl-loading-icon
        v-if="isContentLoading"
        :label="__('Loading snippet')"
        size="lg"
        class="loading-animation prepend-top-20 append-bottom-20"
      />
      <blob-content-edit v-else v-model="content" :file-name="filePath" />
    </div>
  </div>
</template>