avo 2.11.3.pre.3 → 2.13.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 +2 -4
- data/README.md +2 -1
- data/app/components/avo/actions_component.html.erb +3 -3
- data/app/components/avo/actions_component.rb +12 -3
- data/app/components/avo/button_component.rb +1 -3
- data/app/components/avo/card_component.html.erb +8 -8
- data/app/components/avo/fields/common/gravatar_viewer_component.html.erb +1 -1
- data/app/components/avo/fields/date_field/edit_component.html.erb +0 -3
- data/app/components/avo/fields/date_time_field/edit_component.html.erb +0 -2
- data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/tags_field/show_component.rb +0 -2
- data/app/components/avo/index/ordering/buttons_component.html.erb +1 -1
- data/app/components/avo/index/resource_controls_component.rb +1 -1
- data/app/components/avo/item_switcher_component.html.erb +1 -1
- data/app/components/avo/panel_component.html.erb +1 -1
- data/app/components/avo/panel_component.rb +3 -4
- data/app/components/avo/resource_component.rb +6 -4
- data/app/components/avo/tab_group_component.html.erb +1 -1
- data/app/components/avo/tab_switcher_component.rb +2 -2
- data/app/components/avo/views/resource_edit_component.html.erb +1 -1
- data/app/components/avo/views/resource_edit_component.rb +1 -21
- data/app/components/avo/views/resource_index_component.html.erb +49 -97
- data/app/components/avo/views/resource_index_component.rb +19 -0
- data/app/components/avo/views/resource_show_component.html.erb +139 -53
- data/app/components/avo/views/resource_show_component.rb +1 -0
- data/app/controllers/avo/application_controller.rb +7 -3
- data/app/controllers/avo/associations_controller.rb +2 -2
- data/app/controllers/avo/base_controller.rb +11 -18
- data/app/controllers/avo/cards_controller.rb +5 -18
- data/app/controllers/avo/dashboards_controller.rb +2 -4
- data/app/controllers/avo/search_controller.rb +57 -20
- data/app/javascript/js/controllers/{card_controller.js → dashboard_card_controller.js} +0 -0
- data/app/javascript/js/controllers/menu_controller.js +2 -2
- data/app/javascript/js/controllers/search_controller.js +42 -15
- data/app/javascript/js/controllers.js +2 -2
- data/app/views/avo/associations/new.html.erb +1 -0
- data/app/views/avo/cards/_metric_card.html.erb +2 -2
- data/app/views/avo/dashboards/show.html.erb +20 -3
- data/app/views/avo/debug/index.html.erb +1 -1
- data/app/views/avo/debug/report.html.erb +1 -0
- data/app/views/avo/home/index.html.erb +1 -1
- data/app/views/avo/partials/_resource_search.html.erb +6 -0
- data/app/views/avo/private/design.html.erb +2 -2
- data/config/routes.rb +0 -3
- data/lib/avo/base_card.rb +21 -40
- data/lib/avo/base_resource.rb +5 -2
- data/lib/avo/concerns/has_editable_controls.rb +34 -0
- data/lib/avo/concerns/has_fields.rb +11 -10
- data/lib/avo/dashboards/base_dashboard.rb +50 -15
- data/lib/avo/dashboards/base_divider.rb +1 -5
- data/lib/avo/dashboards/chartkick_card.rb +4 -5
- data/lib/avo/fields/base_field.rb +13 -7
- data/lib/avo/fields/date_field.rb +1 -3
- data/lib/avo/fields/field_extensions/has_include_blank.rb +1 -1
- data/lib/avo/fields/field_extensions/visible_in_different_views.rb +1 -12
- data/lib/avo/fields/has_base_field.rb +18 -1
- data/lib/avo/fields/key_value_field.rb +6 -6
- data/lib/avo/hosts/base_host.rb +2 -1
- data/lib/avo/hosts/dashboard_card.rb +1 -1
- data/lib/avo/hosts/search_scope_host.rb +7 -0
- data/lib/avo/licensing/h_q.rb +12 -4
- data/lib/avo/licensing/pro_license.rb +1 -0
- data/lib/avo/menu/builder.rb +2 -0
- data/lib/avo/resources/controls/action.rb +32 -0
- data/lib/avo/resources/controls/actions_list.rb +19 -0
- data/lib/avo/resources/controls/back_button.rb +13 -0
- data/lib/avo/resources/controls/base_control.rb +59 -0
- data/lib/avo/resources/controls/delete_button.rb +13 -0
- data/lib/avo/resources/controls/detach_button.rb +13 -0
- data/lib/avo/resources/controls/edit_button.rb +13 -0
- data/lib/avo/resources/controls/execution_context.rb +58 -0
- data/lib/avo/resources/controls/items_holder.rb +19 -0
- data/lib/avo/resources/controls/link_to.rb +27 -0
- data/lib/avo/tab.rb +1 -3
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/action.tt +1 -1
- data/lib/generators/avo/templates/cards/partial_card_partial.tt +1 -1
- data/lib/generators/avo/templates/initializer/avo.tt +1 -0
- data/lib/generators/avo/templates/resource/resource.tt +1 -1
- data/lib/generators/avo/templates/resource_tools/partial.tt +1 -1
- data/lib/generators/avo/templates/standalone_action.tt +1 -1
- data/public/avo-assets/avo.css +592 -124
- data/public/avo-assets/avo.js +48 -48
- data/public/avo-assets/avo.js.map +3 -3
- metadata +17 -10
- data/app/components/avo/cards_list_component.html.erb +0 -16
- data/app/components/avo/cards_list_component.rb +0 -13
- data/lib/avo/concerns/has_cards.rb +0 -88
- data/lib/avo/concerns/has_model.rb +0 -11
- data/lib/avo/concerns/styles_cards.rb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16af345f63f08dc026b6c1a29ce0938d7a0aad278a53884e542b8f31a17c34fa
|
4
|
+
data.tar.gz: ed4abef748fbe4e8e22edecd85ea70f361875e30f28ffdbddfb648fbf9cde226
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98d1460f53524d1747ac7db6a85c1c3e0e033d6ad42f624d699865500fa34079f30ea08d0a698ee756771269fb1b6d6e51d30a7663b008366a860dad6b1b6ed2
|
7
|
+
data.tar.gz: df8cd199ec20e5cf1f17a407ebcd6aa0d020254eedaf8b514a517d4c800d2a923bc4bd131aec1d1967b713be49f12d56167fc69efa4b638a17570967a568f312
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (2.
|
4
|
+
avo (2.13.0)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
@@ -136,7 +136,7 @@ GEM
|
|
136
136
|
rack-test (>= 0.6.3)
|
137
137
|
regexp_parser (>= 1.5, < 3.0)
|
138
138
|
xpath (~> 3.2)
|
139
|
-
chartkick (4.2.
|
139
|
+
chartkick (4.2.1)
|
140
140
|
childprocess (4.1.0)
|
141
141
|
concurrent-ruby (1.1.10)
|
142
142
|
countries (4.2.1)
|
@@ -252,8 +252,6 @@ GEM
|
|
252
252
|
nokogiri (1.13.7)
|
253
253
|
mini_portile2 (~> 2.8.0)
|
254
254
|
racc (~> 1.4)
|
255
|
-
nokogiri (1.13.7-x86_64-linux)
|
256
|
-
racc (~> 1.4)
|
257
255
|
orm_adapter (0.5.0)
|
258
256
|
pagy (5.10.1)
|
259
257
|
activesupport
|
data/README.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
![reviewdog](https://github.com/avo-hq/avo/workflows/reviewdog/badge.svg)
|
4
4
|
[![codecov](https://codecov.io/gh/avo-hq/avo/branch/master/graph/badge.svg?token=Q2LMFE4989)](https://codecov.io/gh/avo-hq/avo)
|
5
5
|
[![Maintainability](https://api.codeclimate.com/v1/badges/676a0afa2cc79f03aa29/maintainability)](https://codeclimate.com/github/avo-hq/avo/maintainability)
|
6
|
+
[![Open Source Helpers](https://www.codetriage.com/avo-hq/avo/badges/users.svg)](https://www.codetriage.com/avo-hq/avo)
|
6
7
|
|
7
8
|
![](./public/avo-assets/logo-on-white.png)
|
8
9
|
|
@@ -73,7 +74,7 @@ Please read the [UPGRADE_GUIDE.MD](https://docs.avohq.io/2.0/upgrade.html)
|
|
73
74
|
|
74
75
|
Please read the [RELEASE.MD](./RELEASE.MD)
|
75
76
|
|
76
|
-
# ✨ Contributors
|
77
|
+
# ✨ [Contributors](https://avohq.io/contributors)
|
77
78
|
|
78
79
|
<a href="https://github.com/avo-hq/avo/graphs/contributors">
|
79
80
|
<img src="https://contrib.rocks/image?repo=avo-hq/avo" />
|
@@ -3,9 +3,9 @@
|
|
3
3
|
data-actions-picker-enabled-class="text-black hover:bg-blue-500 hover:text-white"
|
4
4
|
data-actions-picker-disabled-class="cursor-wait text-gray-500"
|
5
5
|
>
|
6
|
-
<%= a_button style:
|
6
|
+
<%= a_button style: @style,
|
7
7
|
type: :button,
|
8
|
-
color:
|
8
|
+
color: @color,
|
9
9
|
class: "focus:outline-none",
|
10
10
|
icon: 'arrow-circle-right',
|
11
11
|
icon_class: 'transform rotate-90',
|
@@ -18,7 +18,7 @@
|
|
18
18
|
data-toggle-panel-target="panel"
|
19
19
|
>
|
20
20
|
<div class="w-full space divide-y">
|
21
|
-
<%
|
21
|
+
<% actions.each_with_index do |action, index| %>
|
22
22
|
<%= link_to action_path(action.param_id),
|
23
23
|
data: {
|
24
24
|
'turbo-frame': 'actions_show',
|
@@ -3,14 +3,23 @@
|
|
3
3
|
class Avo::ActionsComponent < ViewComponent::Base
|
4
4
|
include Avo::ApplicationHelper
|
5
5
|
|
6
|
-
def initialize(actions: [], resource: nil, view: nil)
|
7
|
-
@actions = actions
|
6
|
+
def initialize(actions: [], resource: nil, view: nil, exclude: [], style: :outline, color: :blue)
|
7
|
+
@actions = actions || []
|
8
8
|
@resource = resource
|
9
9
|
@view = view
|
10
|
+
@exclude = exclude
|
11
|
+
@color = color
|
12
|
+
@style = style
|
10
13
|
end
|
11
14
|
|
12
15
|
def render?
|
13
|
-
|
16
|
+
actions.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def actions
|
20
|
+
@actions.select do |action|
|
21
|
+
!action.class.in?(@exclude)
|
22
|
+
end
|
14
23
|
end
|
15
24
|
|
16
25
|
# When running an action for one record we should do it on a special path.
|
@@ -43,9 +43,7 @@ class Avo::ButtonComponent < ViewComponent::Base
|
|
43
43
|
classes = "button-component inline-flex flex-grow-0 items-center font-semibold leading-6 fill-current whitespace-nowrap transition duration-100 transform transition duration-100 cursor-pointer disabled:cursor-not-allowed disabled:opacity-70 border justify-center active:outline active:outline-1 #{@class}"
|
44
44
|
|
45
45
|
classes += " rounded" if @rounded.present?
|
46
|
-
|
47
46
|
classes += style_classes
|
48
|
-
|
49
47
|
classes += horizontal_padding_classes
|
50
48
|
classes += vertical_padding_classes
|
51
49
|
classes += text_size_classes
|
@@ -151,7 +149,7 @@ class Avo::ButtonComponent < ViewComponent::Base
|
|
151
149
|
def style_classes
|
152
150
|
case @style
|
153
151
|
when :primary
|
154
|
-
" bg-
|
152
|
+
" bg-#{@color}-500 text-white border-#{@color}-500 hover:bg-#{@color}-600 hover:border-#{@color}-600 active:border-#{@color}-700 active:outline-#{@color}-700 active:bg-#{@color}-600"
|
155
153
|
when :outline
|
156
154
|
" bg-white text-#{@color}-500 border-#{@color}-500 hover:bg-#{@color}-100 active:bg-#{@color}-100 active:border-#{@color}-500 active:outline-#{@color}-500"
|
157
155
|
when :text
|
@@ -1,19 +1,19 @@
|
|
1
1
|
<div class="relative flex-1 flex flex-col justify-between h-full"
|
2
|
-
data-controller="card"
|
3
|
-
data-card-target="card"
|
2
|
+
data-controller="dashboard-card"
|
3
|
+
data-dashboard-card-target="card"
|
4
4
|
data-refresh-every="<%= @card.refresh_every %>"
|
5
5
|
data-card-id="<%= @card.id %>"
|
6
6
|
data-card-index="<%= @card.index %>">
|
7
7
|
<% if @card.class.display_header %>
|
8
8
|
<div class="px-4 pt-4">
|
9
|
-
<div class="flex justify-between items-center">
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
<div
|
9
|
+
<div class="flex justify-between items-center min-h-6">
|
10
|
+
<div class="text-base font-bold text-gray-700 leading-none">
|
11
|
+
<%= @card.label %>
|
12
|
+
</div>
|
13
|
+
<div data-controller="select">
|
14
14
|
<% if @card.type.in?([:metric, :chartkick, :partial]) && @card.ranges.present? %>
|
15
15
|
<%= select_tag "#{@card.id}_#{@card.index}_range", options_for_select(@card.ranges, @card.range),
|
16
|
-
class: 'appearance-none inline-flex bg-blue-gray-100 disabled:bg-blue-gray-300 disabled:cursor-not-allowed focus:bg-white text-
|
16
|
+
class: 'appearance-none inline-flex bg-blue-gray-100 disabled:bg-blue-gray-300 disabled:cursor-not-allowed focus:bg-white text-sm text-blue-gray-700 disabled:text-blue-gray-700 leading-none rounded-md py-px px-2 leading-tight border outline-none outline w-24',
|
17
17
|
data: {
|
18
18
|
target: 'select',
|
19
19
|
action: 'change->select#onChange'
|
@@ -9,4 +9,4 @@
|
|
9
9
|
url = URI::HTTPS.build(host: "www.gravatar.com", path: "/avatar/#{@md5}", query: query)
|
10
10
|
classes = @rounded ? 'rounded-full' : ''
|
11
11
|
%>
|
12
|
-
<%= link_to_if @link_to_resource.present?, image_tag(url.to_s, class: classes), @link, title: @title %>
|
12
|
+
<%= link_to_if @link_to_resource.present?, image_tag(url.to_s, class: classes, width: options[:size], height: options[:size]), @link, title: @title %>
|
@@ -7,7 +7,6 @@
|
|
7
7
|
date_field_picker_format_value: @field.picker_format,
|
8
8
|
date_field_first_day_of_week_value: @field.first_day_of_week,
|
9
9
|
date_field_disable_mobile_value: @field.disable_mobile,
|
10
|
-
date_field_relative_value: @field.relative,
|
11
10
|
} do %>
|
12
11
|
<%= datetime_field "fake_#{@field.id}", "fake",
|
13
12
|
value: @field.edit_formatted_value,
|
@@ -15,7 +14,6 @@
|
|
15
14
|
data: {
|
16
15
|
'date-field-target': 'fakeInput',
|
17
16
|
placeholder: @field.placeholder,
|
18
|
-
relative: @field.relative,
|
19
17
|
**@field.get_html(:data, view: view, element: :input)
|
20
18
|
},
|
21
19
|
disabled: @field.readonly,
|
@@ -28,7 +26,6 @@
|
|
28
26
|
data: {
|
29
27
|
'date-field-target': 'input',
|
30
28
|
placeholder: @field.placeholder,
|
31
|
-
relative: @field.relative,
|
32
29
|
**@field.get_html(:data, view: view, element: :input)
|
33
30
|
},
|
34
31
|
disabled: @field.readonly,
|
@@ -15,7 +15,6 @@
|
|
15
15
|
data: {
|
16
16
|
'date-field-target': 'fakeInput',
|
17
17
|
placeholder: @field.placeholder,
|
18
|
-
relative: @field.relative,
|
19
18
|
**@field.get_html(:data, view: view, element: :input)
|
20
19
|
},
|
21
20
|
disabled: @field.readonly,
|
@@ -28,7 +27,6 @@
|
|
28
27
|
data: {
|
29
28
|
'date-field-target': 'input',
|
30
29
|
placeholder: @field.placeholder,
|
31
|
-
relative: @field.relative,
|
32
30
|
**@field.get_html(:data, view: view, element: :input)
|
33
31
|
},
|
34
32
|
disabled: @field.readonly,
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<%= render(Avo::LoadingComponent.new(title: @field.name)) %>
|
4
4
|
</turbo-frame>
|
5
5
|
<% else %>
|
6
|
-
<%= render Avo::PanelComponent.new(
|
6
|
+
<%= render Avo::PanelComponent.new(name: @field.name) do |c| %>
|
7
7
|
<% c.tools do %>
|
8
8
|
<% if !@field.readonly && can_attach? %>
|
9
9
|
<%= a_link attach_path, icon: 'heroicons/outline/link', color: :primary, 'data-turbo-frame': 'attach_modal' do %>
|
@@ -9,7 +9,7 @@
|
|
9
9
|
<% else %>
|
10
10
|
<div class="popover inline-block"
|
11
11
|
data-controller="popover"
|
12
|
-
data-popover-translate-x="-100%"
|
12
|
+
data-popover-translate-x="<%= Avo.configuration.resource_controls_placement == :left ? '20%' : '-100%' %>"
|
13
13
|
data-popover-translate-y="-32px"
|
14
14
|
data-action="mouseover->popover#mouseOver mouseout->popover#mouseOut"
|
15
15
|
>
|
@@ -58,7 +58,7 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
|
|
58
58
|
|
59
59
|
def singular_resource_name
|
60
60
|
if @reflection.present?
|
61
|
-
reflection_resource.name
|
61
|
+
field&.name&.singularize || reflection_resource.name
|
62
62
|
else
|
63
63
|
@resource.singular_name.present? ? @resource.singular_name : @resource.model_class.model_name.name.downcase
|
64
64
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<%= render item.partial, tool: item, form: @form %>
|
4
4
|
<% end %>
|
5
5
|
<% elsif item.is_panel? %>
|
6
|
-
<%= render Avo::PanelComponent.new(
|
6
|
+
<%= render Avo::PanelComponent.new(name: item.name, description: item.description, index: index) do |c| %>
|
7
7
|
<% c.body do %>
|
8
8
|
<div class="divide-y">
|
9
9
|
<% item.items.each_with_index do |field, index| %>
|
@@ -17,7 +17,7 @@
|
|
17
17
|
<% end %>
|
18
18
|
</div>
|
19
19
|
<% if tools.present? %>
|
20
|
-
<div class="flex-1 w-full flex flex-col sm:flex-row xl:justify-end sm:items-end
|
20
|
+
<div class="flex-1 w-full flex flex-wrap flex-col sm:flex-row xl:justify-end sm:items-end gap-2 mt-4 xl:mt-0" data-target="panel-tools">
|
21
21
|
<%= tools %>
|
22
22
|
</div>
|
23
23
|
<% end %>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::PanelComponent < ViewComponent::Base
|
4
|
-
attr_reader :title
|
4
|
+
attr_reader :title # deprecating title in favor of name
|
5
5
|
attr_reader :name
|
6
6
|
attr_reader :classes
|
7
7
|
|
@@ -11,9 +11,9 @@ class Avo::PanelComponent < ViewComponent::Base
|
|
11
11
|
renders_one :footer_tools
|
12
12
|
renders_one :footer
|
13
13
|
|
14
|
-
def initialize(
|
14
|
+
def initialize(name: nil, description: nil, body_classes: nil, data: {}, display_breadcrumbs: false, index: nil, classes: nil, **args)
|
15
15
|
# deprecating title in favor of name
|
16
|
-
@title = title
|
16
|
+
@title = args[:title]
|
17
17
|
@name = name || title
|
18
18
|
@description = description
|
19
19
|
@classes = classes
|
@@ -21,7 +21,6 @@ class Avo::PanelComponent < ViewComponent::Base
|
|
21
21
|
@data = data
|
22
22
|
@display_breadcrumbs = display_breadcrumbs
|
23
23
|
@index = index
|
24
|
-
@view = view
|
25
24
|
end
|
26
25
|
|
27
26
|
private
|
@@ -22,6 +22,12 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
22
22
|
authorize_association_for("detach")
|
23
23
|
end
|
24
24
|
|
25
|
+
def detach_path
|
26
|
+
return "/" if @reflection.blank?
|
27
|
+
|
28
|
+
helpers.resource_detach_path(params[:resource_name], params[:id], @reflection.name.to_s, @resource.model.id)
|
29
|
+
end
|
30
|
+
|
25
31
|
def can_see_the_edit_button?
|
26
32
|
@resource.authorization.authorize_action(:edit, raise_exception: false)
|
27
33
|
end
|
@@ -30,10 +36,6 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
30
36
|
@resource.authorization.authorize_action(:destroy, raise_exception: false)
|
31
37
|
end
|
32
38
|
|
33
|
-
def detach_path
|
34
|
-
helpers.resource_detach_path(params[:resource_name], params[:id], @reflection.name.to_s, @resource.model.id)
|
35
|
-
end
|
36
|
-
|
37
39
|
def destroy_path
|
38
40
|
helpers.resource_path(model: @resource.model, resource: @resource)
|
39
41
|
end
|
@@ -25,7 +25,7 @@
|
|
25
25
|
# On edit screens we want to load each tab because we wnst the DOM to have the fields present on form submission.
|
26
26
|
# If you have a field which is in the second tab and it's required, the form submission will fail because the required field is not in view, and we don't want that.
|
27
27
|
# We also want to load the current tab
|
28
|
-
should_lazy_load = if @view.to_s.in?(['edit', 'new'])
|
28
|
+
should_lazy_load = if @view.to_s.in?(['edit', 'new', 'update', 'create'])
|
29
29
|
false
|
30
30
|
else
|
31
31
|
!is_current_tab
|
@@ -15,7 +15,7 @@
|
|
15
15
|
},
|
16
16
|
multipart: true do |form| %>
|
17
17
|
<%= render Avo::ReferrerParamsComponent.new back_path: back_path %>
|
18
|
-
<%= render Avo::PanelComponent.new(
|
18
|
+
<%= render Avo::PanelComponent.new(name: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
|
19
19
|
<% c.tools do %>
|
20
20
|
<%= a_link back_path,
|
21
21
|
style: :text,
|
@@ -35,26 +35,6 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
|
|
35
35
|
@resource.authorization.authorize_action @view, raise_exception: false
|
36
36
|
end
|
37
37
|
|
38
|
-
def is_edit?
|
39
|
-
view == :edit
|
40
|
-
end
|
41
|
-
|
42
|
-
def form_url
|
43
|
-
if is_edit?
|
44
|
-
helpers.resource_path(
|
45
|
-
model: @resource.model,
|
46
|
-
resource: @resource
|
47
|
-
)
|
48
|
-
else
|
49
|
-
helpers.resources_path(
|
50
|
-
resource: @resource,
|
51
|
-
via_relation_class: params[:via_relation_class],
|
52
|
-
via_relation: params[:via_relation],
|
53
|
-
via_resource_id: params[:via_resource_id]
|
54
|
-
)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
38
|
private
|
59
39
|
|
60
40
|
def via_index?
|
@@ -62,7 +42,7 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
|
|
62
42
|
end
|
63
43
|
|
64
44
|
def is_edit?
|
65
|
-
view
|
45
|
+
view.in?([:edit, :update])
|
66
46
|
end
|
67
47
|
|
68
48
|
def form_method
|
@@ -1,126 +1,78 @@
|
|
1
1
|
<%= content_tag :div,
|
2
|
-
class: 'space-y-6',
|
3
2
|
data: {
|
4
3
|
**@resource.stimulus_data_attributes
|
5
4
|
} do %>
|
6
|
-
<%= render Avo::
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
<% if can_attach? %>
|
11
|
-
<%= a_link attach_path,
|
5
|
+
<%= render Avo::PanelComponent.new(name: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
|
6
|
+
<% c.tools do %>
|
7
|
+
<% if can_attach? %>
|
8
|
+
<%= a_link attach_path,
|
12
9
|
icon: 'heroicons/outline/link',
|
13
10
|
color: :primary,
|
14
11
|
style: :text,
|
15
12
|
'data-turbo-frame': 'attach_modal',
|
16
13
|
'data-target': 'attach' do %>
|
17
|
-
|
18
|
-
<% end %>
|
14
|
+
<%= t('avo.attach_item', item: singular_resource_name).capitalize %>
|
19
15
|
<% end %>
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
16
|
+
<% end %>
|
17
|
+
<% if can_see_the_actions_button? %>
|
18
|
+
<%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
|
19
|
+
<% end %>
|
20
|
+
<% if can_see_the_create_button? %>
|
21
|
+
<%= a_link create_path,
|
25
22
|
icon: 'heroicons/outline/plus',
|
26
23
|
'data-target': 'create',
|
27
24
|
style: :primary,
|
28
25
|
color: :primary do %>
|
29
|
-
|
30
|
-
<% end %>
|
26
|
+
<%= t('avo.create_new_item', item: singular_resource_name.downcase ) %>
|
31
27
|
<% end %>
|
32
28
|
<% end %>
|
33
|
-
|
34
|
-
|
29
|
+
<% end %>
|
30
|
+
<% c.body do %>
|
31
|
+
<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 %>"
|
35
32
|
data-selected-resources-name="<%= @resource.model_key %>"
|
36
33
|
data-selected-resources="[]"
|
37
34
|
>
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
<% end %>
|
46
|
-
<% if @filters.present? || available_view_types.count > 1 %>
|
47
|
-
<div class="justify-self-end flex justify-start xs:justify-end items-center px-4 space-x-3">
|
48
|
-
<%= render Avo::FiltersComponent.new filters: @filters, resource: @resource, applied_filters: @applied_filters %>
|
49
|
-
<%= render partial: 'avo/partials/view_toggle_button', locals: { available_view_types: available_view_types, view_type: view_type, turbo_frame: @turbo_frame } if available_view_types.count > 1 %>
|
50
|
-
</div>
|
51
|
-
<% end %>
|
52
|
-
</div>
|
53
|
-
<% if view_type.to_sym == :table %>
|
54
|
-
<% if @resources.present? %>
|
55
|
-
<div class="w-full overflow-auto flex flex-col mt-0 mac-styled-scrollbar">
|
56
|
-
<div class="relative flex-1 flex">
|
57
|
-
<%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource)) %>
|
58
|
-
</div>
|
59
|
-
</div>
|
60
|
-
<% else %>
|
61
|
-
<%= helpers.empty_state resource_name: @resource.name.downcase.pluralize, related_name: params[:related_name], view_type: view_type, add_background: true %>
|
62
|
-
<% end %>
|
35
|
+
<% unless hide_search_input %>
|
36
|
+
<div class="flex items-center px-4 w-64">
|
37
|
+
<%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.route_key, via_reflection: via_reflection} %>
|
38
|
+
</div>
|
39
|
+
<% else %>
|
40
|
+
<%# Offset for the space-y-2 property when the search is missing %>
|
41
|
+
<div class="-mb-2"></div>
|
63
42
|
<% end %>
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
43
|
+
<% if @filters.present? || available_view_types.count > 1 %>
|
44
|
+
<div class="justify-self-end flex justify-start xs:justify-end items-center px-4 space-x-3">
|
45
|
+
<%= render Avo::FiltersComponent.new filters: @filters, resource: @resource, applied_filters: @applied_filters %>
|
46
|
+
<%= render partial: 'avo/partials/view_toggle_button', locals: { available_view_types: available_view_types, view_type: view_type, turbo_frame: @turbo_frame } if available_view_types.count > 1 %>
|
47
|
+
</div>
|
48
|
+
<% end %>
|
49
|
+
</div>
|
50
|
+
<% if view_type.to_sym == :table %>
|
51
|
+
<% if @resources.present? %>
|
52
|
+
<div class="w-full overflow-auto flex flex-col mt-0 mac-styled-scrollbar">
|
53
|
+
<div class="relative flex-1 flex">
|
54
|
+
<%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource)) %>
|
70
55
|
</div>
|
71
|
-
|
56
|
+
</div>
|
57
|
+
<% else %>
|
58
|
+
<%= helpers.empty_state resource_name: @resource.name.downcase.pluralize, related_name: params[:related_name], view_type: view_type, add_background: true %>
|
72
59
|
<% end %>
|
73
|
-
|
74
|
-
|
75
|
-
|
60
|
+
<% end %>
|
61
|
+
<% end %>
|
62
|
+
<% c.bare_content do %>
|
63
|
+
<% if view_type.to_sym == :table %>
|
64
|
+
<% if @models.present? %>
|
65
|
+
<div class="mt-4">
|
76
66
|
<%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_model: @parent_model, discreet_pagination: field&.discreet_pagination %>
|
77
67
|
</div>
|
78
|
-
<% if view_type.to_sym == :table %>
|
79
|
-
<% if @resources.present? %>
|
80
|
-
<div class="w-full overflow-auto flex flex-col mt-0">
|
81
|
-
<div class="relative flex-1 flex">
|
82
|
-
<%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model)) %>
|
83
|
-
</div>
|
84
|
-
<% else %>
|
85
|
-
<%# Offset for the space-y-2 property when the serach is missing %>
|
86
|
-
<div class="-mb-2"></div>
|
87
|
-
<% end %>
|
88
|
-
<% if @filters.present? || available_view_types.count > 1 %>
|
89
|
-
<div class="justify-self-end flex justify-start xs:justify-end items-center px-4 space-x-3">
|
90
|
-
<%= render Avo::FiltersComponent.new filters: @filters, resource: @resource, applied_filters: @applied_filters %>
|
91
|
-
<%= render partial: 'avo/partials/view_toggle_button', locals: { available_view_types: available_view_types, view_type: view_type, turbo_frame: @turbo_frame } if available_view_types.count > 1 %>
|
92
|
-
</div>
|
93
|
-
<% end %>
|
94
|
-
</div>
|
95
|
-
<% if view_type.to_sym == :table %>
|
96
|
-
<% if @resources.present? %>
|
97
|
-
<div class="w-full overflow-auto flex flex-col mt-0">
|
98
|
-
<div class="relative flex-1 flex">
|
99
|
-
<%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model)) %>
|
100
|
-
</div>
|
101
|
-
</div>
|
102
|
-
<% else %>
|
103
|
-
<%= helpers.empty_state resource_name: @resource.name.downcase.pluralize, related_name: params[:related_name], view_type: view_type, add_background: true %>
|
104
|
-
<% end %>
|
105
|
-
<% end %>
|
106
|
-
<% end %>
|
107
|
-
<% c.bare_content do %>
|
108
|
-
<% if view_type.to_sym == :table %>
|
109
|
-
<% if @models.present? %>
|
110
|
-
<div class="mt-4">
|
111
|
-
<%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_model: @parent_model %>
|
112
|
-
</div>
|
113
|
-
<% end %>
|
114
|
-
<% end %>
|
115
|
-
<% if view_type.to_sym == :grid %>
|
116
|
-
<%= render Avo::Index::ResourceGridComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model) %>
|
117
|
-
<div class="mt-6">
|
118
|
-
<%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_model: @parent_model %>
|
119
|
-
</div>
|
120
|
-
<% end %>
|
121
|
-
<% end %>
|
122
68
|
<% end %>
|
123
69
|
<% end %>
|
70
|
+
<% if view_type.to_sym == :grid %>
|
71
|
+
<%= render Avo::Index::ResourceGridComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model) %>
|
72
|
+
<div class="mt-6">
|
73
|
+
<%= render Avo::PaginatorComponent.new pagy: @pagy, turbo_frame: @turbo_frame || 'none', index_params: @index_params, resource: @resource, parent_model: @parent_model, discreet_pagination: field&.discreet_pagination %>
|
74
|
+
</div>
|
75
|
+
<% end %>
|
124
76
|
<% end %>
|
125
77
|
<% end %>
|
126
78
|
<% end %>
|
@@ -124,6 +124,8 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
124
124
|
|
125
125
|
def singular_resource_name
|
126
126
|
if @reflection.present?
|
127
|
+
return name.singularize if field.present?
|
128
|
+
|
127
129
|
reflection_resource.name
|
128
130
|
else
|
129
131
|
@resource.singular_name || @resource.model_class.model_name.name.downcase
|
@@ -141,6 +143,12 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
141
143
|
@resource.resource_description
|
142
144
|
end
|
143
145
|
|
146
|
+
def hide_search_input
|
147
|
+
return true unless @resource.search_query.present?
|
148
|
+
|
149
|
+
field&.hide_search_input || false
|
150
|
+
end
|
151
|
+
|
144
152
|
private
|
145
153
|
|
146
154
|
def reflection_model_class
|
@@ -151,4 +159,15 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
151
159
|
field.custom_name? ? field.name : field.plural_name
|
152
160
|
end
|
153
161
|
|
162
|
+
def via_reflection
|
163
|
+
return unless @reflection.present?
|
164
|
+
|
165
|
+
{
|
166
|
+
association: 'has_many',
|
167
|
+
association_id: @reflection.name,
|
168
|
+
class: reflection_model_class,
|
169
|
+
id: @parent_model.id
|
170
|
+
}
|
171
|
+
end
|
172
|
+
|
154
173
|
end
|