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              {{ value }}
39            </b-form-checkbox>
40          </b-form-checkbox-group>
41        </b-form-group>
42      </b-dropdown-form>
43      <b-dropdown-item-button
44        variant="primary"
45        data-test-id="tableFilter-button-clearAll"
46        @click="clearAllTags"
47      >
48        {{ $t('global.action.clearAll') }}
49      </b-dropdown-item-button>
50    </b-dropdown>
51  </div>
52</template>
53
54<script>
55import IconFilter from '@carbon/icons-vue/es/settings--adjust/20';
56
57export default {
58  name: 'TableFilter',
59  components: { IconFilter },
60  props: {
61    filters: {
62      type: Array,
63      default: () => [],
64      validator: (prop) => {
65        return prop.every(
66          (filter) => 'label' in filter && 'values' in filter && 'key' in filter
67        );
68      },
69    },
70  },
71  data() {
72    return {
73      dropdownVisible: false,
74      tags: [],
75    };
76  },
77  watch: {
78    tags: {
79      handler() {
80        this.emitChange();
81      },
82      deep: true,
83    },
84  },
85  methods: {
86    removeTag(removedTag) {
87      this.tags = this.tags.filter((tag) => tag !== removedTag);
88    },
89    clearAllTags() {
90      this.tags = [];
91    },
92    emitChange() {
93      const activeFilters = this.filters.map(({ key, values }) => {
94        const activeValues = values.filter(
95          (value) => this.tags.indexOf(value) !== -1
96        );
97        return {
98          key,
99          values: activeValues,
100        };
101      });
102      this.$emit('filter-change', { activeFilters });
103    },
104  },
105};
106</script>
107
108<style lang="scss" scoped>
109.badge {
110  margin-right: $spacer / 2;
111}
112</style>
113