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
@@ -12,8 +12,8 @@ module Avo
12
12
  hide_on :index
13
13
 
14
14
  @key_label = args[:key_label] if args[:key_label].present?
15
- @value_label = args[:value_label]if args[:value_label].present?
16
- @action_text = args[:action_text] if args[:action_text].present?
15
+ @value_label = args[:value_label] if args[:value_label].present?
16
+ @action_text = args[:action_text] if args[:action_text].present? # This should be add_row_label
17
17
  @delete_text = args[:delete_text] if args[:delete_text].present?
18
18
 
19
19
  @disable_editing_keys = args[:disable_editing_keys].present? ? args[:disable_editing_keys] : false
@@ -31,25 +31,25 @@ module Avo
31
31
  def key_label
32
32
  return @key_label if @key_label.present?
33
33
 
34
- I18n.translate('avo.key_value_field.key')
34
+ I18n.translate("avo.key_value_field.key")
35
35
  end
36
36
 
37
37
  def value_label
38
38
  return @value_label if @value_label.present?
39
39
 
40
- I18n.translate('avo.key_value_field.value')
40
+ I18n.translate("avo.key_value_field.value")
41
41
  end
42
42
 
43
43
  def action_text
44
44
  return @action_text if @action_text.present?
45
45
 
46
- I18n.translate('avo.key_value_field.add_row')
46
+ I18n.translate("avo.key_value_field.add_row")
47
47
  end
48
48
 
49
49
  def delete_text
50
50
  return @delete_text if @delete_text.present?
51
51
 
52
- I18n.translate('avo.key_value_field.delete_row')
52
+ I18n.translate("avo.key_value_field.delete_row")
53
53
  end
54
54
 
55
55
  def to_permitted_param
@@ -1,6 +1,6 @@
1
1
  require "dry-initializer"
2
2
 
3
- # This object holds some data tha is usually needed to compute blocks around the app.
3
+ # This object holds some data that is usually needed to compute blocks around the app.
4
4
  module Avo
5
5
  module Hosts
6
6
  class BaseHost
@@ -10,6 +10,7 @@ module Avo
10
10
  option :params, default: proc { Avo::App.params }
11
11
  option :view_context, default: proc { Avo::App.view_context }
12
12
  option :current_user, default: proc { Avo::App.current_user }
13
+ # This is optional because we might instantiate the `Host` first and later hydrate it with a block.
13
14
  option :block, optional: true
14
15
 
15
16
  delegate :authorize, to: Avo::Services::AuthorizationService
@@ -7,7 +7,7 @@ module Avo
7
7
 
8
8
  option :context
9
9
  option :range
10
- option :parent
10
+ option :dashboard
11
11
  option :card
12
12
  option :params
13
13
  option :options
@@ -0,0 +1,7 @@
1
+ module Avo
2
+ module Hosts
3
+ class SearchScopeHost < BaseHost
4
+ option :scope
5
+ end
6
+ end
7
+ end
@@ -22,16 +22,24 @@ module Avo
22
22
  def response
23
23
  expire_cache_if_overdue
24
24
 
25
+ # ------------------------------------------------------------------
26
+ # You could set this to true to become a pro user for free.
27
+ # I'd rather you didn't. Avo takes time & love to build,
28
+ # and I can't do that if it doesn't pay my bills!
29
+ #
30
+ # If you want Pro, help pay for its development.
31
+ # Can't afford it? Get in touch: adrian@avohq.io
32
+ # ------------------------------------------------------------------
25
33
  make_request
26
34
  end
27
35
 
28
36
  # Some cache stores don't auto-expire their keys and payloads so we need to do it for them
29
37
  def expire_cache_if_overdue
30
38
  return unless cached_response.present?
31
- return unless cached_response['fetched_at'].present?
39
+ return unless cached_response["fetched_at"].present?
32
40
 
33
41
  allowed_time = 1.hour
34
- parsed_time = Time.parse(cached_response['fetched_at'].to_s)
42
+ parsed_time = Time.parse(cached_response["fetched_at"].to_s)
35
43
  time_has_passed = parsed_time < Time.now - allowed_time
36
44
 
37
45
  clear_response if time_has_passed
@@ -159,7 +167,7 @@ module Avo
159
167
  def perform_request
160
168
  ::Rails.logger.debug "[Avo] Performing request to avohq.io API to check license availability." if Rails.env.development?
161
169
 
162
- HTTParty.post ENDPOINT, body: payload.to_json, headers: {'Content-type': "application/json"}, timeout: REQUEST_TIMEOUT
170
+ HTTParty.post ENDPOINT, body: payload.to_json, headers: {"Content-type": "application/json"}, timeout: REQUEST_TIMEOUT
163
171
  end
164
172
 
165
173
  def app_name
@@ -177,7 +185,7 @@ module Avo
177
185
 
178
186
  {
179
187
  "#{type}_count": type_count,
180
- "#{type}_per_resource": type_per_resource,
188
+ "#{type}_per_resource": type_per_resource
181
189
  }
182
190
  end
183
191
 
@@ -15,6 +15,7 @@ module Avo
15
15
  :dashboards,
