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.
- checksums.yaml +4 -4
- data/Gemfile +4 -6
- data/Gemfile.lock +76 -77
- data/app/components/avo/actions_component.html.erb +1 -1
- data/app/components/avo/actions_component.rb +4 -4
- data/app/components/avo/base_component.rb +17 -0
- data/app/components/avo/card_component.html.erb +15 -15
- data/app/components/avo/card_component.rb +7 -5
- data/app/components/avo/field_wrapper_component.rb +7 -1
- data/app/components/avo/fields/has_one_field/show_component.rb +1 -2
- data/app/components/avo/fields/index_component.rb +4 -3
- data/app/components/avo/fields/select_field/edit_component.html.erb +1 -1
- data/app/components/avo/filters_component.html.erb +1 -1
- data/app/components/avo/filters_component.rb +2 -2
- data/app/components/avo/index/grid_item_component.rb +2 -2
- data/app/components/avo/index/resource_controls_component.rb +2 -2
- data/app/components/avo/index/table_row_component.html.erb +1 -1
- data/app/components/avo/item_switcher_component.html.erb +1 -1
- data/app/components/avo/panel_component.html.erb +1 -1
- data/app/components/avo/resource_component.rb +1 -1
- data/app/components/avo/resource_sidebar_component.rb +1 -6
- data/app/components/avo/sidebar/group_component.html.erb +18 -12
- data/app/components/avo/sidebar/heading_component.html.erb +17 -10
- data/app/components/avo/sidebar_profile_component.rb +3 -1
- data/app/components/avo/tab_group_component.rb +1 -1
- data/app/components/avo/views/resource_show_component.html.erb +1 -1
- data/app/controllers/avo/actions_controller.rb +27 -5
- data/app/controllers/avo/application_controller.rb +7 -0
- data/app/controllers/avo/base_controller.rb +30 -18
- data/app/controllers/avo/dashboards/cards_controller.rb +37 -0
- data/app/controllers/avo/dashboards_controller.rb +1 -0
- data/app/helpers/avo/application_helper.rb +5 -1
- data/app/javascript/js/controllers/search_controller.js +11 -2
- data/app/views/avo/actions/keep_modal_open.turbo_stream.erb +5 -0
- data/app/views/avo/actions/show.html.erb +2 -1
- data/app/views/avo/{cards → dashboards/cards}/_chartkick_card.html.erb +0 -0
- data/app/views/avo/{cards → dashboards/cards}/_metric_card.html.erb +0 -0
- data/app/views/avo/{cards → dashboards/cards}/chartkick_missing.html.erb +0 -0
- data/app/views/avo/{cards → dashboards/cards}/show.html.erb +0 -0
- data/app/views/avo/partials/_branding.html.erb +1 -0
- data/app/views/layouts/avo/application.html.erb +1 -1
- data/avo.gemspec +1 -2
- data/bin/init +11 -1
- data/bin/test +1 -0
- data/config/routes.rb +2 -2
- data/db/factories.rb +10 -0
- data/lib/avo/app.rb +14 -1
- data/lib/avo/base_action.rb +35 -10
- data/lib/avo/base_card.rb +3 -1
- data/lib/avo/base_resource.rb +21 -10
- data/lib/avo/concerns/breadcrumbs.rb +96 -0
- data/lib/avo/concerns/filters_session_handler.rb +43 -0
- data/lib/avo/concerns/has_fields.rb +2 -0
- data/lib/avo/concerns/has_html_attributes.rb +14 -16
- data/lib/avo/concerns/visible_items.rb +44 -0
- data/lib/avo/configuration/branding.rb +10 -2
- data/lib/avo/configuration.rb +3 -0
- data/lib/avo/dashboards/base_dashboard.rb +7 -1
- data/lib/avo/dynamic_router.rb +16 -15
- data/lib/avo/engine.rb +6 -9
- data/lib/avo/fields/base_field.rb +21 -12
- data/lib/avo/fields/concerns/has_default.rb +17 -0
- data/lib/avo/fields/concerns/is_readonly.rb +1 -1
- data/lib/avo/fields/concerns/is_required.rb +2 -2
- data/lib/avo/fields/has_base_field.rb +2 -0
- data/lib/avo/fields/key_value_field.rb +1 -1
- data/lib/avo/fields/select_field.rb +39 -34
- data/lib/avo/filters/base_filter.rb +24 -2
- data/lib/avo/hosts/resource_view_record_host.rb +7 -0
- data/lib/avo/hosts/visibility_host.rb +13 -0
- data/lib/avo/panel.rb +4 -1
- data/lib/avo/resources/controls/action.rb +1 -3
- data/lib/avo/sidebar.rb +1 -31
- data/lib/avo/tab.rb +5 -22
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +9 -0
- data/lib/generators/avo/resource_generator.rb +281 -0
- data/lib/generators/avo/templates/action.tt +3 -0
- data/lib/generators/avo/templates/filters/boolean_filter.tt +3 -0
- data/lib/generators/avo/templates/filters/multiple_select_filter.tt +3 -0
- data/lib/generators/avo/templates/filters/select_filter.tt +3 -0
- data/lib/generators/avo/templates/filters/text_filter.tt +3 -0
- data/lib/generators/avo/templates/initializer/avo.tt +4 -0
- data/lib/generators/avo/templates/resource/controller.tt +1 -1
- data/lib/generators/avo/templates/resource/resource.tt +2 -2
- data/lib/generators/model_generator.rb +10 -0
- data/lib/generators/rails/avo_resource_generator.rb +11 -0
- data/public/avo-assets/avo.base.css +14 -14
- data/public/avo-assets/avo.base.js +1 -1
- data/public/avo-assets/avo.base.js.map +2 -2
- data/public/avo-assets/favicon.ico +0 -0
- data/{app/assets/svgs → public/avo-assets}/placeholder.svg +0 -0
- metadata +20 -25
- data/app/controllers/avo/cards_controller.rb +0 -35
- data/config/master.key +0 -1
data/lib/avo/base_action.rb
CHANGED
@@ -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
|
-
{
|
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
|
-
|
119
|
-
|
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
|
-
|
122
|
-
|
124
|
+
# Show on all other views
|
125
|
+
return true
|
126
|
+
end
|
123
127
|
|
124
|
-
#
|
125
|
-
|
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
|
data/lib/avo/base_resource.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
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
|
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 = " » ".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
|
@@ -16,12 +16,14 @@ module Avo
|
|
16
16
|
default_attribute_value name
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
elsif
|
24
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
35
|
+
# Returns Hash, HTML::Builder, or nil.
|
36
|
+
def parse_html
|
36
37
|
return if @html.nil?
|
37
38
|
|
38
|
-
|
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
|
-
|
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
|
data/lib/avo/configuration.rb
CHANGED
@@ -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
|
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
|
data/lib/avo/dynamic_router.rb
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
module Avo
|
2
|
-
|
3
|
-
def self.routes
|
4
|
-
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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 =
|
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
|
-
|
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
|
171
|
-
|
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
|