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

Expand available filters, give applications the ability to filter and order via ENV #128

Merged
merged 3 commits into from
Mar 5, 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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ change as part of the work.

- `ABOUT_APP`: If populated, an 'about' partial containing the contents of this variable will render on
`basic_search#index`.
- `ACTIVE_FILTERS`: If populated, this list of strings defines which filters are shown to the user, and the order in which they appear. Values are case sensitive, and must match those used in the TIMDEX GraphQL query. Extraneous values will be ignored. If not populated, all filters will be shown.
- `FILTER_CONTENT_TYPE`: The name to use instead of "Content type" for that filter / aggregation.
- `FILTER_CONTRIBUTOR`: The name to use instead of "Contributor" for that filter / aggregation.
- `FILTER_FORMAT`: The name to use instead of "Format" for that filter / aggregation.
- `FILTER_LANGUAGE`: The name to use instead of "Language" for that filter / aggregation.
- `FILTER_LITERARY_FORM`: The name to use instead of "Literary form" for that filter / aggregation.
- `FILTER_SOURCE`: The name to use instead of "Source" for that filter / aggregation.
- `FILTER_SUBJECT`: The name to use instead of "Subject" for that filter / aggregation.
- `GDT`: Enables features related to geospatial data discovery. Setting this variable with any value will trigger GDT
mode (e.g., `GDT=false` will still enable GDT features). Note that this is currently intended _only_ for the GDT app and
may have unexpected consequences if applied to other TIMDEX UI apps.
Expand Down
16 changes: 15 additions & 1 deletion app/controllers/search_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ def results

private

def active_filters
ENV.fetch('ACTIVE_FILTERS', '').split(',').map(&:strip)
end

def extract_errors(response)
response&.errors&.details&.to_h&.dig('data')
end
Expand All @@ -33,17 +37,27 @@ def extract_filters(response)
aggs = response&.data&.search&.to_h&.dig('aggregations')
return if aggs.blank?

aggs = reorder_filters(aggs, active_filters) unless active_filters.blank?

# We use aggregations to determine which terms can be filtered. However, agg names do not include 'filter', whereas
# our filter fields do (e.g., 'source' vs 'sourceFilter'). Because of this mismatch, we need to modify the
# aggregation key names before collecting them as filters, so that when a filter is applied, it searches the
# correct field name.
aggs.select { |_, agg_values| agg_values.present? }.transform_keys { |key| (key.dup << 'Filter').to_sym }
aggs
.select { |_, agg_values| agg_values.present? }
.transform_keys { |key| (key.dup << 'Filter').to_sym }
end

def extract_results(response)
response&.data&.search&.to_h&.dig('records')
end

def reorder_filters(aggs, active_filters)
aggs
.select { |key, _| active_filters.include?(key) }
.sort_by { |key, _| active_filters.index(key) }.to_h
end

def validate_q!
return if params[:advanced]&.strip.present?
return if params[:q]&.strip.present?
Expand Down
9 changes: 7 additions & 2 deletions app/helpers/filter_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ def add_filter(query, filter, term)

def nice_labels
{
contentTypeFilter: 'Content type',
sourceFilter: 'Source'
contentTypeFilter: ENV.fetch('FILTER_CONTENT_TYPE', 'Content type'),
contributorsFilter: ENV.fetch('FILTER_CONTRIBUTOR', 'Contributor'),
formatFilter: ENV.fetch('FILTER_FORMAT', 'Format'),
languagesFilter: ENV.fetch('FILTER_LANGUAGE', 'Language'),
literaryFormFilter: ENV.fetch('FILTER_LITERARY_FORM', 'Literary form'),
sourceFilter: ENV.fetch('FILTER_SOURCE', 'Source'),
subjectsFilter: ENV.fetch('FILTER_SUBJECT', 'Subject')
}
end

Expand Down
20 changes: 20 additions & 0 deletions app/models/timdex_search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,30 @@ class TimdexSearch < TimdexBase
key
docCount
}
contributors {
key
docCount
}
format {
key
docCount
}
languages {
key
docCount
}
literaryForm {
key
docCount
}
source {
key
docCount
}
subjects {
key
docCount
}
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions test/controllers/search_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -417,4 +417,42 @@ def source_filter_count(controller)
assert(source_filter_count(@controller) == 2)
end
end

test 'applications can customize the displayed filters via ENV' do
VCR.use_cassette('data basic controller',
allow_playback_repeats: true,
match_requests_on: %i[method uri body]) do
# Our standard test ENV does not define ACTIVE_FILTERS, but this confirms
# the behavior when it is not defined.
ClimateControl.modify ACTIVE_FILTERS: '' do
get '/results?q=data'
assert_response :success
assert_select '#filters .category .filter-label', { minimum: 1 }
end

# Ask for a single filter, get that filter.
ClimateControl.modify ACTIVE_FILTERS: 'subjects' do
get '/results?q=data'
assert_response :success
assert_select '#filters .category .filter-label', { count: 1 }
assert_select '#filters .category:first-of-type .filter-label', 'Subject'
end

# The order of the terms matter, so now Format should be first.
ClimateControl.modify ACTIVE_FILTERS: 'format, contentType, source' do
get '/results?q=data'
assert_response :success
assert_select '#filters .category .filter-label', { count: 3 }
assert_select '#filters .category:first-of-type .filter-label', 'Format'
end

# Including extra values does not affect anything - "nonsense" is extraneous.
ClimateControl.modify ACTIVE_FILTERS: 'contentType, nonsense, source' do
get '/results?q=data'
assert_response :success
assert_select '#filters .category .filter-label', { count: 2 }
assert_select '#filters .category:first-of-type .filter-label', 'Content type'
end
end
end
end
13 changes: 13 additions & 0 deletions test/helpers/filter_helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ class FilterHelperTest < ActionView::TestCase
assert_nil nice_labels[needle]
end

test 'nice_labels will use a value from ENV instead of the default if provided' do
label = 'Content type'
ClimateControl.modify FILTER_CONTENT_TYPE: nil do
needle = :contentTypeFilter
assert_equal label, nice_labels[needle]
end
label = 'Custom label'
ClimateControl.modify FILTER_CONTENT_TYPE: label do
needle = :contentTypeFilter
assert_equal label, nice_labels[needle]
end
end

test 'remove_filter will remove a specific filter parameter from a search URL' do
original_query = {
page: 1,
Expand Down
24 changes: 13 additions & 11 deletions test/vcr_cassettes/advanced.yml

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/advanced_all_spaces.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/advanced_citation_asdf.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/advanced_source_defaults_to_all.yml

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/advanced_source_limit_to_one_source.yml

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/advanced_source_limit_to_two_sources.yml

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/advanced_title_data.yml

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/data.yml

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/data_basic_controller.yml

Large diffs are not rendered by default.

18 changes: 10 additions & 8 deletions test/vcr_cassettes/data_from_ridiculous_start.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/data_page_2.yml

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/timdex_10_1038_nphys1170_.yml

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/timdex_1234-5678.yml

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions test/vcr_cassettes/timdex_9781857988536.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading