avo 2.18.1 → 2.20.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of avo might be problematic. Click here for more details.

Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -6
  3. data/Gemfile.lock +76 -77
  4. data/app/components/avo/actions_component.html.erb +1 -1
  5. data/app/components/avo/actions_component.rb +4 -4
  6. data/app/components/avo/base_component.rb +17 -0
  7. data/app/components/avo/card_component.html.erb +15 -15
  8. data/app/components/avo/card_component.rb +7 -5
  9. data/app/components/avo/field_wrapper_component.rb +7 -1
  10. data/app/components/avo/fields/has_one_field/show_component.rb +1 -2
  11. data/app/components/avo/fields/index_component.rb +4 -3
  12. data/app/components/avo/fields/select_field/edit_component.html.erb +1 -1
  13. data/app/components/avo/filters_component.html.erb +1 -1
  14. data/app/components/avo/filters_component.rb +2 -2
  15. data/app/components/avo/index/grid_item_component.rb +2 -2
  16. data/app/components/avo/index/resource_controls_component.rb +2 -2
  17. data/app/components/avo/index/table_row_component.html.erb +1 -1
  18. data/app/components/avo/item_switcher_component.html.erb +1 -1
  19. data/app/components/avo/panel_component.html.erb +1 -1
  20. data/app/components/avo/resource_component.rb +1 -1
  21. data/app/components/avo/resource_sidebar_component.rb +1 -6
  22. data/app/components/avo/sidebar/group_component.html.erb +18 -12
  23. data/app/components/avo/sidebar/heading_component.html.erb +17 -10
  24. data/app/components/avo/sidebar_profile_component.rb +3 -1
  25. data/app/components/avo/tab_group_component.rb +1 -1
  26. data/app/components/avo/views/resource_show_component.html.erb +1 -1
  27. data/app/controllers/avo/actions_controller.rb +27 -5
  28. data/app/controllers/avo/application_controller.rb +7 -0
  29. data/app/controllers/avo/base_controller.rb +30 -18
  30. data/app/controllers/avo/dashboards/cards_controller.rb +37 -0
  31. data/app/controllers/avo/dashboards_controller.rb +1 -0
  32. data/app/helpers/avo/application_helper.rb +5 -1
  33. data/app/javascript/js/controllers/search_controller.js +11 -2
  34. data/app/views/avo/actions/keep_modal_open.turbo_stream.erb +5 -0
  35. data/app/views/avo/actions/show.html.erb +2 -1
  36. data/app/views/avo/{cards → dashboards/cards}/_chartkick_card.html.erb +0 -0
  37. data/app/views/avo/{cards → dashboards/cards}/_metric_card.html.erb +0 -0
  38. data/app/views/avo/{cards → dashboards/cards}/chartkick_missing.html.erb +0 -0
  39. data/app/views/avo/{cards → dashboards/cards}/show.html.erb +0 -0
  40. data/app/views/avo/partials/_branding.html.erb +1 -0
  41. data/app/views/layouts/avo/application.html.erb +1 -1
  42. data/avo.gemspec +1 -2
  43. data/bin/init +11 -1
  44. data/bin/test +1 -0
  45. data/config/routes.rb +2 -2
  46. data/db/factories.rb +10 -0
  47. data/lib/avo/app.rb +14 -1
  48. data/lib/avo/base_action.rb +35 -10
  49. data/lib/avo/base_card.rb +3 -1
  50. data/lib/avo/base_resource.rb +21 -10
  51. data/lib/avo/concerns/breadcrumbs.rb +96 -0
  52. data/lib/avo/concerns/filters_session_handler.rb +43 -0
  53. data/lib/avo/concerns/has_fields.rb +2 -0
  54. data/lib/avo/concerns/has_html_attributes.rb +14 -16
  55. data/lib/avo/concerns/visible_items.rb +44 -0
  56. data/lib/avo/configuration/branding.rb +10 -2
  57. data/lib/avo/configuration.rb +3 -0
  58. data/lib/avo/dashboards/base_dashboard.rb +7 -1
  59. data/lib/avo/dynamic_router.rb +16 -15
  60. data/lib/avo/engine.rb +6 -9
  61. data/lib/avo/fields/base_field.rb +21 -12
  62. data/lib/avo/fields/concerns/has_default.rb +17 -0
  63. data/lib/avo/fields/concerns/is_readonly.rb +1 -1
  64. data/lib/avo/fields/concerns/is_required.rb +2 -2
  65. data/lib/avo/fields/has_base_field.rb +2 -0
  66. data/lib/avo/fields/key_value_field.rb +1 -1
  67. data/lib/avo/fields/select_field.rb +39 -34
  68. data/lib/avo/filters/base_filter.rb +24 -2
  69. data/lib/avo/hosts/resource_view_record_host.rb +7 -0
  70. data/lib/avo/hosts/visibility_host.rb +13 -0
  71. data/lib/avo/panel.rb +4 -1
  72. data/lib/avo/resources/controls/action.rb +1 -3
  73. data/lib/avo/sidebar.rb +1 -31
  74. data/lib/avo/tab.rb +5 -22
  75. data/lib/avo/version.rb +1 -1
  76. data/lib/avo.rb +9 -0
  77. data/lib/generators/avo/resource_generator.rb +281 -0
  78. data/lib/generators/avo/templates/action.tt +3 -0
  79. data/lib/generators/avo/templates/filters/boolean_filter.tt +3 -0
  80. data/lib/generators/avo/templates/filters/multiple_select_filter.tt +3 -0
  81. data/lib/generators/avo/templates/filters/select_filter.tt +3 -0
  82. data/lib/generators/avo/templates/filters/text_filter.tt +3 -0
  83. data/lib/generators/avo/templates/initializer/avo.tt +4 -0
  84. data/lib/generators/avo/templates/resource/controller.tt +1 -1
  85. data/lib/generators/avo/templates/resource/resource.tt +2 -2
  86. data/lib/generators/model_generator.rb +10 -0
  87. data/lib/generators/rails/avo_resource_generator.rb +11 -0
  88. data/public/avo-assets/avo.base.css +14 -14
  89. data/public/avo-assets/avo.base.js +1 -1
  90. data/public/avo-assets/avo.base.js.map +2 -2
  91. data/public/avo-assets/favicon.ico +0 -0
  92. data/{app/assets/svgs → public/avo-assets}/placeholder.svg +0 -0
  93. metadata +20 -25
  94. data/app/controllers/avo/cards_controller.rb +0 -35
  95. data/config/master.key +0 -1
@@ -19,6 +19,7 @@ module Avo
19
19
  attr_accessor :model
20
20
  attr_accessor :resource
21
21
  attr_accessor :user
22
+ attr_reader :arguments
22
23
 
23
24
  delegate :view, to: :class
24
25
  delegate :context, to: ::Avo::App
@@ -34,9 +35,9 @@ module Avo
34
35
  def form_data_attributes
35
36
  # We can't respond with a file download from Turbo se we disable it on the form
36
37
  if may_download_file
37
- {turbo: false, remote: false}
38
+ {turbo: false, remote: false, action_target: :form}
38
39
  else
39
- {"turbo-frame": "_top", "action-target": "form"}
40
+ {turbo_frame: :_top, action_target: :form}
40
41
  end
41
42
  end
42
43
 
@@ -56,11 +57,12 @@ module Avo
56
57
  self.class.to_s.demodulize.underscore.humanize(keep_id_suffix: true)
57
58
  end
58
59
 
59
- def initialize(model: nil, resource: nil, user: nil, view: nil)
60
+ def initialize(model: nil, resource: nil, user: nil, view: nil, arguments: {})
60
61
  self.class.model = model if model.present?
61
62
  self.class.resource = resource if resource.present?
62
63
  self.class.user = user if user.present?
63
64
  self.class.view = view if view.present?
65
+ @arguments = arguments
64
66
 
65
67
  self.class.message ||= I18n.t("avo.are_you_sure_you_want_to_run_this_option")
66
68
  self.class.confirm_button_label ||= I18n.t("avo.run")
@@ -114,15 +116,26 @@ module Avo
114
116
  self
115
117
  end
116
118
 
117
- def visible_in_view
118
- # Run the visible block if available
119
- return instance_exec(resource: self.class.resource, view: view, &visible) if visible.present?
119
+ def visible_in_view(parent_model: nil, parent_resource: nil)
120
+ if visible.blank?
121
+ # Hide on the :new view by default
122
+ return false if view == :new
120
123
 
121
- # Hide on the :new view by default
122
- return false if view == :new
124
+ # Show on all other views
125
+ return true
126
+ end
123
127
 
124
- # Show on all other views
125
- true
128
+ # Run the visible block if available
129
+ Avo::Hosts::VisibilityHost.new(
130
+ block: visible,
131
+ model: self.class.model,
132
+ params: params,
133
+ parent_model: parent_model,
134
+ parent_resource: parent_resource,
135
+ resource: self.class.resource,
136
+ view: self.class.view,
137
+ arguments: arguments
138
+ ).handle
126
139
  end
127
140
 
128
141
  def param_id
@@ -136,6 +149,12 @@ module Avo
136
149
  end
137
150
 
138
151
  def fail(text)
152
+ Rails.logger.warn "DEPRECATION WARNING: Action fail method is deprecated in favor of error method and will be removed from Avo version 3.0.0"
153
+
154
+ error text
155
+ end
156
+
157
+ def error(text)
139
158
  add_message text, :error
140
159
 
141
160
  self
@@ -153,6 +172,12 @@ module Avo
153
172
  self
154
173
  end
155
174
 
175
+ def keep_modal_open
176
+ response[:keep_modal_open] = true
177
+
178
+ self
179
+ end
180
+
156
181
  # Add a placeholder silent message from when a user wants to do a redirect action or something similar
157
182
  def silent
158
183
  add_message nil, :silent
data/lib/avo/base_card.rb CHANGED
@@ -15,6 +15,7 @@ module Avo
15
15
 
16
16
  attr_accessor :dashboard
17
17
  attr_accessor :options
18
+ attr_accessor :arguments
18
19
  attr_accessor :index
19
20
  attr_accessor :params
20
21
 
@@ -26,9 +27,10 @@ module Avo
26
27
  end
27
28
  end
28
29
 
29
- def initialize(dashboard:, options: {}, index: 0, cols: nil, rows: nil, label: nil, description: nil, refresh_every: nil)
30
+ def initialize(dashboard:, options: {}, arguments: {}, index: 0, cols: nil, rows: nil, label: nil, description: nil, refresh_every: nil)
30
31
  @dashboard = dashboard
31
32
  @options = options
33
+ @arguments = arguments
32
34
  @index = index
33
35
  @cols = cols
34
36
  @rows = rows
@@ -49,6 +49,7 @@ module Avo
49
49
  class_attribute :record_selector, default: true
50
50
  class_attribute :keep_filters_panel_open, default: false
51
51
  class_attribute :extra_params
52
+ class_attribute :link_to_child_resource, default: false
52
53
 
53
54
  class << self
54
55
  delegate :t, to: ::I18n
@@ -61,16 +62,18 @@ module Avo
61
62
  self.grid_loader = grid_collector
62
63
  end
63
64
 
64
- def action(action_class)
65
+ def action(action_class, arguments: {})
65
66
  self.actions_loader ||= Avo::Loaders::Loader.new
66
67
 
67
- self.actions_loader.use action_class
68
+ action = { class: action_class, arguments: arguments }
69
+ self.actions_loader.use action
68
70
  end
69
71
 
70
- def filter(filter_class)
72
+ def filter(filter_class, arguments: {})
71
73
  self.filters_loader ||= Avo::Loaders::Loader.new
72
74
 
73
- self.filters_loader.use filter_class
75
+ filter = { class: filter_class , arguments: arguments }
76
+ self.filters_loader.use filter
74
77
  end
75
78
 
76
79
  # This is the search_query scope
@@ -169,12 +172,24 @@ module Avo
169
172
  self.class.filters_loader.bag
170
173
  end
171
174
 
175
+ def get_filter_arguments(filter_class)
176
+ filter = get_filters.find { |filter| filter[:class] == filter_class.constantize }
177
+
178
+ filter[:arguments]
179
+ end
180
+
172
181
  def get_actions
173
182
  return [] if self.class.actions_loader.blank?
174
183
 
175
184
  self.class.actions_loader.bag
176
185
  end
177
186
 
187
+ def get_action_arguments(action_class)
188
+ action = get_actions.find { |action| action[:class].to_s == action_class.to_s }
189
+
190
+ action[:arguments]
191
+ end
192
+
178
193
  def default_panel_name
179
194
  return @params[:related_name].capitalize if @params.present? && @params[:related_name].present?
180
195
 
@@ -422,9 +437,7 @@ module Avo
422
437
  end
423
438
 
424
439
  def label
425
- label_field.value || model_title
426
- rescue
427
- model_title
440
+ label_field&.value || model_title
428
441
  end
