summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
blob: 9d537a4ef2c60d2868fe510a9cf589bd349b6eee (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
<script>
import { mapGetters, mapActions } from 'vuex';
import { GlLabel } from '@gitlab/ui';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
import { isScopedLabel } from '~/lib/utils/common_utils';
import createFlash from '~/flash';
import { __ } from '~/locale';

export default {
  components: {
    BoardEditableItem,
    LabelsSelect,
    GlLabel,
  },
  data() {
    return {
      loading: false,
    };
  },
  inject: ['labelsFetchPath', 'labelsManagePath', 'labelsFilterBasePath'],
  computed: {
    ...mapGetters(['activeIssue', 'projectPathForActiveIssue']),
    selectedLabels() {
      const { labels = [] } = this.activeIssue;

      return labels.map(label => ({
        ...label,
        id: getIdFromGraphQLId(label.id),
      }));
    },
    issueLabels() {
      const { labels = [] } = this.activeIssue;

      return labels.map(label => ({
        ...label,
        scoped: isScopedLabel(label),
      }));
    },
  },
  methods: {
    ...mapActions(['setActiveIssueLabels']),
    async setLabels(payload) {
      this.loading = true;
      this.$refs.sidebarItem.collapse();

      try {
        const addLabelIds = payload.filter(label => label.set).map(label => label.id);
        const removeLabelIds = this.selectedLabels
          .filter(label => !payload.find(selected => selected.id === label.id))
          .map(label => label.id);

        const input = { addLabelIds, removeLabelIds, projectPath: this.projectPathForActiveIssue };
        await this.setActiveIssueLabels(input);
      } catch (e) {
        createFlash({ message: __('An error occurred while updating labels.') });
      } finally {
        this.loading = false;
      }
    },
    async removeLabel(id) {
      this.loading = true;

      try {
        const removeLabelIds = [getIdFromGraphQLId(id)];
        const input = { removeLabelIds, projectPath: this.projectPathForActiveIssue };
        await this.setActiveIssueLabels(input);
      } catch (e) {
        createFlash({ message: __('An error occurred when removing the label.') });
      } finally {
        this.loading = false;
      }
    },
  },
};
</script>

<template>
  <board-editable-item ref="sidebarItem" :title="__('Labels')" :loading="loading">
    <template #collapsed>
      <gl-label
        v-for="label in issueLabels"
        :key="label.id"
        :background-color="label.color"
        :title="label.title"
        :description="label.description"
        :scoped="label.scoped"
        :show-close-button="true"
        :disabled="loading"
        class="gl-mr-2 gl-mb-2"
        @close="removeLabel(label.id)"
      />
    </template>
    <template>
      <labels-select
        ref="labelsSelect"
        :allow-label-edit="false"
        :allow-label-create="false"
        :allow-multiselect="true"
        :allow-scoped-labels="true"
        :selected-labels="selectedLabels"
        :labels-fetch-path="labelsFetchPath"
        :labels-manage-path="labelsManagePath"
        :labels-filter-base-path="labelsFilterBasePath"
        :labels-list-title="__('Select label')"
        :dropdown-button-text="__('Choose labels')"
        variant="embedded"
        class="gl-display-block labels gl-w-full"
        @updateSelectedLabels="setLabels"
      >
        {{ __('None') }}
      </labels-select>
    </template>
  </board-editable-item>
</template>