trestle 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/Gemfile +2 -2
  4. data/app/assets/bundle/trestle/bundle.css +0 -0
  5. data/app/assets/bundle/trestle/bundle.js +0 -0
  6. data/app/assets/bundle/trestle/fa-brands-400.eot +0 -0
  7. data/app/assets/bundle/trestle/fa-brands-400.svg +0 -0
  8. data/app/assets/bundle/trestle/fa-brands-400.ttf +0 -0
  9. data/app/assets/bundle/trestle/fa-brands-400.woff +0 -0
  10. data/app/assets/bundle/trestle/fa-brands-400.woff2 +0 -0
  11. data/app/assets/bundle/trestle/fa-regular-400.eot +0 -0
  12. data/app/assets/bundle/trestle/fa-regular-400.svg +0 -0
  13. data/app/assets/bundle/trestle/fa-regular-400.ttf +0 -0
  14. data/app/assets/bundle/trestle/fa-regular-400.woff +0 -0
  15. data/app/assets/bundle/trestle/fa-regular-400.woff2 +0 -0
  16. data/app/assets/bundle/trestle/fa-solid-900.eot +0 -0
  17. data/app/assets/bundle/trestle/fa-solid-900.svg +0 -0
  18. data/app/assets/bundle/trestle/fa-solid-900.ttf +0 -0
  19. data/app/assets/bundle/trestle/fa-solid-900.woff +0 -0
  20. data/app/assets/bundle/trestle/fa-solid-900.woff2 +0 -0
  21. data/app/assets/bundle/trestle/flatpickr/ar.js +0 -0
  22. data/app/assets/bundle/trestle/flatpickr/at.js +0 -0
  23. data/app/assets/bundle/trestle/flatpickr/az.js +0 -0
  24. data/app/assets/bundle/trestle/flatpickr/be.js +0 -0
  25. data/app/assets/bundle/trestle/flatpickr/bg.js +0 -0
  26. data/app/assets/bundle/trestle/flatpickr/bn.js +0 -0
  27. data/app/assets/bundle/trestle/flatpickr/bs.js +0 -0
  28. data/app/assets/bundle/trestle/flatpickr/cat.js +0 -0
  29. data/app/assets/bundle/trestle/flatpickr/cs.js +0 -0
  30. data/app/assets/bundle/trestle/flatpickr/cy.js +0 -0
  31. data/app/assets/bundle/trestle/flatpickr/da.js +0 -0
  32. data/app/assets/bundle/trestle/flatpickr/de.js +0 -0
  33. data/app/assets/bundle/trestle/flatpickr/default.js +0 -0
  34. data/app/assets/bundle/trestle/flatpickr/eo.js +0 -0
  35. data/app/assets/bundle/trestle/flatpickr/es.js +0 -0
  36. data/app/assets/bundle/trestle/flatpickr/et.js +0 -0
  37. data/app/assets/bundle/trestle/flatpickr/fa.js +0 -0
  38. data/app/assets/bundle/trestle/flatpickr/fi.js +0 -0
  39. data/app/assets/bundle/trestle/flatpickr/fo.js +0 -0
  40. data/app/assets/bundle/trestle/flatpickr/fr.js +0 -0
  41. data/app/assets/bundle/trestle/flatpickr/ga.js +0 -0
  42. data/app/assets/bundle/trestle/flatpickr/gr.js +0 -0
  43. data/app/assets/bundle/trestle/flatpickr/he.js +0 -0
  44. data/app/assets/bundle/trestle/flatpickr/hi.js +0 -0
  45. data/app/assets/bundle/trestle/flatpickr/hr.js +0 -0
  46. data/app/assets/bundle/trestle/flatpickr/hu.js +0 -0
  47. data/app/assets/bundle/trestle/flatpickr/id.js +0 -0
  48. data/app/assets/bundle/trestle/flatpickr/is.js +0 -0
  49. data/app/assets/bundle/trestle/flatpickr/it.js +0 -0
  50. data/app/assets/bundle/trestle/flatpickr/ja.js +0 -0
  51. data/app/assets/bundle/trestle/flatpickr/ka.js +0 -0
  52. data/app/assets/bundle/trestle/flatpickr/km.js +0 -0
  53. data/app/assets/bundle/trestle/flatpickr/ko.js +0 -0
  54. data/app/assets/bundle/trestle/flatpickr/kz.js +0 -0
  55. data/app/assets/bundle/trestle/flatpickr/lt.js +0 -0
  56. data/app/assets/bundle/trestle/flatpickr/lv.js +0 -0
  57. data/app/assets/bundle/trestle/flatpickr/mk.js +0 -0
  58. data/app/assets/bundle/trestle/flatpickr/mn.js +0 -0
  59. data/app/assets/bundle/trestle/flatpickr/my.js +0 -0
  60. data/app/assets/bundle/trestle/flatpickr/nl.js +0 -0
  61. data/app/assets/bundle/trestle/flatpickr/no.js +0 -0
  62. data/app/assets/bundle/trestle/flatpickr/pa.js +0 -0
  63. data/app/assets/bundle/trestle/flatpickr/pl.js +0 -0
  64. data/app/assets/bundle/trestle/flatpickr/pt.js +0 -0
  65. data/app/assets/bundle/trestle/flatpickr/ro.js +0 -0
  66. data/app/assets/bundle/trestle/flatpickr/ru.js +0 -0
  67. data/app/assets/bundle/trestle/flatpickr/si.js +0 -0
  68. data/app/assets/bundle/trestle/flatpickr/sk.js +0 -0
  69. data/app/assets/bundle/trestle/flatpickr/sl.js +0 -0
  70. data/app/assets/bundle/trestle/flatpickr/sq.js +0 -0
  71. data/app/assets/bundle/trestle/flatpickr/sr-cyr.js +0 -0
  72. data/app/assets/bundle/trestle/flatpickr/sr.js +0 -0
  73. data/app/assets/bundle/trestle/flatpickr/sv.js +0 -0
  74. data/app/assets/bundle/trestle/flatpickr/th.js +0 -0
  75. data/app/assets/bundle/trestle/flatpickr/tr.js +0 -0
  76. data/app/assets/bundle/trestle/flatpickr/uk.js +0 -0
  77. data/app/assets/bundle/trestle/flatpickr/uz.js +0 -0
  78. data/app/assets/bundle/trestle/flatpickr/uz_latn.js +0 -0
  79. data/app/assets/bundle/trestle/flatpickr/vn.js +0 -0
  80. data/app/assets/bundle/trestle/flatpickr/zh-tw.js +0 -0
  81. data/app/assets/bundle/trestle/flatpickr/zh.js +0 -0
  82. data/app/helpers/trestle/hook_helper.rb +1 -27
  83. data/app/helpers/trestle/table_helper.rb +15 -0
  84. data/app/views/trestle/resource/index.html.erb +1 -1
  85. data/app/views/trestle/table/_pagination.html.erb +1 -1
  86. data/config/locales/vi.rb +18 -0
  87. data/config/locales/vi.yml +101 -0
  88. data/frontend/css/components/_scopes.scss +2 -0
  89. data/frontend/css/components/_table.scss +4 -0
  90. data/frontend/js/components/pagination.js +51 -0
  91. data/frontend/js/index.js +1 -0
  92. data/lib/trestle/admin.rb +12 -2
  93. data/lib/trestle/engine.rb +3 -6
  94. data/lib/trestle/form/field.rb +19 -12
  95. data/lib/trestle/form/fields/collection_select.rb +1 -1
  96. data/lib/trestle/form/fields/date_picker.rb +9 -3
  97. data/lib/trestle/form/fields/file_field.rb +1 -1
  98. data/lib/trestle/form/fields/form_group.rb +13 -2
  99. data/lib/trestle/form/fields/grouped_collection_select.rb +1 -1
  100. data/lib/trestle/form/fields/range_field.rb +2 -4
  101. data/lib/trestle/form/fields/select.rb +2 -3
  102. data/lib/trestle/form/fields/static_field.rb +2 -2
  103. data/lib/trestle/form/fields/tag_select.rb +1 -1
  104. data/lib/trestle/form/fields/time_zone_select.rb +1 -1
  105. data/lib/trestle/form/renderer.rb +5 -3
  106. data/lib/trestle/hook.rb +3 -29
  107. data/lib/trestle/hook/helpers.rb +33 -0
  108. data/lib/trestle/hook/set.rb +32 -0
  109. data/lib/trestle/reloader.rb +25 -5
  110. data/lib/trestle/resource.rb +4 -3
  111. data/lib/trestle/scopes.rb +5 -4
  112. data/lib/trestle/scopes/block.rb +9 -8
  113. data/lib/trestle/scopes/scope.rb +1 -1
  114. data/lib/trestle/version.rb +1 -1
  115. data/package.json +8 -8
  116. data/yarn.lock +1360 -1452
  117. metadata +12 -5
@@ -29,6 +29,7 @@ import Dialog from './components/dialog'
29
29
  import './components/file'
30
30
  import './components/form'
31
31
  import './components/gallery'
32
+ import './components/pagination'
32
33
  import './components/select'
33
34
  import './components/sidebar'
34
35
  import './components/table'
@@ -90,12 +90,12 @@ module Trestle
90
90
  defaults = [:"admin.#{i18n_key}.#{key}", :"admin.#{key}"]
91
91
  defaults << options[:default] if options[:default]
92
92
 
93
- I18n.t(defaults.shift, options.merge(default: defaults))
93
+ I18n.t(defaults.shift, **options.merge(default: defaults))
94
94
  end
95
95
  alias t translate
96
96
 
97
97
  def parameter_name
98
- admin_name.singularize
98
+ unscope_path(admin_name.singularize)
99
99
  end
100
100
 
101
101
  def route_name
@@ -165,6 +165,16 @@ module Trestle
165
165
  def validate!
166
166
  # No validations by default. This can be overridden in subclasses.
167
167
  end
168
+
169
+ private
170
+ def unscope_path(path)
171
+ path = path.to_s
172
+ if i = path.rindex("/")
173
+ path[(i + 1)..-1]
174
+ else
175
+ path
176
+ end
177
+ end
168
178
  end
169
179
  end
170
180
  end
@@ -44,12 +44,9 @@ module Trestle
44
44
  Engine.reset_helpers!
45
45
  end
46
46
 
47
- config.to_prepare do
48
- Engine.reloader.execute
49
- end
50
-
51
- def reloader
52
- @reloader ||= Trestle::Reloader.new
47
+ config.after_initialize do |app|
48
+ reloader = Trestle::Reloader.new(*app.watchable_args)
49
+ reloader.install(app) unless app.config.eager_load
53
50
  end
54
51
 
55
52
  def reset_helpers!
@@ -17,17 +17,17 @@ module Trestle
17
17
  end
18
18
 
19
19
  def form_group(opts={})
20
- @builder.form_group(name, @wrapper.merge(opts)) do
20
+ if @wrapper
21
+ @builder.form_group(name, @wrapper.merge(opts)) do
22
+ yield
23
+ end
24
+ else
21
25
  yield
22
26
  end
23
27
  end
24
28
 
25
29
  def render
26
- if @wrapper
27
- form_group do
28
- field
29
- end
30
- else
30
+ form_group do
31
31
  field
32
32
  end
33
33
  end
@@ -40,6 +40,10 @@ module Trestle
40
40
  Trestle::Options.new(readonly: readonly?)
41
41
  end
42
42
 
43
+ def disabled?
44
+ options[:disabled]
45
+ end
46
+
43
47
  def readonly?
44
48
  options[:readonly] || admin.readonly?