429
442
 
430
443
  def avatar_field
@@ -460,9 +473,7 @@ module Avo
460
473
  end
461
474
 
462
475
  def description
463
- description_field.value
464
- rescue
465
- nil
476
+ description_field&.value
466
477
  end
467
478
 
468
479
  def form_scope
@@ -0,0 +1,96 @@
1
+ module Avo
2
+ module Concerns
3
+ # This is a custom implementation of breadcrumbs largely based on breadcrumbs_on_rails gem
4
+ # created by Simone Carletti (@weppos) and released on MIT license.
5
+ #
6
+ # https://github.com/weppos/breadcrumbs_on_rails
7
+ #
8
+ # The reason to use custom implementation is to
9
+ # * Avoid naming conflicts with other gems adding helpers like `breadcrumbs`
10
+ # * Reduce number of dependencies
11
+ module Breadcrumbs
12
+ extend ActiveSupport::Concern
13
+
14
+ included do |base|
15
+ helper HelperMethods
16
+ extend ClassMethods
17
+ helper_method :add_breadcrumb, :avo_breadcrumbs
18
+ end
19
+
20
+ Crumb = Struct.new(:name, :path) unless defined?(Crumb)
21
+
22
+ class Builder
23
+ DEFAULT_SEPARATOR = " &raquo; ".freeze unless defined?(DEFAULT_SEPARATOR)
24
+
25
+ attr_reader :context, :options
26
+
27
+ def initialize(context, options)
28
+ @context = context
29
+ @options = options
30
+ end
31
+
32
+ def render
33
+ separator = options.fetch(:separator, DEFAULT_SEPARATOR)
34
+ breadcrumbs.map(&method(:render_element)).join(separator)
35
+ end
36
+
37
+ private
38
+
39
+ def breadcrumbs
40
+ context.avo_breadcrumbs
41
+ end
42
+
43
+ def render_element(element)
44
+ content = element.path.nil? ? compute_name(element) : context.link_to_unless_current(compute_name(element), compute_path(element))
45
+ options[:tag] ? context.content_tag(options[:tag], content) : ERB::Util.h(content)
46
+ end
47
+
48
+ def compute_name(element)
49
+ case name = element.name
50
+ when Symbol
51
+ context.send(name)
52
+ when Proc
53
+ name.call(context)
54
+ else
55
+ name.to_s
56
+ end
57
+ end
58
+
59
+ def compute_path(element)
60
+ case path = element.path
61
+ when Symbol
62
+ context.send(path)
63
+ when Proc
64
+ path.call(context)
65
+ else
66
+ context.url_for(path)
67
+ end
68
+ end
69
+ end
70
+
71
+ module ClassMethods
72
+ def add_breadcrumb(name, path = nil)
73
+ before_action(filter_options) do |controller|
74
+ controller.send(:add_breadcrumb, name, path)
75
+ end
76
+ end
77
+ end
78
+
79
+ def add_breadcrumb(name, path = nil)
80
+ avo_breadcrumbs << Crumb.new(name, path)
81
+ end
82
+
83
+ def avo_breadcrumbs
84
+ @avo_breadcrumbs ||= []
85
+ end
86
+
87
+ module HelperMethods
88
+ def render_avo_breadcrumbs(options = {}, &block)
89
+ builder = Builder.new(self, options)
90
+ content = builder.render.html_safe
91
+ block_given? ? capture(content, &block) : content
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,43 @@
1
+
2
+ module Avo
3
+ module Concerns
4
+ module FiltersSessionHandler
5
+ def reset_filters
6
+ return unless cache_resource_filters?
7
+
8
+ session.delete(filters_session_key)
9
+ end
10
+
11
+ def fetch_filters
12
+ return filters_from_params unless cache_resource_filters?
13
+
14
+ (filters_from_params && save_filters_to_session) || filters_from_session
15
+ end
16
+
17
+ def filters_from_params
18
+ params[Avo::Filters::BaseFilter::PARAM_KEY].presence
19
+ end
20
+
21
+ def save_filters_to_session
22
+ session[filters_session_key] = params[Avo::Filters::BaseFilter::PARAM_KEY]
23
+ end
24
+
25
+ def filters_from_session
26
+ session[filters_session_key]
27
+ end
28
+
29
+ def filters_session_key
30
+ @filters_session_key ||= '/filters/' << %w[
31
+ turbo_frame controller resource_name related_name
32
+ action id
33
+ ].map { |key| params[key] }.compact.join('/')
34
+ end
35
+
36
+ def cache_resource_filters?
37
+ return Avo.configuration.cache_resource_filters unless Avo.configuration.cache_resource_filters.is_a?(Proc)
38
+
39
+ Avo.configuration.cache_resource_filters.call(current_user: current_user, resource: @resource)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -270,6 +270,8 @@ module Avo
270
270
  end
