diff --git a/lib/ruby_ui/data_table/data_table_kaminari_adapter.rb b/lib/ruby_ui/data_table/data_table_kaminari_adapter.rb new file mode 100644 index 00000000..6dd83402 --- /dev/null +++ b/lib/ruby_ui/data_table/data_table_kaminari_adapter.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module RubyUI + class DataTableKaminariAdapter + def initialize(collection) + @collection = collection + end + + def current_page = @collection.current_page + + def total_pages = @collection.total_pages + + def total_count = @collection.total_count + + def per_page = @collection.limit_value + end +end diff --git a/lib/ruby_ui/data_table/data_table_manual_adapter.rb b/lib/ruby_ui/data_table/data_table_manual_adapter.rb new file mode 100644 index 00000000..46b859e6 --- /dev/null +++ b/lib/ruby_ui/data_table/data_table_manual_adapter.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module RubyUI + class DataTableManualAdapter + attr_reader :current_page, :per_page, :total_count + + def initialize(page:, per_page:, total_count:) + @current_page = page.to_i + @per_page = [per_page.to_i, 1].max + @total_count = total_count.to_i + end + + def total_pages + [(@total_count.to_f / @per_page).ceil, 1].max + end + end +end diff --git a/lib/ruby_ui/data_table/data_table_pagination.rb b/lib/ruby_ui/data_table/data_table_pagination.rb index 02625c57..af12d3f5 100644 --- a/lib/ruby_ui/data_table/data_table_pagination.rb +++ b/lib/ruby_ui/data_table/data_table_pagination.rb @@ -1,22 +1,26 @@ # frozen_string_literal: true require "cgi" -require_relative "../data_table_pagination_adapters/manual" -require_relative "../data_table_pagination_adapters/pagy" -require_relative "../data_table_pagination_adapters/kaminari" +require_relative "data_table_manual_adapter" +require_relative "data_table_pagy_adapter" +require_relative "data_table_kaminari_adapter" module RubyUI class DataTablePagination < Base - def initialize(with: nil, pagy: nil, kaminari: nil, page: nil, per_page: nil, total_count: nil, page_param: "page", path: "", query: {}, window: 1, **attrs) + def initialize(with: nil, pagy: nil, kaminari: nil, page: nil, per_page: nil, total_count: nil, page_param: "page", path: "", query: {}, window: 1, prev_label: "<", next_label: ">", **attrs) @adapter = resolve_adapter(with:, pagy:, kaminari:, page:, per_page:, total_count:) @page_param = page_param @path = path @query = query.to_h.transform_keys(&:to_s) @window = window + @prev_label = prev_label + @next_label = next_label super(**attrs) end def view_template + return if total <= 1 + render RubyUI::Pagination.new(class: "mx-0 w-auto justify-end", **attrs) do render RubyUI::PaginationContent.new do prev_item @@ -30,10 +34,10 @@ def view_template def resolve_adapter(with:, pagy:, kaminari:, page:, per_page:, total_count:) return with if with - return RubyUI::DataTablePaginationAdapters::Pagy.new(pagy) if pagy - return RubyUI::DataTablePaginationAdapters::Kaminari.new(kaminari) if kaminari + return RubyUI::DataTablePagyAdapter.new(pagy) if pagy + return RubyUI::DataTableKaminariAdapter.new(kaminari) if kaminari if page && per_page && total_count - return RubyUI::DataTablePaginationAdapters::Manual.new(page:, per_page:, total_count:) + return RubyUI::DataTableManualAdapter.new(page:, per_page:, total_count:) end raise ArgumentError, "DataTablePagination requires one of: with:, pagy:, kaminari:, or page:+per_page:+total_count:" end @@ -48,26 +52,28 @@ def page_href(p) end def build_query(hash) - hash.map { |k, v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join("&") + hash.flat_map { |k, v| + Array(v).map { |val| "#{CGI.escape(k.to_s)}=#{CGI.escape(val.to_s)}" } + }.join("&") end def prev_item if current <= 1 li do - span(class: "opacity-50 pointer-events-none px-3 h-9 inline-flex items-center text-sm") { plain "Previous" } + span(class: "opacity-50 pointer-events-none px-3 h-9 inline-flex items-center text-sm") { @prev_label } end else - render RubyUI::PaginationItem.new(href: page_href(current - 1)) { plain "Previous" } + render RubyUI::PaginationItem.new(href: page_href(current - 1)) { @prev_label } end end def next_item if current >= total li do - span(class: "opacity-50 pointer-events-none px-3 h-9 inline-flex items-center text-sm") { plain "Next" } + span(class: "opacity-50 pointer-events-none px-3 h-9 inline-flex items-center text-sm") { @next_label } end else - render RubyUI::PaginationItem.new(href: page_href(current + 1)) { plain "Next" } + render RubyUI::PaginationItem.new(href: page_href(current + 1)) { @next_label } end end diff --git a/lib/ruby_ui/data_table/data_table_pagy_adapter.rb b/lib/ruby_ui/data_table/data_table_pagy_adapter.rb new file mode 100644 index 00000000..fad905d3 --- /dev/null +++ b/lib/ruby_ui/data_table/data_table_pagy_adapter.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module RubyUI + class DataTablePagyAdapter + def initialize(pagy) + @pagy = pagy + end + + def current_page = @pagy.page + + def total_pages = @pagy.pages + + def total_count = @pagy.count + + def per_page = @pagy.items + end +end diff --git a/lib/ruby_ui/data_table/data_table_sort_head.rb b/lib/ruby_ui/data_table/data_table_sort_head.rb index d74ff0dd..7cd174c7 100644 --- a/lib/ruby_ui/data_table/data_table_sort_head.rb +++ b/lib/ruby_ui/data_table/data_table_sort_head.rb @@ -44,7 +44,9 @@ def sort_href end def build_query(hash) - hash.map { |k, v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join("&") + hash.flat_map { |k, v| + Array(v).map { |val| "#{CGI.escape(k.to_s)}=#{CGI.escape(val.to_s)}" } + }.join("&") end def sort_icon diff --git a/lib/ruby_ui/data_table_pagination_adapters/kaminari.rb b/lib/ruby_ui/data_table_pagination_adapters/kaminari.rb deleted file mode 100644 index 85cc2b14..00000000 --- a/lib/ruby_ui/data_table_pagination_adapters/kaminari.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -module RubyUI - module DataTablePaginationAdapters - class Kaminari - def initialize(collection) - @collection = collection - end - - def current_page = @collection.current_page - - def total_pages = @collection.total_pages - - def total_count = @collection.total_count - - def per_page = @collection.limit_value - end - end -end diff --git a/lib/ruby_ui/data_table_pagination_adapters/manual.rb b/lib/ruby_ui/data_table_pagination_adapters/manual.rb deleted file mode 100644 index b038ff1c..00000000 --- a/lib/ruby_ui/data_table_pagination_adapters/manual.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -module RubyUI - module DataTablePaginationAdapters - class Manual - attr_reader :current_page, :per_page, :total_count - - def initialize(page:, per_page:, total_count:) - @current_page = page.to_i - @per_page = [per_page.to_i, 1].max - @total_count = total_count.to_i - end - - def total_pages - [(@total_count.to_f / @per_page).ceil, 1].max - end - end - end -end diff --git a/lib/ruby_ui/data_table_pagination_adapters/pagy.rb b/lib/ruby_ui/data_table_pagination_adapters/pagy.rb deleted file mode 100644 index a6e0f0a7..00000000 --- a/lib/ruby_ui/data_table_pagination_adapters/pagy.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -module RubyUI - module DataTablePaginationAdapters - class Pagy - def initialize(pagy) - @pagy = pagy - end - - def current_page = @pagy.page - - def total_pages = @pagy.pages - - def total_count = @pagy.count - - def per_page = @pagy.items - end - end -end diff --git a/test/ruby_ui/data_table_pagination_adapters/kaminari_test.rb b/test/ruby_ui/data_table_kaminari_adapter_test.rb similarity index 70% rename from test/ruby_ui/data_table_pagination_adapters/kaminari_test.rb rename to test/ruby_ui/data_table_kaminari_adapter_test.rb index 8ff7ac05..8b568e50 100644 --- a/test/ruby_ui/data_table_pagination_adapters/kaminari_test.rb +++ b/test/ruby_ui/data_table_kaminari_adapter_test.rb @@ -1,14 +1,14 @@ # frozen_string_literal: true require "test_helper" -require "ruby_ui/data_table_pagination_adapters/kaminari" +require "ruby_ui/data_table/data_table_kaminari_adapter" -class RubyUI::DataTablePaginationAdapters::KaminariTest < ComponentTest +class RubyUI::DataTableKaminariAdapterTest < ComponentTest CollectionDouble = Data.define(:current_page, :total_pages, :total_count, :limit_value) def test_reads_current_page_total_pages_total_count_limit_value coll = CollectionDouble.new(current_page: 3, total_pages: 7, total_count: 61, limit_value: 10) - adapter = RubyUI::DataTablePaginationAdapters::Kaminari.new(coll) + adapter = RubyUI::DataTableKaminariAdapter.new(coll) assert_equal 3, adapter.current_page assert_equal 7, adapter.total_pages assert_equal 61, adapter.total_count diff --git a/test/ruby_ui/data_table_pagination_adapters/manual_test.rb b/test/ruby_ui/data_table_manual_adapter_test.rb similarity index 53% rename from test/ruby_ui/data_table_pagination_adapters/manual_test.rb rename to test/ruby_ui/data_table_manual_adapter_test.rb index 35d7f916..d90bf8ea 100644 --- a/test/ruby_ui/data_table_pagination_adapters/manual_test.rb +++ b/test/ruby_ui/data_table_manual_adapter_test.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true require "test_helper" -require "ruby_ui/data_table_pagination_adapters/manual" +require "ruby_ui/data_table/data_table_manual_adapter" -class RubyUI::DataTablePaginationAdapters::ManualTest < ComponentTest +class RubyUI::DataTableManualAdapterTest < ComponentTest def test_computes_total_pages_from_total_count_and_per_page - adapter = RubyUI::DataTablePaginationAdapters::Manual.new(page: 2, per_page: 10, total_count: 25) + adapter = RubyUI::DataTableManualAdapter.new(page: 2, per_page: 10, total_count: 25) assert_equal 2, adapter.current_page assert_equal 10, adapter.per_page assert_equal 25, adapter.total_count @@ -13,12 +13,12 @@ def test_computes_total_pages_from_total_count_and_per_page end def test_total_pages_is_at_least_1_for_empty_total - adapter = RubyUI::DataTablePaginationAdapters::Manual.new(page: 1, per_page: 10, total_count: 0) + adapter = RubyUI::DataTableManualAdapter.new(page: 1, per_page: 10, total_count: 0) assert_equal 1, adapter.total_pages end def test_coerces_integer_inputs - adapter = RubyUI::DataTablePaginationAdapters::Manual.new(page: "3", per_page: "5", total_count: "12") + adapter = RubyUI::DataTableManualAdapter.new(page: "3", per_page: "5", total_count: "12") assert_equal 3, adapter.current_page assert_equal 3, adapter.total_pages end diff --git a/test/ruby_ui/data_table_pagination_adapters/pagy_test.rb b/test/ruby_ui/data_table_pagy_adapter_test.rb similarity index 67% rename from test/ruby_ui/data_table_pagination_adapters/pagy_test.rb rename to test/ruby_ui/data_table_pagy_adapter_test.rb index 2c9c1682..833f0dde 100644 --- a/test/ruby_ui/data_table_pagination_adapters/pagy_test.rb +++ b/test/ruby_ui/data_table_pagy_adapter_test.rb @@ -1,14 +1,14 @@ # frozen_string_literal: true require "test_helper" -require "ruby_ui/data_table_pagination_adapters/pagy" +require "ruby_ui/data_table/data_table_pagy_adapter" -class RubyUI::DataTablePaginationAdapters::PagyTest < ComponentTest +class RubyUI::DataTablePagyAdapterTest < ComponentTest PagyDouble = Data.define(:page, :pages, :count, :items) def test_reads_page_pages_count_items pagy = PagyDouble.new(page: 2, pages: 5, count: 47, items: 10) - adapter = RubyUI::DataTablePaginationAdapters::Pagy.new(pagy) + adapter = RubyUI::DataTablePagyAdapter.new(pagy) assert_equal 2, adapter.current_page assert_equal 5, adapter.total_pages assert_equal 47, adapter.total_count