45
49
  end
@@ -57,8 +61,11 @@ module Trestle
57
61
  end
58
62
 
59
63
  def extract_wrapper_options!
60
- unless options[:wrapper] == false
61
- @wrapper = extract_wrapper_options(*Fields::FormGroup::WRAPPER_OPTIONS).merge(options.delete(:wrapper))
64
+ wrapper = options.delete(:wrapper)
65
+
66
+ unless wrapper == false
67
+ @wrapper = extract_options(*Fields::FormGroup::WRAPPER_OPTIONS)
68
+ @wrapper.merge!(wrapper) if wrapper.is_a?(Hash)
62
69
  end
63
70
  end
64
71
 
@@ -83,10 +90,10 @@ module Trestle
83
90
  keys
84
91
  end
85
92
 
86
- def extract_wrapper_options(*keys)
87
- wrapper = Trestle::Options.new
88
- keys.each { |k| wrapper[k] = options.delete(k) if options.key?(k) }
89
- wrapper
93
+ def extract_options(*keys)
94
+ extracted = Trestle::Options.new
95
+ keys.each { |k| extracted[k] = options.delete(k) if options.key?(k) }
96
+ extracted
90
97
  end
91
98
  end
92
99
  end
@@ -16,7 +16,7 @@ module Trestle
16
16
  end
17
17
 
18
18
  def default_html_options
19
- Trestle::Options.new(class: ["form-control"], disabled: readonly?, data: { enable_select2: true })
19
+ Trestle::Options.new(class: ["form-control"], disabled: disabled? || readonly?, data: { enable_select2: true })
20
20
  end
21
21
  end
22
22
  end
@@ -1,9 +1,11 @@
1
1
  module Trestle::Form::Fields::DatePicker
2
2
  def normalize_options!
3
- options[:prepend] ||= options.delete(:icon) { default_icon }
3
+ unless options[:prepend] == false
4
+ options[:prepend] ||= options.delete(:icon) { default_icon }
5
+ end
4
6
 
5
- unless options[:disabled] || options[:readonly]
6
- options.reverse_merge!(data: { picker: options.delete(:picker) { true }, allow_clear: true })
7
+ if enable_date_picker?
8
+ options.reverse_merge!(data: { picker: true, allow_clear: true })
7
9
  end
8
10
 
9
11
  super
@@ -12,4 +14,8 @@ module Trestle::Form::Fields::DatePicker
12
14
  def default_icon
13
15
  icon("fa fa-calendar")
14
16
  end
17
+
18
+ def enable_date_picker?
19
+ !disabled? && !readonly? && options[:picker] != false
20
+ end
15
21
  end
@@ -18,7 +18,7 @@ module Trestle
18
18
  end
19
19
 
20
20
  def choose_file_text
21
- I18n.t("trestle.file.choose_file", default: "Choose file")
21
+ I18n.t("trestle.file.choose_file", default: "Choose file...")
22
22
  end
23
23
 
24
24
  def browse_text
@@ -4,12 +4,19 @@ module Trestle
4
4
  class FormGroup < Field
5
5
  WRAPPER_OPTIONS = [:help, :label, :hide_label]
6
6
 
7
+ def initialize(builder, template, name=nil, options={}, &block)
8
+ # Normalize options passed as name parameter
9
+ name, options = nil, name if name.is_a?(Hash)
10
+
11
+ super(builder, template, name, options, &block)
12
+ end
13
+
7
14
  def render
8
15
  content_tag(:div, options.except(*WRAPPER_OPTIONS)) do
9
- concat label unless options[:label] == false
16
+ concat label if name && options[:label] != false
10
17
  concat template.capture(&block) if block
11
18
  concat help_message if options[:help]
12
- concat error_message if errors.any?
19
+ concat error_message if name && errors.any?
13
20
  end
14
21
  end
15
22
 
@@ -48,6 +55,10 @@ module Trestle
48
55
  def error_class
49
56
  "has-error"
50
57
  end
58
+
59
+ def error_keys
60
+ name ? super : []
61
+ end
51
62
  end
52
63
  end
53
64
  end
@@ -16,7 +16,7 @@ module Trestle
16
16
  end
17
17
 
18
18
  def default_html_options
19
- Trestle::Options.new(class: ["form-control"], data: { enable_select2: true })
19
+ Trestle::Options.new(class: ["form-control"], disabled: disabled? || readonly?, data: { enable_select2: true })
20
20
  end
21
21
  end
22
22
  end
@@ -10,10 +10,8 @@ module Trestle
10
10
  options[:custom] != false
11
11
  end
12
12
 
13
- def normalize_options!
14
- options.reverse_merge!(class: ["custom-range"]) if custom?
15
-
16
- super
13
+ def defaults
14
+ custom? ? super.merge(class: ["custom-range"]) : super
17
15
  end
18
16
  end
19
17
  end
@@ -18,7 +18,7 @@ module Trestle
18
18
  end
19
19
 
20
20
  def default_html_options
21
- Trestle::Options.new(class: ["form-control"], disabled: readonly?, data: { enable_select2: true })
21
+ Trestle::Options.new(class: ["form-control"], disabled: disabled? || readonly?, data: { enable_select2: true })
22
22
  end
23
23
 
24
24
  def default_choices
@@ -44,8 +44,7 @@ module Trestle
44
44
  protected
45
45
  def option_text_and_value(option)
46
46
  if !option.is_a?(String) && option.respond_to?(:first) && option.respond_to?(:last)
47
- option = option.reject { |e| Hash === e } if Array === option
48
- [option.first, option.last]
47
+ option
49
48
  elsif option.respond_to?(:id)
50
49
  [Trestle::Display.new(option).to_s, option.id]
51
50
  else
@@ -5,8 +5,8 @@ module Trestle
5
5
  attr_reader :value
6
6
 
7
7
  def initialize(builder, template, name, value=nil, options={}, &block)
8
- if block_given? && value.is_a?(Hash)
9
- options = value
8
+ if value.is_a?(Hash)
9
+ @value, options = nil, value
10
10
  else
11
11
  @value = value
12
12
  end
@@ -9,7 +9,7 @@ module Trestle
9
9
  end
10
10
 
11
11
  def default_html_options
12
- super.merge(multiple: true, class: "tag-select", disabled: readonly?, data: { tags: true })
12
+ super.merge(multiple: true, class: ["tag-select"], data: { tags: true })
13
13
  end
14
14
  end
15
15
  end
@@ -16,7 +16,7 @@ module Trestle
16
16
  end
17
17
 
18
18
  def default_html_options
19
- Trestle::Options.new(class: ["form-control"], disabled: readonly?, data: { enable_select2: true })
19
+ Trestle::Options.new(class: ["form-control"], disabled: disabled? || readonly?, data: { enable_select2: true })
20
20
  end
21
21
  end
22
22
  end
@@ -7,11 +7,13 @@ module Trestle
7
7
  include ::ActionView::Context
8
8
  include ::ActionView::Helpers::CaptureHelper
9
9
 
10
+ # Include hook helpers directly so that they are evaluated in the context of the renderer instead of the template.
11
+ include Hook::Helpers
12
+
10
13
  # Whitelisted helpers will concatenate their result to the output buffer when called.
11
- WHITELISTED_HELPERS = [:row, :col, :hook, :render, :tab, :table, :divider, :h1, :h2, :h3, :h4, :h5, :h6, :card, :panel, :well]
14
+ WHITELISTED_HELPERS = [:row, :col, :render, :tab, :table, :divider, :h1, :h2, :h3, :h4, :h5, :h6, :card, :panel, :well]
12
15
 
13
- # Raw block helpers will pass their block argument directly to the method
14
- # without wrapping it in a new output buffer.
16
+ # Raw block helpers will pass their block argument directly to the method without wrapping it in a new output buffer.
15
17
  RAW_BLOCK_HELPERS = [:table, :toolbar]
