trestle 0.8.7 → 0.8.8

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/app/assets/javascripts/trestle/components/_datepicker.js +18 -3
  4. data/app/assets/javascripts/trestle/components/_dialog.js +5 -1
  5. data/app/assets/javascripts/trestle/components/_form.js +3 -1
  6. data/app/assets/javascripts/trestle/core/_l10n.js +23 -0
  7. data/app/assets/stylesheets/trestle/components/_avatar.scss +23 -0
  8. data/app/assets/stylesheets/trestle/components/_datepicker.scss +28 -0
  9. data/app/assets/stylesheets/trestle/components/_input-group.scss +18 -0
  10. data/app/helpers/trestle/avatar_helper.rb +7 -2
  11. data/app/helpers/trestle/debug_helper.rb +1 -1
  12. data/app/helpers/trestle/form_helper.rb +1 -1
  13. data/app/helpers/trestle/i18n_helper.rb +14 -0
  14. data/app/helpers/trestle/tab_helper.rb +2 -2
  15. data/app/helpers/trestle/url_helper.rb +37 -9
  16. data/app/views/layouts/trestle/admin.html.erb +1 -3
  17. data/app/views/trestle/application/_layout.html.erb +1 -1
  18. data/app/views/trestle/application/_tabs.html.erb +1 -1
  19. data/app/views/trestle/{application → flash}/_alert.html.erb +2 -2
  20. data/app/views/trestle/flash/_debug.html.erb +8 -0
  21. data/app/views/trestle/flash/_flash.html.erb +7 -0
  22. data/app/views/trestle/resource/edit.html.erb +5 -5
  23. data/app/views/trestle/resource/index.html.erb +2 -2
  24. data/app/views/trestle/resource/new.html.erb +4 -4
  25. data/app/views/trestle/resource/show.html.erb +5 -5
  26. data/app/views/trestle/shared/_sidebar.html.erb +2 -2
  27. data/config/locales/cs.rb +18 -0
  28. data/config/locales/cs.yml +95 -0
  29. data/config/locales/en.yml +43 -22
  30. data/config/locales/fr.yml +37 -22
  31. data/config/locales/nl.yml +37 -22
  32. data/config/locales/pl.yml +37 -22
  33. data/config/locales/pt-BR.yml +37 -22
  34. data/config/locales/zh-CN.rb +18 -0
  35. data/config/locales/zh-CN.yml +94 -0
  36. data/gemfiles/rails-5.2.gemfile +14 -0
  37. data/lib/trestle/adapters/adapter.rb +3 -3
  38. data/lib/trestle/admin.rb +30 -2
  39. data/lib/trestle/admin/builder.rb +17 -7
  40. data/lib/trestle/breadcrumb.rb +3 -1
  41. data/lib/trestle/configurable.rb +6 -0
  42. data/lib/trestle/configuration.rb +7 -1
  43. data/lib/trestle/engine.rb +5 -1
  44. data/lib/trestle/form/fields/date_picker.rb +2 -2
  45. data/lib/trestle/form/fields/form_group.rb +1 -1
  46. data/lib/trestle/resource.rb +38 -3
  47. data/lib/trestle/resource/builder.rb +10 -0
  48. data/lib/trestle/resource/controller.rb +36 -22
  49. data/lib/trestle/tab.rb +4 -0
  50. data/lib/trestle/table/column.rb +4 -4
  51. data/lib/trestle/table/row.rb +1 -1
  52. data/lib/trestle/version.rb +1 -1
  53. data/vendor/assets/javascripts/trestle/flatpickr.js.erb +2 -0
  54. metadata +12 -4
  55. data/app/views/trestle/application/_flash.html.erb +0 -25
@@ -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
@@ -83,13 +83,19 @@ module Trestle
83
83
  end
84
84
 
85
85
  # List of i18n keys to pass into the Trestle.i18n JavaScript object
86
- option :javascript_i18n_keys, ["admin.confirmation.title", "admin.confirmation.delete", "admin.confirmation.cancel", "trestle.dialog.error", "admin.buttons.ok"]
86
+ option :javascript_i18n_keys, [
87
+ "trestle.confirmation.title", "trestle.confirmation.delete", "trestle.confirmation.cancel", "trestle.dialog.error",
88
+ "admin.buttons.ok", "admin.datepicker.formats.date", "admin.datepicker.formats.datetime", "admin.datepicker.formats.time"
89
+ ]
87
90
 
88
91
  # List of load paths for where to find admin definitions
89
92
  option :load_paths, [
90
93
  -> { ActiveSupport::Dependencies.autoload_paths.grep(/\/app\/admin\Z/) }
91
94
  ]
92
95
 
96
+ # When to reload Trestle admin within a to_prepare block (`:always` or `:on_update`)
97
+ option :reload, :on_update
98
+
93
99
 
94
100
  ## Debugging
95
101
 
@@ -35,7 +35,11 @@ module Trestle
35
35
  end
36
36
 
37
37
  config.to_prepare do
38
- Engine.reloader.execute_if_updated
38
+ if Trestle.config.reload == :always
39
+ Engine.reloader.execute
40
+ else
41
+ Engine.reloader.execute_if_updated
42
+ end
39
43
  end
40
44
 
41
45
  def reloader
@@ -1,7 +1,7 @@
1
1
  module Trestle::Form::Fields::DatePicker
2
2
  def extract_options!
3
- options[:prepend] ||= options.key?(:icon) ? options.delete(:icon) : default_icon
4
- options.merge!(data: { picker: options.key?(:picker) ? options.delete(:picker) : true })
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
@@ -9,7 +9,7 @@ module Trestle
9
9
 
10
10
  content_tag(:div, options.except(*WRAPPER_OPTIONS)) do
11
11
  concat label unless options[:label] == false
12
- concat block.call if block
12
+ concat template.capture(&block) if block
13
13
  concat help_message if options[:help]
14
14
  concat error_message if errors.any?
15
15
  end
@@ -99,19 +99,48 @@ module Trestle
99
99
  @actions ||= (readonly? ? READONLY_ACTIONS : RESOURCE_ACTIONS).dup
100
100
  end
101
101
 
102
+ def root_action
103
+ singular? ? :show : :index
104
+ end
105
+
102
106
  def readonly?
103
107
  options[:readonly]
104
108
  end
105
109
 
106
- def default_breadcrumb
107
- Breadcrumb.new(I18n.t("admin.breadcrumbs.#{admin_name}", default: model_name.plural.titleize), path)
110
+ def singular?
111
+ options[:singular]
112
+ end
113
+
114
+ def translate(key, options={})
115
+ super(key, options.merge({
116
+ model_name: model_name.titleize,
117
+ lowercase_model_name: model_name.downcase,
118
+ pluralized_model_name: model_name.plural.titleize
119
+ }))
120
+ end
121
+ alias t translate
122
+
123
+ def instance_path(instance, options={})
124
+ action = options.fetch(:action) { :show }
125
+ options = options.merge(id: to_param(instance)) unless singular?
126
+
127
+ path(action, options)
108
128
  end
109
129
 
110
130
  def routes
111
131
  admin = self
112
132
 
133
+ resource_method = singular? ? :resource : :resources
134
+ resource_name = admin_name
135
+ resource_options = {
136
+ controller: controller_namespace,
137
+ as: route_name,
138
+ path: options[:path],
139
+ except: (RESOURCE_ACTIONS - actions)
140
+ }
141
+
113
142
  Proc.new do
114
- resources admin.admin_name, controller: admin.controller_namespace, as: admin.route_name, path: admin.options[:path], except: (RESOURCE_ACTIONS - admin.actions) do
143
+ public_send(resource_method, resource_name, resource_options) do
115
144
  instance_exec(&admin.additional_routes) if admin.additional_routes
116
145
  end
117
146
  end
@@ -125,6 +154,12 @@ module Trestle
125
154
  Resource::Builder.build(self, &block)
126
155
  end
127
156
 
157
+ def validate!
158
+ if singular? && find_instance_block.nil?
159
+ raise NotImplementedError, "Singular resources must define an instance block."
160
+ end
161
+ end
162
+
128
163
  private
129
164
  def infer_model_class
130
165
  parent.const_get(admin_name.classify)
@@ -99,6 +99,16 @@ module Trestle
99
99
  admin.return_locations[action.to_sym] = block
100
100
  end
101
101
  end
102
+
103
+ protected
104
+ def normalize_table_options(name, options)
105
+ if name.is_a?(Hash)
106
+ # Default index table
107
+ name, options = :index, name.reverse_merge(sortable: true)
108
+ end
109
+
110
+ [name, options.reverse_merge(admin: admin)]
111
+ end
102
112
  end
103
113
  end
104
114
  end
@@ -1,6 +1,9 @@
1
1
  module Trestle
2
2
  class Resource
3
3
  class Controller < Admin::Controller
4
+ before_action :load_collection, only: [:index]
5
+ before_action :load_instance, only: [:show, :edit, :update, :destroy]
6
+
4
7
  def index
5
8
  respond_to do |format|
6
9
  format.html
@@ -10,7 +13,7 @@ module Trestle
10
13
  end
11
14
 
12
15
  def new
13
- self.instance = admin.build_instance({}, params)
16
+ self.instance = admin.build_instance(params.key?(admin.parameter_name) ? permitted_params : {}, params)
14
17
 
15
18
  respond_to do |format|
16
19
  format.html
@@ -25,16 +28,16 @@ module Trestle
25
28
  if admin.save_instance(instance)
26
29
  respond_to do |format|
27
30
  format.html do
28
- flash[:message] = flash_message("success.create", default: "The %{lowercase_model_name} was successfully created.")
29
- redirect_to_return_location(:create, instance, default: admin.path(:show, id: admin.to_param(instance)))
31
+ flash[:message] = flash_message("create.success", title: "Success!", message: "The %{lowercase_model_name} was successfully created.")
32
+ redirect_to_return_location(:create, instance, default: admin.instance_path(instance))
30
33
  end
31
- format.json { render json: instance, status: :created, location: { action: :show, id: admin.to_param(instance) } }
34
+ format.json { render json: instance, status: :created, location: admin.instance_path(instance) }
32
35
  format.js
33
36
  end
34
37
  else
35
38
  respond_to do |format|
36
39
  format.html do
37
- flash.now[:error] = flash_message("failure.create", default: "Please correct the errors below.")
40
+ flash.now[:error] = flash_message("create.failure", title: "Warning!", message: "Please correct the errors below.")
38
41
  render "new", status: :unprocessable_entity
39
42
  end
40
43
  format.json { render json: instance.errors, status: :unprocessable_entity }
@@ -44,10 +47,18 @@ module Trestle
44
47
  end
45
48
 
46
49
  def show
47
- respond_to do |format|
48
- format.html
49
- format.json { render json: instance }
50
- format.js
50
+ if admin.singular? && instance.nil?
51
+ respond_to do |format|
52
+ format.html { redirect_to action: :new }
53
+ format.json { head :not_found }
54
+ format.js
55
+ end
56
+ else
57
+ respond_to do |format|
58
+ format.html
59
+ format.json { render json: instance }
60
+ format.js
61
+ end
51
62
  end
52
63
  end
53
64
 
@@ -60,8 +71,8 @@ module Trestle
60
71
  if admin.save_instance(instance)
61
72
  respond_to do |format|
62
73
  format.html do
63
- flash[:message] = flash_message("success.update", default: "The %{lowercase_model_name} was successfully updated.")
64
- redirect_to_return_location(:update, instance, default: admin.path(:show, id: admin.to_param(instance)))
74
+ flash[:message] = flash_message("update.success", title: "Success!", message: "The %{lowercase_model_name} was successfully updated.")
75
+ redirect_to_return_location(:update, instance, default: admin.instance_path(instance))
65
76
  end
66
77
  format.json { render json: instance, status: :ok }
67
78
  format.js
@@ -69,7 +80,7 @@ module Trestle
69
80
  else
70
81
  respond_to do |format|
71
82
  format.html do
72
- flash.now[:error] = flash_message("failure.update", default: "Please correct the errors below.")
83
+ flash.now[:error] = flash_message("update.failure", title: "Warning!", message: "Please correct the errors below.")
73
84
  render "show", status: :unprocessable_entity
74
85
  end
75
86
  format.json { render json: instance.errors, status: :unprocessable_entity }
@@ -84,13 +95,13 @@ module Trestle
84
95
  respond_to do |format|
85
96
  format.html do
86
97
  if success
87
- flash[:message] = flash_message("success.destroy", default: "The %{lowercase_model_name} was successfully deleted.")
98
+ flash[:message] = flash_message("destroy.success", title: "Success!", message: "The %{lowercase_model_name} was successfully deleted.")
88
99
  redirect_to_return_location(:destroy, instance, default: admin.path(:index))
89
100
  else
90
- flash[:error] = flash_message("failure.destroy", default: "Could not delete %{lowercase_model_name}.")
101
+ flash[:error] = flash_message("destroy.failure", title: "Warning!", message: "Could not delete %{lowercase_model_name}.")
91
102
 
92
103
  if self.instance = admin.find_instance(params)
93
- redirect_to_return_location(:update, instance, default: admin.path(:show, id: admin.to_param(instance)))
104
+ redirect_to_return_location(:update, instance, default: admin.instance_path(instance))
94
105
  else
95
106
  redirect_to_return_location(:destroy, instance, default: admin.path(:index))
96
107
  end
@@ -102,19 +113,22 @@ module Trestle
102
113
  end
103
114
 
104
115
  protected
105
- def instance
106
- @instance ||= admin.find_instance(params)
116
+ def load_instance
117
+ self.instance = admin.find_instance(params)
107
118
  end
108
119
 
109
- def collection
110
- @collection ||= admin.prepare_collection(params)
120
+ def load_collection
121
+ self.collection = admin.prepare_collection(params)
111
122
  end
112
123
 
113
- attr_writer :instance, :collection
124
+ attr_accessor :instance, :collection
114
125
  helper_method :instance, :collection
115
126
 
116
- def flash_message(type, options={})
117
- t("trestle.flash.#{type}", options.merge(model_name: admin.model_name, lowercase_model_name: admin.model_name.downcase))
127
+ def flash_message(type, title:, message:)
128
+ {
129
+ title: admin.t("flash.#{type}.title", default: title),
130
+ message: admin.t("flash.#{type}.message", default: message)
131
+ }
118
132
  end
119
133
 
120
134
  def permitted_params
data/lib/trestle/tab.rb CHANGED
@@ -8,6 +8,10 @@ module Trestle
8
8
  @name, @options = name, options
9
9
  end
10
10
 
11
+ def id(tag=nil)
12
+ ["tab", tag, name].compact.join("-")
13
+ end
14
+
11
15
  def label
12
16
  safe_join([options[:label] || I18n.t("admin.tabs.#{name}", default: name.to_s.titleize), badge].compact, " ")
13
17
  end
@@ -32,9 +32,9 @@ module Trestle
32
32
  if options[:header]
33
33
  options[:header]
34
34
  elsif table.admin
35
- table.admin.human_attribute_name(field)
35
+ table.admin.t("table.headers.#{field}", default: table.admin.human_attribute_name(field))
36
36
  else
37
- field.to_s.humanize.titleize
37
+ I18n.t("admin.table.headers.#{field}", default: field.to_s.humanize.titleize)
38
38
  end
39
39
  end
40
40
 
@@ -50,9 +50,9 @@ module Trestle
50
50
  end
51
51
 
52
52
  def header
53
- return if options.has_key?(:header) && options[:header].in?([nil, false])
53
+ return if options.key?(:header) && options[:header].in?([nil, false])
54
54
 
55
- header = I18n.t("admin.table.headers.#{@column.field}", default: @column.header)
55
+ header = @column.header
56
56
  header = @template.sort_link(header, @column.sort_field, @column.sort_options) if @column.sortable?
57
57
  header
58
58
  end
@@ -32,7 +32,7 @@ module Trestle
32
32
  def options(instance)
33
33
  options = Trestle::Options.new
34
34
 
35
- if table.admin && table.autolink?
35
+ if table.admin && table.autolink? && table.admin.actions.include?(:show)
36
36
  options.merge!(data: { url: admin_url_for(instance) })
37
37
  options.merge!(data: { behavior: "dialog" }) if table.admin.form.dialog?
38
38
  end
@@ -1,3 +1,3 @@
1
1
  module Trestle
2
- VERSION = "0.8.7"
2
+ VERSION = "0.8.8"
3
3
  end
@@ -1,5 +1,7 @@
1
1
  //= require trestle/flatpickr/dist/flatpickr
2
2
 
3
+ <% flatpickr_locale_conversions = { ca: "cat", el: "gr", nb: "no", vi: "vn" } %>
3
4
  <% I18n.available_locales.each do |locale| %>
5
+ <% locale = flatpickr_locale_conversions[locale] if flatpickr_locale_conversions.key?(locale) %>
4
6
  <% require_asset("trestle/flatpickr/dist/l10n/#{locale}") rescue nil %>
5
7
  <% end %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trestle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.7
4
+ version: 0.8.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Pohlenz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-20 00:00:00.000000000 Z
11
+ date: 2018-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -210,6 +210,7 @@ files:
210
210
  - app/assets/javascripts/trestle/core/_contexts.js
211
211
  - app/assets/javascripts/trestle/core/_cookies.js
212
212
  - app/assets/javascripts/trestle/core/_events.js
213
+ - app/assets/javascripts/trestle/core/_l10n.js
213
214
  - app/assets/javascripts/trestle/core/_visit.js
214
215
  - app/assets/javascripts/trestle/custom.js
215
216
  - app/assets/stylesheets/trestle/_custom.scss
@@ -264,6 +265,7 @@ files:
264
265
  - app/helpers/trestle/grid_helper.rb
265
266
  - app/helpers/trestle/headings_helper.rb
266
267
  - app/helpers/trestle/hook_helper.rb
268
+ - app/helpers/trestle/i18n_helper.rb
267
269
  - app/helpers/trestle/icon_helper.rb
268
270
  - app/helpers/trestle/navigation_helper.rb
269
271
  - app/helpers/trestle/pagination_helper.rb
@@ -283,14 +285,15 @@ files:
283
285
  - app/views/kaminari/trestle/_paginator.html.erb
284
286
  - app/views/layouts/trestle/admin.html.erb
285
287
  - app/views/trestle/admin/index.html.erb
286
- - app/views/trestle/application/_alert.html.erb
287
288
  - app/views/trestle/application/_dialog.html.erb
288
- - app/views/trestle/application/_flash.html.erb
289
289
  - app/views/trestle/application/_header.html.erb
290
290
  - app/views/trestle/application/_layout.html.erb
291
291
  - app/views/trestle/application/_tabs.html.erb
292
292
  - app/views/trestle/application/_utilities.html.erb
293
293
  - app/views/trestle/dashboard/index.html.erb
294
+ - app/views/trestle/flash/_alert.html.erb
295
+ - app/views/trestle/flash/_debug.html.erb
296
+ - app/views/trestle/flash/_flash.html.erb
294
297
  - app/views/trestle/resource/_form.html.erb
295
298
  - app/views/trestle/resource/_scopes.html.erb
296
299
  - app/views/trestle/resource/_table.html.erb
@@ -306,6 +309,8 @@ files:
306
309
  - bin/console
307
310
  - bin/setup
308
311
  - bower.json
312
+ - config/locales/cs.rb
313
+ - config/locales/cs.yml
309
314
  - config/locales/en.rb
310
315
  - config/locales/en.yml
311
316
  - config/locales/fr.rb
@@ -316,10 +321,13 @@ files:
316
321
  - config/locales/pl.yml
317
322
  - config/locales/pt-BR.rb
318
323
  - config/locales/pt-BR.yml
324
+ - config/locales/zh-CN.rb
325
+ - config/locales/zh-CN.yml
319
326
  - config/routes.rb
320
327
  - gemfiles/rails-4.2.gemfile
321
328
  - gemfiles/rails-5.0.gemfile
322
329
  - gemfiles/rails-5.1.gemfile
330
+ - gemfiles/rails-5.2.gemfile
323
331
  - gemfiles/rails-edge.gemfile
324
332
  - lib/generators/trestle/admin/admin_generator.rb
325
333
  - lib/generators/trestle/admin/templates/admin.rb.erb
@@ -1,25 +0,0 @@
1
- <% if flash[:message] -%>
2
- <%= render "alert", html_class: "alert-success",
3
- icon: icon("alert-icon ion-ios-checkmark-outline"),
4
- title: t("trestle.flash.success.title", default: "Success!"),
5
- message: flash[:message] %>
6
- <% elsif flash[:error] -%>
7
- <%= render layout: "alert",
8
- locals: {
9
- html_class: "alert-danger",
10
- icon: icon("alert-icon ion-ios-close-outline"),
11
- title: t("trestle.flash.failure.title", default: "Warning!"),
12
- message: flash[:error]
13
- } do %>
14
- <%- if debug_form_errors? -%>
15
- <%= link_to "Debug errors", "#debug-errors", class: "toggle-debug-errors small", data: { toggle: "collapse" } %>
16
- <div id="debug-errors" class="debug-errors collapse">
17
- <ul>
18
- <% instance.errors.each do |key, message| %>
19
- <li class="small"><tt><%= key %>:</tt> <%= message %></li>
20
- <% end %>
21
- </ul>
22
- </div>
23
- <%- end -%>
24
- <% end %>
25
- <% end -%>