avo 3.0.0.pre18 → 3.0.0.pre19

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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +23 -25
  4. data/Rakefile +2 -0
  5. data/{public/avo-assets/avo.css → app/assets/builds/avo.base.css} +587 -3848
  6. data/app/assets/builds/avo.base.js +124556 -0
  7. data/app/assets/builds/avo.base.js.map +7 -0
  8. data/app/assets/builds/avo.custom.js +6 -0
  9. data/app/assets/builds/avo.custom.js.map +7 -0
  10. data/app/assets/stylesheets/avo.base.css +1 -0
  11. data/app/assets/stylesheets/css/fields/tags.css +32 -0
  12. data/app/components/avo/actions_component.rb +1 -1
  13. data/app/components/avo/field_wrapper_component.html.erb +1 -1
  14. data/app/components/avo/field_wrapper_component.rb +1 -7
  15. data/app/components/avo/fields/boolean_field/index_component.html.erb +1 -1
  16. data/app/components/avo/fields/common/badge_viewer_component.html.erb +1 -24
  17. data/app/components/avo/fields/common/badge_viewer_component.rb +24 -0
  18. data/app/components/avo/fields/common/boolean_check_component.html.erb +1 -12
  19. data/app/components/avo/fields/common/boolean_check_component.rb +2 -1
  20. data/app/components/avo/fields/common/gravatar_viewer_component.html.erb +1 -1
  21. data/app/components/avo/fields/common/gravatar_viewer_component.rb +2 -2
  22. data/app/components/avo/fields/common/heading_component.html.erb +3 -8
  23. data/app/components/avo/fields/common/heading_component.rb +1 -3
  24. data/app/components/avo/fields/common/key_value_component.html.erb +2 -2
  25. data/app/components/avo/fields/common/key_value_component.rb +2 -2
  26. data/app/components/avo/fields/common/progress_bar_component.rb +3 -9
  27. data/app/components/avo/fields/common/status_viewer_component.html.erb +3 -0
  28. data/app/components/avo/fields/edit_component.rb +1 -1
  29. data/app/components/avo/fields/external_image_field/index_component.html.erb +1 -1
  30. data/app/components/avo/fields/file_field/index_component.html.erb +2 -2
  31. data/app/components/avo/fields/gravatar_field/index_component.html.erb +1 -1
  32. data/app/components/avo/fields/heading_field/edit_component.html.erb +1 -1
  33. data/app/components/avo/fields/heading_field/show_component.html.erb +1 -1
  34. data/app/components/avo/fields/id_field/index_component.html.erb +1 -1
  35. data/app/components/avo/fields/index_component.rb +1 -1
  36. data/app/components/avo/fields/show_component.rb +1 -1
  37. data/app/components/avo/fields/text_field/index_component.html.erb +1 -1
  38. data/app/components/avo/index/field_wrapper_component.rb +1 -1
  39. data/app/components/avo/index/resource_controls_component.rb +1 -1
  40. data/app/components/avo/index/resource_table_component.rb +3 -9
  41. data/app/components/avo/resource_component.rb +9 -4
  42. data/app/components/avo/sidebar_profile_component.html.erb +4 -4
  43. data/app/components/avo/tab_group_component.html.erb +1 -1
  44. data/app/components/avo/tab_switcher_component.rb +2 -2
  45. data/app/components/avo/views/resource_edit_component.html.erb +9 -20
  46. data/app/components/avo/views/resource_edit_component.rb +5 -5
  47. data/app/components/avo/views/resource_index_component.rb +1 -1
  48. data/app/components/avo/views/resource_show_component.html.erb +1 -1
  49. data/app/components/avo/views/resource_show_component.rb +1 -1
  50. data/app/controllers/avo/actions_controller.rb +9 -20
  51. data/app/controllers/avo/application_controller.rb +5 -5
  52. data/app/controllers/avo/base_controller.rb +39 -1
  53. data/app/controllers/avo/search_controller.rb +19 -2
  54. data/app/controllers/concerns/avo/initializes_avo.rb +1 -0
  55. data/app/helpers/avo/resources_helper.rb +1 -1
  56. data/app/helpers/avo/url_helpers.rb +1 -1
  57. data/app/views/avo/base/edit.html.erb +1 -1
  58. data/app/views/avo/base/index.html.erb +1 -1
  59. data/app/views/avo/base/new.html.erb +1 -1
  60. data/app/views/avo/base/show.html.erb +1 -1
  61. data/app/views/layouts/avo/application.html.erb +10 -2
  62. data/bin/dev +2 -0
  63. data/config/routes.rb +4 -3
  64. data/db/factories.rb +1 -1
  65. data/lib/avo/base_action.rb +21 -26
  66. data/lib/avo/base_resource.rb +13 -7
  67. data/lib/avo/concerns/filters_session_handler.rb +3 -3
  68. data/lib/avo/concerns/has_helpers.rb +18 -0
  69. data/lib/avo/concerns/has_items.rb +1 -5
  70. data/lib/avo/concerns/visible_in_different_views.rb +7 -1
  71. data/lib/avo/concerns/visible_items.rb +43 -0
  72. data/lib/avo/configuration.rb +28 -4
  73. data/lib/avo/current.rb +1 -6
  74. data/lib/avo/dsl/field_parser.rb +1 -1
  75. data/lib/avo/execution_context.rb +4 -1
  76. data/lib/avo/fields/badge_field.rb +1 -1
  77. data/lib/avo/fields/base_field.rb +21 -44
  78. data/lib/avo/fields/belongs_to_field.rb +1 -1
  79. data/lib/avo/fields/concerns/has_html_attributes.rb +2 -0
  80. data/lib/avo/fields/concerns/use_view_components.rb +45 -0
  81. data/lib/avo/fields/external_image_field.rb +2 -2
  82. data/lib/avo/fields/file_field.rb +2 -2
  83. data/lib/avo/fields/gravatar_field.rb +2 -2
  84. data/lib/avo/fields/has_base_field.rb +2 -2
  85. data/lib/avo/fields/heading_field.rb +5 -13
  86. data/lib/avo/fields/id_field.rb +2 -2
  87. data/lib/avo/fields/status_field.rb +3 -1
  88. data/lib/avo/fields/text_field.rb +2 -2
  89. data/lib/avo/filters/base_filter.rb +1 -1
  90. data/lib/avo/html/builder.rb +1 -1
  91. data/lib/avo/licensing/license_manager.rb +1 -1
  92. data/lib/avo/resources/items/holder.rb +0 -6
  93. data/lib/avo/resources/items/item_group.rb +2 -2
  94. data/lib/avo/resources/items/row.rb +3 -3
  95. data/lib/avo/resources/items/sidebar.rb +1 -1
  96. data/lib/avo/resources/items/tab.rb +2 -2
  97. data/lib/avo/resources/items/tab_group.rb +1 -1
  98. data/lib/avo/resources/resource_manager.rb +6 -1
  99. data/lib/avo/version.rb +1 -1
  100. data/lib/avo/view_inquirer.rb +36 -0
  101. data/lib/avo.rb +9 -0
  102. data/lib/generators/avo/concerns/parent_controller.rb +20 -0
  103. data/lib/generators/avo/controller_generator.rb +3 -0
  104. data/lib/generators/avo/eject_generator.rb +180 -15
  105. data/lib/generators/avo/field_generator.rb +49 -2
  106. data/lib/generators/avo/js/install_generator.rb +2 -2
  107. data/lib/generators/avo/resource_generator.rb +10 -7
  108. data/lib/generators/avo/tailwindcss/install_generator.rb +58 -12
  109. data/lib/generators/avo/templates/initializer/avo.tt +6 -1
  110. data/lib/generators/avo/templates/resource/controller.tt +1 -1
  111. data/lib/generators/avo/templates/tailwindcss/avo.tailwind.css +5 -3
  112. data/lib/generators/avo/templates/tailwindcss/tailwind.config.js +11 -0
  113. data/lib/tasks/avo_tasks.rake +33 -5
  114. data/public/avo-assets/avo.base.css +75 -4146
  115. metadata +14 -6
  116. data/config/master.key +0 -1
  117. data/public/avo-assets/avo.js +0 -513
  118. data/public/avo-assets/avo.js.map +0 -7
