Skip to content

Commit

Permalink
Adds feature to allow ENV to reorder & filter aggs
Browse files Browse the repository at this point in the history
** Why are these changes being introduced:

While the API provides a large number of possible options for users to
filter and aggregate their search results, not every instance of the
application will want to use every category (GeoData and the basic
Search application will likely use different sets, for example). One
good option for enabling these differences is to leverage environment
variables.

** Relevant ticket(s):

* https://mitlibraries.atlassian.net/browse/gdt-128

** How does this address that need:

This adds a new environment variable to the application, ACTIVE_FILTERS.
This is meant to be a list of the filter categories which should be
displayed in the application. The variable is optional - without it, the
application should include every available category, in the order they
appear in the query model.

The env variable is loaded and processed in the search controller, which
is then used to order and filter the categories returned from the API
before sending the result to the user in the UI.

The tests added in this commit demonstrate the impact of this change.

** Document any side effects to this change:

Because the env var is optional, I'm not adding it to app.json. I'm
leaning toward adding it to the Heroku pipeline, to preserve the current
behavior (only content type and source being shown).

Also, the next commit will show a quick refactoring that is motivated
by codeclimate feedback.

starting
  • Loading branch information
matt-bernhardt committed Mar 4, 2024
1 parent 2b6ae5c commit 205db6a
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ 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.
- `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
14 changes: 13 additions & 1 deletion app/controllers/search_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,29 @@ def extract_filters(response)
aggs = response&.data&.search&.to_h&.dig('aggregations')
return if aggs.blank?

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

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, value| active_filters.include?(key) }
.sort_by { |key, value| active_filters.index(key) }.to_h
end

def validate_q!
return if params[:advanced]&.strip.present?
return if params[:q]&.strip.present?
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

0 comments on commit 205db6a

Please sign in to comment.