avo 2.3.1.pre.6 → 2.5.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.lock +1 -3
- data/app/assets/stylesheets/css/components/code.css +1 -0
- data/app/components/avo/edit/field_wrapper_component.html.erb +2 -2
- data/app/components/avo/edit/field_wrapper_component.rb +6 -1
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +3 -0
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +4 -0
- data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +26 -27
- data/app/components/avo/filters_component.html.erb +3 -3
- data/app/components/avo/filters_component.rb +2 -1
- data/app/components/avo/paginator_component.html.erb +3 -3
- data/app/components/avo/paginator_component.rb +3 -3
- data/app/components/avo/profile_item_component.html.erb +1 -1
- data/app/components/avo/profile_item_component.rb +6 -1
- data/app/components/avo/sidebar_component.html.erb +5 -2
- data/app/components/avo/sidebar_profile_component.html.erb +1 -1
- data/app/components/avo/views/resource_index_component.html.erb +3 -3
- data/app/components/avo/views/resource_index_component.rb +10 -3
- data/app/controllers/avo/associations_controller.rb +6 -1
- data/app/controllers/avo/base_controller.rb +37 -9
- data/app/controllers/avo/debug_controller.rb +3 -0
- data/app/controllers/avo/search_controller.rb +22 -1
- data/app/helpers/avo/url_helpers.rb +3 -3
- data/app/javascript/js/controllers/fields/code_field_controller.js +0 -1
- data/app/javascript/js/controllers/filter_controller.js +20 -1
- data/app/javascript/js/controllers/multiple_select_filter_controller.js +3 -1
- data/app/javascript/js/controllers/search_controller.js +9 -2
- data/app/javascript/js/controllers/select_filter_controller.js +1 -1
- data/app/views/avo/base/_boolean_filter.html.erb +23 -28
- data/app/views/avo/base/_multiple_select_filter.html.erb +7 -14
- data/app/views/avo/base/_select_filter.html.erb +6 -10
- data/app/views/avo/base/_text_filter.html.erb +7 -11
- data/app/views/avo/base/index.html.erb +1 -0
- data/app/views/avo/debug/index.html.erb +3 -3
- data/app/views/avo/debug/report.html.erb +1 -1
- data/app/views/avo/partials/_footer.html.erb +1 -1
- data/app/views/avo/partials/_navbar.html.erb +4 -1
- data/app/views/avo/partials/_sidebar_extra.html.erb +2 -0
- data/db/factories.rb +5 -3
- data/lib/avo/app.rb +37 -12
- data/lib/avo/base_resource.rb +1 -0
- data/lib/avo/configuration.rb +2 -0
- data/lib/avo/engine.rb +13 -0
- data/lib/avo/fields/belongs_to_field.rb +11 -1
- data/lib/avo/fields/code_field.rb +1 -1
- data/lib/avo/fields/has_base_field.rb +2 -0
- data/lib/avo/filters/base_filter.rb +35 -2
- data/lib/avo/filters/boolean_filter.rb +12 -0
- data/lib/avo/filters/multiple_select_filter.rb +15 -0
- data/lib/avo/filters/text_filter.rb +4 -0
- data/lib/avo/hosts/association_scope_host.rb +8 -0
- data/lib/avo/licensing/h_q.rb +52 -15
- data/lib/avo/services/authorization_service.rb +8 -10
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/eject_generator.rb +2 -3
- data/lib/generators/avo/templates/initializer/avo.tt +1 -0
- data/lib/generators/avo/templates/locales/avo.en.yml +2 -1
- data/lib/generators/avo/templates/locales/avo.nb-NO.yml +2 -1
- data/lib/generators/avo/templates/locales/avo.pt-BR.yml +2 -1
- data/lib/generators/avo/templates/locales/avo.ro.yml +2 -1
- data/lib/tasks/avo_tasks.rake +30 -0
- data/public/avo-assets/avo.css +11 -0
- data/public/avo-assets/avo.js +22 -22
- data/public/avo-assets/avo.js.map +2 -2
- metadata +5 -8
- data/app/assets/builds/avo.css +0 -8846
- data/app/assets/builds/avo.js +0 -423
- data/app/assets/builds/avo.js.map +0 -7
- data/app/mailers/avo/application_mailer.rb +0 -6
@@ -68,8 +68,15 @@ export default class extends Controller {
|
|
68
68
|
}
|
69
69
|
|
70
70
|
if (this.isBelongsToSearch) {
|
71
|
-
|
72
|
-
|
71
|
+
params = {
|
72
|
+
...params,
|
73
|
+
// eslint-disable-next-line camelcase
|
74
|
+
via_association_id: this.dataset.viaAssociationId,
|
75
|
+
// eslint-disable-next-line camelcase
|
76
|
+
via_reflection_class: this.dataset.viaReflectionClass,
|
77
|
+
// eslint-disable-next-line camelcase
|
78
|
+
via_reflection_id: this.dataset.viaReflectionId,
|
79
|
+
}
|
73
80
|
}
|
74
81
|
|
75
82
|
return url.segment(segments).search(params).toString()
|
@@ -1,33 +1,28 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
if filter.default.present?
|
7
|
-
set_value = filter.default.stringify_keys
|
8
|
-
else
|
9
|
-
set_value = {}
|
10
|
-
end
|
11
|
-
end
|
12
|
-
set_value = {} if set_value.nil?
|
13
|
-
%>
|
14
|
-
<div data-controller="boolean-filter" data-filter-name="<%= filter.name %>">
|
1
|
+
<div
|
2
|
+
data-controller="boolean-filter"
|
3
|
+
data-filter-name="<%= filter.name %>"
|
4
|
+
data-boolean-filter-keep-filters-panel-open-value="<%= @resource.keep_filters_panel_open %>"
|
5
|
+
>
|
15
6
|
<%= filter_wrapper name: filter.name do %>
|
16
7
|
<div class="flex items-center">
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
8
|
+
<% if filter.options.empty? %>
|
9
|
+
<div class="text-sm text-gray-600"><%= filter.class.empty_message %></div>
|
10
|
+
<% else %>
|
11
|
+
<div class="space-y-2">
|
12
|
+
<% filter.options.each do |value, label| %>
|
13
|
+
<label class="flex items-center text-gray-700 text-sm">
|
14
|
+
<%= check_box_tag filter.id, value, filter.selected_value(value.to_s, @applied_filters),
|
15
|
+
class: 'mr-2 text-lg h-4 w-4',
|
16
|
+
id: "avo_filters_#{filter.id.parameterize.underscore}",
|
17
|
+
'data-filter-class': filter.class,
|
18
|
+
'data-boolean-filter-target': 'option',
|
19
|
+
'data-action': 'input->boolean-filter#changeFilter'
|
20
|
+
%>
|
21
|
+
<%= label %>
|
22
|
+
</label>
|
23
|
+
<% end %>
|
24
|
+
</div>
|
25
|
+
<% end %>
|
31
26
|
<%= link_to 'url_redirect', request.url, data: { 'boolean-filter-target': 'urlRedirect', 'turbo-frame': params[:turbo_frame] }, style: 'hidden', class: 'hidden' %>
|
32
27
|
</div>
|
33
28
|
<% end %>
|
@@ -1,17 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
if decoded_filters_param[filter.class.to_s].present?
|
7
|
-
set_value = decoded_filters_param[filter.class.to_s]
|
8
|
-
end
|
9
|
-
rescue
|
10
|
-
end
|
11
|
-
%>
|
12
|
-
<div data-controller="multiple-select-filter" data-filter-name="<%= filter.name %>">
|
1
|
+
<div
|
2
|
+
data-controller="multiple-select-filter"
|
3
|
+
data-filter-name="<%= filter.name %>"
|
4
|
+
data-multiple-select-filter-keep-filters-panel-open-value="<%= @resource.keep_filters_panel_open %>"
|
5
|
+
>
|
13
6
|
<%= filter_wrapper name: filter.name do %>
|
14
|
-
<%= select_tag filter.id, options_for_select(filter.options.invert,
|
7
|
+
<%= select_tag filter.id, options_for_select(filter.options.invert, filter.selected_value(@applied_filters)),
|
15
8
|
class: input_classes('w-full mb-0'),
|
16
9
|
multiple: true,
|
17
10
|
id: "avo_filters_#{filter.id.parameterize.underscore}",
|
@@ -19,7 +12,7 @@
|
|
19
12
|
'data-multiple-select-filter-target': 'selector'
|
20
13
|
%>
|
21
14
|
<div class="flex justify-end">
|
22
|
-
<%= a_button class: 'mt-4', color: :blue, size: :
|
15
|
+
<%= a_button class: 'mt-4', color: :blue, size: :xs, data: { action: "multiple-select-filter#changeFilter" } do %>
|
23
16
|
Filter by <%=filter.name %>
|
24
17
|
<% end %>
|
25
18
|
</div>
|
@@ -1,14 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
set_value = filter.default
|
7
|
-
end
|
8
|
-
%>
|
9
|
-
<div data-controller="select-filter" data-filter-name="<%= filter.name %>">
|
1
|
+
<div
|
2
|
+
data-controller="select-filter"
|
3
|
+
data-filter-name="<%= filter.name %>"
|
4
|
+
data-select-filter-keep-filters-panel-open-value="<%= @resource.keep_filters_panel_open %>"
|
5
|
+
>
|
10
6
|
<%= filter_wrapper name: filter.name do %>
|
11
|
-
<%= select_tag filter.id, options_for_select(filter.options.invert,
|
7
|
+
<%= select_tag filter.id, options_for_select(filter.options.invert, filter.applied_or_default_value(@applied_filters)),
|
12
8
|
class: input_classes('w-full mb-0'),
|
13
9
|
include_blank: '—',
|
14
10
|
id: "avo_filters_#{filter.id.parameterize.underscore}",
|
@@ -1,14 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
set_value = filter.default
|
7
|
-
end
|
8
|
-
%>
|
9
|
-
<div data-controller="text-filter" data-filter-name="<%= filter.name %>">
|
1
|
+
<div
|
2
|
+
data-controller="text-filter"
|
3
|
+
data-filter-name="<%= filter.name %>"
|
4
|
+
data-text-filter-keep-filters-panel-open-value="<%= @resource.keep_filters_panel_open %>"
|
5
|
+
>
|
10
6
|
<%= filter_wrapper name: filter.name do %>
|
11
|
-
<%= text_field_tag filter.id,
|
7
|
+
<%= text_field_tag filter.id, filter.applied_or_default_value(@applied_filters),
|
12
8
|
class: input_classes('w-full mb-0'),
|
13
9
|
id: "avo_filters_#{filter.id.parameterize.underscore}",
|
14
10
|
'data-filter-class': filter.class.to_s,
|
@@ -16,7 +12,7 @@
|
|
16
12
|
'data-action': 'keypress->text-filter#tryToSubmit'
|
17
13
|
%>
|
18
14
|
<div class="flex justify-end">
|
19
|
-
<%= a_button class: 'mt-4', color: :blue, data: { action: "text-filter#changeFilter" }, size: :
|
15
|
+
<%= a_button class: 'mt-4', color: :blue, data: { action: "text-filter#changeFilter" }, size: :xs do %>
|
20
16
|
<%= filter.button_label || "Filter by #{filter.name}" %>
|
21
17
|
<% end %>
|
22
18
|
</div>
|
@@ -21,7 +21,7 @@
|
|
21
21
|
<div class="grid gap-4 sm:grid-cols-3">
|
22
22
|
<div class="relative flex flex-col bg-white rounded shadow-panel p-4 space-y-4 h-full col-span-1">
|
23
23
|
<div class="font-semibold">License info</div>
|
24
|
-
<div class="flex flex-col
|
24
|
+
<div class="flex flex-col flex-1">
|
25
25
|
<div>
|
26
26
|
<div class="text-xl font-semibold"><%= license.name %></div>
|
27
27
|
<% if license.response['reason'] %>
|
@@ -57,7 +57,7 @@
|
|
57
57
|
<div class="flex justify-end mt-4">
|
58
58
|
<%= a_button style: :outline,
|
59
59
|
color: :blue,
|
60
|
-
url:
|
60
|
+
url: "#{root_path}avo_private/debug/refresh_license",
|
61
61
|
method: :post,
|
62
62
|
loading: true,
|
63
63
|
icon: 'heroicons/outline/refresh' do %>
|
@@ -67,7 +67,7 @@
|
|
67
67
|
</div>
|
68
68
|
</div>
|
69
69
|
<div class="relative bg-white rounded shadow-panel p-4 space-y-4 col-span-2">
|
70
|
-
<turbo-frame id="debug-report" src="
|
70
|
+
<turbo-frame id="debug-report" src="<%= root_path %>avo_private/debug/report" target="_top" class="block">
|
71
71
|
Loading...
|
72
72
|
</turbo-frame>
|
73
73
|
</div>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<turbo-frame id="debug-report">
|
2
|
-
<div class="font-semibold">Debug report</div>
|
2
|
+
<div class="font-semibold">Debug report <small class="font-normal">(don't post this anywhere public)</small></div>
|
3
3
|
<div>
|
4
4
|
<% if defined?(ap) %>
|
5
5
|
<%== ap Avo::App.debug_report(request) %>
|
@@ -1,3 +1,3 @@
|
|
1
|
-
<div class="text-center text-sm text-gray-700">
|
1
|
+
<div class="text-center text-sm text-gray-700 <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>">
|
2
2
|
<a href="https://avohq.io/" target="_blank">Avo</a> · © <%= Date.today.year %> AvoHQ · <span title="<%= Avo::App.license.valid ? 'valid' : 'invalid'%> <%= Avo::App.license.id %> license">v<%= Avo::VERSION %></span>
|
3
3
|
</div>
|
@@ -1,4 +1,7 @@
|
|
1
|
-
<div
|
1
|
+
<div
|
2
|
+
class="relative bg-white p-2 w-full flex flex-shrink-0 items-center z-50 px-4 lg:px-8 border-b space-x-4 lg:space-x-0 min-h-[4rem] <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>"
|
3
|
+
v-if="layout !== 'blank'"
|
4
|
+
>
|
2
5
|
<%= a_button class: 'lg:hidden', icon: 'menu', data: { action: 'click->mobile#toggleSidebar' } %>
|
3
6
|
<div class="flex-1 flex items-center justify-between lg:justify-start space-x-8">
|
4
7
|
<div class="m-0">
|
data/db/factories.rb
CHANGED
@@ -25,7 +25,7 @@ FactoryBot.define do
|
|
25
25
|
Time.now - rand(10...365).days
|
26
26
|
end
|
27
27
|
end
|
28
|
-
status {
|
28
|
+
status { ::Post.statuses.keys.sample }
|
29
29
|
end
|
30
30
|
|
31
31
|
factory :project do
|
@@ -42,11 +42,11 @@ FactoryBot.define do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
factory :comment do
|
45
|
-
body { Faker::Lorem.paragraphs(number: rand(4...10)).join(
|
45
|
+
body { Faker::Lorem.paragraphs(number: rand(4...10)).join(" ") }
|
46
46
|
end
|
47
47
|
|
48
48
|
factory :review do
|
49
|
-
body { Faker::Lorem.paragraphs(number: rand(4...10)).join(
|
49
|
+
body { Faker::Lorem.paragraphs(number: rand(4...10)).join(" ") }
|
50
50
|
end
|
51
51
|
|
52
52
|
factory :person do
|
@@ -64,6 +64,8 @@ FactoryBot.define do
|
|
64
64
|
|
65
65
|
factory :course do
|
66
66
|
name { Faker::Educator.unique.course_name }
|
67
|
+
country { Course.countries.sample }
|
68
|
+
city { Course.cities.stringify_keys[country].sample }
|
67
69
|
end
|
68
70
|
|
69
71
|
factory :course_link, class: "Course::Link" do
|
data/lib/avo/app.rb
CHANGED
@@ -104,37 +104,62 @@ module Avo
|
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
|
+
def has_main_menu?
|
108
|
+
return false if Avo::App.license.lacks_with_trial(:menu_editor)
|
109
|
+
return false if Avo.configuration.main_menu.nil?
|
110
|
+
|
111
|
+
true
|
112
|
+
end
|
113
|
+
|
114
|
+
def has_profile_menu?
|
115
|
+
return false if Avo::App.license.lacks_with_trial(:menu_editor)
|
116
|
+
return false if Avo.configuration.profile_menu.nil?
|
117
|
+
|
118
|
+
true
|
119
|
+
end
|
120
|
+
|
107
121
|
def main_menu
|
108
|
-
|
109
|
-
return
|
122
|
+
# Return empty menu if the app doesn't have the profile menu configured
|
123
|
+
return Avo::Menu::Builder.new.build unless has_main_menu?
|
110
124
|
|
111
125
|
Avo::Menu::Builder.parse_menu(&Avo.configuration.main_menu)
|
112
126
|
end
|
113
127
|
|
114
128
|
def profile_menu
|
115
|
-
|
116
|
-
return
|
129
|
+
# Return empty menu if the app doesn't have the profile menu configured
|
130
|
+
return Avo::Menu::Builder.new.build unless has_profile_menu?
|
117
131
|
|
118
132
|
Avo::Menu::Builder.parse_menu(&Avo.configuration.profile_menu)
|
119
133
|
end
|
120
134
|
|
121
|
-
def debug_report(request)
|
135
|
+
def debug_report(request = nil)
|
122
136
|
payload = {}
|
137
|
+
|
123
138
|
hq = Avo::Licensing::HQ.new(request)
|
124
139
|
|
125
|
-
payload[:
|
126
|
-
payload[:
|
127
|
-
payload[:
|
128
|
-
payload[:
|
129
|
-
payload[:
|
130
|
-
payload[:
|
131
|
-
payload[:
|
140
|
+
payload[:thread_count] = get_thread_count
|
141
|
+
payload[:hq_payload] = hq&.payload
|
142
|
+
payload[:license_id] = Avo::App&.license&.id
|
143
|
+
payload[:license_valid] = Avo::App&.license&.valid?
|
144
|
+
payload[:license_payload] = Avo::App&.license&.payload
|
145
|
+
payload[:license_response] = Avo::App&.license&.response
|
146
|
+
payload[:license_abilities] = Avo::App&.license&.abilities
|
147
|
+
payload[:cache_store] = self.cache_store&.class&.to_s
|
148
|
+
payload[:avo_metadata] = hq&.avo_metadata
|
132
149
|
payload[:app_timezone] = Time.now.zone
|
150
|
+
payload[:cache_key] = Avo::Licensing::HQ.cache_key
|
151
|
+
payload[:cache_key_contents] = hq&.cached_response
|
133
152
|
|
134
153
|
payload
|
135
154
|
rescue => e
|
136
155
|
e
|
137
156
|
end
|
157
|
+
|
158
|
+
def get_thread_count
|
159
|
+
Thread.list.select {|thread| thread.status == "run"}.count
|
160
|
+
rescue => e
|
161
|
+
e
|
162
|
+
end
|
138
163
|
end
|
139
164
|
end
|
140
165
|
end
|
data/lib/avo/base_resource.rb
CHANGED
data/lib/avo/configuration.rb
CHANGED
@@ -20,6 +20,7 @@ module Avo
|
|
20
20
|
attr_accessor :cache_resources_on_index_view
|
21
21
|
attr_accessor :context
|
22
22
|
attr_accessor :display_breadcrumbs
|
23
|
+
attr_accessor :hide_layout_when_printing
|
23
24
|
attr_accessor :initial_breadcrumbs
|
24
25
|
attr_accessor :home_path
|
25
26
|
attr_accessor :search_debounce
|
@@ -64,6 +65,7 @@ module Avo
|
|
64
65
|
add_breadcrumb I18n.t("avo.home").humanize, avo.root_path
|
65
66
|
}
|
66
67
|
@display_breadcrumbs = true
|
68
|
+
@hide_layout_when_printing = false
|
67
69
|
@home_path = nil
|
68
70
|
@search_debounce = 300
|
69
71
|
@view_component_path = "app/components"
|
data/lib/avo/engine.rb
CHANGED
@@ -63,5 +63,18 @@ module Avo
|
|
63
63
|
config.generators do |g|
|
64
64
|
g.test_framework :rspec, view_specs: false
|
65
65
|
end
|
66
|
+
|
67
|
+
# After deploy we want to make sure the license response is being cleared.
|
68
|
+
# We need a fresh license response.
|
69
|
+
# This is disabled in development because the initialization process might be triggered more than once.
|
70
|
+
config.after_initialize do
|
71
|
+
unless Rails.env.development?
|
72
|
+
begin
|
73
|
+
Licensing::HQ.new.clear_response
|
74
|
+
rescue => exception
|
75
|
+
puts "Failed to clear Avo HQ response: #{e.message}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
66
79
|
end
|
67
80
|
end
|
@@ -62,6 +62,8 @@ module Avo
|
|
62
62
|
attr_reader :relation_method
|
63
63
|
attr_reader :types # for Polymorphic associations
|
64
64
|
attr_reader :allow_via_detaching
|
65
|
+
attr_reader :scope
|
66
|
+
attr_reader :polymorphic_help
|
65
67
|
|
66
68
|
def initialize(id, **args, &block)
|
67
69
|
args[:placeholder] ||= I18n.t("avo.choose_an_option")
|
@@ -73,6 +75,8 @@ module Avo
|
|
73
75
|
@types = args[:types]
|
74
76
|
@relation_method = id.to_s.parameterize.underscore
|
75
77
|
@allow_via_detaching = args[:allow_via_detaching] == true
|
78
|
+
@scope = args[:scope]
|
79
|
+
@polymorphic_help = args[:polymorphic_help]
|
76
80
|
end
|
77
81
|
|
78
82
|
def searchable
|
@@ -111,7 +115,13 @@ module Avo
|
|
111
115
|
resource = target_resource
|
112
116
|
resource = App.get_resource_by_model_name model if model.present?
|
113
117
|
|
114
|
-
|
118
|
+
query = Avo::Services::AuthorizationService.apply_policy(user, resource.class.query_scope)
|
119
|
+
|
120
|
+
if scope.present?
|
121
|
+
query = Avo::Hosts::AssociationScopeHost.new(block: scope, query: query, parent: get_model).handle
|
122
|
+
end
|
123
|
+
|
124
|
+
query.all.map do |model|
|
115
125
|
[model.send(resource.class.title), model.id]
|
116
126
|
end
|
117
127
|
end
|
@@ -14,7 +14,7 @@ module Avo
|
|
14
14
|
super(id, **args, &block)
|
15
15
|
|
16
16
|
@language = args[:language].present? ? args[:language].to_s : "javascript"
|
17
|
-
@theme = args[:theme].present? ? args[:theme].to_s : "
|
17
|
+
@theme = args[:theme].present? ? args[:theme].to_s : "default"
|
18
18
|
@height = args[:height].present? ? args[:height].to_s : "auto"
|
19
19
|
@tab_size = args[:tab_size].present? ? args[:tab_size] : 2
|
20
20
|
@indent_with_tabs = args[:indent_with_tabs].present? ? args[:indent_with_tabs] : false
|
@@ -3,6 +3,7 @@ module Avo
|
|
3
3
|
class HasBaseField < BaseField
|
4
4
|
attr_accessor :display
|
5
5
|
attr_accessor :scope
|
6
|
+
attr_accessor :description
|
6
7
|
|
7
8
|
def initialize(id, **args, &block)
|
8
9
|
super(id, **args, &block)
|
@@ -10,6 +11,7 @@ module Avo
|
|
10
11
|
@scope = args[:scope].present? ? args[:scope] : nil
|
11
12
|
@display = args[:display].present? ? args[:display] : :show
|
12
13
|
@searchable = args[:searchable] == true
|
14
|
+
@description = args[:description]
|
13
15
|
end
|
14
16
|
|
15
17
|
def searchable
|
@@ -1,13 +1,26 @@
|
|
1
1
|
module Avo
|
2
2
|
module Filters
|
3
3
|
class BaseFilter
|
4
|
+
PARAM_KEY = :filters unless const_defined?(:PARAM_KEY)
|
5
|
+
|
4
6
|
class_attribute :name, default: "Filter"
|
5
7
|
class_attribute :component, default: "boolean-filter"
|
6
|
-
class_attribute :default, default:
|
8
|
+
class_attribute :default, default: nil
|
7
9
|
class_attribute :template, default: "avo/base/select_filter"
|
10
|
+
class_attribute :empty_message, default: I18n.t("avo.no_options_available")
|
11
|
+
|
12
|
+
delegate :params, to: Avo::App
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def decode_filters(filter_params)
|
16
|
+
JSON.parse(Base64.decode64(filter_params))
|
17
|
+
rescue
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
end
|
8
21
|
|
9
22
|
def apply_query(request, query, value)
|
10
|
-
value.
|
23
|
+
value.stringify_keys! if value.is_a? Hash
|
11
24
|
|
12
25
|
apply(request, query, value)
|
13
26
|
end
|
@@ -15,6 +28,26 @@ module Avo
|
|
15
28
|
def id
|
16
29
|
self.class.name.underscore.tr("/", "_")
|
17
30
|
end
|
31
|
+
|
32
|
+
# Get the applied value this filter.
|
33
|
+
# If it's not present return the default value.
|
34
|
+
def applied_or_default_value(applied_filters)
|
35
|
+
# Get the values for this particular filter
|
36
|
+
applied_value = applied_filters[self.class.to_s]
|
37
|
+
|
38
|
+
# Return that value if present
|
39
|
+
return applied_value unless applied_value.nil?
|
40
|
+
|
41
|
+
# Return that default
|
42
|
+
default
|
43
|
+
rescue
|
44
|
+
default
|
45
|
+
end
|
46
|
+
|
47
|
+
# Fetch the applied filters from the params
|
48
|
+
def applied_filters
|
49
|
+
self.class.decode_filters params[PARAM_KEY]
|
50
|
+
end
|
18
51
|
end
|
19
52
|
end
|
20
53
|
end
|
@@ -2,6 +2,18 @@ module Avo
|
|
2
2
|
module Filters
|
3
3
|
class BooleanFilter < BaseFilter
|
4
4
|
self.template = "avo/base/boolean_filter"
|
5
|
+
|
6
|
+
def selected_value(item, applied_filters)
|
7
|
+
# See if there are any applied rules for this particular filter
|
8
|
+
if applied_filters[self.class.to_s].present?
|
9
|
+
# Symbolize the keys because they are returned from de-serialization (JSON and Base64)
|
10
|
+
applied_filters[self.class.to_s].stringify_keys.dig(item.to_s)
|
11
|
+
else
|
12
|
+
applied_or_default_value(applied_filters).stringify_keys.dig(item.to_s)
|
13
|
+
end
|
14
|
+
rescue
|
15
|
+
false
|
16
|
+
end
|
5
17
|
end
|
6
18
|
end
|
7
19
|
end
|
@@ -2,6 +2,21 @@ module Avo
|
|
2
2
|
module Filters
|
3
3
|
class MultipleSelectFilter < BaseFilter
|
4
4
|
self.template = "avo/base/multiple_select_filter"
|
5
|
+
|
6
|
+
# The input expects an array of strings for the value
|
7
|
+
# Ex: ['admins', 'non_admins']
|
8
|
+
def selected_value(applied_filters)
|
9
|
+
# Get the values for this particular filter
|
10
|
+
applied_value = applied_filters[self.class.to_s]
|
11
|
+
|
12
|
+
# Return that value if present
|
13
|
+
return applied_value unless applied_value.nil?
|
14
|
+
|
15
|
+
# Return that default
|
16
|
+
return default unless default.nil?
|
17
|
+
|
18
|
+
[]
|
19
|
+
end
|
5
20
|
end
|
6
21
|
end
|
7
22
|
end
|