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.

Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -3
  3. data/app/assets/stylesheets/css/components/code.css +1 -0
  4. data/app/components/avo/profile_item_component.html.erb +1 -1
  5. data/app/components/avo/profile_item_component.rb +6 -1
  6. data/app/components/avo/sidebar_component.html.erb +5 -2
  7. data/app/components/avo/sidebar_profile_component.html.erb +4 -1
  8. data/app/controllers/avo/base_controller.rb +14 -9
  9. data/app/controllers/avo/debug_controller.rb +3 -0
  10. data/app/javascript/js/controllers/fields/code_field_controller.js +0 -1
  11. data/app/javascript/js/controllers/filter_controller.js +11 -1
  12. data/app/javascript/js/controllers/multiple_select_filter_controller.js +3 -1
  13. data/app/javascript/js/controllers/select_filter_controller.js +1 -1
  14. data/app/views/avo/base/_boolean_filter.html.erb +1 -14
  15. data/app/views/avo/base/_multiple_select_filter.html.erb +2 -13
  16. data/app/views/avo/base/_select_filter.html.erb +1 -9
  17. data/app/views/avo/base/_text_filter.html.erb +2 -10
  18. data/app/views/avo/debug/index.html.erb +3 -3
  19. data/app/views/avo/debug/report.html.erb +1 -1
  20. data/app/views/avo/partials/_footer.html.erb +1 -1
  21. data/app/views/avo/partials/_navbar.html.erb +4 -1
  22. data/lib/avo/app.rb +37 -12
  23. data/lib/avo/configuration.rb +2 -0
  24. data/lib/avo/engine.rb +13 -0
  25. data/lib/avo/fields/code_field.rb +1 -1
  26. data/lib/avo/filters/base_filter.rb +17 -2
  27. data/lib/avo/filters/boolean_filter.rb +12 -0
  28. data/lib/avo/filters/multiple_select_filter.rb +15 -0
  29. data/lib/avo/filters/text_filter.rb +4 -0
  30. data/lib/avo/licensing/h_q.rb +52 -15
  31. data/lib/avo/version.rb +1 -1
  32. data/lib/generators/avo/templates/initializer/avo.tt +1 -0
  33. data/lib/tasks/avo_tasks.rake +30 -0
  34. data/public/avo-assets/avo.css +11 -0
  35. data/public/avo-assets/avo.js +3 -3
  36. data/public/avo-assets/avo.js.map +2 -2
  37. metadata +4 -8
  38. data/app/assets/builds/avo.css +0 -8846
  39. data/app/assets/builds/avo.js +0 -423
  40. data/app/assets/builds/avo.js.map +0 -7
  41. data/app/mailers/avo/application_mailer.rb +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa5d2395db02e3b37f787b0680a4cae6748c99049f369d8e2a3db2fb6c2a2dd8
4
- data.tar.gz: 4de2e1dcc865e6ebbc693ddefd4e5407f9d6a6c60f3c1153deeb8d7dcc6ba17b
3
+ metadata.gz: 495fa6563fa7c807d8070c90168a91ae1fc5149d12b3ddd909b278abfe725a59
4
+ data.tar.gz: 076655d016376b0756dd68d5be6487c6b5830dcbfcd197f7b4bce62bc4226a5d
5
5
  SHA512:
6
- metadata.gz: 498b612171a47529d988c8ba89ac0330013afef141a0a4d74df9d41fe60b7d00543777be08b0fa35bf1a5972c06f512a2be76510f4b5a9fd90d779c7fc90a2e8
7
- data.tar.gz: fefaff30ae62e0c5de60d64f3e5952bca7b1ae816d454613f3803ca268b2724505231dff2d9d9ce348a625a7ecf74fc9c669179fbbf03366f2c4c26a52c9b277
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.3.1.pre.6)
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
@@ -8,6 +8,7 @@
8
8
  .CodeMirror {
9
9
  height: var(--height) !important;
10
10
  min-height: auto;
11
+ padding: 0;
11
12
  }
12
13
 
13
14
  /* overlay CodeMirror fullscreen & Preview on small screens */
@@ -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 class="fixed z-[60] application-sidebar hidden lg:flex h-full bg-white text-white w-64 border-r" data-mobile-target="sidebar">
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.license.has_with_trial(:menu_editor) && Avo.configuration.main_menu.present? %>
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.license.has_with_trial(:menu_editor) && Avo.configuration.profile_menu.present? %>
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
- applied_filters.each do |filter_class, filter_value|
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 applied_filters
312
- if params[:filters].present?
313
- return JSON.parse(Base64.decode64(params[:filters]))
314
- end
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
- if filter.default.present?
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: 7.days)
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
@@ -5,6 +5,9 @@ module Avo
5
5
  def index
6
6
  end
7
7
 
8
+ def report
9
+ end
10
+
8
11
  def refresh_license
9
12
  license = Licensing::LicenseManager.refresh_license request
10
13
 
@@ -1,5 +1,4 @@
1
1
  import 'codemirror/mode/css/css'
2
-
3
2
  import 'codemirror/mode/dockerfile/dockerfile'
4
3
  import 'codemirror/mode/htmlmixed/htmlmixed'
5
4
  import 'codemirror/mode/javascript/javascript'
@@ -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
- .filter((key) => filters[key] !== '')
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
- return Array.from(this.selectorTarget.selectedOptions).map(({ value }) => value)
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() {
@@ -4,7 +4,7 @@ export default class extends BaseFilterController {
4
4
  static targets = ['selector']
5
5
 
6
6
  getFilterValue() {
7
- return this.selectorTarget.value
7
+ return this.selectorTarget.value === '' ? null : this.selectorTarget.value
8
8
  }
9
9
 
10
10
  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, set_value[value.to_s],
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, set_value),
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: :sm, data: { action: "multiple-select-filter#changeFilter" } do %>
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, set_value),
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, set_value,
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: :sm do %>
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 justify-between flex-1">
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: '/admin/avo_private/debug/refresh_license',
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="/admin/avo_private/debug/report" target="_top" class="block">
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> · &copy; <%= 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 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]" v-if="layout !== 'blank'">
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
- return [] if Avo::App.license.lacks_with_trial(:menu_builder)
109
- return [] if Avo.configuration.main_menu.nil?
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
- return [] if Avo::App.license.lacks_with_trial(:menu_builder)
116
- return [] if Avo.configuration.profile_menu.nil?
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[:hq_payload] = hq.payload
126
- payload[:license_id] = Avo::App.license.id
127
- payload[:license_valid] = Avo::App.license.valid?
128
- payload[:license_payload] = Avo::App.license.payload
129
- payload[:license_response] = Avo::App.license.response
130
- payload[:cache_store] = self.cache_store.class.to_s
131
- payload[:avo_metadata] = hq.avo_metadata
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
@@ -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 : "material-darker"
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.symbolize_keys! if value.is_a? Hash
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
@@ -4,6 +4,10 @@ module Avo
4
4
  class_attribute :button_label
5
5
 
6
6
  self.template = "avo/base/text_filter"
7
+
8
+ def selected_value(applied_filters)
9
+ applied_or_default_value
10
+ end
7
11
  end
8
12
  end
9
13
  end