Skip to content

Commit

Permalink
[#53767] ensure focus for autocompleter and multi select
Browse files Browse the repository at this point in the history
  • Loading branch information
EinLama committed Oct 21, 2024
1 parent 7fb084c commit 9bca254
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 21 deletions.
1 change: 1 addition & 0 deletions app/views/filters/_autocomplete.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# Stimulus controller.
}.merge(autocomplete_options.except(:component)),
class: 'form--field',
id: "#{filter.name}_value",
data: {
'filter-autocomplete': true,
'filter--filters-form-target': 'filterValueContainer',
Expand Down
3 changes: 2 additions & 1 deletion app/views/filters/list/_select.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
{
class: 'form--select -slim',
'data-filter--filters-form-target': 'filterValueSelect',
'data-filter-name': filter.name
'data-filter-name': filter.name,
id: "#{filter.name}_value"
}]
if multi_value
select_options.third[:multiple] = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,16 +214,27 @@ export default class FiltersFormController extends Controller {
// Takes an Element and tries to find the next input or select child element. This should be the filter value.
// If found, it will be focused.
focusFilterValueIfPossible(element:undefined|HTMLElement) {
if (!element) { return; }
if (!element) return;

// Try different selectors for various filter styles. The order is important as some selectors match unwanted
// hidden fields when used too early in the chain.
const selectors = [
'.advanced-filters--filter-value ng-select input',
'.advanced-filters--filter-value input',
'.advanced-filters--filter-value select',
];

const valueField = element.querySelector('.advanced-filters--filter-value input') as HTMLInputElement;
if (valueField) {
valueField.focus();
return;
}
selectors.some((selector) => {
const target = element.querySelector(selector) as HTMLElement;

const select = element.querySelector('.advanced-filters--filter-value select') as HTMLSelectElement;
select?.focus();
if (target) {
target.focus();
// We have found and focused our element, abort the iteration.
return true;
}

return false;
});
}

removeFilter({ params: { filterName } }:{ params:{ filterName:string } }) {
Expand Down
27 changes: 15 additions & 12 deletions spec/features/projects/projects_index_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -877,42 +877,45 @@ def load_and_open_filters(user)

# switching to multiselect keeps the current selection
cf_filter = page.find("li[data-filter-name='#{list_custom_field.column_name}']")

select_value_id = "#{list_custom_field.column_name}_value"

within(cf_filter) do
# Initial filter is a 'single select'
expect(cf_filter.find(:select, "value")).not_to be_multiple
expect(cf_filter.find(:select, select_value_id)).not_to be_multiple
click_on "Toggle multiselect"
# switching to multiselect keeps the current selection
expect(cf_filter.find(:select, "value")).to be_multiple
expect(cf_filter).to have_select("value", selected: list_custom_field.possible_values[2].value)
expect(cf_filter.find(:select, select_value_id)).to be_multiple
expect(cf_filter).to have_select(select_value_id, selected: list_custom_field.possible_values[2].value)

select list_custom_field.possible_values[3].value, from: "value"
select list_custom_field.possible_values[3].value, from: select_value_id
end
wait_for_reload

cf_filter = page.find("li[data-filter-name='#{list_custom_field.column_name}']")
within(cf_filter) do
# Query has two values for that filter, so it should show a 'multi select'.
expect(cf_filter.find(:select, "value")).to be_multiple
expect(cf_filter.find(:select, select_value_id)).to be_multiple
expect(cf_filter)
.to have_select("value",
.to have_select(select_value_id,
selected: [list_custom_field.possible_values[2].value,
list_custom_field.possible_values[3].value])

# switching to single select keeps the first selection
select list_custom_field.possible_values[1].value, from: "value"
unselect list_custom_field.possible_values[2].value, from: "value"
select list_custom_field.possible_values[1].value, from: select_value_id
unselect list_custom_field.possible_values[2].value, from: select_value_id

click_on "Toggle multiselect"
expect(cf_filter.find(:select, "value")).not_to be_multiple
expect(cf_filter).to have_select("value", selected: list_custom_field.possible_values[1].value)
expect(cf_filter).to have_no_select("value", selected: list_custom_field.possible_values[3].value)
expect(cf_filter.find(:select, select_value_id)).not_to be_multiple
expect(cf_filter).to have_select(select_value_id, selected: list_custom_field.possible_values[1].value)
expect(cf_filter).to have_no_select(select_value_id, selected: list_custom_field.possible_values[3].value)
end
wait_for_reload

cf_filter = page.find("li[data-filter-name='#{list_custom_field.column_name}']")
within(cf_filter) do
# Query has one value for that filter, so it should show a 'single select'.
expect(cf_filter.find(:select, "value")).not_to be_multiple
expect(cf_filter.find(:select, select_value_id)).not_to be_multiple
end

# CF date filter work (at least for one operator)
Expand Down

0 comments on commit 9bca254

Please sign in to comment.