271
271
  # each field has it's own visibility checker
272
272
  if item.respond_to? :visible?
273
+ item.hydrate(view: view) if item.view.nil?
274
+
273
275
  next unless item.visible?
274
276
  end
275
277
  # check if the user is authorized to view it
@@ -16,12 +16,14 @@ module Avo
16
16
  default_attribute_value name
17
17
  end
18
18
 
19
- attributes = if html_builder.is_a? Hash
20
- get_html_from_hash name, element: element, view: view
21
- elsif html_builder.is_a? Avo::HTML::Builder
22
- get_html_from_block name, element: element, view: view
23
- elsif html_builder.nil?
24
- # Handle empty html_builder by returning an empty state
19
+ parsed = parse_html
20
+
21
+ attributes = if parsed.is_a? Hash
22
+ get_html_from_hash name, element: element, hash: parsed, view: view
23
+ elsif parsed.is_a? Avo::HTML::Builder
24
+ get_html_from_block name, element: element, html_builder: parsed, view: view
25
+ elsif parsed.nil?
26
+ # Handle empty parsed by returning an empty state
25
27
  default_attribute_value name
26
28
  end
27
29
 
@@ -30,19 +32,15 @@ module Avo
30
32
 
31
33
  private
32
34
 
33
- def html_builder
34
- return @parsed_html if @parsed_html.present?
35
-
35
+ # Returns Hash, HTML::Builder, or nil.
36
+ def parse_html
36
37
  return if @html.nil?
37
38
 
38
- # Memoize the value
39
- @parsed_html = if @html.is_a? Hash
39
+ if @html.is_a? Hash
40
40
  @html
41
41
  elsif @html.respond_to? :call
42
42
  Avo::HTML::Builder.parse_block(record: model, resource: resource, &@html)
43
43
  end
44
-
45
- @parsed_html
46
44
  end
47
45
 
48
46
  def default_attribute_value(name)
@@ -64,7 +62,7 @@ module Avo
64
62
  end
65
63
  end
66
64
 
67
- def get_html_from_block(name = nil, element:, view:)
65
+ def get_html_from_block(name = nil, element:, html_builder:, view:)
68
66
  values = []
69
67
 
70
68
  # get view ancestor
@@ -83,9 +81,9 @@ module Avo
83
81
  merge_values_as(as: values_type, values: values)
84
82
  end
85
83
 
86
- def get_html_from_hash(name = nil, element:, view:)
84
+ def get_html_from_hash(name = nil, element:, hash:, view:)
87
85
  # @todo: what if this is not a Hash but a string?
88
- html_builder.dig(view, element, name) || {}
86
+ hash.dig(view, element, name) || {}
89
87
  end
90
88
 
91
89
  # Merge the values from all possible locations.
@@ -0,0 +1,44 @@
1
+ # This concern helps us figure out what items are visible for each tab, panel or sidebar
2
+ module Avo
3
+ module Concerns
4
+ module VisibleItems
5
+ extend ActiveSupport::Concern
6
+ def items
7
+ if items_holder.present?
8
+ items_holder.items
9
+ else
10
+ []
11
+ end
12
+ end
13
+
14
+ def visible_items
15
+ items
16
+ .map do |item|
17
+ visible(item) ? item : nil
18
+ end
19
+ .compact
20
+ end
21
+
22
+ def visible(item)
23
+ if item.is_field?
24
+ item.visible? && item.visible_on?(view)
25
+ else
26
+ item.visible?
27
+ end
28
+ end
29
+
30
+ def visible?
31
+ any_item_visible = visible_items.any?
32
+ return any_item_visible unless respond_to?(:visible_on?)
33
+
34
+ visible_on?(view) && any_item_visible
35
+ end
36
+
37
+ def hydrate(view: nil)
38
+ @view = view
39
+
40
+ self
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,10 +1,11 @@
1
1
  class Avo::Configuration::Branding
