avo 2.5.2.pre.7 → 2.6.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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/app/assets/stylesheets/avo.css +33 -1
  4. data/app/assets/stylesheets/css/search.css +1 -1
  5. data/app/assets/svgs/heroicons/solid/user-remove.svg +1 -1
  6. data/app/components/avo/actions_component.html.erb +3 -2
  7. data/app/components/avo/alert_component.html.erb +1 -1
  8. data/app/components/avo/alert_component.rb +24 -5
  9. data/app/components/avo/button_component.rb +50 -17
  10. data/app/components/avo/card_component.rb +12 -0
  11. data/app/components/avo/fields/concerns/item_labels.rb +40 -0
  12. data/app/components/avo/fields/tags_field/edit_component.html.erb +1 -1
  13. data/app/components/avo/fields/tags_field/index_component.html.erb +1 -5
  14. data/app/components/avo/fields/tags_field/index_component.rb +2 -0
  15. data/app/components/avo/fields/tags_field/show_component.rb +3 -7
  16. data/app/components/avo/fields/tags_field/tag_component.html.erb +1 -1
  17. data/app/components/avo/filters_component.html.erb +1 -1
  18. data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
  19. data/app/components/avo/index/grid_cover_empty_state_component.html.erb +1 -1
  20. data/app/components/avo/index/table_row_component.html.erb +1 -1
  21. data/app/components/avo/panel_component.html.erb +3 -3
  22. data/app/components/avo/panel_component.rb +1 -1
  23. data/app/components/avo/resource_component.rb +50 -0
  24. data/app/components/avo/sidebar/group_component.html.erb +4 -2
  25. data/app/components/avo/sidebar/heading_component.html.erb +1 -1
  26. data/app/components/avo/sidebar/link_component.html.erb +1 -1
  27. data/app/components/avo/sidebar/link_component.rb +1 -1
  28. data/app/components/avo/sidebar_component.html.erb +5 -13
  29. data/app/components/avo/sidebar_profile_component.html.erb +1 -1
  30. data/app/components/avo/views/resource_edit_component.html.erb +28 -3
  31. data/app/components/avo/views/resource_edit_component.rb +4 -6
  32. data/app/components/avo/views/resource_index_component.html.erb +17 -9
  33. data/app/components/avo/views/resource_new_component.html.erb +8 -2
  34. data/app/components/avo/views/resource_show_component.html.erb +16 -6
  35. data/app/components/avo/views/resource_show_component.rb +0 -45
  36. data/app/controllers/avo/actions_controller.rb +23 -8
  37. data/app/controllers/avo/associations_controller.rb +3 -3
  38. data/app/controllers/avo/base_controller.rb +11 -21
  39. data/app/controllers/avo/private_controller.rb +1 -0
  40. data/app/controllers/avo/search_controller.rb +2 -2
  41. data/app/helpers/avo/application_helper.rb +1 -1
  42. data/app/javascript/js/controllers/fields/key_value_controller.js +1 -1
  43. data/app/javascript/js/controllers/fields/tags_field_controller.js +3 -3
  44. data/app/javascript/js/controllers/filter_controller.js +4 -1
  45. data/app/javascript/js/controllers.js +0 -2
  46. data/app/views/avo/actions/show.html.erb +5 -2
  47. data/app/views/avo/dashboards/_chartkick_card.html.erb +1 -1
  48. data/app/views/avo/dashboards/_metric_card.html.erb +1 -1
  49. data/app/views/avo/partials/_logo.html.erb +1 -1
  50. data/app/views/avo/partials/_navbar.html.erb +9 -6
  51. data/app/views/avo/partials/_table_header.html.erb +3 -2
  52. data/app/views/avo/private/_links_and_buttons.html.erb +2 -2
  53. data/app/views/layouts/avo/application.html.erb +50 -53
  54. data/lib/avo/base_action.rb +24 -6
  55. data/lib/avo/engine.rb +1 -1
  56. data/lib/avo/fields/belongs_to_field.rb +4 -4
  57. data/lib/avo/fields/has_and_belongs_to_many_field.rb +2 -2
  58. data/lib/avo/fields/has_base_field.rb +2 -0
  59. data/lib/avo/fields/has_many_field.rb +2 -2
  60. data/lib/avo/fields/has_one_field.rb +2 -2
  61. data/lib/avo/fields/tags_field.rb +5 -5
  62. data/lib/avo/version.rb +1 -1
  63. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  64. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  65. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  66. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  67. data/lib/tasks/avo_tasks.rake +7 -3
  68. data/public/avo-assets/avo.css +233 -176
  69. data/public/avo-assets/avo.js +63 -63
  70. data/public/avo-assets/avo.js.map +3 -3
  71. metadata +5 -9
  72. data/app/assets/builds/avo.css +0 -9557
  73. data/app/assets/builds/avo.js +0 -512
  74. data/app/assets/builds/avo.js.map +0 -7
  75. data/app/assets/stylesheets/css/alerts.css +0 -35
  76. data/app/javascript/js/controllers/alerts_controller.js +0 -26
@@ -1,4 +1,6 @@
1
- <div data-model-id="<%= @resource.model.id %>">
1
+ <div data-model-id="<%= @resource.model.id %>"
2
+ class="space-y-8"
3
+ >
2
4
  <% @resource.panels.each do |resource_panel| %>
3
5
  <%= form_with model: @resource.model,
4
6
  scope: @resource.form_scope,
@@ -9,11 +11,17 @@
9
11
  <%= render Avo::ReferrerParamsComponent.new back_path: back_path %>
10
12
  <%= render Avo::PanelComponent.new(title: resource_panel[:name], description: @resource.resource_description, display_breadcrumbs: true) do |c| %>
11
13
  <% c.tools do %>
12
- <%= a_link back_path, icon: 'arrow-left' do %>
14
+ <%= a_link back_path,
15
+ style: :text,
16
+ icon: 'arrow-left' do %>
13
17
  <%= t('avo.cancel').capitalize %>
14
18
  <% end %>
15
19
  <% if can_see_the_save_button? %>
16
- <%= a_button color: :green, loading: true, type: :submit, icon: 'save' do %>
20
+ <%= a_button color: :primary,
21
+ style: :primary,
22
+ loading: true,
23
+ type: :submit,
24
+ icon: 'save' do %>
17
25
  <%= t('avo.save').capitalize %>
18
26
  <% end %>
19
27
  <% end %>
@@ -40,4 +48,21 @@
40
48
  <% end %>
41
49
  <% end %>
42
50
  <% end %>
51
+ <% if @reflection.blank? %>
52
+ <% if has_one_panels.present? %>
53
+ <% has_one_panels.each_with_index do |field, index| %>
54
+ <%= render field.component_for_view(:show).new(field: field, resource: @resource, index: index) %>
55
+ <% end %>
56
+ <% end %>
57
+ <% if has_many_panels.present? %>
58
+ <% has_many_panels.each_with_index do |field, index| %>
59
+ <%= render field.component_for_view(:show).new(field: field, resource: @resource, index: index) %>
60
+ <% end %>
61
+ <% end %>
62
+ <% if has_as_belongs_to_many_panels.present? %>
63
+ <% has_as_belongs_to_many_panels.each_with_index do |field, index| %>
64
+ <%= render field.component_for_view(:show).new(field: field, resource: @resource, index: index) %>
65
+ <% end %>
66
+ <% end %>
67
+ <% end %>
43
68
  </div>
@@ -4,8 +4,12 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
4
4
  include Avo::ResourcesHelper
5
5
  include Avo::ApplicationHelper
6
6
 
7
+ attr_reader :fields_by_panel, :has_one_panels, :has_many_panels, :has_as_belongs_to_many_panels
8
+
7
9
  def initialize(resource: nil)
8
10
  @resource = resource
11
+
12
+ split_panel_fields
9
13
  end
10
14
 
11
15
  def back_path
@@ -21,10 +25,4 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
21
25
  def can_see_the_save_button?
22
26
  @resource.authorization.authorize_action :edit, raise_exception: false
23
27
  end
24
-
25
- private
26
-
27
- def via_resource?
28
- params[:via_resource_class].present? && params[:via_resource_id].present?
29
- end
30
28
  end
