Commit 3f44c4ce authored by LUKE BENNETT's avatar LUKE BENNETT

Merge branch '38596-fix-backspace-visual-token-clearing' into 'master'

Clears visual token on second backspace

Closes #38596

See merge request gitlab-org/gitlab-ce!15348
parents 81dcd8ed 3e51c5e6
...@@ -127,7 +127,7 @@ class FilteredSearchManager { ...@@ -127,7 +127,7 @@ class FilteredSearchManager {
this.handleInputVisualTokenWrapper = this.handleInputVisualToken.bind(this); this.handleInputVisualTokenWrapper = this.handleInputVisualToken.bind(this);
this.checkForEnterWrapper = this.checkForEnter.bind(this); this.checkForEnterWrapper = this.checkForEnter.bind(this);
this.onClearSearchWrapper = this.onClearSearch.bind(this); this.onClearSearchWrapper = this.onClearSearch.bind(this);
this.checkForBackspaceWrapper = this.checkForBackspace.bind(this); this.checkForBackspaceWrapper = this.checkForBackspace.call(this);
this.removeSelectedTokenKeydownWrapper = this.removeSelectedTokenKeydown.bind(this); this.removeSelectedTokenKeydownWrapper = this.removeSelectedTokenKeydown.bind(this);
this.unselectEditTokensWrapper = this.unselectEditTokens.bind(this); this.unselectEditTokensWrapper = this.unselectEditTokens.bind(this);
this.editTokenWrapper = this.editToken.bind(this); this.editTokenWrapper = this.editToken.bind(this);
...@@ -180,22 +180,34 @@ class FilteredSearchManager { ...@@ -180,22 +180,34 @@ class FilteredSearchManager {
this.unbindStateEvents(); this.unbindStateEvents();
} }
checkForBackspace(e) { checkForBackspace() {
let backspaceCount = 0;
// closure for keeping track of the number of backspace keystrokes
return (e) => {
// 8 = Backspace Key // 8 = Backspace Key
// 46 = Delete Key // 46 = Delete Key
if (e.keyCode === 8 || e.keyCode === 46) { if (e.keyCode === 8 || e.keyCode === 46) {
const { lastVisualToken } = gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); const { lastVisualToken } = gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const { tokenName, tokenValue } = gl.DropdownUtils.getVisualTokenValues(lastVisualToken); const { tokenName, tokenValue } = gl.DropdownUtils.getVisualTokenValues(lastVisualToken);
const canEdit = tokenName && this.canEdit && this.canEdit(tokenName, tokenValue); const canEdit = tokenName && this.canEdit && this.canEdit(tokenName, tokenValue);
if (this.filteredSearchInput.value === '' && lastVisualToken && canEdit) { if (this.filteredSearchInput.value === '' && lastVisualToken && canEdit) {
backspaceCount += 1;
if (backspaceCount === 2) {
backspaceCount = 0;
this.filteredSearchInput.value = gl.FilteredSearchVisualTokens.getLastTokenPartial(); this.filteredSearchInput.value = gl.FilteredSearchVisualTokens.getLastTokenPartial();
gl.FilteredSearchVisualTokens.removeLastTokenPartial(); gl.FilteredSearchVisualTokens.removeLastTokenPartial();
} }
}
// Reposition dropdown so that it is aligned with cursor // Reposition dropdown so that it is aligned with cursor
this.dropdownManager.updateCurrentDropdownOffset(); this.dropdownManager.updateCurrentDropdownOffset();
} else {
backspaceCount = 0;
} }
};
} }
checkForEnter(e) { checkForEnter(e) {
......
---
title: Clears visual token on second backspace
merge_request:
author: Martin Wortschack
type: fixed
...@@ -176,6 +176,7 @@ describe 'Dropdown hint', :js do ...@@ -176,6 +176,7 @@ describe 'Dropdown hint', :js do
it 'reuses existing author text' do it 'reuses existing author text' do
filtered_search.send_keys('author:') filtered_search.send_keys('author:')
filtered_search.send_keys(:backspace) filtered_search.send_keys(:backspace)
filtered_search.send_keys(:backspace)
click_hint('author') click_hint('author')
expect_tokens([{ name: 'author' }]) expect_tokens([{ name: 'author' }])
...@@ -185,6 +186,7 @@ describe 'Dropdown hint', :js do ...@@ -185,6 +186,7 @@ describe 'Dropdown hint', :js do
it 'reuses existing assignee text' do it 'reuses existing assignee text' do
filtered_search.send_keys('assignee:') filtered_search.send_keys('assignee:')
filtered_search.send_keys(:backspace) filtered_search.send_keys(:backspace)
filtered_search.send_keys(:backspace)
click_hint('assignee') click_hint('assignee')
expect_tokens([{ name: 'assignee' }]) expect_tokens([{ name: 'assignee' }])
...@@ -194,6 +196,7 @@ describe 'Dropdown hint', :js do ...@@ -194,6 +196,7 @@ describe 'Dropdown hint', :js do
it 'reuses existing milestone text' do it 'reuses existing milestone text' do
filtered_search.send_keys('milestone:') filtered_search.send_keys('milestone:')
filtered_search.send_keys(:backspace) filtered_search.send_keys(:backspace)
filtered_search.send_keys(:backspace)
click_hint('milestone') click_hint('milestone')
expect_tokens([{ name: 'milestone' }]) expect_tokens([{ name: 'milestone' }])
...@@ -203,6 +206,7 @@ describe 'Dropdown hint', :js do ...@@ -203,6 +206,7 @@ describe 'Dropdown hint', :js do
it 'reuses existing label text' do it 'reuses existing label text' do
filtered_search.send_keys('label:') filtered_search.send_keys('label:')
filtered_search.send_keys(:backspace) filtered_search.send_keys(:backspace)
filtered_search.send_keys(:backspace)
click_hint('label') click_hint('label')
expect_tokens([{ name: 'label' }]) expect_tokens([{ name: 'label' }])
...@@ -212,6 +216,7 @@ describe 'Dropdown hint', :js do ...@@ -212,6 +216,7 @@ describe 'Dropdown hint', :js do
it 'reuses existing emoji text' do it 'reuses existing emoji text' do
filtered_search.send_keys('my-reaction:') filtered_search.send_keys('my-reaction:')
filtered_search.send_keys(:backspace) filtered_search.send_keys(:backspace)
filtered_search.send_keys(:backspace)
click_hint('my-reaction') click_hint('my-reaction')
expect_tokens([{ name: 'my-reaction' }]) expect_tokens([{ name: 'my-reaction' }])
......
...@@ -252,6 +252,7 @@ describe('Filtered Search Manager', () => { ...@@ -252,6 +252,7 @@ describe('Filtered Search Manager', () => {
it('removes last token', () => { it('removes last token', () => {
spyOn(gl.FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough(); spyOn(gl.FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
dispatchBackspaceEvent(input, 'keyup'); dispatchBackspaceEvent(input, 'keyup');
dispatchBackspaceEvent(input, 'keyup');
expect(gl.FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled(); expect(gl.FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled();
}); });
...@@ -259,6 +260,7 @@ describe('Filtered Search Manager', () => { ...@@ -259,6 +260,7 @@ describe('Filtered Search Manager', () => {
it('sets the input', () => { it('sets the input', () => {
spyOn(gl.FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough(); spyOn(gl.FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough();
dispatchDeleteEvent(input, 'keyup'); dispatchDeleteEvent(input, 'keyup');
dispatchDeleteEvent(input, 'keyup');
expect(gl.FilteredSearchVisualTokens.getLastTokenPartial).toHaveBeenCalled(); expect(gl.FilteredSearchVisualTokens.getLastTokenPartial).toHaveBeenCalled();
expect(input.value).toEqual('~bug'); expect(input.value).toEqual('~bug');
...@@ -276,6 +278,18 @@ describe('Filtered Search Manager', () => { ...@@ -276,6 +278,18 @@ describe('Filtered Search Manager', () => {
expect(gl.FilteredSearchVisualTokens.getLastTokenPartial).not.toHaveBeenCalled(); expect(gl.FilteredSearchVisualTokens.getLastTokenPartial).not.toHaveBeenCalled();
expect(input.value).toEqual('text'); expect(input.value).toEqual('text');
}); });
it('does not remove previous token on single backspace press', () => {
spyOn(gl.FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
spyOn(gl.FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough();
input.value = 't';
dispatchDeleteEvent(input, 'keyup');
expect(gl.FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled();
expect(gl.FilteredSearchVisualTokens.getLastTokenPartial).not.toHaveBeenCalled();
expect(input.value).toEqual('t');
});
}); });
describe('removeToken', () => { describe('removeToken', () => {
......
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