Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redesign filter sidebar #112

Merged
merged 1 commit into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 83 additions & 24 deletions app/assets/stylesheets/partials/_filters.scss
Original file line number Diff line number Diff line change
@@ -1,48 +1,107 @@
#filters {
h3 {
.category {
position: relative;
margin-bottom: 0.5em;
border: 1px solid $gray-l3;
border-radius: 3px;
}

button.filter-label {
display: flex;
justify-content: space-between;
width: 100%;
text-align: left;
margin-bottom: 0;
padding: 1rem;
border: 0;
color: $black;
background-color: $gray-l4;
font-size: $fs-small;
font-weight: $fw-bold;

&::after {
font-family: FontAwesome;
content: '\f054';
}
&.expanded {
border: 0;
border-radius: 0;
border-bottom: 1px solid $gray-l3;
& + .filter-options {
max-height: 200px;
overflow-y: scroll;
scrollbar-gutter: auto;
scroll-behavior: auto;
}
}
&.expanded:after {
font-family: FontAwesome;
content: '\f078';
}
&::-webkit-details-marker {
display: none;
}
}

.category {
margin-bottom: 1em;
.filter-options {
max-height: 0;
transition: max-height 0.5s ease-in-out;
overflow: hidden;
}

ul.category-terms {
border-collapse: separate;
border-spacing: 0px 4px;
display: table;
margin-bottom: 0;
table-layout: fixed;
width: 100%;
margin: 1rem;
margin-bottom: 2rem;

li.term {
display: contents;
display: block;
width: 100%;
float: none;
margin: 0;
font-size: $fs-small;

a {
display: table-row;
display: block;
width: 100%;
text-decoration: none;

&:hover,
&:focus,
&.applied {
background: #000;
color: #fff;
}

span {
display: table-cell;
padding: 2px;

&.name {
width: 75%;
text-decoration: underline;
}
&.name {
width: 100%;
color: $blue;
}

&.count {
min-width: 25%;
text-align: right;
text-decoration: none;
&.count {
text-align: right;
text-decoration: none;
}
}

&:hover,
&:focus {
background: #000;
span {
color: #fff;
}
}
&.applied {
.name {
color: #000;
&:hover,
&:focus {
color: #fff;
}
}
.name::after {
font-family: FontAwesome;
margin-left: 0.5rem;
content: '\f00d';
}
}
}
}
Expand Down
16 changes: 14 additions & 2 deletions app/helpers/filter_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,22 @@ def nice_labels
}
end

def remove_filter(query, filter)
def remove_filter(query, filter, term)
new_query = query.deep_dup
new_query[:page] = 1
new_query.delete filter.to_sym

if new_query[filter].length > 1
new_query[filter].delete(term) # If more than one term is filtered, we only delete the selected term
else
new_query.delete(filter) # If only one term is filtered, delete the entire filter from the query
end

new_query
end

def filter_applied?(terms, term)
return if terms.blank?

terms.include?(term)
end
end
5 changes: 5 additions & 0 deletions app/helpers/results_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module ResultsHelper
def results_summary(hits)
hits.to_i >= 10_000 ? '10,000+ items' : "#{number_with_delimiter(hits)} items"
end
end
40 changes: 25 additions & 15 deletions app/views/search/_filter.html.erb
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
<% return if values.empty? %>

<div class="category">
<h3><%= nice_labels[category] || category %></h3>
<ul class="category-terms list-unbulleted">
<% values.each do |term| %>
<li class="term">
<a href="<%= results_path(add_filter(@enhanced_query, category, term['key'])) %>" class="<%= "applied" if @enhanced_query[category.to_sym] == term['key'] %>">
<span class="name"><%= term['key'] %></span>
<span class="count"><%= term['docCount'] %> <span class="sr">records</span></span>
</a>
</li>
<% end %>
</ul>
<% if @enhanced_query[category.to_sym].present? %>
<div><%= link_to "Show all #{nice_labels[category]&.downcase || category}", results_path(remove_filter(@enhanced_query, category)) %>
</div>
<% end %>
<button class="filter-label <%= 'expanded' if @enhanced_query[category.to_sym].present? || first == true %>"
onclick="toggleFilter(this)"><%= nice_labels[category] || category %></button>
<div class="filter-options">
<ul class="category-terms list-unbulleted">
<% values.each do |term| %>
<li class="term">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure why, but the scroll overlaps the content initially in Safari. If I select an element (via tab for example) it reflows the display and looks correct.

Expanded but with nothing selected the scrollbar overlaps the content
Screenshot 2024-02-05 at 2 35 09 PM

Tabbed into an element, the overlap is fixed
Screenshot 2024-02-05 at 3 42 42 PM

<% if filter_applied?(@enhanced_query[category.to_sym], term['key']) %>
<a href="<%= results_path(remove_filter(@enhanced_query, category.to_sym, term['key'])) %>" class="applied">
<span class="sr">Remove applied filter?</span>
<% else %>
<a href="<%= results_path(add_filter(@enhanced_query, category.to_sym, term['key'])) %>">
<% end %>
<span class="name"><%= term['key'] %></span>
<span class="count"><%= term['docCount'] %> <span class="sr">records</span></span>
</a>
</li>
<% end %>
</ul>
</div>
</div>

<script>
function toggleFilter(e) {
e.parentNode.getElementsByClassName("filter-label")[0].classList.toggle("expanded");
}
</script>
1 change: 0 additions & 1 deletion app/views/search/_filter_empty.html.erb

This file was deleted.

28 changes: 16 additions & 12 deletions app/views/search/results.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@
<%= render(partial: 'shared/error', collection: @errors) %>

<div class="<%= 'layout-1q3q' if @filters.present? %> layout-band top-space">
<% if @filters.present? %>
<aside class="col1q filter-container">
<div id="filters">
<h2 class="hd-3">Filter your results</h2>
<h3 class="hd-4"><em><%= results_summary(@pagination[:hits]) %></em></h3>
<% @filters&.each_with_index do |(category, values), index| %>
<% if index == 0 %>
<%= render(partial: 'search/filter', locals: {category: category, values: values, first: true}) %>
<% else %>
<%= render(partial: 'search/filter', locals: {category: category, values: values, first: false }) %>
<% end %>
<% end %>
</div>
</aside>
<% end %>

<div class="col3q wrap-results">
<% if @results.present? %>
<ul id="results" class="list-unbulleted">
Expand All @@ -61,18 +77,6 @@
<% end %>
</div>

<% if @filters.present? %>
<aside class="col1q filter-container">
<div id="filters">
<h2>Available filters</h2>
<% @filters&.each do |category, values| %>
<%= render(partial: 'search/filter', locals: {category: category, values: values}) %>
<% end %>
</div>
</aside>
<% end %>
</div>

<% if @results.present? %>
<div id="pagination">
<%= render partial: "pagination" %>
Expand Down
2 changes: 1 addition & 1 deletion test/controllers/search_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class SearchControllerTest < ActionDispatch::IntegrationTest
get '/results?q=data'
assert_response :success
assert_select '#filters'
assert_select '#filters .category h3', { minimum: 1 }
assert_select '#filters .category .filter-label', { minimum: 1 }
end
end

Expand Down
49 changes: 45 additions & 4 deletions test/helpers/filter_helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,66 @@ class FilterHelperTest < ActionView::TestCase
original_query = {
page: 1,
q: 'data',
contentType: 'dataset'
contentType: ['dataset']
}
expected_query = {
page: 1,
q: 'data'
}
assert_equal expected_query, remove_filter(original_query, 'contentType')
assert_equal expected_query, remove_filter(original_query, :contentType, 'dataset')
end

test 'remove_filter will reset a page count when called' do
original_query = {
page: 3,
q: 'data',
contentType: 'dataset'
contentType: ['dataset']
}
expected_query = {
page: 1,
q: 'data'
}
assert_equal expected_query, remove_filter(original_query, 'contentType')
assert_equal expected_query, remove_filter(original_query, :contentType, 'dataset')
end

test 'remove_filter removes only one filter parameter if multiple are applied' do
original_query = {
page: 3,
q: 'data',
contentType: ['dataset', 'microfiche', 'vinyl record']
}
expected_query = {
page: 1,
q: 'data',
contentType: ['dataset', 'vinyl record']
}
assert_equal expected_query, remove_filter(original_query, :contentType, 'microfiche')
end

test 'filter_applied? returns true if a filter is applied' do
query = {
page: 3,
q: 'data',
contentType: ['dataset']
}
assert filter_applied?(query[:contentType], 'dataset')
end

test 'filter_applied? returns false if the filter does not include the target term' do
query = {
page: 3,
q: 'data',
contentType: ['dataset']
}
assert_not filter_applied?(query[:contentType], 'microfiche')
end

# This is an unlikely state to reach, but better safe than sorry
test 'filter_applied? returns false if no filter is supplied in the query' do
query = {
page: 3,
q: 'data',
}
assert_not filter_applied?(query[:contentType], 'dataset')
end
end
20 changes: 20 additions & 0 deletions test/helpers/results_helper_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'test_helper'

class ResultsHelperTest < ActionView::TestCase
include ResultsHelper

test 'if number of hits is equal to 10,000, results summary returns "10,000+"' do
hits = 10000
assert_equal '10,000+ items', results_summary(hits)
end

test 'if number of hits is above 10,000, results summary returns "10,000+"' do
hits = 10500
assert_equal '10,000+ items', results_summary(hits)
end

test 'if number of hits is below 10,000, results summary returns actual number of results' do
hits = 9000
assert_equal '9,000 items', results_summary(hits)
end
end
Loading