summaryrefslogtreecommitdiff
path: root/src/components/Global/TableFilter.vue
blob: bf72952271c90e76accf50084532fafd12618e3f (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
120
121
122
123
124
125
126
127
128
129
130
131
<template>
  <div class="table-filter d-inline-block">
    <p class="d-inline-block mb-0">
      <b-badge v-for="(tag, index) in tags" :key="index" pill>
        {{ tag }}
        <b-button-close
          :disabled="dropdownVisible"
          :aria-hidden="true"
          @click="removeTag(tag)"
        />
      </b-badge>
    </p>
    <b-dropdown
      variant="link"
      no-caret
      right
      data-test-id="tableFilter-dropdown-options"
      @hide="dropdownVisible = false"
      @show="dropdownVisible = true"
    >
      <template #button-content>
        <icon-filter />
        {{ $t('global.action.filter') }}
      </template>
      <b-dropdown-form>
        <b-form-group
          v-for="(filter, index) of filters"
          :key="index"
          :label="filter.label"
        >
          <b-form-checkbox-group v-model="tags">
            <b-form-checkbox
              v-for="value in filter.values"
              :key="value"
              :value="value"
              :data-test-id="`tableFilter-checkbox-${value}`"
              @change="onChange($event, { filter, value })"
            >
              {{ value }}
            </b-form-checkbox>
          </b-form-checkbox-group>
        </b-form-group>
      </b-dropdown-form>
      <b-dropdown-item-button
        variant="primary"
        data-test-id="tableFilter-button-clearAll"
        @click="clearAllTags"
      >
        {{ $t('global.action.clearAll') }}
      </b-dropdown-item-button>
    </b-dropdown>
  </div>
</template>

<script>
import IconFilter from '@carbon/icons-vue/es/settings--adjust/20';

export default {
  name: 'TableFilter',
  components: { IconFilter },
  props: {
    filters: {
      type: Array,
      default: () => [],
      validator: (prop) => {
        return prop.every(
          (filter) => 'label' in filter && 'values' in filter && 'key' in filter
        );
      },
    },
  },
  data() {
    return {
      dropdownVisible: false,
      activeFilters: this.filters.map(({ key }) => {
        return {
          key,
          values: [],
        };
      }),
    };
  },
  computed: {
    tags: {
      get() {
        return this.activeFilters.reduce((arr, filter) => {
          return [...arr, ...filter.values];
        }, []);
      },
      set(value) {
        return value;
      },
    },
  },
  methods: {
    removeTag(tag) {
      this.activeFilters.forEach((filter) => {
        filter.values = filter.values.filter((val) => val !== tag);
      });
      this.emitChange();
    },
    clearAllTags() {
      this.activeFilters.forEach((filter) => {
        filter.values = [];
      });
      this.emitChange();
    },
    emitChange() {
      this.$emit('filter-change', {
        activeFilters: this.activeFilters,
      });
    },
    onChange(checked, { filter: { key }, value }) {
      this.activeFilters.forEach((filter) => {
        if (filter.key === key) {
          checked
            ? filter.values.push(value)
            : (filter.values = filter.values.filter((val) => val !== value));
        }
      });
      this.emitChange();
    },
  },
};
</script>

<style lang="scss" scoped>
.badge {
  margin-right: $spacer / 2;
}
</style>