avo 2.12.0 → 2.13.1

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -2
  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/fields/common/gravatar_viewer_component.html.erb +1 -1
  8. data/app/components/avo/fields/date_field/edit_component.html.erb +0 -3
  9. data/app/components/avo/fields/date_time_field/edit_component.html.erb +0 -2
  10. data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -1
  11. data/app/components/avo/fields/tags_field/show_component.rb +0 -2
  12. data/app/components/avo/item_switcher_component.html.erb +1 -1
  13. data/app/components/avo/panel_component.html.erb +1 -1
  14. data/app/components/avo/panel_component.rb +3 -4
  15. data/app/components/avo/resource_component.rb +6 -4
  16. data/app/components/avo/sidebar_component.html.erb +1 -1
  17. data/app/components/avo/tab_group_component.html.erb +1 -1
  18. data/app/components/avo/tab_switcher_component.rb +2 -2
  19. data/app/components/avo/views/resource_edit_component.html.erb +1 -1
  20. data/app/components/avo/views/resource_edit_component.rb +1 -1
  21. data/app/components/avo/views/resource_index_component.html.erb +3 -3
  22. data/app/components/avo/views/resource_index_component.rb +18 -1
  23. data/app/components/avo/views/resource_show_component.html.erb +139 -48
  24. data/app/components/avo/views/resource_show_component.rb +1 -0
  25. data/app/controllers/avo/base_controller.rb +87 -33
  26. data/app/controllers/avo/search_controller.rb +57 -20
  27. data/app/javascript/js/controllers/menu_controller.js +2 -2
  28. data/app/javascript/js/controllers/search_controller.js +42 -15
  29. data/app/views/avo/associations/new.html.erb +1 -0
  30. data/app/views/avo/dashboards/show.html.erb +1 -1
  31. data/app/views/avo/debug/index.html.erb +1 -1
  32. data/app/views/avo/debug/report.html.erb +1 -0
  33. data/app/views/avo/home/index.html.erb +1 -1
  34. data/app/views/avo/partials/_resource_search.html.erb +6 -0
  35. data/app/views/avo/private/design.html.erb +2 -2
  36. data/app/views/layouts/avo/application.html.erb +1 -1
  37. data/lib/avo/base_resource.rb +5 -1
  38. data/lib/avo/concerns/has_editable_controls.rb +34 -0
  39. data/lib/avo/concerns/has_fields.rb +11 -10
  40. data/lib/avo/fields/base_field.rb +1 -1
  41. data/lib/avo/fields/date_field.rb +1 -3
  42. data/lib/avo/fields/field_extensions/has_include_blank.rb +1 -1
  43. data/lib/avo/fields/has_base_field.rb +2 -0
  44. data/lib/avo/fields/key_value_field.rb +6 -6
  45. data/lib/avo/hosts/base_host.rb +2 -1
  46. data/lib/avo/hosts/search_scope_host.rb +7 -0
  47. data/lib/avo/licensing/h_q.rb +12 -4
  48. data/lib/avo/licensing/pro_license.rb +1 -0
  49. data/lib/avo/menu/builder.rb +2 -0
  50. data/lib/avo/resources/controls/action.rb +32 -0
  51. data/lib/avo/resources/controls/actions_list.rb +19 -0
  52. data/lib/avo/resources/controls/back_button.rb +13 -0
  53. data/lib/avo/resources/controls/base_control.rb +59 -0
  54. data/lib/avo/resources/controls/delete_button.rb +13 -0
  55. data/lib/avo/resources/controls/detach_button.rb +13 -0
  56. data/lib/avo/resources/controls/edit_button.rb +13 -0
  57. data/lib/avo/resources/controls/execution_context.rb +58 -0
  58. data/lib/avo/resources/controls/items_holder.rb +19 -0
  59. data/lib/avo/resources/controls/link_to.rb +27 -0
  60. data/lib/avo/version.rb +1 -1
  61. data/lib/generators/avo/templates/action.tt +1 -1
  62. data/lib/generators/avo/templates/initializer/avo.tt +1 -0
  63. data/lib/generators/avo/templates/resource/resource.tt +1 -1
  64. data/lib/generators/avo/templates/resource_tools/partial.tt +1 -1
  65. data/lib/generators/avo/templates/standalone_action.tt +1 -1
  66. data/public/avo-assets/avo.css +564 -44
  67. data/public/avo-assets/avo.js +47 -47
  68. data/public/avo-assets/avo.js.map +2 -2
  69. metadata +14 -3
  70. data/lib/avo/concerns/has_model.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb6907b0e852005ad23b73029892ac673ef73f955afe6b317d61c0c9303d3ef3
