trestle 0.8.9 → 0.8.10

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/trestle/components/_confirmation.js +31 -14
  3. data/app/assets/javascripts/trestle/components/_form.js +19 -15
  4. data/app/assets/javascripts/trestle/components/_tabs.js +1 -1
  5. data/app/assets/stylesheets/trestle/components/_breadcrumbs.scss +12 -0
  6. data/app/assets/stylesheets/trestle/components/_buttons.scss +102 -1
  7. data/app/assets/stylesheets/trestle/components/_content.scss +41 -21
  8. data/app/assets/stylesheets/trestle/components/_input-group.scss +8 -1
  9. data/app/assets/stylesheets/trestle/components/_modal.scss +3 -0
  10. data/app/assets/stylesheets/trestle/components/_pagination.scss +0 -3
  11. data/app/assets/stylesheets/trestle/components/_scopes.scss +11 -2
  12. data/app/assets/stylesheets/trestle/components/_table.scss +34 -10
  13. data/app/assets/stylesheets/trestle/components/_timestamp.scss +4 -1
  14. data/app/assets/stylesheets/trestle/components/_toolbars.scss +55 -0
  15. data/app/assets/stylesheets/trestle/core/_defaults.scss +13 -2
  16. data/app/assets/stylesheets/trestle/core/_mixins.scss +11 -0
  17. data/app/helpers/trestle/form_helper.rb +1 -5
  18. data/app/helpers/trestle/hook_helper.rb +10 -6
  19. data/app/helpers/trestle/timestamp_helper.rb +49 -7
  20. data/app/helpers/trestle/toolbars_helper.rb +34 -0
  21. data/app/views/layouts/trestle/admin.html.erb +2 -2
  22. data/app/views/trestle/application/_dialog.html.erb +8 -10
  23. data/app/views/trestle/application/_header.html.erb +22 -20
  24. data/app/views/trestle/resource/edit.html.erb +4 -6
  25. data/app/views/trestle/resource/index.html.erb +15 -6
  26. data/app/views/trestle/resource/new.html.erb +2 -2
  27. data/app/views/trestle/resource/show.html.erb +4 -6
  28. data/app/views/trestle/shared/_sidebar.html.erb +3 -1
  29. data/app/views/trestle/shared/_title.html.erb +14 -0
  30. data/config/locales/en.yml +2 -0
  31. data/config/locales/es-MX.yml +94 -0
  32. data/config/locales/es.yml +94 -0
  33. data/config/locales/lv.rb +18 -0
  34. data/config/locales/lv.yml +94 -0
  35. data/lib/generators/trestle/install/templates/trestle.rb.erb +12 -2
  36. data/lib/trestle.rb +2 -0
  37. data/lib/trestle/configuration.rb +9 -3
  38. data/lib/trestle/engine.rb +5 -3
  39. data/lib/trestle/form/fields/form_control.rb +14 -4
  40. data/lib/trestle/form/renderer.rb +2 -2
  41. data/lib/trestle/hook.rb +27 -0
  42. data/lib/trestle/table/actions_column.rb +31 -26
  43. data/lib/trestle/table/column.rb +1 -0
  44. data/lib/trestle/toolbar.rb +43 -0
  45. data/lib/trestle/toolbar/builder.rb +52 -0
  46. data/lib/trestle/toolbar/context.rb +39 -0
  47. data/lib/trestle/version.rb +1 -1
  48. metadata +13 -3
  49. data/app/helpers/trestle/title_helper.rb +0 -26
@@ -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.path)] }
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"
@@ -78,8 +84,8 @@ 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
@@ -7,9 +7,11 @@ module Trestle
7
7
  config.assets.precompile << "trestle/admin.css" << "trestle/admin.js"
8
8
 
9
9
  # Vendor assets
10
- config.assets.precompile << %r(trestle/bootstrap-sass/assets/fonts/bootstrap/glyphicons-halflings-regular\.(?:eot|svg|ttf|woff|woff2)$)
11
- config.assets.precompile << %r(trestle/font-awesome/fonts/fontawesome-webfont\.(?:eot|svg|ttf|woff|woff2)$)
12
- config.assets.precompile << %r(trestle/ionicons/fonts/ionicons\.(?:eot|svg|ttf|woff)$)
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
@@ -13,15 +13,23 @@ module Trestle
13
13
  def input_group
14
14
  if @prepend || @append
15
15
  content_tag(:div, class: "input-group") do
16
- concat content_tag(:span, @prepend, class: "input-group-addon") if @prepend
16
+ concat input_group_addon(@prepend) if @prepend
17
17
  concat yield
18
- concat content_tag(:span, @append, class: "input-group-addon") if @append
18
+ concat input_group_addon(@append) if @append
19
19
  end
20
20
  else
21
21
  yield
22
22
  end
