trestle 0.10.0.pre → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +26 -0
  3. data/.github/workflows/rspec.yml +6 -2
  4. data/Gemfile +14 -5
  5. data/README.md +1 -1
  6. data/app/assets/bundle/trestle/admin.css +9 -9
  7. data/app/assets/bundle/trestle/admin.js +13 -13
  8. data/app/assets/bundle/trestle/fa-brands-400.ttf +0 -0
  9. data/app/assets/bundle/trestle/fa-brands-400.woff2 +0 -0
  10. data/app/assets/bundle/trestle/fa-regular-400.ttf +0 -0
  11. data/app/assets/bundle/trestle/fa-regular-400.woff2 +0 -0
  12. data/app/assets/bundle/trestle/fa-solid-900.ttf +0 -0
  13. data/app/assets/bundle/trestle/fa-solid-900.woff2 +0 -0
  14. data/app/assets/bundle/trestle/photoswipe-063ce7be40e10b3e6848.digested.js +6 -0
  15. data/app/assets/sprockets/trestle/icons/font-awesome.css.erb +1 -1
  16. data/app/controllers/concerns/trestle/controller/modal.rb +3 -1
  17. data/app/controllers/concerns/trestle/controller/turbo_stream.rb +12 -0
  18. data/app/controllers/concerns/trestle/resource/controller/actions.rb +3 -3
  19. data/app/controllers/trestle/application_controller.rb +1 -1
  20. data/app/helpers/trestle/modal_helper.rb +0 -5
  21. data/app/helpers/trestle/turbo/frame_helper.rb +29 -0
  22. data/app/helpers/trestle/turbo/stream_helper.rb +9 -0
  23. data/app/helpers/trestle/turbo/tag_builder.rb +21 -0
  24. data/app/helpers/trestle/url_helper.rb +2 -2
  25. data/app/views/layouts/trestle/admin.html.erb +1 -1
  26. data/app/views/layouts/trestle/admin.turbo_stream.erb +2 -9
  27. data/app/views/trestle/application/_header.html.erb +12 -10
  28. data/app/views/trestle/resource/create.turbo_stream.erb +1 -5
  29. data/app/views/trestle/resource/destroy.turbo_stream.erb +1 -1
  30. data/app/views/trestle/resource/edit.html.erb +2 -0
  31. data/app/views/trestle/resource/index.html.erb +5 -0
  32. data/app/views/trestle/resource/new.html.erb +5 -0
  33. data/app/views/trestle/resource/show.html.erb +2 -0
  34. data/app/views/trestle/resource/update.turbo_stream.erb +1 -5
  35. data/app/views/trestle/shared/_sidebar.html.erb +2 -2
  36. data/frontend/css/components/_alerts.scss +22 -20
  37. data/frontend/css/components/_avatar.scss +12 -12
  38. data/frontend/css/components/_background.scss +1 -1
  39. data/frontend/css/components/_breadcrumbs.scss +8 -29
  40. data/frontend/css/components/_buttons.scss +3 -3
  41. data/frontend/css/components/_datepicker.scss +3 -3
  42. data/frontend/css/components/_dropdown.scss +18 -26
  43. data/frontend/css/components/_forms.scss +4 -4
  44. data/frontend/css/components/_grid.scss +29 -0
  45. data/frontend/css/components/_media-grid.scss +1 -1
  46. data/frontend/css/components/_modal.scss +4 -4
  47. data/frontend/css/components/_pagination.scss +4 -8
  48. data/frontend/css/components/_popover.scss +1 -1
  49. data/frontend/css/components/_scopes.scss +4 -10
  50. data/frontend/css/components/_select.scss +8 -9
  51. data/frontend/css/components/_sort.scss +1 -1
  52. data/frontend/css/components/_table.scss +5 -5
  53. data/frontend/css/components/_tabs.scss +11 -18
  54. data/frontend/css/components/_tags.scss +16 -6
  55. data/frontend/css/components/_toolbars.scss +9 -9
  56. data/frontend/css/core/_functions.scss +0 -8
  57. data/frontend/css/core/_theme.scss +3 -0
  58. data/frontend/css/core/_typography.scss +12 -19
  59. data/frontend/css/index.scss +3 -1
  60. data/frontend/css/layout/_base.scss +4 -2
  61. data/frontend/css/layout/_content-header.scss +71 -0
  62. data/frontend/css/layout/_footer.scss +5 -7
  63. data/frontend/css/layout/_main-content.scss +107 -0
  64. data/frontend/css/layout/_navigation.scss +111 -49
  65. data/frontend/css/layout/_sidebar.scss +60 -34
  66. data/frontend/css/variables/_bootstrap.scss +30 -21
  67. data/frontend/css/variables/_trestle.scss +20 -17
  68. data/frontend/js/controllers/batch_action_controller.js +59 -0
  69. data/frontend/js/controllers/checkbox_select_controller.js +3 -0
  70. data/frontend/js/controllers/confirm_delete_controller.js +4 -4
  71. data/frontend/js/controllers/gallery_controller.js +2 -0
  72. data/frontend/js/controllers/lightbox_controller.js +0 -2
  73. data/lib/trestle/engine.rb +18 -16
  74. data/lib/trestle/form/renderer.rb +1 -1
  75. data/lib/trestle/resource/toolbar.rb +18 -8
  76. data/lib/trestle/sprockets_compressor.rb +16 -0
  77. data/lib/trestle/toolbar/context.rb +7 -4
  78. data/lib/trestle/toolbar/menu.rb +8 -5
  79. data/lib/trestle/version.rb +1 -1
  80. data/package.json +1 -1
  81. data/trestle.gemspec +5 -9
  82. data/yarn.lock +350 -363
  83. metadata +35 -70
  84. data/app/assets/bundle/trestle/photoswipe-7aa1aec9c3c1fd65c382.digested.js +0 -6
  85. data/app/controllers/concerns/trestle/controller/turbo.rb +0 -21
  86. data/app/helpers/trestle/turbo_frame_helper.rb +0 -34
  87. data/frontend/css/layout/_content.scss +0 -173