4
- data.tar.gz: 980fbca1412954ea0e5d1f75ae12e653cd10bfb58307a2fec1a8eafc08c51852
3
+ metadata.gz: 6b921afbe3cb5f55ee67ac20bb21d65dffa91b2b3608dddf1c21b6f9fa5a686e
4
+ data.tar.gz: 5a7d24f4c324b1109717321b3200c41f6b61470fabc915fe41c662fb3858a108
5
5
  SHA512:
6
- metadata.gz: c43462a617f2bb6131b899665687ab371823a2c983338f32d095e0b33dfd543a4e3488e94b03f8e6dec1b7ed6162c0fa86d1cbacfde7b1cf07ef6ed5120192e6
7
- data.tar.gz: e06be5c7fd0c244f683d4bf9960892dac729dc155bbc90f0903758ba3beca5a0394feea932db9c8d67c3ef2836fcf03a1e0056efcb90f8fded28998969cb6e56
6
+ metadata.gz: 0e740c3c1eb71a50fe32bf7856b993e8921c6891e16a09341d636fbcaa32faf8564fd417efc8c914573d959364d573851faaf1b943a5314f7aab78f8c752758f
7
+ data.tar.gz: 7d66c540afb965ac2a07e0a2d88fe811cd6c035cee7a0ce88e8cc926c53f2dd186cabf69fb69946becec707711edb49033cf2c4d6952cdfc13894302554fc1ac
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (2.12.0)
4
+ avo (2.13.1)
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)
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
@@ -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
@@ -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
@@ -1,5 +1,5 @@
1
1
  <div
2
- class="avo-sidebar fixed z-[60] t-0 application-sidebar w-64 flex-1 border-r lg:border-none bg-none h-[calc(100vh-4rem)] bg-gray-25 lg:bg-transparent <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %> <%= @sidebar_open ? 'flex' : 'hidden' %>"
2
+ class="avo-sidebar fixed z-[60] t-0 application-sidebar w-64 flex-1 border-r lg:border-none bg-none h-[calc(100vh-4rem)] bg-application lg:bg-transparent <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %> <%= @sidebar_open ? 'flex' : 'hidden' %>"
3
3
  data-sidebar-target="<%= stimulus_target %>"
4
4
  data-transition-enter="transition ease-out duration-100"
5
5
  data-transition-enter-start="transform opacity-0 -translate-x-full"
@@ -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,
@@ -42,7 +42,7 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
42
42
  end
43
43
 
44
44
  def is_edit?
45
- view == :edit
45
+ view.in?([:edit, :update])
46
46
  end
47
47
 
48
48
  def form_method
@@ -2,7 +2,7 @@
2
2
  data: {
3
3
  **@resource.stimulus_data_attributes
4
4
  } do %>
5
- <%= render Avo::PanelComponent.new(title: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
5
+ <%= render Avo::PanelComponent.new(name: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
6
6
  <% c.tools do %>
7
7
  <% if can_attach? %>
8
8
  <%= a_link attach_path,
@@ -32,9 +32,9 @@
32
32
  data-selected-resources-name="<%= @resource.model_key %>"
33
33
  data-selected-resources="[]"
34
34
  >
35
- <% if @resource.search_query.present? %>
35
+ <% unless hide_search_input %>
36
36
  <div class="flex items-center px-4 w-64">
37
- <%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.route_key} %>
37
+ <%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.route_key, via_reflection: via_reflection} %>
38
38
  </div>
39
39
  <% else %>
40
40
  <%# Offset for the space-y-2 property when the search is missing %>
@@ -125,7 +125,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
125
125
  def singular_resource_name
