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:
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue')
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue137
1 files changed, 85 insertions, 52 deletions
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
index 857367a0721..e6a25362ff0 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
@@ -1,12 +1,18 @@
<script>
-import { GlDropdownForm, GlDropdownItem, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
+import {
+ GlDropdownForm,
+ GlDropdownItem,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+ GlIntersectionObserver,
+} from '@gitlab/ui';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import { debounce } from 'lodash';
import createFlash from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { __ } from '~/locale';
-import projectLabelsQuery from './graphql/project_labels.query.graphql';
+import { labelsQueries } from '~/sidebar/constants';
import LabelItem from './label_item.vue';
export default {
@@ -15,9 +21,12 @@ export default {
GlDropdownItem,
GlLoadingIcon,
GlSearchBoxByType,
+ GlIntersectionObserver,
LabelItem,
},
- inject: ['projectPath'],
+ model: {
+ prop: 'localSelectedLabels',
+ },
props: {
selectedLabels: {
type: Array,
@@ -27,30 +36,44 @@ export default {
type: Boolean,
required: true,
},
+ issuableType: {
+ type: String,
+ required: true,
+ },
+ localSelectedLabels: {
+ type: Array,
+ required: true,
+ },
+ fullPath: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
searchKey: '',
labels: [],
- localSelectedLabels: [...this.selectedLabels],
+ isVisible: false,
};
},
apollo: {
labels: {
- query: projectLabelsQuery,
+ query() {
+ return labelsQueries[this.issuableType].workspaceQuery;
+ },
variables() {
return {
- fullPath: this.projectPath,
+ fullPath: this.fullPath,
searchTerm: this.searchKey,
};
},
skip() {
- return this.searchKey.length === 1;
+ return this.searchKey.length === 1 || !this.isVisible;
},
update: (data) => data.workspace?.labels?.nodes || [],
async result() {
if (this.$refs.searchInput) {
- await this.$nextTick();
+ await this.$nextTick;
this.$refs.searchInput.focusInput();
}
},
@@ -64,7 +87,7 @@ export default {
return this.$apollo.queries.labels.loading;
},
localSelectedLabelsIds() {
- return this.localSelectedLabels.map((label) => label.id);
+ return this.localSelectedLabels.map((label) => getIdFromGraphQLId(label.id));
},
visibleLabels() {
if (this.searchKey) {
@@ -82,7 +105,6 @@ export default {
this.debouncedSearchKeyUpdate = debounce(this.setSearchKey, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
},
beforeDestroy() {
- this.$emit('setLabels', this.localSelectedLabels);
this.debouncedSearchKeyUpdate.cancel();
},
methods: {
@@ -109,16 +131,21 @@ export default {
}
},
updateSelectedLabels(label) {
+ let labels;
if (this.isLabelSelected(label)) {
- this.localSelectedLabels = this.localSelectedLabels.filter(
- ({ id }) => id !== getIdFromGraphQLId(label.id),
+ labels = this.localSelectedLabels.filter(
+ ({ id }) => id !== getIdFromGraphQLId(label.id) && id !== label.id,
);
} else {
- this.localSelectedLabels.push({
- ...label,
- id: getIdFromGraphQLId(label.id),
- });
+ labels = [
+ ...this.localSelectedLabels,
+ {
+ ...label,
+ id: getIdFromGraphQLId(label.id),
+ },
+ ];
}
+ this.$emit('input', labels);
},
handleLabelClick(label) {
this.updateSelectedLabels(label);
@@ -129,46 +156,52 @@ export default {
setSearchKey(value) {
this.searchKey = value;
},
+ onDropdownAppear() {
+ this.isVisible = true;
+ this.$refs.searchInput.focusInput();
+ },
},
};
</script>
<template>
- <gl-dropdown-form class="labels-select-contents-list js-labels-list">
- <gl-search-box-by-type
- ref="searchInput"
- :value="searchKey"
- :disabled="labelsFetchInProgress"
- data-qa-selector="dropdown_input_field"
- data-testid="dropdown-input-field"
- @input="debouncedSearchKeyUpdate"
- />
- <div ref="labelsListContainer" data-testid="dropdown-content">
- <gl-loading-icon
- v-if="labelsFetchInProgress"
- class="labels-fetch-loading gl-align-items-center gl-w-full gl-h-full"
- size="md"
+ <gl-intersection-observer @appear="onDropdownAppear">
+ <gl-dropdown-form class="labels-select-contents-list js-labels-list">
+ <gl-search-box-by-type
+ ref="searchInput"
+ :value="searchKey"
+ :disabled="labelsFetchInProgress"
+ data-qa-selector="dropdown_input_field"
+ data-testid="dropdown-input-field"
+ @input="debouncedSearchKeyUpdate"
/>
- <template v-else>
- <gl-dropdown-item
- v-for="label in visibleLabels"
- :key="label.id"
- :is-checked="isLabelSelected(label)"
- :is-check-centered="true"
- :is-check-item="true"
- data-testid="labels-list"
- @click.native.capture.stop="handleLabelClick(label)"
- >
- <label-item :label="label" />
- </gl-dropdown-item>
- <gl-dropdown-item
- v-show="showNoMatchingResultsMessage"
- class="gl-p-3 gl-text-center"
- data-testid="no-results"
- >
- {{ __('No matching results') }}
- </gl-dropdown-item>
- </template>
- </div>
- </gl-dropdown-form>
+ <div ref="labelsListContainer" data-testid="dropdown-content">
+ <gl-loading-icon
+ v-if="labelsFetchInProgress"
+ class="labels-fetch-loading gl-align-items-center gl-w-full gl-h-full gl-mb-3"
+ size="md"
+ />
+ <template v-else>
+ <gl-dropdown-item
+ v-for="label in visibleLabels"
+ :key="label.id"
+ :is-checked="isLabelSelected(label)"
+ :is-check-centered="true"
+ :is-check-item="true"
+ data-testid="labels-list"
+ @click.native.capture.stop="handleLabelClick(label)"
+ >
+ <label-item :label="label" />
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-show="showNoMatchingResultsMessage"
+ class="gl-p-3 gl-text-center"
+ data-testid="no-results"
+ >
+ {{ __('No matching results') }}
+ </gl-dropdown-item>
+ </template>
+ </div>
+ </gl-dropdown-form>
+ </gl-intersection-observer>
</template>