trestle 0.9.2 → 0.9.3

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -6
  3. data/Gemfile +0 -1
  4. data/README.md +3 -1
  5. data/app/assets/bundle/trestle/bundle.css +0 -0
  6. data/app/assets/bundle/trestle/bundle.js +0 -0
  7. data/app/assets/bundle/trestle/fa-brands-400.eot +0 -0
  8. data/app/assets/bundle/trestle/fa-brands-400.svg +0 -0
  9. data/app/assets/bundle/trestle/fa-brands-400.ttf +0 -0
  10. data/app/assets/bundle/trestle/fa-brands-400.woff +0 -0
  11. data/app/assets/bundle/trestle/fa-brands-400.woff2 +0 -0
  12. data/app/assets/bundle/trestle/fa-regular-400.eot +0 -0
  13. data/app/assets/bundle/trestle/fa-regular-400.svg +0 -0
  14. data/app/assets/bundle/trestle/fa-regular-400.ttf +0 -0
  15. data/app/assets/bundle/trestle/fa-regular-400.woff +0 -0
  16. data/app/assets/bundle/trestle/fa-regular-400.woff2 +0 -0
  17. data/app/assets/bundle/trestle/fa-solid-900.eot +0 -0
  18. data/app/assets/bundle/trestle/fa-solid-900.svg +0 -0
  19. data/app/assets/bundle/trestle/fa-solid-900.ttf +0 -0
  20. data/app/assets/bundle/trestle/fa-solid-900.woff +0 -0
  21. data/app/assets/bundle/trestle/fa-solid-900.woff2 +0 -0
  22. data/{lib → app/controllers/concerns}/trestle/controller/breadcrumbs.rb +0 -0
  23. data/{lib → app/controllers/concerns}/trestle/controller/callbacks.rb +0 -0
  24. data/{lib → app/controllers/concerns}/trestle/controller/dialog.rb +0 -0
  25. data/{lib → app/controllers/concerns}/trestle/controller/helpers.rb +0 -0
  26. data/{lib → app/controllers/concerns}/trestle/controller/layout.rb +0 -0
  27. data/{lib → app/controllers/concerns}/trestle/controller/location.rb +0 -0
  28. data/{lib → app/controllers/concerns}/trestle/controller/title.rb +0 -0
  29. data/{lib → app/controllers/concerns}/trestle/controller/toolbars.rb +0 -0
  30. data/{lib → app/controllers/concerns}/trestle/resource/controller/actions.rb +1 -1
  31. data/{lib → app/controllers/concerns}/trestle/resource/controller/data_methods.rb +1 -1
  32. data/{lib → app/controllers/concerns}/trestle/resource/controller/redirection.rb +1 -1
  33. data/{lib → app/controllers/concerns}/trestle/resource/controller/toolbar.rb +1 -1
  34. data/app/controllers/trestle/admin_controller.rb +33 -0
  35. data/{lib → app/controllers}/trestle/application_controller.rb +0 -0
  36. data/app/controllers/trestle/dashboard_controller.rb +13 -11
  37. data/app/controllers/trestle/resource_controller.rb +8 -0
  38. data/app/helpers/trestle/grid_helper.rb +7 -3
  39. data/app/helpers/trestle/hook_helper.rb +8 -6
  40. data/app/views/trestle/resource/edit.html.erb +2 -2
  41. data/app/views/trestle/resource/index.html.erb +1 -1
  42. data/app/views/trestle/resource/new.html.erb +1 -1
  43. data/app/views/trestle/resource/show.html.erb +2 -2
  44. data/frontend/css/components/_table.scss +16 -0
  45. data/frontend/css/layout/_sidebar.scss +6 -1
  46. data/frontend/js/components/confirmation.js +4 -2
  47. data/frontend/js/components/dialog.js +3 -0
  48. data/frontend/js/components/form.js +9 -0
  49. data/frontend/js/components/sidebar.js +5 -5
  50. data/frontend/js/components/table.js +33 -2
  51. data/frontend/theme/trestle/theme/bootstrap/_buttons.scss +3 -0
  52. data/lib/trestle.rb +22 -38
  53. data/lib/trestle/adapters.rb +1 -1
  54. data/lib/trestle/admin.rb +1 -4
  55. data/lib/trestle/admin/builder.rb +2 -2
  56. data/lib/trestle/configurable.rb +10 -0
  57. data/lib/trestle/configuration.rb +2 -2
  58. data/lib/trestle/engine.rb +1 -5
  59. data/lib/trestle/form.rb +5 -7
  60. data/lib/trestle/form/builder.rb +2 -3
  61. data/lib/trestle/form/field.rb +13 -3
  62. data/lib/trestle/form/fields.rb +6 -38
  63. data/lib/trestle/form/fields/tag_select.rb +2 -0
  64. data/lib/trestle/form/renderer.rb +4 -2
  65. data/lib/trestle/hook.rb +2 -2
  66. data/lib/trestle/navigation.rb +3 -6
  67. data/lib/trestle/reloader.rb +0 -8
  68. data/lib/trestle/resource.rb +4 -7
  69. data/lib/trestle/resource/builder.rb +1 -1
  70. data/lib/trestle/resource/toolbar.rb +16 -3
  71. data/lib/trestle/scopes.rb +2 -4
  72. data/lib/trestle/tab.rb +2 -0
  73. data/lib/trestle/table.rb +12 -13
  74. data/lib/trestle/table/actions_column.rb +6 -6
  75. data/lib/trestle/table/automatic.rb +3 -3
  76. data/lib/trestle/table/builder.rb +4 -4
  77. data/lib/trestle/table/column.rb +29 -24
  78. data/lib/trestle/table/row.rb +13 -13
  79. data/lib/trestle/table/select_column.rb +19 -7
  80. data/lib/trestle/toolbar.rb +4 -11
  81. data/lib/trestle/version.rb +1 -1
  82. data/trestle.gemspec +5 -6
  83. data/yarn.lock +1226 -1144
  84. metadata +24 -24
  85. data/lib/trestle/admin/controller.rb +0 -35
  86. data/lib/trestle/resource/controller.rb +0 -17