@@ -4,5 +4,29 @@ class Avo::Fields::Common::BadgeViewerComponent < ViewComponent::Base
4
4
  def initialize(value:, options:)
5
5
  @value = value
6
6
  @options = options
7
+ @backgrounds = {
8
+ info: "bg-blue-500",
9
+ success: "bg-green-500",
10
+ danger: "bg-red-500",
11
+ warning: "bg-yellow-500",
12
+ neutral: "bg-gray-500"
13
+ }
14
+ end
15
+
16
+ def classes
17
+ background = :info
18
+
19
+ @options.invert.each do |values, type|
20
+ if [values].flatten.map { |value| value }.include? @value
21
+ background = type.to_sym
22
+ next
23
+ end
24
+ end
25
+
26
+ classes = "whitespace-nowrap rounded-md uppercase px-2 py-1 text-xs font-bold block text-center truncate "
27
+
28
+ classes += "#{@backgrounds[background]} text-white" if @backgrounds[background].present?
29
+
30
+ classes
7
31
  end
8
32
  end
@@ -1,12 +1 @@
1
- <%
2
- classes = 'h-6 float-left mr-1'
3
-
4
- if @checked
5
- classes += ' text-green-600'
6
- icon = 'heroicons/outline/check-circle'
7
- else
8
- classes += ' text-red-500'
9
- icon = 'heroicons/outline/x-circle'
10
- end
11
- %>
12
- <%= helpers.svg "#{icon}.svg", class: classes %>
1
+ <%= helpers.svg "#{@icon}.svg", class: @classes %>
@@ -2,6 +2,7 @@
2
2
 
