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.

Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -4
  3. data/README.md +2 -1
  4. data/app/components/avo/actions_component.html.erb +3 -3
  5. data/app/components/avo/actions_component.rb +12 -3
  6. data/app/components/avo/button_component.rb +1 -3
  7. data/app/components/avo/card_component.html.erb +8 -8
  8. data/app/components/avo/fields/common/gravatar_viewer_component.html.erb +1 -1
  9. data/app/components/avo/fields/date_field/edit_component.html.erb +0 -3
  10. data/app/components/avo/fields/date_time_field/edit_component.html.erb +0 -2
  11. data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -1
  12. data/app/components/avo/fields/tags_field/show_component.rb +0 -2
  13. data/app/components/avo/index/ordering/buttons_component.html.erb +1 -1
  14. data/app/components/avo/index/resource_controls_component.rb +1 -1
  15. data/app/components/avo/item_switcher_component.html.erb +1 -1
  16. data/app/components/avo/panel_component.html.erb +1 -1
  17. data/app/components/avo/panel_component.rb +3 -4
  18. data/app/components/avo/resource_component.rb +6 -4
  19. data/app/components/avo/tab_group_component.html.erb +1 -1
  20. data/app/components/avo/tab_switcher_component.rb +2 -2
  21. data/app/components/avo/views/resource_edit_component.html.erb +1 -1
  22. data/app/components/avo/views/resource_edit_component.rb +1 -21
  23. data/app/components/avo/views/resource_index_component.html.erb +49 -97
  24. data/app/components/avo/views/resource_index_component.rb +19 -0
  25. data/app/components/avo/views/resource_show_component.html.erb +139 -53
  26. data/app/components/avo/views/resource_show_component.rb +1 -0
  27. data/app/controllers/avo/application_controller.rb +7 -3
  28. data/app/controllers/avo/associations_controller.rb +2 -2
  29. data/app/controllers/avo/base_controller.rb +11 -18
  30. data/app/controllers/avo/cards_controller.rb +5 -18
  31. data/app/controllers/avo/dashboards_controller.rb +2 -4
  32. data/app/controllers/avo/search_controller.rb +57 -20
  33. data/app/javascript/js/controllers/{card_controller.js → dashboard_card_controller.js} +0 -0
  34. data/app/javascript/js/controllers/menu_controller.js +2 -2
  35. data/app/javascript/js/controllers/search_controller.js +42 -15
  36. data/app/javascript/js/controllers.js +2 -2
  37. data/app/views/avo/associations/new.html.erb +1 -0
  38. data/app/views/avo/cards/_metric_card.html.erb +2 -2
  39. data/app/views/avo/dashboards/show.html.erb +20 -3
  40. data/app/views/avo/debug/index.html.erb +1 -1
  41. data/app/views/avo/debug/report.html.erb +1 -0
  42. data/app/views/avo/home/index.html.erb +1 -1
  43. data/app/views/avo/partials/_resource_search.html.erb +6 -0
  44. data/app/views/avo/private/design.html.erb +2 -2
  45. data/config/routes.rb +0 -3
  46. data/lib/avo/base_card.rb +21 -40
  47. data/lib/avo/base_resource.rb +5 -2
  48. data/lib/avo/concerns/has_editable_controls.rb +34 -0
  49. data/lib/avo/concerns/has_fields.rb +11 -10
  50. data/lib/avo/dashboards/base_dashboard.rb +50 -15
  51. data/lib/avo/dashboards/base_divider.rb +1 -5
  52. data/lib/avo/dashboards/chartkick_card.rb +4 -5
  53. data/lib/avo/fields/base_field.rb +13 -7
  54. data/lib/avo/fields/date_field.rb +1 -3
  55. data/lib/avo/fields/field_extensions/has_include_blank.rb +1 -1
  56. data/lib/avo/fields/field_extensions/visible_in_different_views.rb +1 -12
  57. data/lib/avo/fields/has_base_field.rb +18 -1
  58. data/lib/avo/fields/key_value_field.rb +6 -6
  59. data/lib/avo/hosts/base_host.rb +2 -1
  60. data/lib/avo/hosts/dashboard_card.rb +1 -1
  61. data/lib/avo/hosts/search_scope_host.rb +7 -0
  62. data/lib/avo/licensing/h_q.rb +12 -4
  63. data/lib/avo/licensing/pro_license.rb +1 -0
  64. data/lib/avo/menu/builder.rb +2 -0
  65. data/lib/avo/resources/controls/action.rb +32 -0
  66. data/lib/avo/resources/controls/actions_list.rb +19 -0
  67. data/lib/avo/resources/controls/back_button.rb +13 -0
  68. data/lib/avo/resources/controls/base_control.rb +59 -0
  69. data/lib/avo/resources/controls/delete_button.rb +13 -0
  70. data/lib/avo/resources/controls/detach_button.rb +13 -0
  71. data/lib/avo/resources/controls/edit_button.rb +13 -0
  72. data/lib/avo/resources/controls/execution_context.rb +58 -0
  73. data/lib/avo/resources/controls/items_holder.rb +19 -0
  74. data/lib/avo/resources/controls/link_to.rb +27 -0
  75. data/lib/avo/tab.rb +1 -3
  76. data/lib/avo/version.rb +1 -1
  77. data/lib/generators/avo/templates/action.tt +1 -1
  78. data/lib/generators/avo/templates/cards/partial_card_partial.tt +1 -1
  79. data/lib/generators/avo/templates/initializer/avo.tt +1 -0
  80. data/lib/generators/avo/templates/resource/resource.tt +1 -1
  81. data/lib/generators/avo/templates/resource_tools/partial.tt +1 -1
  82. data/lib/generators/avo/templates/standalone_action.tt +1 -1
  83. data/public/avo-assets/avo.css +592 -124
  84. data/public/avo-assets/avo.js +48 -48
  85. data/public/avo-assets/avo.js.map +3 -3
  86. metadata +17 -10
  87. data/app/components/avo/cards_list_component.html.erb +0 -16
  88. data/app/components/avo/cards_list_component.rb +0 -13
  89. data/lib/avo/concerns/has_cards.rb +0 -88
  90. data/lib/avo/concerns/has_model.rb +0 -11
  91. data/lib/avo/concerns/styles_cards.rb +0 -48
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33a3f78d32b04247f263b94f22dcfbc0e825e3ea99a311c1642866b30a46524f
4
- data.tar.gz: 7344cfbc9197ac2537003045a2ab340165ba4964b095ef914e6ca49852881373
3
+ metadata.gz: 16af345f63f08dc026b6c1a29ce0938d7a0aad278a53884e542b8f31a17c34fa
4
+ data.tar.gz: ed4abef748fbe4e8e22edecd85ea70f361875e30f28ffdbddfb648fbf9cde226
5
5
  SHA512:
6
- metadata.gz: 25e7ee4600617e4786e3b0c43e6b1f03fa4e3e14ab861745d5c9915352cdeb2c66e4d1444ebf1e834c6cb82fea7d854f3440b274ca90a946630279370928cc69
7
- data.tar.gz: 4363ffce5ed2b2172d0c992d98dd8c9bcc8c68e82e7e48dfec8040efe877f8b2aab9203e538110f1ac3a2f77fa2f2d90caa573fc24f7eddc6af6f619da791966
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.11.3.pre.3)
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.0)
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: :outline,
6
+ <%= a_button style: @style,
7
7
  type: :button,
8
- color: :primary,
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
- <% @actions.each_with_index do |action, index| %>
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
- @actions.present?
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-primary-500 text-white border-primary-500 hover:bg-primary-600 hover:border-primary-600 active:border-primary-700 active:outline-primary-700 active:bg-primary-600"
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
- <div class="text-sm font-bold text-gray-700 leading-none">
11
- <%= @card.label %>
12
- </div>
13
- <div class="flex" data-controller="select">
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-xs text-blue-gray-700 disabled:text-blue-gray-700 leading-none rounded-md py-px px-2 border outline-none outline w-24',
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(title: @field.name) do |c| %>
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 %>
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # require_relative 'item_labels'
4
-
5
3
  class Avo::Fields::TagsField::ShowComponent < Avo::Fields::ShowComponent
6
4
  include Avo::Fields::Concerns::ItemLabels
7
5
  end
@@ -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(title: item.name, description: item.description, index: index, view: view) do |c| %>
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 space-y-2 sm:space-y-0 sm:space-x-2 mt-4 xl:mt-0">
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(title: nil, name: nil, description: nil, body_classes: nil, data: {}, display_breadcrumbs: false, index: nil, classes: nil, view: nil)
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
@@ -30,11 +30,11 @@ class Avo::TabSwitcherComponent < Avo::BaseComponent
30
30
  end
31
31
 
32
32
  def is_edit?
33
- @view == :edit
33
+ @view.in?([:edit, :update])
34
34
  end
35
35
 
36
36
  def is_new?
37
- @view == :new
37
+ @view.in?([:new, :create])
38
38
  end
39
39
 
40
40
  def is_initial_load?
@@ -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(title: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
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 == :edit
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::CardsListComponent.new parent: @resource %>
7
- <%= content_tag :div, class: "space-y-12" do %>
8
- <%= render Avo::PanelComponent.new(title: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
9
- <% c.tools do %>
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
- <%= t('avo.attach_item', item: singular_resource_name).capitalize %>
18
- <% end %>
14
+ <%= t('avo.attach_item', item: singular_resource_name).capitalize %>
19
15
  <% end %>
20
- <% if can_see_the_actions_button? %>
21
- <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
22
- <% end %>
23
- <% if can_see_the_create_button? %>
24
- <%= a_link create_path,
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
- <%= t('avo.create_new_item', item: singular_resource_name.downcase ) %>
30
- <% end %>
26
+ <%= t('avo.create_new_item', item: singular_resource_name.downcase ) %>
31
27
  <% end %>
32
28
  <% end %>
33
- <% c.body do %>
34
- <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 %>"
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
- <% if @resource.search_query.present? %>
39
- <div class="flex items-center px-4 w-64">
40
- <%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.route_key} %>
41
- </div>
42
- <% else %>
43
- <%# Offset for the space-y-2 property when the search is missing %>
44
- <div class="-mb-2"></div>
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
- <% end %>
65
- <% c.bare_content do %>
66
- <% if view_type.to_sym == :table %>
67
- <% if @models.present? %>
68
- <div class="mt-4">
69
- <%= 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 %>
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
- <% end %>
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
- <% if view_type.to_sym == :grid %>
74
- <%= render Avo::Index::ResourceGridComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model) %>
75
- <div class="mt-6">
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