summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/search/group_filter/components/group_filter.vue
blob: 4b7963c51870408e65fdcc8b6e9fd4a1e3fa2ded (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
<script>
import {
  GlDropdown,
  GlDropdownItem,
  GlSearchBoxByType,
  GlLoadingIcon,
  GlIcon,
  GlSkeletonLoader,
  GlTooltipDirective,
} from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import { isEmpty } from 'lodash';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
import { ANY_GROUP, GROUP_QUERY_PARAM, PROJECT_QUERY_PARAM } from '../constants';

export default {
  name: 'GroupFilter',
  components: {
    GlDropdown,
    GlDropdownItem,
    GlSearchBoxByType,
    GlLoadingIcon,
    GlIcon,
    GlSkeletonLoader,
  },
  directives: {
    GlTooltip: GlTooltipDirective,
  },
  props: {
    initialGroup: {
      type: Object,
      required: false,
      default: () => ({}),
    },
  },
  data() {
    return {
      groupSearch: '',
    };
  },
  computed: {
    ...mapState(['groups', 'fetchingGroups']),
    selectedGroup: {
      get() {
        return isEmpty(this.initialGroup) ? ANY_GROUP : this.initialGroup;
      },
      set(group) {
        visitUrl(setUrlParams({ [GROUP_QUERY_PARAM]: group.id, [PROJECT_QUERY_PARAM]: null }));
      },
    },
  },
  methods: {
    ...mapActions(['fetchGroups']),
    isGroupSelected(group) {
      return group.id === this.selectedGroup.id;
    },
    handleGroupChange(group) {
      this.selectedGroup = group;
    },
  },
  ANY_GROUP,
};
</script>

<template>
  <gl-dropdown
    ref="groupFilter"
    class="gl-w-full"
    menu-class="gl-w-full!"
    toggle-class="gl-text-truncate gl-reset-line-height!"
    :header-text="__('Filter results by group')"
    @show="fetchGroups(groupSearch)"
  >
    <template #button-content>
      <span class="dropdown-toggle-text gl-flex-grow-1 gl-text-truncate">
        {{ selectedGroup.name }}
      </span>
      <gl-loading-icon v-if="fetchingGroups" inline class="mr-2" />
      <gl-icon
        v-if="!isGroupSelected($options.ANY_GROUP)"
        v-gl-tooltip
        name="clear"
        :title="__('Clear')"
        class="gl-text-gray-200! gl-hover-text-blue-800!"
        @click.stop="handleGroupChange($options.ANY_GROUP)"
      />
      <gl-icon name="chevron-down" />
    </template>
    <div class="gl-sticky gl-top-0 gl-z-index-1 gl-bg-white">
      <gl-search-box-by-type
        v-model="groupSearch"
        class="m-2"
        :debounce="500"
        @input="fetchGroups"
      />
      <gl-dropdown-item
        class="gl-border-b-solid gl-border-b-gray-100 gl-border-b-1 gl-pb-2! gl-mb-2"
        :is-check-item="true"
        :is-checked="isGroupSelected($options.ANY_GROUP)"
        @click="handleGroupChange($options.ANY_GROUP)"
      >
        {{ $options.ANY_GROUP.name }}
      </gl-dropdown-item>
    </div>
    <div v-if="!fetchingGroups">
      <gl-dropdown-item
        v-for="group in groups"
        :key="group.id"
        :is-check-item="true"
        :is-checked="isGroupSelected(group)"
        @click="handleGroupChange(group)"
      >
        {{ group.full_name }}
      </gl-dropdown-item>
    </div>
    <div v-if="fetchingGroups" class="mx-3 mt-2">
      <gl-skeleton-loader :height="100">
        <rect y="0" width="90%" height="20" rx="4" />
        <rect y="40" width="70%" height="20" rx="4" />
        <rect y="80" width="80%" height="20" rx="4" />
      </gl-skeleton-loader>
    </div>
  </gl-dropdown>
</template>