3
3
  class Avo::Fields::Common::BooleanCheckComponent < ViewComponent::Base
4
4
  def initialize(checked: false)
5
- @checked = checked
5
+ @icon = checked ? "heroicons/outline/check-circle" : "heroicons/outline/x-circle"
6
+ @classes = "h-6 #{checked ? "text-green-600" : "text-red-500"}"
6
7
  end
7
8
  end
@@ -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, width: options[:size], height: options[:size]), @link, title: @title %>
12
+ <%= link_to_if @link_to_record.present?, image_tag(url.to_s, class: classes, width: options[:size], height: options[:size]), @link, title: @title %>
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Fields::Common::GravatarViewerComponent < ViewComponent::Base
4
- def initialize(md5: nil, link: nil, default: nil, size: nil, rounded: false, link_to_resource: false, title: nil)
4
+ def initialize(md5: nil, link: nil, default: nil, size: nil, rounded: false, link_to_record: false, title: nil)
5
5
  @md5 = md5
6
6
  @link = link
7
7
  @default = default
8
8
  @size = size
9
9
  @rounded = rounded
10
- @link_to_resource = link_to_resource
10
+ @link_to_record = link_to_record
11
11
  @title = title
12
12
  end
13
13
  end
@@ -1,14 +1,9 @@
1
1
  <div class="flex items-start py-1 leading-tight bg-gray-100 text-gray-500 text-xs">
2
2
  <div class="py-2 px-6 h-full w-full">
3
- <% if empty %>
4
- <% elsif value.present? %>
5
- <% if as_html %>
6
- <%= sanitize value %>
7
- <% else %>
8
- <div class="font-semibold uppercase"><%= value %></div>
9
- <% end %>
3
+ <% if as_html %>
4
+ <%= sanitize value %>
10
5
  <% else %>
11
-
6
+ <div class="font-semibold uppercase"><%= value %></div>
12
7
  <% end %>
13
8
  </div>
14
9
  </div>
@@ -3,11 +3,9 @@
3
3
  class Avo::Fields::Common::HeadingComponent < ViewComponent::Base
4
4
  attr_reader :value
5
5
  attr_reader :as_html
6
- attr_reader :empty
7
6
 
8
- def initialize(value:, as_html:, empty:)
7
+ def initialize(value:, as_html:)
9
8
  @value = value
10
9
  @as_html = as_html
11
- @empty = empty
12
10
  end
13
11
  end
@@ -3,7 +3,7 @@
3
3
  data-key-value-target="controller"
4
4
  data-options="<%= @field.options.to_json %>"
5
5
  data-input-classes="<%= input_classes %>"
6
- data-editable="<%= @view.in?([:edit, :new]) %>"
6
+ data-editable="<%= @view.form? %>"
7
7
  >
8
8
  <div class="w-full flex flex-col">
9
9
  <div class="flex w-full">
@@ -14,7 +14,7 @@
14
14
  <div class="w-1/2 py-3 px-3 uppercase font-semibold text-xs text-white">
15
15
  <%= @field.value_label %>
16
16
  </div>
17
- <% if @view.in?([:edit, :new]) %>
17
+ <% if @view.form? %>
18
18
  <div class="flex items-center justify-center p-2 px-3 border-l border-gray-600">
19
19
  <a href="javascript:void(0);"
20
20
  title="<%= @field.action_text %>"
@@ -5,9 +5,9 @@ class Avo::Fields::Common::KeyValueComponent < ViewComponent::Base
5
5
 
6
6
  attr_reader :view
7
7
 
8
- def initialize(field:, form: nil, view: :show)
8
+ def initialize(field:, form: nil, view: "show")
9
9
  @field = field
10
10
  @form = form
11
- @view = view
11
+ @view = Avo::ViewInquirer.new(view)
12
12
  end
13
13
  end
@@ -7,19 +7,13 @@ class Avo::Fields::Common::ProgressBarComponent < ViewComponent::Base
7
7
  attr_reader :max
8
8
  attr_reader :view
9
9
 
10
- def initialize(value:, display_value: false, value_suffix: nil, max: 100, view: :index)
10
+ def initialize(value:, display_value: false, value_suffix: nil, max: 100, view: "index")
11
11
  @value = value
12
12
  @display_value = display_value
13
13
  @value_suffix = value_suffix
14
14
  @max = max
15
- @view = view
15
+ @view = Avo::ViewInquirer.new(view)
16
16
  end
17
17
 
18
- def show?
19
- view == :show
20
- end
21
-
22
- def index?
23
- view == :index
24
- end
18
+ delegate :show?, :index?, to: :view
25
19
  end
@@ -2,12 +2,15 @@
2
2
  classes = "inline-block"
3
3
  classes += " text-red-600" if @status == 'failed'
4
4
  classes += " text-green-600" if @status == 'success'
5
+ classes += " text-gray-600" if @status == 'neutral'
5
6
  %>
6
7
  <div class="flex flex-shrink-0 <%= classes %> items-center">
7
8
  <% if @status == 'success' %>
8
9
  <%= helpers.svg 'heroicons/solid/check-circle', class: 'h-4' %>
9
10
  <% elsif @status == 'failed' %>
10
11
  <%= helpers.svg 'heroicons/solid/x-circle', class: 'h-4' %>
12
+ <% elsif @status == 'neutral' %>
13
+ <%= helpers.svg 'heroicons/solid/minus-circle', class: 'h-4' %>
11
14
  <% elsif @status == 'loading' %>
12
15
  <div class="spinner">
13
16
  <div class="double-bounce1 bg-gray-600"></div>
@@ -20,7 +20,7 @@ class Avo::Fields::EditComponent < ViewComponent::Base
20
20
  @multiple = multiple
21
21
  @resource = resource
22
22
  @stacked = stacked
23
- @view = :edit
23
+ @view = Avo::ViewInquirer.new("edit")
24
24
  end
25
25
 
26
26
  def classes(extra_classes = "")
@@ -1,6 +1,6 @@
1
1
  <%= index_field_wrapper **field_wrapper_args, flush: true do %>
2
2
  <% if @field.value.present? %>
3
- <%= link_to_if @field.link_to_resource.present?,
3
+ <%= link_to_if @field.link_to_record.present?,
4
4
  image_tag(@field.value,
5
5
  height: @field.height,
6
6
  style: "border-radius: #{@field.radius}px; max-height: #{@field.height}#{@field.height.to_s&.ends_with?('px') ? '' : 'px'};"),
