Commit 9bf856f4 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '350312-labels-widget-auto-select-first-label-when-searching' into 'master'

Labels widget - select first item on search when pressing enter

See merge request gitlab-org/gitlab!78425
parents 6b8b079e 13986d5b
...@@ -179,6 +179,9 @@ export default { ...@@ -179,6 +179,9 @@ export default {
this.searchKey = ''; this.searchKey = '';
this.setFocus(); this.setFocus();
}, },
selectFirstItem() {
this.$refs.dropdownContentsView.selectFirstItem();
},
}, },
}; };
</script> </script>
...@@ -204,11 +207,13 @@ export default { ...@@ -204,11 +207,13 @@ export default {
@toggleDropdownContentsCreateView="toggleDropdownContent" @toggleDropdownContentsCreateView="toggleDropdownContent"
@closeDropdown="$emit('closeDropdown')" @closeDropdown="$emit('closeDropdown')"
@input="debouncedSearchKeyUpdate" @input="debouncedSearchKeyUpdate"
@searchEnter="selectFirstItem"
/> />
</template> </template>
<template #default> <template #default>
<component <component
:is="dropdownContentsView" :is="dropdownContentsView"
ref="dropdownContentsView"
v-model="localSelectedLabels" v-model="localSelectedLabels"
:search-key="searchKey" :search-key="searchKey"
:allow-multiselect="allowMultiselect" :allow-multiselect="allowMultiselect"
......
...@@ -84,6 +84,9 @@ export default { ...@@ -84,6 +84,9 @@ export default {
showNoMatchingResultsMessage() { showNoMatchingResultsMessage() {
return Boolean(this.searchKey) && this.visibleLabels.length === 0; return Boolean(this.searchKey) && this.visibleLabels.length === 0;
}, },
shouldHighlightFirstItem() {
return this.searchKey !== '' && this.visibleLabels.length > 0;
},
}, },
methods: { methods: {
isLabelSelected(label) { isLabelSelected(label) {
...@@ -128,6 +131,11 @@ export default { ...@@ -128,6 +131,11 @@ export default {
onDropdownAppear() { onDropdownAppear() {
this.isVisible = true; this.isVisible = true;
}, },
selectFirstItem() {
if (this.shouldHighlightFirstItem) {
this.handleLabelClick(this.visibleLabels[0]);
}
},
}, },
}; };
</script> </script>
...@@ -143,11 +151,13 @@ export default { ...@@ -143,11 +151,13 @@ export default {
/> />
<template v-else> <template v-else>
<gl-dropdown-item <gl-dropdown-item
v-for="label in visibleLabels" v-for="(label, index) in visibleLabels"
:key="label.id" :key="label.id"
:is-checked="isLabelSelected(label)" :is-checked="isLabelSelected(label)"
:is-check-centered="true" :is-check-centered="true"
:is-check-item="true" :is-check-item="true"
:active="shouldHighlightFirstItem && index === 0"
active-class="is-focused"
data-testid="labels-list" data-testid="labels-list"
@click.native.capture.stop="handleLabelClick(label)" @click.native.capture.stop="handleLabelClick(label)"
> >
......
...@@ -83,6 +83,7 @@ export default { ...@@ -83,6 +83,7 @@ export default {
data-qa-selector="dropdown_input_field" data-qa-selector="dropdown_input_field"
data-testid="dropdown-input-field" data-testid="dropdown-input-field"
@input="$emit('input', $event)" @input="$emit('input', $event)"
@keydown.enter="$emit('searchEnter', $event)"
/> />
</div> </div>
</template> </template>
...@@ -110,6 +110,19 @@ describe('DropdownContentsLabelsView', () => { ...@@ -110,6 +110,19 @@ describe('DropdownContentsLabelsView', () => {
}); });
}); });
it('first item is highlighted when search is not empty', async () => {
createComponent({
queryHandler: jest.fn().mockResolvedValue(workspaceLabelsQueryResponse),
searchKey: 'Label',
});
await makeObserverAppear();
await waitForPromises();
await nextTick();
expect(findLabelsList().exists()).toBe(true);
expect(findFirstLabel().attributes('active')).toBe('true');
});
it('when search returns 0 results', async () => { it('when search returns 0 results', async () => {
createComponent({ createComponent({
queryHandler: jest.fn().mockResolvedValue({ queryHandler: jest.fn().mockResolvedValue({
......
...@@ -47,6 +47,26 @@ RSpec.shared_examples 'labels sidebar widget' do ...@@ -47,6 +47,26 @@ RSpec.shared_examples 'labels sidebar widget' do
end end
end end
it 'adds first label by pressing enter when search' do
within(labels_widget) do
page.within('[data-testid="value-wrapper"]') do
expect(page).not_to have_content(development.name)
end
fill_in 'Search', with: 'Devel'
sleep 1
expect(page.all(:css, '[data-testid="dropdown-content"] .gl-new-dropdown-item').length).to eq(1)
find_field('Search').native.send_keys(:enter)
click_button 'Close'
wait_for_requests
page.within('[data-testid="value-wrapper"]') do
expect(page).to have_content(development.name)
end
end
end
it 'escapes XSS when viewing issuable labels' do it 'escapes XSS when viewing issuable labels' do
page.within(labels_widget) do page.within(labels_widget) do
expect(page).to have_content '<script>alert("xss");</script>' expect(page).to have_content '<script>alert("xss");</script>'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment