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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/app/assets/stylesheets/avo.css +33 -1
- data/app/assets/stylesheets/css/search.css +1 -1
- data/app/assets/svgs/heroicons/solid/user-remove.svg +1 -1
- data/app/components/avo/actions_component.html.erb +3 -2
- data/app/components/avo/alert_component.html.erb +1 -1
- data/app/components/avo/alert_component.rb +24 -5
- data/app/components/avo/button_component.rb +50 -17
- data/app/components/avo/card_component.rb +12 -0
- data/app/components/avo/fields/concerns/item_labels.rb +40 -0
- data/app/components/avo/fields/tags_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/tags_field/index_component.html.erb +1 -5
- data/app/components/avo/fields/tags_field/index_component.rb +2 -0
- data/app/components/avo/fields/tags_field/show_component.rb +3 -7
- data/app/components/avo/fields/tags_field/tag_component.html.erb +1 -1
- data/app/components/avo/filters_component.html.erb +1 -1
- data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
- data/app/components/avo/index/grid_cover_empty_state_component.html.erb +1 -1
- data/app/components/avo/index/table_row_component.html.erb +1 -1
- data/app/components/avo/panel_component.html.erb +3 -3
- data/app/components/avo/panel_component.rb +1 -1
- data/app/components/avo/resource_component.rb +50 -0
- data/app/components/avo/sidebar/group_component.html.erb +4 -2
- data/app/components/avo/sidebar/heading_component.html.erb +1 -1
- data/app/components/avo/sidebar/link_component.html.erb +1 -1
- data/app/components/avo/sidebar/link_component.rb +1 -1
- data/app/components/avo/sidebar_component.html.erb +5 -13
- data/app/components/avo/sidebar_profile_component.html.erb +1 -1
- data/app/components/avo/views/resource_edit_component.html.erb +28 -3
- data/app/components/avo/views/resource_edit_component.rb +4 -6
- data/app/components/avo/views/resource_index_component.html.erb +17 -9
- data/app/components/avo/views/resource_new_component.html.erb +8 -2
- data/app/components/avo/views/resource_show_component.html.erb +16 -6
- data/app/components/avo/views/resource_show_component.rb +0 -45
- data/app/controllers/avo/actions_controller.rb +23 -8
- data/app/controllers/avo/associations_controller.rb +3 -3
- data/app/controllers/avo/base_controller.rb +11 -21
- data/app/controllers/avo/private_controller.rb +1 -0
- data/app/controllers/avo/search_controller.rb +2 -2
- data/app/helpers/avo/application_helper.rb +1 -1
- data/app/javascript/js/controllers/fields/key_value_controller.js +1 -1
- data/app/javascript/js/controllers/fields/tags_field_controller.js +3 -3
- data/app/javascript/js/controllers/filter_controller.js +4 -1
- data/app/javascript/js/controllers.js +0 -2
- data/app/views/avo/actions/show.html.erb +5 -2
- data/app/views/avo/dashboards/_chartkick_card.html.erb +1 -1
- data/app/views/avo/dashboards/_metric_card.html.erb +1 -1
- data/app/views/avo/partials/_logo.html.erb +1 -1
- data/app/views/avo/partials/_navbar.html.erb +9 -6
- data/app/views/avo/partials/_table_header.html.erb +3 -2
- data/app/views/avo/private/_links_and_buttons.html.erb +2 -2
- data/app/views/layouts/avo/application.html.erb +50 -53
- data/lib/avo/base_action.rb +24 -6
- data/lib/avo/engine.rb +1 -1
- data/lib/avo/fields/belongs_to_field.rb +4 -4
- data/lib/avo/fields/has_and_belongs_to_many_field.rb +2 -2
- data/lib/avo/fields/has_base_field.rb +2 -0
- data/lib/avo/fields/has_many_field.rb +2 -2
- data/lib/avo/fields/has_one_field.rb +2 -2
- data/lib/avo/fields/tags_field.rb +5 -5
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
- data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
- data/lib/tasks/avo_tasks.rake +7 -3
- data/public/avo-assets/avo.css +233 -176
- data/public/avo-assets/avo.js +63 -63
- data/public/avo-assets/avo.js.map +3 -3
- metadata +5 -9
- data/app/assets/builds/avo.css +0 -9557
- data/app/assets/builds/avo.js +0 -512
- data/app/assets/builds/avo.js.map +0 -7
- data/app/assets/stylesheets/css/alerts.css +0 -35
- 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,
|
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: :
|
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,
|
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-
|
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-
|
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,
|
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:
|
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-
|
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,
|
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,
|
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,
|
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].
|
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
|
-
|
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
|
70
|
+
redirect_to path
|
69
71
|
elsif response[:type] == :reload
|
70
|
-
redirect_back fallback_location: resources_path(resource: @resource)
|
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.
|
50
|
-
query = Avo::Hosts::AssociationScopeHost.new(block: @field.
|
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 {
|
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
|
-
|
50
|
+
@query = if field&.sortable.is_a?(Proc)
|
51
|
+
field.sortable.call(@query, @index_params[:sort_direction])
|
54
52
|
else
|
55
|
-
@query
|
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
|
-
|
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
|
@@ -51,12 +51,12 @@ module Avo
|
|
51
51
|
# Fetch the field
|
52
52
|
field = belongs_to_field
|
53
53
|
|
54
|
-
if field.
|
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.
|
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-
|
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
|
18
|
-
return this.getJsonAttribute(this.inputTarget, 'data-
|
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.
|
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' },
|
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: :
|
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,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.
|
3
|
+
<span class="text-5xl"><%= @card.result_data %></span>
|
4
4
|
<span class="text-3xl"><%= @card.suffix %></span>
|
5
5
|
</div>
|
@@ -1,14 +1,17 @@
|
|
1
1
|
<div
|
2
|
-
class="
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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-
|
33
|
-
|
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
|
%>
|