summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared/components/metric_images/metric_images_tab.vue
blob: 3e796a73f720cba3174d626d5025847b0820e6a3 (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
118
119
<script>
import { GlFormGroup, GlFormInput, GlLoadingIcon, GlModal, GlTab } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import { __, s__ } from '~/locale';
import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
import MetricImagesTable from '~/vue_shared/components/metric_images/metric_images_table.vue';

export default {
  components: {
    GlFormGroup,
    GlFormInput,
    GlLoadingIcon,
    GlModal,
    GlTab,
    MetricImagesTable,
    UploadDropzone,
  },
  inject: ['canUpdate', 'projectId', 'iid'],
  data() {
    return {
      currentFiles: [],
      modalVisible: false,
      modalUrl: '',
      modalUrlText: '',
    };
  },
  computed: {
    ...mapState(['metricImages', 'isLoadingMetricImages', 'isUploadingImage']),
    actionPrimaryProps() {
      return {
        text: this.$options.i18n.modalUpload,
        attributes: {
          loading: this.isUploadingImage,
          disabled: this.isUploadingImage,
          category: 'primary',
          variant: 'confirm',
        },
      };
    },
  },
  mounted() {
    this.setInitialData({ modelIid: this.iid, projectId: this.projectId });
    this.fetchImages();
  },
  methods: {
    ...mapActions(['fetchImages', 'uploadImage', 'setInitialData']),
    clearInputs() {
      this.modalVisible = false;
      this.modalUrl = '';
      this.modalUrlText = '';
      this.currentFile = false;
    },
    openMetricDialog(files) {
      this.modalVisible = true;
      this.currentFiles = files;
    },
    async onUpload() {
      try {
        await this.uploadImage({
          files: this.currentFiles,
          url: this.modalUrl,
          urlText: this.modalUrlText,
        });
        // Error case handled within action
      } finally {
        this.clearInputs();
      }
    },
  },
  i18n: {
    modalUpload: __('Upload'),
    modalCancel: __('Cancel'),
    modalTitle: s__('Incidents|Add image details'),
    modalDescription: s__(
      "Incidents|Add text or a link to display with your image. If you don't add either, the file name displays instead.",
    ),
    dropDescription: s__(
      'Incidents|Drop or %{linkStart}upload%{linkEnd} a metric screenshot to attach it to the incident',
    ),
  },
};
</script>

<template>
  <gl-tab :title="s__('Incident|Metrics')" data-testid="metrics-tab">
    <div v-if="isLoadingMetricImages">
      <gl-loading-icon class="gl-p-5" size="sm" />
    </div>
    <gl-modal
      modal-id="upload-metric-modal"
      size="sm"
      :action-primary="actionPrimaryProps"
      :action-cancel="{ text: $options.i18n.modalCancel }"
      :title="$options.i18n.modalTitle"
      :visible="modalVisible"
      @hidden="clearInputs"
      @primary.prevent="onUpload"
    >
      <p>{{ $options.i18n.modalDescription }}</p>
      <gl-form-group :label="__('Text (optional)')" label-for="upload-text-input">
        <gl-form-input id="upload-text-input" v-model="modalUrlText" />
      </gl-form-group>

      <gl-form-group
        :label="__('Link (optional)')"
        label-for="upload-url-input"
        :description="s__('Incidents|Must start with http or https')"
      >
        <gl-form-input id="upload-url-input" v-model="modalUrl" />
      </gl-form-group>
    </gl-modal>
    <metric-images-table v-for="metric in metricImages" :key="metric.id" v-bind="metric" />
    <upload-dropzone
      v-if="canUpdate"
      :drop-description-message="$options.i18n.dropDescription"
      @change="openMetricDialog"
    />
  </gl-tab>
</template>