16
18
 
17
19
  # The #select and #display methods are defined on Kernel. Undefine them so
@@ -1,5 +1,8 @@
1
1
  module Trestle
2
2
  class Hook
3
+ require_relative "hook/helpers"
4
+ require_relative "hook/set"
5
+
3
6
  attr_reader :name, :options, :block
4
7
 
5
8
  def initialize(name, options={}, &block)
@@ -23,34 +26,5 @@ module Trestle
23
26
  def evaluate(context, *args)
24
27
  context.instance_exec(*args, &block)
25
28
  end
26
-
27
- class Set
28
- attr_reader :hooks
29
-
30
- def initialize
31
- @hooks = {}
32
- end
33
-
34
- def append(name, options={}, &block)
35
- hooks[name.to_s] ||= []
36
- hooks[name.to_s] << Hook.new(name.to_s, options, &block)
37
- end
38
-
39
- def any?(name)
40
- hooks.key?(name.to_s) && hooks[name.to_s].any?
41
- end
42
-
43
- def for(name)
44
- hooks.fetch(name.to_s) { [] }
45
- end
46
-
47
- def empty?
48
- hooks.empty?
49
- end
50
-
51
- def ==(other)
52
- other.is_a?(self.class) && hooks == other.hooks
53
- end
54
- end
55
29
  end
56
30
  end
@@ -0,0 +1,33 @@
1
+ module Trestle
2
+ class Hook
3
+ module Helpers
4
+ def hook(name, *args, &block)
5
+ hooks = hooks(name)
6
+
7
+ if hooks.any?
8
+ safe_join(hooks.map { |hook|
9
+ hook.evaluate(self, *args)
10
+ }, "\n")
11
+ elsif block_given?
12
+ capture(*args, &block)
13
+ end
14
+ end
15
+
16
+ def hook?(name)
17
+ hooks(name).any?
18
+ end
19
+
20
+ protected
21
+ def hooks(name)
22
+ hook_sets.map { |set| set.for(name) }.inject(&:+).select { |h| h.visible?(self) }
23
+ end
24
+
25
+ def hook_sets
26
+ @_hook_sets ||= [
27
+ (admin.hooks if defined?(admin) && admin),
28
+ Trestle.config.hooks
29
+ ].compact
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ module Trestle
2
+ class Hook
3
+ class Set
4
+ attr_reader :hooks
5
+
6
+ def initialize
7
+ @hooks = {}
8
+ end
9
+
10
+ def append(name, options={}, &block)
11
+ hooks[name.to_s] ||= []
12
+ hooks[name.to_s] << Hook.new(name.to_s, options, &block)
13
+ end
14
+
15
+ def any?(name)
16
+ hooks.key?(name.to_s) && hooks[name.to_s].any?
17
+ end
18
+
19
+ def for(name)
20
+ hooks.fetch(name.to_s) { [] }
21
+ end
22
+
23
+ def empty?
24
+ hooks.empty?
25
+ end
26
+
27
+ def ==(other)
28
+ other.is_a?(self.class) && hooks == other.hooks
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,9 +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
+
5
+ def initialize(files, dirs = {})
6
+ @files, @dirs = files, dirs
7
+ end
4
8
 
5
9
  def updater
6
- @updater ||= ActiveSupport::FileUpdateChecker.new([], compile_load_paths) do
10
+ @updater ||= ActiveSupport::FileUpdateChecker.new(@files, @dirs) do
7
11
  begin
8
12
  clear
9
13
 
@@ -29,9 +33,25 @@ module Trestle
29
33
  Trestle.config.load_paths.map { |path| path.respond_to?(:call) ? path.call : path }.flatten.map(&:to_s)
30
34
  end
31
35
 
32
- private
33
- def compile_load_paths
34
- 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
35
55
  end
36
56
  end
37
57
  end