23
23
  end
24
24
 
25
+ def input_group_addon(addon)
26
+ if addon[:wrap]
27
+ content_tag(:span, addon[:content], class: "input-group-addon")
28
+ else
29
+ addon[:content]
30
+ end
31
+ end
32
+
25
33
  def defaults
26
34
  super.merge(class: ["form-control"])
27
35
  end
@@ -29,8 +37,10 @@ module Trestle
29
37
  def extract_options!
30
38
  super
31
39
 
32
- @prepend = options.delete(:prepend)
33
- @append = options.delete(:append)
40
+ @prepend = { content: options.delete(:prepend), wrap: true } if options[:prepend]
41
+ @prepend = { content: options.delete(:prepend!), wrap: false } if options[:prepend!]
42
+ @append = { content: options.delete(:append), wrap: true } if options[:append]
43
+ @append = { content: options.delete(:append!), wrap: false } if options[:append!]
34
44
  end
35
45
  end
36
46
  end
@@ -5,11 +5,11 @@ module Trestle
5
5
  include ::ActionView::Helpers::CaptureHelper
6
6
 
7
7
  # Whitelisted helpers will concatenate their result to the output buffer when called.
8
- WHITELISTED_HELPERS = [:row, :col, :render, :tab, :toolbar, :table, :divider, :h1, :h2, :h3, :h4, :h5, :h6, :panel, :well]
8
+ WHITELISTED_HELPERS = [:row, :col, :render, :tab, :table, :divider, :h1, :h2, :h3, :h4, :h5, :h6, :panel, :well]
9
9
 
10
10
  # Raw block helpers will pass their block argument directly to the method
11
11
  # without wrapping it in a new output buffer.
12
- RAW_BLOCK_HELPERS = [:table]
12
+ RAW_BLOCK_HELPERS = [:table, :toolbar]
13
13
 
14
14
  # The #select and #display methods are defined on Kernel. Undefine them so
15
15
  # that they can be delegated to the form builder or template by method_missing.
@@ -0,0 +1,27 @@
1
+ module Trestle
2
+ class Hook
3
+ attr_reader :name, :options, :block
4
+
5
+ def initialize(name, options={}, &block)
6
+ @name, @options, @block = name, options, block
7
+ end
8
+
9
+ def ==(other)
10
+ other.is_a?(self.class) && name == other.name && options == other.options && block == other.block
11
+ end
12
+
13
+ def visible?(context)
14
+ if options[:if]
15
+ context.instance_exec(&options[:if])
16
+ elsif options[:unless]
17
+ !context.instance_exec(&options[:unless])
18
+ else
19
+ true
20
+ end
21
+ end
22
+
23
+ def evaluate(context)
24
+ context.instance_exec(&block)
25
+ end
26
+ end
27
+ end
@@ -1,11 +1,17 @@
1
1
  module Trestle
2
2
  class Table
3
3
  class ActionsColumn
4
- attr_reader :table, :options, :block
4
+ attr_reader :table, :toolbar, :options
5
5
 
6
6
  def initialize(table, options={}, &block)
7
7
  @table, @options = table, options
8
- @block = block_given? ? block : default_actions
8
+ @toolbar = Toolbar.new(ActionsBuilder)
9
+
10
+ if block_given?
11
+ @toolbar.append(&block)
12
+ else
13
+ @toolbar.append(&default_actions)
14
+ end
9
15
  end
10
16
 
11
17
  def renderer(template)
@@ -13,43 +19,46 @@ module Trestle
13
19
  end
14
20
 
15
21
  def default_actions
16
- admin = table.admin
17
-
18
- ->(action) do
19
- action.delete if admin && admin.actions.include?(:destroy)
22
+ ->(toolbar, instance, admin) do
23
+ toolbar.delete if admin && admin.actions.include?(:destroy)
20
24
  end
21
25
  end
22
26
 
23
- class ActionsBuilder
24
- attr_reader :instance
25
-
26
- delegate :table, to: :@column
27
+ class ActionsBuilder < Toolbar::Builder
28
+ attr_reader :instance, :admin
27
29
 
28
- delegate :concat, :icon, :link_to, :admin_url_for, :admin_link_to, to: :@template
30
+ def initialize(template, instance, admin)
31
+ super(template)
29
32
 
30
- def initialize(column, template, instance)
31
- @column, @template, @instance = column, template, instance
33
+ @instance, @admin = instance, admin
32
34
  end
33
35
 
34
36
  def show
35
- button(icon("fa fa-info"), instance, action: :show, class: "btn-info")
37
+ link(t("buttons.show", default: "Show"), instance, admin: admin, action: :show, icon: "fa fa-info", style: :info)
36
38
  end
37
39
 
38
40
  def edit
