trestle 0.9.0 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +28 -0
  3. data/.gitignore +3 -0
  4. data/CONTRIBUTING.md +38 -0
  5. data/Gemfile +12 -5
  6. data/README.md +9 -2
  7. data/app/assets/bundle/trestle/bundle.css +9 -9
  8. data/app/assets/bundle/trestle/bundle.js +50 -48
  9. data/app/assets/bundle/trestle/fa-brands-400.eot +0 -0
  10. data/app/assets/bundle/trestle/fa-brands-400.svg +818 -597
  11. data/app/assets/bundle/trestle/fa-brands-400.ttf +0 -0
  12. data/app/assets/bundle/trestle/fa-brands-400.woff +0 -0
  13. data/app/assets/bundle/trestle/fa-brands-400.woff2 +0 -0
  14. data/app/assets/bundle/trestle/fa-regular-400.eot +0 -0
  15. data/app/assets/bundle/trestle/fa-regular-400.svg +93 -95
  16. data/app/assets/bundle/trestle/fa-regular-400.ttf +0 -0
  17. data/app/assets/bundle/trestle/fa-regular-400.woff +0 -0
  18. data/app/assets/bundle/trestle/fa-regular-400.woff2 +0 -0
  19. data/app/assets/bundle/trestle/fa-solid-900.eot +0 -0
  20. data/app/assets/bundle/trestle/fa-solid-900.svg +1209 -842
  21. data/app/assets/bundle/trestle/fa-solid-900.ttf +0 -0
  22. data/app/assets/bundle/trestle/fa-solid-900.woff +0 -0
  23. data/app/assets/bundle/trestle/fa-solid-900.woff2 +0 -0
  24. data/app/assets/bundle/trestle/flatpickr/ar-dz.js +1 -0
  25. data/app/assets/bundle/trestle/flatpickr/ar.js +1 -1
  26. data/app/assets/bundle/trestle/flatpickr/at.js +1 -1
  27. data/app/assets/bundle/trestle/flatpickr/az.js +1 -1
  28. data/app/assets/bundle/trestle/flatpickr/be.js +1 -1
  29. data/app/assets/bundle/trestle/flatpickr/bg.js +1 -1
  30. data/app/assets/bundle/trestle/flatpickr/bn.js +1 -1
  31. data/app/assets/bundle/trestle/flatpickr/bs.js +1 -1
  32. data/app/assets/bundle/trestle/flatpickr/cat.js +1 -1
  33. data/app/assets/bundle/trestle/flatpickr/ckb.js +1 -0
  34. data/app/assets/bundle/trestle/flatpickr/cs.js +1 -1
  35. data/app/assets/bundle/trestle/flatpickr/cy.js +1 -1
  36. data/app/assets/bundle/trestle/flatpickr/da.js +1 -1
  37. data/app/assets/bundle/trestle/flatpickr/de.js +1 -1
  38. data/app/assets/bundle/trestle/flatpickr/default.js +1 -1
  39. data/app/assets/bundle/trestle/flatpickr/eo.js +1 -1
  40. data/app/assets/bundle/trestle/flatpickr/es.js +1 -1
  41. data/app/assets/bundle/trestle/flatpickr/et.js +1 -1
  42. data/app/assets/bundle/trestle/flatpickr/fa.js +1 -1
  43. data/app/assets/bundle/trestle/flatpickr/fi.js +1 -1
  44. data/app/assets/bundle/trestle/flatpickr/fo.js +1 -1
  45. data/app/assets/bundle/trestle/flatpickr/fr.js +1 -1
  46. data/app/assets/bundle/trestle/flatpickr/ga.js +1 -1
  47. data/app/assets/bundle/trestle/flatpickr/gr.js +1 -1
  48. data/app/assets/bundle/trestle/flatpickr/he.js +1 -1
  49. data/app/assets/bundle/trestle/flatpickr/hi.js +1 -1
  50. data/app/assets/bundle/trestle/flatpickr/hr.js +1 -1
  51. data/app/assets/bundle/trestle/flatpickr/hu.js +1 -1
  52. data/app/assets/bundle/trestle/flatpickr/hy.js +1 -0
  53. data/app/assets/bundle/trestle/flatpickr/id.js +1 -1
  54. data/app/assets/bundle/trestle/flatpickr/is.js +1 -1
  55. data/app/assets/bundle/trestle/flatpickr/it.js +1 -1
  56. data/app/assets/bundle/trestle/flatpickr/ja.js +1 -1
  57. data/app/assets/bundle/trestle/flatpickr/ka.js +1 -1
  58. data/app/assets/bundle/trestle/flatpickr/km.js +1 -1
  59. data/app/assets/bundle/trestle/flatpickr/ko.js +1 -1
  60. data/app/assets/bundle/trestle/flatpickr/kz.js +1 -1
  61. data/app/assets/bundle/trestle/flatpickr/lt.js +1 -1
  62. data/app/assets/bundle/trestle/flatpickr/lv.js +1 -1
  63. data/app/assets/bundle/trestle/flatpickr/mk.js +1 -1
  64. data/app/assets/bundle/trestle/flatpickr/mn.js +1 -1
  65. data/app/assets/bundle/trestle/flatpickr/ms.js +1 -1
  66. data/app/assets/bundle/trestle/flatpickr/my.js +1 -1
  67. data/app/assets/bundle/trestle/flatpickr/nl.js +1 -1
  68. data/app/assets/bundle/trestle/flatpickr/nn.js +1 -0
  69. data/app/assets/bundle/trestle/flatpickr/no.js +1 -1
  70. data/app/assets/bundle/trestle/flatpickr/pa.js +1 -1
  71. data/app/assets/bundle/trestle/flatpickr/pl.js +1 -1
  72. data/app/assets/bundle/trestle/flatpickr/pt.js +1 -1
  73. data/app/assets/bundle/trestle/flatpickr/ro.js +1 -1
  74. data/app/assets/bundle/trestle/flatpickr/ru.js +1 -1
  75. data/app/assets/bundle/trestle/flatpickr/si.js +1 -1
  76. data/app/assets/bundle/trestle/flatpickr/sk.js +1 -1
  77. data/app/assets/bundle/trestle/flatpickr/sl.js +1 -1
  78. data/app/assets/bundle/trestle/flatpickr/sq.js +1 -1
  79. data/app/assets/bundle/trestle/flatpickr/sr-cyr.js +1 -1
  80. data/app/assets/bundle/trestle/flatpickr/sr.js +1 -1
  81. data/app/assets/bundle/trestle/flatpickr/sv.js +1 -1
  82. data/app/assets/bundle/trestle/flatpickr/th.js +1 -1
  83. data/app/assets/bundle/trestle/flatpickr/tr.js +1 -1
  84. data/app/assets/bundle/trestle/flatpickr/uk.js +1 -1
  85. data/app/assets/bundle/trestle/flatpickr/uz.js +1 -0
  86. data/app/assets/bundle/trestle/flatpickr/uz_latn.js +1 -0
  87. data/app/assets/bundle/trestle/flatpickr/vn.js +1 -1
  88. data/app/assets/bundle/trestle/flatpickr/zh-tw.js +1 -1
  89. data/app/assets/bundle/trestle/flatpickr/zh.js +1 -1
  90. data/app/assets/javascripts/trestle/admin.js +1 -0
  91. data/app/assets/javascripts/trestle/i18n.js.erb +8 -0
  92. data/{lib → app/controllers/concerns}/trestle/controller/breadcrumbs.rb +1 -1
  93. data/app/controllers/concerns/trestle/controller/title.rb +20 -0
  94. data/app/controllers/concerns/trestle/controller/toolbars.rb +30 -0
  95. data/app/controllers/concerns/trestle/resource/controller/actions.rb +133 -0
  96. data/app/controllers/concerns/trestle/resource/controller/data_methods.rb +52 -0
  97. data/app/controllers/concerns/trestle/resource/controller/redirection.rb +23 -0
  98. data/app/controllers/concerns/trestle/resource/controller/toolbar.rb +11 -0
  99. data/app/controllers/trestle/admin_controller.rb +31 -0
  100. data/app/controllers/trestle/application_controller.rb +12 -0
  101. data/app/controllers/trestle/dashboard_controller.rb +2 -2
  102. data/app/controllers/trestle/resource_controller.rb +6 -0
  103. data/app/helpers/trestle/avatar_helper.rb +6 -2
  104. data/app/helpers/trestle/container_helper.rb +12 -4
  105. data/app/helpers/trestle/grid_helper.rb +51 -7
  106. data/app/helpers/trestle/hook_helper.rb +1 -25
  107. data/app/helpers/trestle/i18n_helper.rb +8 -15
  108. data/app/helpers/trestle/layout_helper.rb +20 -0
  109. data/app/helpers/trestle/navigation_helper.rb +23 -0
  110. data/app/helpers/trestle/params_helper.rb +4 -1
  111. data/app/helpers/trestle/table_helper.rb +22 -3
  112. data/app/helpers/trestle/title_helper.rb +11 -0
  113. data/app/helpers/trestle/toolbars_helper.rb +0 -11
  114. data/app/helpers/trestle/url_helper.rb +1 -11
  115. data/app/views/layouts/trestle/admin.html.erb +6 -6
  116. data/app/views/trestle/application/_dialog.html.erb +1 -1
  117. data/app/views/trestle/application/_header.html.erb +1 -3
  118. data/app/views/trestle/flash/_alert.html.erb +3 -1
  119. data/app/views/trestle/flash/_debug.html.erb +13 -8
  120. data/app/views/trestle/flash/_flash.html.erb +1 -1
  121. data/app/views/trestle/resource/_scopes.html.erb +17 -8
  122. data/app/views/trestle/resource/edit.html.erb +2 -2
  123. data/app/views/trestle/resource/index.html.erb +3 -3
  124. data/app/views/trestle/resource/new.html.erb +1 -1
  125. data/app/views/trestle/resource/show.html.erb +2 -2
  126. data/app/views/trestle/shared/_sidebar.html.erb +5 -6
  127. data/app/views/trestle/table/_pagination.html.erb +1 -1
  128. data/config/locales/de.rb +18 -0
  129. data/config/locales/de.yml +101 -0
  130. data/config/locales/vi.rb +18 -0
  131. data/config/locales/vi.yml +101 -0
  132. data/config/routes.rb +1 -1
  133. data/frontend/css/components/_alerts.scss +31 -0
  134. data/frontend/css/components/_avatar.scss +14 -0
  135. data/frontend/css/components/_buttons.scss +0 -1
  136. data/frontend/css/components/_datepicker.scss +1 -0
  137. data/frontend/css/components/_fields.scss +6 -0
  138. data/frontend/css/components/_modal.scss +2 -0
  139. data/frontend/css/components/_scopes.scss +66 -21
  140. data/frontend/css/components/_table.scss +20 -0
  141. data/frontend/css/components/_tags.scss +2 -0
  142. data/frontend/css/components/_timestamp.scss +1 -1
  143. data/frontend/css/layout/_content.scss +5 -2
  144. data/frontend/css/layout/_sidebar.scss +9 -3
  145. data/frontend/css/variables/_bootstrap.scss +1 -0
  146. data/frontend/css/variables/_trestle.scss +25 -5
  147. data/frontend/js/components/confirmation.js +4 -2
  148. data/frontend/js/components/dialog.js +15 -4
  149. data/frontend/js/components/form.js +9 -0
  150. data/frontend/js/components/navigation.js +63 -0
  151. data/frontend/js/components/pagination.js +51 -0
  152. data/frontend/js/components/sidebar.js +8 -11
  153. data/frontend/js/components/table.js +33 -2
  154. data/frontend/js/components/tabs.js +3 -3
  155. data/frontend/js/core/events.js +7 -3
  156. data/frontend/js/index.js +1 -0
  157. data/frontend/theme/trestle/theme/_defaults.scss +4 -4
  158. data/frontend/theme/trestle/theme/bootstrap/_buttons.scss +3 -0
  159. data/lib/generators/trestle/install/install_generator.rb +6 -2
  160. data/lib/generators/trestle/install/templates/_custom.css +8 -0
  161. data/lib/generators/trestle/install/templates/_theme.scss +1 -1
  162. data/lib/generators/trestle/install/templates/trestle.rb.erb +8 -2
  163. data/lib/generators/trestle/resource/resource_generator.rb +15 -1
  164. data/lib/generators/trestle/resource/templates/admin.rb.erb +15 -8
  165. data/lib/trestle/adapters/active_record_adapter.rb +17 -1
  166. data/lib/trestle/adapters.rb +1 -1
  167. data/lib/trestle/admin/builder.rb +7 -3
  168. data/lib/trestle/admin.rb +18 -8
  169. data/lib/trestle/configurable.rb +16 -0
  170. data/lib/trestle/configuration.rb +7 -8
  171. data/lib/trestle/debug_errors.rb +24 -0
  172. data/lib/trestle/engine.rb +3 -10
  173. data/lib/trestle/evaluation_context.rb +11 -3
  174. data/lib/trestle/form/automatic.rb +4 -2
  175. data/lib/trestle/form/builder.rb +6 -7
  176. data/lib/trestle/form/field.rb +44 -17
  177. data/lib/trestle/form/fields/check_box_helpers.rb +1 -1
  178. data/lib/trestle/form/fields/collection_select.rb +1 -1
  179. data/lib/trestle/form/fields/date_picker.rb +9 -3
  180. data/lib/trestle/form/fields/date_select.rb +1 -1
  181. data/lib/trestle/form/fields/datetime_select.rb +1 -1
  182. data/lib/trestle/form/fields/file_field.rb +1 -1
  183. data/lib/trestle/form/fields/form_group.rb +18 -5
  184. data/lib/trestle/form/fields/grouped_collection_select.rb +1 -1
  185. data/lib/trestle/form/fields/range_field.rb +2 -4
  186. data/lib/trestle/form/fields/select.rb +2 -3
  187. data/lib/trestle/form/fields/static_field.rb +7 -3
  188. data/lib/trestle/form/fields/tag_select.rb +3 -1
  189. data/lib/trestle/form/fields/time_select.rb +1 -1
  190. data/lib/trestle/form/fields/time_zone_select.rb +1 -1
  191. data/lib/trestle/form/fields.rb +6 -38
  192. data/lib/trestle/form/renderer.rb +11 -4
  193. data/lib/trestle/form.rb +5 -7
  194. data/lib/trestle/hook/helpers.rb +33 -0
  195. data/lib/trestle/hook/set.rb +32 -0
  196. data/lib/trestle/hook.rb +5 -31
  197. data/lib/trestle/lazy.rb +56 -0
  198. data/lib/trestle/navigation/group.rb +5 -2
  199. data/lib/trestle/navigation/item.rb +7 -3
  200. data/lib/trestle/navigation.rb +3 -6
  201. data/lib/trestle/registry.rb +61 -0
  202. data/lib/trestle/reloader.rb +24 -12
  203. data/lib/trestle/resource/builder.rb +4 -3
  204. data/lib/trestle/resource/collection.rb +1 -5
  205. data/lib/trestle/resource/toolbar.rb +42 -0
  206. data/lib/trestle/resource.rb +8 -9
  207. data/lib/trestle/scopes/block.rb +9 -8
  208. data/lib/trestle/scopes/definition.rb +22 -0
  209. data/lib/trestle/scopes/scope.rb +6 -2
  210. data/lib/trestle/scopes.rb +38 -11
  211. data/lib/trestle/tab.rb +2 -0
  212. data/lib/trestle/table/actions_column.rb +6 -6
  213. data/lib/trestle/table/automatic.rb +10 -3
  214. data/lib/trestle/table/builder.rb +4 -4
  215. data/lib/trestle/table/column.rb +34 -25
  216. data/lib/trestle/table/row.rb +13 -13
  217. data/lib/trestle/table/select_column.rb +19 -7
  218. data/lib/trestle/table.rb +17 -12
  219. data/lib/trestle/toolbar.rb +4 -11
  220. data/lib/trestle/version.rb +1 -1
  221. data/lib/trestle.rb +62 -48
  222. data/package.json +21 -24
  223. data/trestle.gemspec +6 -6
  224. data/webpack.config.js +40 -49
  225. data/yarn.lock +3044 -4730
  226. metadata +66 -22
  227. data/.travis.yml +0 -27
  228. data/lib/trestle/admin/controller.rb +0 -28
  229. data/lib/trestle/application_controller.rb +0 -12
  230. data/lib/trestle/resource/controller.rb +0 -174
  231. /data/{lib → app/controllers/concerns}/trestle/controller/callbacks.rb +0 -0
  232. /data/{lib → app/controllers/concerns}/trestle/controller/dialog.rb +0 -0
  233. /data/{lib → app/controllers/concerns}/trestle/controller/helpers.rb +0 -0
  234. /data/{lib → app/controllers/concerns}/trestle/controller/layout.rb +0 -0
  235. /data/{lib → app/controllers/concerns}/trestle/controller/location.rb +0 -0
@@ -0,0 +1,56 @@
1
+ module Trestle
2
+ module Lazy
3
+ module Constantize
4
+ def constantize(value)
5
+ case value
6
+ when String
7
+ value.safe_constantize
8
+ when Proc
9
+ value.call
10
+ else
11
+ value
12
+ end
13
+ end
14
+ end
15
+
16
+ class List
17
+ include Enumerable
18
+ include Constantize
19
+
20
+ def initialize(*items)
21
+ @list = items
22
+ end
23
+
24
+ def each(&block)
25
+ @list.each do |item|
26
+ yield constantize(item)
27
+ end
28
+ end
29
+
30
+ def <<(items)
31
+ @list += Array(items)
32
+ end
33
+ end
34
+
35
+ class Hash
36
+ include Enumerable
37
+ include Constantize
38
+
39
+ delegate :[]=, :key?, to: :@hash
40
+
41
+ def initialize
42
+ @hash = {}
43
+ end
44
+
45
+ def each(&block)
46
+ @hash.each do |key, value|
47
+ yield key, constantize(value)
48
+ end
49
+ end
50
+
51
+ def [](key)
52
+ constantize(@hash[key])
53
+ end
54
+ end
55
+ end
56
+ end
@@ -4,8 +4,7 @@ module Trestle
4
4
  attr_reader :name, :options
5
5
 
6
6
  def initialize(name, options={})
7
- @name = name
8
- @options = options
7
+ @name, @options = name.to_s, options
9
8
  end
10
9
 
11
10
  def ==(other)
@@ -41,6 +40,10 @@ module Trestle
41
40
  end
42
41
  end
43
42
 
43
+ def collapse?
44
+ options[:collapse]
45
+ end
46
+
44
47
  def label
45
48
  I18n.t("admin.navigation.groups.#{name}", default: name.to_s.titlecase)
46
49
  end
@@ -4,7 +4,7 @@ module Trestle
4
4
  attr_reader :name, :path, :options
5
5
 
6
6
  def initialize(name, path=nil, options={})
7
- @name, @path, @options = name, path, options
7
+ @name, @path, @options = name.to_s, path, options
8
8
  end
9
9
 
10
10
  def ==(other)
@@ -17,7 +17,7 @@ module Trestle
17
17
  end
18
18
 
19
19
  def <=>(other)
20
- priority <=> other.priority
20
+ [priority, name] <=> [other.priority, other.name]
21
21
  end
22
22
 
23
23
  def priority
@@ -40,7 +40,7 @@ module Trestle
40
40
  end
41
41
 
42
42
  def label
43
- options[:label] || I18n.t("admin.navigation.items.#{name}", default: name.to_s.titlecase)
43
+ options[:label] || I18n.t("admin.navigation.items.#{name}", default: name.titlecase)
44
44
  end
45
45
 
46
46
  def icon
@@ -55,6 +55,10 @@ module Trestle
55
55
  Badge.new(options[:badge]) if badge?
56
56
  end
57
57
 
58
+ def html_options
59
+ options.except(:admin, :badge, :group, :icon, :if, :label, :priority, :unless)
60
+ end
61
+
58
62
  def visible?(context)
59
63
  if options[:if]
60
64
  context.instance_exec(&options[:if])
@@ -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
 
@@ -0,0 +1,61 @@
1
+ module Trestle
2
+ class Registry
3
+ include Enumerable
4
+
5
+ # The admins hash is left exposed for backwards compatibility
6
+ attr_reader :admins
7
+
8
+ def initialize
9
+ reset!
10
+ end
11
+
12
+ def each(&block)
13
+ @admins.values.sort_by(&:admin_name).each(&block)
14
+ end
15
+
16
+ def reset!
17
+ @admins = {}
18
+ @models = {}
19
+ end
20
+
21
+ def empty?
22
+ none?
23
+ end
24
+
25
+ def register(admin, register_model: true)
26
+ @admins[admin.admin_name] = admin
27
+
28
+ if register_model && register_admin_for_model_loookup?(admin)
29
+ @models[admin.model.name] ||= admin
30
+ end
31
+
32
+ admin
33
+ end
34
+
35
+ def lookup_admin(admin)
36
+ # Given object is already an admin class
37
+ return admin if admin.is_a?(Class) && admin < Trestle::Admin
38
+
39
+ @admins[admin.to_s]
40
+ end
41
+ alias lookup lookup_admin
42
+
43
+ def lookup_model(model)
44
+ # Lookup each class in the model's ancestor chain
45
+ while model
46
+ admin = @models[model.name]
47
+ return admin if admin
48
+
49
+ model = model.superclass
50
+ end
51
+
52
+ # No admin found
53
+ nil
54
+ end
55
+
56
+ private
57
+ def register_admin_for_model_loookup?(admin)
58
+ admin.respond_to?(:model) && !(admin.respond_to?(:singular?) && admin.singular?)
59
+ end
60
+ end
61
+ end
@@ -1,17 +1,13 @@
1
1
  module Trestle
2
2
  class Reloader
3
- delegate :execute, :updated?, to: :updater
3
+ delegate :execute, :execute_if_updated, :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
5
+ def initialize(files, dirs = {})
6
+ @files, @dirs = files, dirs
11
7
  end
12
8
 
13
9
  def updater
14
- @updater ||= ActiveSupport::FileUpdateChecker.new([], compile_load_paths) do
10
+ @updater ||= ActiveSupport::FileUpdateChecker.new(@files, @dirs) do
15
11
  begin
16
12
  clear
17
13
 
@@ -30,16 +26,32 @@ module Trestle
30
26
  end
31
27
 
32
28
  def clear
33
- Trestle.admins = {}
29
+ Trestle.registry.reset!
34
30
  end
35
31
 
36
32
  def load_paths
37
33
  Trestle.config.load_paths.map { |path| path.respond_to?(:call) ? path.call : path }.flatten.map(&:to_s)
38
34
  end
39
35
 
40
- private
41
- def compile_load_paths
42
- Hash[*load_paths.map { |path| [path, "rb"] }.flatten]
36
+ def install(app)
37
+ reloader = self
38
+
39
+ app.reloaders << reloader
40
+
41
+ if app.respond_to?(:reloader)
42
+ # Rails >= 5.0
43
+ app.reloader.to_run do
44
+ reloader.execute_if_updated
45
+ true # Rails <= 5.1
46
+ end
47
+ else
48
+ # Rails 4.2
49
+ ActionDispatch::Reloader.to_prepare do
50
+ reloader.execute_if_updated
51
+ end
52
+ end
53
+
54
+ reloader.execute
43
55
  end
44
56
  end
45
57
  end
@@ -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
@@ -83,8 +83,9 @@ module Trestle
83
83
  admin.define_adapter_method(:count, &block)
84
84
  end
85
85
 
86
- def scopes(&block)
87
- admin.scopes.append(&block)
86
+ def scopes(options={}, &block)
87
+ admin.scopes.options.merge!(options)
88
+ admin.scopes.append(&block) if block_given?
88
89
  end
89
90
 
90
91
  def scope(name, scope=nil, options={}, &block)
@@ -42,15 +42,11 @@ module Trestle
42
42
  def apply_scopes(collection, params)
43
43
  unscoped = collection(params)
44
44
 
45
- active_scopes(params).reduce(collection) do |collection, scope|
45
+ scopes.active(params).reduce(collection) do |collection, scope|
46
46
  merge_scopes(collection, scope.apply(unscoped))
47
47
  end
48
48
  end
49
49
 
50
- def active_scopes(params)
51
- scopes.values.select { |s| s.active?(params) }
52
- end
53
-
54
50
  def apply_sorting(collection, params)
55
51
  return collection unless params[:sort]
56
52
 
@@ -0,0 +1,42 @@
1
+ module Trestle
2
+ class Resource
3
+ module Toolbar
4
+ class Builder < Trestle::Toolbar::Builder
5
+ delegate :admin, :instance, to: :@template
6
+ delegate :translate, :t, to: :admin
7
+
8
+ def new
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
+ end
11
+
12
+ def save
13
+ button(t("buttons.save", default: "Save %{model_name}"), style: :success)
14
+ end
15
+
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" }) if action?(:destroy)
18
+ end
19
+
20
+ def dismiss
21
+ button(t("buttons.ok", default: "OK"), style: :light, data: { dismiss: "modal" }) if @template.dialog_request?
22
+ end
23
+ alias ok dismiss
24
+
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
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,11 +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
3
+ require_relative "resource/adapter_methods"
4
+ require_relative "resource/builder"
5
+ require_relative "resource/collection"
6
+ require_relative "resource/toolbar"
9
7
 
10
8
  include AdapterMethods
11
9
 
@@ -50,9 +48,10 @@ module Trestle
50
48
  Collection.new(self, options).prepare(params)
51
49
  end
52
50
 
53
- # Evaluates the admin's scope block(s) and returns a hash of Scope objects keyed by the scope name
51
+ # Evaluates the admin's scope block(s) using the adapter context
52
+ # and returns a hash of Scope objects keyed by the scope name.
54
53
  def scopes
55
- @scopes ||= self.class.scopes.evaluate(@context)
54
+ @scopes ||= Scopes.new(self.class.scopes, adapter)
56
55
  end
57
56
 
58
57
  class << self
@@ -62,7 +61,7 @@ module Trestle
62
61
  end
63
62
 
64
63
  def scopes
65
- @scopes ||= Scopes.new(self)
64
+ @scopes ||= Scopes::Definition.new
66
65
  end
67
66
 
68
67
  def column_sorts
@@ -1,16 +1,17 @@
1
1
  module Trestle
2
2
  class Scopes
3
3
  class Block
4
- attr_reader :block, :admin
4
+ attr_reader :block
5
5
 
6
- def initialize(admin=nil, &block)
7
- @admin = admin
6
+ def initialize(&block)
8
7
  @block = block
9
8
  end
10
9
 
10
+ # Evaluates the scope block within the given admin context
11
+ # and returns an array of the scopes that were defined.
11
12
  def scopes(context)
12
- context = Evaluator.new(@admin, context)
13
- context.instance_exec(@admin, &block)
13
+ context = Evaluator.new(context)
14
+ context.instance_exec(context, &block)
14
15
  context.scopes
15
16
  end
16
17
 
@@ -19,8 +20,8 @@ module Trestle
19
20
 
20
21
  attr_reader :scopes
21
22
 
22
- def initialize(admin, context=nil)
23
- @admin, @context = admin, context
23
+ def initialize(context=nil)
24
+ @context = context
24
25
  @scopes = []
25
26
  end
26
27
 
@@ -30,7 +31,7 @@ module Trestle
30
31
  scope = nil
31
32
  end
32
33
 
33
- scopes << Scope.new(@admin, name, options, &(scope || block))
34
+ scopes << Scope.new(@context, name, options, &(scope || block))
34
35
  end
35
36
  end
36
37
  end
@@ -0,0 +1,22 @@
1
+ module Trestle
2
+ class Scopes
3
+ class Definition
4
+ attr_reader :blocks, :options
5
+
6
+ def initialize
7
+ @blocks = []
8
+ @options = {}
9
+ end
10
+
11
+ def append(&block)
12
+ @blocks << Block.new(&block)
13
+ end
14
+
15
+ # Evaluates each of the scope blocks within the given admin context
16
+ # and returns a hash of Scope objects keyed by the scope name.
17
+ def evaluate(context)
18
+ @blocks.map { |block| block.scopes(context) }.flatten.index_by(&:name)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -8,11 +8,15 @@ module Trestle
8
8
  end
9
9
 
10
10
  def to_param
11
- name
11
+ name unless default?
12
12
  end
13
13
 
14
14
  def label
15
- @options[:label] || I18n.t("admin.scopes.#{name}", default: name.to_s.humanize.titleize)
15
+ @options[:label] || @admin.t("scopes.#{name}", default: name.to_s.humanize.titleize)
16
+ end
17
+
18
+ def group
19
+ @options[:group]
16
20
  end
17
21
 
18
22
  def default?
@@ -1,23 +1,50 @@
1
1
  module Trestle
2
2
  class Scopes
3
- extend ActiveSupport::Autoload
3
+ require_relative "scopes/block"
4
+ require_relative "scopes/definition"
5
+ require_relative "scopes/scope"
4
6
 
5
- autoload :Block
6
- autoload :Scope
7
+ include Enumerable
7
8
 
8
- attr_reader :admin, :blocks
9
+ delegate :options, to: :@definition
9
10
 
10
- def initialize(admin)
11
- @admin = admin
12
- @blocks = []
11
+ def initialize(definition, context)
12
+ @definition = definition
13
+ @scopes = @definition.evaluate(context)
13
14
  end
14
15
 
15
- def append(&block)
16
- @blocks << Block.new(admin, &block)
16
+ def classes
17
+ [
18
+ 'scopes',
19
+ ('grouped' if grouped?),
20
+ layout_class,
21
+ options[:class]
22
+ ].compact
17
23
  end
18
24
 
19
- def evaluate(context)
20
- @blocks.map { |block| block.scopes(context) }.flatten.index_by(&:name)
25
+ def each(&block)
26
+ @scopes.values.each(&block)
27
+ end
28
+
29
+ def grouped?
30
+ options[:group] != false && any?(&:group)
31
+ end
32
+
33
+ def grouped
34
+ if grouped?
35
+ group_by(&:group)
36
+ else
37
+ { nil => @scopes.values.flatten }
38
+ end
39
+ end
40
+
41
+ def active(params)
42
+ select { |s| s.active?(params) }
43
+ end
44
+
45
+ private
46
+ def layout_class
47
+ "columns" if %w(column columns).include?(options[:layout].to_s)
21
48
  end
22
49
  end
23
50
  end
data/lib/trestle/tab.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require "action_view/helpers"
2
+
1
3
  module Trestle
2
4
  class Tab
3
5
  include ActionView::Helpers::TagHelper
@@ -1,10 +1,10 @@
1
1
  module Trestle
2
2
  class Table
3
3
  class ActionsColumn
4
- attr_reader :table, :toolbar, :options
4
+ attr_reader :toolbar, :options
5
5
 
6
- def initialize(table, options={}, &block)
7
- @table, @options = table, options
6
+ def initialize(options={}, &block)
7
+ @options = options
8
8
  @toolbar = Toolbar.new(ActionsBuilder)
9
9
 
10
10
  if block_given?
@@ -14,8 +14,8 @@ module Trestle
14
14
  end
15
15
  end
16
16
 
17
- def renderer(template)
18
- Renderer.new(self, template)
17
+ def renderer(table:, template:)
18
+ Renderer.new(self, table: table, template: template)
19
19
  end
20
20
 
21
21
  def default_actions
@@ -71,7 +71,7 @@ module Trestle
71
71
  end
72
72
 
73
73
  def content(instance)
74
- @template.render_toolbar(@column.toolbar, instance, table.admin)
74
+ @template.render_toolbar(@column.toolbar, instance, @table.admin)
75
75
  end
76
76
  end
77
77
  end
@@ -13,15 +13,22 @@ module Trestle
13
13
  admin.default_table_attributes.map.with_index do |attribute, index|
14
14
  case attribute.type
15
15
  when :association
16
- Column.new(self, attribute.association_name, sort: false)
16
+ Column.new(attribute.association_name, sort: false)
17
+ when :enum
18
+ Column.new(attribute.name, align: :center, sort: attribute.name) do |instance|
19
+ if value = instance.public_send(attribute.name)
20
+ full_attribute_name = [attribute.name.to_s.pluralize, value].join(".")
21
+ status_tag(admin.human_attribute_name(full_attribute_name, default: value.humanize))
22
+ end
23
+ end
17
24
  else
18
- Column.new(self, attribute.name, link: index.zero?, align: (:center if [:datetime, :boolean].include?(attribute.type)))
25
+ Column.new(attribute.name, link: index.zero?, align: (:center if [:datetime, :boolean].include?(attribute.type)))
19
26
  end
20
27
  end
21
28
  end
22
29
 
23
30
  def actions_column
24
- ActionsColumn.new(self)
31
+ ActionsColumn.new
25
32
  end
26
33
  end
27
34
  end
@@ -9,11 +9,11 @@ module Trestle
9
9
  end
10
10
 
11
11
  def row(options={}, &block)
12
- table.row = Row.new(table, options, &block)
12
+ table.row = Row.new(options, &block)
13
13
  end
14
14
 
15
15
  def selectable_column(options={})
16
- table.columns << SelectColumn.new(table, options)
16
+ table.columns << SelectColumn.new(options)
17
17
  end
18
18
 
19
19
  def column(field, proc=nil, options={}, &block)
@@ -22,11 +22,11 @@ module Trestle
22
22
  proc = nil
23
23
  end
24
24
 
25
- table.columns << Column.new(table, field, options, &(proc || block))
25
+ table.columns << Column.new(field, options, &(proc || block))
26
26
  end
27
27
 
28
28
  def actions(options={}, &block)
29
- table.columns << ActionsColumn.new(table, options, &block)
29
+ table.columns << ActionsColumn.new(options, &block)
30
30
  end
31
31
  end
32
32
  end