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 +4 -4
- data/app/assets/javascripts/yummy_guide_administrate/sticky_left_columns.js +12 -1
- data/app/assets/javascripts/yummy_guide_administrate/sticky_table_headers.js +13 -1
- data/app/assets/stylesheets/yummy_guide_administrate/components.scss +21 -0
- data/app/dashboards/yummy_guide/administrate/application_dashboard.rb +12 -1
- data/app/helpers/yummy_guide/administrate/collection_helper.rb +27 -9
- data/app/helpers/yummy_guide/administrate/filter_controls_helper.rb +22 -4
- data/app/views/yummy_guide/administrate/administrate/application/_collection.html.erb +1 -0
- data/lib/yummy_guide/administrate/version.rb +1 -1
- data/spec/yummy_guide/administrate/application_dashboard_spec.rb +24 -0
- data/spec/yummy_guide/administrate/collection_helper_spec.rb +17 -0
- data/spec/yummy_guide/administrate/filter_controls_helper_spec.rb +4 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a0a5f41bc5f403a7d4da80d9a2b66c7313a9370374e171d2916b96de8aea2a8d
|
|
4
|
+
data.tar.gz: 77c5494b19b7c2364477e394c954e5640ac737658e05ec481ecef62aafc30c59
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
21
|
-
|
|
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
|
-
|
|
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>
|
|
@@ -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.
|
|
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-
|
|
11
|
+
date: 2026-06-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: administrate
|