39
- button(icon("fa fa-pencil"), instance, action: :edit, class: "btn-warning")
41
+ link(t("buttons.edit", default: "Edit"), instance, admin: admin, action: :edit, icon: "fa fa-pencil", style: :warning)
40
42
  end
41
43
 
42
44
  def delete
43
- button(icon("fa fa-trash"), instance, action: :destroy, method: :delete, class: "btn-danger", data: { toggle: "confirm-delete", placement: "left" })
45
+ link(t("buttons.delete", default: "Delete"), instance, admin: admin, action: :destroy, method: :delete, icon: "fa fa-trash", style: :danger, data: { toggle: "confirm-delete", placement: "left" })
44
46
  end
45
47
 
46
- def button(content, instance_or_url, options={})
47
- options[:class] = Array(options[:class])
48
- options[:class] << "btn" unless options[:class].include?("btn")
48
+ builder_method :show, :edit, :delete
49
49
 
50
- concat admin_link_to(content, instance_or_url, options.reverse_merge(admin: table.admin))
50
+ # Disallow button tags within the actions toolbar. Alias to link for backwards compatibility.
51
+ alias button link
52
+
53
+ private
54
+ def translate(key, options={})
55
+ if admin
56
+ admin.translate(key, options)
57
+ else
58
+ I18n.t(:"admin.#{key}", options)
59
+ end
51
60
  end
52
- alias_method :link, :button
61
+ alias t translate
53
62
  end
54
63
 
55
64
  class Renderer < Column::Renderer
@@ -62,11 +71,7 @@ module Trestle
62
71
  end
63
72
 
64
73
  def content(instance)
65
- builder = ActionsBuilder.new(@column, @template, instance)
66
-
67
- @template.with_output_buffer do
68
- @template.instance_exec(builder, &@column.block)
69
- end
74
+ @template.render_toolbar(@column.toolbar, instance, table.admin)
70
75
  end
71
76
  end
72
77
  end
@@ -53,6 +53,7 @@ module Trestle
53
53
  return if options.key?(:header) && options[:header].in?([nil, false])
54
54
 
55
55
  header = @column.header
56
+ header = @template.instance_exec(&header) if header.respond_to?(:call)
56
57
  header = @template.sort_link(header, @column.sort_field, @column.sort_options) if @column.sortable?
57
58
  header
58
59
  end
@@ -0,0 +1,43 @@
1
+ module Trestle
2
+ class Toolbar
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :Builder
6
+ autoload :Context
7
+
8
+ def initialize(builder=Builder)
9
+ @builder = builder
10
+ @blocks = []
11
+ end
12
+
13
+ def groups(template, *args)
14
+ Enumerator.new do |y|
15
+ @blocks.each do |block|
16
+ builder = @builder.new(template, *args)
17
+ block.evaluate(builder, template, y, *args)
18
+ end
19
+ end
20
+ end
21
+
22
+ def append(&block)
23
+ @blocks.push(Block.new(&block))
24
+ end
25
+
26
+ def prepend(&block)
27
+ @blocks.unshift(Block.new(&block))
28
+ end
29
+
30
+ # Wraps a toolbar block to provide evaluation within the context of a template and enumerator
31
+ class Block
32
+ def initialize(&block)
33
+ @block = block
34
+ end
35
+
36
+ def evaluate(builder, template, enumerator, *args)
37
+ context = Context.new(builder, enumerator, *args)
38
+ result = template.capture { template.instance_exec(context, *args, &@block) }
39
+ enumerator << [result] if result.present?
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,52 @@
1
+ module Trestle
2
+ class Toolbar
3
+ class Builder
4
+ def initialize(template)
5
+ @template = template
6
+ end
7
+
8
+ def button(content, options={})
9
+ options[:class] = button_classes_from_options(options)
10
+
11
+ button_tag(button_label(content, options), options)
12
+ end
13
+
14
+ def link(content, instance_or_url={}, options={})
15
+ options = instance_or_url if instance_or_url.is_a?(Hash)
16
+ options[:class] = button_classes_from_options(options)
17
+
18
+ admin_link_to(button_label(content, options), instance_or_url, options)
19
+ end
20
+
21
+ # Only methods explicitly tagged as builder methods will be automatically
22
+ # appended to the toolbar when called by Toolbar::Context.
23
+
24
+ class_attribute :builder_methods
25
+ self.builder_methods = []
26
+
27
+ def self.builder_method(*methods)
28
+ self.builder_methods += methods
29
+ end
30
+
31
+ builder_method :button, :link
32
+
33
+ private
34
+ delegate :admin_link_to, :button_tag, :content_tag, :safe_join, :icon, to: :@template
35
+
36
+ def button_classes_from_options(options)
37
+ classes = (options[:class] || "").split("\s")
38
+ classes.unshift("btn-#{options.delete(:style) || "default"}")
39
+ classes.unshift("btn") unless classes.include?("btn")
40
+ classes.push("has-icon") if options[:icon]
41
+ classes
42
+ end
43
+
44
+ def button_label(content, options)
45
+ icon = icon(options.delete(:icon)) if options[:icon]
46
+ label = content_tag(:span, content, class: "btn-label")
47
+
48
+ safe_join([icon, label].compact, " ")
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,39 @@
1
+ module Trestle
2
+ class Toolbar
3
+ # The toolbar Context is the object that is yielded to a toolbar block and handles the delegation of builder methods.
4
+ class Context
5
+ attr_reader :builder
6
+
7
+ def initialize(builder, enumerator, *args)
8
+ @builder, @enumerator = builder, enumerator
9
+ @args = args
10
+ end
11
+
12
+ def group
13
+ if @current_group
14
+ yield
15
+ else
16
+ @current_group = []
17
+ yield
18
+ @enumerator << @current_group
19
+ @current_group = nil
20
+ end
21
+ end
22
+
23
+ private
24
+ def respond_to_missing?(name, include_all=false)
25
+ builder.respond_to?(name) || super
26
+ end
27
+
28
+ def method_missing(name, *args, &block)
29
+ result = builder.send(name, *args, &block)
30
+
31
+ if builder.builder_methods.include?(name)
32
+ group { @current_group << result }
33
+ else
34
+ result
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,3 @@
1
1
  module Trestle
