trestle 0.9.2 → 0.9.3

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