avo 2.3.1.pre.6 → 2.4.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/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 +4 -1
- data/app/controllers/avo/base_controller.rb +14 -9
- data/app/controllers/avo/debug_controller.rb +3 -0
- data/app/javascript/js/controllers/fields/code_field_controller.js +0 -1
- data/app/javascript/js/controllers/filter_controller.js +11 -1
- data/app/javascript/js/controllers/multiple_select_filter_controller.js +3 -1
- data/app/javascript/js/controllers/select_filter_controller.js +1 -1
- data/app/views/avo/base/_boolean_filter.html.erb +1 -14
- data/app/views/avo/base/_multiple_select_filter.html.erb +2 -13
- data/app/views/avo/base/_select_filter.html.erb +1 -9
- data/app/views/avo/base/_text_filter.html.erb +2 -10
- 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/lib/avo/app.rb +37 -12
- data/lib/avo/configuration.rb +2 -0
- data/lib/avo/engine.rb +13 -0
- data/lib/avo/fields/code_field.rb +1 -1
- data/lib/avo/filters/base_filter.rb +17 -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/licensing/h_q.rb +52 -15
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/initializer/avo.tt +1 -0
- data/lib/tasks/avo_tasks.rake +30 -0
- data/public/avo-assets/avo.css +11 -0
- data/public/avo-assets/avo.js +3 -3
- data/public/avo-assets/avo.js.map +2 -2
- metadata +4 -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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 495fa6563fa7c807d8070c90168a91ae1fc5149d12b3ddd909b278abfe725a59
|
4
|
+
data.tar.gz: 076655d016376b0756dd68d5be6487c6b5830dcbfcd197f7b4bce62bc4226a5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9eb0bcd0253809f826b48cc5ab89c7a917ac0c2a3d8a6c4eaac84e1bb94a610d56d8b55b43aef79813e34009e6e17c77b61bd07d5208f3464a5a30d8e231939a
|
7
|
+
data.tar.gz: 0a1c0805378ccfbd11d173716ba179e05d0d67159ad14c5781de30282be619b1b558e45bd9aefc46dbdc3a21cfad1f750606e8be6b82568f6866938ca2fc44c9
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (2.
|
4
|
+
avo (2.4.0)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
@@ -248,8 +248,6 @@ GEM
|
|
248
248
|
nokogiri (1.13.4)
|
249
249
|
mini_portile2 (~> 2.8.0)
|
250
250
|
racc (~> 1.4)
|
251
|
-
nokogiri (1.13.4-x86_64-linux)
|
252
|
-
racc (~> 1.4)
|
253
251
|
orm_adapter (0.5.0)
|
254
252
|
pagy (5.10.1)
|
255
253
|
activesupport
|
@@ -1,3 +1,3 @@
|
|
1
|
-
<%= link_to path, class: "flex-1 flex items-center justify-center bg-white text-left cursor-pointer text-gray-800 font-semibold hover:bg-blue-100 block px-4 py-1 w-full py-3 text-center rounded w-full", target: target do %>
|
1
|
+
<%= link_to path, class: "flex-1 flex items-center justify-center bg-white text-left cursor-pointer text-gray-800 font-semibold hover:bg-blue-100 block px-4 py-1 w-full py-3 text-center rounded w-full", target: target, title: title do %>
|
2
2
|
<%= helpers.svg(icon, class: 'h-4 mr-1') if icon.present? %> <%= label %>
|
3
3
|
<% end %>
|
@@ -7,11 +7,16 @@ class Avo::ProfileItemComponent < ViewComponent::Base
|
|
7
7
|
attr_reader :active
|
8
8
|
attr_reader :target
|
9
9
|
|
10
|
-
def initialize(label: nil, icon: nil, path: nil, active: :inclusive, target: nil)
|
10
|
+
def initialize(label: nil, icon: nil, path: nil, active: :inclusive, target: nil, title: nil)
|
11
11
|
@label = label
|
12
12
|
@icon = icon
|
13
13
|
@path = path
|
14
14
|
@active = active
|
15
15
|
@target = target
|
16
|
+
@title = title
|
17
|
+
end
|
18
|
+
|
19
|
+
def title
|
20
|
+
@title || @label
|
16
21
|
end
|
17
22
|
end
|
@@ -1,4 +1,7 @@
|
|
1
|
-
<div
|
1
|
+
<div
|
2
|
+
class="fixed z-[60] application-sidebar hidden lg:flex h-full bg-white text-white w-64 border-r <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>"
|
3
|
+
data-mobile-target="sidebar"
|
4
|
+
>
|
2
5
|
<div class="flex flex-col w-full h-full">
|
3
6
|
<div class="flex justify-between">
|
4
7
|
<%= render partial: "avo/partials/logo" %>
|
@@ -10,7 +13,7 @@
|
|
10
13
|
<div class="space-y-6 mb-4">
|
11
14
|
<%= render Avo::Sidebar::LinkComponent.new label: 'Get started', path: helpers.avo.root_path, active: :exclusive if Rails.env.development? && Avo.configuration.home_path.nil? %>
|
12
15
|
|
13
|
-
<% if Avo::App.
|
16
|
+
<% if Avo::App.has_main_menu? %>
|
14
17
|
<div class="text-black">
|
15
18
|
<% Avo::App.main_menu.items.each do |item| %>
|
16
19
|
<%= render Avo::Sidebar::ItemSwitcherComponent.new item: item %>
|
@@ -25,7 +25,7 @@
|
|
25
25
|
class="hidden absolute flex flex-col inset-auto right-0 -mt-12 bg-white rounded min-w-[200px] shadow-context -translate-y-full"
|
26
26
|
data-toggle-panel-target="panel"
|
27
27
|
>
|
28
|
-
<% if Avo::App.
|
28
|
+
<% if Avo::App.has_profile_menu? %>
|
29
29
|
<div class="text-black space-y-4">
|
30
30
|
<% Avo::App.profile_menu.items.each do |item| %>
|
31
31
|
<% if item.is_a? Avo::Menu::Link %>
|
@@ -34,6 +34,9 @@
|
|
34
34
|
<% end %>
|
35
35
|
</div>
|
36
36
|
<% end %>
|
37
|
+
<% if Rails.env.development? %>
|
38
|
+
<%= render Avo::ProfileItemComponent.new label: 'Debug', path: "#{root_path}avo_private/debug", icon: 'heroicons/outline/receipt-refund', title: 'Menu item visible only in development.' %>
|
39
|
+
<% end %>
|
37
40
|
<%# Example link below %>
|
38
41
|
<%#= render Avo::ProfileItemComponent.new label: 'Profile', path: '/profile', icon: 'user-circle' %>
|
39
42
|
<%= button_to helpers.main_app.send(destroy_user_session_path),
|
@@ -5,6 +5,7 @@ module Avo
|
|
5
5
|
before_action :set_resource_name
|
6
6
|
before_action :set_resource
|
7
7
|
before_action :hydrate_resource
|
8
|
+
before_action :set_applied_filters, only: :index
|
8
9
|
before_action :set_model, only: [:show, :edit, :destroy, :update, :order]
|
9
10
|
before_action :set_model_to_fill
|
10
11
|
before_action :set_edit_title_and_breadcrumbs, only: [:edit, :update]
|
@@ -55,8 +56,8 @@ module Avo
|
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
58
|
-
# Apply filters
|
59
|
-
|
59
|
+
# Apply filters to the current query
|
60
|
+
filters_to_be_applied.each do |filter_class, filter_value|
|
60
61
|
@query = filter_class.safe_constantize.new.apply_query request, @query, filter_value
|
61
62
|
end
|
62
63
|
|
@@ -308,28 +309,32 @@ module Avo
|
|
308
309
|
.select { |action| action.visible_in_view }
|
309
310
|
end
|
310
311
|
|
311
|
-
def
|
312
|
-
|
313
|
-
|
314
|
-
|
312
|
+
def set_applied_filters
|
313
|
+
@applied_filters = JSON.parse(Base64.decode64(params[:filters]))
|
314
|
+
rescue
|
315
|
+
@applied_filters = {}
|
316
|
+
end
|
315
317
|
|
318
|
+
# Get the default state of the filters and override with the user applied filters
|
319
|
+
def filters_to_be_applied
|
316
320
|
filter_defaults = {}
|
317
321
|
|
318
322
|
@resource.get_filters.each do |filter_class|
|
319
323
|
filter = filter_class.new
|
320
324
|
|
321
|
-
|
325
|
+
unless filter.default.nil?
|
322
326
|
filter_defaults[filter_class.to_s] = filter.default
|
323
327
|
end
|
324
328
|
end
|
325
329
|
|
326
|
-
filter_defaults
|
330
|
+
filter_defaults.merge(@applied_filters)
|
327
331
|
end
|
328
332
|
|
333
|
+
# Caching these so we know when the filters have changed so we reset the pagination
|
329
334
|
def cache_applied_filters
|
330
335
|
::Avo::App.cache_store.delete applied_filters_cache_key if params[:filters].nil?
|
331
336
|
|
332
|
-
::Avo::App.cache_store.write(applied_filters_cache_key, params[:filters], expires_in:
|
337
|
+
::Avo::App.cache_store.write(applied_filters_cache_key, params[:filters], expires_in: 1.day)
|
333
338
|
end
|
334
339
|
|
335
340
|
def reset_pagination_if_filters_changed
|
@@ -38,18 +38,22 @@ export default class extends Controller {
|
|
38
38
|
const value = this.getFilterValue()
|
39
39
|
const filterClass = this.getFilterClass()
|
40
40
|
|
41
|
+
// Get the `filters` param for all params
|
41
42
|
let filters = this.uriParams()[this.uriParam('filters')]
|
42
43
|
|
44
|
+
// Decode the filters
|
43
45
|
if (filters) {
|
44
46
|
filters = JSON.parse(this.b64DecodeUnicode(filters))
|
45
47
|
} else {
|
46
48
|
filters = {}
|
47
49
|
}
|
48
50
|
|
51
|
+
// Get the values for this particular filter
|
49
52
|
filters[filterClass] = value
|
50
53
|
|
51
54
|
const filtered = Object.keys(filters)
|
52
|
-
|
55
|
+
// Filter out the filters without a value
|
56
|
+
.filter((key) => filters[key] !== null)
|
53
57
|
.reduce((obj, key) => {
|
54
58
|
obj[key] = filters[key]
|
55
59
|
|
@@ -58,10 +62,16 @@ export default class extends Controller {
|
|
58
62
|
|
59
63
|
let encodedFilters
|
60
64
|
|
65
|
+
// Encode the filters and their values
|
61
66
|
if (filtered && Object.keys(filtered).length > 0) {
|
62
67
|
encodedFilters = this.b64EncodeUnicode(JSON.stringify(filtered))
|
63
68
|
}
|
64
69
|
|
70
|
+
this.navigateToURLWithFilters(encodedFilters)
|
71
|
+
}
|
72
|
+
|
73
|
+
navigateToURLWithFilters(encodedFilters) {
|
74
|
+
// Create a new URI with them
|
65
75
|
const url = new URI(this.urlRedirectTarget.href)
|
66
76
|
|
67
77
|
const query = {
|
@@ -4,7 +4,9 @@ export default class extends BaseFilterController {
|
|
4
4
|
static targets = ['selector']
|
5
5
|
|
6
6
|
getFilterValue() {
|
7
|
-
|
7
|
+
const filterValue = Array.from(this.selectorTarget.selectedOptions).map(({ value }) => value)
|
8
|
+
|
9
|
+
return filterValue.length === 0 ? null : filterValue
|
8
10
|
}
|
9
11
|
|
10
12
|
getFilterClass() {
|
@@ -1,23 +1,10 @@
|
|
1
|
-
<%
|
2
|
-
begin
|
3
|
-
decoded_filters_param = JSON.parse(Base64.decode64(params[:filters]))
|
4
|
-
set_value = decoded_filters_param[filter.class.to_s]
|
5
|
-
rescue => exception
|
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
1
|
<div data-controller="boolean-filter" data-filter-name="<%= filter.name %>">
|
15
2
|
<%= filter_wrapper name: filter.name do %>
|
16
3
|
<div class="flex items-center">
|
17
4
|
<div class="space-y-2">
|
18
5
|
<% filter.options.each do |value, label| %>
|
19
6
|
<label class="flex items-center text-gray-700 text-sm">
|
20
|
-
<%= check_box_tag filter.id, value,
|
7
|
+
<%= check_box_tag filter.id, value, filter.selected_value(value.to_s, @applied_filters),
|
21
8
|
class: 'mr-2 text-lg h-4 w-4',
|
22
9
|
id: "avo_filters_#{filter.id.parameterize.underscore}",
|
23
10
|
'data-filter-class': filter.class,
|
@@ -1,17 +1,6 @@
|
|
1
|
-
<%
|
2
|
-
set_value = filter.default.present? ? filter.default.select { |key, value| value }.keys.map(&:to_sym) : {}
|
3
|
-
|
4
|
-
begin
|
5
|
-
decoded_filters_param = JSON.parse(Base64.decode64(params[:filters]))
|
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
1
|
<div data-controller="multiple-select-filter" data-filter-name="<%= filter.name %>">
|
13
2
|
<%= filter_wrapper name: filter.name do %>
|
14
|
-
<%= select_tag filter.id, options_for_select(filter.options.invert,
|
3
|
+
<%= select_tag filter.id, options_for_select(filter.options.invert, filter.selected_value(@applied_filters)),
|
15
4
|
class: input_classes('w-full mb-0'),
|
16
5
|
multiple: true,
|
17
6
|
id: "avo_filters_#{filter.id.parameterize.underscore}",
|
@@ -19,7 +8,7 @@
|
|
19
8
|
'data-multiple-select-filter-target': 'selector'
|
20
9
|
%>
|
21
10
|
<div class="flex justify-end">
|
22
|
-
<%= a_button class: 'mt-4', color: :blue, size: :
|
11
|
+
<%= a_button class: 'mt-4', color: :blue, size: :xs, data: { action: "multiple-select-filter#changeFilter" } do %>
|
23
12
|
Filter by <%=filter.name %>
|
24
13
|
<% end %>
|
25
14
|
</div>
|
@@ -1,14 +1,6 @@
|
|
1
|
-
<%
|
2
|
-
begin
|
3
|
-
decoded_filters_param = JSON.parse(Base64.decode64(params[:filters]))
|
4
|
-
set_value = decoded_filters_param[filter.class.to_s]
|
5
|
-
rescue => exception
|
6
|
-
set_value = filter.default
|
7
|
-
end
|
8
|
-
%>
|
9
1
|
<div data-controller="select-filter" data-filter-name="<%= filter.name %>">
|
10
2
|
<%= filter_wrapper name: filter.name do %>
|
11
|
-
<%= select_tag filter.id, options_for_select(filter.options.invert,
|
3
|
+
<%= select_tag filter.id, options_for_select(filter.options.invert, filter.applied_or_default_value(@applied_filters)),
|
12
4
|
class: input_classes('w-full mb-0'),
|
13
5
|
include_blank: '—',
|
14
6
|
id: "avo_filters_#{filter.id.parameterize.underscore}",
|
@@ -1,14 +1,6 @@
|
|
1
|
-
<%
|
2
|
-
begin
|
3
|
-
decoded_filters_param = JSON.parse(Base64.decode64(params[:filters]))
|
4
|
-
set_value = decoded_filters_param[filter.class.to_s]
|
5
|
-
rescue => exception
|
6
|
-
set_value = filter.default
|
7
|
-
end
|
8
|
-
%>
|
9
1
|
<div data-controller="text-filter" data-filter-name="<%= filter.name %>">
|
10
2
|
<%= filter_wrapper name: filter.name do %>
|
11
|
-
<%= text_field_tag filter.id,
|
3
|
+
<%= text_field_tag filter.id, filter.applied_or_default_value(@applied_filters),
|
12
4
|
class: input_classes('w-full mb-0'),
|
13
5
|
id: "avo_filters_#{filter.id.parameterize.underscore}",
|
14
6
|
'data-filter-class': filter.class.to_s,
|
@@ -16,7 +8,7 @@
|
|
16
8
|
'data-action': 'keypress->text-filter#tryToSubmit'
|
17
9
|
%>
|
18
10
|
<div class="flex justify-end">
|
19
|
-
<%= a_button class: 'mt-4', color: :blue, data: { action: "text-filter#changeFilter" }, size: :
|
11
|
+
<%= a_button class: 'mt-4', color: :blue, data: { action: "text-filter#changeFilter" }, size: :xs do %>
|
20
12
|
<%= filter.button_label || "Filter by #{filter.name}" %>
|
21
13
|
<% end %>
|
22
14
|
</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/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/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
|
@@ -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,11 +3,11 @@ module Avo
|
|
3
3
|
class BaseFilter
|
4
4
|
class_attribute :name, default: "Filter"
|
5
5
|
class_attribute :component, default: "boolean-filter"
|
6
|
-
class_attribute :default, default:
|
6
|
+
class_attribute :default, default: nil
|
7
7
|
class_attribute :template, default: "avo/base/select_filter"
|
8
8
|
|
9
9
|
def apply_query(request, query, value)
|
10
|
-
value.
|
10
|
+
value.stringify_keys! if value.is_a? Hash
|
11
11
|
|
12
12
|
apply(request, query, value)
|
13
13
|
end
|
@@ -15,6 +15,21 @@ module Avo
|
|
15
15
|
def id
|
16
16
|
self.class.name.underscore.tr("/", "_")
|
17
17
|
end
|
18
|
+
|
19
|
+
# Get the applied value this filter.
|
20
|
+
# If it's not present return the default value.
|
21
|
+
def applied_or_default_value(applied_filters)
|
22
|
+
# Get the values for this particular filter
|
23
|
+
applied_value = applied_filters[self.class.to_s]
|
24
|
+
|
25
|
+
# Return that value if present
|
26
|
+
return applied_value unless applied_value.nil?
|
27
|
+
|
28
|
+
# Return that default
|
29
|
+
default
|
30
|
+
rescue
|
31
|
+
default
|
32
|
+
end
|
18
33
|
end
|
19
34
|
end
|
20
35
|
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
|