madmin 3.1.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dde4d963db323d7d26197c454095beed2eff86ff40dcd9359e85ee480dd3bc13
4
- data.tar.gz: 68566f86e2163ce2b7bf2fd12f6289d786fa118639936eff1aeef5f84feea616
3
+ metadata.gz: d296cf7cb6a9354c9592abe179e09f696c1d57d29b180832a89b5cbc40bd0af9
4
+ data.tar.gz: 413c7d5f5f4182c623e1e396a8cec662c3ddc6a6b3fa154bdbed42ea85de655a
5
5
  SHA512:
6
- metadata.gz: 0c2206a2935ec06380389dbca3109acabf2a3f0af8d84105d964b9551bde50c30c8746403aa718b0acd9e397efecb7fe70e74f9b8704d5a2c3d7d8474898305f
7
- data.tar.gz: eb2128311c6fd923d69f3d58955e7c9e0bdf322a8949532fc156ec8fec6bba4ab6afd6771d4b06df584a3939ef67ba5879dad16da75611d37816857b92d9582f
6
+ metadata.gz: d8ec5350c6adb616086c148e18323a16bb6ea06049e96c2731b4c2ffe1a23208493265415772833c44ea6684e9909e289a27d6447378fad79682a5ae0f64f017
7
+ data.tar.gz: 07a42b02500a2bb14eae9d2817b75f54c7798917b76fdf39aefa6c66d8dcf813cc3553842643db20abf12e5998a7de9c695226eb843966a5430cd40ca5033222
@@ -1,4 +1,7 @@
1
1
  .pagination {
2
+ display: flex;
3
+ flex-wrap: wrap;
4
+ align-items: center;
2
5
  padding: 0.5rem;
3
6
  }
4
7
 
@@ -44,3 +47,16 @@
44
47
  .pagination-info {
45
48
  margin-left: 0.5rem;
46
49
  }
50
+
51
+ .per-page {
52
+ display: inline-flex;
53
+ gap: 0.5rem;
54
+ align-items: center;
55
+ margin-left: auto;
56
+ font-size: 0.875rem;
57
+
58
+ a[aria-current="true"] {
59
+ color: var(--text-color);
60
+ font-weight: 600;
61
+ }
62
+ }
@@ -91,7 +91,7 @@ module Madmin
91
91
  # Returns [page, records]. Override for non-ActiveRecord collections and
92
92
  # return an object responding to the Madmin::Page interface.
93
93
  def paginate_collection(collection)
94
- paginate(collection, page: params[:page])
94
+ paginate(collection, page: params[:page], per_page: Madmin::Page.per_page_for(params[:per_page]))
95
95
  end
96
96
 
97
97
  def valid_scope
@@ -19,5 +19,23 @@ module Madmin
19
19
  def index_path_with(**changes)
20
20
  resource.index_path(request.query_parameters.symbolize_keys.except(:page).merge(changes))
21
21
  end
22
+
23
+ # The current URL with some params changed, or removed when nil. Works on
24
+ # any page, unlike index_path_with
25
+ def current_path_with(changes)
26
+ "#{request.path}?#{request.query_parameters.merge(changes).compact.to_query}"
27
+ end
28
+
29
+ # Hidden fields carrying the current index params through a GET form, so
30
+ # submitting it keeps what index_path_with keeps. Pass the params the form
31
+ # sets itself in except
32
+ def index_params_fields(except: [])
33
+ query = request.query_parameters.except("page", *except.map(&:to_s)).to_query
34
+ fields = query.split("&").map do |pair|
35
+ name, value = pair.split("=", 2).map { |part| CGI.unescape(part) }
36
+ hidden_field_tag name, value, id: nil
37
+ end
38
+ safe_join(fields, "\n")
39
+ end
22
40
  end
23
41
  end
@@ -6,9 +6,7 @@
6
6
 
7
7
  <div id="filters" class="filters" popover data-controller="filters">
8
8
  <%= form_with url: resource.index_path, method: :get, skip_enforcing_utf8: true do %>
9
- <% request.query_parameters.slice("q", "scope", "sort", "direction").each do |name, value| %>
10
- <%= hidden_field_tag name, value, id: nil %>
11
- <% end %>
9
+ <%= index_params_fields except: [:filters] %>
12
10
 
13
11
  <p class="filters-heading"><%= t("madmin.filters.heading") %></p>
14
12
 
@@ -1,8 +1,7 @@
1
1
  <div class="pagination">
2
2
  <% if page.last > 1 %>
3
- <% page_url = ->(number) { "#{request.path}?#{request.query_parameters.merge(page.param => number).to_query}" } %>
4
3
  <nav class="pages" aria-label="<%= t("madmin.pagination.label") %>">
5
- <%= link_to_if page.prev, "<", page.prev && page_url.call(page.prev), aria: { label: t("madmin.pagination.previous") } do %>
4
+ <%= link_to_if page.prev, "<", page.prev && current_path_with(page.param => page.prev), aria: { label: t("madmin.pagination.previous") } do %>
6
5
  <a role="link" aria-disabled="true" aria-label="<%= t("madmin.pagination.previous") %>">&lt;</a>
7
6
  <% end %>
8
7
 
@@ -12,11 +11,11 @@
12
11
  <% elsif number == page.page %>
13
12
  <a role="link" aria-disabled="true" aria-current="page"><%= number %></a>
14
13
  <% else %>
15
- <%= link_to number, page_url.call(number) %>
14
+ <%= link_to number, current_path_with(page.param => number) %>
16
15
  <% end %>
17
16
  <% end %>
18
17
 
19
- <%= link_to_if page.next, ">", page.next && page_url.call(page.next), aria: { label: t("madmin.pagination.next") } do %>
18
+ <%= link_to_if page.next, ">", page.next && current_path_with(page.param => page.next), aria: { label: t("madmin.pagination.next") } do %>
20
19
  <a role="link" aria-disabled="true" aria-label="<%= t("madmin.pagination.next") %>">&gt;</a>
21
20
  <% end %>
22
21
  </nav>
@@ -29,4 +28,6 @@
29
28
  <%= t("madmin.pagination.info", from: page.from, to: page.to, count: page.count) %>
30
29
  <% end %>
31
30
  </span>
31
+
32
+ <%= render "per_page", page: page if page.resizable? %>
32
33
  </div>
@@ -0,0 +1,10 @@
1
+ <nav class="per-page" aria-label="<%= t("madmin.pagination.per_page") %>">
2
+ <span><%= t("madmin.pagination.per_page") %></span>
3
+ <% page.per_page_options.each do |size| %>
4
+ <% if size == page.per_page %>
5
+ <a role="link" aria-disabled="true" aria-current="true"><%= size %></a>
6
+ <% else %>
7
+ <%= link_to size, current_path_with(page.param => nil, page.per_page_param => size) %>
8
+ <% end %>
9
+ <% end %>
10
+ </nav>
@@ -6,12 +6,8 @@
6
6
  <div class="actions">
7
7
  <form class="search">
8
8
  <%= hidden_field_tag :page, params[:page], value: 1 %>
9
+ <%= index_params_fields except: [:q] %>
9
10
  <%= search_field_tag :q, params[:q], placeholder: t("madmin.search.placeholder") %>
10
- <% filters.map(&:to_h).each do |filter| %>
11
- <% filter.each do |name, value| %>
12
- <%= hidden_field_tag "filters[][#{name}]", value, id: nil %>
13
- <% end %>
14
- <% end %>
15
11
  </form>
16
12
 
17
13
  <%= link_to clear_search_params, class: "btn btn-secondary" do %>
@@ -48,6 +48,7 @@ el:
48
48
  next: Επόμενη
49
49
  info: "Εμφάνιση %{from}-%{to} από %{count}"
50
50
  empty: Δεν βρέθηκαν εγγραφές
51
+ per_page: Ανά σελίδα
51
52
  filters:
52
53
  button: "Φίλτρα"
53
54
  heading: "Εμφάνιση εγγραφών όπου"
@@ -48,6 +48,7 @@ en:
48
48
  next: Next
49
49
  info: "Displaying %{from}-%{to} of %{count}"
50
50
  empty: No records found
51
+ per_page: Per page
51
52
  filters:
52
53
  button: "Filters"
53
54
  heading: "Show records where"
@@ -48,6 +48,7 @@ fr:
48
48
  next: Suivant
49
49
  info: "Affichage de %{from} à %{to} sur %{count}"
50
50
  empty: Aucun enregistrement trouvé
51
+ per_page: Par page
51
52
  filters:
52
53
  button: "Filtres"
53
54
  heading: "Afficher les enregistrements où"
@@ -47,6 +47,7 @@ ko:
47
47
  next: 다음
48
48
  info: "%{count}개 중 %{from}-%{to} 표시"
49
49
  empty: 레코드가 없습니다
50
+ per_page: 페이지당
50
51
  filters:
51
52
  button: "필터"
52
53
  heading: "다음 조건의 레코드 표시"
@@ -38,7 +38,9 @@ module Madmin
38
38
 
39
39
  def paginated_value(record, params)
40
40
  page_key = "#{attribute_name}_page"
41
- paginate value(record), page: params[page_key], param: page_key
41
+ per_page = Madmin::Page.per_page_for(params["#{attribute_name}_per_page"])
42
+
43
+ paginate value(record), page: params[page_key], per_page: per_page, param: page_key
42
44
  end
43
45
  end
44
46
  end
data/lib/madmin/page.rb CHANGED
@@ -5,9 +5,22 @@ module Madmin
5
5
  # these (or any object responding to the same methods) alongside their records.
6
6
  class Page
7
7
  SERIES_SLOTS = 7
8
+ PER_PAGE_OPTIONS = [20, 50, 100, 200].freeze
8
9
 
9
10
  attr_reader :count, :page, :per_page, :param
10
11
 
12
+ # The page size for a request param. Invalid sizes fall back to the default
13
+ # and large ones are capped. Sizes passed to Page.new directly aren't capped
14
+ def self.per_page_for(param)
15
+ size = param.to_s.to_i
16
+ size.positive? ? [size, max_per_page].min : Madmin.per_page
17
+ end
18
+
19
+ def self.max_per_page
20
+ [PER_PAGE_OPTIONS.max, Madmin.per_page].max
21
+ end
22
+ private_class_method :max_per_page
23
+
11
24
  def initialize(count:, page: 1, per_page: Madmin.per_page, param: :page)
12
25
  @count = count.to_i
13
26
  @per_page = [per_page.to_i, 1].max
@@ -15,6 +28,21 @@ module Madmin
15
28
  @param = param.to_s
16
29
  end
17
30
 
31
+ # The param carrying the page size: "per_page", or "posts_per_page" for a "posts_page" param
32
+ def per_page_param
33
+ "#{param.delete_suffix("page")}per_page"
34
+ end
35
+
36
+ # Page sizes to offer, always including the default and the current one
37
+ def per_page_options
38
+ (PER_PAGE_OPTIONS | [Madmin.per_page, per_page]).sort
39
+ end
40
+
41
+ # Whether a different page size would change what's shown
42
+ def resizable?
43
+ count > per_page_options.min
44
+ end
45
+
18
46
  def last
19
47
  [(count.to_f / per_page).ceil, 1].max
20
48
  end
@@ -1,3 +1,3 @@
1
1
  module Madmin
2
- VERSION = "3.1.2"
2
+ VERSION = "3.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: madmin
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.2
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Oliver
@@ -113,6 +113,7 @@ files:
113
113
  - app/views/madmin/application/_missing_resource.html.erb
114
114
  - app/views/madmin/application/_navigation.html.erb
115
115
  - app/views/madmin/application/_pagination.html.erb
116
+ - app/views/madmin/application/_per_page.html.erb
116
117
  - app/views/madmin/application/edit.html.erb
117
118
  - app/views/madmin/application/index.html.erb
118
119
  - app/views/madmin/application/new.html.erb