@@ -1,9 +1,9 @@
1
1
  <%= index_field_wrapper **field_wrapper_args, flush: flush? do %>
2
2
  <% if @field.value.present? %>
3
3
  <% if @field.value.attached? && @field.value.representable? && @field.is_image %>
4
- <%= link_to_if @field.link_to_resource, image_tag(helpers.main_app.url_for(@field.value), class: 'h-10'), resource_view_path, class: 'block' %>
4
+ <%= link_to_if @field.link_to_record, image_tag(helpers.main_app.url_for(@field.value), class: 'h-10'), resource_view_path, class: 'block' %>
5
5
  <% elsif @field.value.attached? && @field.is_audio %>
6
- <%= link_to_if @field.link_to_resource, audio_tag(helpers.main_app.url_for(@field.value), controls: true, preload: false, class: 'max-h-full h-10'), resource_view_path, class: 'block h-8' %>
6
+ <%= link_to_if @field.link_to_record, audio_tag(helpers.main_app.url_for(@field.value), controls: true, preload: false, class: 'max-h-full h-10'), resource_view_path, class: 'block h-8' %>
7
7
  <% else %>
8
8
  <%= @field.value.filename %>
9
9
  <% end %>
@@ -4,7 +4,7 @@
4
4
  default: @field.default,
5
5
  size: @field.size,
6
6
  rounded: @field.rounded,
7
- link_to_resource: @field.link_to_resource,
7
+ link_to_record: @field.link_to_record,
8
8
  link: resource_view_path,
9
9
  title: t('avo.view_item', item: @resource.name).humanize
10
10
  )
@@ -1,3 +1,3 @@
1
1
  <div <% if @index == 0 %> class="overflow-hidden rounded-t" <% end %> data-field-id="<%= @field.id %>">
2
- <%= render Avo::Fields::Common::HeadingComponent.new value: @field.name, as_html: @field.as_html, empty: @field.empty %>
2
+ <%= render Avo::Fields::Common::HeadingComponent.new value: @field.value, as_html: @field.as_html %>
3
3
  </div>
@@ -1,3 +1,3 @@
1
1
  <div <% if @index == 0 %> class="overflow-hidden rounded-t" <% end %> data-field-id="<%= @field.id %>">
2
- <%= render Avo::Fields::Common::HeadingComponent.new value: @field.name, as_html: @field.as_html, empty: @field.empty %>
2
+ <%= render Avo::Fields::Common::HeadingComponent.new value: @field.value, as_html: @field.as_html %>
3
3
  </div>
@@ -1,3 +1,3 @@
1
1
  <%= index_field_wrapper **field_wrapper_args, class: 'whitespace-no-wrap w-[1%]' do %>
2
- <% link_to_if (@field.link_to_resource or Avo.configuration.id_links_to_resource), @field.value, resource_view_path, title: t('avo.view_item', item: @resource.name).humanize %>
2
+ <% link_to_if (@field.link_to_record or Avo.configuration.id_links_to_resource), @field.value, resource_view_path, title: t('avo.view_item', item: @resource.name).humanize %>
3
3
  <% end %>
@@ -13,7 +13,7 @@ class Avo::Fields::IndexComponent < Avo::BaseComponent
13
13
  @index = index
14
14
  @parent_record = parent_record
15
15
  @parent_resource = parent_resource
16
- @view = :index
16
+ @view = Avo::ViewInquirer.new("index")
17
17
  @reflection = reflection
18
18
  end
19
19
 
@@ -18,7 +18,7 @@ class Avo::Fields::ShowComponent < ViewComponent::Base
18
18
  @resource = resource
19
19
  @stacked = stacked
20
20
  @short = short
21
- @view = :show
21
+ @view = Avo::ViewInquirer.new("show")
22
22
  end
23
23
 
24
24
  def wrapper_data
@@ -4,6 +4,6 @@
4
4
  <% elsif @field.protocol.present? %>
5
5
  <%= link_to @field.value, "#{@field.protocol}:#{@field.value}" %>