@@ -1,19 +1,28 @@
1
1
  <div>
2
2
  <%= render Avo::PanelComponent.new(title: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
3
3
  <% c.tools do %>
4
+ <% if can_attach? %>
5
+ <%= a_link attach_path,
6
+ icon: 'heroicons/outline/link',
7
+ color: :primary,
8
+ style: :text,
9
+ 'data-turbo-frame': 'attach_modal',
10
+ 'data-target': 'attach' do %>
11
+ <%= t('avo.attach_item', item: singular_resource_name).capitalize %>
12
+ <% end %>
13
+ <% end %>
4
14
  <% if can_see_the_actions_button? %>
5
15
  <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
6
16
  <% end %>
7
17
  <% if can_see_the_create_button? %>
8
- <%= a_link create_path, icon: 'heroicons/outline/plus', 'data-target': 'create', color: :primary do %>
18
+ <%= a_link create_path,
19
+ icon: 'heroicons/outline/plus',
20
+ 'data-target': 'create',
21
+ style: :primary,
22
+ color: :primary do %>
9
23
  <%= t('avo.create_new_item', item: singular_resource_name.downcase ) %>
10
24
  <% end %>
11
25
  <% end %>
12
- <% if can_attach? %>
13
- <%= a_link attach_path, icon: 'heroicons/outline/link', color: :primary, 'data-turbo-frame': 'attach_modal', 'data-target': 'attach' do %>
14
- <%= t('avo.attach_item', item: singular_resource_name).capitalize %>
15
- <% end %>
16
- <% end %>
17
26
  <% end %>
18
27
  <% c.body do %>
19
28
  <div class="flex flex-col xs:flex-row xs:justify-between space-y-2 xs:space-y-0 py-4 <%= 'hidden' if @resource.search_query.nil? && @filters.empty? && available_view_types.count <= 1 %>"
@@ -50,15 +59,14 @@
50
59
  <% c.bare_content do %>
51
60
  <% if view_type.to_sym == :table %>
52
61
  <% if @models.present? %>
53
- <div class="mt-8">
62
+ <div class="mt-4">
54
63
  <%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_model: @parent_model %>
55
64
  </div>
56
65
  <% end %>
57
66
  <% end %>
58
-
59
67
  <% if view_type.to_sym == :grid %>
60
68
  <%= render Avo::Index::ResourceGridComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model) %>
61
- <div class="mt-14">
69
+ <div class="mt-6">
62
70
  <%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_model: @parent_model %>
63
71
  </div>
64
72
  <% end %>
@@ -14,11 +14,17 @@
14
14
  <%= render Avo::PanelComponent.new(title: resource_panel[:name], description: @resource.resource_description, display_breadcrumbs: true) do |c| %>
15
15
  <% c.tools do %>
16
16
  <div class="flex justify-end space-x-2">
17
- <%= a_link back_path, icon: 'arrow-left' do %>
17
+ <%= a_link back_path,
18
+ style: :text,
19
+ icon: 'arrow-left' do %>
18
20
  <%= t('avo.cancel').capitalize %>
19
21
  <% end %>
20
22
  <% if can_see_the_save_button? %>
21
- <%= a_button color: 'green', loading: true, type: :submit, icon: 'save' do %>
23
+ <%= a_button color: :primary,
24
+ style: :primary,
25
+ loading: true,
26
+ type: :submit,
27
+ icon: 'save' do %>
22
28
  <%= t('avo.save').capitalize %>
23
29
  <% end %>
24
30
  <% end %>
@@ -1,39 +1,45 @@
1
1
  <div data-model-id="<%= @resource.model.id %>"
2
2
  data-selected-resources-name="<%= @resource.model_key %>"
3
3
  data-selected-resources='["<%= @resource.model.id %>"]'
4
- class="space-y-8"
4
+ class="space-y-12"
5
5
  >
6
6
  <% @resource.panels.each_with_index do |resource_panel, index| %>
7
7
  <%= render Avo::PanelComponent.new(title: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: index) do |c| %>
8
8
  <% c.tools do %>
9
9
  <% if resource_panel[:name] == @resource.default_panel_name %>