@@ -1,9 +1,19 @@
1
1
  @use "sass:math";
2
2
 
3
+ .app-wrapper {
4
+ --sidebar-width: #{$sidebar-width};
5
+ --sidebar-width-collapsed: #{$sidebar-width-collapsed};
6
+ --sidebar-padding: #{$sidebar-padding};
7
+ --sidebar-padding-collapsed: #{$sidebar-padding-collapsed};
8
+ --sidebar-transition-duration: #{$sidebar-transition-duration};
9
+ --sidebar-transition-timing: ease-out;
10
+ --sidebar-bg: #{$sidebar-bg};
11
+ }
12
+
3
13
  .app-sidebar {
4
- background: $sidebar-bg;
14
+ background: var(--sidebar-bg);
5
15
 
6
- width: $sidebar-width;
16
+ width: var(--sidebar-width);
7
17
  padding: 0;
8
18
 
9
19
  flex-shrink: 0;
@@ -15,6 +25,8 @@
15
25
  flex-wrap: nowrap;
16
26
 
17
27
  align-items: stretch;
28
+
29
+ transition: width var(--sidebar-transition-duration) var(--sidebar-transition-timing);
18
30
  }
19
31
 
20
32
  .app-sidebar-header {
@@ -25,10 +37,12 @@
25
37
  display: flex;
26
38
  align-items: stretch;
27
39
 
40
+ overflow: hidden;
41
+
28
42
  .navbar-toggler {
29
- --bs-navbar-toggler-bg: #{$sidebar-mobile-toggle-bg};
30
- --bs-navbar-toggler-color: #{$sidebar-mobile-toggle-border-color};
31
- --bs-navbar-toggler-border-color: #{$sidebar-mobile-toggle-border-color};
43
+ --#{$prefix}navbar-toggler-bg: #{$sidebar-mobile-toggle-bg};
44
+ --#{$prefix}navbar-toggler-color: #{$sidebar-mobile-toggle-border-color};
45
+ --#{$prefix}navbar-toggler-border-color: #{$sidebar-mobile-toggle-border-color};
32
46
 
33
47
  outline: none;
34
48
 
@@ -37,28 +51,29 @@
37
51
  margin-left: math.div($grid-gutter-width, 2);
38
52
  margin-right: math.div($grid-gutter-width, 2);
39
53
 
40
- background: var(--bs-navbar-toggler-bg);
54
+ background: var(--#{$prefix}navbar-toggler-bg);
41
55
 
42
56
  &:hover, &:focus {
43
- --bs-navbar-toggler-border-color: #{$sidebar-mobile-toggle-active-border-color};
44
- --bs-navbar-toggler-bg: #{$sidebar-mobile-toggle-active-bg};
57
+ --#{$prefix}navbar-toggler-border-color: #{$sidebar-mobile-toggle-active-border-color};
58
+ --#{$prefix}navbar-toggler-bg: #{$sidebar-mobile-toggle-active-bg};
45
59
  }
46
60
  }
47
61
 
48
62
  .navbar-toggler-icon {
49
- --bs-navbar-toggler-icon-bg: #{$sidebar-mobile-toggle-icon-bg};
63
+ --#{$prefix}navbar-toggler-icon-bg: #{$sidebar-mobile-toggle-icon-bg};
50
64
  }
51
65
  }
52
66
 
53
67
  .app-sidebar-title {
54
- flex: 1;
68
+ flex: 1 0 var(--sidebar-width);
69
+ width: var(--sidebar-width);
55
70
 
56
71
  display: flex;
57
72
  align-items: center;
58
73
 
59
- padding: 10px 15px;
74
+ padding: var(--sidebar-padding);
60
75
 
61
- font-size: 1.4rem;
76
+ font-size: 1.25rem;
62
77
  font-weight: 500;
63
78
  text-shadow: rgba(black, 0.5) 0 1px 1px;
64
79
  color: white;
@@ -72,7 +87,7 @@
72
87
  max-height: 100%;
73
88
 
74
89
  & + .title-large {
75
- margin-left: 10px;
90
+ margin-left: 0.75rem;
76
91
  }
77
92
  }
78
93
 
@@ -112,8 +127,9 @@
112
127
  color: $sidebar-toggle-color;
113
128
  border: none;
114
129
 
115
- font-size: 1.4rem;
116
- padding: 10px 20px;
130
+ font-size: 1.25rem;
131
+ width: var(--sidebar-width-collapsed);
132
+ padding: 0.625rem;
117
133
 
118
134
  cursor: pointer;
119
135
 
@@ -138,19 +154,13 @@
138
154
  }
