avo 2.12.1.pre.1 → 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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -3
  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 +8 -11
  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/fields/base_field.rb +1 -1
  40. data/lib/avo/fields/date_field.rb +1 -3
  41. data/lib/avo/fields/field_extensions/has_include_blank.rb +1 -1
  42. data/lib/avo/fields/has_base_field.rb +2 -0
  43. data/lib/avo/fields/key_value_field.rb +6 -6
  44. data/lib/avo/hosts/search_scope_host.rb +7 -0
  45. data/lib/avo/licensing/h_q.rb +12 -4
  46. data/lib/avo/licensing/pro_license.rb +1 -0
  47. data/lib/avo/menu/builder.rb +2 -0
  48. data/lib/avo/resources/controls/action.rb +32 -0
  49. data/lib/avo/resources/controls/actions_list.rb +19 -0
  50. data/lib/avo/resources/controls/back_button.rb +13 -0
  51. data/lib/avo/resources/controls/base_control.rb +59 -0
  52. data/lib/avo/resources/controls/delete_button.rb +13 -0
  53. data/lib/avo/resources/controls/detach_button.rb +13 -0
  54. data/lib/avo/resources/controls/edit_button.rb +13 -0
  55. data/lib/avo/resources/controls/execution_context.rb +58 -0
  56. data/lib/avo/resources/controls/items_holder.rb +19 -0
  57. data/lib/avo/resources/controls/link_to.rb +27 -0
  58. data/lib/avo/version.rb +1 -1
  59. data/lib/generators/avo/templates/action.tt +1 -1
  60. data/lib/generators/avo/templates/initializer/avo.tt +1 -0
  61. data/lib/generators/avo/templates/resource/resource.tt +1 -1
  62. data/lib/generators/avo/templates/resource_tools/partial.tt +1 -1
  63. data/lib/generators/avo/templates/standalone_action.tt +1 -1
  64. data/public/avo-assets/avo.css +564 -44
  65. data/public/avo-assets/avo.js +47 -47
  66. data/public/avo-assets/avo.js.map +2 -2
  67. metadata +16 -5
  68. data/lib/avo/concerns/has_model.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c32b3f69d566186e0bd65d5189642e9929bfa7e0ea1cf8c146bfabff1658955a
4
- data.tar.gz: 1fe470c1af50110165a1ad3b06c28a42153931a9100d8d6f0e0e850427214a6c
3
+ metadata.gz: 16af345f63f08dc026b6c1a29ce0938d7a0aad278a53884e542b8f31a17c34fa
4
+ data.tar.gz: ed4abef748fbe4e8e22edecd85ea70f361875e30f28ffdbddfb648fbf9cde226
5
5
  SHA512:
6
- metadata.gz: aa99c1aeb3fe23c10d7422dbb651b5b67148e344ddf5c79a992cd67c6b2421611139231d6502d1046234f9fa89050444cdb8bcbc582ee167115d1b5aa7f41600
7
- data.tar.gz: 5fbeb32c8061326a8c09a0926cb6531f3fb0f5716138a60db2f7e723beeca4dae78d666f1952c66f24434dece2b0abaade6621b0b151b3edcc364f7e53b106c8
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.12.1.pre.1)
4
+ avo (2.13.0)
5
5
  active_link_to
6
6
  addressable
7
7
  breadcrumbs_on_rails
@@ -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
@@ -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
@@ -115,7 +115,7 @@ module Avo
115
115
  add_breadcrumb via_resource.model_title, resource_path(model: via_model, resource: via_resource)
116
116
  end
117
117
 
118
- add_breadcrumb @resource.plural_name.humanize
118
+ add_breadcrumb @resource.plural_name.humanize, resources_path(resource: @resource)
119
119
  add_breadcrumb t("avo.new").humanize
120
120
  end
121
121
 
@@ -129,21 +129,14 @@ module Avo
129
129
  @reflection = @model._reflections[params[:via_relation]]
130
130
  # Figure out what kind of association does the record have with the parent record
131
131
 
132
- # belongs_to
133
- # has_many
132
+ # Fills in the required infor for belongs_to and has_many
134
133
  # Get the foreign key and set it to the id we received in the params
135
134
  if @reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection) || @reflection.is_a?(ActiveRecord::Reflection::HasManyReflection)
136
- foreign_key = @reflection.foreign_key
137
- @model.send("#{foreign_key}=", params[:via_resource_id])
135
+ @model.send("#{@reflection.foreign_key}=", params[:via_resource_id])
138
136
  @model.save
139
137
  end
140
138
 
141
- # has_one
142
- # has_one_through
143
-
144
- # has_many_through
145
- # has_and_belongs_to_many
146
- # polymorphic
139
+ # For when working with has_one, has_one_through, has_many_through, has_and_belongs_to_many, polymorphic
147
140
  if @reflection.is_a? ActiveRecord::Reflection::ThroughReflection
148
141
  # find the record
149
142
  via_resource = ::Avo::App.get_resource_by_model_name params[:via_relation_class]
@@ -157,6 +150,9 @@ module Avo
157
150
  if saved
158
151
  format.html { redirect_to after_create_path, notice: "#{@resource.name} #{t("avo.was_successfully_created")}." }
159
152
  else
153
+ add_breadcrumb @resource.plural_name.humanize, resources_path(resource: @resource)
154
+ add_breadcrumb t("avo.new").humanize
155
+ set_actions
160
156
  flash.now[:error] = t "avo.you_missed_something_check_form"
161
157
  format.html { render :new, status: :unprocessable_entity }
162
158
  end
@@ -176,6 +172,7 @@ module Avo
176
172
  if saved
177
173
  format.html { redirect_to after_update_path, notice: "#{@resource.name} #{t("avo.was_successfully_updated")}." }
178
174
  else
175
+ set_actions
179
176
  flash.now[:error] = t "avo.you_missed_something_check_form"
180
177
  format.html { render :edit, status: :unprocessable_entity }
181
178
  end