16
16
  :menu_editor,
17
17
  :stimulus_js_integration,
18
+ :resource_show_controls,
18
19
  :advanced_fields
19
20
  ]
20
21
  end
@@ -11,6 +11,8 @@ class Avo::Menu::Builder
11
11
  delegate :request, to: ::Avo::App
12
12
  delegate :root_path, to: ::Avo::App
13
13
  delegate :view_context, to: ::Avo::App
14
+ delegate :main_app, to: :view_context
15
+ delegate :avo, to: :view_context
14
16
 
15
17
  def initialize(name: nil, items: [])
16
18
  @menu = Avo::Menu::Menu.new
@@ -0,0 +1,32 @@
1
+ module Avo
2
+ module Resources
3
+ module Controls
4
+ class Action < BaseControl
5
+ attr_reader :klass
6
+
7
+ def initialize(klass, model: nil, resource: nil, view: nil, **args)
8
+ super(**args)
9
+
10
+ @klass = klass
11
+ @resource = resource
12
+ @model = model
13
+ @view = view
14
+ end
15
+
16
+ def action
17
+ return @instance if @instance.present?
18
+
19
+ @instance = @klass.new(model: @model, resource: @resource, view: @view)
20
+ end
21
+
22
+ def path
23
+ Avo::Services::URIService.parse(@resource.record_path).append_paths("actions", action.param_id).to_s
24
+ end
25
+
26
+ def label
27
+ @args[:label] || action.action_name
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ module Avo
2
+ module Resources
3
+ module Controls
4
+ class ActionsList < BaseControl
5
+ def exclude
6
+ Array.wrap(@args[:exclude]) || []
7
+ end
8
+
9
+ def color
10
+ @args[:color] || :primary
11
+ end
12
+
13
+ def style
14
+ @args[:style] || :outline
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module Avo
2
+ module Resources
3
+ module Controls
4
+ class BackButton < BaseControl
5
+ def initialize(**args)
6
+ super(**args)
7
+
8
+ @label = I18n.t("avo.go_back")
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,59 @@
1
+ module Avo
2
+ module Resources
3
+ module Controls
4
+ class BaseControl
5
+ def initialize(**args)
6
+ @args = args
7
+ end
8
+
9
+ def label
10
+ @args[:label] || @label
11
+ end
12
+
13
+ def title
14
+ @args[:title]
15
+ end
16
+
17
+ def color
18
+ @args[:color] || :gray
19
+ end
20
+
21
+ def style
22
+ @args[:style] || :text
23
+ end
24
+
25
+ def icon
26
+ @args[:icon] || nil
27
+ end
28
+
29
+ def back_button?
30
+ is_a? Avo::Resources::Controls::BackButton
31
+ end
32
+
33
+ def edit_button?
34
+ is_a? Avo::Resources::Controls::EditButton
35
+ end
36
+
37
+ def delete_button?
38
+ is_a? Avo::Resources::Controls::DeleteButton
39
+ end
40
+
41
+ def actions_list?
42
+ is_a? Avo::Resources::Controls::ActionsList
43
+ end
44
+
45
+ def link_to?
46
+ is_a? Avo::Resources::Controls::LinkTo
47
+ end
48
+
49
+ def detach_button?
50
+ is_a? Avo::Resources::Controls::DetachButton
51
+ end
52
+
53
+ def action?
54
+ is_a? Avo::Resources::Controls::Action
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,13 @@
1
+ module Avo
2
+ module Resources
3
+ module Controls
4
+ class DeleteButton < BaseControl
5
+ def initialize(**args)
6
+ super(**args)
7
+
8
+ @label = I18n.t("avo.delete").capitalize
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Avo
2
+ module Resources
3
+ module Controls
4
+ class DetachButton < BaseControl
5
+ def initialize(**args)
6
+ super(**args)
7
+
8
+ @label = I18n.t("avo.detach_item", item: title).capitalize
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Avo
2
+ module Resources
3
+ module Controls
4
+ class EditButton < BaseControl
5
+ def initialize(**args)
6
+ super(**args)
7
+
8
+ @label = I18n.t("avo.edit").capitalize
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,58 @@
1
+ require "dry-initializer"
2
+
3
+ # This object holds some data tha is usually needed to compute blocks around the app.
4
+ module Avo
5
+ module Resources
6
+ module Controls
7
+ class ExecutionContext
8
+ extend Dry::Initializer
9
+
10
+ option :context, default: proc { Avo::App.context }
11
+ option :params, default: proc { Avo::App.params }
12
+ option :view_context, default: proc { Avo::App.view_context }
13
+ option :current_user, default: proc { Avo::App.current_user }
14
+ option :items_holder, default: proc { Avo::Resources::Controls::ItemsHolder.new }
15
+ option :resource, optional: true
16
+ option :record, optional: true
17
+ option :view, optional: true
18
+ option :block, optional: true
19
+
20
+ delegate :authorize, to: Avo::Services::AuthorizationService
21
+
22
+ def handle
23
+ instance_exec(&block)
24
+ end
25
+
26
+ private
27
+
28
+ def back_button(**args)
29
+ items_holder.add_item Avo::Resources::Controls::BackButton.new(**args)
30
+ end
31
+
32
+ def delete_button(**args)
33
+ items_holder.add_item Avo::Resources::Controls::DeleteButton.new(**args)
34
+ end
35
+
36
+ def detach_button(**args)
37
+ items_holder.add_item Avo::Resources::Controls::DetachButton.new(**args)
38
+ end
39
+
40
+ def edit_button(**args)
41
+ items_holder.add_item Avo::Resources::Controls::EditButton.new(**args)
42
+ end
43
+
44
+ def link_to(label, path, **args)
45
+ items_holder.add_item Avo::Resources::Controls::LinkTo.new(label: label, path: path, **args)
46
+ end
47
+
48
+ def actions_list(**args)
49
+ items_holder.add_item Avo::Resources::Controls::ActionsList.new(**args)
50
+ end
51
+
52
+ def action(klass, **args)
53
+ items_holder.add_item Avo::Resources::Controls::Action.new(klass, record: record, resource: resource, view: view, **args)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,19 @@
1
+ module Avo
2
+ module Resources
3
+ module Controls
4
+ class ItemsHolder
5
+ attr_reader :items
6
+
7
+ def initialize
8
+ @items = []
9
+ end
10
+
11
+ def add_item(instance)
12
+ @items << instance
13
+
14
+ self
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module Avo
2
+ module Resources
3
+ module Controls
4
+ class LinkTo < BaseControl
5
+ def initialize(**args)
6
+ super(**args)
7
+ end
8
+
9
+ def path
10
+ @args[:path]
11
+ end
12
+
13
+ def target
14
+ @args[:target] || nil
15
+ end
16
+
17
+ def data
18
+ @args[:data] || {}
19
+ end
20
+
21
+ def class
22
+ @args[:class] || nil
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
data/lib/avo/tab.rb CHANGED
@@ -13,7 +13,7 @@ class Avo::Tab
13
13
 