6
6
  <% else %>
7
- <%= link_to_if @field.link_to_resource, @field.value, resource_view_path %>
7
+ <%= link_to_if @field.link_to_record, @field.value, resource_view_path %>
8
8
  <% end %>
9
9
  <% end %>
@@ -11,7 +11,7 @@ class Avo::Index::FieldWrapperComponent < ViewComponent::Base
11
11
  @classes = args[:class].present? ? args[:class] : ""
12
12
  @args = args
13
13
  @flush = flush
14
- @view = :index
14
+ @view = Avo::ViewInquirer.new("index")
15
15
  end
16
16
 
17
17
  def classes
@@ -23,7 +23,7 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
23
23
  end
24
24
 
25
25
  def can_view?
26
- return false if Avo.configuration.resource_default_view == :edit
26
+ return false if Avo.configuration.resource_default_view.edit?
27
27
 
28
28
  return authorize_association_for(:show) if @reflection.present?
29
29
 
@@ -17,18 +17,12 @@ class Avo::Index::ResourceTableComponent < ViewComponent::Base
17
17
 
18
18
  def encrypted_query
19
19
  # TODO: move this to the resource where we can apply the adapter pattern
20
- serialized_query = if Module.const_defined?("Ransack::Search") && query.instance_of?(Ransack::Search)
21
- query.context.object.to_sql
22
- else
23
- return :select_all_disabled if query.nil? || !query.respond_to?(:all) || !query.all.respond_to?(:to_sql)
24
-
25
- query.all.to_sql
20
+ if Module.const_defined?("Ransack::Search") && query.instance_of?(Ransack::Search)
21
+ @query = @query.result
26
22
  end
27
23
 
28
- return if serialized_query.nil?
29
-
30
24
  Avo::Services::EncryptionService.encrypt(
31
- message: serialized_query,
25
+ message: Marshal.dump(@query),
32
26
  purpose: :select_all
33
27
  )
34
28
  end
@@ -53,11 +53,16 @@ class Avo::ResourceComponent < Avo::BaseComponent
53
53
  end
54
54
 
55
55
  def destroy_path
56
- if params[:via_resource_class].present?
57
- helpers.resource_path(record: @resource.record, resource: @resource, referrer: back_path)
58
- else
59
- helpers.resource_path(record: @resource.record, resource: @resource)
56
+ args = {record: @resource.record, resource: @resource}
57
+
58
+ args[:referrer] = if params[:via_resource_class].present?
59
+ back_path
60
+ # If we're deleting a resource from a parent resource, we need to go back to the parent resource page after the deletion
61
+ elsif @parent_resource.present?
62
+ helpers.resource_path(record: @parent_record, resource: @parent_resource)
60
63
  end
64
+
65
+ helpers.resource_path(**args)
61
66
  end
62
67
 
63
68
  # Ex: A Post has many Comments
@@ -1,12 +1,12 @@
1
1
  <div class="text-black border-gray-150 p-4 flex border-t">
2
- <div class="flex-1 flex space-x-4">
2
+ <div class="flex-1 flex space-x-4 w-full">
3
3
  <% if avatar.present? %>
4
- <div class="relative aspect-square w-10 h-10 overflow-hidden rounded">
4
+ <div class="relative aspect-square w-10 h-10 overflow-hidden rounded shrink-0">
5
5
  <%= image_tag avatar, class: "object-cover min-w-full min-h-full h-full" %>
6
6
  </div>
7
7
  <% end %>
8
- <div class="flex flex-col">
9
- <div class="font-medium">
8
+ <div class="flex flex-col pr-3 min-w-0">
9
+ <div class="font-medium text-ellipsis overflow-hidden">
10
10
  <%= name %>
11
11
  </div>
12
12
  <% if title.present? %>
@@ -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', 'update', 'create'])
28
+ should_lazy_load = if @view.in?(%w[edit new update create])
29
29
  false
30
30
  else
31
31
  !is_current_tab
@@ -33,11 +33,11 @@ class Avo::TabSwitcherComponent < Avo::BaseComponent
33
33
  end
34
34
 
