trestle 0.8.7 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
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 -%>