14
14
  def initialize(name: nil, description: nil, view: nil, holds_one_field: false, **args)
15
15
  # Initialize the visibility markers
16
- # super
16
+ super
17
17
 
18
18
  @name = name
19
19
  @description = description
@@ -25,8 +25,6 @@ class Avo::Tab
25
25
  hide_on args[:hide_on] if args[:hide_on].present?
26
26
  only_on args[:only_on] if args[:only_on].present?
27
27
  except_on args[:except_on] if args[:except_on].present?
28
-
29
- initialize_visibility args
30
28
  end
31
29
 
32
30
  def hydrate(view: nil)
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.11.3.pre.3" unless const_defined?(:VERSION)
2
+ VERSION = "2.13.0" unless const_defined?(:VERSION)
3
3
  end
@@ -1,5 +1,5 @@
1
1
  class <%= class_name.camelize %> < Avo::BaseAction
2
- self.name = '<%= name.underscore.humanize %>'
2
+ self.name = "<%= name.underscore.humanize %>"
3
3
 
4
4
  def handle(**args)
5
5
  models, fields, current_user, resource = args.values_at(:models, :fields, :current_user, :resource)
@@ -1,6 +1,6 @@
1
1
  <div class="flex-1 flex p-4">
2
2
  <div class="place-self-end">
3
- Parent ID: <%%= @parent.id %>
3
+ Dashboard ID: <%%= @dashboard.id %>
4
4
  <br />
5
5
  <br />
6
6
  Customize this partial under <code class='p-1 rounded bg-gray-500 text-white text-sm'>app/views/avo/cards/_<%= name.underscore %>.html.erb</code>
@@ -51,6 +51,7 @@ Avo.configure do |config|
51
51
  # config.view_component_path = "app/components"
52
52
  # config.display_license_request_timeout_error = true
53
53
  # config.disabled_features = []
54
+ # config.resource_controls = :right
54
55
 
55
56
 
56
57
  ## == Breadcrumbs ==
@@ -1,7 +1,7 @@
1
1
  class <%= resource_class %> < Avo::BaseResource
2
2
  self.title = :id
3
3
  self.includes = []
4
- # self.search_query = ->(params:) do
4
+ # self.search_query = -> do
5
5
  # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false)
6
6
  # end
7
7
 
@@ -1,7 +1,7 @@
1
1
  <div class="flex flex-col">
2
2
  <%%= render Avo::PanelComponent.new(name: "<%= human_name %>") do |c| %>
3
3
  <%% c.tools do %>
4
- <%%= a_link('/avo', icon: 'heroicons/solid/academic-cap', style: :primary) do %>
4
+ <%%= a_link('/avo', icon: 'heroicons/solid/academic-cap', color: :primary, style: :primary) do %>
5
5
  Dummy link
6
6
  <%% end %>
7
7
  <%% end %>
@@ -1,5 +1,5 @@
1
1
  class <%= class_name.camelize %> < Avo::BaseAction
2
- self.name = '<%= name.underscore.humanize %>'
2
+ self.name = "<%= name.underscore.humanize %>"
3
3
  self.standalone = true
4
4
 
5
5
  def handle(fields:)