Skip to content

Commit 6cb6a51

Browse files
committed
Adds Primo API-based tabs
Why are these changes being introduced: * Breaking out Primo results into Articles (CDI) and Catalog (Alma) tabs is how we want to present Primo results to users when they are not using the All tab Relevant ticket(s): * https://mitlibraries.atlassian.net/browse/USE-202 How does this address that need: * Adds new tabs for Articles and Catalog in the search results UI * Creates Feature flag `primo_tabs` to enable/disable full Primo results * Modifies PrimoSearch to accept a new `tab` parameter to set the scope * Adds documentation as to what Primo Scopes and Tabs mean and what values are available Document any side effects to this change: * I've moved some Primo Scope and Tab values to code rather than ENV as they are more tightly coupled to the Primo API behavior than ENV implies. Additionally, we use those ENV values to construct links in the UI and those values need to be different than the API calls due to our desire to send users to a specific UI regardless of how we queried the API. The UI values are still set via ENV at this time.
1 parent f5168a2 commit 6cb6a51

File tree

9 files changed

+67
-18
lines changed

9 files changed

+67
-18
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,9 @@ See `Optional Environment Variables` for more information.
9898
mode. Note that this is currently intended _only_ for the geodata app and
9999
may have unexpected consequences if applied to other TIMDEX UI apps.
100100
- `FEATURE_SIMULATE_SEARCH_LATENCY`: DO NOT SET IN PRODUCTION. Set to ensure a minimum of a one second delay in returning search results. Useful to see spinners/loaders. Only introduces delay for results that take less than one second to complete.
101-
- `FEATURE_TAB_TIMDEX_ALL`: Display a tab for displaying the combined TIMDEX data
102-
- `FEATURE_TAB_TIMDEX_ALMA`: Display a tab for displaying Alma data from TIMDEX
101+
- `FEATURE_TAB_PRIMO_ALL`: Display a tab for displaying the combined Primo data (CDI + Alma)
102+
- `FEATURE_TAB_TIMDEX_ALL`: Display a tab for displaying the combined TIMDEX data. `TIMDEX_INDEX` affects which data appears in this tab.
103+
- `FEATURE_TAB_TIMDEX_ALMA`: Display a tab for displaying Alma data from TIMDEX. `TIMDEX_INDEX` must include `Alma` data or no results will return.
103104
- `FILTER_ACCESS_TO_FILES`: The name to use instead of "Access to files" for that filter / aggregation.
104105
- `FILTER_CONTENT_TYPE`: The name to use instead of "Content type" for that filter / aggregation.
105106
- `FILTER_CONTRIBUTOR`: The name to use instead of "Contributor" for that filter / aggregation.

app/controllers/search_controller.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def fetch_primo_data
139139
primo_response = query_primo(per_page, offset)
140140
hits = primo_response.dig('info', 'total') || 0
141141
results = NormalizePrimoResults.new(primo_response, @enhanced_query[:q]).normalize
142-
pagination = Analyzer.new(@enhanced_query, hits , :primo).pagination
142+
pagination = Analyzer.new(@enhanced_query, hits, :primo).pagination
143143

144144
# Handle empty results from Primo API. Sometimes Primo will return no results at a given offset,
145145
# despite claiming in the initial query that more are available. This happens randomly and
@@ -226,7 +226,7 @@ def query_primo(per_page, offset)
226226
cache_key = generate_cache_key(@enhanced_query)
227227

228228
Rails.cache.fetch("#{cache_key}/primo", expires_in: 12.hours) do
229-
primo_search = PrimoSearch.new
229+
primo_search = PrimoSearch.new(@enhanced_query[:tab])
230230
primo_search.search(@enhanced_query[:q], per_page, offset)
231231
end
232232
end

app/models/feature.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
#
3434
class Feature
3535
# List of all valid features in the application
36-
VALID_FEATURES = %i[geodata boolean_picker simulate_search_latency tab_timdex_all tab_timdex_alma].freeze
36+
VALID_FEATURES = %i[geodata boolean_picker simulate_search_latency tab_primo_all tab_timdex_all
37+
tab_timdex_alma].freeze
3738

3839
# Check if a feature is enabled by name
3940
#

app/models/primo_search.rb

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
# Searches Primo Search API and formats results
22
#
33
class PrimoSearch
4-
def initialize
4+
# Initializes the PrimoSearch with the given query parameters
5+
# @param tab [String] Current `active_tab` value from SearchController. Used to set Primo tab/scope.
6+
# Defaults to 'all'.
7+
# @return [PrimoSearch] An instance of PrimoSearch
8+
def initialize(tab = 'all')
9+
@tab = tab
10+
511
validate_env
612
@primo_http = HTTP.persistent(primo_api_url)
713
@results = {}
814
end
915

