yummy-guide-generic-administrate 0.7.0 → 0.7.1

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: cef007572ee8fc90b0579c0e6261263bb568d192702eb92ee418976a06404ffc
4
- data.tar.gz: be42920844cf830f365d2297e21605ad5191257d5a3f37ba2dd9f364ae16c768
3
+ metadata.gz: a0a5f41bc5f403a7d4da80d9a2b66c7313a9370374e171d2916b96de8aea2a8d
4
+ data.tar.gz: 77c5494b19b7c2364477e394c954e5640ac737658e05ec481ecef62aafc30c59
5
5
  SHA512:
6
- metadata.gz: 1f9203647f13a0974af5bd4b0de54ff23c2a8991ce0eb3e065a3c0d561b1f88898c9bc470642c294bf786f5250eab2f9d5780c91b35d3f6b3cc1da9f36e2a305
7
- data.tar.gz: b5d15a4f6ca3e708542fab9b1ce320ee76e45f3774bf775394cbff9548f4aca75f945259ef5e1a4c703a5ac5a3baa604a6933a6171868e83633f203698119866
6
+ metadata.gz: 73ea4e2fb99ffc3e16393fc105e93b39e0812ad313f4e88f95a333ae18a10132e7207e482c956f37dad5391c8ceb6ab246724adc6e413fe8d5b012c3d45c03fc
7
+ data.tar.gz: e891e0b581251db97ac188c934bef264d77790b47b154e44dd57f4d82cc57e4bd1f8d5a48e1537cf710e0e585935ff10eb889c3bac690a1455d16477b979b069
@@ -1,5 +1,6 @@
1
1
  (function() {
2
2
  var TABLE_SELECTOR = "table[data-fixed-columns-count]";
3
+ var MOBILE_MEDIA_QUERY = "(max-width: 767px)";
3
4
  var resizeObservers = new WeakMap();
4
5
 
5
6
  function directCells(row) {
@@ -31,10 +32,20 @@
31
32
  }
32
33
 
33
34
  function fixedColumnsCount(table) {
34
- var parsedCount = parseInt(table.dataset.fixedColumnsCount || "0", 10);
35
+ var rawCount = table.dataset.fixedColumnsCount || "0";
36
+
37
+ if (isMobile() && table.dataset.mobileFixedColumnsCount) {
38
+ rawCount = table.dataset.mobileFixedColumnsCount;
39
+ }
40
+
41
+ var parsedCount = parseInt(rawCount, 10);
35
42
  return Number.isNaN(parsedCount) ? 0 : Math.max(parsedCount, 0);
36
43
  }
37
44
 
45
+ function isMobile() {
46
+ return window.matchMedia && window.matchMedia(MOBILE_MEDIA_QUERY).matches;
47
+ }
48
+
38
49
  function stickyOffsets(table, count) {
39
50
  var headerRow = table.querySelector("thead tr");
40
51
  if (!headerRow) return [];
@@ -1,6 +1,7 @@
1
1
  (function() {
2
2
  var TABLE_SELECTOR = 'table[data-fixed-columns-count]';
3
3
  var WRAPPER_SELECTOR = '[data-fixed-header-scroll], .scroll-table, .home-table__wrapper, .table-wrap, .af__table__content';
4
+ var MOBILE_MEDIA_QUERY = '(max-width: 767px)';
4
5
  var resizeObservers = new WeakMap();
5
6
  var observedScrolls = new WeakMap();
6
7
  var observedFixedScrolls = new WeakMap();
@@ -36,10 +37,20 @@
36
37
  }
37
38
 
38
39
  function fixedColumnsCount(table) {
39
- var parsedCount = parseInt(table.dataset.fixedColumnsCount || '0', 10);
40
+ var rawCount = table.dataset.fixedColumnsCount || '0';
41
+
42
+ if (isMobile() && table.dataset.mobileFixedColumnsCount) {
43
+ rawCount = table.dataset.mobileFixedColumnsCount;
44
+ }
45
+
46
+ var parsedCount = parseInt(rawCount, 10);
40
47
  return Number.isNaN(parsedCount) ? 0 : Math.max(parsedCount, 0);
41
48
  }
42
49
 
50
+ function isMobile() {
51
+ return window.matchMedia && window.matchMedia(MOBILE_MEDIA_QUERY).matches;
52
+ }
53
+
43
54
  function stickyOffsets(widths) {
44
55
  var offsets = [];
45
56
  var currentLeft = 0;
@@ -555,6 +566,7 @@
555
566
 
556
567
  fixedTable.className = fixedHeaderTableClassName(sourceTable);
557
568
  fixedTable.dataset.fixedColumnsCount = sourceTable.dataset.fixedColumnsCount || '0';
569
+ fixedTable.dataset.mobileFixedColumnsCount = sourceTable.dataset.mobileFixedColumnsCount || fixedTable.dataset.fixedColumnsCount;
558
570
  fixedTable.style.width = '';
559
571
  fixedTable.innerHTML = sourceHead.outerHTML;
560
572
 
@@ -661,6 +661,27 @@ table[data-fixed-columns-count] [data-fixed-header-column-min-width] {
661
661
  }
662
662
 
663
663
  @media (max-width: 767px) {
664
+ .scroll-table,
665
+ .sticky-table-scroll,
666
+ .home-table__wrapper,
667
+ .table-wrap,
668
+ .af__table__content {
669
+ max-width: 100%;
670
+ overflow-x: auto;
671
+ overflow-y: hidden;
672
+ -webkit-overflow-scrolling: touch;
673
+ overscroll-behavior-x: contain;
674
+ touch-action: pan-x pan-y;
675
+ }
676
+
677
+ .scroll-table table[data-fixed-columns-count],
678
+ .sticky-table-scroll table[data-fixed-columns-count],
679
+ .home-table__wrapper table[data-fixed-columns-count],
680
+ .table-wrap table[data-fixed-columns-count],
681
+ .af__table__content table[data-fixed-columns-count] {
682
+ min-width: max-content;
683
+ }
684
+
664
685
  .yummy-guide-administrate-filter-form__title {
665
686
  padding: 16px 16px 12px;
666
687
  }
@@ -25,6 +25,18 @@ module YummyGuide
25
25
  end
26
26
  end
27
27
 
28
+ def self.index_mobile_fixed_columns_count
29
+ if const_defined?(:INDEX_MOBILE_FIXED_COLUMNS_COUNT, false)
30
+ const_get(:INDEX_MOBILE_FIXED_COLUMNS_COUNT)
31
+ elsif const_defined?(:INDEX_FIXED_COLUMNS_COUNT, false)
32
+ [index_fixed_columns_count.to_i, 1].min
33
+ elsif superclass.respond_to?(:index_mobile_fixed_columns_count)
34
+ superclass.index_mobile_fixed_columns_count
35
+ else
36
+ [index_fixed_columns_count.to_i, 1].min
37
+ end
38
+ end
39
+
28
40
  def self.collection_sortable_attributes
29
41
  if const_defined?(:COLLECTION_SORTABLE_ATTRIBUTES, false)
30
42
  const_get(:COLLECTION_SORTABLE_ATTRIBUTES)
@@ -43,4 +55,3 @@ module YummyGuide
43
55
  end
44
56
  end
45
57
  end
46
-
@@ -9,16 +9,19 @@ module YummyGuide
9
9
  ].freeze
10
10
 
11
11
  def yummy_guide_administrate_collection_table_fixed_columns_count(page:, collection_presenter:)
12
- return 0 unless page.respond_to?(:instance_variable_defined?) && page.instance_variable_defined?(:@dashboard)
13
-
14
- dashboard = page.instance_variable_get(:@dashboard)
15
- return 0 unless dashboard&.class&.respond_to?(:index_fixed_columns_count)
16
-
17
- fixed_columns_count = dashboard.class.index_fixed_columns_count.to_i
18
- fixed_columns_count = 0 if fixed_columns_count.negative?
12
+ yummy_guide_administrate_collection_fixed_columns_count_for(
13
+ page: page,
14
+ collection_presenter: collection_presenter,
15
+ method_name: :index_fixed_columns_count
16
+ )
17
+ end
19
18
 
20
- attribute_count = collection_presenter.attribute_types.size
21
- [fixed_columns_count, attribute_count].min
19
+ def yummy_guide_administrate_collection_table_mobile_fixed_columns_count(page:, collection_presenter:)
20
+ yummy_guide_administrate_collection_fixed_columns_count_for(
21
+ page: page,
22
+ collection_presenter: collection_presenter,
23
+ method_name: :index_mobile_fixed_columns_count
24
+ )
22
25
  rescue NoMethodError
23
26
  0
24
27
  end
@@ -87,6 +90,21 @@ module YummyGuide
87
90
 
88
91
  private
89
92
 
93
+ def yummy_guide_administrate_collection_fixed_columns_count_for(page:, collection_presenter:, method_name:)
94
+ return 0 unless page.respond_to?(:instance_variable_defined?) && page.instance_variable_defined?(:@dashboard)
95
+
96
+ dashboard = page.instance_variable_get(:@dashboard)
97
+ return 0 unless dashboard&.class&.respond_to?(method_name)
98
+
99
+ fixed_columns_count = dashboard.class.public_send(method_name).to_i
100
+ fixed_columns_count = 0 if fixed_columns_count.negative?
101
+
102
+ attribute_count = collection_presenter.attribute_types.size
103
+ [fixed_columns_count, attribute_count].min
104
+ rescue NoMethodError
105
+ 0
106
+ end
107
+
90
108
  def yummy_guide_administrate_collection_link(content, href:, target: nil, html_class: "action-show", aria: nil, data: nil)
91
109
  return content if href.blank?
92
110
 
@@ -17,7 +17,8 @@ module YummyGuide
17
17
  extra_actions: [],
18
18
  button_label: "Filter",
19
19
  title: "Filter Options",
20
- submit_label: "Filter"
20
+ submit_label: "Filter",
21
+ close_label: "Close"
21
22
  )
22
23
  dashboard ||= admin_filter_dashboard_from_page(page)
23
24
  scope = form.to_s
@@ -63,7 +64,8 @@ module YummyGuide
63
64
  locals: locals,
64
65
  extra_actions: extra_actions,
65
66
  title: title,
66
- submit_label: submit_label
67
+ submit_label: submit_label,
68
+ close_label: close_label
67
69
  )
68
70
  ])
69
71
  end
@@ -104,7 +106,7 @@ module YummyGuide
104
106
  .select { |field| field.visible?(self, locals) }
105
107
  end
106
108
 
107
- def admin_filter_form(fields:, scope:, path:, clear_path:, method:, current_values:, hidden_fields:, root_hidden_fields:, locals:, extra_actions:, title:, submit_label:)
109
+ def admin_filter_form(fields:, scope:, path:, clear_path:, method:, current_values:, hidden_fields:, root_hidden_fields:, locals:, extra_actions:, title:, submit_label:, close_label:)
108
110
  form_with(
109
111
  url: path,
110
112
  scope: scope,
@@ -119,7 +121,7 @@ module YummyGuide
119
121
  ) do |f|
120
122
  safe_join([
121
123
  admin_filter_hidden_fields(scope, hidden_fields, root_hidden_fields),
122
- content_tag(:h2, title, class: "filter-form__title"),
124
+ admin_filter_form_header(title: title, close_label: close_label),
123
125
  content_tag(:div, class: "filter-form__body") do
124
126
  content_tag(:table, class: "filter_table") do
125
127
  safe_join(fields.map { |field| field.row(self, f, scope, current_values, locals) })
@@ -136,6 +138,22 @@ module YummyGuide
136
138
  end
137
139
  end
138
140
 
141
+ def admin_filter_form_header(title:, close_label:)
142
+ content_tag(:div, class: "filter-form__header") do
143
+ safe_join([
144
+ content_tag(:h2, title, class: "filter-form__title"),
145
+ button_tag(
146
+ "x",
147
+ type: "button",
148
+ class: "filter-form__close",
149
+ data: { behavior: "filter-form-close" },
150
+ aria: { label: close_label },
151
+ title: close_label
152
+ )
153
+ ])
154
+ end
155
+ end
156
+
139
157
  def admin_filter_hidden_fields(scope, hidden_fields, root_hidden_fields)
140
158
  root_tags = admin_filter_evaluated_hash(root_hidden_fields).map do |key, value|
141
159
  hidden_field_tag(key, value)
@@ -2,6 +2,7 @@
2
2
  <table
3
3
  aria-labelledby="<%= table_title %>"
4
4
  data-fixed-columns-count="<%= yummy_guide_administrate_collection_table_fixed_columns_count(page: page, collection_presenter: collection_presenter) %>"
5
+ data-mobile-fixed-columns-count="<%= yummy_guide_administrate_collection_table_mobile_fixed_columns_count(page: page, collection_presenter: collection_presenter) %>"
5
6
  data-fixed-header-source
6
7
  >
7
8
  <thead>
@@ -2,6 +2,6 @@
2
2
 
3
3
  module YummyGuide
4
4
  module Administrate
5
- VERSION = "0.7.0"
5
+ VERSION = "0.7.1"
6
6
  end
7
7
  end
@@ -18,6 +18,30 @@ RSpec.describe YummyGuide::Administrate::ApplicationDashboard do
18
18
  end
19
19
  end
20
20
 
21
+ describe ".index_mobile_fixed_columns_count" do
22
+ it "uses the subclass mobile constant when defined" do
23
+ subclass = Class.new(described_class)
24
+ subclass.const_set(:INDEX_FIXED_COLUMNS_COUNT, 5)
25
+ subclass.const_set(:INDEX_MOBILE_FIXED_COLUMNS_COUNT, 2)
26
+
27
+ expect(subclass.index_mobile_fixed_columns_count).to eq(2)
28
+ end
29
+
30
+ it "caps a subclass desktop fixed column count to one by default" do
31
+ subclass = Class.new(described_class)
32
+ subclass.const_set(:INDEX_FIXED_COLUMNS_COUNT, 5)
33
+
34
+ expect(subclass.index_mobile_fixed_columns_count).to eq(1)
35
+ end
36
+
37
+ it "keeps zero fixed columns on mobile when desktop fixed columns are zero" do
38
+ subclass = Class.new(described_class)
39
+ subclass.const_set(:INDEX_FIXED_COLUMNS_COUNT, 0)
40
+
41
+ expect(subclass.index_mobile_fixed_columns_count).to eq(0)
42
+ end
43
+ end
44
+
21
45
  describe ".collection_attribute_sortable?" do
22
46
  it "uses collection attributes when explicit sortable attributes are absent" do
23
47
  subclass = Class.new(described_class)
@@ -37,6 +37,23 @@ RSpec.describe YummyGuide::Administrate::CollectionHelper do
37
37
  end
38
38
  end
39
39
 
40
+ describe "#yummy_guide_administrate_collection_table_mobile_fixed_columns_count" do
41
+ # dashboard のモバイル固定列数も表示列数を超えないことを確認する
42
+ it "caps the mobile fixed column count by the number of visible attributes" do
43
+ dashboard_class = Class.new do
44
+ def self.index_mobile_fixed_columns_count
45
+ 4
46
+ end
47
+ end
48
+
49
+ page = Object.new
50
+ page.instance_variable_set(:@dashboard, dashboard_class.new)
51
+ collection_presenter = Struct.new(:attribute_types).new({ id: :integer, name: :string })
52
+
53
+ expect(helper_host.yummy_guide_administrate_collection_table_mobile_fixed_columns_count(page: page, collection_presenter: collection_presenter)).to eq(2)
54
+ end
55
+ end
56
+
40
57
  describe "#yummy_guide_administrate_build_collection_cell" do
41
58
  let(:present_path) { "/admin/articles/test-article" }
42
59
 
@@ -42,8 +42,12 @@ RSpec.describe YummyGuide::Administrate::FilterControlsHelper do
42
42
  search_options: { keyword: "tokyo", status: "closed" }
43
43
  )
44
44
  document = fragment(html)
45
+ close_button = document.at_css('button.filter-form__close[data-behavior="filter-form-close"]')
45
46
 
46
47
  expect(document.at_css("#reserv-filter-options > a.button").text).to eq("Filter")
48
+ expect(document.at_css(".filter-form__header .filter-form__title").text).to eq("Filter Options")
49
+ expect(close_button["aria-label"]).to eq("Close")
50
+ expect(close_button["type"]).to eq("button")
47
51
  expect(document.at_css("form.filter-form")["action"]).to eq("/admin/resources")
48
52
  expect(document.at_css('input[name="search_options[keyword]"]')["value"]).to eq("tokyo")
49
53
  expect(document.at_css('select[name="search_options[status]"] option[selected]')["value"]).to eq("closed")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yummy-guide-generic-administrate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - akatsuki-kk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-29 00:00:00.000000000 Z
11
+ date: 2026-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: administrate