diff --git a/apps/pagy_calendar_app.ru b/apps/pagy_calendar_app.ru index 2510c6f81..c85328a5e 100644 --- a/apps/pagy_calendar_app.ru +++ b/apps/pagy_calendar_app.ru @@ -18,7 +18,7 @@ require 'bundler/inline' # NOTICE: if you get any installation error with the following setup # temporarily remove the Gemfile and Gemfile.lock from the repo (they may interfere with the bundler/inline) -gemfile true do +gemfile false do source 'https://rubygems.org' gem 'rack' # gem 'pagy' # <--install from rubygems @@ -69,15 +69,17 @@ class PagyCalendarApp < Sinatra::Base get '/' do Time.zone = 'EST' # convert the UTC storage time to time with zone 'EST' collection = MockCollection::Calendar.new + # Default calendar # The conf Hash defines the pagy objects variables keyed by calendar unit and the final pagy standard object # The :skip is an optional and arbitrarily named param that skips the calendar pagination and uses only the pagy # object to paginate the unfiltered collection. (It's active by default even without a :skip param). # You way want to invert the logic (also in the view) with something like `active: params[:active]`, # which would be inactive by default and only active on demand. - @calendar, @pagy, @records = pagy_calendar(collection, year: { size: 4 }, - month: { size: 12, format: '%b' }, - pagy: { items: 10 }, + @calendar, @pagy, @records = pagy_calendar(collection, year: {}, + month: {}, + day: {}, active: !params[:skip]) + erb :pagy_demo # template available in the __END__ section as @@ pagy_demo end end @@ -112,7 +114,7 @@ __END__ <% else %> Hide Calendar
- Go to the 2022-03 Page + Go to the 2022-03-02 Page <% end %>

@@ -122,6 +124,8 @@ __END__

Showtime: <%= @calendar.showtime %>

<%= pagy_bootstrap_nav(@calendar[:year]) %> <%= pagy_bootstrap_nav(@calendar[:month]) %> + + <%= pagy_bootstrap_nav(@calendar[:day]) if @calendar[:day] %> <% end %> diff --git a/e2e/pagy_app.ru b/e2e/pagy_app.ru index 386e64942..67408d854 100644 --- a/e2e/pagy_app.ru +++ b/e2e/pagy_app.ru @@ -87,7 +87,9 @@ class PagyApp < Sinatra::Base %W[/#{name}-calendar /#{name}-calendar/:trim].each do |route| get(route) do collection = MockCollection::Calendar.new - @calendar, @pagy, @records = pagy_calendar(collection, month: { size: [1, 2, 2, 1], trim_extra: params['trim'] }) + @calendar, @pagy, @records = pagy_calendar(collection, month: { size: [1, 2, 2, 1], + format: '%Y-%m', + trim_extra: params['trim'] }) name_fragment = name == 'navs' ? '' : "#{name}_" erb :calendar_helpers, locals: { name: name, name_fragment: name_fragment } end diff --git a/lib/pagy/calendar/day.rb b/lib/pagy/calendar/day.rb index f3ac606d1..5815583f9 100644 --- a/lib/pagy/calendar/day.rb +++ b/lib/pagy/calendar/day.rb @@ -5,8 +5,9 @@ class Pagy # :nodoc: class Calendar # :nodoc: # Calendar day subclass class Day < Calendar - DEFAULT = { order: :asc, # rubocop:disable Style/MutableConstant - format: '%Y-%m-%d' } + DEFAULT = { size: 31, # rubocop:disable Style/MutableConstant + order: :asc, + format: '%d' } protected diff --git a/lib/pagy/calendar/helper.rb b/lib/pagy/calendar/helper.rb index 44b491b85..864bd61f6 100644 --- a/lib/pagy/calendar/helper.rb +++ b/lib/pagy/calendar/helper.rb @@ -17,13 +17,13 @@ def init(conf, period, params) # Create the calendar def init(conf, period, params) - @units = Calendar::UNITS & conf.keys # get the units in time length desc order + @conf = Marshal.load(Marshal.dump(conf)) # store a copy + @units = Calendar::UNITS & @conf.keys # get the units in time length desc order raise ArgumentError, 'no calendar unit found in pagy_calendar @configuration' if @units.empty? @period = period @params = params @page_param = conf[:pagy][:page_param] || DEFAULT[:page_param] - @conf = Marshal.load(Marshal.dump(conf)) # store a copy @units.each do |unit| # set all the :page_param vars for later deletion unit_page_param = :"#{unit}_#{@page_param}" conf[unit][:page_param] = unit_page_param diff --git a/lib/pagy/calendar/month.rb b/lib/pagy/calendar/month.rb index 877460f31..9f256877a 100644 --- a/lib/pagy/calendar/month.rb +++ b/lib/pagy/calendar/month.rb @@ -5,8 +5,9 @@ class Pagy # :nodoc: class Calendar # :nodoc: # Calendar month subclass class Month < Calendar - DEFAULT = { order: :asc, # rubocop:disable Style/MutableConstant - format: '%Y-%m' } + DEFAULT = { size: 12, # rubocop:disable Style/MutableConstant + order: :asc, + format: '%b' } protected diff --git a/lib/pagy/calendar/quarter.rb b/lib/pagy/calendar/quarter.rb index 6d7a91fca..811111abf 100644 --- a/lib/pagy/calendar/quarter.rb +++ b/lib/pagy/calendar/quarter.rb @@ -5,8 +5,9 @@ class Pagy # :nodoc: class Calendar # :nodoc: # Calendar quarter subclass class Quarter < Calendar - DEFAULT = { order: :asc, # rubocop:disable Style/MutableConstant - format: '%Y-Q%q' } # '%q' token + DEFAULT = { size: 4, # rubocop:disable Style/MutableConstant + order: :asc, + format: 'Q%q' } # '%q' token # The label for any page, with the substitution of the '%q' token def label_for(page, opts = {}) diff --git a/lib/pagy/calendar/year.rb b/lib/pagy/calendar/year.rb index 81ed75e1b..e48f2b117 100644 --- a/lib/pagy/calendar/year.rb +++ b/lib/pagy/calendar/year.rb @@ -5,7 +5,8 @@ class Pagy # :nodoc: class Calendar # :nodoc: # Calendar year subclass class Year < Calendar - DEFAULT = { order: :asc, # rubocop:disable Style/MutableConstant + DEFAULT = { size: 10, # rubocop:disable Style/MutableConstant + order: :asc, format: '%Y' } protected diff --git a/lib/pagy/extras/calendar.rb b/lib/pagy/extras/calendar.rb index 2f1266f85..6c8970170 100644 --- a/lib/pagy/extras/calendar.rb +++ b/lib/pagy/extras/calendar.rb @@ -15,11 +15,10 @@ module Backend # Take a collection and a conf Hash with keys in CONF_KEYS and return an array with 3 items: [calendar, pagy, results] def pagy_calendar(collection, conf) - unless conf.is_a?(Hash) && (conf.keys - CONF_KEYS).empty? && conf.all? { |k, v| v.is_a?(Hash) || k == :active } - raise ArgumentError, "keys must be in #{CONF_KEYS.inspect} and object values must be Hashes; got #{conf.inspect}" - end + raise ArgumentError, "keys must be in #{CONF_KEYS.inspect}" \ + unless conf.is_a?(Hash) && (conf.keys - CONF_KEYS).empty? - conf[:pagy] = {} unless conf[:pagy] # use default Pagy object when omitted + conf[:pagy] ||= {} unless conf.key?(:active) && !conf[:active] calendar, from, to = Calendar::Helper.send(:init, conf, pagy_calendar_period(collection), params) collection = pagy_calendar_filter(collection, from, to) diff --git a/test/pagy/calendar_dst_test.rb b/test/pagy/calendar_dst_test.rb index b8ab1de8c..00e12f46d 100644 --- a/test/pagy/calendar_dst_test.rb +++ b/test/pagy/calendar_dst_test.rb @@ -11,25 +11,25 @@ it 'calculates the last label out of DST' do starting = Time.zone.local(2022, 3, 1, 3) # PST ending = Time.zone.local(2022, 3, 10, 3) # PST - p = Pagy::Calendar.send(:create, :day, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :day, format: '%Y-%m-%d', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-03-10" end it 'calculates the last label entering DST' do starting = Time.zone.local(2022, 3, 10, 3) # PST ending = Time.zone.local(2022, 3, 20, 3) # PDT - p = Pagy::Calendar.send(:create, :day, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :day, format: '%Y-%m-%d', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-03-20" end it 'calculates the last label in DST' do starting = Time.zone.local(2022, 10, 1, 3) # PDT ending = Time.zone.local(2022, 10, 10, 3) # PDT - p = Pagy::Calendar.send(:create, :day, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :day, format: '%Y-%m-%d', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-10-10" end it 'calculates the last label exiting DST' do starting = Time.zone.local(2022, 11, 1, 3) # PDT ending = Time.zone.local(2022, 11, 10, 3) # PST - p = Pagy::Calendar.send(:create, :day, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :day, format: '%Y-%m-%d', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-11-10" end end @@ -65,25 +65,25 @@ it 'calculates the last label out of DST' do starting = Time.zone.local(2021, 12, 3, 3) # PST ending = Time.zone.local(2022, 2, 10, 3) # PST - p = Pagy::Calendar.send(:create, :month, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :month, format: '%Y-%m', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-02" end it 'calculates the last label entering DST' do starting = Time.zone.local(2022, 2, 10, 3) # PST ending = Time.zone.local(2022, 4, 21, 3) # PDT W - p = Pagy::Calendar.send(:create, :month, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :month, format: '%Y-%m', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-04" end it 'calculates the last label in DST' do starting = Time.zone.local(2022, 7, 1, 3) # PDT ending = Time.zone.local(2022, 9, 10, 3) # PDT - p = Pagy::Calendar.send(:create, :month, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :month, format: '%Y-%m', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-09" end it 'calculates the last label exiting DST' do starting = Time.zone.local(2022, 9, 10, 3) # PDT ending = Time.zone.local(2022, 11, 10, 3) # PST - p = Pagy::Calendar.send(:create, :month, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :month, format: '%Y-%m', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-11" end end @@ -92,25 +92,25 @@ it 'calculates the last label out of DST' do starting = Time.zone.local(2022, 1, 3, 3) # PST ending = Time.zone.local(2022, 2, 10, 3) # PST - p = Pagy::Calendar.send(:create, :quarter, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :quarter, format: '%Y-Q%q', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-Q1" end it 'calculates the last label entering DST' do starting = Time.zone.local(2022, 2, 10, 3) # PST ending = Time.zone.local(2022, 4, 21, 3) # PDT W - p = Pagy::Calendar.send(:create, :quarter, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :quarter, format: '%Y-Q%q', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-Q2" end it 'calculates the last label in DST' do starting = Time.zone.local(2022, 7, 1, 3) # PDT ending = Time.zone.local(2022, 9, 10, 3) # PDT - p = Pagy::Calendar.send(:create, :quarter, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :quarter, format: '%Y-Q%q', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-Q3" end it 'calculates the last label exiting DST' do starting = Time.zone.local(2022, 9, 10, 3) # PDT ending = Time.zone.local(2022, 11, 10, 3) # PST - p = Pagy::Calendar.send(:create, :quarter, period: [starting, ending]) + p = Pagy::Calendar.send(:create, :quarter, format: '%Y-Q%q', period: [starting, ending]) _(p.label_for(p.last)).must_equal "2022-Q4" end end diff --git a/test/pagy/calendar_test.rb b/test/pagy/calendar_test.rb index 7342229da..dbe1063e8 100644 --- a/test/pagy/calendar_test.rb +++ b/test/pagy/calendar_test.rb @@ -252,7 +252,7 @@ def pagy(unit: :month, **vars) describe '#label' do it 'uses the default and custom format' do p = pagy(unit: :month, order: :desc, page: 2) - _(p.label).must_equal '2023-10' + _(p.label).must_equal 'Oct' _(p.label(format: '%B %Y')).must_equal 'October 2023' end end diff --git a/test/pagy/calendar_test.rb.rematch b/test/pagy/calendar_test.rb.rematch index 9fb2f32f8..5580a9db7 100644 --- a/test/pagy/calendar_test.rb.rematch +++ b/test/pagy/calendar_test.rb.rematch @@ -1,11 +1,11 @@ --- -"[1] pagy/calendar::#label_for#test_0001_labels the year": '2021' -"[2] pagy/calendar::#label_for#test_0001_labels the year": '2022' -"[1] pagy/calendar::#label_for#test_0003_labels the month": 2021-10 -"[2] pagy/calendar::#label_for#test_0003_labels the month": 2021-11 -"[1] pagy/calendar::#label_for#test_0002_labels the quarter": 2021-Q4 -"[2] pagy/calendar::#label_for#test_0002_labels the quarter": 2022-Q1 -"[1] pagy/calendar::#label_for#test_0005_labels the day": '2021-10-21' -"[2] pagy/calendar::#label_for#test_0005_labels the day": '2021-10-22' +"[1] pagy/calendar::#label_for#test_0003_labels the month": Oct +"[2] pagy/calendar::#label_for#test_0003_labels the month": Nov "[1] pagy/calendar::#label_for#test_0004_labels the week": 2021-41 "[2] pagy/calendar::#label_for#test_0004_labels the week": 2021-42 +"[1] pagy/calendar::#label_for#test_0002_labels the quarter": Q4 +"[2] pagy/calendar::#label_for#test_0002_labels the quarter": Q1 +"[1] pagy/calendar::#label_for#test_0001_labels the year": '2021' +"[2] pagy/calendar::#label_for#test_0001_labels the year": '2022' +"[1] pagy/calendar::#label_for#test_0005_labels the day": '21' +"[2] pagy/calendar::#label_for#test_0005_labels the day": '22' diff --git a/test/pagy/extras/calendar_extra_test.rb b/test/pagy/extras/calendar_extra_test.rb index b6744c728..67a6d98f9 100644 --- a/test/pagy/extras/calendar_extra_test.rb +++ b/test/pagy/extras/calendar_extra_test.rb @@ -48,7 +48,7 @@ def app(**opts) it 'raises ArgumentError for wrong conf' do _ { MockApp::Calendar.new.send(:pagy_calendar, @collection, []) }.must_raise ArgumentError _ { MockApp::Calendar.new.send(:pagy_calendar, @collection, unknown: {}) }.must_raise ArgumentError - _ { MockApp::Calendar.new.send(:pagy_calendar, @collection, year: []) }.must_raise ArgumentError + _ { MockApp::Calendar.new.send(:pagy_calendar, @collection, year: []) }.must_raise TypeError _ { MockApp::Calendar.new.send(:pagy_calendar, @collection, {}) }.must_raise ArgumentError end it 'selects :year for the pages and check the total' do @@ -123,7 +123,7 @@ def app(**opts) end it 'selects :month for an intermediate page' do calendar, _pagy, entries = app(params: { month_page: 25 }).send(:pagy_calendar, @collection, - month: {}, + month: { size: [1, 4, 4, 1] }, pagy: { items: 600 }) _(calendar[:month].series).must_equal [1, :gap, 21, 22, 23, 24, '25', 26] _(calendar[:month].prev).must_equal 24 @@ -132,7 +132,7 @@ def app(**opts) end it 'selects :month for the last page' do calendar, _pagy, entries = app(params: { month_page: 26 }).send(:pagy_calendar, @collection, - month: {}, + month: {size: [1, 4, 4, 1]}, pagy: { items: 600 }) _(calendar[:month].series).must_equal [1, :gap, 22, 23, 24, 25, '26'] _(calendar[:month].prev).must_equal 25 @@ -170,7 +170,7 @@ def app(**opts) it 'selects :day for the first page' do collection = MockCollection::Calendar.new(@collection[0, 40]) calendar, _pagy, entries = app(params: { day_page: 1 }).send(:pagy_calendar, collection, - day: {}, + day: { size: [1, 4, 4, 1] }, pagy: { items: 600 }) _(calendar[:day].series).must_equal ["1", 2, 3, 4, 5, :gap, 60] @@ -182,7 +182,7 @@ def app(**opts) it 'selects :day for an intermediate page' do collection = MockCollection::Calendar.new(@collection[0, 40]) calendar, _pagy, entries = app(params: { day_page: 25 }).send(:pagy_calendar, collection, - day: {}, + day: { size: [1, 4, 4, 1] }, pagy: { items: 600 }) _(calendar[:day].series).must_equal [1, :gap, 21, 22, 23, 24, "25", 26, 27, 28, 29, :gap, 60] _(calendar[:day].prev).must_equal 24 @@ -192,7 +192,7 @@ def app(**opts) it 'selects :day for the last page' do collection = MockCollection::Calendar.new(@collection[0, 40]) calendar, _pagy, entries = app(params: { day_page: 60 }).send(:pagy_calendar, collection, - day: {}, + day: { size: [1, 4, 4, 1]}, pagy: { items: 600 }) _(calendar[:day].series).must_equal [1, :gap, 56, 57, 58, 59, "60"] _(calendar[:day].prev).must_equal 59 diff --git a/test/pagy/extras/frontend_helpers_json_test.rb.rematch b/test/pagy/extras/frontend_helpers_json_test.rb.rematch index f35c2778e..8ccab99e5 100644 --- a/test/pagy/extras/frontend_helpers_json_test.rb.rematch +++ b/test/pagy/extras/frontend_helpers_json_test.rb.rematch @@ -19,24 +19,24 @@ - 26 "[2] pagy/extras/frontend_helpers_json::Calendar sequels and label_sequels#test_0001_generate the labels for the sequels": '0': - - 2021-10 - - 2021-11 - - 2021-12 - - 2022-01 - - 2022-02 + - Oct + - Nov + - Dec + - Jan + - Feb - :gap - - 2023-11 + - Nov '600': - - 2021-10 - - 2021-11 - - 2021-12 - - 2022-01 - - 2022-02 - - 2022-03 + - Oct + - Nov + - Dec + - Jan + - Feb + - Mar - :gap - - 2023-11 + - Nov +"[1] pagy/extras/frontend_helpers_json::#pagy_data#test_0001_uses json": data-pagy="WyJ0ZXN0X2Z1bmN0aW9uIiwic29tZS1zdHJpbmciLDEyMyx0cnVlXQ==" '[1] pagy/extras/frontend_helpers_json::#pagy_marked_link#test_0001_returns only the "standard" link': '' '[2] pagy/extras/frontend_helpers_json::#pagy_marked_link#test_0001_returns only the "standard" link': '' -"[1] pagy/extras/frontend_helpers_json::#pagy_data#test_0001_uses json": data-pagy="WyJ0ZXN0X2Z1bmN0aW9uIiwic29tZS1zdHJpbmciLDEyMyx0cnVlXQ==" diff --git a/test/pagy/extras/frontend_helpers_oj_test.rb.rematch b/test/pagy/extras/frontend_helpers_oj_test.rb.rematch index 8e4234f4e..e70665d9b 100644 --- a/test/pagy/extras/frontend_helpers_oj_test.rb.rematch +++ b/test/pagy/extras/frontend_helpers_oj_test.rb.rematch @@ -1,4 +1,8 @@ --- +'[1] pagy/extras/frontend_helpers_oj::#pagy_marked_link#test_0001_returns only the "standard" link': '' +'[2] pagy/extras/frontend_helpers_oj::#pagy_marked_link#test_0001_returns only the "standard" link': '' "[1] pagy/extras/frontend_helpers_oj::Calendar sequels and label_sequels#test_0001_generate the labels for the sequels": '0': - 1 @@ -19,25 +23,21 @@ - 26 "[2] pagy/extras/frontend_helpers_oj::Calendar sequels and label_sequels#test_0001_generate the labels for the sequels": '0': - - 2021-10 - - 2021-11 - - 2021-12 - - 2022-01 - - 2022-02 + - Oct + - Nov + - Dec + - Jan + - Feb - :gap - - 2023-11 + - Nov '600': - - 2021-10 - - 2021-11 - - 2021-12 - - 2022-01 - - 2022-02 - - 2022-03 + - Oct + - Nov + - Dec + - Jan + - Feb + - Mar - :gap - - 2023-11 + - Nov "[1] pagy/extras/frontend_helpers_oj::#pagy_data#test_0001_uses oj": data-pagy="WyJ0ZXN0X2Z1bmN0aW9uIiwic29tZS1zdHJpbmciLDEyMyx0cnVlXQ==" "[2] pagy/extras/frontend_helpers_oj::#pagy_data#test_0001_uses oj": data-pagy="WyJ0ZXN0X2Z1bmN0aW9uIiwic29tZS1zdHJpbmciLDEyMyx0cnVlLCJwYWdlIl0=" -'[1] pagy/extras/frontend_helpers_oj::#pagy_marked_link#test_0001_returns only the "standard" link': '' -'[2] pagy/extras/frontend_helpers_oj::#pagy_marked_link#test_0001_returns only the "standard" link': '' diff --git a/test/pagy/extras/overflow_test.rb b/test/pagy/extras/overflow_test.rb index 7db67b356..3a2dd403b 100644 --- a/test/pagy/extras/overflow_test.rb +++ b/test/pagy/extras/overflow_test.rb @@ -116,7 +116,7 @@ _(pagy.page).must_equal 100 end it 'computes series for empty page for Pagy::Calendar' do - pagy = Pagy::Calendar::Day.new(calendar_vars.merge(overflow: :empty_page)) + pagy = Pagy::Calendar::Day.new(calendar_vars.merge(size: [1, 4, 4, 1], overflow: :empty_page)) series = pagy.series _(series).must_equal [1, :gap, 7, 8, 9, 10, 11] _(pagy.page).must_equal 100