trestle 0.8.9 → 0.8.10

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