139
155
 
140
156
  .app-wrapper {
141
- margin-left: -$sidebar-width;
142
- margin-right: 0;
157
+ width: calc(100% + var(--sidebar-width));
143
158
 
144
- &.animate {
145
- transition: all $sidebar-transition-duration ease-out;
146
- transition-property: margin-left, margin-right;
147
- }
148
- }
159
+ translate: calc(var(--sidebar-width) * -1);
160
+ transition: translate var(--sidebar-transition-duration) ease-out;
149
161
 
150
- .mobile-nav-expanded {
151
- .app-wrapper {
152
- margin-left: 0;
153
- margin-right: -$sidebar-width;
162
+ .mobile-nav-expanded & {
163
+ translate: 0;
154
164
  }
155
165
  }
156
166
 
@@ -161,14 +171,14 @@
161
171
  .app-sidebar-header {
162
172
  position: absolute;
163
173
  top: 0;
164
- left: $sidebar-width;
174
+ left: var(--sidebar-width);
165
175
  right: 0;
166
176
  z-index: 1;
167
177
  }
168
178
 
169
179
  .app-sidebar-title {
170
180
  justify-content: center;
171
- padding: 10px 5px;
181
+ padding: var(--sidebar-padding-collapsed);
172
182
 
173
183
  // Match right margin with navbar toggler width:
174
184
  // (margin + border + font-size * icon-width + padding)
@@ -182,14 +192,17 @@
182
192
 
183
193
  @include media-breakpoint-between(md, xl) {
184
194
  .app-sidebar {
185
- width: $sidebar-width-collapsed;
195
+ width: var(--sidebar-width-collapsed);
186
196
 
187
197
  .app-sidebar-header {
188
198
  text-align: center;
189
199
  }
190
200
 
191
201
  .app-sidebar-title {
192
- padding: 10px 5px;
202
+ width: var(--sidebar-width-collapsed);
203
+ flex-basis: var(--sidebar-width-collapsed);
204
+
205
+ padding: var(--sidebar-padding-collapsed);
193
206
  justify-content: center;
194
207
 
195
208
  img {
@@ -210,14 +223,17 @@
210
223
  }
211
224
 
212
225
  .sidebar-expanded & {
213
- width: $sidebar-width;
226
+ width: var(--sidebar-width);
214
227
 
215
228
  .app-sidebar-header {
216
229
  text-align: left;
217
230
  }
218
231
 
219
232
  .app-sidebar-title {
220
- padding: 10px 15px;
233
+ width: var(--sidebar-width);
234
+ flex-basis: var(--sidebar-width);
235
+
236
+ padding: var(--sidebar-padding);
221
237
  justify-content: flex-start;
222
238
 
223
239
  img {
@@ -243,14 +259,17 @@
243
259
  @include media-breakpoint-up(xl) {
244
260
  .app-sidebar {
245
261
  .sidebar-collapsed & {
246
- width: $sidebar-width-collapsed;
262
+ width: var(--sidebar-width-collapsed);
247
263
 
248
264
  .app-sidebar-header {
249
265
  text-align: center;
250
266
  }
251
267
 
252
268
  .app-sidebar-title {
253
- padding: 10px 5px;
269
+ width: var(--sidebar-width-collapsed);
270
+ flex-basis: var(--sidebar-width-collapsed);
271
+
272
+ padding: var(--sidebar-padding-collapsed);
254
273
  justify-content: center;
255
274
 
256
275
  img {
@@ -272,3 +291,10 @@
272
291
  }
273
292
  }
274
293
  }
294
+
295
+ @media (prefers-reduced-motion) {
296
+ .app-sidebar,
297
+ .app-wrapper {
298
+ transition: none;
299
+ }
300
+ }
@@ -23,7 +23,7 @@ $min-contrast-ratio: 1.7;
23
23
  $enable-shadows: true;
24
24
 
25
25
  // Decrease default grid spacing
26
- $grid-gutter-width: 1.375rem;
26
+ $grid-gutter-width: 1.25rem;
27
27
 
28
28
 
29
29
  // Characters which are escaped by the escape-svg function
@@ -49,15 +49,17 @@ $link-decoration: none;
49
49
  $headings-font-weight: 400;
50
50
  $headings-margin-bottom: 1rem;
51
51
 
52
- $h1-font-size: 2rem;
53
- $h2-font-size: 1.75rem;
54
- $h3-font-size: 1.5rem;
55
- $h4-font-size: 1.25rem;
56
- $h5-font-size: 1.1rem;
57
- $h6-font-size: 1rem;
52
+ $font-size-base: 0.875rem;
53
+
54
+ $h1-font-size: 1.75rem;
55
+ $h2-font-size: 1.5rem;
56
+ $h3-font-size: 1.25rem;
57
+ $h4-font-size: 1.125rem;
58
+ $h5-font-size: 0.95rem;
59
+ $h6-font-size: 0.875rem;
58
60
 
59
61
  $hr-color: rgba(black, 0.375);
60
- $hr-margin-y: 1.5rem;
62
+ $hr-margin-y: 1.25rem;
61
63
 
62
64
 
63
65
  // Navs
@@ -80,8 +82,11 @@ $nav-tabs-link-active-color: $body-color;
80
82
 
81
83
  // Navbar
82
84
 
83
- $navbar-toggler-padding-x: 0.4rem;
84
- $navbar-dark-color: rgba(white, 0.75);
85
+ $navbar-light-color: rgba(white, 0.75);
86
+ $navbar-dark-color: rgba(white, 0.75);
87
+
88
+ $navbar-toggler-padding-x: 0.375rem;
89
+ $navbar-toggler-focus-width: 0.25rem;
85
90
 
86
91
 
87
92
  // Breadcrumbs
@@ -94,7 +99,7 @@ $breadcrumb-divider-color: #cccccc;
94
99
 
95
100
  // Tables
96
101
 
97
- $table-cell-padding-x: 0.625rem;
102
+ $table-cell-padding-x: 0.5rem;
98
103
  $table-cell-padding-y: 0.375rem;
99
104
 
100
105
  $table-bg: transparent;
@@ -105,7 +110,7 @@ $table-border-color: rgba(black, 0.13);
105
110
 
106
111
  // Alerts
107
112
 
108
- $alert-padding-y: 1.5rem;
113
+ $alert-padding-y: 1.25rem;
109
114
  $alert-border-radius: 0.1rem;
110
115
 
111
116
 
@@ -134,7 +139,8 @@ $badge-padding-x: 0.6em;
134
139
 
135
140
  // Buttons
136
141
 
137
- $btn-padding-x-sm: 0.65rem;
142
+ $btn-padding-x-sm: 0.625rem;
143
+ $btn-padding-y-sm: 0.25rem;
138
144
 
139
145
 
140
146
  // Forms
@@ -163,7 +169,7 @@ $form-check-padding-start: $form-check-input-width + 0.6em;
163
169
  $form-switch-width: 2.25em;
164
170
  $form-switch-focus-color: #aaaaaa;
165
171
 
166
- $form-select-padding-x-sm: 0.62rem;
172
+ $form-select-padding-x-sm: 0.625rem;
167
173
  $form-select-padding-x-lg: 0.75rem;
168
174
 
169
175
 
@@ -175,7 +181,7 @@ $dropdown-box-shadow: $box-shadow-sm;
175
181
  $dropdown-arrow-width: 7px;
176
182
  $dropdown-arrow-outer-width: $dropdown-arrow-width + 1px;
177
183
  $dropdown-header-color: #111111;
178
- $dropdown-font-size: 0.9rem;
184
+ $dropdown-font-size: 0.8125rem;
179
185
 
180
186
  $dropdown-link-active-bg: var(--primary);
181
187
 
@@ -208,24 +214,27 @@ $tooltip-color: white;
208
214
 
209
215
  // Popovers
210
216
 
211
- $popover-font-size: 0.9rem;
217
+ $popover-font-size: 0.75rem;
212
218
  $popover-box-shadow: $dropdown-box-shadow;
213
219
 
214
220
  $popover-header-bg: #f7f7f7;
215
221
  $popover-header-border: #ebebeb;
216
222
 
223
+ $popover-header-padding-x: 0.625rem;
224
+ $popover-header-padding-y: 0.375rem;
225
+
226
+ $popover-body-padding-x: 0.625rem;
217
227
  $popover-body-padding-y: 0.5rem;
218
- $popover-body-padding-x: 0.75rem;
219
228
 
220
229
  $popover-arrow-width: $dropdown-arrow-width;
221
230
 
222
231
 
223
232
  // Modals
224
233
 
225
- $modal-inner-padding: 1.5rem;
234
+ $modal-inner-padding: 1.25rem;
226
235
 
227
- $modal-header-padding-x: 1.5rem;
228
- $modal-header-padding-y: 1.05rem;
236
+ $modal-header-padding-x: 1.25rem;
237
+ $modal-header-padding-y: 1rem;
229
238
 
230
239
  $modal-content-bg: white;
231
240
  $modal-content-border-radius: 0;
@@ -262,7 +271,7 @@ $s2bs5-clear-hover-bg-lg: $s2bs5-clear-bg-lg;
262
271
  $s2bs5-clear-tag-icon: $btn-close-bg;
263
272
  $s2bs5-clear-tag-bg: transparent escape-svg($s2bs5-clear-tag-icon) center / $s2b25-clear-height-sm auto no-repeat;
264
273
 
265
- $s2bs5-padding-x: 0.75rem;
274
+ $s2bs5-padding-x: 0.625rem;
266
275
  $s2bs5-padding-y: 0.375rem;
267
276
 
268
277
  $s2bs5-multi-item-padding-x: 0.375rem;
@@ -21,7 +21,7 @@ $theme-bg-variations: (
21
21
  $header-bg: white;
22
22
  $header-color: #333333;
23
23
 
24
- $header-height: 50px;
24
+ $header-height: 3.125rem;
25
25
 
26
26
 
27
27
  // Footer
@@ -29,13 +29,15 @@ $header-height: 50px;
29
29
  $footer-bg: #f9f9f9;
30
30
  $footer-color: #888888;
31
31
 
32
+ $footer-padding: 0.375rem 1.25rem;
33
+
32
34
 
33
35
  // Sidebar
34
36
 
35
37
  $sidebar-bg: #222222;
36
38
  $sidebar-hover-bg: #1a1a1a;
37
39
  $sidebar-active-bg: #393939;
38
- $sidebar-active-border: 4px;
40
+ $sidebar-active-border: 0.25rem;
39
41
 
40
42
  $sidebar-link-color: #919191;
41
43
  $sidebar-group-color: #595959;
@@ -56,10 +58,13 @@ $sidebar-mobile-toggle-active-border-width: $sidebar-mobile-toggle-border-width;
56
58
  $sidebar-mobile-toggle-active-border-color: $sidebar-mobile-toggle-border-color;
57
59
  $sidebar-mobile-toggle-active-border: $sidebar-mobile-toggle-border-width solid $sidebar-mobile-toggle-active-border-color;
58
60
 
59
- $sidebar-width: 250px;
60
- $sidebar-width-collapsed: 54px;
61
+ $sidebar-width: 15.625rem;
62
+ $sidebar-width-collapsed: 3.5rem;
63
+
64
+ $sidebar-padding: 0.5rem 0.875rem;
65
+ $sidebar-padding-collapsed: 0.5rem 0.25rem;
61
66
 
62
- $sidebar-transition-duration: 250ms;
67
+ $sidebar-transition-duration: 200ms;
63
68
 
64
69
 
65
70
  // Content
@@ -67,23 +72,21 @@ $sidebar-transition-duration: 250ms;
67
72
  $content-header-bg: #fafafa;
68
73
  $content-sidebar-bg: #f9f9f9;
69
74
 
70
- $content-sidebar-width: 285px;
75
+ $content-sidebar-width: 17.5rem;
71
76
 
72
- $main-content-header-bg: $content-sidebar-bg;
73
- $main-content-header-padding: 12px 20px;
74
- $main-content-header-border: 1px solid rgba(black, 0.1);
77
+ $main-content-header-bg: $content-sidebar-bg;
78
+ $main-content-header-border: 1px solid rgba(black, 0.1);
75
79
 
76
- $main-content-footer-bg: $content-sidebar-bg;
77
- $main-content-footer-padding: 12px 20px;
78
- $main-content-footer-border: 1px solid rgba(black, 0.1);
80
+ $main-content-footer-bg: $content-sidebar-bg;
81
+ $main-content-footer-border: 1px solid rgba(black, 0.1);
79
82
 
80
83
 
81
84
  // Typography
82
85
 
83
86
  $headings-border: 1px solid rgba(black, 0.1);
84
87
 
85
- $header-font-size-scale: 0.925;
86
- $sidebar-font-size-scale: 0.925;
88
+ $header-font-size-scale: 0.8125;
89
+ $sidebar-font-size-scale: 0.8125;
87
90
 
88
91
  $badge-hover-scale: -15%;
89
92
 
@@ -96,13 +99,13 @@ $tag-border-scale: 0;
96
99
  $tag-hover-bg-scale: -15%;
97
100
  $tag-hover-border-scale: 15%;
98
101
 
99
- $tag-spacing-x: 0.325rem;
100
- $tag-spacing-y: 0.25rem;
102
+ $tag-spacing-x: 0.25rem;
103
+ $tag-spacing-y: 0.2rem;
101
104
 
102
105
 
103
106
  // Scopes
104
107
 
105
- $scope-padding: 0.25rem 0.675rem;
108
+ $scope-padding: 0.2rem 0.625rem;
106
109
 
107
110
  $scope-color: rgba(black, 0.4);
108
111
  $scope-bg: rgba(black, 0.035);
@@ -0,0 +1,59 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ export default class extends ApplicationController {
4
+ static outlets = ['checkbox-select']
5
+
6
+ connect () {
7
+ if (!this.hasCheckboxSelectOutlet) {
8
+ // Set default outlet if none specified
9
+ this.element.setAttribute(`data-${this.identifier}-checkbox-select-outlet`, '.trestle-table')
10
+ }
11
+
12
+ this.baseHref = this.element.href
13
+
14
+ this.update()
15
+ }
16
+
17
+ update () {
18
+ this.toggleEnabled()
19
+ this.updateHref()
20
+ }
21
+
22
+ toggleEnabled () {
23
+ this.element.classList.toggle('disabled', this.checkboxes.length === 0)
24
+ }
25
+
26
+ updateHref () {
27
+ this.element.href = this.hrefWithSelectedIds
28
+ }
29
+
30
+ get checkboxes () {
31
+ if (this.hasCheckboxSelectOutlet) {
32
+ return this.checkboxSelectOutlet.checked
33
+ } else {
34
+ return []
35
+ }
36
+ }
37
+
38
+ get selectedIds () {
39
+ return this.checkboxes.map(c => c.value)
40
+ }
41
+
42
+ get hrefWithSelectedIds () {
43
+ const ids = this.selectedIds
44
+
45
+ if (ids.length) {
46
+ return `${this.baseHref}?ids=${ids.join(',')}`
47
+ } else {
48
+ return this.baseHref
49
+ }
50
+ }
51
+
52
+ checkboxSelectOutletConnected (outlet, element) {
53
+ element.addEventListener('checkbox-select:change', this.update.bind(this))
54
+ }
55
+
56
+ checkboxSelectOutletDisconnected (outlet, element) {
57
+ element.removeEventListener('checkbox-select:change', this.update.bind(this))
58
+ }
59
+ }
@@ -5,6 +5,7 @@ export default class extends ApplicationController {
5
5
 
6
6
  toggle () {
7
7
  this.updateSelectAllState()
8
+ this.dispatch('change')
8
9
  }
9
10
 
10
11
  toggleAll () {
@@ -13,6 +14,8 @@ export default class extends ApplicationController {
13
14
  this.checkboxTargets.forEach((checkbox) => {
14
15
  checkbox.checked = isChecked
15
16
  })
17
+
18
+ this.dispatch('change')
16
19
  }
17
20
 
18
21
  updateSelectAllState () {
@@ -3,9 +3,9 @@ import ConfirmController from './confirm_controller'
3
3
  import { i18n } from '../core/i18n'
4
4
 
5
5
  export default class extends ConfirmController {
6
- static values = {
7
- confirmLabel: i18n['trestle.confirmation.delete'] || 'Delete'
8
- }
9
-
10
6
  static defaultConfirmClass = 'btn-danger'
7
+
8
+ get confirmLabel () {
9
+ return this.confirmLabelValue || i18n.t('trestle.confirmation.delete', { defaultValue: 'Delete' })
10
+ }
11
11
  }
@@ -1,6 +1,8 @@
1
1
  import LightboxController from './lightbox_controller'
2
2
 
3
3
  export default class extends LightboxController {
4
+ static targets = ["image"]
5
+
4
6
  get options () {
5
7
  return {
6
8
  ...super.options,
@@ -26,8 +26,6 @@ const VideoIframeUrl = {
26
26
  }
27
27
 
28
28
  export default class extends ApplicationController {
29
- static targets = ["image"]
30
-
31
29
  static values = {
32
30
  animationType: { type: String, default: 'zoom' },
33
31
  animationDuration: { type: Number, default: 150 },
@@ -1,3 +1,5 @@
1
+ require "turbo-rails"
2
+
1
3
  module Trestle
2
4
  class Engine < ::Rails::Engine
3
5
  isolate_namespace Trestle
@@ -30,22 +32,6 @@ module Trestle
30
32
  end
31
33
  end
32
34
 
33
- initializer "turbo.mimetype" do
34
- Mime::Type.register "text/vnd.turbo-stream.html", :turbo_stream unless Mime[:turbo_stream]
35
- end
36
-
37
- initializer "turbo.renderer" do
38
- ActiveSupport.on_load(:action_controller) do
39
- # Compatibility fix for Rails 5.2
40
- delegate :media_type, to: "@_response" unless instance_methods.include?(:media_type)
41
-
42
- ActionController::Renderers.add :turbo_stream do |turbo_streams_html, options|
43
- self.content_type = Mime[:turbo_stream] if media_type.nil?
44
- turbo_streams_html
45
- end
46
- end
47
- end
48
-
49
35
  config.to_prepare do
50
36
  Engine.reset_helpers!
51
37
  end
@@ -55,6 +41,22 @@ module Trestle
55
41
  reloader.install(app) unless app.config.eager_load
56
42
  end
57
43
 
44
+ # For compatibility with the `sassc-rails`` gem, register a custom compressor that excludes the
45
+ # Trestle admin stylesheets as a) they are already minimized and b) libsass is not compatible with
46
+ # some of the newer CSS syntax that is used.
47
+ #
48
+ # To avoid this being necessary, it is recommended that either
49
+ # 1) `sassc-rails` is removed from the Gemfile (if not required),
50
+ # 2) the `sassc-embedded` gem is added to the Gemfile, or
51
+ # 3) `sassc-rails` is replaced with `dartsass-sprockets`
52
+ config.assets.configure do |env|
53
+ if original_compressor = config.assets.css_compressor
54
+ require "trestle/sprockets_compressor"
55
+ original_compressor = Sprockets.compressors['text/css'][original_compressor] if original_compressor.is_a?(Symbol)
56
+ config.assets.css_compressor = Trestle::SprocketsCompressor.new(original_compressor)
57
+ end
58
+ end if defined?(SassC::Rails)
59
+
58
60
  def reset_helpers!
59
61
  @helpers = nil
60
62
  end
@@ -14,7 +14,7 @@ module Trestle
14
14
  include Hook::Helpers
15
15
 
16
16
  # Whitelisted helpers will concatenate their result to the output buffer when called.
17
- WHITELISTED_HELPERS = [:row, :col, :render, :tab, :table, :divider, :h1, :h2, :h3, :h4, :h5, :h6, :card, :panel, :well]
17
+ WHITELISTED_HELPERS = [:row, :col, :render, :tab, :table, :divider, :h1, :h2, :h3, :h4, :h5, :h6, :card, :panel, :well, :turbo_frame_tag]
18
18
 
19
19
  # Raw block helpers will pass their block argument directly to the method without wrapping it in a new output buffer.
20
20
  RAW_BLOCK_HELPERS = [:table, :toolbar]
@@ -5,20 +5,30 @@ module Trestle
5
5
  delegate :admin, :instance, to: :@template
6
6
  delegate :translate, :t, to: :admin
7
7
 
8
- def new
9
- link(t("buttons.new", default: "New %{model_name}"), action: :new, style: :light, icon: "fa fa-plus", class: "btn-new-resource") if action?(:new)
8
+ def new(label: t("buttons.new", default: "New %{model_name}"), **attrs)
9
+ return unless action?(:new)
10
+
11
+ defaults = { action: :new, style: :light, icon: "fa fa-plus", class: "btn-new-resource" }
12
+ link(label, defaults.merge(attrs))
10
13
  end
11
14
 
12
- def save
13
- button(t("buttons.save", default: "Save %{model_name}"), style: :success)
15
+ def save(label: t("buttons.save", default: "Save %{model_name}"), **attrs)
16
+ defaults = { style: :success }
17
+ button(label, defaults.merge(attrs))
14
18
  end
15
19
 
16
- def delete
17
- link(t("buttons.delete", default: "Delete %{model_name}"), instance, action: :destroy, style: :danger, icon: "fa fa-trash", data: { turbo_method: "delete", controller: "confirm-delete", confirm_delete_placement_value: "bottom" }) if action?(:destroy)
20
+ def delete(label: t("buttons.delete", default: "Delete %{model_name}"), **attrs)
21
+ return unless action?(:destroy)
22
+
23
+ defaults = Trestle::Options.new(action: :destroy, style: :danger, icon: "fa fa-trash", data: { turbo_method: "delete", turbo_frame: "_top", controller: "confirm-delete", confirm_delete_placement_value: "bottom" })
24
+ link(label, instance, defaults.merge(attrs))
18
25
  end
19
26
 
20
- def dismiss
21
- button(t("buttons.ok", default: "OK"), style: :light, data: { bs_dismiss: "modal" }) if @template.modal_request?
27
+ def dismiss(label: t("buttons.ok", default: "OK"), **attrs)
28
+ return unless @template.modal_request?
29
+
30
+ defaults = Trestle::Options.new(type: :button, style: :light, data: { bs_dismiss: "modal" })
31
+ button(label, defaults.merge(attrs))
22
32
  end
23
33
  alias ok dismiss
24
34
 
@@ -0,0 +1,16 @@
1
+ module Trestle
2
+ class SprocketsCompressor
3
+ def initialize(original_compressor, excluded_files: ["trestle/admin"])
4
+ @original_compressor = original_compressor
5
+ @excluded_files = excluded_files
6
+ end
7
+
8
+ def call(input)
9
+ if @excluded_files.include?(input[:name])
10
+ input[:data]
11
+ else
12
+ @original_compressor.call(input)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -21,11 +21,10 @@ module Trestle
21
21
  end
22
22
 
23
23
  private
24
- def respond_to_missing?(name, include_all=false)
25
- builder.respond_to?(name) || super
26
- end
24
+ def self.ruby2_keywords(*)
25
+ end unless respond_to?(:ruby2_keywords, true)
27
26
 
28
- def method_missing(name, *args, &block)
27
+ ruby2_keywords def method_missing(name, *args, &block)
29
28
  result = builder.send(name, *args, &block)
30
29
 
31
30
  if builder.builder_methods.include?(name)
@@ -34,6 +33,10 @@ module Trestle
34
33
  result
35
34
  end
36
35
  end
36
+
37
+ def respond_to_missing?(name, include_all=false)
38
+ builder.respond_to?(name) || super
39
+ end
37
40
  end
38
41
  end
39
42
  end