10
10
  <% if @reflection.present? && @resource.model.present? %>
11
- <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
12
11
  <% if can_detach? %>
13
12
  <%= a_button url: detach_path,
14
13
  icon: 'detach',
15
14
  method: :delete,
16
15
  form_class: 'flex flex-col sm:flex-row sm:inline-flex',
16
+ style: :text,
17
17
  data: {
18
18
  confirm: "Are you sure you want to detach this #{@reflection.name.to_s}."
19
19
  } do %>
20
20
  <%= t('avo.detach_item', item: @reflection.name.to_s).capitalize %>
21
21
  <% end %>
22
+ <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
22
23
  <% end %>
23
24
  <% if can_see_the_edit_button? %>
24
- <%= a_link edit_path, color: :primary, icon: 'edit' do %>
25
+ <%= a_link edit_path,
26
+ color: :primary,
27
+ style: :primary,
28
+ icon: 'edit' do %>
25
29
  <%= t('avo.edit').capitalize %>
26
30
  <% end %>
27
31
  <% end %>
28
32
  <% else %>
29
- <%= a_link back_path, icon: 'arrow-left' do %>
33
+ <%= a_link back_path,
34
+ style: :text,
35
+ icon: 'arrow-left' do %>
30
36
  <%= t('avo.go_back') %>
31
37
  <% end %>
32
- <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
33
38
  <% if can_see_the_destroy_button? %>
34
39
  <%= a_button url: helpers.resource_path(model: @resource.model, resource: @resource),
35
40
  method: :delete,
36
41
  local: true,
42
+ style: :text,
37
43
  title: t('avo.delete_item', item: @resource.model.model_name.name.downcase).capitalize,
38
44
  loading: true,
39
45
  confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
@@ -48,8 +54,12 @@
48
54
  <%= t('avo.delete').capitalize %>
49
55
  <% end %>
50
56
  <% end %>
57
+ <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
51
58
  <% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
52
- <%= a_link edit_path, color: :primary, icon: 'edit' do %>
59
+ <%= a_link edit_path,
60
+ color: :primary,
61
+ style: :primary,
62
+ icon: 'edit' do %>
53
63
  <%= t('avo.edit').capitalize %>
54
64
  <% end %>
55
65
  <% end %>
@@ -44,53 +44,8 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
44
44
  helpers.edit_resource_path(model: @resource.model, resource: @resource, **args)
45
45
  end
46
46
 
47
- def detach_path
48
- helpers.resource_detach_path(params[:resource_name], params[:id], @reflection.name.to_s, @resource.model.id)
49
- end
50
-
51
- def destroy_path
52
- helpers.resource_path(model: @resource.model, resource: @resource)
53
- end
54
-
55
- def can_detach?
56
- authorize_association_for("detach")
57
- end
58
-
59
- def can_see_the_edit_button?
60
- @resource.authorization.authorize_action(:edit, raise_exception: false)
61
- end
62
-
63
- def can_see_the_destroy_button?
64
- @resource.authorization.authorize_action(:destroy, raise_exception: false)
65
- end
66
-
67
47
  private
68
48
 
69
- def via_resource?
70
- params[:via_resource_class].present? && params[:via_resource_id].present?
71
- end
72
-
73
- def split_panel_fields
74
- @fields_by_panel = {}
75
- @has_one_panels = []
76
- @has_many_panels = []
77
- @has_as_belongs_to_many_panels = []
78
-
79
- @resource.get_fields.each do |field|
80
- case field.class.to_s
81
- when "Avo::Fields::HasOneField"
82
- @has_one_panels << field
83
- when "Avo::Fields::HasManyField"
84
- @has_many_panels << field
85
- when "Avo::Fields::HasAndBelongsToManyField"
86
- @has_as_belongs_to_many_panels << field
87
- else
88
- @fields_by_panel[field.panel_name] ||= []
89
- @fields_by_panel[field.panel_name] << field
90
- end
91
- end
92
- end
93
-
94
49
  # In development and test environments we shoudl show the invalid field errors
95
50
  def should_display_invalid_fields_errors?
96
51
  (Rails.env.development? || Rails.env.test?) && @resource.invalid_fields.present?
@@ -14,14 +14,12 @@ module Avo
14
14
  resource_ids = action_params[:fields][:resource_ids].split(",")
15
15
  models = @resource.class.find_scope.find resource_ids
16
16
 
17
- fields = action_params[:fields].select do |key, value|
18
- key != "resource_ids"
19
- end
17
+ fields = action_params[:fields].except("resource_ids")
20
18
 
21
19
  args = {
22
20
  fields: fields,
23
21
  current_user: _current_user,
24
- resource: resource,
22
+ resource: resource
25
23
  }
26
24
 
27
25
  args[:models] = models unless @action.standalone
@@ -49,8 +47,7 @@ module Avo
49
47
 
50
48
  def respond(response)
51
49
  response[:type] ||= :reload
52
- response[:message_type] ||= :notice
53
- response[:message] ||= I18n.t("avo.action_ran_successfully")
50
+ messages = get_messages response
54
51
 
55
52
  if response[:type] == :download
56
53
  return send_data response[:path], filename: response[:filename]
@@ -58,6 +55,11 @@ module Avo
58
55
 
59
56
  respond_to do |format|
60
57
  format.html do
58
+ # Flash the messages collected from the action
59
+ messages.each do |message|
60
+ flash[message[:type]] = message[:body]
61
+ end
62
+
61
63
  if response[:type] == :redirect
62
64
  path = response[:path]
63
65
 
@@ -65,12 +67,25 @@ module Avo
65
67
  path = instance_eval(&path)
66
68
  end
67
69
 
68
- redirect_to path, "#{response[:message_type]}": response[:message]
70
+ redirect_to path
69
71
  elsif response[:type] == :reload
70
- redirect_back fallback_location: resources_path(resource: @resource), "#{response[:message_type]}": response[:message]
72
+ redirect_back fallback_location: resources_path(resource: @resource)
71
73
  end
72
74
  end
73
75
  end
74
76
  end
77
+
78
+ private
79
+
80
+ def get_messages(response)
81
+ default_message = {
82
+ type: :info,
83
+ body: I18n.t("avo.action_ran_successfully")
84
+ }
85
+
86
+ return [default_message] if response[:messages].blank?
87
+
88
+ response[:messages]
89
+ end
75
90
  end
76
91
  end
@@ -46,8 +46,8 @@ module Avo
46
46
  query = @authorization.apply_policy @attachment_class
47
47
 
48
48
  # Add the association scope to the query scope
49
- if @field.scope.present?
50
- query = Avo::Hosts::AssociationScopeHost.new(block: @field.scope, query: query, parent: @model).handle
49
+ if @field.attach_scope.present?
50
+ query = Avo::Hosts::AssociationScopeHost.new(block: @field.attach_scope, query: query, parent: @model).handle
51
51
  end
52
52
 
53
53
  @options = query.all.map do |model|
@@ -65,7 +65,7 @@ module Avo
65
65
 
66
66
  respond_to do |format|
67
67
  if @model.save
68
- format.html { redirect_to resource_path(model: @model, resource: @resource), notice: t("avo.attachment_class_attached", attachment_class: @related_resource.name) }
68
+ format.html { redirect_back fallback_location: resource_path(model: @model, resource: @resource), notice: t("avo.attachment_class_attached", attachment_class: @related_resource.name) }
69
69
  else
70
70
  format.html { render :new }
71
71
  end
@@ -11,8 +11,6 @@ module Avo
11
11
  before_action :set_edit_title_and_breadcrumbs, only: [:edit, :update]
12
12
  before_action :fill_model, only: [:create, :update]
13
13
  before_action :authorize_action
14
- before_action :reset_pagination_if_filters_changed, only: :index
15
- before_action :cache_applied_filters, only: :index
16
14
 
17
15
  def index
18
16
  @page_title = @resource.plural_name.humanize
@@ -49,10 +47,10 @@ module Avo
49
47
  # Check if the sortable field option is actually a proc and we need to do a custom sort
50
48
  field_id = @index_params[:sort_by].to_sym
51
49
  field = @resource.get_field_definitions.find { |field| field.id == field_id }
52
- if field&.sortable.is_a?(Proc)
53
- @query = field.sortable.call(@query, @index_params[:sort_direction])
50
+ @query = if field&.sortable.is_a?(Proc)
51
+ field.sortable.call(@query, @index_params[:sort_direction])
54
52
  else
55
- @query = @query.order("#{@resource.model_class.table_name}.#{@index_params[:sort_by]} #{@index_params[:sort_direction]}")
53
+ @query.order("#{@resource.model_class.table_name}.#{@index_params[:sort_by]} #{@index_params[:sort_direction]}")
56
54
  end
57
55
  end
58
56
 
@@ -61,7 +59,14 @@ module Avo
61
59
  @query = filter_class.safe_constantize.new.apply_query request, @query, filter_value
62
60
  end
63
61
 
64
- @pagy, @models = pagy(@query, items: @index_params[:per_page], link_extra: "data-turbo-frame=\"#{params[:turbo_frame]}\"", size: [1, 2, 2, 1])
62
+ extra_pagy_params = {}
63
+
64
+ # Reset open filters when a user navigates to a new page
65
+ extra_pagy_params[:keep_filters_panel_open] = if params[:keep_filters_panel_open] == "1"
66
+ "0"
67
+ end
68
+
69
+ @pagy, @models = pagy(@query, items: @index_params[:per_page], link_extra: "data-turbo-frame=\"#{params[:turbo_frame]}\"", size: [1, 2, 2, 1], params: extra_pagy_params)
65
70
 
66
71
  # Create resources for each model
67
72
  @resources = @models.map do |model|
@@ -353,21 +358,6 @@ module Avo
353
358
  filter_defaults.merge(@applied_filters)
354
359
  end
355
360
 
356
- # Caching these so we know when the filters have changed so we reset the pagination
357
- def cache_applied_filters
358
- ::Avo::App.cache_store.delete applied_filters_cache_key if params[:filters].nil?
359
-
360
- ::Avo::App.cache_store.write(applied_filters_cache_key, params[:filters], expires_in: 1.day)
361
- end
362
-
363
- def reset_pagination_if_filters_changed
364
- params[:page] = 1 if params[:filters] != ::Avo::App.cache_store.read(applied_filters_cache_key)
365
- end
366
-
367
- def applied_filters_cache_key
368
- "avo.base_controller.#{@resource.model_key}.applied_filters"
369
- end
370
-
371
361
  def set_edit_title_and_breadcrumbs
372
362
  @resource = @resource.hydrate(model: @model, view: :edit, user: _current_user)
373
363
  @page_title = @resource.default_panel_name.to_s
@@ -3,6 +3,7 @@ require_dependency "avo/application_controller"
3
3
  module Avo
4
4
  class PrivateController < ApplicationController
5
5
  def design
6
+ @page_title = "Design [Private]"
6
7
  end
7
8
  end
8
9
  end
@@ -51,12 +51,12 @@ module Avo
51
51
  # Fetch the field
52
52
  field = belongs_to_field
53
53
 
54
- if field.scope.present?
54
+ if field.attach_scope.present?
55
55
  # Fetch the parent
56
56
  parent = params[:via_reflection_class].safe_constantize.find params[:via_reflection_id]
57
57
 
58
58
  # Add to the query
59
- query = Avo::Hosts::AssociationScopeHost.new(block: belongs_to_field.scope, query: query, parent: parent).handle
59
+ query = Avo::Hosts::AssociationScopeHost.new(block: belongs_to_field.attach_scope, query: query, parent: parent).handle
60
60
  end
61
61
  end
62
62
 
@@ -118,7 +118,7 @@ module Avo
118
118
  end
119
119
 
120
120
  def input_classes(extra_classes = "", has_error: false)
121
- classes = "appearance-none inline-flex bg-gray-100 disabled:cursor-not-allowed text-gray-600 disabled:opacity-50 rounded py-2 px-3 leading-tight border focus:border-gray-600 focus-visible:ring-0 focus:text-gray-700"
121
+ classes = "appearance-none inline-flex bg-gray-25 disabled:cursor-not-allowed text-gray-600 disabled:opacity-50 rounded py-2 px-3 leading-tight border focus:border-gray-600 focus-visible:ring-0 focus:text-gray-700"
122
122
 
