Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-30 21:08:56 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-30 21:08:56 +0300
commit98d7cc758fb73239fb957c297446c811ab4150d9 (patch)
tree227a5e8efe35d2ac158e762397609a3f1754b224 /app/assets/javascripts/search
parent038366a0932c5f88019cc3db85382f26af3933e7 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/search')
-rw-r--r--app/assets/javascripts/search/group_filter/components/group_filter.vue124
-rw-r--r--app/assets/javascripts/search/group_filter/constants.js10
-rw-r--r--app/assets/javascripts/search/group_filter/index.js28
-rw-r--r--app/assets/javascripts/search/index.js2
-rw-r--r--app/assets/javascripts/search/store/actions.js16
-rw-r--r--app/assets/javascripts/search/store/index.js4
-rw-r--r--app/assets/javascripts/search/store/mutation_types.js3
-rw-r--r--app/assets/javascripts/search/store/mutations.js15
-rw-r--r--app/assets/javascripts/search/store/state.js2
9 files changed, 204 insertions, 0 deletions
diff --git a/app/assets/javascripts/search/group_filter/components/group_filter.vue b/app/assets/javascripts/search/group_filter/components/group_filter.vue
new file mode 100644
index 00000000000..4b7963c5187
--- /dev/null
+++ b/app/assets/javascripts/search/group_filter/components/group_filter.vue
@@ -0,0 +1,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>
diff --git a/app/assets/javascripts/search/group_filter/constants.js b/app/assets/javascripts/search/group_filter/constants.js
new file mode 100644
index 00000000000..9bd92eaa130
--- /dev/null
+++ b/app/assets/javascripts/search/group_filter/constants.js
@@ -0,0 +1,10 @@
+import { __ } from '~/locale';
+
+export const ANY_GROUP = Object.freeze({
+ id: null,
+ name: __('Any'),
+});
+
+export const GROUP_QUERY_PARAM = 'group_id';
+
+export const PROJECT_QUERY_PARAM = 'project_id';
diff --git a/app/assets/javascripts/search/group_filter/index.js b/app/assets/javascripts/search/group_filter/index.js
new file mode 100644
index 00000000000..9b009bc0305
--- /dev/null
+++ b/app/assets/javascripts/search/group_filter/index.js
@@ -0,0 +1,28 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import GroupFilter from './components/group_filter.vue';
+
+Vue.use(Translate);
+
+export default store => {
+ let initialGroup;
+ const el = document.getElementById('js-search-group-dropdown');
+
+ const { initialGroupData } = el.dataset;
+
+ initialGroup = JSON.parse(initialGroupData);
+ initialGroup = convertObjectPropsToCamelCase(initialGroup, { deep: true });
+
+ return new Vue({
+ el,
+ store,
+ render(createElement) {
+ return createElement(GroupFilter, {
+ props: {
+ initialGroup,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/search/index.js b/app/assets/javascripts/search/index.js
index 780d3ff0d25..7d175bace4f 100644
--- a/app/assets/javascripts/search/index.js
+++ b/app/assets/javascripts/search/index.js
@@ -1,9 +1,11 @@
import { queryToObject } from '~/lib/utils/url_utility';
import createStore from './store';
import initDropdownFilters from './dropdown_filter';
+import initGroupFilter from './group_filter';
export default () => {
const store = createStore({ query: queryToObject(window.location.search) });
initDropdownFilters(store);
+ initGroupFilter(store);
};
diff --git a/app/assets/javascripts/search/store/actions.js b/app/assets/javascripts/search/store/actions.js
new file mode 100644
index 00000000000..4bc8b2a9a5d
--- /dev/null
+++ b/app/assets/javascripts/search/store/actions.js
@@ -0,0 +1,16 @@
+import Api from '~/api';
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+import * as types from './mutation_types';
+
+export const fetchGroups = ({ commit }, search) => {
+ commit(types.REQUEST_GROUPS);
+ Api.groups(search)
+ .then(data => {
+ commit(types.RECEIVE_GROUPS_SUCCESS, data);
+ })
+ .catch(() => {
+ createFlash({ message: __('There was a problem fetching groups.') });
+ commit(types.RECEIVE_GROUPS_ERROR);
+ });
+};
diff --git a/app/assets/javascripts/search/store/index.js b/app/assets/javascripts/search/store/index.js
index 10cfb647a92..e0a7e488f9f 100644
--- a/app/assets/javascripts/search/store/index.js
+++ b/app/assets/javascripts/search/store/index.js
@@ -1,10 +1,14 @@
import Vue from 'vue';
import Vuex from 'vuex';
+import * as actions from './actions';
+import mutations from './mutations';
import createState from './state';
Vue.use(Vuex);
export const getStoreConfig = ({ query }) => ({
+ actions,
+ mutations,
state: createState({ query }),
});
diff --git a/app/assets/javascripts/search/store/mutation_types.js b/app/assets/javascripts/search/store/mutation_types.js
new file mode 100644
index 00000000000..8469f3517c0
--- /dev/null
+++ b/app/assets/javascripts/search/store/mutation_types.js
@@ -0,0 +1,3 @@
+export const REQUEST_GROUPS = 'REQUEST_GROUPS';
+export const RECEIVE_GROUPS_SUCCESS = 'RECEIVE_GROUPS_SUCCESS';
+export const RECEIVE_GROUPS_ERROR = 'RECEIVE_GROUPS_ERROR';
diff --git a/app/assets/javascripts/search/store/mutations.js b/app/assets/javascripts/search/store/mutations.js
new file mode 100644
index 00000000000..34fe14716f9
--- /dev/null
+++ b/app/assets/javascripts/search/store/mutations.js
@@ -0,0 +1,15 @@
+import * as types from './mutation_types';
+
+export default {
+ [types.REQUEST_GROUPS](state) {
+ state.fetchingGroups = true;
+ },
+ [types.RECEIVE_GROUPS_SUCCESS](state, data) {
+ state.fetchingGroups = false;
+ state.groups = data;
+ },
+ [types.RECEIVE_GROUPS_ERROR](state) {
+ state.fetchingGroups = false;
+ state.groups = [];
+ },
+};
diff --git a/app/assets/javascripts/search/store/state.js b/app/assets/javascripts/search/store/state.js
index 9115a613767..70a8aab9998 100644
--- a/app/assets/javascripts/search/store/state.js
+++ b/app/assets/javascripts/search/store/state.js
@@ -1,4 +1,6 @@
const createState = ({ query }) => ({
query,
+ groups: [],
+ fetchingGroups: false,
});
export default createState;