Skip to content

Commit 5edb8f8

Browse files
authored
Merge pull request #286 from MITLibraries/use-202-primo-tabs
Adds Primo API-based tabs
2 parents f5168a2 + c9fec16 commit 5edb8f8

File tree

9 files changed

+75
-23
lines changed

9 files changed

+75
-23
lines changed

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ See `Optional Environment Variables` for more information.
7979
- `MIT_PRIMO_URL`: The base URL for MIT Libraries' Primo instance (used to generate record links).
8080
- `PRIMO_API_KEY`: The Primo Search API key.
8181
- `PRIMO_API_URL`: The Primo Search API base URL.
82-
- `PRIMO_SCOPE`: The Primo Search API `scope` param (set to `cdi` for CDI-scoped results).
83-
- `PRIMO_TAB`: The Primo Search API `tab` param (typically `all`).
84-
- `PRIMO_VID`: The Primo Search API `vid` (or 'view ID`) param.
82+
- `PRIMO_SCOPE`: The Primo Search API `scope` used in Primo UI links. Does not affect our API calls. Ask Enterprise Systems for value.
83+
- `PRIMO_TAB`: The Primo Search API `tab` used in Primo UI links. Does not affect our API calls. Ask Enterprise Systems for value.
84+
- `PRIMO_VID`: The Primo Search API `vid` (or 'view ID`) param. Used in both our API calls and Primo UI. Ask Enterprise Systems for value.
8585
- `SECRET_KEY_BASE`: You can generate this via `bin/rails secret`. Please do not re-use the production value locally.
8686
- `SYNDETICS_PRIMO_URL`: The Syndetics API URL for Primo. This is used to construct thumbnail URLs.
8787
- `TIMDEX_GRAPHQL`: Set this to the URL of the GraphQL endpoint. There is no default value in the application.
@@ -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: 44 additions & 5 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 PrimoSearch
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)
@@ -23,13 +34,15 @@ def search(term, per_page, offset = 0)
2334

2435
private
2536

37+
# Validates required environment variables are set
38+
#
39+
# PRIMO_SCOPE and PRIMO_TAB look related by name, but are only used in the links to Primo UI and cannot be the same
40+
# values we use for API calls so are not checked here.
2641
def validate_env
2742
missing_vars = []
2843

2944
missing_vars << 'PRIMO_API_URL' if primo_api_url.nil?
3045
missing_vars << 'PRIMO_API_KEY' if primo_api_key.nil?
31-
missing_vars << 'PRIMO_SCOPE' if primo_scope.nil?
32-
missing_vars << 'PRIMO_TAB' if primo_tab.nil?
3346
missing_vars << 'PRIMO_VID' if primo_vid.nil?
3447

3548
return if missing_vars.empty?
@@ -46,14 +59,40 @@ def primo_api_key
4659
ENV.fetch('PRIMO_API_KEY', nil)
4760
end
4861

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

84+
# In Primo, Tabs act as "search scope slots". They contain one or more Search Profile (which Primo API calls `scopes`).
85+
# Primo VE configuration refers to these as `Search Profile Slots`
86+
# Configured tabs in our Primo
87+
# all: scopes(all, all_filtered, catalog, cdi, CourseReserves)
88+
# bento: scopes(cdi, catalog, bento_catalog, all_use)
89+
# USE: scopes(all_use, all, catalog_use, cdi_use)
90+
# This application should always use the 'use' tab for Primo searches.
5391
def primo_tab
54-
ENV.fetch('PRIMO_TAB', nil)
92+
'use'
5593
end
5694

95+
# In Primo API, a view (vid) contains Search Profile Slots (tabs) which in turn contain Search Profiles (scopes).
5796
def primo_vid
5897
ENV.fetch('PRIMO_VID', nil)
5998
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)