@@ -5,7 +5,7 @@ import visit from '../core/visit'
5
5
  // Allow clicking on any part of a table row to follow either the table's data-url
6
6
  // or the first link within the row (that is not in the actions column).
7
7
  $(document).on('click', 'tr[data-url]:not([data-behavior="dialog"])', function (e) {
8
- let row = $(e.currentTarget)
8
+ const row = $(e.currentTarget)
9
9
 
10
10
  let url
11
11
 
@@ -25,6 +25,37 @@ $(document).on('click', 'tr[data-url]:not([data-behavior="dialog"])', function (
25
25
  })
26
26
 
27
27
  // Ignore the above event handler when clicking directly on a link or input element
28
- $(document).on('click', 'tr[data-url] a, tr[data-url] input', function (e) {
28
+ $(document).on('click', 'tr[data-url] a, tr[data-url] input, .select-row', function (e) {
29
29
  e.stopPropagation()
30
30
  })
31
+
32
+ // Handle clicking on select all checkbox in table header
33
+ $(document).on('click', 'th.select-row input', function (e) {
34
+ const table = $(this).closest('table')
35
+ const checked = $(this).is(':checked')
36
+
37
+ table.find('td.select-row input').prop('checked', checked)
38
+ })
39
+
40
+ // Handle single row selection to update header row status
41
+ $(document).on('click', 'td.select-row input', function (e) {
42
+ const table = $(this).closest('table')
43
+
44
+ const checkboxes = table.find('td.select-row input')
45
+ const selectedCheckboxes = checkboxes.filter(':checked')
46
+
47
+ const header = table.find('th.select-row input')
48
+
49
+ if (checkboxes.length === selectedCheckboxes.length) {
50
+ // All checked
51
+ header.prop('indeterminate', false)
52
+ header.prop('checked', true)
53
+ } else if (selectedCheckboxes.length === 0) {
54
+ // None checked
55
+ header.prop('indeterminate', false)
56
+ header.prop('checked', false)
57
+ } else {
58
+ // Some checked
59
+ header.prop('indeterminate', true)
60
+ }
61
+ })
@@ -11,6 +11,9 @@
11
11
 
12
12
  &:focus,
13
13
  &.focus {
14
+ color: color-yiq($hover-background);
15
+ background-color: $hover-background;
16
+ border-color: $hover-border;
14
17
  box-shadow: 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
15
18
  }
16
19
 
@@ -1,45 +1,29 @@
1
- require "trestle/version"
1
+ require_relative "trestle/version"
2
2
 
3
3
  require "active_support/all"
4
4
  require "kaminari"
5
5
 
6
6
  module Trestle
7
- extend ActiveSupport::Autoload
8
-
9
- autoload :Adapters
10
- autoload :Admin
11
- autoload :ApplicationController
12
- autoload :Attribute
13
- autoload :Breadcrumb
14
- autoload :Builder
15
- autoload :Configurable
16
- autoload :Configuration
17
- autoload :Display
18
- autoload :EvaluationContext
19
- autoload :Form
20
- autoload :Hook
21
- autoload :ModelName
22
- autoload :Navigation
23
- autoload :Options
24
- autoload :Reloader
25
- autoload :Resource
26
- autoload :Scopes
27
- autoload :Tab
28
- autoload :Table
29
- autoload :Toolbar
30
-
31
- module Controller
32
- extend ActiveSupport::Autoload
33
-
34
- autoload :Breadcrumbs
35
- autoload :Callbacks
36
- autoload :Dialog
37
- autoload :Helpers
38
- autoload :Layout
39
- autoload :Location
40
- autoload :Title
41
- autoload :Toolbars
42
- end
7
+ require_relative "trestle/evaluation_context"
8
+ require_relative "trestle/builder"
9
+ require_relative "trestle/hook"
10
+ require_relative "trestle/toolbar"
11
+ require_relative "trestle/adapters"
12
+ require_relative "trestle/attribute"
13
+ require_relative "trestle/breadcrumb"
14
+ require_relative "trestle/configurable"
15
+ require_relative "trestle/configuration"
16
+ require_relative "trestle/display"
17
+ require_relative "trestle/form"
18
+ require_relative "trestle/model_name"
19
+ require_relative "trestle/navigation"
20
+ require_relative "trestle/options"
21
+ require_relative "trestle/reloader"
22
+ require_relative "trestle/scopes"
23
+ require_relative "trestle/tab"
24
+ require_relative "trestle/table"
25
+ require_relative "trestle/admin"
26
+ require_relative "trestle/resource"
43
27
 
44
28
  mattr_accessor :admins
45
29
  self.admins = {}
@@ -86,4 +70,4 @@ module Trestle
86
70
  end
87
71
  end
88
72
 
89
- require "trestle/engine" if defined?(Rails)
73
+ require_relative "trestle/engine" if defined?(Rails)
@@ -2,7 +2,7 @@ module Trestle
2
2
  module Adapters
3
3
  extend ActiveSupport::Autoload
4
4
 
5
- autoload :Adapter
5
+ require_relative "adapters/adapter"
6
6
 
7
7
  autoload :ActiveRecordAdapter
8
8
  autoload :DraperAdapter
@@ -1,9 +1,6 @@
1
1
  module Trestle
2
2
  class Admin
3
- extend ActiveSupport::Autoload
4
-
5
- autoload :Builder
6
- autoload :Controller
3
+ require_relative "admin/builder"
7
4
 
8
5
  delegate :to_param, to: :class
9
6
 
@@ -7,7 +7,7 @@ module Trestle
7
7
  self.admin_class = Admin
8
8
 
9
9
  class_attribute :controller
10
- self.controller = Controller
10
+ self.controller = -> { AdminController }
11
11
 
12
12
  delegate :helper, :before_action, :after_action, :around_action, to: :@controller
13
13
 
@@ -27,7 +27,7 @@ module Trestle
27
27
  # Define admin controller class
28
28
  # This is done using class_eval rather than Class.new so that the full
29
29
  # class name and parent chain is set when Rails' inherited hooks are called.
30
- admin.class_eval("class AdminController < #{controller.name}; end")
30
+ admin.class_eval("class AdminController < #{controller.call.name}; end")
31
31
 
32
32
  # Set a reference on the controller class to the admin class
33
33
  controller = admin.const_get(:AdminController)
@@ -62,6 +62,16 @@ module Trestle
62
62
 
63
63
  defaults[name] = default
64
64
  end
65
+
66
+ def deprecated_option(name, message=nil)
67
+ define_method("#{name}=") do |value|
68
+ ActiveSupport::Deprecation.warn(message)
69
+ end
70
+
71
+ define_method(name) do |*args|
72
+ ActiveSupport::Deprecation.warn(message)
73
+ end
74
+ end
65
75
  end
66
76
 
67
77
  module Open
@@ -105,8 +105,8 @@ module Trestle
105
105
  -> { ActiveSupport::Dependencies.autoload_paths.grep(/\/app\/admin\Z/) }
106
106
  ]
107
107
 
108
- # When to reload Trestle admin within a to_prepare block (`:always` or `:on_update`)
109
- option :reload, :on_update
108
+ # [DEPRECATED] When to reload Trestle admin within a to_prepare block
109
+ deprecated_option :reload, "The config.reload option is deprecated. Admins are now always reloaded when config.to_prepare is called."
110
110
 
111
111
 
112
112
  ## Debugging
@@ -45,11 +45,7 @@ module Trestle
45
45
  end
46
46
 
47
47
  config.to_prepare do
48
- if Trestle.config.reload == :always
49
- Engine.reloader.execute
50
- else
51
- Engine.reloader.execute_if_updated
52
- end
48
+ Engine.reloader.execute
53
49
  end
54
50
 
55
51
  def reloader
@@ -1,12 +1,10 @@
1
1
  module Trestle
2
2
  class Form
3
- extend ActiveSupport::Autoload
4
-
5
- autoload :Automatic
6
- autoload :Builder
7
- autoload :Field
8
- autoload :Fields
9
- autoload :Renderer
3
+ require_relative "form/automatic"
4
+ require_relative "form/builder"
5
+ require_relative "form/field"
6
+ require_relative "form/fields"
7
+ require_relative "form/renderer"
10
8
 
11
9
  attr_reader :options, :block
12
10
 
@@ -1,3 +1,5 @@
1
+ require "action_view/helpers"
2
+
1
3
  module Trestle
2
4
  class Form
3
5
  class Builder < ActionView::Helpers::FormBuilder
@@ -48,6 +50,3 @@ module Trestle
48
50
  end
49
51
  end
50
52
  end
51
-
52
- # Load all form fields
53
- Trestle::Form::Fields.eager_load!
@@ -13,9 +13,7 @@ module Trestle
13
13
  end
14
14
 
15
15
  def errors
16
- errors = builder.errors(name)
17
- errors += builder.errors(name.to_s.sub(/_id$/, '')) if name.to_s =~ /_id$/
18
- errors
16
+ error_keys.map { |key| builder.errors(key) }.flatten
19
17
  end
20
18
 
21
19
  def form_group(opts={})
@@ -73,6 +71,18 @@ module Trestle
73
71
  "is-invalid"
74
72
  end
75
73
 
74
+ def error_keys
75
+ keys = [name]
76
+
77
+ # Singular associations (belongs_to)
78
+ keys << name.to_s.sub(/_id$/, '') if name.to_s =~ /_id$/
79
+
80
+ # Collection associations (has_many / has_and_belongs_to_many)
81
+ keys << name.to_s.sub(/_ids$/, 's') if name.to_s =~ /_ids$/
82
+
83
+ keys
84
+ end
85
+
76
86
  def extract_wrapper_options(*keys)
77
87
  wrapper = Trestle::Options.new
78
88
  keys.each { |k| wrapper[k] = options.delete(k) if options.key?(k) }
@@ -1,47 +1,15 @@
1
1
  module Trestle
2
2
  class Form
3
3
  module Fields
4
- extend ActiveSupport::Autoload
4
+ require_relative "fields/form_control"
5
+ require_relative "fields/form_group"
5
6
 
6
- eager_autoload do
7
- autoload :FormControl
8
- autoload :FormGroup
7
+ require_relative "fields/date_picker"
9
8
 
10
- autoload :DatePicker
9
+ require_relative "fields/check_box_helpers"
10
+ require_relative "fields/radio_button_helpers"
11
11
 
12
- autoload :CheckBoxHelpers
13
- autoload :RadioButtonHelpers
14
-
15
- autoload :CheckBox
16
- autoload :CollectionCheckBoxes
17
- autoload :CollectionRadioButtons
18
- autoload :CollectionSelect
19
- autoload :ColorField
20
- autoload :DateField
21
- autoload :DateSelect
22
- autoload :DatetimeField
23
- autoload :DatetimeSelect
24
- autoload :EmailField
25
- autoload :FileField
26
- autoload :GroupedCollectionSelect
27
- autoload :MonthField
28
- autoload :NumberField
29
- autoload :RadioButton
30
- autoload :RangeField
31
- autoload :SearchField
32
- autoload :Select
33
- autoload :StaticField
34
- autoload :TagSelect
35
- autoload :TelephoneField
36
- autoload :TextArea
37
- autoload :TextField
38
- autoload :TimeField
39
- autoload :TimeSelect
40
- autoload :TimeZoneSelect
41
- autoload :UrlField
42
- autoload :PasswordField
43
- autoload :WeekField
44
- end
12
+ Dir.glob("#{__dir__}/fields/*.rb") { |f| require_relative f }
45
13
  end
46
14
  end
47
15
  end
@@ -1,3 +1,5 @@
1
+ require_relative "select"
2
+
1
3
  module Trestle
2
4
  class Form
3
5
  module Fields
@@ -1,12 +1,14 @@
1
+ require "action_view/context"
2
+ require "action_view/helpers"
3
+
1
4
  module Trestle
2
5
  class Form
3
6
  class Renderer
4
7
  include ::ActionView::Context
5
8
  include ::ActionView::Helpers::CaptureHelper
6
- include HookHelper
7
9
 
8
10
  # Whitelisted helpers will concatenate their result to the output buffer when called.
9
- WHITELISTED_HELPERS = [:row, :col, :render, :tab, :table, :divider, :h1, :h2, :h3, :h4, :h5, :h6, :card, :panel, :well]
11
+ WHITELISTED_HELPERS = [:row, :col, :hook, :render, :tab, :table, :divider, :h1, :h2, :h3, :h4, :h5, :h6, :card, :panel, :well]
10
12
 
11
13
  # Raw block helpers will pass their block argument directly to the method
12
14
  # without wrapping it in a new output buffer.
@@ -20,8 +20,8 @@ module Trestle
20
20
  end
21
21
  end
22
22
 
23
- def evaluate(context)
24
- context.instance_exec(&block)
23
+ def evaluate(context, *args)
24
+ context.instance_exec(*args, &block)
25
25
  end
26
26
 
27
27
  class Set
@@ -1,11 +1,8 @@
1
1
  module Trestle
2
2
  class Navigation
3
- extend ActiveSupport::Autoload
4
-
5
- autoload :Block
6
- autoload :Item
7
- autoload :Group
8
- autoload :NullGroup, "trestle/navigation/group"
3
+ require_relative "navigation/block"
4
+ require_relative "navigation/item"
5
+ require_relative "navigation/group"
9
6
 
10
7
  attr_reader :items
11
8
 
@@ -2,14 +2,6 @@ module Trestle
2
2
  class Reloader
3
3
  delegate :execute, :updated?, to: :updater
4
4
 
5
- def execute_if_updated
6
- if defined?(@updater)
7
- updater.execute_if_updated
8
- else
9
- updater.execute
10
- end
11
- end
12
-
13
5
  def updater
14
6
  @updater ||= ActiveSupport::FileUpdateChecker.new([], compile_load_paths) do
15
7
  begin
@@ -1,12 +1,9 @@
1
1
  module Trestle
2
2
  class Resource < Admin
3
- extend ActiveSupport::Autoload
4
-
5
- autoload :AdapterMethods
6
- autoload :Builder
7
- autoload :Collection
8
- autoload :Controller
9
- autoload :Toolbar
3
+ require_relative "resource/adapter_methods"
4
+ require_relative "resource/builder"
5
+ require_relative "resource/collection"
6
+ require_relative "resource/toolbar"
10
7
 
11
8
  include AdapterMethods
12
9
 
@@ -2,7 +2,7 @@ module Trestle
2
2
  class Resource
3
3
  class Builder < Admin::Builder
4
4
  self.admin_class = Resource
5
- self.controller = Controller
5
+ self.controller = -> { ResourceController }
6
6
 
7
7
  def adapter(&block)
8
8
  klass = admin.adapter_class
@@ -6,7 +6,7 @@ module Trestle
6
6
  delegate :translate, :t, to: :admin
7
7
 
8
8
  def new
9
- link(t("buttons.new", default: "New %{model_name}"), action: :new, style: :light, icon: "fa fa-plus", class: "btn-new-resource")
9
+ link(t("buttons.new", default: "New %{model_name}"), action: :new, style: :light, icon: "fa fa-plus", class: "btn-new-resource") if action?(:new)
10
10
  end
11
11
 
12
12
  def save
@@ -14,7 +14,7 @@ module Trestle
14
14
  end
15
15
 
16
16
  def delete
17
- link(t("buttons.delete", default: "Delete %{model_name}"), instance, action: :destroy, method: :delete, style: :danger, icon: "fa fa-trash", data: { toggle: "confirm-delete", placement: "bottom" })
17
+ link(t("buttons.delete", default: "Delete %{model_name}"), instance, action: :destroy, method: :delete, style: :danger, icon: "fa fa-trash", data: { toggle: "confirm-delete", placement: "bottom" }) if action?(:destroy)
18
18
  end
19
19
 
20
20
  def dismiss
@@ -22,7 +22,20 @@ module Trestle
22
22
  end
23
23
  alias ok dismiss
24
24
 
25
- builder_method :new, :save, :delete, :dismiss, :ok
25
+ def save_or_dismiss(action=:update)
26
+ if action?(action)
27
+ save
28
+ else
29
+ dismiss
30
+ end
31
+ end
32
+
33
+ builder_method :new, :save, :delete, :dismiss, :ok, :save_or_dismiss
34
+
35
+ protected
36
+ def action?(action)
37
+ admin.actions.include?(action)
38
+ end
26
39
  end
27
40
  end
28
41
  end