Skip to content

Commit f8e7966

Browse files
committed
Add new search tabs and improve tab handling
Why are these changes being introduced: * `website` and `aspace` tabs were needed in the search interface to allow users to filter results by source * The `timdex` tab is not needed for user facing interfaces, but is useful for internal testing and development, so a feature flag was added to control its visibility * The `timdex_alma` tab will be useful to help us decide if we want a TIMDEX or Primo based Alma tab Relevant ticket(s): * https://mitlibraries.atlassian.net/browse/USE-187 How does this address that need: * Introduces 'website' and 'aspace' tabs to the search interface * refactors tab logic to support dynamic tab lists * adds a feature flag for displaying the TIMDEX tab * Updates tab rendering, controller logic, and tests to accommodate new tabs and feature flag. * Adds support for tabs with spaces in their names * Adds support for tab labels that differ from their internal names which will be important to allow UXWS to change labels without having to update valid tab lists in the code.
1 parent 77970ca commit f8e7966

File tree

8 files changed

+77
-35
lines changed

8 files changed

+77
-35
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ 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
101103
- `FILTER_ACCESS_TO_FILES`: The name to use instead of "Access to files" for that filter / aggregation.
102104
- `FILTER_CONTENT_TYPE`: The name to use instead of "Content type" for that filter / aggregation.
103105
- `FILTER_CONTRIBUTOR`: The name to use instead of "Contributor" for that filter / aggregation.

app/controllers/application_controller.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class ApplicationController < ActionController::Base
88
def set_active_tab
99
# GeoData doesn't use the tab system.
1010
return if Feature.enabled?(:geodata)
11-
11+
1212
@active_tab = if params[:tab].present? && valid_tab?(params[:tab])
1313
# If params[:tab] is set and valid, use it and set session
1414
cookies[:last_tab] = params[:tab]
@@ -21,9 +21,17 @@ def set_active_tab
2121
end
2222
end
2323

24+
def primo_tabs
25+
%w[all alma cdi primo]
26+
end
27+
28+
def timdex_tabs
29+
%w[all aspace timdex timdex_alma website]
30+
end
31+
2432
private
2533

2634
def valid_tab?(tab)
27-
%w[primo timdex all].include?(tab)
35+
(primo_tabs << timdex_tabs).flatten.uniq.include?(tab)
2836
end
2937
end

app/controllers/search_controller.rb

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,18 @@ def results
2323
render 'results_geo'
2424
return
2525
end
26-
26+
27+
@primo_tabs = primo_tabs
28+
@timdex_tabs = timdex_tabs
29+
2730
# Route to appropriate search based on active tab
2831
case @active_tab
29-
when 'primo'
32+
when 'all' # all tab must come first to avoid matching primo or timdex arrays which contain all
33+
load_all_results
34+
when *primo_tabs
3035
load_primo_results
31-
when 'timdex'
36+
when *timdex_tabs
3237
load_timdex_results
33-
when 'all'
34-
load_all_results
3538
end
3639
end
3740

@@ -108,7 +111,7 @@ def load_all_results
108111

109112
# For now, just use primo pagination as a placeholder
110113
@pagination = primo_data[:pagination] || {}
111-
114+
112115
# Handle primo continuation for high page numbers
113116
@show_primo_continuation = primo_data[:show_continuation] || false
114117
end
@@ -119,9 +122,7 @@ def fetch_primo_data
119122
offset = (current_page - 1) * per_page
120123

121124
# Check if we're beyond Primo API limits before making the request.
122-
if offset >= Analyzer::PRIMO_MAX_OFFSET
123-
return { results: [], pagination: {}, errors: nil, show_continuation: true }
124-
end
125+
return { results: [], pagination: {}, errors: nil, show_continuation: true } if offset >= Analyzer::PRIMO_MAX_OFFSET
125126

126127
primo_response = query_primo
127128
results = NormalizePrimoResults.new(primo_response, @enhanced_query[:q]).normalize
@@ -133,7 +134,7 @@ def fetch_primo_data
133134
# exists in Primo UI, sending users there seems like the best we can do.
134135
show_continuation = false
135136
errors = nil
136-
137+
137138
if results.empty?
138139
docs = primo_response['docs'] if primo_response.is_a?(Hash)
139140
if docs.nil? || docs.empty?
@@ -153,7 +154,7 @@ def fetch_timdex_data
153154
query = QueryBuilder.new(@enhanced_query).query
154155
response = query_timdex(query)
155156
errors = extract_errors(response)
156-
157+
157158
if errors.nil?
158159
pagination = Analyzer.new(@enhanced_query, response, :timdex).pagination
159160
raw_results = extract_results(response)
@@ -169,14 +170,18 @@ def active_filters
169170
end
170171

171172
def query_timdex(query)
173+
query[:sourceFilter] = ['MIT Libraries Website', 'LibGuides'] if @active_tab == 'website'
174+
query[:sourceFilter] = ['MIT ArchivesSpace'] if @active_tab == 'aspace'
175+
query[:sourceFilter] = ['MIT Alma'] if @active_tab == 'timdex_alma'
176+
172177
# We generate unique cache keys to avoid naming collisions.
173178
cache_key = generate_cache_key(query)
174179

175180
# Builder hands off to wrapper which returns raw results here.
176181
Rails.cache.fetch("#{cache_key}/#{@active_tab}", expires_in: 12.hours) do
177182
raw = if Feature.enabled?(:geodata)
178183
execute_geospatial_query(query)
179-
elsif @active_tab == 'timdex' || @active_tab == 'all'
184+
elsif timdex_tabs.include? @active_tab
180185
TimdexBase::Client.query(TimdexSearch::BaseQuery, variables: query)
181186
end
182187

