trestle 0.8.4 → 0.8.11
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 +5 -5
- data/.gitignore +4 -0
- data/.travis.yml +14 -1
- data/Gemfile +6 -0
- data/README.md +15 -9
- data/app/assets/javascripts/trestle/admin.js +11 -10
- data/app/assets/javascripts/trestle/components/_confirmation.js +40 -0
- data/app/assets/javascripts/trestle/components/_datepicker.js +37 -0
- data/app/assets/javascripts/trestle/components/_dialog.js +136 -0
- data/app/assets/javascripts/trestle/{_errors.js → components/_errors.js} +2 -2
- data/app/assets/javascripts/trestle/components/_form.js +75 -0
- data/app/assets/javascripts/trestle/{_gallery.js → components/_gallery.js} +3 -3
- data/app/assets/javascripts/trestle/{_select.js → components/_select.js} +2 -2
- data/app/assets/javascripts/trestle/components/_sidebar.js +77 -0
- data/app/assets/javascripts/trestle/{_table.js → components/_table.js} +1 -1
- data/app/assets/javascripts/trestle/components/_tabs.js +25 -0
- data/app/assets/javascripts/trestle/components/_tooltips.js +19 -0
- data/app/assets/javascripts/trestle/core/_contexts.js +13 -0
- data/app/assets/javascripts/trestle/core/_cookies.js +24 -0
- data/app/assets/javascripts/trestle/core/_events.js +39 -0
- data/app/assets/javascripts/trestle/core/_l10n.js +23 -0
- data/app/assets/javascripts/trestle/core/_visit.js +10 -0
- data/app/assets/stylesheets/trestle/components/_alerts.scss +28 -0
- data/app/assets/stylesheets/trestle/components/_avatar.scss +23 -1
- data/app/assets/stylesheets/trestle/components/_breadcrumbs.scss +12 -0
- data/app/assets/stylesheets/trestle/components/_buttons.scss +111 -1
- data/app/assets/stylesheets/trestle/components/_content.scss +53 -21
- data/app/assets/stylesheets/trestle/components/_datepicker.scss +28 -0
- data/app/assets/stylesheets/trestle/components/_fields.scss +17 -0
- data/app/assets/stylesheets/trestle/components/_input-group.scss +26 -1
- data/app/assets/stylesheets/trestle/components/_modal.scss +108 -0
- data/app/assets/stylesheets/trestle/components/_navigation.scss +104 -14
- data/app/assets/stylesheets/trestle/components/_pagination.scss +3 -3
- data/app/assets/stylesheets/trestle/components/_scopes.scss +11 -2
- data/app/assets/stylesheets/trestle/components/_sidebar.scss +3 -2
- data/app/assets/stylesheets/trestle/components/_table.scss +34 -10
- data/app/assets/stylesheets/trestle/components/_tags.scss +9 -0
- data/app/assets/stylesheets/trestle/components/_timestamp.scss +4 -1
- data/app/assets/stylesheets/trestle/components/_toolbars.scss +55 -0
- data/app/assets/stylesheets/trestle/components/_wells.scss +9 -1
- data/app/assets/stylesheets/trestle/core/_defaults.scss +21 -6
- data/app/assets/stylesheets/trestle/core/_layout.scss +8 -0
- data/app/assets/stylesheets/trestle/core/_mixins.scss +11 -0
- data/app/assets/stylesheets/trestle/core/_typography.scss +39 -0
- data/app/controllers/concerns/trestle/controller/breadcrumbs.rb +21 -0
- data/app/controllers/concerns/trestle/controller/callbacks.rb +21 -0
- data/app/controllers/concerns/trestle/controller/dialog.rb +16 -0
- data/app/controllers/concerns/trestle/controller/helpers.rb +18 -0
- data/app/controllers/concerns/trestle/controller/layout.rb +16 -0
- data/app/controllers/concerns/trestle/controller/location.rb +15 -0
- data/app/controllers/trestle/application_controller.rb +6 -30
- data/app/helpers/trestle/avatar_helper.rb +9 -2
- data/app/helpers/trestle/flash_helper.rb +15 -0
- data/app/helpers/trestle/form_helper.rb +8 -5
- data/app/helpers/trestle/format_helper.rb +7 -3
- data/app/helpers/trestle/headings_helper.rb +27 -0
- data/app/helpers/trestle/hook_helper.rb +13 -4
- data/app/helpers/trestle/i18n_helper.rb +14 -0
- data/app/helpers/trestle/panel_helper.rb +24 -0
- data/app/helpers/trestle/tab_helper.rb +2 -2
- data/app/helpers/trestle/table_helper.rb +41 -2
- data/app/helpers/trestle/timestamp_helper.rb +49 -7
- data/app/helpers/trestle/toolbars_helper.rb +34 -0
- data/app/helpers/trestle/url_helper.rb +72 -8
- data/app/views/layouts/trestle/admin.html.erb +3 -5
- data/app/views/trestle/application/_dialog.html.erb +34 -0
- data/app/views/trestle/application/_header.html.erb +22 -20
- data/app/views/trestle/application/_layout.html.erb +1 -1
- data/app/views/trestle/application/_tabs.html.erb +8 -2
- data/app/views/trestle/{application → flash}/_alert.html.erb +7 -2
- data/app/views/trestle/flash/_debug.html.erb +8 -0
- data/app/views/trestle/flash/_flash.html.erb +7 -0
- data/app/views/trestle/resource/_scopes.html.erb +1 -1
- data/app/views/trestle/resource/edit.html.erb +8 -10
- data/app/views/trestle/resource/index.html.erb +16 -4
- data/app/views/trestle/resource/new.html.erb +6 -6
- data/app/views/trestle/resource/show.html.erb +8 -10
- data/app/views/trestle/shared/_sidebar.html.erb +10 -7
- data/app/views/trestle/shared/_title.html.erb +14 -0
- data/app/views/trestle/table/_table.html.erb +4 -6
- data/bower.json +1 -1
- data/config/locales/cs.rb +18 -0
- data/config/locales/cs.yml +95 -0
- data/config/locales/en.yml +65 -36
- data/config/locales/es-MX.yml +94 -0
- data/config/locales/es.yml +94 -0
- data/config/locales/fr.rb +18 -0
- data/config/locales/fr.yml +84 -0
- data/config/locales/lv.rb +18 -0
- data/config/locales/lv.yml +94 -0
- data/config/locales/nl.rb +18 -0
- data/config/locales/nl.yml +82 -0
- data/config/locales/pl.rb +18 -0
- data/config/locales/pl.yml +85 -0
- data/config/locales/pt-BR.rb +18 -0
- data/config/locales/pt-BR.yml +84 -0
- data/config/locales/zh-CN.rb +18 -0
- data/config/locales/zh-CN.yml +94 -0
- data/gemfiles/rails-4.2.gemfile +16 -0
- data/gemfiles/rails-5.0.gemfile +16 -0
- data/gemfiles/rails-5.1.gemfile +16 -0
- data/gemfiles/rails-5.2.gemfile +16 -0
- data/gemfiles/rails-edge.gemfile +17 -0
- data/lib/generators/trestle/install/templates/trestle.rb.erb +18 -2
- data/lib/generators/trestle/resource/templates/admin.rb.erb +2 -2
- data/lib/trestle/adapters/active_record_adapter.rb +2 -6
- data/lib/trestle/adapters/adapter.rb +40 -15
- data/lib/trestle/adapters/sequel_adapter.rb +2 -6
- data/lib/trestle/admin/builder.rb +42 -12
- data/lib/trestle/admin/controller.rb +3 -1
- data/lib/trestle/admin.rb +84 -3
- data/lib/trestle/breadcrumb.rb +16 -1
- data/lib/trestle/configurable.rb +6 -0
- data/lib/trestle/configuration.rb +28 -5
- data/lib/trestle/display.rb +1 -1
- data/lib/trestle/engine.rb +10 -4
- data/lib/trestle/form/automatic.rb +6 -3
- data/lib/trestle/form/builder.rb +5 -1
- data/lib/trestle/form/field.rb +1 -1
- data/lib/trestle/form/fields/date_picker.rb +2 -2
- data/lib/trestle/form/fields/form_control.rb +14 -4
- data/lib/trestle/form/fields/form_group.rb +14 -3
- data/lib/trestle/form/fields/select.rb +5 -1
- data/lib/trestle/form/fields/tag_select.rb +1 -1
- data/lib/trestle/form/renderer.rb +2 -2
- data/lib/trestle/form.rb +7 -3
- data/lib/trestle/hook.rb +27 -0
- data/lib/trestle/model_name.rb +64 -0
- data/lib/trestle/navigation/group.rb +16 -0
- data/lib/trestle/navigation/item.rb +11 -1
- data/lib/trestle/navigation.rb +24 -6
- data/lib/trestle/options.rb +7 -5
- data/lib/trestle/reloader.rb +1 -1
- data/lib/trestle/resource/adapter_methods.rb +62 -0
- data/lib/trestle/resource/builder.rb +43 -17
- data/lib/trestle/resource/collection.rb +68 -0
- data/lib/trestle/resource/controller.rb +70 -33
- data/lib/trestle/resource.rb +97 -105
- data/lib/trestle/scope.rb +13 -3
- data/lib/trestle/tab.rb +4 -0
- data/lib/trestle/table/actions_column.rb +41 -31
- data/lib/trestle/table/automatic.rb +1 -2
- data/lib/trestle/table/builder.rb +2 -2
- data/lib/trestle/table/column.rb +40 -9
- data/lib/trestle/table/row.rb +18 -2
- data/lib/trestle/table.rb +18 -2
- data/lib/trestle/toolbar/builder.rb +52 -0
- data/lib/trestle/toolbar/context.rb +39 -0
- data/lib/trestle/toolbar.rb +43 -0
- data/lib/trestle/version.rb +1 -1
- data/lib/trestle.rb +9 -4
- data/trestle.gemspec +5 -3
- data/vendor/assets/bower_components/trestle/select2/dist/js/select2.full.js +90 -69
- data/vendor/assets/javascripts/trestle/flatpickr.js.erb +2 -0
- data/vendor/assets/stylesheets/trestle/magnific-popup.scss +13 -1
- metadata +99 -22
- data/app/assets/javascripts/trestle/_confirmation.js +0 -23
- data/app/assets/javascripts/trestle/_datepicker.js +0 -22
- data/app/assets/javascripts/trestle/_form.js +0 -6
- data/app/assets/javascripts/trestle/_sidebar.js +0 -52
- data/app/assets/javascripts/trestle/_tabs.js +0 -13
- data/app/assets/javascripts/trestle/_tooltips.js +0 -3
- data/app/helpers/trestle/title_helper.rb +0 -26
- data/app/views/trestle/application/_flash.html.erb +0 -11
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
group :test do
|
|
4
|
+
gem 'coveralls', require: false
|
|
5
|
+
gem 'simplecov', require: false
|
|
6
|
+
|
|
7
|
+
gem 'capybara'
|
|
8
|
+
gem 'capybara-selenium'
|
|
9
|
+
gem 'selenium-webdriver'
|
|
10
|
+
gem 'chromedriver-helper'
|
|
11
|
+
gem 'puma'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
gem 'rails', github: 'rails/rails'
|
|
15
|
+
gem 'arel', github: 'rails/arel'
|
|
16
|
+
|
|
17
|
+
gemspec :path => "../"
|
|
@@ -20,6 +20,11 @@ Trestle.configure do |config|
|
|
|
20
20
|
#
|
|
21
21
|
# config.footer = "Powered by Trestle"
|
|
22
22
|
|
|
23
|
+
# Sets the default precision for timestamps (either :minutes or :seconds).
|
|
24
|
+
# Defaults to :minutes.
|
|
25
|
+
#
|
|
26
|
+
# config.timestamp_precision = :minutes
|
|
27
|
+
|
|
23
28
|
# == Mounting Options
|
|
24
29
|
#
|
|
25
30
|
# Set the path at which to mount the Trestle admin. Defaults to /admin.
|
|
@@ -33,10 +38,15 @@ Trestle.configure do |config|
|
|
|
33
38
|
|
|
34
39
|
# == Navigation Options
|
|
35
40
|
#
|
|
41
|
+
# Set the path to consider the application root (for title links and breadcrumbs).
|
|
42
|
+
# Defaults to the same value as `config.path`.
|
|
43
|
+
#
|
|
44
|
+
# config.root = "/"
|
|
45
|
+
|
|
36
46
|
# Set the initial breadcrumbs to display in the breadcrumb trail.
|
|
37
|
-
# Defaults to a breadcrumb labeled 'Home' linking to to the
|
|
47
|
+
# Defaults to a breadcrumb labeled 'Home' linking to to the application root.
|
|
38
48
|
#
|
|
39
|
-
# config.root_breadcrumbs = -> { [Trestle::Breadcrumb.new("Home", Trestle.config.
|
|
49
|
+
# config.root_breadcrumbs = -> { [Trestle::Breadcrumb.new("Home", Trestle.config.root)] }
|
|
40
50
|
|
|
41
51
|
# Set the default icon class to use when it is not explicitly provided.
|
|
42
52
|
# Defaults to "fa fa-arrow-circle-o-right".
|
|
@@ -105,4 +115,10 @@ Trestle.configure do |config|
|
|
|
105
115
|
# end
|
|
106
116
|
#
|
|
107
117
|
# config.form_field :custom, CustomFormField
|
|
118
|
+
|
|
119
|
+
# == Debugging Options
|
|
120
|
+
#
|
|
121
|
+
# Enable debugging of form errors. Defaults to true in development mode.
|
|
122
|
+
#
|
|
123
|
+
# config.debug_form_errors = true
|
|
108
124
|
end
|
|
@@ -13,7 +13,7 @@ Trestle.resource(:<%= plural_name %><% if module? %>, scope: <%= module_name %><
|
|
|
13
13
|
|
|
14
14
|
# Customize the form fields shown on the new/edit views.
|
|
15
15
|
#
|
|
16
|
-
# form do |<%=
|
|
16
|
+
# form do |<%= singular_table_name %>|
|
|
17
17
|
# text_field :name
|
|
18
18
|
#
|
|
19
19
|
# row do
|
|
@@ -30,6 +30,6 @@ Trestle.resource(:<%= plural_name %><% if module? %>, scope: <%= module_name %><
|
|
|
30
30
|
# http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters
|
|
31
31
|
#
|
|
32
32
|
# params do |params|
|
|
33
|
-
# params.require(:<%=
|
|
33
|
+
# params.require(:<%= singular_table_name %>).permit(:name, ...)
|
|
34
34
|
# end
|
|
35
35
|
end
|
|
@@ -17,18 +17,14 @@ module Trestle
|
|
|
17
17
|
instance.assign_attributes(attrs)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def save_instance(instance)
|
|
20
|
+
def save_instance(instance, params={})
|
|
21
21
|
instance.save
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def delete_instance(instance)
|
|
24
|
+
def delete_instance(instance, params={})
|
|
25
25
|
instance.destroy
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def unscope(scope)
|
|
29
|
-
scope.unscoped
|
|
30
|
-
end
|
|
31
|
-
|
|
32
28
|
def merge_scopes(scope, other)
|
|
33
29
|
scope.merge(other)
|
|
34
30
|
end
|
|
@@ -4,8 +4,9 @@ module Trestle
|
|
|
4
4
|
attr_reader :admin
|
|
5
5
|
delegate :model, to: :admin
|
|
6
6
|
|
|
7
|
-
def initialize(admin)
|
|
7
|
+
def initialize(admin, context=nil)
|
|
8
8
|
@admin = admin
|
|
9
|
+
@context = context
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
# Loads the initial collection for use by the index action.
|
|
@@ -46,21 +47,35 @@ module Trestle
|
|
|
46
47
|
# Saves an instance (used by the create and update actions).
|
|
47
48
|
#
|
|
48
49
|
# instance - The instance to save
|
|
50
|
+
# params - Unfiltered params hash from the controller
|
|
49
51
|
#
|
|
50
52
|
# Returns a boolean indicating the success/fail status of the save.
|
|
51
|
-
def save_instance(instance)
|
|
53
|
+
def save_instance(instance, params={})
|
|
52
54
|
raise NotImplementedError
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
# Deletes an instance (used by the destroy action).
|
|
56
58
|
#
|
|
57
59
|
# instance - The instance to delete
|
|
60
|
+
# params - Unfiltered params hash from the controller
|
|
58
61
|
#
|
|
59
62
|
# Returns a boolean indicating the success/fail status of the deletion.
|
|
60
|
-
def delete_instance(instance)
|
|
63
|
+
def delete_instance(instance, params={})
|
|
61
64
|
raise NotImplementedError
|
|
62
65
|
end
|
|
63
66
|
|
|
67
|
+
# Finalizes a collection so that it can be rendered within the index view.
|
|
68
|
+
#
|
|
69
|
+
# In most cases (e.g. ActiveRecord), no finalization is required. However if you are using a search library then
|
|
70
|
+
# you may need to explicitly execute the search, or access the models via a #records or #objects method.
|
|
71
|
+
#
|
|
72
|
+
# collection - The collection to finalize
|
|
73
|
+
#
|
|
74
|
+
# Returns an enumerable collection of instances.
|
|
75
|
+
def finalize_collection(collection)
|
|
76
|
+
collection
|
|
77
|
+
end
|
|
78
|
+
|
|
64
79
|
# Decorates a collection for rendering by the index view.
|
|
65
80
|
# Decorating is the final step in preparing the collection for the view.
|
|
66
81
|
#
|
|
@@ -82,15 +97,6 @@ module Trestle
|
|
|
82
97
|
instance.id
|
|
83
98
|
end
|
|
84
99
|
|
|
85
|
-
# Unscopes a collection so that it can be merged with other scopes without duplication or interference.
|
|
86
|
-
#
|
|
87
|
-
# scope - The scope to unscope
|
|
88
|
-
#
|
|
89
|
-
# Returns a scope object.
|
|
90
|
-
def unscope(scope)
|
|
91
|
-
scope
|
|
92
|
-
end
|
|
93
|
-
|
|
94
100
|
# Merges scopes together for Trestle scope application and counting.
|
|
95
101
|
#
|
|
96
102
|
# scope - The first scope
|
|
@@ -130,8 +136,10 @@ module Trestle
|
|
|
130
136
|
#
|
|
131
137
|
# Returns a Kaminari-compatible scope corresponding to a single page.
|
|
132
138
|
def paginate(collection, params)
|
|
133
|
-
collection = Kaminari.paginate_array(collection.to_a) unless collection.respond_to?(
|
|
134
|
-
|
|
139
|
+
collection = Kaminari.paginate_array(collection.to_a) unless collection.respond_to?(Kaminari.config.page_method_name)
|
|
140
|
+
per_page = admin.pagination_options[:per]
|
|
141
|
+
|
|
142
|
+
collection.public_send(Kaminari.config.page_method_name, params[:page]).per(per_page)
|
|
135
143
|
end
|
|
136
144
|
|
|
137
145
|
# Filters the submitted form parameters and returns a whitelisted attributes 'hash'
|
|
@@ -144,7 +152,7 @@ module Trestle
|
|
|
144
152
|
#
|
|
145
153
|
# Returns the permitted set of parameters as a ActionController::Parameters object.
|
|
146
154
|
def permitted_params(params)
|
|
147
|
-
params.require(admin.
|
|
155
|
+
params.require(admin.parameter_name).permit!
|
|
148
156
|
end
|
|
149
157
|
|
|
150
158
|
# Produces a human-readable name for a given attribute, applying I18n where appropriate.
|
|
@@ -171,6 +179,23 @@ module Trestle
|
|
|
171
179
|
def default_form_attributes
|
|
172
180
|
raise NotImplementedError
|
|
173
181
|
end
|
|
182
|
+
|
|
183
|
+
protected
|
|
184
|
+
# Missing methods are called on the given context if available.
|
|
185
|
+
#
|
|
186
|
+
# We include private methods as methods such as current_user
|
|
187
|
+
# are usually declared as private or protected.
|
|
188
|
+
def method_missing(name, *args, &block)
|
|
189
|
+
if @context && @context.respond_to?(name, true)
|
|
190
|
+
@context.send(name, *args, &block)
|
|
191
|
+
else
|
|
192
|
+
super
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def respond_to_missing?(name, include_private=false)
|
|
197
|
+
(@context && @context.respond_to?(name, true)) || super
|
|
198
|
+
end
|
|
174
199
|
end
|
|
175
200
|
end
|
|
176
201
|
end
|
|
@@ -26,18 +26,14 @@ module Trestle
|
|
|
26
26
|
instance.set(attrs)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
def save_instance(instance)
|
|
29
|
+
def save_instance(instance, params={})
|
|
30
30
|
instance.save
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
def delete_instance(instance)
|
|
33
|
+
def delete_instance(instance, params={})
|
|
34
34
|
instance.destroy
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
def unscope(scope)
|
|
38
|
-
scope.unfiltered
|
|
39
|
-
end
|
|
40
|
-
|
|
41
37
|
def merge_scopes(scope, other)
|
|
42
38
|
scope.intersect(other)
|
|
43
39
|
end
|
|
@@ -11,23 +11,32 @@ module Trestle
|
|
|
11
11
|
|
|
12
12
|
delegate :helper, :before_action, :after_action, :around_action, to: :@controller
|
|
13
13
|
|
|
14
|
-
def initialize(
|
|
14
|
+
def initialize(admin)
|
|
15
|
+
@admin, @controller = admin, admin.const_get(:AdminController)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.create(name, options={}, &block)
|
|
15
19
|
# Create admin subclass
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
admin = Class.new(admin_class)
|
|
21
|
+
admin.options = options
|
|
18
22
|
|
|
19
23
|
# Define a constant based on the admin name
|
|
20
24
|
scope = options[:scope] || Object
|
|
21
|
-
scope.const_set("#{name.to_s.camelize}Admin",
|
|
25
|
+
scope.const_set("#{name.to_s.camelize}Admin", admin)
|
|
22
26
|
|
|
23
27
|
# Define admin controller class
|
|
24
28
|
# This is done using class_eval rather than Class.new so that the full
|
|
25
29
|
# class name and parent chain is set when Rails' inherited hooks are called.
|
|
26
|
-
|
|
30
|
+
admin.class_eval("class AdminController < #{controller.name}; end")
|
|
27
31
|
|
|
28
32
|
# Set a reference on the controller class to the admin class
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
controller = admin.const_get(:AdminController)
|
|
34
|
+
controller.instance_variable_set("@admin", admin)
|
|
35
|
+
|
|
36
|
+
admin.build(&block)
|
|
37
|
+
admin.validate!
|
|
38
|
+
|
|
39
|
+
admin
|
|
31
40
|
end
|
|
32
41
|
|
|
33
42
|
def menu(*args, &block)
|
|
@@ -38,16 +47,17 @@ module Trestle
|
|
|
38
47
|
end
|
|
39
48
|
end
|
|
40
49
|
|
|
41
|
-
def table(options={}, &block)
|
|
42
|
-
|
|
50
|
+
def table(name_or_options={}, options={}, &block)
|
|
51
|
+
name, options = normalize_table_options(name_or_options, options)
|
|
52
|
+
admin.tables[name] = Table::Builder.build(options, &block)
|
|
43
53
|
end
|
|
44
54
|
|
|
45
|
-
def form(&block)
|
|
46
|
-
admin.form = Form.new(&block)
|
|
55
|
+
def form(options={}, &block)
|
|
56
|
+
admin.form = Form.new(options, &block)
|
|
47
57
|
end
|
|
48
58
|
|
|
49
59
|
def admin(&block)
|
|
50
|
-
@admin.
|
|
60
|
+
@admin.instance_eval(&block) if block_given?
|
|
51
61
|
@admin
|
|
52
62
|
end
|
|
53
63
|
|
|
@@ -59,6 +69,26 @@ module Trestle
|
|
|
59
69
|
def routes(&block)
|
|
60
70
|
@admin.additional_routes = block
|
|
61
71
|
end
|
|
72
|
+
|
|
73
|
+
def breadcrumb(label=nil, path=nil, &block)
|
|
74
|
+
if block_given?
|
|
75
|
+
@admin.breadcrumb = block
|
|
76
|
+
elsif label
|
|
77
|
+
@admin.breadcrumb = -> { Breadcrumb.new(label, path) }
|
|
78
|
+
else
|
|
79
|
+
@admin.breadcrumb = -> { false }
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
protected
|
|
84
|
+
def normalize_table_options(name, options)
|
|
85
|
+
if name.is_a?(Hash)
|
|
86
|
+
# Default index table
|
|
87
|
+
name, options = :index, name
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
[name, options]
|
|
91
|
+
end
|
|
62
92
|
end
|
|
63
93
|
end
|
|
64
94
|
end
|
data/lib/trestle/admin.rb
CHANGED
|
@@ -5,32 +5,93 @@ module Trestle
|
|
|
5
5
|
autoload :Builder
|
|
6
6
|
autoload :Controller
|
|
7
7
|
|
|
8
|
+
delegate :to_param, to: :class
|
|
9
|
+
|
|
10
|
+
def initialize(context=nil)
|
|
11
|
+
@context = context
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Delegate all missing methods to corresponding class method if available
|
|
15
|
+
def method_missing(name, *args, &block)
|
|
16
|
+
if self.class.respond_to?(name)
|
|
17
|
+
self.class.send(name, *args, &block)
|
|
18
|
+
else
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def respond_to_missing?(name, include_private=false)
|
|
24
|
+
self.class.respond_to?(name, include_private) || super
|
|
25
|
+
end
|
|
26
|
+
|
|
8
27
|
class << self
|
|
9
28
|
attr_accessor :menu
|
|
10
29
|
|
|
11
|
-
attr_accessor :table
|
|
12
30
|
attr_accessor :form
|
|
13
31
|
|
|
14
32
|
attr_accessor :additional_routes
|
|
15
33
|
|
|
16
34
|
attr_writer :options
|
|
35
|
+
attr_writer :breadcrumb
|
|
17
36
|
|
|
18
37
|
def options
|
|
19
38
|
@options ||= {}
|
|
20
39
|
end
|
|
21
40
|
|
|
41
|
+
def tables
|
|
42
|
+
@tables ||= {}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Deprecated: Use `tables[:index]` instead
|
|
46
|
+
def table
|
|
47
|
+
tables[:index]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Deprecated: Use `tables[:index]=` instead
|
|
51
|
+
def table=(table)
|
|
52
|
+
tables[:index] = table
|
|
53
|
+
end
|
|
54
|
+
|
|
22
55
|
def breadcrumbs
|
|
23
56
|
Breadcrumb::Trail.new(Array(Trestle.config.root_breadcrumbs) + [breadcrumb])
|
|
24
57
|
end
|
|
25
58
|
|
|
26
59
|
def breadcrumb
|
|
27
|
-
|
|
60
|
+
if @breadcrumb
|
|
61
|
+
Breadcrumb.cast(@breadcrumb.call)
|
|
62
|
+
else
|
|
63
|
+
default_breadcrumb
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def default_breadcrumb
|
|
68
|
+
Breadcrumb.new(human_admin_name, path)
|
|
28
69
|
end
|
|
29
70
|
|
|
30
71
|
def admin_name
|
|
31
72
|
name.underscore.sub(/_admin$/, '')
|
|
32
73
|
end
|
|
33
74
|
|
|
75
|
+
def i18n_key
|
|
76
|
+
admin_name
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def human_admin_name
|
|
80
|
+
I18n.t("admin.breadcrumbs.#{i18n_key}", default: name.demodulize.underscore.sub(/_admin$/, '').titleize)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def translate(key, options={})
|
|
84
|
+
defaults = [:"admin.#{i18n_key}.#{key}", :"admin.#{key}"]
|
|
85
|
+
defaults << options[:default] if options[:default]
|
|
86
|
+
|
|
87
|
+
I18n.t(defaults.shift, options.merge(default: defaults))
|
|
88
|
+
end
|
|
89
|
+
alias t translate
|
|
90
|
+
|
|
91
|
+
def parameter_name
|
|
92
|
+
admin_name.singularize
|
|
93
|
+
end
|
|
94
|
+
|
|
34
95
|
def route_name
|
|
35
96
|
"#{admin_name.tr('/', '_')}_admin"
|
|
36
97
|
end
|
|
@@ -43,10 +104,22 @@ module Trestle
|
|
|
43
104
|
"#{name.underscore}/admin"
|
|
44
105
|
end
|
|
45
106
|
|
|
46
|
-
def path(action
|
|
107
|
+
def path(action=root_action, options={})
|
|
47
108
|
Engine.routes.url_for(options.merge(controller: controller_namespace, action: action, only_path: true))
|
|
48
109
|
end
|
|
49
110
|
|
|
111
|
+
def to_param(*)
|
|
112
|
+
raise NoMethodError, "#to_param called on non-resourceful admin. You may need to explicitly specify the admin."
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def actions
|
|
116
|
+
[:index]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def root_action
|
|
120
|
+
:index
|
|
121
|
+
end
|
|
122
|
+
|
|
50
123
|
def routes
|
|
51
124
|
admin = self
|
|
52
125
|
|
|
@@ -62,6 +135,14 @@ module Trestle
|
|
|
62
135
|
def railtie_routes_url_helpers(include_path_helpers=true)
|
|
63
136
|
Trestle.railtie_routes_url_helpers(include_path_helpers)
|
|
64
137
|
end
|
|
138
|
+
|
|
139
|
+
def build(&block)
|
|
140
|
+
Admin::Builder.build(self, &block)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def validate!
|
|
144
|
+
# No validations by default. This can be overridden in subclasses.
|
|
145
|
+
end
|
|
65
146
|
end
|
|
66
147
|
end
|
|
67
148
|
end
|
data/lib/trestle/breadcrumb.rb
CHANGED
|
@@ -10,11 +10,26 @@ module Trestle
|
|
|
10
10
|
label == other.label && path == other.path
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
def self.cast(obj)
|
|
14
|
+
case obj
|
|
15
|
+
when Breadcrumb
|
|
16
|
+
obj
|
|
17
|
+
when String
|
|
18
|
+
new(obj)
|
|
19
|
+
when Array
|
|
20
|
+
new(*obj)
|
|
21
|
+
when NilClass, false
|
|
22
|
+
nil
|
|
23
|
+
else
|
|
24
|
+
raise ArgumentError, "Unable to cast #{obj.inspect} to Breadcrumb"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
13
28
|
class Trail
|
|
14
29
|
include Enumerable
|
|
15
30
|
|
|
16
31
|
def initialize(breadcrumbs=[])
|
|
17
|
-
@breadcrumbs = Array(breadcrumbs)
|
|
32
|
+
@breadcrumbs = Array(breadcrumbs).compact
|
|
18
33
|
end
|
|
19
34
|
|
|
20
35
|
def ==(other)
|
data/lib/trestle/configurable.rb
CHANGED
|
@@ -17,6 +17,12 @@ module Trestle
|
|
|
17
17
|
@options ||= {}
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
def as_json(options=nil)
|
|
21
|
+
@options.each_with_object({}) do |(k, v), h|
|
|
22
|
+
h[k] = v.as_json(options)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
20
26
|
def inspect
|
|
21
27
|
"#<#{self.class.name || "Anonymous(Trestle::Configurable)"}>"
|
|
22
28
|
end
|
|
@@ -16,6 +16,9 @@ module Trestle
|
|
|
16
16
|
# Text shown in the admin page footer
|
|
17
17
|
option :footer, -> { I18n.t("trestle.footer", default: "Powered by Trestle") }
|
|
18
18
|
|
|
19
|
+
# Default timestamp precision
|
|
20
|
+
option :timestamp_precision, :minutes
|
|
21
|
+
|
|
19
22
|
|
|
20
23
|
## Mounting Options
|
|
21
24
|
|
|
@@ -28,8 +31,11 @@ module Trestle
|
|
|
28
31
|
|
|
29
32
|
## Navigation Options
|
|
30
33
|
|
|
34
|
+
# Path to consider the application root (for title links and breadcrumbs)
|
|
35
|
+
option :root, -> { Trestle.config.path }
|
|
36
|
+
|
|
31
37
|
# Initial breadcrumbs to display in the breadcrumb trail
|
|
32
|
-
option :root_breadcrumbs, -> { [Trestle::Breadcrumb.new(I18n.t("admin.breadcrumbs.home", default: "Home"), Trestle.config.
|
|
38
|
+
option :root_breadcrumbs, -> { [Trestle::Breadcrumb.new(I18n.t("admin.breadcrumbs.home", default: "Home"), Trestle.config.root)] }
|
|
33
39
|
|
|
34
40
|
# Default icon class to use when it is not explicitly provided
|
|
35
41
|
option :default_navigation_icon, "fa fa-arrow-circle-o-right"
|
|
@@ -64,7 +70,7 @@ module Trestle
|
|
|
64
70
|
option :persistent_params, [:sort, :order, :scope]
|
|
65
71
|
|
|
66
72
|
# List of methods to try calling on an instance when displayed by the `display` helper
|
|
67
|
-
option :display_methods, [:display_name, :full_name, :name, :title, :username, :login, :email
|
|
73
|
+
option :display_methods, [:display_name, :full_name, :name, :title, :username, :login, :email]
|
|
68
74
|
|
|
69
75
|
# Default adapter class used by all admin resources
|
|
70
76
|
option :default_adapter, Adapters.compose(Adapters::ActiveRecordAdapter, Adapters::DraperAdapter)
|
|
@@ -78,12 +84,29 @@ module Trestle
|
|
|
78
84
|
option :hooks, Hash.new { |h, k| h[k] = [] }
|
|
79
85
|
|
|
80
86
|
# Register an extension hook
|
|
81
|
-
def hook(name, &block)
|
|
82
|
-
hooks[name.to_s] << block
|
|
87
|
+
def hook(name, options={}, &block)
|
|
88
|
+
hooks[name.to_s] << Hook.new(name.to_s, options, &block)
|
|
83
89
|
end
|
|
84
90
|
|
|
85
91
|
# List of i18n keys to pass into the Trestle.i18n JavaScript object
|
|
86
|
-
option :javascript_i18n_keys, [
|
|
92
|
+
option :javascript_i18n_keys, [
|
|
93
|
+
"trestle.confirmation.title", "trestle.confirmation.delete", "trestle.confirmation.cancel", "trestle.dialog.error",
|
|
94
|
+
"admin.buttons.ok", "admin.datepicker.formats.date", "admin.datepicker.formats.datetime", "admin.datepicker.formats.time"
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
# List of load paths for where to find admin definitions
|
|
98
|
+
option :load_paths, [
|
|
99
|
+
-> { ActiveSupport::Dependencies.autoload_paths.grep(/\/app\/admin\Z/) }
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
# When to reload Trestle admin within a to_prepare block (`:always` or `:on_update`)
|
|
103
|
+
option :reload, :on_update
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
## Debugging
|
|
107
|
+
|
|
108
|
+
# Enable debugging of form errors
|
|
109
|
+
option :debug_form_errors, Rails.env.development?
|
|
87
110
|
|
|
88
111
|
|
|
89
112
|
## Callbacks
|
data/lib/trestle/display.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Trestle
|
|
|
14
14
|
|
|
15
15
|
private
|
|
16
16
|
def display_method
|
|
17
|
-
@display_method ||= Trestle.config.display_methods.find { |m| @instance.respond_to?(m) }
|
|
17
|
+
@display_method ||= Trestle.config.display_methods.find { |m| @instance.respond_to?(m) } || :to_s
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
end
|
data/lib/trestle/engine.rb
CHANGED
|
@@ -7,9 +7,11 @@ module Trestle
|
|
|
7
7
|
config.assets.precompile << "trestle/admin.css" << "trestle/admin.js"
|
|
8
8
|
|
|
9
9
|
# Vendor assets
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
%w(eot svg ttf woff woff2).each do |ext|
|
|
11
|
+
config.assets.precompile << "trestle/bootstrap-sass/assets/fonts/bootstrap/glyphicons-halflings-regular.#{ext}"
|
|
12
|
+
config.assets.precompile << "trestle/font-awesome/fonts/fontawesome-webfont.#{ext}"
|
|
13
|
+
config.assets.precompile << "trestle/ionicons/fonts/ionicons.#{ext}"
|
|
14
|
+
end
|
|
13
15
|
|
|
14
16
|
initializer "trestle.automount" do |app|
|
|
15
17
|
if Trestle.config.automount
|
|
@@ -35,7 +37,11 @@ module Trestle
|
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
config.to_prepare do
|
|
38
|
-
|
|
40
|
+
if Trestle.config.reload == :always
|
|
41
|
+
Engine.reloader.execute
|
|
42
|
+
else
|
|
43
|
+
Engine.reloader.execute_if_updated
|
|
44
|
+
end
|
|
39
45
|
end
|
|
40
46
|
|
|
41
47
|
def reloader
|
|
@@ -2,7 +2,7 @@ module Trestle
|
|
|
2
2
|
class Form
|
|
3
3
|
class Automatic < Form
|
|
4
4
|
def initialize(admin)
|
|
5
|
-
|
|
5
|
+
super() do |instance|
|
|
6
6
|
admin.default_form_attributes.each do |attribute|
|
|
7
7
|
if attribute.array?
|
|
8
8
|
if [:string, :text].include?(attribute.type)
|
|
@@ -13,8 +13,11 @@ module Trestle
|
|
|
13
13
|
when :association
|
|
14
14
|
if attribute.polymorphic?
|
|
15
15
|
static_field attribute.name do
|
|
16
|
-
associated_instance = instance.public_send(attribute.association_name)
|
|
17
|
-
|
|
16
|
+
if associated_instance = instance.public_send(attribute.association_name)
|
|
17
|
+
admin_link_to format_value(associated_instance), associated_instance
|
|
18
|
+
else
|
|
19
|
+
content_tag(:span, I18n.t("admin.format.blank"), class: "blank")
|
|
20
|
+
end
|
|
18
21
|
end
|
|
19
22
|
else
|
|
20
23
|
prompt = I18n.t("admin.form.select.prompt", default: "- Select %{attribute_name} -", attribute_name: admin.human_attribute_name(attribute.association_name))
|
data/lib/trestle/form/builder.rb
CHANGED
data/lib/trestle/form/field.rb
CHANGED
|
@@ -39,7 +39,7 @@ module Trestle
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def extract_options!
|
|
42
|
-
@wrapper = extract_wrapper_options(
|
|
42
|
+
@wrapper = extract_wrapper_options(*Fields::FormGroup::WRAPPER_OPTIONS).merge(options.delete(:wrapper))
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
private
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Trestle::Form::Fields::DatePicker
|
|
2
2
|
def extract_options!
|
|
3
|
-
options[:prepend] ||= options.
|
|
4
|
-
options.
|
|
3
|
+
options[:prepend] ||= options.delete(:icon) { default_icon }
|
|
4
|
+
options.reverse_merge!(data: { picker: options.delete(:picker) { true }, allow_clear: true })
|
|
5
5
|
|
|
6
6
|
super
|
|
7
7
|
end
|