2
- VERSION = "0.8.9"
2
+ VERSION = "0.8.10"
3
3
  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.9
4
+ version: 0.8.10
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-05-24 00:00:00.000000000 Z
11
+ date: 2018-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -242,6 +242,7 @@ files:
242
242
  - app/assets/stylesheets/trestle/components/_tabs.scss
243
243
  - app/assets/stylesheets/trestle/components/_tags.scss
244
244
  - app/assets/stylesheets/trestle/components/_timestamp.scss
245
+ - app/assets/stylesheets/trestle/components/_toolbars.scss
245
246
  - app/assets/stylesheets/trestle/components/_turbolinks.scss
246
247
  - app/assets/stylesheets/trestle/components/_wells.scss
247
248
  - app/assets/stylesheets/trestle/core/_defaults.scss
@@ -276,7 +277,7 @@ files:
276
277
  - app/helpers/trestle/tab_helper.rb
277
278
  - app/helpers/trestle/table_helper.rb
278
279
  - app/helpers/trestle/timestamp_helper.rb
279
- - app/helpers/trestle/title_helper.rb
280
+ - app/helpers/trestle/toolbars_helper.rb
280
281
  - app/helpers/trestle/url_helper.rb
281
282
  - app/views/kaminari/trestle/_first_page.html.erb
282
283
  - app/views/kaminari/trestle/_gap.html.erb
@@ -304,6 +305,7 @@ files:
304
305
  - app/views/trestle/shared/_footer.html.erb
305
306
  - app/views/trestle/shared/_header.html.erb
306
307
  - app/views/trestle/shared/_sidebar.html.erb
308
+ - app/views/trestle/shared/_title.html.erb
307
309
  - app/views/trestle/table/_pagination.html.erb
308
310
  - app/views/trestle/table/_table.html.erb
309
311
  - bin/console
@@ -313,8 +315,12 @@ files:
313
315
  - config/locales/cs.yml
314
316
  - config/locales/en.rb
315
317
  - config/locales/en.yml
318
+ - config/locales/es-MX.yml
319
+ - config/locales/es.yml
316
320
  - config/locales/fr.rb
317
321
  - config/locales/fr.yml
322
+ - config/locales/lv.rb
323
+ - config/locales/lv.yml
318
324
  - config/locales/nl.rb
319
325
  - config/locales/nl.yml
320
326
  - config/locales/pl.rb
@@ -393,6 +399,7 @@ files:
393
399
  - lib/trestle/form/fields/url_field.rb
394
400
  - lib/trestle/form/fields/week_field.rb
395
401
  - lib/trestle/form/renderer.rb
402
+ - lib/trestle/hook.rb
396
403
  - lib/trestle/model_name.rb
397
404
  - lib/trestle/navigation.rb
398
405
  - lib/trestle/navigation/block.rb
@@ -413,6 +420,9 @@ files:
413
420
  - lib/trestle/table/column.rb
414
421
  - lib/trestle/table/row.rb
415
422
  - lib/trestle/table/select_column.rb
423
+ - lib/trestle/toolbar.rb
424
+ - lib/trestle/toolbar/builder.rb
425
+ - lib/trestle/toolbar/context.rb
416
426
  - lib/trestle/version.rb
417
427
  - trestle.gemspec
418
428
  - vendor/assets/bower_components/trestle/bootstrap-confirmation2/bootstrap-confirmation.js