trestle 0.9.5 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rspec.yml +28 -0
- data/.gitignore +3 -0
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +9 -2
- data/README.md +6 -1
- data/app/assets/bundle/trestle/bundle.css +7 -7
- data/app/assets/bundle/trestle/bundle.js +40 -38
- data/app/assets/bundle/trestle/fa-brands-400.eot +0 -0
- data/app/assets/bundle/trestle/fa-brands-400.svg +41 -41
- data/app/assets/bundle/trestle/fa-brands-400.ttf +0 -0
- data/app/assets/bundle/trestle/fa-brands-400.woff +0 -0
- data/app/assets/bundle/trestle/fa-brands-400.woff2 +0 -0
- data/app/assets/bundle/trestle/fa-regular-400.eot +0 -0
- data/app/assets/bundle/trestle/fa-regular-400.svg +2 -2
- data/app/assets/bundle/trestle/fa-regular-400.ttf +0 -0
- data/app/assets/bundle/trestle/fa-regular-400.woff +0 -0
- data/app/assets/bundle/trestle/fa-regular-400.woff2 +0 -0
- data/app/assets/bundle/trestle/fa-solid-900.eot +0 -0
- data/app/assets/bundle/trestle/fa-solid-900.svg +13 -7
- data/app/assets/bundle/trestle/fa-solid-900.ttf +0 -0
- data/app/assets/bundle/trestle/fa-solid-900.woff +0 -0
- data/app/assets/bundle/trestle/fa-solid-900.woff2 +0 -0
- data/app/assets/bundle/trestle/flatpickr/ar-dz.js +1 -0
- data/app/assets/bundle/trestle/flatpickr/ar.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/at.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/az.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/be.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/bg.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/bn.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/bs.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/cat.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/ckb.js +1 -0
- data/app/assets/bundle/trestle/flatpickr/cs.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/cy.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/da.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/de.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/default.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/eo.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/es.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/et.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/fa.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/fi.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/fo.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/fr.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/ga.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/gr.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/he.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/hi.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/hr.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/hu.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/hy.js +1 -0
- data/app/assets/bundle/trestle/flatpickr/id.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/is.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/it.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/ja.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/ka.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/km.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/ko.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/kz.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/lt.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/lv.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/mk.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/mn.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/ms.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/my.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/nl.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/nn.js +1 -0
- data/app/assets/bundle/trestle/flatpickr/no.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/pa.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/pl.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/pt.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/ro.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/ru.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/si.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/sk.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/sl.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/sq.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/sr-cyr.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/sr.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/sv.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/th.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/tr.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/uk.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/uz.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/uz_latn.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/vn.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/zh-tw.js +1 -1
- data/app/assets/bundle/trestle/flatpickr/zh.js +1 -1
- data/app/assets/javascripts/trestle/i18n.js.erb +1 -1
- data/app/controllers/trestle/dashboard_controller.rb +2 -2
- data/app/helpers/trestle/avatar_helper.rb +6 -2
- data/app/helpers/trestle/container_helper.rb +12 -4
- data/app/helpers/trestle/params_helper.rb +4 -1
- data/app/helpers/trestle/url_helper.rb +1 -11
- data/app/views/trestle/flash/_alert.html.erb +3 -1
- data/app/views/trestle/flash/_debug.html.erb +13 -8
- data/app/views/trestle/flash/_flash.html.erb +1 -1
- data/config/routes.rb +1 -1
- data/frontend/css/components/_alerts.scss +31 -0
- data/frontend/css/components/_avatar.scss +14 -0
- data/frontend/css/components/_buttons.scss +0 -1
- data/frontend/css/components/_datepicker.scss +1 -0
- data/frontend/css/components/_modal.scss +2 -0
- data/frontend/css/components/_tags.scss +2 -0
- data/frontend/css/components/_timestamp.scss +1 -1
- data/frontend/css/layout/_sidebar.scss +3 -2
- data/frontend/css/variables/_bootstrap.scss +1 -0
- data/frontend/css/variables/_trestle.scss +20 -0
- data/frontend/js/components/dialog.js +8 -3
- data/frontend/theme/trestle/theme/_defaults.scss +4 -4
- data/lib/generators/trestle/install/templates/_theme.scss +1 -1
- data/lib/generators/trestle/install/templates/trestle.rb.erb +8 -2
- data/lib/trestle/adapters/active_record_adapter.rb +16 -0
- data/lib/trestle/configurable.rb +6 -0
- data/lib/trestle/configuration.rb +4 -5
- data/lib/trestle/form/automatic.rb +2 -0
- data/lib/trestle/form/builder.rb +4 -4
- data/lib/trestle/form/field.rb +1 -1
- data/lib/trestle/form/renderer.rb +4 -1
- data/lib/trestle/lazy.rb +56 -0
- data/lib/trestle/navigation/item.rb +1 -1
- data/lib/trestle/registry.rb +61 -0
- data/lib/trestle/reloader.rb +1 -1
- data/lib/trestle/table/automatic.rb +7 -0
- data/lib/trestle/table/column.rb +5 -1
- data/lib/trestle/version.rb +1 -1
- data/lib/trestle.rb +30 -14
- data/package.json +20 -23
- data/webpack.config.js +36 -48
- data/yarn.lock +2817 -4562
- metadata +11 -4
- data/.travis.yml +0 -33
@@ -2,6 +2,6 @@
|
|
2
2
|
<%= render "trestle/flash/alert", html_class: "alert-success", icon: icon("alert-icon far fa-check-circle"), alert: normalize_flash_alert(flash[:message]) %>
|
3
3
|
<% elsif flash[:error] -%>
|
4
4
|
<%= render layout: "trestle/flash/alert", locals: { html_class: "alert-danger", icon: icon("alert-icon far fa-times-circle"), alert: normalize_flash_alert(flash[:error]) } do %>
|
5
|
-
<%= render "trestle/flash/debug" if debug_form_errors? %>
|
5
|
+
<%= render "trestle/flash/debug", errors: instance.errors if debug_form_errors? %>
|
6
6
|
<% end %>
|
7
7
|
<% end -%>
|
data/config/routes.rb
CHANGED
@@ -32,13 +32,18 @@
|
|
32
32
|
|
33
33
|
.alert-icon {
|
34
34
|
margin-right: $alert-padding-x;
|
35
|
+
|
35
36
|
font-size: 40px;
|
37
|
+
width: 40px;
|
38
|
+
|
39
|
+
text-align: center;
|
36
40
|
|
37
41
|
@include media-breakpoint-down(sm) {
|
38
42
|
margin-left: $alert-padding-x * 0.25;
|
39
43
|
margin-right: $alert-padding-x * 0.75;
|
40
44
|
|
41
45
|
font-size: 32px;
|
46
|
+
width: 32px;
|
42
47
|
}
|
43
48
|
}
|
44
49
|
|
@@ -74,10 +79,16 @@
|
|
74
79
|
border-color: $border;
|
75
80
|
|
76
81
|
a {
|
82
|
+
color: $color;
|
83
|
+
|
77
84
|
&:hover, &:focus {
|
78
85
|
color: mix($color, $background, 80%);
|
79
86
|
}
|
80
87
|
}
|
88
|
+
|
89
|
+
code {
|
90
|
+
color: $color;
|
91
|
+
}
|
81
92
|
}
|
82
93
|
|
83
94
|
.alert-success {
|
@@ -88,6 +99,26 @@
|
|
88
99
|
@include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-color);
|
89
100
|
}
|
90
101
|
|
102
|
+
.alert-info {
|
103
|
+
@include alert-variant($alert-info-bg, $alert-info-border, $alert-info-color);
|
104
|
+
}
|
105
|
+
|
106
|
+
.alert-warning {
|
107
|
+
@include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-color);
|
108
|
+
}
|
109
|
+
|
110
|
+
.alert-light {
|
111
|
+
@include alert-variant($alert-light-bg, $alert-light-border, $alert-light-color);
|
112
|
+
}
|
113
|
+
|
114
|
+
.alert-dark {
|
115
|
+
@include alert-variant($alert-dark-bg, $alert-dark-border, $alert-dark-color);
|
116
|
+
}
|
117
|
+
|
118
|
+
.alert-primary {
|
119
|
+
@include alert-variant($alert-primary-bg, $alert-primary-border, $alert-primary-color);
|
120
|
+
}
|
121
|
+
|
91
122
|
|
92
123
|
// Debug errors
|
93
124
|
|
@@ -16,11 +16,13 @@
|
|
16
16
|
height: $header-height;
|
17
17
|
|
18
18
|
display: flex;
|
19
|
-
align-items:
|
19
|
+
align-items: stretch;
|
20
20
|
|
21
21
|
.navbar-toggler {
|
22
22
|
outline: none;
|
23
23
|
|
24
|
+
align-self: center;
|
25
|
+
|
24
26
|
margin-left: $grid-gutter-width / 2;
|
25
27
|
margin-right: $grid-gutter-width / 2;
|
26
28
|
|
@@ -44,7 +46,6 @@
|
|
44
46
|
display: flex;
|
45
47
|
align-items: center;
|
46
48
|
|
47
|
-
height: 100%;
|
48
49
|
padding: 10px 15px;
|
49
50
|
|
50
51
|
font-size: 1.4rem;
|
@@ -101,6 +101,26 @@ $alert-danger-bg: #de7471;
|
|
101
101
|
$alert-danger-color: white;
|
102
102
|
$alert-danger-border: #d85956;
|
103
103
|
|
104
|
+
$alert-info-bg: darken(theme-color("info"), 10%);
|
105
|
+
$alert-info-color: white;
|
106
|
+
$alert-info-border: darken($alert-info-bg, 10%);
|
107
|
+
|
108
|
+
$alert-warning-bg: darken(theme-color("warning"), 5%);
|
109
|
+
$alert-warning-color: white;
|
110
|
+
$alert-warning-border: darken($alert-warning-bg, 5%);
|
111
|
+
|
112
|
+
$alert-light-bg: theme-color("light");
|
113
|
+
$alert-light-color: $body-color;
|
114
|
+
$alert-light-border: darken($alert-light-bg, 5%);
|
115
|
+
|
116
|
+
$alert-dark-bg: theme-color("dark");
|
117
|
+
$alert-dark-color: white;
|
118
|
+
$alert-dark-border: darken($alert-dark-bg, 10%);
|
119
|
+
|
120
|
+
$alert-primary-bg: darken(theme-color("primary"), 5%);
|
121
|
+
$alert-primary-color: white;
|
122
|
+
$alert-primary-border: darken($alert-primary-bg, 10%);
|
123
|
+
|
104
124
|
|
105
125
|
// Modals
|
106
126
|
|
@@ -20,14 +20,19 @@ function createElement () {
|
|
20
20
|
focus: false
|
21
21
|
})
|
22
22
|
|
23
|
-
// Remove dialog elements once hidden
|
24
23
|
$el.on('hidden.bs.modal', function () {
|
24
|
+
// Restore modal-open class on body if background modals still visible
|
25
|
+
if ($el.prevAll('.modal.show').length) {
|
26
|
+
$(document.body).addClass('modal-open')
|
27
|
+
}
|
28
|
+
|
29
|
+
// Remove dialog elements once hidden
|
25
30
|
$el.remove()
|
26
31
|
})
|
27
32
|
|
28
33
|
// Restore the next visible modal to the foreground
|
29
34
|
$el.on('hide.bs.modal', function () {
|
30
|
-
$el.prevAll('.modal.
|
35
|
+
$el.prevAll('.modal.show').last().removeClass('background')
|
31
36
|
})
|
32
37
|
|
33
38
|
// Set X-Trestle-Dialog header on AJAX requests initiated from the dialog
|
@@ -120,7 +125,7 @@ export default class Dialog {
|
|
120
125
|
this.$el.modal('show')
|
121
126
|
|
122
127
|
// Background any existing visible modals
|
123
|
-
this.$el.prevAll('.modal.
|
128
|
+
this.$el.prevAll('.modal.show').addClass('background')
|
124
129
|
}
|
125
130
|
|
126
131
|
hide () {
|
@@ -8,7 +8,7 @@ $theme-colors: (
|
|
8
8
|
$theme-color-interval: 8% !default;
|
9
9
|
|
10
10
|
// The yiq lightness value that determines when the lightness of color changes from "dark" to "light". Acceptable values are between 0 and 255.
|
11
|
-
$yiq-contrasted-threshold:
|
11
|
+
$yiq-contrasted-threshold: 175 !default;
|
12
12
|
|
13
13
|
// Customize the light and dark text colors for use in our YIQ color contrast function.
|
14
14
|
$yiq-text-dark: #212529 !default;
|
@@ -115,9 +115,9 @@ $badge-focus-width: $input-btn-focus-width !default;
|
|
115
115
|
|
116
116
|
// Alerts
|
117
117
|
|
118
|
-
$alert-bg-level:
|
119
|
-
$alert-border-level:
|
120
|
-
$alert-color-level:
|
118
|
+
$alert-bg-level: 2 !default;
|
119
|
+
$alert-border-level: 3 !default;
|
120
|
+
$alert-color-level: -12 !default;
|
121
121
|
|
122
122
|
|
123
123
|
// Progress bars
|
@@ -15,7 +15,7 @@ Trestle.configure do |config|
|
|
15
15
|
#
|
16
16
|
# config.site_logo_small = "logo-small.png"
|
17
17
|
|
18
|
-
#
|
18
|
+
# Specify a favicon to be used within the admin.
|
19
19
|
#
|
20
20
|
# config.favicon = "favicon.ico"
|
21
21
|
|
@@ -70,6 +70,7 @@ Trestle.configure do |config|
|
|
70
70
|
# Specify helper modules to expose to the admin.
|
71
71
|
#
|
72
72
|
# config.helper :all
|
73
|
+
# config.helper -> { CustomHelper }
|
73
74
|
|
74
75
|
# Register callbacks to run before, after or around all Trestle actions.
|
75
76
|
#
|
@@ -103,6 +104,11 @@ Trestle.configure do |config|
|
|
103
104
|
#
|
104
105
|
# config.persistent_params << :query
|
105
106
|
|
107
|
+
# List of methods to try calling on an instance when displayed by the `display` helper.
|
108
|
+
# Defaults to [:display_name, :full_name, :name, :title, :username, :login, :email].
|
109
|
+
#
|
110
|
+
# config.display_methods.unshift(:admin_label)
|
111
|
+
|
106
112
|
# Customize the default adapter class used by all admin resources.
|
107
113
|
# See the documentation on Trestle::Adapters::Adapter for details on
|
108
114
|
# the adapter methods that can be customized.
|
@@ -118,7 +124,7 @@ Trestle.configure do |config|
|
|
118
124
|
# def render; end
|
119
125
|
# end
|
120
126
|
#
|
121
|
-
# config.form_field :custom, CustomFormField
|
127
|
+
# config.form_field :custom, -> { CustomFormField }
|
122
128
|
|
123
129
|
# == Debugging Options
|
124
130
|
#
|
@@ -60,6 +60,8 @@ module Trestle
|
|
60
60
|
Attribute::Association.new(column.name, class: -> { reflection.klass }, name: name, polymorphic: reflection.polymorphic?, type_column: reflection.foreign_type)
|
61
61
|
elsif column.name.end_with?("_type") && (name = column.name.sub(/_type$/, '')) && (reflection = model.reflections[name])
|
62
62
|
# Ignore type columns for polymorphic associations
|
63
|
+
elsif enum_column?(column)
|
64
|
+
Attribute.new(column.name, :enum, values: enum_values(column))
|
63
65
|
else
|
64
66
|
Attribute.new(column.name, column.type, array_column?(column) ? { array: true } : {})
|
65
67
|
end
|
@@ -81,6 +83,20 @@ module Trestle
|
|
81
83
|
def array_column?(column)
|
82
84
|
column.respond_to?(:array?) && column.array?
|
83
85
|
end
|
86
|
+
|
87
|
+
def enum_column?(column)
|
88
|
+
model.defined_enums.key?(column.name)
|
89
|
+
end
|
90
|
+
|
91
|
+
def enum_values(column)
|
92
|
+
model.defined_enums[column.name].map { |key, value|
|
93
|
+
[value, enum_human_name(column, key)]
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
def enum_human_name(column, value)
|
98
|
+
human_attribute_name([column.name.pluralize, value].join("."), default: value.humanize)
|
99
|
+
end
|
84
100
|
end
|
85
101
|
end
|
86
102
|
end
|
data/lib/trestle/configurable.rb
CHANGED
@@ -15,6 +15,12 @@ module Trestle
|
|
15
15
|
options.fetch(name) {
|
16
16
|
if defaults.key?(name)
|
17
17
|
value = defaults[name]
|
18
|
+
|
19
|
+
# Avoid references to the same instance of a default value
|
20
|
+
if value.respond_to?(:dup) && !value.is_a?(Proc)
|
21
|
+
value = value.dup
|
22
|
+
end
|
23
|
+
|
18
24
|
assign(name, value)
|
19
25
|
end
|
20
26
|
}
|
@@ -54,18 +54,17 @@ module Trestle
|
|
54
54
|
menus << Navigation::Block.new(&block)
|
55
55
|
end
|
56
56
|
|
57
|
-
|
58
57
|
## Extension Options
|
59
58
|
|
60
59
|
# [Internal] List of helper modules to include in all Trestle controllers
|
61
|
-
option :helpers,
|
60
|
+
option :helpers, Lazy::List.new
|
62
61
|
|
63
62
|
# [Internal] Container module for block-defined helpers
|
64
63
|
option :helper_module, Module.new
|
65
64
|
|
66
65
|
# Register global helpers available to all Trestle admins
|
67
66
|
def helper(*helpers, &block)
|
68
|
-
self.helpers
|
67
|
+
self.helpers << helpers
|
69
68
|
self.helper_module.module_eval(&block) if block_given?
|
70
69
|
end
|
71
70
|
|
@@ -82,8 +81,8 @@ module Trestle
|
|
82
81
|
option :default_adapter, Adapters.compose(Adapters::ActiveRecordAdapter, Adapters::DraperAdapter)
|
83
82
|
|
84
83
|
# Register a custom form field class
|
85
|
-
def form_field(name,
|
86
|
-
Form::Builder.register(name,
|
84
|
+
def form_field(name, field)
|
85
|
+
Form::Builder.register(name, field)
|
87
86
|
end
|
88
87
|
|
89
88
|
# [Internal] List of registered hooks
|
@@ -32,6 +32,8 @@ module Trestle
|
|
32
32
|
datetime_field attribute.name
|
33
33
|
when :boolean
|
34
34
|
check_box attribute.name
|
35
|
+
when :enum
|
36
|
+
collection_radio_buttons attribute.name, attribute.options[:values] || [], :first, :last
|
35
37
|
when :json, :jsonb
|
36
38
|
value = instance.public_send(attribute.name)
|
37
39
|
text_area attribute.name, value: value.try(:to_json)
|
data/lib/trestle/form/builder.rb
CHANGED
@@ -9,7 +9,7 @@ module Trestle
|
|
9
9
|
undef_method :display
|
10
10
|
|
11
11
|
cattr_accessor :fields
|
12
|
-
self.fields =
|
12
|
+
self.fields = Lazy::Hash.new
|
13
13
|
|
14
14
|
def errors(name)
|
15
15
|
if object.respond_to?(:errors) && object.errors.respond_to?(:[])
|
@@ -19,14 +19,14 @@ module Trestle
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def self.register(name,
|
22
|
+
def self.register(name, field)
|
23
23
|
rename_existing_helper_method(name)
|
24
|
-
self.fields[name] =
|
24
|
+
self.fields[name] = field
|
25
25
|
end
|
26
26
|
|
27
27
|
protected
|
28
28
|
def respond_to_missing?(name, include_all=false)
|
29
|
-
self.class.fields.
|
29
|
+
self.class.fields.key?(name) || super
|
30
30
|
end
|
31
31
|
|
32
32
|
def method_missing(name, *args, &block)
|
data/lib/trestle/form/field.rb
CHANGED
@@ -4,6 +4,9 @@ require "action_view/helpers"
|
|
4
4
|
module Trestle
|
5
5
|
class Form
|
6
6
|
class Renderer
|
7
|
+
def self.ruby2_keywords(*)
|
8
|
+
end unless respond_to?(:ruby2_keywords, true)
|
9
|
+
|
7
10
|
include ::ActionView::Context
|
8
11
|
include ::ActionView::Helpers::CaptureHelper
|
9
12
|
|
@@ -40,7 +43,7 @@ module Trestle
|
|
40
43
|
concat(result)
|
41
44
|
end
|
42
45
|
|
43
|
-
def method_missing(name, *args, &block)
|
46
|
+
ruby2_keywords def method_missing(name, *args, &block)
|
44
47
|
target = @form.respond_to?(name) ? @form : @template
|
45
48
|
|
46
49
|
if block_given? && !RAW_BLOCK_HELPERS.include?(name)
|
data/lib/trestle/lazy.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Trestle
|
2
|
+
module Lazy
|
3
|
+
module Constantize
|
4
|
+
def constantize(value)
|
5
|
+
case value
|
6
|
+
when String
|
7
|
+
value.safe_constantize
|
8
|
+
when Proc
|
9
|
+
value.call
|
10
|
+
else
|
11
|
+
value
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class List
|
17
|
+
include Enumerable
|
18
|
+
include Constantize
|
19
|
+
|
20
|
+
def initialize(*items)
|
21
|
+
@list = items
|
22
|
+
end
|
23
|
+
|
24
|
+
def each(&block)
|
25
|
+
@list.each do |item|
|
26
|
+
yield constantize(item)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def <<(items)
|
31
|
+
@list += Array(items)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Hash
|
36
|
+
include Enumerable
|
37
|
+
include Constantize
|
38
|
+
|
39
|
+
delegate :[]=, :key?, to: :@hash
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
@hash = {}
|
43
|
+
end
|
44
|
+
|
45
|
+
def each(&block)
|
46
|
+
@hash.each do |key, value|
|
47
|
+
yield key, constantize(value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def [](key)
|
52
|
+
constantize(@hash[key])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Trestle
|
2
|
+
class Registry
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
# The admins hash is left exposed for backwards compatibility
|
6
|
+
attr_reader :admins
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
reset!
|
10
|
+
end
|
11
|
+
|
12
|
+
def each(&block)
|
13
|
+
@admins.values.sort_by(&:admin_name).each(&block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset!
|
17
|
+
@admins = {}
|
18
|
+
@models = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def empty?
|
22
|
+
none?
|
23
|
+
end
|
24
|
+
|
25
|
+
def register(admin, register_model: true)
|
26
|
+
@admins[admin.admin_name] = admin
|
27
|
+
|
28
|
+
if register_model && register_admin_for_model_loookup?(admin)
|
29
|
+
@models[admin.model.name] ||= admin
|
30
|
+
end
|
31
|
+
|
32
|
+
admin
|
33
|
+
end
|
34
|
+
|
35
|
+
def lookup_admin(admin)
|
36
|
+
# Given object is already an admin class
|
37
|
+
return admin if admin.is_a?(Class) && admin < Trestle::Admin
|
38
|
+
|
39
|
+
@admins[admin.to_s]
|
40
|
+
end
|
41
|
+
alias lookup lookup_admin
|
42
|
+
|
43
|
+
def lookup_model(model)
|
44
|
+
# Lookup each class in the model's ancestor chain
|
45
|
+
while model
|
46
|
+
admin = @models[model.name]
|
47
|
+
return admin if admin
|
48
|
+
|
49
|
+
model = model.superclass
|
50
|
+
end
|
51
|
+
|
52
|
+
# No admin found
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def register_admin_for_model_loookup?(admin)
|
58
|
+
admin.respond_to?(:model) && !(admin.respond_to?(:singular?) && admin.singular?)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/trestle/reloader.rb
CHANGED
@@ -14,6 +14,13 @@ module Trestle
|
|
14
14
|
case attribute.type
|
15
15
|
when :association
|
16
16
|
Column.new(attribute.association_name, sort: false)
|
17
|
+
when :enum
|
18
|
+
Column.new(attribute.name, align: :center, sort: attribute.name) do |instance|
|
19
|
+
if value = instance.public_send(attribute.name)
|
20
|
+
full_attribute_name = [attribute.name.to_s.pluralize, value].join(".")
|
21
|
+
status_tag(admin.human_attribute_name(full_attribute_name, default: value.humanize))
|
22
|
+
end
|
23
|
+
end
|
17
24
|
else
|
18
25
|
Column.new(attribute.name, link: index.zero?, align: (:center if [:datetime, :boolean].include?(attribute.type)))
|
19
26
|
end
|
data/lib/trestle/table/column.rb
CHANGED
@@ -108,7 +108,7 @@ module Trestle
|
|
108
108
|
|
109
109
|
def column_value(instance)
|
110
110
|
if @column.block
|
111
|
-
if
|
111
|
+
if block_is_legacy_haml?
|
112
112
|
# In order for table column blocks to work properly within Haml templates,
|
113
113
|
# the _hamlout local variable needs to be defined in the scope of the block,
|
114
114
|
# so that the Haml version of the capture method is used. Because we
|
@@ -131,6 +131,10 @@ module Trestle
|
|
131
131
|
instance.send(@column.field)
|
132
132
|
end
|
133
133
|
end
|
134
|
+
|
135
|
+
def block_is_legacy_haml?
|
136
|
+
defined?(Haml) && Haml::Helpers.respond_to?(:block_is_haml?) && Haml::Helpers.block_is_haml?(@column.block)
|
137
|
+
end
|
134
138
|
end
|
135
139
|
end
|
136
140
|
end
|
data/lib/trestle/version.rb
CHANGED