app/helpers/search_helper.rb

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,22 @@ def link_to_result(result)
2222
end
2323
end
2424

25-
def link_to_tab(target)
26-
if @active_tab == target.downcase
27-
link_to target, results_path(params.permit(:q, :per_page, :booleanType, :tab).merge(tab: target.downcase)),
28-
aria: { current: "page" },
29-
class: "active tab-link",
30-
data: { turbo_frame: "search-results", turbo_action: "advance" }
25+
# Generates a link for a search results tab, marking it as active if it matches the current active tab.
26+
# @param target [String] The name of the tab to link to
27+
# @param label [String] The display label for the tab (optional)
28+
# @return [String] HTML link element for the tab
29+
def link_to_tab(target, label = nil)
30+
clean_target = target.downcase.gsub(' ', '_').downcase
31+
target = label || target
32+
if @active_tab == clean_target
33+
link_to target, results_path(params.permit(:q, :per_page, :booleanType, :tab).merge(tab: clean_target)),
34+
aria: { current: 'page' },
35+
class: 'active tab-link',
36+
data: { turbo_frame: 'search-results', turbo_action: 'advance' }
3137
else
32-
link_to target, results_path(params.permit(:q, :per_page, :booleanType, :tab).merge(tab: target.downcase)),
33-
class: "tab-link",
34-
data: { turbo_frame: "search-results", turbo_action: "advance" }
38+
link_to target, results_path(params.permit(:q, :per_page, :booleanType, :tab).merge(tab: clean_target)),
39+
class: 'tab-link',
40+
data: { turbo_frame: 'search-results', turbo_action: 'advance' }
3541
end
3642
end
3743

app/models/feature.rb

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

3838
# Check if a feature is enabled by name
3939
#

app/views/search/_source_tabs.html.erb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@
33
<ul>
44
<li><%= link_to_tab("All") %></li>
55
<li><%= link_to_tab("Primo") %></li>
6-
<li><%= link_to_tab("TIMDEX") %></li>
6+
<% if Feature.enabled?(:tab_timdex_all) %>
7+
<li><%= link_to_tab("TIMDEX") %></li>
8+
<% end %>
9+
<% if Feature.enabled?(:tab_timdex_alma) %>
10+
<li><%= link_to_tab("timdex_alma", "Alma (TIMDEX)") %></li>
11+
<% end %>
12+
<li><%= link_to_tab("Website") %></li>
13+
<li><%= link_to_tab("aspace", "Archival materials") %></li>
714
</ul>
815
</nav>
916

app/views/search/results.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
<main id="results">
2525
<ol class="results-list" start="<%= @pagination[:start] %>">
2626
<% case @active_tab %>
27-
<% when 'primo' %>
27+
<% when *@primo_tabs %>
2828
<%= render(partial: 'search/result_primo', collection: @results, as: :result) %>
29-
<% when 'timdex' %>
29+
<% when *@timdex_tabs %>
3030
<%= render(partial: 'search/result', collection: @results, as: :result) %>
3131
<% when 'all' %>
3232
<% @results.each do |result| %>

test/controllers/search_controller_test.rb

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -593,12 +593,24 @@ def source_filter_count(controller)
593593
assert_select 'a.tab-link.active[href*="tab=primo"]', count: 1
594594
end
595595

596-
test 'results respects timdex tab parameter' do
597-
mock_timdex_search_success
596+
test 'results respects timdex all tab parameter' do
597+
ClimateControl.modify FEATURE_TAB_TIMDEX_ALL: 'true' do
598+
mock_timdex_search_success
598599

599-
get '/results?q=test&tab=timdex'
600-
assert_response :success
601-
assert_select 'a.tab-link.active[href*="tab=timdex"]', count: 1
600+
get '/results?q=test&tab=timdex'
601+
assert_response :success
602+
assert_select 'a.tab-link.active[href*="tab=timdex"]', count: 1
603+
end
604+
end
605+
606+
test 'results respects timdex alma tab parameter' do
607+
ClimateControl.modify FEATURE_TAB_TIMDEX_ALMA: 'true' do
608+
mock_timdex_search_success
609+
610+
get '/results?q=test&tab=timdex_alma'
611+
assert_response :success
612+
assert_select 'a.tab-link.active[href*="tab=timdex_alma"]', count: 1
613+
end
602614
end
603615

604616
test 'results shows tab navigation when GeoData is disabled' do
@@ -608,7 +620,9 @@ def source_filter_count(controller)
608620
assert_response :success
609621
assert_select '.tab-navigation', count: 1
610622
assert_select 'a[href*="tab=primo"]', count: 1
611-
assert_select 'a[href*="tab=timdex"]', count: 1
623+
# assert_select 'a[href*="tab=timdex"]', count: 1
624+
assert_select 'a[href*="tab=aspace"]', count: 1
625+
assert_select 'a[href*="tab=website"]', count: 1
612626
end
613627

614628
test 'results handles primo search errors gracefully' do
@@ -726,7 +740,7 @@ def source_filter_count(controller)
726740

727741
get '/results?q=test&tab=all'
728742
assert_response :success
729-
743+
730744
# Verify that we get results from both sources
731745
assert_select '.record-title', text: /Sample Primo Document Title/
732746
assert_select '.record-title', text: /Sample TIMDEX Document Title/
@@ -768,7 +782,7 @@ def source_filter_count(controller)
768782

769783
get '/results?q=test&tab=all&page=49'
770784
assert_response :success
771-
785+
772786
# Should show primo continuation partial
773787
assert_select '.primo-continuation', count: 1
774788
assert_select '.primo-continuation h2', text: /Continue your search in Search Our Collections/

0 commit comments

Comments
 (0)