35
35
  def is_edit?
36
- @view.in?([:edit, :update])
36
+ @view.in?(%w[edit update])
37
37
  end
38
38
 
39
39
  def is_new?
40
- @view.in?([:new, :create])
40
+ @view.in?(%w[new create])
41
41
  end
42
42
 
43
43
  def is_initial_load?
@@ -44,26 +44,6 @@
44
44
  <%= render sidebar_component form: form %>
45
45
  <% end %>
46
46
  <% end %>
47
- <% if Avo.configuration.buttons_on_form_footers %>
48
- <% c.with_footer_tools do %>
49
- <div class="mt-4">
50
- <%= a_link back_path,
51
- style: :text,
52
- icon: 'arrow-left' do %>
53
- <%= t('avo.cancel').capitalize %>
54
- <% end %>
55
- <% if can_see_the_save_button? %>
56
- <%= a_button color: :primary,
57
- style: :primary,
58
- loading: true,
59
- type: :submit,
60
- icon: 'save' do %>
61
- <%= t('avo.save').capitalize %>
62
- <% end %>
63
- <% end %>
64
- </div>
65
- <% end %>
66
- <% end %>
67
47
  <% end %>
68
48
  <%= content_tag :div, class: 'space-y-12' do %>
69
49
  <% @resource.get_items.each_with_index do |item, index| %>
@@ -71,6 +51,15 @@
71
51
  <%= render Avo::ItemSwitcherComponent.new resource: @resource, item: item, index: index + 1, view: view, form: form %>
72
52
  <% end %>
73
53
  <% end %>
54
+ <% if Avo.configuration.buttons_on_form_footers %>
55
+ <%= render Avo::PanelComponent.new do |c| %>
56
+ <% c.with_footer_tools do %>
57
+ <% @resource.render_edit_controls.each do |control| %>
58
+ <%= render_control control %>
59
+ <% end %>
60
+ <% end %>
61
+ <% end %>
62
+ <% end %>
74
63
  <% end %>
75
64
  <% end %>
76
65
  <% end %>
@@ -3,11 +3,11 @@
3
3
  class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
4
4
  include Avo::ApplicationHelper
5
5
 
6
- def initialize(resource: nil, record: nil, actions: [], view: :edit)
6
+ def initialize(resource: nil, record: nil, actions: [], view: "edit")
7
7
  @resource = resource
8
8
  @record = record
9
9
  @actions = actions
10
- @view = view
10
+ @view = Avo::ViewInquirer.new(view)
11
11
  end
12
12
 
13
13
  def title
@@ -18,7 +18,7 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
18
18
  return resource_view_path if via_resource?
19
19
  return resources_path if via_index?
20
20
 
21
- if is_edit? && Avo.configuration.resource_default_view == :show # via resource show or edit page
21
+ if is_edit? && Avo.configuration.resource_default_view.show? # via resource show or edit page
22
22
  return helpers.resource_path(record: @resource.record, resource: @resource)
23
23
  end
24
24
 
@@ -34,7 +34,7 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
34
34
  end
35
35
 
36
36
  def can_see_the_destroy_button?
37
- return super if is_edit? && Avo.configuration.resource_default_view == :edit
37
+ return super if is_edit? && Avo.configuration.resource_default_view.edit?
38
38
 
39
39
  false
40
40
  end
@@ -52,7 +52,7 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
52
52
  end
53
53
 
54
54
  def is_edit?
55
- view.in?([:edit, :update])
55
+ view.in?(%w[edit update])
56
56
  end
57
57
 
58
58
  def form_method
@@ -34,7 +34,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
34
34
  @parent_record = parent_record
35
35
  @parent_resource = parent_resource
36
36
  @applied_filters = applied_filters
37
- @view = :index
37
+ @view = Avo::ViewInquirer.new("index")
38
38
  @query = query
39
39
  @scopes = scopes
40
40
  end
@@ -4,7 +4,7 @@
4
4
  resource_name: @resource.class.to_s,
5
5
  record_id: @resource.record.id,
6
6
  selected_resources_name: @resource.model_key,