2
- def initialize(colors: nil, chart_colors: nil, logo: nil, logomark: nil, placeholder: nil)
2
+ def initialize(colors: nil, chart_colors: nil, logo: nil, logomark: nil, placeholder: nil, favicon: nil)
3
3
  @colors = colors || {}
4
4
  @chart_colors = chart_colors
5
5
  @logo = logo
6
6
  @logomark = logomark
7
7
  @placeholder = placeholder
8
+ @favicon = favicon
8
9
 
9
10
  @default_colors = {
10
11
  background: "#F6F6F7",
@@ -16,7 +17,8 @@ class Avo::Configuration::Branding
16
17
  @default_chart_colors = ["#0B8AE2", "#34C683", "#2AB1EE", "#34C6A8"]
17
18
  @default_logo = "/avo-assets/logo.png"
18
19
  @default_logomark = "/avo-assets/logomark.png"
19
- @default_placeholder = "placeholder.svg"
20
+ @default_placeholder = "/avo-assets/placeholder.svg"
21
+ @default_favicon = "/avo-assets/favicon.ico"
20
22
  end
21
23
 
22
24
  def css_colors
@@ -53,6 +55,12 @@ class Avo::Configuration::Branding
53
55
  @chart_colors || @default_chart_colors
54
56
  end
55
57
 
58
+ def favicon
59
+ return @default_favicon if Avo::App.license.lacks_with_trial(:branding)
60
+
61
+ @favicon || @default_favicon
62
+ end
63
+
56
64
  private
57
65
 
58
66
  def colors
@@ -20,6 +20,7 @@ module Avo
20
20
  attr_accessor :full_width_container
21
21
  attr_accessor :full_width_index_view
22
22
  attr_accessor :cache_resources_on_index_view
23
+ attr_accessor :cache_resource_filters
23
24
  attr_accessor :context
24
25
  attr_accessor :display_breadcrumbs
25
26
  attr_accessor :hide_layout_when_printing
@@ -39,6 +40,7 @@ module Avo
39
40
  attr_accessor :resource_default_view
40
41
  attr_accessor :authorization_client
41
42
  attr_accessor :field_wrapper_layout
43
+ attr_accessor :sign_out_path_name
42
44
  attr_writer :branding
43
45
 
44
46
  def initialize
@@ -68,6 +70,7 @@ module Avo
68
70
  @full_width_container = false
69
71
  @full_width_index_view = false
70
72
  @cache_resources_on_index_view = Avo::PACKED
73
+ @cache_resource_filters = false
71
74
  @context = proc {}
72
75
  @initial_breadcrumbs = proc {
73
76
  add_breadcrumb I18n.t("avo.home").humanize, avo.root_path
@@ -12,7 +12,12 @@ module Avo
12
12
  class_attribute :index, default: 0
13
13
 
14
14
  class << self
15
- def card(klass, label: nil, description: nil, cols: nil, rows: nil, refresh_every: nil, options: {})
15
+ def options_deprecation_message
16
+ Rails.logger.warn "DEPRECATION WARNING: Card options parameter is deprecated in favor of arguments parameter and will be removed from Avo version 3.0.0"
17
+ end
18
+
19
+ def card(klass, label: nil, description: nil, cols: nil, rows: nil, refresh_every: nil, options: {}, arguments: {})
20
+ options_deprecation_message if options.present?
16
21
  self.items_holder ||= []
17
22
 
18
23
  self.items_holder << klass.new(dashboard: self,
@@ -22,6 +27,7 @@ module Avo
22
27
  rows: rows,
23
28
  refresh_every: refresh_every,
24
29
  options: options,
30
+ arguments: arguments,
25
31
  index: index
26
32
  )
27
33
  self.index += 1
@@ -1,21 +1,22 @@
1
1
  module Avo
2
- module DynamicRouter
3
- def self.routes(router)
4
- Rails.application.eager_load! unless Rails.env.production?
2
+ class DynamicRouter
3
+ def self.routes
4
+ Avo::Engine.routes.draw do
5
+ scope "resources", as: "resources" do
6
+ Avo::App.eager_load(:resources) unless Rails.application.config.eager_load
5
7
 
6
- BaseResource.descendants
7
- .select do |resource|
8
- resource != :BaseResource
9
- end
10
- .select do |resource|
11
- resource.is_a? Class
12
- end
13
- # .select do |resource|
14
- # resource.model_class.present?
15
- # end
16
- .map do |resource|
17
- router.resources resource.new.route_key
8
+ BaseResource.descendants
9
+ .select do |resource|
10
+ resource != :BaseResource
11
+ end
12
+ .select do |resource|
13
+ resource.is_a? Class
14
+ end
15
+ .map do |resource|
16
+ resources resource.new.route_key
17
+ end
18
18
  end
19
+ end
19
20
  end
20
21
  end
21
22
  end
data/lib/avo/engine.rb CHANGED
@@ -27,15 +27,7 @@ module Avo
27
27
  end
28
28
 
29
29
  initializer "avo.autoload" do |app|
30
- [
31
- ["app", "avo", "fields"],
32
- ["app", "avo", "filters"],
33
- ["app", "avo", "actions"],
34
- ["app", "avo", "resources"],
35
- ["app", "avo", "dashboards"],
36
- ["app", "avo", "cards"],
37
- ["app", "avo", "resource_tools"]
38
- ].each do |path_params|
30
+ Avo::ENTITIES.values.each do |path_params|
39
31
  path = Rails.root.join(*path_params)
40
32
 
41
33
  if File.directory? path.to_s
@@ -72,6 +64,11 @@ module Avo
72
64
  g.test_framework :rspec, view_specs: false
73
65
  end
74
66
 
67
+ generators do |app|
68
+ Rails::Generators.configure! app.config.generators
69
+ require_relative "../generators/model_generator"
70
+ end
71
+
75
72
  # After deploy we want to make sure the license response is being cleared.
76
73
  # We need a fresh license response.
77
74
  # This is disabled in development because the initialization process might be triggered more than once.
@@ -14,6 +14,7 @@ module Avo
14
14
  include Avo::Concerns::HasHTMLAttributes
15
15
  include Avo::Fields::Concerns::IsRequired
16
16
  include Avo::Fields::Concerns::IsReadonly
17
+ include Avo::Fields::Concerns::HasDefault
17
18
 
18
19
  delegate :view_context, to: ::Avo::App
19
20
  delegate :simple_format, :content_tag, to: :view_context
@@ -83,7 +84,7 @@ module Avo
83
84
 
84
85
  @args = args
85
86
 
86
- @updatable = true
87
+ @updatable = !readonly
87
88
  @computable = true
88
89
  @computed = block.present?
89
90
  @computed_value = nil
@@ -145,9 +146,11 @@ module Avo
145
146
  end
146
147
 
147
148
  def placeholder
148
- return @placeholder if @placeholder.present?
149
+ if @placeholder.respond_to?(:call)
150
+ return Avo::Hosts::ResourceViewRecordHost.new(block: @placeholder, record: @model, resource: @resource, view: @view).handle
151
+ end
149
152
 
150
- name
153
+ @placeholder || name
151
154
  end
152
155
 
153
156
  def visible?
@@ -166,15 +169,9 @@ module Avo
166
169
  # Get model value
167
170
  final_value = @model.send(property) if is_model?(@model) && @model.respond_to?(property)
168
171
 
169
- # On new views and actions modals we need to prefill the fields
170
- if @view.in?([:new, :create]) || @action.present?
171
- if default.present?
172
- final_value = if default.respond_to?(:call)
173
- default.call
174
- else
175
- default
176
- end
177
- end
172
+ # On new views and actions modals we need to prefill the fields with the default value
173
+ if should_fill_with_default_value? && default.present?
174
+ final_value = computed_default_value
178
175
  end
179
176
 
180
177
  # Run computable callback block if present
@@ -269,6 +266,18 @@ module Avo
269
266
  def is_model?(model)
270
267
  model_or_class(model) == "model"
271
268
  end
269
+
270
+ def should_fill_with_default_value?
271
+ on_create? || in_action?
272
+ end
273
+
274
+ def on_create?
275
+ @view.in?([:new, :create])
276
+ end
277
+
278
+ def in_action?
279
+ @action.present?
280
+ end
272
281
  end
273
282
  end
274
283
  end
@@ -0,0 +1,17 @@
1
+ module Avo
2
+ module Fields
3
+ module Concerns
4
+ module HasDefault
5
+ extend ActiveSupport::Concern
6
+
7
+ def computed_default_value
8
+ if default.respond_to? :call
9
+ Avo::Hosts::ResourceViewRecordHost.new(block: default, record: model, view: view, resource: resource).handle
10
+ else
11
+ default
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end