126
126
  if @reflection.present?
127
127
  return name.singularize if field.present?
128
-
128
+
129
129
  reflection_resource.name
130
130
  else
131
131
  @resource.singular_name || @resource.model_class.model_name.name.downcase
@@ -143,6 +143,12 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
143
143
  @resource.resource_description
144
144
  end
145
145
 
146
+ def hide_search_input
147
+ return true unless @resource.search_query.present?
148
+
149
+ field&.hide_search_input || false
150
+ end
151
+
146
152
  private
147
153
 
148
154
  def reflection_model_class
@@ -153,4 +159,15 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
153
159
  field.custom_name? ? field.name : field.plural_name
154
160
  end
155
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
+
156
173
  end
@@ -5,60 +5,151 @@
5
5
  selected_resources: [@resource.model.id],
6
6
  **@resource.stimulus_data_attributes
7
7
  } do %>
8
- <%= render Avo::PanelComponent.new(title: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
8
+ <%= render Avo::PanelComponent.new(name: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
9
9
  <% c.tools do %>
10
- <% if @reflection.present? && @resource.model.present? %>
11
- <% if can_detach? %>
12
- <%= a_button url: detach_path,
13
- icon: 'detach',
14
- method: :delete,
15
- form_class: 'flex flex-col sm:flex-row sm:inline-flex',
16
- style: :text,
17
- data: {
18
- confirm: "Are you sure you want to detach this #{title}."
19
- } do %>
20
- <%= t('avo.detach_item', item: title).capitalize %>
21
- <% end %>
22
- <% end %>
23
- <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
24
- <% if can_see_the_edit_button? %>
25
- <%= a_link edit_path,
26
- color: :primary,
27
- style: :primary,
28
- icon: 'edit' do %>
29
- <%= t('avo.edit').capitalize %>
10
+ <% if @resource.has_show_controls? %>
11
+ <% @resource.render_show_controls.each do |control| %>
12
+ <% if control.back_button? %>
13
+ <%= a_link back_path,
14
+ style: :text,
15
+ title: control.title,
16
+ data: {
17
+ tippy: control.title ? :tooltip : nil,
18
+ },
19
+ icon: 'arrow-left' do %>
20
+ <%= control.label %>
21
+ <% end %>
22
+ <% elsif control.delete_button? %>
23
+ <% if can_see_the_destroy_button? %>
24
+ <%= a_button url: helpers.resource_path(model: @resource.model, resource: @resource),
25
+ method: :delete,
26
+ local: true,
27
+ style: :text,
28
+ loading: true,
29
+ confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
30
+ color: :red,
31
+ icon: 'trash',
32
+ form_class: 'flex flex-col sm:flex-row sm:inline-flex',
33
+ title: control.title,
34
+ data: {
35
+ control: :destroy,
36
+ tippy: control.title ? :tooltip : nil,
37
+ 'resource-id': @resource.model.id,
38
+ } do %>
39
+ <%= control.label %>
40
+ <% end %>
41
+ <% end %>
42
+ <% elsif control.actions_list? %>
43
+ <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view, exclude: control.exclude, style: control.style, color: control.color %>
44
+ <% elsif control.edit_button? %>
45
+ <% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
46
+ <% end %>
47
+ <%= a_link edit_path,
48
+ color: :primary,
49
+ style: :primary,
50
+ title: control.title,
51
+ data: {
52
+ tippy: control.title ? :tooltip : nil,
53
+ },
54
+ icon: 'edit' do %>
55
+ <%= control.label %>
56
+ <% end %>
57
+ <% elsif control.action? %>
58
+ <%= a_link control.path,
59
+ color: control.color,
60
+ style: control.style,
61
+ icon: control.icon,
62
+ title: control.title,
63
+ data: {
64
+ tippy: control.title ? :tooltip : nil,
65
+ 'turbo-frame': 'actions_show',
66
+ 'action': 'click->actions-picker#visitAction',
67
+ } do %>
68
+ <%= control.label %>
69
+ <% end %>
70
+ <% elsif control.link_to? %>
71
+ <%= a_link control.path,
72
+ color: control.color,
73
+ style: control.style,
74
+ icon: control.icon,
75
+ title: control.title,
76
+ target: control.target,
77
+ class: control.class,
78
+ data: {
79
+ **control.data,
80
+ tippy: control.title ? :tooltip : nil,
81
+ } do %>
82
+ <%= control.label %>
83
+ <% end %>
84
+ <% elsif control.detach_button? %>
85
+ <% if @reflection.present? && @resource.model.present? && can_detach? %>
86
+ <%= a_button url: detach_path,
87
+ icon: 'detach',
88
+ method: :delete,
89
+ form_class: 'flex flex-col sm:flex-row sm:inline-flex',
90
+ style: :text,
91
+ data: {
92
+ confirm: "Are you sure you want to detach this #{title}."
93
+ } do %>
94
+ <%= control.label %>
95
+ <% end %>
96
+ <% end %>
30
97
  <% end %>
31
98
  <% end %>
32
99
  <% else %>
33
- <%= a_link back_path,
34
- style: :text,
35
- icon: 'arrow-left' do %>
36
- <%= t('avo.go_back') %>
37
- <% end %>
38
- <% if can_see_the_destroy_button? %>
39
- <%= a_button url: helpers.resource_path(model: @resource.model, resource: @resource),
40
- method: :delete,
41
- local: true,
100
+ <% if @reflection.present? && @resource.model.present? %>
101
+ <% if can_detach? %>
102
+ <%= a_button url: detach_path,
103
+ icon: 'detach',
104
+ method: :delete,
105
+ form_class: 'flex flex-col sm:flex-row sm:inline-flex',
106
+ style: :text,
107
+ data: {
108
+ confirm: "Are you sure you want to detach this #{title}."
109
+ } do %>
110
+ <%= t('avo.detach_item', item: title).capitalize %>
111
+ <% end %>
112
+ <% end %>
113
+ <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
114
+ <% if can_see_the_edit_button? %>
115
+ <%= a_link edit_path,
116
+ color: :primary,
117
+ style: :primary,
118
+ icon: 'edit' do %>
119
+ <%= t('avo.edit').capitalize %>
120
+ <% end %>
121
+ <% end %>
122
+ <% else %>
123
+ <%= a_link back_path,
42
124
  style: :text,
43
- loading: true,
44
- confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
45
- color: :red,
46
- icon: 'trash',
47
- form_class: 'flex flex-col sm:flex-row sm:inline-flex',
48
- data: {
49
- control: :destroy,
50
- 'resource-id': @resource.model.id,
51
- } do %>
52
- <%= t('avo.delete').capitalize %>
125
+ icon: 'arrow-left' do %>
126
+ <%= t('avo.go_back') %>
53
127
  <% end %>
54
- <% end %>
55
- <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
56
- <% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
57
- <%= a_link edit_path,
58
- color: :primary,
59
- style: :primary,
60
- icon: 'edit' do %>
61
- <%= t('avo.edit').capitalize %>
128
+ <% if can_see_the_destroy_button? %>
129
+ <%= a_button url: helpers.resource_path(model: @resource.model, resource: @resource),
130
+ method: :delete,
131
+ local: true,
132
+ style: :text,
133
+ loading: true,
134
+ confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
135
+ color: :red,
136
+ icon: 'trash',
137
+ form_class: 'flex flex-col sm:flex-row sm:inline-flex',
138
+ data: {
139
+ control: :destroy,
140
+ 'resource-id': @resource.model.id,
141
+ } do %>
142
+ <%= t('avo.delete').capitalize %>
143
+ <% end %>
144
+ <% end %>
145
+ <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource, view: @view %>
146
+ <% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
147
+ <%= a_link edit_path,
148
+ color: :primary,
149
+ style: :primary,
150
+ icon: 'edit' do %>
151
+ <%= t('avo.edit').capitalize %>
152
+ <% end %>
62
153
  <% end %>
63
154
  <% end %>
64
155
  <% end %>
@@ -17,6 +17,7 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
17
17
  def title
18
18
  if @reflection.present?
19
19
  return field.name if has_one_field?
20
+
20
21
  reflection_resource.name
21
22
  else
22
23
  @resource.default_panel_name