7
- selected_resources: [@resource.record.id],
7
+ selected_resources: [@resource.record.to_param],
8
8
  **@resource.stimulus_data_attributes
9
9
  } do %>
10
10
  <%= render Avo::PanelComponent.new(name: title, description: @resource.description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
@@ -10,7 +10,7 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
10
10
  @actions = actions
11
11
  @parent_record = parent_record
12
12
  @parent_resource = parent_resource
13
- @view = :show
13
+ @view = Avo::ViewInquirer.new("show")
14
14
  end
15
15
 
16
16
  def title
@@ -13,7 +13,7 @@ module Avo
13
13
 
14
14
  def show
15
15
  # Se the view to :new so the default value gets prefilled
16
- @view = :new
16
+ @view = Avo::ViewInquirer.new("new")
17
17
 
18
18
  @resource.hydrate(record: @record, view: @view, user: _current_user, params: params)
19
19
  @record = ActionModel.new @action.get_attributes_for_action
@@ -21,23 +21,13 @@ module Avo
21
21
 
22
22
  def handle
23
23
  resource_ids = action_params[:fields][:avo_resource_ids].split(",")
24
- @selected_query = action_params[:fields][:avo_selected_query]
25
24
 
26
- fields = action_params[:fields].except(:avo_resource_ids, :avo_selected_query)
27
-
28
- args = {
29
- fields: fields,
25
+ performed_action = @action.handle_action(
26
+ fields: action_params[:fields].except(:avo_resource_ids, :avo_selected_query),
30
27
  current_user: _current_user,
31
- resource: resource
32
- }
33
-
34
- args[:records] = if @selected_query.present?
35
- @resource.model_class.find_by_sql decrypted_query
36
- else
37
- @resource.find_record resource_ids, params: params
38
- end
39
-
40
- performed_action = @action.handle_action(**args)
28
+ resource: resource,
29
+ query: decrypted_query || @resource.find_record(resource_ids, params: params)
30
+ )
41
31
 
42
32
  respond performed_action.response
43
33
  end
@@ -106,10 +96,9 @@ module Avo
106
96
  end
107
97
 
108
98
  def decrypted_query
109
- Avo::Services::EncryptionService.decrypt(
110
- message: @selected_query,
111
- purpose: :select_all
112
- )
99
+ return if (encrypted_query = action_params[:fields][:avo_selected_query]).blank?
100
+
101
+ Marshal.load(Avo::Services::EncryptionService.decrypt(message: encrypted_query, purpose: :select_all))
113
102
  end
114
103
 
115
104
  def decrypted_arguments
@@ -115,7 +115,7 @@ module Avo
115
115
  def set_resource
116
116
  raise ActionController::RoutingError.new "No route matches" if resource.nil?
117
117
 
118
- @resource = resource.new(view: action_name.to_sym, user: _current_user, params: params)
118
+ @resource = resource.new(view: action_name.to_s, user: _current_user, params: params)
119
119
 
120
120
  set_authorization
121
121
  end
@@ -149,12 +149,12 @@ module Avo
149
149
  end
150
150
 
151
151
  def set_view
152
- @view = action_name.to_sym
152
+ @view = Avo::ViewInquirer.new(action_name.to_s)
153
153
  end
154
154
 
155
155
  def set_record_to_fill
156
- @record_to_fill = @resource.model_class.new if @view == :create
157
- @record_to_fill = @record if @view == :update
156
+ @record_to_fill = @resource.model_class.new if @view.create?
157
+ @record_to_fill = @record if @view.update?
158
158
 
159
159
  # If resource.record is nil, most likely the user is creating a new record.
160
160
  # In that case, to access resource.record in visible and readonly blocks we hydrate the resource with a new record.
@@ -167,7 +167,7 @@ module Avo
167
167
  return if is_attach_action?
168
168
 
169
169
  @record = @resource.fill_record(@record_to_fill, cast_nullable(model_params), extra_params: extra_params)
170
- assign_default_value_to_disabled_fields if @view == :create
170
+ assign_default_value_to_disabled_fields if @view.create?
171
171
  end
172
172
 
173
173
  def is_attach_action?