16+
# Performs a search against the Primo API
17+
# @param term [String] The search term
18+
# @param per_page [Integer] Number of results per page
19+
# @param offset [Integer] The result offset for pagination
20+
# @return [Hash] Parsed JSON response from Primo API
1021
def search(term, per_page, offset = 0)
1122
url = search_url(term, per_page, offset)
1223
result = @primo_http.timeout(http_timeout)
@@ -46,14 +57,39 @@ def primo_api_key
4657
ENV.fetch('PRIMO_API_KEY', nil)
4758
end
4859

60+
# In Primo API, Search scopes determines which records are being searched
61+
# Primo VE configuration calls this `Search Profiles` and uses `Scope` differently.
62+
# For Primo VE API we want to be doing &scope={Primo VE Search Profile}
63+
#
64+
# Available scopes for USE
65+
# all_use: includes CDI configured like Primo UI + Alma (does not include ASpace)
66+
# all: same as all_use but includes ASpace
67+
# catalog_use: just Alma
68+
# cdi_use: just CDI configured like Primo UI
69+
#
70+
# The scope we use will be driven by the tab provided during initialization
4971
def primo_scope
50-
ENV.fetch('PRIMO_SCOPE', nil)
72+
case @tab
73+
when 'cdi'
74+
'cdi_use'
75+
when 'alma'
76+
'catalog_use'
77+
else
78+
'all_use'
79+
end
5180
end
5281

82+
# In Primo, Tabs act as "search scope slots". They contain one or more Search Profile (which Primo API calls `scopes`).
83+
# Primo VE configuration refers to these as `Search Profile Slots`
84+
# Configured tabs in our Primo
85+
# all: scopes(all, all_filtered, catalog, cdi, CourseReserves)
86+
# bento: scopes(cdi, catalog, bento_catalog, all_use)
87+
# USE: scopes(all_use, all, catalog_use, cdi_use)
5388
def primo_tab
54-
ENV.fetch('PRIMO_TAB', nil)
89+
'use'
5590
end
5691

92+
# In Primo API, a vid is...[documentaiton needed!]
5793
def primo_vid
5894
ENV.fetch('PRIMO_VID', nil)
5995
end

app/views/search/_source_tabs.html.erb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22
<nav id="tabs" class="tab-navigation" aria-label="Result type navigation">
33
<ul>
44
<li><%= link_to_tab("All") %></li>
5-
<li><%= link_to_tab("Primo", "Articles and Catalog") %></li>
5+
6+
<% if Feature.enabled?(:tab_primo_all) %>
7+
<li><%= link_to_tab("Primo", "Articles and Catalog") %></li>
8+
<% end %>
9+
10+
<li><%= link_to_tab("cdi", "Articles") %></li>
11+
<li><%= link_to_tab("alma", "Catalog") %></li>
12+
613
<% if Feature.enabled?(:tab_timdex_all) %>
714
<li><%= link_to_tab("TIMDEX") %></li>
815
<% end %>

test/controllers/search_controller_test.rb

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -655,11 +655,13 @@ def source_filter_count(controller)
655655
end
656656

657657
test 'results respects primo tab parameter' do
658-
mock_primo_search_success
658+
ClimateControl.modify FEATURE_TAB_PRIMO_ALL: 'true' do
659+
mock_primo_search_success
659660

660-
get '/results?q=test&tab=primo'
661-
assert_response :success
662-
assert_select 'a.tab-link.active[href*="tab=primo"]', count: 1
661+
get '/results?q=test&tab=primo'
662+
assert_response :success
663+
assert_select 'a.tab-link.active[href*="tab=primo"]', count: 1
664+
end
663665
end
664666

665667
test 'results respects timdex all tab parameter' do
@@ -688,7 +690,10 @@ def source_filter_count(controller)
688690
get '/results?q=test&tab=primo'
689691
assert_response :success
690692
assert_select '.tab-navigation', count: 1
691-
assert_select 'a[href*="tab=primo"]', count: 1
693+
assert_select 'a[href*="tab=all"]', count: 1
694+
assert_select 'a[href*="tab=cdi"]', count: 1
695+
assert_select 'a[href*="tab=alma"]', count: 1
696+
# assert_select 'a[href*="tab=primo"]', count: 1
692697
# assert_select 'a[href*="tab=timdex"]', count: 1
693698
assert_select 'a[href*="tab=aspace"]', count: 1
694699
assert_select 'a[href*="tab=website"]', count: 1

test/models/primo_search_test.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,11 @@ class PrimoSearchTest < ActiveSupport::TestCase
2828
end
2929

3030
test 'raises error when multiple environment variables are missing' do
31-
ClimateControl.modify(PRIMO_API_URL: nil, PRIMO_SCOPE: nil, PRIMO_VID: nil) do
31+
ClimateControl.modify(PRIMO_API_URL: nil, PRIMO_VID: nil) do
3232
error = assert_raises(ArgumentError) do
3333
PrimoSearch.new
3434
end
3535
assert_match(/PRIMO_API_URL/, error.message)
36-
assert_match(/PRIMO_SCOPE/, error.message)
3736
assert_match(/PRIMO_VID/, error.message)
3837
end
3938
end

test/vcr_cassettes/primo_search_error.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/vcr_cassettes/primo_search_success.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)