1<template>
2  <div class="table-filter d-inline-block">
3    <p class="d-inline-block mb-0">
4      <b-badge v-for="(tag, index) in tags" :key="index" pill>
5        {{ tag }}
6        <b-button-close
7          :disabled="dropdownVisible"
8          :aria-hidden="true"
9          @click="removeTag(tag)"
10        />
11      </b-badge>
12    </p>
13    <b-dropdown
14      variant="link"
15      no-caret
16      right
17      data-test-id="tableFilter-dropdown-options"
18      @hide="dropdownVisible = false"
19      @show="dropdownVisible = true"
20    >
21      <template #button-content>
22        <icon-filter />
23        {{ $t('global.action.filter') }}
24      </template>
25      <b-dropdown-form>
26        <b-form-group
27          v-for="(filter, index) of filters"
28          :key="index"
29          :label="filter.label"
30        >
31          <b-form-checkbox-group v-model="tags">
32            <b-form-checkbox
33              v-for="value in filter.values"
34              :key="value"
35              :value="value"
36              :data-test-id="`tableFilter-checkbox-${value}`"
37            >
38              <b-dropdown-item>
39                {{ value }}
40              </b-dropdown-item>
41            </b-form-checkbox>
42          </b-form-checkbox-group>
43        </b-form-group>
44      </b-dropdown-form>
45      <b-dropdown-item-button
46        variant="primary"
47        data-test-id="tableFilter-button-clearAll"
48        @click="clearAllTags"
49      >
50        {{ $t('global.action.clearAll') }}
51      </b-dropdown-item-button>
52    </b-dropdown>
53  </div>
54</template>
55
56<script>
57import IconFilter from '@carbon/icons-vue/es/settings--adjust/20';
58
59export default {
60  name: 'TableFilter',
61  components: { IconFilter },
62  props: {
63    filters: {
64      type: Array,
65      default: () => [],
66      validator: (prop) => {
67        return prop.every(
68          (filter) => 'label' in filter && 'values' in filter && 'key' in filter
69        );
70      },
71    },
72  },
73  data() {
74    return {
75      dropdownVisible: false,
76      tags: [],
77    };
78  },
79  watch: {
80    tags: {
81      handler() {
82        this.emitChange();
83      },
84      deep: true,
85    },
86  },
87  methods: {
88    removeTag(removedTag) {
89      this.tags = this.tags.filter((tag) => tag !== removedTag);
90    },
91    clearAllTags() {
92      this.tags = [];
93    },
94    emitChange() {
95      const activeFilters = this.filters.map(({ key, values }) => {
96        const activeValues = values.filter(
97          (value) => this.tags.indexOf(value) !== -1
98        );
99        return {
100          key,
101          values: activeValues,
102        };
103      });
104      this.$emit('filter-change', { activeFilters });
105    },
106  },
107};
108</script>
109
110<style lang="scss" scoped>
111.badge {
112  margin-right: $spacer / 2;
113}
114</style>
115