yummy-guide-generic-administrate 0.8.4 → 0.8.5
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/column_resizer.js +66 -0
- data/app/assets/stylesheets/yummy_guide_administrate/components.scss +270 -0
- data/app/dashboards/yummy_guide/administrate/application_dashboard.rb +11 -0
- data/app/helpers/yummy_guide/administrate/collection_helper.rb +128 -0
- data/app/views/yummy_guide/administrate/administrate/application/_collection.html.erb +22 -4
- data/lib/yummy_guide/administrate/engine.rb +0 -2
- data/lib/yummy_guide/administrate/version.rb +1 -1
- data/spec/yummy_guide/administrate/application_dashboard_spec.rb +17 -0
- data/spec/yummy_guide/administrate/collection_helper_spec.rb +132 -0
- data/spec/yummy_guide/administrate/column_resizer_asset_spec.rb +40 -66
- 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: 3940f84fd25e7fe60419f17273656e50af22465caf4bbfa29e1ac209d03b5bd4
|
|
4
|
+
data.tar.gz: 3bc3455f747754d483ee5329c5d4991289eaac0630961a808558f551e7f9c819
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b9843e5fdc03dd2e08330368cb267ac888fa1d5327bad40550b44a0960881d6d4cd87b77a0e2cad10f70d3d04f503d88b39192f20f82e4e3adc04910e5af3a7e
|
|
7
|
+
data.tar.gz: ba1be8f0226de1a9bd37650827529ea7b5c59d2d680f4d31066f86246fcb3085a87b9a5c1b6c91ccce5d7ffd0360e98d5f2bc281a07426f07987edef714a1503
|
|
@@ -71,6 +71,11 @@
|
|
|
71
71
|
return preciseNumber(value) + 'px';
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
function parsedPixelValue(value) {
|
|
75
|
+
var parsedValue = parseFloat(value || '0');
|
|
76
|
+
return Number.isNaN(parsedValue) ? 0 : preciseNumber(parsedValue);
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
function measuredWidth(element) {
|
|
75
80
|
if (!element) return 0;
|
|
76
81
|
|
|
@@ -307,6 +312,7 @@
|
|
|
307
312
|
indexByColumnId: indexByColumnId
|
|
308
313
|
};
|
|
309
314
|
tableStates.set(table, state);
|
|
315
|
+
refreshCssStickyLeftColumns(table);
|
|
310
316
|
|
|
311
317
|
return state;
|
|
312
318
|
}
|
|
@@ -375,6 +381,7 @@
|
|
|
375
381
|
table.style.setProperty(columnWidthVariable(index), widthValue);
|
|
376
382
|
setAdjustedColumn(table, index, true);
|
|
377
383
|
applyColgroupWidth(table, state.columnCount, index, widthValue);
|
|
384
|
+
refreshCssStickyLeftColumns(table);
|
|
378
385
|
}
|
|
379
386
|
|
|
380
387
|
function clearTableColumnWidth(table, columnId) {
|
|
@@ -385,6 +392,65 @@
|
|
|
385
392
|
table.style.removeProperty(columnWidthVariable(index));
|
|
386
393
|
setAdjustedColumn(table, index, false);
|
|
387
394
|
clearColgroupWidth(table, state.columnCount, index);
|
|
395
|
+
refreshCssStickyLeftColumns(table);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function stickyColumnIndexes(table, className) {
|
|
399
|
+
var row = table && table.querySelector('thead tr');
|
|
400
|
+
if (!row) return [];
|
|
401
|
+
|
|
402
|
+
return directCells(row).map(function(cell, index) {
|
|
403
|
+
return cell.classList && cell.classList.contains(className) ? index : null;
|
|
404
|
+
}).filter(function(index) {
|
|
405
|
+
return index !== null;
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function managedColumnWidth(table, index) {
|
|
410
|
+
var colgroup = table && table.querySelector('colgroup[data-admin-column-resizer-colgroup], colgroup[data-fixed-header-colgroup]');
|
|
411
|
+
var col = colgroup && colgroup.children[index];
|
|
412
|
+
|
|
413
|
+
return col ? parsedPixelValue(col.style.width) : 0;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function stickyColumnWidth(table, header, index, widthVariable) {
|
|
417
|
+
return measuredWidth(header) ||
|
|
418
|
+
managedColumnWidth(table, index) ||
|
|
419
|
+
parsedPixelValue(header && header.style && header.style.getPropertyValue(widthVariable));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function applyStickyColumnPosition(table, index, leftVariable, left, widthVariable, width) {
|
|
423
|
+
Array.from(table.querySelectorAll('thead tr, tbody tr, tfoot tr')).forEach(function(row) {
|
|
424
|
+
var cell = directCells(row)[index];
|
|
425
|
+
if (!cell) return;
|
|
426
|
+
|
|
427
|
+
cell.style.setProperty(leftVariable, cssPixelValue(left));
|
|
428
|
+
if (width) {
|
|
429
|
+
cell.style.setProperty(widthVariable, cssPixelValue(width));
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function refreshCssStickyLeftColumnSet(table, className, leftVariable, widthVariable) {
|
|
435
|
+
var headerRow = table && table.querySelector('thead tr');
|
|
436
|
+
if (!headerRow) return;
|
|
437
|
+
|
|
438
|
+
var headerCells = directCells(headerRow);
|
|
439
|
+
var left = 0;
|
|
440
|
+
|
|
441
|
+
stickyColumnIndexes(table, className).forEach(function(index) {
|
|
442
|
+
var width = stickyColumnWidth(table, headerCells[index], index, widthVariable);
|
|
443
|
+
|
|
444
|
+
applyStickyColumnPosition(table, index, leftVariable, left, widthVariable, width);
|
|
445
|
+
left += width;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function refreshCssStickyLeftColumns(table) {
|
|
450
|
+
if (!table || table.getAttribute('aria-hidden') === 'true' || table.classList.contains(FIXED_HEADER_TABLE_CLASS)) return;
|
|
451
|
+
|
|
452
|
+
refreshCssStickyLeftColumnSet(table, 'sticky-left', '--sticky-left', '--sticky-width');
|
|
453
|
+
refreshCssStickyLeftColumnSet(table, 'sticky-left-mobile', '--sticky-mobile-left', '--sticky-mobile-width');
|
|
388
454
|
}
|
|
389
455
|
|
|
390
456
|
function applyColumnWidth(columnId, width, key) {
|
|
@@ -88,6 +88,121 @@
|
|
|
88
88
|
overflow-x: auto;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
.scroll-table[data-css-sticky-table],
|
|
92
|
+
.home-table__wrapper[data-css-sticky-table] {
|
|
93
|
+
max-width: 100%;
|
|
94
|
+
max-height: var(--admin-sticky-table-max-height, calc(100dvh - 10rem));
|
|
95
|
+
overflow: auto;
|
|
96
|
+
-webkit-overflow-scrolling: touch;
|
|
97
|
+
overscroll-behavior: contain;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.scroll-table[data-css-sticky-table] table[data-fixed-columns-count],
|
|
101
|
+
.home-table__wrapper[data-css-sticky-table] table[data-fixed-columns-count] {
|
|
102
|
+
width: max-content;
|
|
103
|
+
min-width: 100%;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.scroll-table table[data-fixed-columns-count],
|
|
107
|
+
.sticky-table-scroll table[data-fixed-columns-count],
|
|
108
|
+
.home-table__wrapper table[data-fixed-columns-count],
|
|
109
|
+
.table-wrap table[data-fixed-columns-count],
|
|
110
|
+
.af__table__content table[data-fixed-columns-count] {
|
|
111
|
+
--sticky-col-1-width: var(--admin-sticky-col-1-width, 4rem);
|
|
112
|
+
--sticky-col-2-width: var(--admin-sticky-col-2-width, 8rem);
|
|
113
|
+
--sticky-col-3-width: var(--admin-sticky-col-3-width, 8rem);
|
|
114
|
+
--sticky-col-4-width: var(--admin-sticky-col-4-width, 8rem);
|
|
115
|
+
--sticky-col-5-width: var(--admin-sticky-col-5-width, 8rem);
|
|
116
|
+
--sticky-col-6-width: var(--admin-sticky-col-6-width, 8rem);
|
|
117
|
+
--sticky-col-1-left: 0px;
|
|
118
|
+
--sticky-col-2-left: var(--sticky-col-1-width);
|
|
119
|
+
--sticky-col-3-left: calc(var(--sticky-col-1-width) + var(--sticky-col-2-width));
|
|
120
|
+
--sticky-col-4-left: calc(var(--sticky-col-1-width) + var(--sticky-col-2-width) + var(--sticky-col-3-width));
|
|
121
|
+
--sticky-col-5-left: calc(var(--sticky-col-1-width) + var(--sticky-col-2-width) + var(--sticky-col-3-width) + var(--sticky-col-4-width));
|
|
122
|
+
--sticky-col-6-left: calc(var(--sticky-col-1-width) + var(--sticky-col-2-width) + var(--sticky-col-3-width) + var(--sticky-col-4-width) + var(--sticky-col-5-width));
|
|
123
|
+
--sticky-mobile-col-1-width: var(--admin-sticky-mobile-col-1-width, var(--sticky-col-1-width));
|
|
124
|
+
--sticky-mobile-col-2-width: var(--admin-sticky-mobile-col-2-width, var(--sticky-col-2-width));
|
|
125
|
+
--sticky-mobile-col-3-width: var(--admin-sticky-mobile-col-3-width, var(--sticky-col-3-width));
|
|
126
|
+
--sticky-mobile-col-4-width: var(--admin-sticky-mobile-col-4-width, var(--sticky-col-4-width));
|
|
127
|
+
--sticky-mobile-col-5-width: var(--admin-sticky-mobile-col-5-width, var(--sticky-col-5-width));
|
|
128
|
+
--sticky-mobile-col-6-width: var(--admin-sticky-mobile-col-6-width, var(--sticky-col-6-width));
|
|
129
|
+
--sticky-mobile-col-1-left: 0px;
|
|
130
|
+
--sticky-mobile-col-2-left: var(--sticky-mobile-col-1-width);
|
|
131
|
+
--sticky-mobile-col-3-left: calc(var(--sticky-mobile-col-1-width) + var(--sticky-mobile-col-2-width));
|
|
132
|
+
--sticky-mobile-col-4-left: calc(var(--sticky-mobile-col-1-width) + var(--sticky-mobile-col-2-width) + var(--sticky-mobile-col-3-width));
|
|
133
|
+
--sticky-mobile-col-5-left: calc(var(--sticky-mobile-col-1-width) + var(--sticky-mobile-col-2-width) + var(--sticky-mobile-col-3-width) + var(--sticky-mobile-col-4-width));
|
|
134
|
+
--sticky-mobile-col-6-left: calc(var(--sticky-mobile-col-1-width) + var(--sticky-mobile-col-2-width) + var(--sticky-mobile-col-3-width) + var(--sticky-mobile-col-4-width) + var(--sticky-mobile-col-5-width));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@for $count from 1 through 6 {
|
|
138
|
+
@for $index from 1 through $count {
|
|
139
|
+
.scroll-table table[data-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}):not(.sticky-left),
|
|
140
|
+
.sticky-table-scroll table[data-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}):not(.sticky-left),
|
|
141
|
+
.home-table__wrapper table[data-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}):not(.sticky-left),
|
|
142
|
+
.table-wrap table[data-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}):not(.sticky-left),
|
|
143
|
+
.af__table__content table[data-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}):not(.sticky-left) {
|
|
144
|
+
position: sticky;
|
|
145
|
+
left: var(--sticky-col-#{$index}-left);
|
|
146
|
+
box-sizing: border-box;
|
|
147
|
+
width: var(--sticky-col-#{$index}-width);
|
|
148
|
+
min-width: var(--sticky-col-#{$index}-width);
|
|
149
|
+
max-width: var(--sticky-col-#{$index}-width);
|
|
150
|
+
background-clip: padding-box;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.scroll-table table[data-fixed-columns-count="#{$count}"] th:nth-child(#{$index}),
|
|
154
|
+
.sticky-table-scroll table[data-fixed-columns-count="#{$count}"] th:nth-child(#{$index}),
|
|
155
|
+
.home-table__wrapper table[data-fixed-columns-count="#{$count}"] th:nth-child(#{$index}),
|
|
156
|
+
.table-wrap table[data-fixed-columns-count="#{$count}"] th:nth-child(#{$index}),
|
|
157
|
+
.af__table__content table[data-fixed-columns-count="#{$count}"] th:nth-child(#{$index}) {
|
|
158
|
+
z-index: 4;
|
|
159
|
+
background-color: #121012;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.scroll-table table[data-fixed-columns-count="#{$count}"] td:nth-child(#{$index}),
|
|
163
|
+
.sticky-table-scroll table[data-fixed-columns-count="#{$count}"] td:nth-child(#{$index}),
|
|
164
|
+
.home-table__wrapper table[data-fixed-columns-count="#{$count}"] td:nth-child(#{$index}),
|
|
165
|
+
.table-wrap table[data-fixed-columns-count="#{$count}"] td:nth-child(#{$index}),
|
|
166
|
+
.af__table__content table[data-fixed-columns-count="#{$count}"] td:nth-child(#{$index}) {
|
|
167
|
+
z-index: 3;
|
|
168
|
+
background-color: var(--sticky-cell-background, #fff);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.scroll-table table[data-fixed-columns-count] th,
|
|
174
|
+
.sticky-table-scroll table[data-fixed-columns-count] th,
|
|
175
|
+
.home-table__wrapper table[data-fixed-columns-count] th,
|
|
176
|
+
.table-wrap table[data-fixed-columns-count] th,
|
|
177
|
+
.af__table__content table[data-fixed-columns-count] th {
|
|
178
|
+
position: sticky;
|
|
179
|
+
top: 0;
|
|
180
|
+
z-index: 2;
|
|
181
|
+
background-clip: padding-box;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.scroll-table[data-css-sticky-table] table > thead th,
|
|
185
|
+
.sticky-table-scroll[data-css-sticky-table] table > thead th,
|
|
186
|
+
.home-table__wrapper[data-css-sticky-table] table > thead th,
|
|
187
|
+
.table-wrap[data-css-sticky-table] table > thead th,
|
|
188
|
+
.af__table__content[data-css-sticky-table] table > thead th {
|
|
189
|
+
background-color: #121012;
|
|
190
|
+
color: #fff;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.scroll-table[data-css-sticky-table] table > thead th a,
|
|
194
|
+
.scroll-table[data-css-sticky-table] table > thead th button,
|
|
195
|
+
.sticky-table-scroll[data-css-sticky-table] table > thead th a,
|
|
196
|
+
.sticky-table-scroll[data-css-sticky-table] table > thead th button,
|
|
197
|
+
.home-table__wrapper[data-css-sticky-table] table > thead th a,
|
|
198
|
+
.home-table__wrapper[data-css-sticky-table] table > thead th button,
|
|
199
|
+
.table-wrap[data-css-sticky-table] table > thead th a,
|
|
200
|
+
.table-wrap[data-css-sticky-table] table > thead th button,
|
|
201
|
+
.af__table__content[data-css-sticky-table] table > thead th a,
|
|
202
|
+
.af__table__content[data-css-sticky-table] table > thead th button {
|
|
203
|
+
color: inherit;
|
|
204
|
+
}
|
|
205
|
+
|
|
91
206
|
.table-fixed-header-slot {
|
|
92
207
|
overflow-y: hidden;
|
|
93
208
|
}
|
|
@@ -265,6 +380,11 @@ td.cell-data:hover .admin-copy-cell__button:not([disabled]),
|
|
|
265
380
|
.home-table th.sticky-left,
|
|
266
381
|
.home-table td.sticky-left {
|
|
267
382
|
position: sticky;
|
|
383
|
+
left: var(--sticky-left, 0);
|
|
384
|
+
box-sizing: border-box;
|
|
385
|
+
width: var(--sticky-width, auto);
|
|
386
|
+
min-width: var(--sticky-width, auto);
|
|
387
|
+
max-width: var(--sticky-width, none);
|
|
268
388
|
background-clip: padding-box;
|
|
269
389
|
}
|
|
270
390
|
|
|
@@ -307,6 +427,139 @@ td.cell-data:hover .admin-copy-cell__button:not([disabled]),
|
|
|
307
427
|
box-shadow: 6px 0 8px -8px rgba(0, 0, 0, 0.35);
|
|
308
428
|
}
|
|
309
429
|
|
|
430
|
+
@media (max-width: 767px) {
|
|
431
|
+
@for $count from 1 through 6 {
|
|
432
|
+
@for $index from 1 through $count {
|
|
433
|
+
.scroll-table table[data-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}),
|
|
434
|
+
.sticky-table-scroll table[data-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}),
|
|
435
|
+
.home-table__wrapper table[data-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}),
|
|
436
|
+
.table-wrap table[data-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}),
|
|
437
|
+
.af__table__content table[data-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}) {
|
|
438
|
+
position: static;
|
|
439
|
+
left: auto;
|
|
440
|
+
width: auto;
|
|
441
|
+
min-width: 0;
|
|
442
|
+
max-width: none;
|
|
443
|
+
box-shadow: none;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
@for $count from 1 through 6 {
|
|
449
|
+
@for $index from 1 through $count {
|
|
450
|
+
.scroll-table table[data-mobile-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}):not(.sticky-left-mobile),
|
|
451
|
+
.sticky-table-scroll table[data-mobile-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}):not(.sticky-left-mobile),
|
|
452
|
+
.home-table__wrapper table[data-mobile-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}):not(.sticky-left-mobile),
|
|
453
|
+
.table-wrap table[data-mobile-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}):not(.sticky-left-mobile),
|
|
454
|
+
.af__table__content table[data-mobile-fixed-columns-count="#{$count}"] tr > :nth-child(#{$index}):not(.sticky-left-mobile) {
|
|
455
|
+
position: sticky;
|
|
456
|
+
left: var(--sticky-mobile-col-#{$index}-left);
|
|
457
|
+
box-sizing: border-box;
|
|
458
|
+
width: var(--sticky-mobile-col-#{$index}-width);
|
|
459
|
+
min-width: var(--sticky-mobile-col-#{$index}-width);
|
|
460
|
+
max-width: var(--sticky-mobile-col-#{$index}-width);
|
|
461
|
+
background-clip: padding-box;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.scroll-table table[data-mobile-fixed-columns-count="#{$count}"] th:nth-child(#{$index}),
|
|
465
|
+
.sticky-table-scroll table[data-mobile-fixed-columns-count="#{$count}"] th:nth-child(#{$index}),
|
|
466
|
+
.home-table__wrapper table[data-mobile-fixed-columns-count="#{$count}"] th:nth-child(#{$index}),
|
|
467
|
+
.table-wrap table[data-mobile-fixed-columns-count="#{$count}"] th:nth-child(#{$index}),
|
|
468
|
+
.af__table__content table[data-mobile-fixed-columns-count="#{$count}"] th:nth-child(#{$index}) {
|
|
469
|
+
z-index: 4;
|
|
470
|
+
background-color: #121012;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.scroll-table table[data-mobile-fixed-columns-count="#{$count}"] td:nth-child(#{$index}),
|
|
474
|
+
.sticky-table-scroll table[data-mobile-fixed-columns-count="#{$count}"] td:nth-child(#{$index}),
|
|
475
|
+
.home-table__wrapper table[data-mobile-fixed-columns-count="#{$count}"] td:nth-child(#{$index}),
|
|
476
|
+
.table-wrap table[data-mobile-fixed-columns-count="#{$count}"] td:nth-child(#{$index}),
|
|
477
|
+
.af__table__content table[data-mobile-fixed-columns-count="#{$count}"] td:nth-child(#{$index}) {
|
|
478
|
+
z-index: 3;
|
|
479
|
+
background-color: var(--sticky-cell-background, #fff);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.scroll-table table th.sticky-left,
|
|
485
|
+
.scroll-table table td.sticky-left,
|
|
486
|
+
.sticky-table-scroll table th.sticky-left,
|
|
487
|
+
.sticky-table-scroll table td.sticky-left,
|
|
488
|
+
.home-table th.sticky-left,
|
|
489
|
+
.home-table td.sticky-left {
|
|
490
|
+
position: static;
|
|
491
|
+
left: auto;
|
|
492
|
+
width: auto;
|
|
493
|
+
min-width: 0;
|
|
494
|
+
max-width: none;
|
|
495
|
+
box-shadow: none;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.scroll-table table th.sticky-left::after,
|
|
499
|
+
.scroll-table table td.sticky-left::after,
|
|
500
|
+
.sticky-table-scroll table th.sticky-left::after,
|
|
501
|
+
.sticky-table-scroll table td.sticky-left::after,
|
|
502
|
+
.home-table th.sticky-left::after,
|
|
503
|
+
.home-table td.sticky-left::after {
|
|
504
|
+
content: none;
|
|
505
|
+
display: none;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
.scroll-table table th.sticky-left-mobile,
|
|
509
|
+
.scroll-table table td.sticky-left-mobile,
|
|
510
|
+
.sticky-table-scroll table th.sticky-left-mobile,
|
|
511
|
+
.sticky-table-scroll table td.sticky-left-mobile,
|
|
512
|
+
.home-table th.sticky-left-mobile,
|
|
513
|
+
.home-table td.sticky-left-mobile {
|
|
514
|
+
position: sticky;
|
|
515
|
+
left: var(--sticky-mobile-left, 0);
|
|
516
|
+
box-sizing: border-box;
|
|
517
|
+
width: var(--sticky-mobile-width, auto);
|
|
518
|
+
min-width: var(--sticky-mobile-width, auto);
|
|
519
|
+
max-width: var(--sticky-mobile-width, none);
|
|
520
|
+
background-clip: padding-box;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.scroll-table table th.sticky-left-mobile,
|
|
524
|
+
.sticky-table-scroll table th.sticky-left-mobile,
|
|
525
|
+
.home-table th.sticky-left-mobile {
|
|
526
|
+
z-index: 4;
|
|
527
|
+
background-color: #121012;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
.scroll-table table td.sticky-left-mobile,
|
|
531
|
+
.sticky-table-scroll table td.sticky-left-mobile,
|
|
532
|
+
.home-table td.sticky-left-mobile {
|
|
533
|
+
z-index: 3;
|
|
534
|
+
background-color: var(--sticky-cell-background, #fff);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
.scroll-table table th.sticky-left-mobile::after,
|
|
538
|
+
.scroll-table table td.sticky-left-mobile::after,
|
|
539
|
+
.sticky-table-scroll table th.sticky-left-mobile::after,
|
|
540
|
+
.sticky-table-scroll table td.sticky-left-mobile::after,
|
|
541
|
+
.home-table th.sticky-left-mobile::after,
|
|
542
|
+
.home-table td.sticky-left-mobile::after {
|
|
543
|
+
content: "";
|
|
544
|
+
position: absolute;
|
|
545
|
+
top: -1px;
|
|
546
|
+
right: -1px;
|
|
547
|
+
bottom: -1px;
|
|
548
|
+
width: 1px;
|
|
549
|
+
background-color: #fff;
|
|
550
|
+
pointer-events: none;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
.scroll-table table th.sticky-left-mobile--last,
|
|
554
|
+
.scroll-table table td.sticky-left-mobile--last,
|
|
555
|
+
.sticky-table-scroll table th.sticky-left-mobile--last,
|
|
556
|
+
.sticky-table-scroll table td.sticky-left-mobile--last,
|
|
557
|
+
.home-table th.sticky-left-mobile--last,
|
|
558
|
+
.home-table td.sticky-left-mobile--last {
|
|
559
|
+
box-shadow: 6px 0 8px -8px rgba(0, 0, 0, 0.35);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
310
563
|
.scroll-table table th.sticky,
|
|
311
564
|
.scroll-table table td.sticky,
|
|
312
565
|
.sticky-table-scroll table th.sticky,
|
|
@@ -342,6 +595,23 @@ td.cell-data:hover .admin-copy-cell__button:not([disabled]),
|
|
|
342
595
|
z-index: 5;
|
|
343
596
|
}
|
|
344
597
|
|
|
598
|
+
.scroll-table[data-css-sticky-table] table th.sticky.actions-column,
|
|
599
|
+
.home-table__wrapper[data-css-sticky-table] table th.sticky.actions-column {
|
|
600
|
+
position: sticky;
|
|
601
|
+
top: 0;
|
|
602
|
+
right: 0;
|
|
603
|
+
z-index: 6;
|
|
604
|
+
background-color: #121012;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
.scroll-table[data-css-sticky-table] table td.sticky.actions-column,
|
|
608
|
+
.home-table__wrapper[data-css-sticky-table] table td.sticky.actions-column {
|
|
609
|
+
position: sticky;
|
|
610
|
+
right: 0;
|
|
611
|
+
z-index: 4;
|
|
612
|
+
background-color: var(--sticky-cell-background, #fff);
|
|
613
|
+
}
|
|
614
|
+
|
|
345
615
|
.scroll-table table td.sticky,
|
|
346
616
|
.sticky-table-scroll table td.sticky,
|
|
347
617
|
.home-table td.sticky {
|
|
@@ -6,6 +6,7 @@ module YummyGuide
|
|
|
6
6
|
module Administrate
|
|
7
7
|
class ApplicationDashboard < ::Administrate::BaseDashboard
|
|
8
8
|
INDEX_FIXED_COLUMNS_COUNT = 1
|
|
9
|
+
INDEX_FIXED_COLUMN_WIDTHS = {}.freeze
|
|
9
10
|
|
|
10
11
|
def default_sorting_attribute
|
|
11
12
|
:created_at
|
|
@@ -37,6 +38,16 @@ module YummyGuide
|
|
|
37
38
|
end
|
|
38
39
|
end
|
|
39
40
|
|
|
41
|
+
def self.index_fixed_column_widths
|
|
42
|
+
if const_defined?(:INDEX_FIXED_COLUMN_WIDTHS, false)
|
|
43
|
+
const_get(:INDEX_FIXED_COLUMN_WIDTHS)
|
|
44
|
+
elsif superclass.respond_to?(:index_fixed_column_widths)
|
|
45
|
+
superclass.index_fixed_column_widths
|
|
46
|
+
else
|
|
47
|
+
{}
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
40
51
|
def self.collection_sortable_attributes
|
|
41
52
|
if const_defined?(:COLLECTION_SORTABLE_ATTRIBUTES, false)
|
|
42
53
|
const_get(:COLLECTION_SORTABLE_ATTRIBUTES)
|
|
@@ -7,6 +7,15 @@ module YummyGuide
|
|
|
7
7
|
address article aside blockquote div dl dt dd fieldset figcaption figure footer
|
|
8
8
|
form h1 h2 h3 h4 h5 h6 header hr li main nav ol p pre section table tr ul
|
|
9
9
|
].freeze
|
|
10
|
+
DEFAULT_FIXED_COLUMN_WIDTHS = {
|
|
11
|
+
id: "4rem",
|
|
12
|
+
month: "6rem",
|
|
13
|
+
assign_group_id: "6rem",
|
|
14
|
+
reservation_type: "7rem",
|
|
15
|
+
short_access_id: "8rem",
|
|
16
|
+
customer: "12rem"
|
|
17
|
+
}.freeze
|
|
18
|
+
DEFAULT_FIXED_COLUMN_WIDTH = "8rem"
|
|
10
19
|
|
|
11
20
|
def yummy_guide_administrate_collection_table_fixed_columns_count(page:, collection_presenter:)
|
|
12
21
|
yummy_guide_administrate_collection_fixed_columns_count_for(
|
|
@@ -26,6 +35,83 @@ module YummyGuide
|
|
|
26
35
|
0
|
|
27
36
|
end
|
|
28
37
|
|
|
38
|
+
def yummy_guide_administrate_collection_table_fixed_columns_count_for_names(page:, column_names:)
|
|
39
|
+
yummy_guide_administrate_collection_fixed_columns_count_for_names(
|
|
40
|
+
page: page,
|
|
41
|
+
column_names: column_names.map(&:to_sym),
|
|
42
|
+
method_name: :index_fixed_columns_count
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def yummy_guide_administrate_collection_table_mobile_fixed_columns_count_for_names(page:, column_names:)
|
|
47
|
+
yummy_guide_administrate_collection_fixed_columns_count_for_names(
|
|
48
|
+
page: page,
|
|
49
|
+
column_names: column_names.map(&:to_sym),
|
|
50
|
+
method_name: :index_mobile_fixed_columns_count
|
|
51
|
+
)
|
|
52
|
+
rescue NoMethodError
|
|
53
|
+
0
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def yummy_guide_administrate_collection_sticky_columns(page:, collection_presenter:, column_names:)
|
|
57
|
+
names = column_names.map(&:to_sym)
|
|
58
|
+
fixed_count = yummy_guide_administrate_collection_fixed_columns_count_for_names(
|
|
59
|
+
page: page,
|
|
60
|
+
column_names: names,
|
|
61
|
+
method_name: :index_fixed_columns_count
|
|
62
|
+
)
|
|
63
|
+
mobile_fixed_count = yummy_guide_administrate_collection_fixed_columns_count_for_names(
|
|
64
|
+
page: page,
|
|
65
|
+
column_names: names,
|
|
66
|
+
method_name: :index_mobile_fixed_columns_count
|
|
67
|
+
)
|
|
68
|
+
max_count = [fixed_count, mobile_fixed_count].max
|
|
69
|
+
return {} if max_count.zero?
|
|
70
|
+
|
|
71
|
+
widths = yummy_guide_administrate_collection_fixed_column_widths(page: page)
|
|
72
|
+
desktop_lefts = yummy_guide_administrate_collection_sticky_lefts(names.first(fixed_count), widths)
|
|
73
|
+
mobile_lefts = yummy_guide_administrate_collection_sticky_lefts(names.first(mobile_fixed_count), widths)
|
|
74
|
+
|
|
75
|
+
names.first(max_count).each_with_index.each_with_object({}) do |(name, index), sticky_columns|
|
|
76
|
+
classes = []
|
|
77
|
+
styles = []
|
|
78
|
+
width = widths.fetch(name, DEFAULT_FIXED_COLUMN_WIDTH)
|
|
79
|
+
|
|
80
|
+
if index < fixed_count
|
|
81
|
+
classes << "sticky-left"
|
|
82
|
+
classes << "sticky-left--last" if index == fixed_count - 1
|
|
83
|
+
styles << "--sticky-left: #{desktop_lefts.fetch(name)}"
|
|
84
|
+
styles << "--sticky-width: #{width}"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
if index < mobile_fixed_count
|
|
88
|
+
classes << "sticky-left-mobile"
|
|
89
|
+
classes << "sticky-left-mobile--last" if index == mobile_fixed_count - 1
|
|
90
|
+
styles << "--sticky-mobile-left: #{mobile_lefts.fetch(name)}"
|
|
91
|
+
styles << "--sticky-mobile-width: #{width}"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
sticky_columns[name] = {
|
|
95
|
+
class: classes.join(" "),
|
|
96
|
+
style: styles.join("; ")
|
|
97
|
+
}
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def yummy_guide_administrate_collection_sticky_table_style(page:, column_names:)
|
|
102
|
+
widths = yummy_guide_administrate_collection_fixed_column_widths(page: page)
|
|
103
|
+
|
|
104
|
+
column_names.map(&:to_sym).first(6).each_with_index.flat_map do |name, index|
|
|
105
|
+
width = widths.fetch(name, DEFAULT_FIXED_COLUMN_WIDTH)
|
|
106
|
+
column_number = index + 1
|
|
107
|
+
|
|
108
|
+
[
|
|
109
|
+
"--admin-sticky-col-#{column_number}-width: #{width}",
|
|
110
|
+
"--admin-sticky-mobile-col-#{column_number}-width: #{width}"
|
|
111
|
+
]
|
|
112
|
+
end.join("; ")
|
|
113
|
+
end
|
|
114
|
+
|
|
29
115
|
def yummy_guide_administrate_collection_column_id(collection_presenter, column_name)
|
|
30
116
|
[
|
|
31
117
|
collection_presenter.resource_name,
|
|
@@ -116,6 +202,48 @@ module YummyGuide
|
|
|
116
202
|
0
|
|
117
203
|
end
|
|
118
204
|
|
|
205
|
+
def yummy_guide_administrate_collection_fixed_columns_count_for_names(page:, column_names:, method_name:)
|
|
206
|
+
return 0 unless page.respond_to?(:instance_variable_defined?) && page.instance_variable_defined?(:@dashboard)
|
|
207
|
+
|
|
208
|
+
dashboard = page.instance_variable_get(:@dashboard)
|
|
209
|
+
return 0 unless dashboard&.class&.respond_to?(method_name)
|
|
210
|
+
|
|
211
|
+
fixed_columns_count = dashboard.class.public_send(method_name).to_i
|
|
212
|
+
fixed_columns_count = 0 if fixed_columns_count.negative?
|
|
213
|
+
|
|
214
|
+
[fixed_columns_count, column_names.size].min
|
|
215
|
+
rescue NoMethodError
|
|
216
|
+
0
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def yummy_guide_administrate_collection_fixed_column_widths(page:)
|
|
220
|
+
configured_widths =
|
|
221
|
+
if page.respond_to?(:instance_variable_defined?) && page.instance_variable_defined?(:@dashboard)
|
|
222
|
+
dashboard = page.instance_variable_get(:@dashboard)
|
|
223
|
+
dashboard.class.index_fixed_column_widths if dashboard&.class&.respond_to?(:index_fixed_column_widths)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
DEFAULT_FIXED_COLUMN_WIDTHS.merge(
|
|
227
|
+
(configured_widths || {}).to_h.transform_keys(&:to_sym).transform_values(&:to_s)
|
|
228
|
+
)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def yummy_guide_administrate_collection_sticky_lefts(column_names, widths)
|
|
232
|
+
current_parts = []
|
|
233
|
+
|
|
234
|
+
column_names.each_with_object({}) do |name, lefts|
|
|
235
|
+
lefts[name] = yummy_guide_administrate_collection_css_sum(current_parts)
|
|
236
|
+
current_parts << widths.fetch(name, DEFAULT_FIXED_COLUMN_WIDTH)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def yummy_guide_administrate_collection_css_sum(parts)
|
|
241
|
+
return "0px" if parts.empty?
|
|
242
|
+
return parts.first if parts.one?
|
|
243
|
+
|
|
244
|
+
"calc(#{parts.join(" + ")})"
|
|
245
|
+
end
|
|
246
|
+
|
|
119
247
|
def yummy_guide_administrate_collection_link(content, href:, target: nil, html_class: "action-show", aria: nil, data: nil)
|
|
120
248
|
return content if href.blank?
|
|
121
249
|
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
<% column_width_storage_scope = local_assigns[:column_width_storage_scope].presence %>
|
|
2
|
-
|
|
2
|
+
<% sticky_columns = yummy_guide_administrate_collection_sticky_columns(
|
|
3
|
+
page: page,
|
|
4
|
+
collection_presenter: collection_presenter,
|
|
5
|
+
column_names: collection_presenter.attribute_types.keys
|
|
6
|
+
) %>
|
|
7
|
+
<% sticky_table_style = yummy_guide_administrate_collection_sticky_table_style(
|
|
8
|
+
page: page,
|
|
9
|
+
column_names: collection_presenter.attribute_types.keys
|
|
10
|
+
) %>
|
|
11
|
+
<div class="scroll-table" data-css-sticky-table>
|
|
3
12
|
<table
|
|
4
13
|
aria-labelledby="<%= table_title %>"
|
|
5
14
|
data-fixed-columns-count="<%= yummy_guide_administrate_collection_table_fixed_columns_count(page: page, collection_presenter: collection_presenter) %>"
|
|
@@ -7,13 +16,17 @@
|
|
|
7
16
|
<% if column_width_storage_scope %>
|
|
8
17
|
data-column-resizer-storage-scope="<%= column_width_storage_scope %>"
|
|
9
18
|
<% end %>
|
|
10
|
-
|
|
19
|
+
<% if sticky_table_style.present? %>
|
|
20
|
+
style="<%= sticky_table_style %>"
|
|
21
|
+
<% end %>
|
|
11
22
|
>
|
|
12
23
|
<thead>
|
|
13
24
|
<tr>
|
|
14
25
|
<% collection_presenter.attribute_types.each do |attr_name, attr_type| %>
|
|
26
|
+
<% sticky_column = sticky_columns[attr_name.to_sym] || {} %>
|
|
15
27
|
<th
|
|
16
|
-
class="cell-label cell-label--<%= attr_type.html_class %> cell-label--<%= collection_presenter.ordered_html_class(attr_name) %> cell-label--<%= "#{collection_presenter.resource_name}_#{attr_name}" %>"
|
|
28
|
+
class="cell-label cell-label--<%= attr_type.html_class %> cell-label--<%= collection_presenter.ordered_html_class(attr_name) %> cell-label--<%= "#{collection_presenter.resource_name}_#{attr_name}" %> <%= sticky_column[:class] %>"
|
|
29
|
+
<% if sticky_column[:style].present? %>style="<%= sticky_column[:style] %>"<% end %>
|
|
17
30
|
scope="col"
|
|
18
31
|
aria-sort="<%= sort_order(collection_presenter.ordered_html_class(attr_name)) %>"
|
|
19
32
|
data-column-id="<%= yummy_guide_administrate_collection_column_id(collection_presenter, attr_name) %>"
|
|
@@ -49,6 +62,8 @@
|
|
|
49
62
|
<% resources.each do |resource| %>
|
|
50
63
|
<tr class="js-table-row">
|
|
51
64
|
<% collection_presenter.attributes_for(resource).each do |attribute| %>
|
|
65
|
+
<% attribute_name = attribute.respond_to?(:name) ? attribute.name : attribute.attribute %>
|
|
66
|
+
<% sticky_column = sticky_columns[attribute_name.to_sym] || {} %>
|
|
52
67
|
<% cell_href = yummy_guide_administrate_collection_attribute_path(attribute: attribute, resource: resource, namespace: namespace) %>
|
|
53
68
|
<% cell = yummy_guide_administrate_build_collection_cell(
|
|
54
69
|
content: render_field(attribute),
|
|
@@ -56,7 +71,10 @@
|
|
|
56
71
|
reference_link: yummy_guide_administrate_collection_reference_link?(attribute),
|
|
57
72
|
text_link: yummy_guide_administrate_collection_text_link?(attribute)
|
|
58
73
|
) %>
|
|
59
|
-
<td
|
|
74
|
+
<td
|
|
75
|
+
class="cell-data cell-data--<%= attribute.html_class %><%= " cell-data--link" if cell[:linkable] %> <%= sticky_column[:class] %>"
|
|
76
|
+
<% if sticky_column[:style].present? %>style="<%= sticky_column[:style] %>"<% end %>
|
|
77
|
+
>
|
|
60
78
|
<%= cell[:content] %>
|
|
61
79
|
</td>
|
|
62
80
|
<% end %>
|
|
@@ -14,10 +14,8 @@ module YummyGuide
|
|
|
14
14
|
yummy_guide_administrate/fixed_submit_actions.js
|
|
15
15
|
yummy_guide_administrate/filter_controls.js
|
|
16
16
|
yummy_guide_administrate/filter_form.js
|
|
17
|
-
yummy_guide_administrate/sticky_left_columns.js
|
|
18
17
|
yummy_guide_administrate/tooltips.js
|
|
19
18
|
yummy_guide_administrate/resizable_navigation.js
|
|
20
|
-
yummy_guide_administrate/sticky_table_headers.js
|
|
21
19
|
]
|
|
22
20
|
end
|
|
23
21
|
|
|
@@ -42,6 +42,23 @@ RSpec.describe YummyGuide::Administrate::ApplicationDashboard do
|
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
describe ".index_fixed_column_widths" do
|
|
46
|
+
# 固定列幅はサブクラスの定数で上書きできることを確認する
|
|
47
|
+
it "returns the subclass fixed column widths when defined" do
|
|
48
|
+
subclass = Class.new(described_class)
|
|
49
|
+
subclass.const_set(:INDEX_FIXED_COLUMN_WIDTHS, { id: "5rem" })
|
|
50
|
+
|
|
51
|
+
expect(subclass.index_fixed_column_widths).to eq({ id: "5rem" })
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# 固定列幅の指定がない場合は親クラスの値にフォールバックすることを確認する
|
|
55
|
+
it "falls back to the superclass fixed column widths" do
|
|
56
|
+
subclass = Class.new(described_class)
|
|
57
|
+
|
|
58
|
+
expect(subclass.index_fixed_column_widths).to eq({})
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
45
62
|
describe ".collection_attribute_sortable?" do
|
|
46
63
|
it "uses collection attributes when explicit sortable attributes are absent" do
|
|
47
64
|
subclass = Class.new(described_class)
|
|
@@ -54,6 +54,138 @@ RSpec.describe YummyGuide::Administrate::CollectionHelper do
|
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
describe "#yummy_guide_administrate_collection_table_fixed_columns_count_for_names" do
|
|
58
|
+
# owner向け一覧のように表示列を手動で絞った場合も、実表示列数で固定列数が打ち止めになることを確認する
|
|
59
|
+
it "caps the fixed column count by the provided column names" do
|
|
60
|
+
dashboard_class = Class.new do
|
|
61
|
+
def self.index_fixed_columns_count
|
|
62
|
+
5
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
page = Object.new
|
|
67
|
+
page.instance_variable_set(:@dashboard, dashboard_class.new)
|
|
68
|
+
|
|
69
|
+
expect(
|
|
70
|
+
helper_host.yummy_guide_administrate_collection_table_fixed_columns_count_for_names(
|
|
71
|
+
page: page,
|
|
72
|
+
column_names: %i[month start_datetime]
|
|
73
|
+
)
|
|
74
|
+
).to eq(2)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe "#yummy_guide_administrate_collection_table_mobile_fixed_columns_count_for_names" do
|
|
79
|
+
# モバイル固定列数も手動指定した表示列数を超えないことを確認する
|
|
80
|
+
it "caps the mobile fixed column count by the provided column names" do
|
|
81
|
+
dashboard_class = Class.new do
|
|
82
|
+
def self.index_mobile_fixed_columns_count
|
|
83
|
+
4
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
page = Object.new
|
|
88
|
+
page.instance_variable_set(:@dashboard, dashboard_class.new)
|
|
89
|
+
|
|
90
|
+
expect(
|
|
91
|
+
helper_host.yummy_guide_administrate_collection_table_mobile_fixed_columns_count_for_names(
|
|
92
|
+
page: page,
|
|
93
|
+
column_names: %i[month start_datetime customer]
|
|
94
|
+
)
|
|
95
|
+
).to eq(3)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe "#yummy_guide_administrate_collection_sticky_columns" do
|
|
100
|
+
# 固定列のclassとCSS変数が表示列順から生成されることを確認する
|
|
101
|
+
it "builds sticky column classes and offsets from the rendered column order" do
|
|
102
|
+
dashboard_class = Class.new do
|
|
103
|
+
def self.index_fixed_columns_count
|
|
104
|
+
2
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def self.index_mobile_fixed_columns_count
|
|
108
|
+
1
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.index_fixed_column_widths
|
|
112
|
+
{ customer: "14rem" }
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
page = Object.new
|
|
117
|
+
page.instance_variable_set(:@dashboard, dashboard_class.new)
|
|
118
|
+
collection_presenter = Struct.new(:attribute_types).new({ id: :integer, customer: :belongs_to, note: :text })
|
|
119
|
+
|
|
120
|
+
sticky_columns = helper_host.yummy_guide_administrate_collection_sticky_columns(
|
|
121
|
+
page: page,
|
|
122
|
+
collection_presenter: collection_presenter,
|
|
123
|
+
column_names: %i[id customer note]
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
expect(sticky_columns[:id]).to eq(
|
|
127
|
+
class: "sticky-left sticky-left-mobile sticky-left-mobile--last",
|
|
128
|
+
style: "--sticky-left: 0px; --sticky-width: 4rem; --sticky-mobile-left: 0px; --sticky-mobile-width: 4rem"
|
|
129
|
+
)
|
|
130
|
+
expect(sticky_columns[:customer]).to eq(
|
|
131
|
+
class: "sticky-left sticky-left--last",
|
|
132
|
+
style: "--sticky-left: 4rem; --sticky-width: 14rem"
|
|
133
|
+
)
|
|
134
|
+
expect(sticky_columns).not_to have_key(:note)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# owner向け一覧のように実際の描画列が変わっても、その列リストを基準に固定列を計算することを確認する
|
|
138
|
+
it "uses the provided column names instead of all dashboard attributes" do
|
|
139
|
+
dashboard_class = Class.new do
|
|
140
|
+
def self.index_fixed_columns_count
|
|
141
|
+
3
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def self.index_mobile_fixed_columns_count
|
|
145
|
+
2
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
page = Object.new
|
|
150
|
+
page.instance_variable_set(:@dashboard, dashboard_class.new)
|
|
151
|
+
collection_presenter = Struct.new(:attribute_types).new({ id: :integer, customer: :belongs_to, note: :text })
|
|
152
|
+
|
|
153
|
+
sticky_columns = helper_host.yummy_guide_administrate_collection_sticky_columns(
|
|
154
|
+
page: page,
|
|
155
|
+
collection_presenter: collection_presenter,
|
|
156
|
+
column_names: %i[month start_datetime]
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
expect(sticky_columns.keys).to eq(%i[month start_datetime])
|
|
160
|
+
expect(sticky_columns[:start_datetime][:class]).to include("sticky-left--last")
|
|
161
|
+
expect(sticky_columns[:start_datetime][:class]).to include("sticky-left-mobile--last")
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
describe "#yummy_guide_administrate_collection_sticky_table_style" do
|
|
166
|
+
# nth-child fallback が参照するテーブル単位の固定列幅CSS変数を生成できることを確認する
|
|
167
|
+
it "builds table-level width variables for fixed column fallbacks" do
|
|
168
|
+
dashboard_class = Class.new do
|
|
169
|
+
def self.index_fixed_column_widths
|
|
170
|
+
{ customer: "14rem" }
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
page = Object.new
|
|
175
|
+
page.instance_variable_set(:@dashboard, dashboard_class.new)
|
|
176
|
+
|
|
177
|
+
style = helper_host.yummy_guide_administrate_collection_sticky_table_style(
|
|
178
|
+
page: page,
|
|
179
|
+
column_names: %i[id customer note]
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
expect(style).to include("--admin-sticky-col-1-width: 4rem")
|
|
183
|
+
expect(style).to include("--admin-sticky-mobile-col-1-width: 4rem")
|
|
184
|
+
expect(style).to include("--admin-sticky-col-2-width: 14rem")
|
|
185
|
+
expect(style).to include("--admin-sticky-col-3-width: 8rem")
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
57
189
|
describe "#yummy_guide_administrate_collection_column_id" do
|
|
58
190
|
let(:collection_presenter) { Struct.new(:resource_name).new("external_reservation") }
|
|
59
191
|
|
|
@@ -9,12 +9,8 @@ RSpec.describe "column resizer assets" do
|
|
|
9
9
|
File.read(File.expand_path("../../../app/assets/stylesheets/yummy_guide_administrate/_column_resizer.scss", __dir__))
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
let(:
|
|
13
|
-
File.read(File.expand_path("../../../app/assets/
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
let(:sticky_left_columns_source) do
|
|
17
|
-
File.read(File.expand_path("../../../app/assets/javascripts/yummy_guide_administrate/sticky_left_columns.js", __dir__))
|
|
12
|
+
let(:components_source) do
|
|
13
|
+
File.read(File.expand_path("../../../app/assets/stylesheets/yummy_guide_administrate/components.scss", __dir__))
|
|
18
14
|
end
|
|
19
15
|
|
|
20
16
|
# 未調整列は内容幅で表示され、調整済み列だけが幅固定されることを静的に確認する
|
|
@@ -116,68 +112,46 @@ RSpec.describe "column resizer assets" do
|
|
|
116
112
|
expect(stylesheet_source).to include("width: 36px")
|
|
117
113
|
end
|
|
118
114
|
|
|
119
|
-
#
|
|
120
|
-
it "
|
|
121
|
-
expect(
|
|
122
|
-
expect(
|
|
123
|
-
expect(
|
|
124
|
-
expect(
|
|
125
|
-
expect(
|
|
126
|
-
expect(
|
|
127
|
-
expect(
|
|
128
|
-
expect(
|
|
129
|
-
expect(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
expect(
|
|
135
|
-
expect(
|
|
136
|
-
expect(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
expect(
|
|
142
|
-
expect(
|
|
143
|
-
expect(
|
|
144
|
-
expect(
|
|
145
|
-
expect(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
expect(
|
|
152
|
-
expect(
|
|
153
|
-
expect(sticky_left_columns_source).to include("width: preciseNumber(width)")
|
|
154
|
-
expect(sticky_left_columns_source).to include("var hasMeasuredWidth = widths.some(Boolean)")
|
|
155
|
-
expect(sticky_left_columns_source).to include("applyWidthOverride(widths, override)")
|
|
156
|
-
expect(sticky_left_columns_source).to include("var offsets = stickyOffsets(table, count, options)")
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
# 幅リセット時は明示幅がないため、クリア後に通常の固定左列再計算へ戻すことを静的に確認する
|
|
160
|
-
it "recalculates sticky-left offsets after clearing a column width" do
|
|
161
|
-
expect(javascript_source).to include("clearColumnWidth(columnId, key)")
|
|
162
|
-
expect(javascript_source).to include("refreshStickyHeaderTable(sourceTable, function()")
|
|
163
|
-
expect(javascript_source).to include("refreshStickyLeftColumns(sourceTable)")
|
|
115
|
+
# CSSだけで固定ヘッダーと固定左列の初期表示に必要なスタイルがあることを静的に確認する
|
|
116
|
+
it "defines CSS-only sticky table styles" do
|
|
117
|
+
expect(components_source).to include("[data-css-sticky-table]")
|
|
118
|
+
expect(components_source).to include("max-height: var(--admin-sticky-table-max-height")
|
|
119
|
+
expect(components_source).to include("top: 0")
|
|
120
|
+
expect(components_source).to include("--sticky-col-1-width")
|
|
121
|
+
expect(components_source).to include("left: var(--sticky-left, 0)")
|
|
122
|
+
expect(components_source).to include("left: var(--sticky-mobile-left, 0)")
|
|
123
|
+
expect(components_source).to include(":not(.sticky-left)")
|
|
124
|
+
expect(components_source).to include(":not(.sticky-left-mobile)")
|
|
125
|
+
expect(components_source).to include("th.sticky.actions-column")
|
|
126
|
+
expect(components_source).to include("td.sticky.actions-column")
|
|
127
|
+
expect(components_source).to include(".scroll-table[data-css-sticky-table] table > thead th")
|
|
128
|
+
expect(components_source).to include("background-color: #121012")
|
|
129
|
+
expect(components_source).to include("color: #fff")
|
|
130
|
+
expect(components_source).to include(".scroll-table[data-css-sticky-table] table > thead th a")
|
|
131
|
+
expect(components_source).to include("color: inherit")
|
|
132
|
+
expect(components_source).to include("z-index: 6")
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# 固定列リサイズ後にCSS変数のleftと幅を再計算する処理があることを静的に確認する
|
|
136
|
+
it "recalculates CSS sticky-left offsets after applying column widths" do
|
|
137
|
+
expect(javascript_source).to include("function refreshCssStickyLeftColumns(table)")
|
|
138
|
+
expect(javascript_source).to include("refreshCssStickyLeftColumnSet(table, 'sticky-left', '--sticky-left', '--sticky-width')")
|
|
139
|
+
expect(javascript_source).to include("refreshCssStickyLeftColumnSet(table, 'sticky-left-mobile', '--sticky-mobile-left', '--sticky-mobile-width')")
|
|
140
|
+
expect(javascript_source).to include("cell.style.setProperty(leftVariable, cssPixelValue(left))")
|
|
141
|
+
expect(javascript_source).to include("refreshCssStickyLeftColumns(table)")
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# 固定ヘッダー複製APIがなくても幅適用後の完了処理に進めることを静的に確認する
|
|
145
|
+
it "keeps a resize fallback when fixed header JavaScript is absent" do
|
|
146
|
+
expect(javascript_source).to include("var api = window.YummyGuideAdministrateStickyTableHeaders")
|
|
147
|
+
expect(javascript_source).to include("if (api && typeof api.refreshColumnWidth === 'function')")
|
|
148
|
+
expect(javascript_source).to include("scheduleStickyRefresh(callback)")
|
|
164
149
|
end
|
|
165
150
|
|
|
166
|
-
#
|
|
167
|
-
it "
|
|
151
|
+
# 幅リセット時も固定列のCSS変数を再計算することを静的に確認する
|
|
152
|
+
it "recalculates CSS sticky-left offsets after clearing a column width" do
|
|
168
153
|
expect(javascript_source).to include("clearColumnWidth(columnId, key)")
|
|
169
|
-
expect(javascript_source).to include("
|
|
170
|
-
expect(javascript_source).to include("
|
|
171
|
-
expect(javascript_source).to include("scheduleStickyRefresh(function()")
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
# 幅リセット時は固定ヘッダーの管理幅を先に作り直してから固定左列を再計算することを静的に確認する
|
|
175
|
-
it "rebuilds fixed headers before refreshing sticky-left columns after clearing a width" do
|
|
176
|
-
expect(javascript_source).to include("function refreshStickyHeaderTable(sourceTable, callback)")
|
|
177
|
-
expect(javascript_source).to include("api.refreshTable(sourceTable, callback)")
|
|
178
|
-
expect(javascript_source).to include("scheduleStickyRefresh(callback)")
|
|
179
|
-
expect(sticky_table_headers_source).to include("function refreshTable(sourceTable, callback)")
|
|
180
|
-
expect(sticky_table_headers_source).to include("initializeFixedHeaderForScroll(scroll)")
|
|
181
|
-
expect(sticky_table_headers_source).to include("window.requestAnimationFrame(callback)")
|
|
154
|
+
expect(javascript_source).to include("clearTableColumnWidth(table, columnId)")
|
|
155
|
+
expect(javascript_source).to include("refreshCssStickyLeftColumns(table)")
|
|
182
156
|
end
|
|
183
157
|
end
|
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.8.
|
|
4
|
+
version: 0.8.5
|
|
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-06-
|
|
11
|
+
date: 2026-06-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: administrate
|