123
123
  classes += if has_error
124
124
  " border-red-600"
@@ -110,7 +110,7 @@ export default class extends Controller {
110
110
 
111
111
  inputField(id = 'key', index, key, value) {
112
112
  return `<input
113
- class="${this.options.inputClasses} !rounded-none border-gray-600 border-r border-l-0 border-b-0 border-t-0 focus:border-gray-300 w-1/2 focus:outline-none outline-none key-value-input-${id}"
113
+ class="${this.options.inputClasses} focus:bg-gray-100 !rounded-none border-gray-600 border-r border-l-0 border-b-0 border-t-0 focus:border-gray-300 w-1/2 focus:outline-none outline-none key-value-input-${id}"
114
114
  data-action="input->key-value#${id}FieldUpdated"
115
115
  placeholder="${this.options[`${id}_label`]}"
116
116
  data-index="${index}"
@@ -14,8 +14,8 @@ export default class extends BaseController {
14
14
  return this.getJsonAttribute(this.inputTarget, 'data-whitelist-items', [])
15
15
  }
16
16
 
17
- get blacklistItems() {
18
- return this.getJsonAttribute(this.inputTarget, 'data-blacklist-items', [])
17
+ get disallowedItems() {
18
+ return this.getJsonAttribute(this.inputTarget, 'data-disallowed-items', [])
19
19
  }
20
20
 
21
21
  get enforceSuggestions() {
@@ -37,7 +37,7 @@ export default class extends BaseController {
37
37
  get tagifyOptions() {
38
38
  let options = {
39
39
  whitelist: this.whitelistItems,
40
- blacklist: this.blacklistItems,
40
+ blacklist: this.disallowedItems,
41
41
  enforceWhitelist: this.enforceSuggestions,
42
42
  delimiters: this.delimiters.join('|'),
43
43
  maxTags: 10,
@@ -84,9 +84,12 @@ export default class extends Controller {
84
84
 
85
85
  if (this.keepFiltersPanelOpenValue) {
86
86
  // eslint-disable-next-line camelcase
87
- query.keep_filters_panel_open = this.keepFiltersPanelOpenValue
87
+ query.keep_filters_panel_open = this.keepFiltersPanelOpenValue ? 1 : null
88
88
  }
89
89
 
90
+ // force to go to the first page if the filters changed
91
+ query.page = 1
92
+
90
93
  if (encodedFilters) {
91
94
  query.filters = encodedFilters
92
95
  } else {
@@ -2,7 +2,6 @@ import { application } from './application'
2
2
 
3
3
  import ActionController from './controllers/action_controller'
4
4
  import ActionsPickerController from './controllers/actions_picker_controller'
5
- import AlertsController from './controllers/alerts_controller'
6
5
  import AttachmentsController from './controllers/attachments_controller'
7
6
  import BelongsToFieldController from './controllers/fields/belongs_to_field_controller'
8
7
  import BooleanFilterController from './controllers/boolean_filter_controller'
@@ -33,7 +32,6 @@ import TrixFieldController from './controllers/fields/trix_field_controller'
33
32
 
34
33
  application.register('action', ActionController)
35
34
  application.register('actions-picker', ActionsPickerController)
36
- application.register('alerts', AlertsController)
37
35
  application.register('attachments', AttachmentsController)
38
36
  application.register('boolean-filter', BooleanFilterController)
39
37
  application.register('copy-to-clipboard', CopyToClipboardController)
@@ -29,11 +29,14 @@
29
29
  </div>
30
30
  <% end %>
31
31
  <% c.controls do %>
32
- <%= a_button data: { action: 'click->modal#close' }, size: :sm do %>
32
+ <%= a_button data: { action: 'click->modal#close' },
33
+ size: :sm,
34
+ color: :primary do %>
33
35
  <%= @action.cancel_button_label %>
34
36
  <% end %>
35
37
  <%= a_button type: :submit,
36
- color: :green,
38
+ color: :primary,
39
+ style: :primary,
37
40
  size: :sm,
38
41
  data: @action.class.submit_button_data_attributes do %>
39
42
  <%= @action.confirm_button_label %>
@@ -1,3 +1,3 @@
1
1
  <div class="relative flex flex-col <%= @card.chartkick_classes %>">
2
- <%= send(@card.chart_type, @card.compute_result.result_data, **@card.chartkick_options) %>
2
+ <%= send(@card.chart_type, @card.result_data, **@card.chartkick_options) %>
3
3
  </div>
@@ -1,5 +1,5 @@
1
1
  <div class="flex mt-4 items-end">
2
2
  <span class="text-3xl"><%= @card.prefix %></span>
3
- <span class="text-5xl"><%= @card.compute_result.result_data %></span>
3
+ <span class="text-5xl"><%= @card.result_data %></span>
4
4
  <span class="text-3xl"><%= @card.suffix %></span>
5
5
  </div>
@@ -1,3 +1,3 @@
1
- <%= link_to root_path, class: 'logo-placeholder h-20 bg-white p-4 flex justify-start' do %>
1
+ <%= link_to root_path, class: 'logo-placeholder h-10 bg-white flex justify-start' do %>
2
2
  <%= image_tag '/avo-assets/logo.png', class: 'h-full', title: 'Avo' %>
3
3
  <% end %>
@@ -1,14 +1,17 @@
1
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 %>"
2
+ class="fixed bg-white p-2 w-full flex flex-shrink-0 items-center z-50 px-4 lg:px-4 border-b space-x-4 lg:space-x-0 h-16 <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>"
3
3
  v-if="layout !== 'blank'"
4
4
  >
5
- <%= a_button class: 'lg:hidden', icon: 'menu', data: { action: 'click->mobile#toggleSidebar' } %>
6
- <div class="flex-1 flex items-center justify-between lg:justify-start space-x-8">
7
- <div class="m-0">
8
- <%= render partial: "avo/partials/header" %>
9
- </div>
5
+ <div class="flex items-center space-x-2 lg:space-x-0 w-32 sm:w-64 flex-shrink-0">
6
+ <%= a_button class: 'lg:hidden', icon: 'menu', size: :xs, compact: true, style: :text, data: { action: 'click->mobile#toggleSidebar' } %>
7
+ <%= render partial: "avo/partials/logo" %>
8
+ </div>
9
+ <div class="flex-1 flex items-center justify-between lg:justify-start space-x-2 sm:space-x-8 lg:pl-4">
10
10
  <div class="flex">
11
11
  <%= render partial: "avo/partials/global_search" if ::Avo::App.license.has_with_trial(:global_search) && ::Avo.configuration.feature_enabled?(:global_search) %>
12
12
  </div>
13
+ <div class="m-0">
14
+ <%= render partial: "avo/partials/header" %>
15
+ </div>
13
16
  </div>
14
17
  </div>
@@ -29,8 +29,9 @@
29
29
  sort_by = field.id
30
30
  sort_direction = 'desc'
31
31
  end
32
- classes = "text-gray-500 tracking-tight leading-tight text-sm font-semibold" %>
33
- <th class="text-left uppercase px-3 py-4 whitespace-nowrap rounded-l">
32
+ classes = "text-gray-500 tracking-tight leading-tight text-xs font-semibold"
33
+ %>
34
+ <th class="text-left uppercase px-3 py-2 whitespace-nowrap rounded-l">
34
35
  <% if field.sortable %>
35
36
  <%= link_to params.permit!.merge(sort_by: sort_by, sort_direction: sort_direction), class: "flex items-center #{classes} #{'cursor-pointer' if field.sortable}", 'data-turbo-frame': params[:turbo_frame] do %>
36
37
  <%= field.name %>
@@ -1,7 +1,7 @@
1
1
  <%
2
2
  entities = [:button, :link]
3
- sizes = [:lg, :md, :sm, :xs]
4
- styles = [:primary, :outline]
3
+ sizes = [:xl, :lg, :md, :sm, :xs].reverse
4
+ styles = [:primary, :outline, :text]
5
5
  colors = [:primary, :gray, :red, :orange, :green]
6
6
  states = [:regular, :hover, :disabled, :active]
7
7
  %>