diff --git a/app/components/blacklight/facet_field_pagination_component.html.erb b/app/components/blacklight/facet_field_pagination_component.html.erb
new file mode 100644
index 000000000..ba97dbb22
--- /dev/null
+++ b/app/components/blacklight/facet_field_pagination_component.html.erb
@@ -0,0 +1,61 @@
+
+
+ <%= helpers.link_to_previous_page @facet_field.paginator, raw(t('views.pagination.previous')), params: @facet_field.search_state.to_h, param_name: param_name, class: 'btn btn-link', data: { blacklight_modal: "preserve" } do %>
+ <%= content_tag :span, raw(t('views.pagination.previous')), class: 'disabled btn' %>
+ <% end %>
+
+ <%= helpers.link_to_next_page @facet_field.paginator, raw(t('views.pagination.next')), params: @facet_field.search_state.to_h, param_name: param_name, class: 'btn btn-link', data: { blacklight_modal: "preserve" } do %>
+ <%= content_tag :span, raw(t('views.pagination.next')), class: 'disabled btn' %>
+ <% end %>
+
+
+
+
+
+
+ <% if @facet_field.paginator.sort == 'index' -%>
+ <%= t('blacklight.search.facets.sort.index') %>
+ <%= helpers.link_to(t('blacklight.search.facets.sort.count'), sort_facet_url('count'), class: "sort_change numeric btn btn-outline-secondary", data: { blacklight_modal: "preserve" }) %>
+ <% elsif @facet_field.paginator.sort == 'count' -%>
+ <%= helpers.link_to(t('blacklight.search.facets.sort.index'), sort_facet_url('index'), class: "sort_change az btn btn-outline-secondary", data: { blacklight_modal: "preserve" }) %>
+ <%= t('blacklight.search.facets.sort.count') %>
+ <% end -%>
+
\ No newline at end of file
diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb
index 36c8b9d03..b2882d0a3 100755
--- a/app/controllers/catalog_controller.rb
+++ b/app/controllers/catalog_controller.rb
@@ -37,6 +37,46 @@ def single_item_search_builder(id)
single_item_search_builder_class.new(self, id).with(params.except(:q, :page))
end
+ def facet_total_count(field_name)
+ query = '*:*'
+ params = {
+ facet: true,
+ 'facet.field': field_name,
+ rows: 0,
+ 'facet.limit': -1, # Retrieve all facets
+ wt: 'json'
+ }
+
+ # Perform the Solr query using Hyrax::SolrService
+ # Using spread operator to convert object into keyword arguments
+ response = Hyrax::SolrService.get(query, **params)
+
+ # Parse the response to extract the total unique facets
+ facet_values = response.dig('facet_counts', 'facet_fields', field_name)
+ # Facet counts are included with names in the list, so divide by 2
+ total_unique_facets = facet_values ? (facet_values.length / 2) : 0
+ total_unique_facets
+ rescue StandardError => e
+ Rails.logger.error("Error retrieving facets for '#{field_name}': #{e.message}")
+ Rails.logger.error(e.backtrace.join("\n"))
+ 0
+ end
+
+ def facet
+ begin
+ facet_field_name = params[:id]
+ targeted_facet_list = ['affiliation_label_sim']
+ super
+ # Only calculate total unique facets for facets in the target list
+ @total_unique_facets = targeted_facet_list.include?(facet_field_name) ? facet_total_count(facet_field_name) : 0
+ rescue StandardError => e
+ # Capture any errors that occur and log them
+ Rails.logger.error("Error during facet action: #{e.message}")
+ Rails.logger.error(e.backtrace.join("\n"))
+ end
+ end
+
+
configure_blacklight do |config|
# Advanced search configuration
config.advanced_search ||= Blacklight::OpenStructWithHashAccess.new
diff --git a/app/overrides/components/blacklight/facet_field_pagination_component_override.rb b/app/overrides/components/blacklight/facet_field_pagination_component_override.rb
new file mode 100644
index 000000000..e9ee1132b
--- /dev/null
+++ b/app/overrides/components/blacklight/facet_field_pagination_component_override.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+# [hyc-override] https://github.com/projectblacklight/blacklight/blob/v7.33.1/app/components/blacklight/facet_field_pagination_component.rb
+Blacklight::FacetFieldPaginationComponent.class_eval do
+ attr_reader :facet_field, :total_unique_facets
+ def initialize(facet_field:, total_unique_facets: nil)
+ @facet_field = facet_field
+ # Integrate total unique facets as an attribute for pagination
+ @total_unique_facets = total_unique_facets
+ end
+end
diff --git a/app/overrides/lib/kanamari/helpers/helper_methods_override.rb b/app/overrides/lib/kanamari/helpers/helper_methods_override.rb
new file mode 100644
index 000000000..0dea36a15
--- /dev/null
+++ b/app/overrides/lib/kanamari/helpers/helper_methods_override.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+# [hyc-override] https://github.com/kaminari/kaminari/blob/v1.2.2/kaminari-core/lib/kaminari/helpers/helper_methods.rb
+Kaminari::Helpers::HelperMethods.module_eval do
+ # Helper to generate a link to a specific page
+ def link_to_specific_page(scope, page, total_entries, **options)
+ specific_page_path = path_to_specific_page(scope, page.to_i, total_entries, options)
+
+ # Remove unnecessary keys :params and :param_name from the options hash before generating the link
+ options.except! :params, :param_name
+
+ # Setting aria instead of rel for accessibility
+ options[:aria] ||= { label: "Go to page #{page.to_i}" }
+
+ if specific_page_path
+ link_to("#{page.to_i}", specific_page_path, options)
+ else
+ Rails.logger.warn "Specific page path could not be generated for page: #{page.to_i}"
+ nil
+ end
+ end
+
+ # Helper to generate the path for a specific page
+ def path_to_specific_page(scope, page_integer, total_entries, options = {})
+ begin
+ # Calculate total pages manually
+ limit = scope.instance_variable_get(:@limit)
+ total_pages = (total_entries.to_f / limit).ceil
+
+ Rails.logger.debug "path_to_specific_page: total_entries=#{total_entries}, limit=#{limit}, calculated total_pages=#{total_pages}, page=#{page_integer}"
+
+ # Validate inputs
+ raise ArgumentError, 'Page number must be a positive integer' unless page_integer.positive?
+ raise ArgumentError, "Page number exceeds total pages (#{total_pages})" if page_integer > total_pages
+ # Generate URL using Kaminari's Page helper
+ Kaminari::Helpers::Page.new(self, **options.reverse_merge(page: page_integer)).url
+ rescue ArgumentError => e
+ Rails.logger.error "Error in path_to_specific_page: #{e.message}"
+ nil
+ rescue => e
+ Rails.logger.error "Unexpected error in path_to_specific_page: #{e.message}\n#{e.backtrace.join("\n")}"
+ nil
+ end
+ end
+end
diff --git a/app/views/catalog/_facet_pagination.html.erb b/app/views/catalog/_facet_pagination.html.erb
new file mode 100644
index 000000000..516ecc64a
--- /dev/null
+++ b/app/views/catalog/_facet_pagination.html.erb
@@ -0,0 +1 @@
+<%= render(Blacklight::FacetFieldPaginationComponent.new(facet_field: facet_field_presenter(@facet, @display_facet), total_unique_facets: @total_unique_facets)) %>
\ No newline at end of file
diff --git a/spec/components/blacklight/facet_field_pagination_component_spec.rb b/spec/components/blacklight/facet_field_pagination_component_spec.rb
new file mode 100644
index 000000000..28c6e1fd4
--- /dev/null
+++ b/spec/components/blacklight/facet_field_pagination_component_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+require 'rails_helper'
+
+RSpec.describe Blacklight::FacetFieldPaginationComponent, type: :component do
+ let(:facet_field) { double('facet_field') }
+ let(:total_unique_facets) { 42 }
+
+ describe '#initialize' do
+ context 'when total_unique_facets is provided' do
+ it 'sets the facet_field and total_unique_facets attributes' do
+ component = Blacklight::FacetFieldPaginationComponent.new(facet_field: facet_field, total_unique_facets: total_unique_facets)
+
+ expect(component.facet_field).to eq(facet_field)
+ expect(component.total_unique_facets).to eq(total_unique_facets)
+ end
+ end
+
+ context 'when total_unique_facets is not provided' do
+ it 'sets the total_unique_facets attribute to nil' do
+ component = Blacklight::FacetFieldPaginationComponent.new(facet_field: facet_field)
+
+ expect(component.facet_field).to eq(facet_field)
+ expect(component.total_unique_facets).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/lib/kanamari/helpers/helper_methods_spec.rb b/spec/lib/kanamari/helpers/helper_methods_spec.rb
new file mode 100644
index 000000000..85c675e9d
--- /dev/null
+++ b/spec/lib/kanamari/helpers/helper_methods_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+require 'rails_helper'
+
+RSpec.describe Kaminari::Helpers::HelperMethods do
+ let(:dummy_class) do
+ Class.new do
+ extend ActionView::Helpers::UrlHelper
+ extend Kaminari::Helpers::HelperMethods
+ end
+ end
+ let(:scope) { double('FacetPaginator', instance_variable_get: 20) }
+ let(:valid_page) { 1 }
+ let(:total_entries) { 100 }
+ let(:options) { { some_option: 'value' } }
+
+ describe '#link_to_specific_page' do
+ before do
+ # Stub Kaminari::Helpers::Page.new to return a mock URL
+ allow(Kaminari::Helpers::Page).to receive(:new).and_return(double(url: '/some_path'))
+ end
+
+ it 'generates a valid link for correct input' do
+ expect(Rails.logger).to_not receive(:error)
+ allow(dummy_class).to receive(:link_to).and_return('link')
+ # Mock link_to to check its arguments
+ dummy_class.link_to_specific_page(scope, valid_page, total_entries, **options)
+ # Expect the method to return the mocked URL
+ end
+
+
+ it 'logs and returns nil for invalid page input' do
+ invalid_page = -1
+ expect(Rails.logger).to receive(:error).with(/Page number must be a positive integer/)
+ expect(Rails.logger).to receive(:warn).with(/Specific page path could not be generated for page/)
+ expect(dummy_class.link_to_specific_page(scope, invalid_page, total_entries, **options))
+ .to be_nil
+ end
+
+ it 'logs and returns nil if page exceeds total pages' do
+ invalid_page = 999
+ expect(Rails.logger).to receive(:error).with(/Page number exceeds total pages/)
+ expect(Rails.logger).to receive(:warn).with(/Specific page path could not be generated for page/)
+ expect(dummy_class.link_to_specific_page(scope, invalid_page, total_entries, **options))
+ .to be_nil
+ end
+
+ it 'logs and returns nil if an unexpected error occurs' do
+ allow(Kaminari::Helpers::Page).to receive(:new).and_raise(StandardError, 'Simulated Kaminari Error')
+ expect(Rails.logger).to receive(:error).with(/Unexpected error in path_to_specific_page/)
+ expect(Rails.logger).to receive(:warn).with(/Specific page path could not be generated for page/)
+ expect(dummy_class.link_to_specific_page(scope, valid_page, total_entries, **options))
+ .to be_nil
+ end
+ end
+end