Skip to content

Commit f6e2169

Browse files
committed
Adds persistence to Tab selection across searches
Why are these changes being introduced: * Running multiple searches always reset to the Primo tab. It is expected that isn't what users want. They want to stay on the tab they selected. Relevant ticket(s): * https://mitlibraries.atlassian.net/browse/USE-135 * https://mitlibraries.atlassian.net/browse/USE-156 How does this address that need: * Updates the tab links to set a cookie with the selected tab when clicked. * Updates the search form to include the active tab as a hidden field so that when a new search is performed, the selected tab is preserved. * Updates the Tabs Turbo Frame to target the whole page to allow the form element to be updated * This also fixed the issue with back links not updating the form keyword input correctly which was a separately reported bug. Document any side effects to this change: * Refactor to extract some logic from the SearchController to ApplicationController to allow reuse in BasicSearchController. * Minor refactor to conditional logic to always use case and eliminate the if statement that was used only for GeoData. Also normalized to `geodata` language (was `gdt`) to match other wording used in the app.
1 parent 9e83341 commit f6e2169

File tree

9 files changed

+117
-21
lines changed

9 files changed

+117
-21
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ See `Optional Environment Variables` for more information.
8282
- `PRIMO_SCOPE`: The Primo Search API `scope` param (set to `cdi` for CDI-scoped results).
8383
- `PRIMO_TAB`: The Primo Search API `tab` param (typically `all`).
8484
- `PRIMO_VID`: The Primo Search API `vid` (or 'view ID`) param.
85+
- `SECRET_KEY_BASE`: You can generate this via `bin/rails secret`. Please do not re-use the production value locally.
8586
- `SYNDETICS_PRIMO_URL`: The Syndetics API URL for Primo. This is used to construct thumbnail URLs.
8687
- `TIMDEX_GRAPHQL`: Set this to the URL of the GraphQL endpoint. There is no default value in the application.
8788

app/assets/stylesheets/partials/_search.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,8 @@
196196
.tab-link {
197197
color: #fff;
198198
}
199+
200+
/* temp style to visualize active tab. Save us from this Dave! */
201+
#tabs .active{
202+
background-color: red;;
203+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
11
class ApplicationController < ActionController::Base
22
helper Mitlibraries::Theme::Engine.helpers
3+
4+
# Set active tab based on feature flag and params
5+
# Also stores the last used tab in a cookie for future searches when passed via params.
6+
# We set this in a session cookie to persist user preference across searches.
7+
# Clicking on a different tab will update the cookie.
8+
def set_active_tab
9+
@active_tab = if Feature.enabled?(:geodata)
10+
# Determine which tab to load - default to primo unless gdt is enabled
11+
'geodata'
12+
elsif params[:tab].present?
13+
# If params[:tab] is set, use it and set session
14+
cookies[:last_tab] = params[:tab]
15+
elsif cookies[:last_tab].present?
16+
# Otherwise, check for last used tab in session
17+
cookies[:last_tab]
18+
else
19+
# Default behavior when no tab is specified in params or session
20+
cookies[:last_tab] = 'primo'
21+
end
22+
end
323
end
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
class BasicSearchController < ApplicationController
2+
before_action :set_active_tab
3+
24
def index; end
35
end

app/controllers/search_controller.rb

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
class SearchController < ApplicationController
22
before_action :validate_q!, only: %i[results]
3+
before_action :set_active_tab, only: %i[results]
34

45
before_action :validate_geobox_presence!, only: %i[results]
56
before_action :validate_geobox_range!, only: %i[results]
@@ -13,29 +14,17 @@ def results
1314
# inject session preference for boolean type if it is present
1415
params[:booleanType] = cookies[:boolean_type] || 'AND'
1516

16-
# Determine which tab to load - default to primo unless gdt is enabled
17-
@active_tab = if Feature.enabled?(:geodata)
18-
'gdt' # Keep existing GDT behavior unchanged
19-
else
20-
params[:tab] || 'primo' # Default to primo for new tabbed interface
21-
end
22-
23-
# Include the active tab in the enhanced query so it's available for pagination and other uses.
24-
params[:tab] = @active_tab unless Feature.enabled?(:gdt)
2517
@enhanced_query = Enhancer.new(params).enhanced_query
2618

2719
# Route to appropriate search based on active tab
28-
if Feature.enabled?(:geodata)
29-
# Keep existing GDT behavior unchanged
20+
case @active_tab
21+
when 'primo'
22+
load_primo_results
23+
when 'timdex'
24+
load_timdex_results
25+
when 'geodata'
3026
load_gdt_results
3127
render 'results_geo'
32-
else
33-
case @active_tab
34-
when 'primo'
35-
load_primo_results
36-
when 'timdex'
37-
load_timdex_results
38-
end
3928
end
4029
end
4130

@@ -112,7 +101,7 @@ def query_timdex(query)
112101

113102
# Builder hands off to wrapper which returns raw results here.
114103
Rails.cache.fetch("#{cache_key}/#{@active_tab}", expires_in: 12.hours) do
115-
raw = if @active_tab == 'gdt'
104+
raw = if @active_tab == 'geodata'
116105
execute_geospatial_query(query)
117106
elsif @active_tab == 'timdex'
118107
TimdexBase::Client.query(TimdexSearch::BaseQuery, variables: query)

app/views/search/_form.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<h3>What can we help you find?</h3>
33
<div class="form-wrapper">
44
<input id="basic-search-main" type="search" class="field field-text basic-search-input" name="q" title="Keyword anywhere" placeholder="Search for anything" value="<%= params[:q] %>" required>
5+
<input id="tab-to-target" type="hidden" name="tab" value="<%= @active_tab %>">
56
<button type="submit" class="btn button-primary">Search</button>
67
</div>
78
</form>

app/views/search/_source_tabs.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
<div id="tabs" class="tab-navigation top-space">
33
<%= link_to "Primo", results_path(params.permit(:q, :per_page, :page).merge(tab: 'primo')),
44
class: "tab-link #{'active' if @active_tab == 'primo'}",
5-
data: { turbo_frame: "search-results", turbo_action: "advance" } %>
5+
data: { turbo_frame: "_top", turbo_action: "advance" } %>
66
<%= link_to "TIMDEX", results_path(params.permit(:q, :per_page, :page).merge(tab: 'timdex')),
77
class: "tab-link #{'active' if @active_tab == 'timdex'}",
8-
data: { turbo_frame: "search-results", turbo_action: "advance" } %>
8+
data: { turbo_frame: "_top", turbo_action: "advance" } %>
99
</div>
1010

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Be sure to restart your server when you modify this file.
2+
# Note, you must set `SECRET_KEY_BASE` environment variable before running the application or sessions will not work.
3+
# Changing `SECRET_KEY_BASE` will invalidate all existing sessions.
4+
# You can generate a new secret key by running `bin/rails secret` command.
5+
Rails.application.config.session_store :cookie_store, key: '_use_session', secure: false, same_site: :strict
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
require 'test_helper'
2+
3+
class ApplicationControllerTest < ActionDispatch::IntegrationTest
4+
test 'set_active_tab sets default to primo when no feature flag or params' do
5+
assert_nil cookies[:last_tab]
6+
7+
get root_path
8+
assert_select '#tab-to-target' do
9+
assert_select '[value=?]', 'primo'
10+
refute_select '[value=?]', 'geodata'
11+
refute_select '[value=?]', 'timdex'
12+
end
13+
14+
assert_equal cookies[:last_tab], 'primo'
15+
end
16+
17+
test 'set_active_tab sets to geodata when feature flag enabled' do
18+
skip 'Geodata uses a different form so we do no set the tab this way'
19+
ClimateControl.modify FEATURE_GEODATA: 'true' do
20+
get root_path
21+
assert_select '#tab-to-target' do
22+
refute_select '[value=?]', 'primo'
23+
assert_select '[value=?]', 'geodata'
24+
refute_select '[value=?]', 'timdex'
25+
end
26+
end
27+
end
28+
29+
test 'set_active_tab sets to geodata when feature flag enabled even if param is passed' do
30+
skip 'Geodata uses a different form'
31+
ClimateControl.modify FEATURE_GEODATA: 'true' do
32+
get root_path, params: { tab: 'primo' }
33+
assert_select '#tab-to-target' do
34+
refute_select '[value=?]', 'primo'
35+
assert_select '[value=?]', 'geodata'
36+
refute_select '[value=?]', 'timdex'
37+
end
38+
end
39+
end
40+
41+
test 'set_active_tab sets to param tab when provided' do
42+
get root_path, params: { tab: 'timdex' }
43+
44+
assert_select '#tab-to-target' do
45+
refute_select '[value=?]', 'primo'
46+
refute_select '[value=?]', 'geodata'
47+
assert_select '[value=?]', 'timdex'
48+
end
49+
end
50+
51+
test 'set_active_tab sets to param tab when provided even if cookie is set and updates cookie' do
52+
cookies[:last_tab] = 'timdex'
53+
get root_path, params: { tab: 'geodata' }
54+
55+
assert_select '#tab-to-target' do
56+
refute_select '[value=?]', 'primo'
57+
assert_select '[value=?]', 'geodata'
58+
refute_select '[value=?]', 'timdex'
59+
end
60+
61+
assert_equal cookies[:last_tab], 'geodata'
62+
end
63+
64+
test 'set_active_tab uses cookie last_tab when no param provided' do
65+
cookies[:last_tab] = 'timdex'
66+
get root_path
67+
assert_select '#tab-to-target' do
68+
refute_select '[value=?]', 'primo'
69+
refute_select '[value=?]', 'geodata'
70+
assert_select '[value=?]', 'timdex'
71+
end
72+
end
73+
end

0 commit comments

Comments
 (0)