debian-mirror-gitlab/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue

117 lines
3 KiB
Vue
Raw Normal View History

2019-07-07 11:18:12 +05:30
<script>
2020-04-22 19:07:51 +05:30
import { debounce } from 'lodash';
2019-12-26 22:10:19 +05:30
import { GlLoadingIcon, GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
2019-07-07 11:18:12 +05:30
import ProjectListItem from './project_list_item.vue';
const SEARCH_INPUT_TIMEOUT_MS = 500;
export default {
name: 'ProjectSelector',
components: {
GlLoadingIcon,
2019-12-04 20:38:33 +05:30
GlSearchBoxByType,
2019-12-26 22:10:19 +05:30
GlInfiniteScroll,
2019-07-07 11:18:12 +05:30
ProjectListItem,
},
props: {
projectSearchResults: {
type: Array,
required: true,
},
selectedProjects: {
type: Array,
required: true,
},
showNoResultsMessage: {
type: Boolean,
required: false,
default: false,
},
showMinimumSearchQueryMessage: {
type: Boolean,
required: false,
default: false,
},
showLoadingIndicator: {
type: Boolean,
required: false,
default: false,
},
showSearchErrorMessage: {
type: Boolean,
required: false,
default: false,
},
2019-12-26 22:10:19 +05:30
totalResults: {
type: Number,
required: false,
default: 0,
},
2019-07-07 11:18:12 +05:30
},
data() {
return {
searchQuery: '',
};
},
methods: {
projectClicked(project) {
this.$emit('projectClicked', project);
},
2019-12-26 22:10:19 +05:30
bottomReached() {
this.$emit('bottomReached');
},
2019-07-07 11:18:12 +05:30
isSelected(project) {
2020-04-22 19:07:51 +05:30
return this.selectedProjects.some(({ id }) => project.id === id);
2019-07-07 11:18:12 +05:30
},
2020-04-22 19:07:51 +05:30
onInput: debounce(function debouncedOnInput() {
2019-07-07 11:18:12 +05:30
this.$emit('searched', this.searchQuery);
}, SEARCH_INPUT_TIMEOUT_MS),
},
};
</script>
<template>
<div>
2019-12-04 20:38:33 +05:30
<gl-search-box-by-type
2019-07-07 11:18:12 +05:30
v-model="searchQuery"
:placeholder="__('Search your projects')"
type="search"
2019-12-04 20:38:33 +05:30
class="mb-3"
2019-07-07 11:18:12 +05:30
autofocus
@input="onInput"
/>
<div class="d-flex flex-column">
2020-04-22 19:07:51 +05:30
<gl-loading-icon v-if="showLoadingIndicator" size="sm" class="py-2 px-4" />
2019-12-26 22:10:19 +05:30
<gl-infinite-scroll
:max-list-height="402"
:fetched-items="projectSearchResults.length"
:total-items="totalResults"
@bottomReached="bottomReached"
>
<div v-if="!showLoadingIndicator" slot="items" class="d-flex flex-column">
<project-list-item
v-for="project in projectSearchResults"
:key="project.id"
:selected="isSelected(project)"
:project="project"
:matcher="searchQuery"
class="js-project-list-item"
@click="projectClicked(project)"
/>
</div>
</gl-infinite-scroll>
2019-07-07 11:18:12 +05:30
<div v-if="showNoResultsMessage" class="text-muted ml-2 js-no-results-message">
{{ __('Sorry, no projects matched your search') }}
</div>
<div
v-if="showMinimumSearchQueryMessage"
class="text-muted ml-2 js-minimum-search-query-message"
>
{{ __('Enter at least three characters to search') }}
</div>
<div v-if="showSearchErrorMessage" class="text-danger ml-2 js-search-error-message">
{{ __('Something went wrong, unable to search projects') }}
</div>
</div>
</div>
</template>