avo 3.0.1.beta2 → 3.0.1.beta4

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2032ff971d1b4fadddfd033ccc539b722d4296b766840575f71cf1edde3d5b33
4
- data.tar.gz: eab6052b7a291a942a1871badbdb76f18b8797ec6b9e791d9ec7a51316705abe
3
+ metadata.gz: 737f7485e4fbc1d44c4241c0f39010b74d078f58e0cc06279223bb81e9878079
4
+ data.tar.gz: b19cc62af7812c430274e0f0b002843a7601ef16e81fa32b0dfc2ae8d96ca304
5
5
  SHA512:
6
- metadata.gz: 8789e31fd450e04667412526084899ae175bcee356cd3d9f33a396610e773cadfa83294a2aeb7c800f527f94d77fdd0d4236073373af4544cd33141e61478bf6
7
- data.tar.gz: c2b5d6df49088c094d0499e039de9793a1e8f2d37a7ddc9db0489b95ec8fec29594dbe6167ac7cd7361ab6f43198c613face277b59466480fa1122124bc1b5ec
6
+ metadata.gz: 995a9e1a12c9bce7368abdc7fb6b5cae46dff35603f3d7b51e4942a730d4f314f52fbfd04ee38948b3c919d3bf25440131559b5bed3a5af7331b608c50ef69d0
7
+ data.tar.gz: 8491c4c0b5a55144ee300574788591c45596b9b97e193e26688f01e8b319f0895eff3b3b55e9c7dca74bf18021f0cb00180f7d624bf22d4e7690daae1456c096
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (3.0.1.beta2)
4
+ avo (3.0.1.beta4)
5
5
  actionview (>= 6.1)
6
6
  active_link_to
7
7
  activerecord (>= 6.1)
@@ -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| %>
@@ -75,6 +75,8 @@ module Avo
75
75
  @resources = @records.map do |record|
76
76
  @resource.hydrate(record: record, params: params).dup
77
77
  end
78
+
79
+ set_component_for __method__
78
80
  end
79
81
 
80
82
  def show
@@ -98,6 +100,8 @@ module Avo
98
100
 
99
101
  add_breadcrumb @resource.record_title
100
102
  add_breadcrumb I18n.t("avo.details").upcase_first
103
+
104
+ set_component_for __method__
101
105
  end
102
106
 
103
107
  def new
@@ -119,6 +123,8 @@ module Avo
119
123
 
120
124
  add_breadcrumb @resource.plural_name.humanize, resources_path(resource: @resource)
121
125
  add_breadcrumb t("avo.new").humanize
126
+
127
+ set_component_for __method__, fallback_view: :edit
122
128
  end
123
129
 
124
130
  def create
@@ -161,6 +167,8 @@ module Avo
161
167
  add_breadcrumb t("avo.new").humanize
162
168
  set_actions
163
169
 
170
+ set_component_for :edit
171
+
164
172
  if saved
165
173
  create_success_action
166
174
  else
@@ -170,6 +178,8 @@ module Avo
170
178
 
171
179
  def edit
172
180
  set_actions
181
+
182
+ set_component_for __method__
173
183
  end
174
184
 
175
185
  def update
@@ -178,6 +188,8 @@ module Avo
178
188
  @resource = @resource.hydrate(record: @record, view: :edit, user: _current_user)
179
189
  set_actions
180
190
 
191
+ set_component_for :edit
192
+
181
193
  if saved
182
194
  update_success_action
183
195
  else
@@ -540,5 +552,31 @@ module Avo
540
552
  def pagy_query
541
553
  @query
542
554
  end
555
+
556
+ # Set the view component for the current view
557
+ # It will try to use the custom component if it's set, otherwise it will use the default one
558
+ def set_component_for(view, fallback_view: nil)
559
+ # Fetch the components from the resource
560
+ components = Avo::ExecutionContext.new(
561
+ target: @resource.components,
562
+ resource: @resource,
563
+ record: @record,
564
+ view: @view
565
+ ).handle
566
+
567
+ # If the component is not set, use the default one
568
+ if (custom_component = components.dig("resource_#{view}_component".to_sym)).nil?
569
+ return @component = "Avo::Views::Resource#{(fallback_view || view).to_s.classify}Component".constantize
570
+ end
571
+
572
+ # If the component is set, try to use it
573
+ @component = custom_component.to_s.safe_constantize
574
+
575
+ # If the component is not found, raise an error
576
+ if @component.nil?
577
+ raise "The component '#{custom_component}' was not found.\n" \
578
+ "That component was fetched from 'self.components' option inside '#{@resource.class}' resource."
579
+ end
580
+ end
543
581
  end
544
582
  end
@@ -38,7 +38,7 @@ module Avo
38
38
  end
39
39
 
40
40
  def item_selector_init(resource)
41
- "data-resource-name='#{resource.model_key}' data-resource-id='#{resource.record.id}' data-controller='item-selector'"
41
+ "data-resource-name='#{resource.model_key}' data-resource-id='#{resource.record.to_param}' data-controller='item-selector'"
42
42
  end
43
43
 
44
44
  def item_selector_input(floating: false, size: :md)
@@ -21,7 +21,7 @@
21
21
  <%= @action.get_message %>
22
22
  </div>
23
23
  <%= hidden_field_tag :action_id, @action.param_id %>
24
- <%= form.hidden_field :avo_resource_ids, value: params[:id] || params[:resource_ids], 'data-action-target': 'resourceIds' %>
24
+ <%= form.hidden_field :avo_resource_ids, value: params[:resource_ids], 'data-action-target': 'resourceIds' %>
25
25
  <%= form.hidden_field :avo_selected_query, 'data-action-target': 'selectedAllQuery' %>
26
26
  <%= form.hidden_field :arguments, value: params[:arguments] %>
27
27
  <% if @action.get_fields.present? %>
@@ -1 +1 @@
1
- <%= render Avo::Views::ResourceEditComponent.new(resource: @resource, view: @view, actions: @actions) %>
1
+ <%= render @component.new(resource: @resource, view: @view, actions: @actions) %>
@@ -1,5 +1,5 @@
1
1
  <%= render Avo::TurboFrameWrapperComponent.new(params[:turbo_frame]) do %>
2
- <%= render Avo::Views::ResourceIndexComponent.new(
2
+ <%= render @component.new(
3
3
  resource: @resource,
4
4
  resources: @resources,
5
5
  records: @records,
@@ -1,2 +1,2 @@
1
- <%= render Avo::Views::ResourceEditComponent.new(resource: @resource, record: @record, view: @view, actions: @actions) %>
1
+ <%= render @component.new(resource: @resource, record: @record, view: @view, actions: @actions) %>
2
2
 
@@ -1,5 +1,5 @@
1
1
  <%= render Avo::TurboFrameWrapperComponent.new(params[:turbo_frame]) do %>
2
- <%= render Avo::Views::ResourceShowComponent.new(
2
+ <%= render @component.new(
3
3
  resource: @resource,
4
4
  reflection: @reflection,
5
5
  actions: @actions,
@@ -65,6 +65,7 @@ module Avo
65
65
  class_attribute :extra_params
66
66
  class_attribute :link_to_child_resource, default: false
67
67
  class_attribute :map_view
68
+ class_attribute :components, default: {}
68
69
 
69
70
  # EXTRACT:
70
71
  class_attribute :ordering
@@ -293,7 +294,11 @@ module Avo
293
294
 
294
295
  # def get_action_arguments / def get_filter_arguments / def get_scope_arguments
295
296
  define_method "get_#{entity}_arguments" do |entity_class|
296
- send("get_#{plural_entity}").find { |entity| entity[:class].to_s == entity_class.to_s }[:arguments]
297
+ klass = send("get_#{plural_entity}").find { |entity| entity[:class].to_s == entity_class.to_s }
298
+
299
+ raise "Couldn't find '#{entity_class}' in the 'def #{plural_entity}' method on your '#{self.class}' resource." if klass.nil?
300
+
301
+ klass[:arguments]
297
302
  end
298
303
  end
299
304
 
@@ -43,6 +43,7 @@ module Avo
43
43
  attr_accessor :sign_out_path_name
44
44
  attr_accessor :resources
45
45
  attr_accessor :prefix_path
46
+ attr_accessor :resource_parent_controller
46
47
 
47
48
  def initialize
48
49
  @root_path = "/avo"
@@ -93,6 +94,7 @@ module Avo
93
94
  @authorization_client = :pundit
94
95
  @field_wrapper_layout = :inline
95
96
  @resources = nil
97
+ @resource_parent_controller = "Avo::ResourcesController"
96
98
  end
97
99
 
98
100
  def current_user_method(&block)
@@ -47,7 +47,7 @@ module Avo
47
47
  else
48
48
  # The symbol can be transformed to a class and found.
49
49
  class_name = as.to_s.camelize
50
- field_class = "#{class_name}Field"
50
+ field_class = "Avo::Fields::#{class_name}Field"
51
51
 
52
52
  # Discover & load custom field classes
53
53
  if Object.const_defined? field_class
@@ -11,6 +11,9 @@ module Avo
11
11
  CommunityLicense.new @hq_response
12
12
  when "pro"
13
13
  ProLicense.new @hq_response
14
+ # temporary fix
15
+ when "advanced"
16
+ ProLicense.new @hq_response
14
17
  else
15
18
  NilLicense.new @hq_response
16
19
  end
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "3.0.1.beta2" unless const_defined?(:VERSION)
2
+ VERSION = "3.0.1.beta4" unless const_defined?(:VERSION)
3
3
  end
@@ -0,0 +1,20 @@
1
+ module Generators
2
+ module Avo
3
+ module Concerns
4
+ module ParentController
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_option "parent-controller",
9
+ desc: "The name of the parent controller.",
10
+ type: :string,
11
+ required: false
12
+ end
13
+
14
+ def parent_controller
15
+ options["parent-controller"] || ::Avo.configuration.resource_parent_controller
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,8 +1,11 @@
1
1
  require_relative "named_base_generator"
2
+ require_relative "concerns/parent_controller"
2
3
 
3
4
  module Generators
4
5
  module Avo
5
6
  class ControllerGenerator < NamedBaseGenerator
7
+ include Generators::Avo::Concerns::ParentController
8
+
6
9
  source_root File.expand_path("templates", __dir__)
7
10
 
8
11
  namespace "avo:controller"
@@ -3,7 +3,20 @@ require_relative "base_generator"
3
3
  module Generators
4
4
  module Avo
5
5
  class EjectGenerator < BaseGenerator
6
- argument :filename, type: :string, required: true
6
+ class_option :partial,
7
+ desc: "The partial to eject. Example: ':logo', 'app/views/layouts/avo/application.html.erb'",
8
+ type: :string,
9
+ required: false
10
+
11
+ class_option :component,
12
+ desc: "The component to eject. Example: 'Avo::Index::TableRowComponent', 'avo/index/table_row_component'",
13
+ type: :string,
14
+ required: false
15
+
16
+ class_option :scope,
17
+ desc: "The scope of the component. Example: 'users', 'admins'",
18
+ type: :string,
19
+ required: false
7
20
 
8
21
  source_root ::Avo::Engine.root
9
22
 
@@ -21,19 +34,18 @@ module Generators
21
34
  }
22
35
 
23
36
  def handle
24
- if @filename.starts_with?(":")
25
- template_id = path_to_sym @filename
26
- template_path = TEMPLATES[template_id]
27
-
28
- if path_exists? template_path
29
- eject template_path
30
- else
31
- say("Failed to find the `#{template_id.to_sym}` template.", :yellow)
32
- end
33
- elsif path_exists? @filename
34
- eject @filename
37
+ if options[:partial].present?
38
+ eject_partial
39
+ elsif options[:component].present?
40
+ eject_component
35
41
  else
36
- say("Failed to find the `#{@filename}` template.", :yellow)
42
+ say "Please specify a partial or a component to eject.\n" \
43
+ "Examples: rails g avo:eject --partial :logo\n" \
44
+ " rails g avo:eject --partial app/views/layouts/avo/application.html.erb\n" \
45
+ " rails g avo:eject --component Avo::Index::TableRowComponent\n" \
46
+ " rails g avo:eject --component avo/index/table_row_component\n" \
47
+ " rails g avo:eject --component Avo::Views::ResourceIndexComponent --scope users\n" \
48
+ " rails g avo:eject --component avo/views/resource_index_component --scope users", :yellow
37
49
  end
38
50
  end
39
51
 
@@ -48,8 +60,84 @@ module Generators
48
60
  path.present? && File.file?(::Avo::Engine.root.join(path))
49
61
  end
50
62
 
51
- def eject(path)
52
- copy_file ::Avo::Engine.root.join(path), ::Rails.root.join(path)
63
+ def eject(path, dest_path = nil)
64
+ copy_file ::Avo::Engine.root.join(path), ::Rails.root.join(dest_path || path)
65
+ end
66
+
67
+ def eject_partial
68
+ if options[:partial].starts_with?(":")
69
+ template_id = path_to_sym options[:partial]
70
+ template_path = TEMPLATES[template_id]
71
+
72
+ if path_exists? template_path
73
+ return unless confirm_ejection_on template_path
74
+ eject template_path
75
+ else
76
+ say("Failed to find the `#{template_id.to_sym}` template.", :yellow)
77
+ end
78
+ elsif path_exists? options[:partial]
79
+ return unless confirm_ejection_on template_path
80
+ eject options[:partial]
81
+ else
82
+ say("Failed to find the `#{options[:partial]}` template.", :yellow)
83
+ end
84
+ end
85
+
86
+ def eject_component
87
+ # Underscore the component name
88
+ # Example: Avo::Views::ResourceIndexComponent => avo/views/resource_index_component
89
+ component = options[:component].underscore
90
+
91
+ # Get the component path for both, the rb and erb files
92
+ rb, erb = ["app/components/#{component}.rb", "app/components/#{component}.html.erb"]
93
+
94
+ # Return if one of the components doesn't exist
95
+ if !path_exists?(rb) || !path_exists?(erb)
96
+ return say("Failed to find the `#{options[:component]}` component.", :yellow)
97
+ end
98
+
99
+ # Add the scope to the component if it's possible
100
+ if add_scope? component
101
+ component = component.gsub("avo/views/", "avo/views/#{options[:scope]}/")
102
+ added_scope = true
103
+ end
104
+
105
+ # Confirm the ejection
106
+ return unless confirm_ejection_on component.camelize
107
+
108
+ # Get the destination path for both, the rb and erb files
109
+ dest_rb = "#{::Avo.configuration.view_component_path}/#{component}.rb"
110
+ dest_erb = "#{::Avo.configuration.view_component_path}/#{component}.html.erb"
111
+
112
+ # Eject the component
113
+ eject rb, dest_rb
114
+ eject erb, dest_erb
115
+
116
+ # Remame the component class if scope was added
117
+ # Example: Avo::Views::ResourceIndexComponent => Avo::Views::Admins::ResourceIndexComponent
118
+ if added_scope
119
+ [dest_rb, dest_erb].each do |path|
120
+ modified_content = File.read(path).gsub("Avo::Views::", "Avo::Views::#{options[:scope].camelize}::")
121
+
122
+ File.open(path, "w") do |file|
123
+ file.puts modified_content
124
+ end
125
+ end
126
+
127
+ say "You can now use this component on any resource by configuring the 'self.components' option.\n" \
128
+ " self.components = {\n" \
129
+ " #{component.split("/").last}: #{component.camelize}\n" \
130
+ " }", :green
131
+ end
132
+ end
133
+
134
+ def confirm_ejection_on(path)
135
+ say("By ejecting the '#{path}' \033[1myou'll take on the responsibility for maintain it.", :yellow)
136
+ yes?("Are you sure you want to eject the '#{path}'? [y/N]", :yellow)
137
+ end
138
+
139
+ def add_scope?(component)
140
+ component.starts_with?("avo/views/") && options[:scope].present?
53
141
  end
54
142
  end
55
143
  end
@@ -8,9 +8,56 @@ module Generators
8
8
  namespace "avo:field"
9
9
  desc "Add a custom Avo field to your project."
10
10
 
11
+ class_option "field-template", type: :string, required: false
12
+
11
13
  def handle
12
- directory "field/components", "#{::Avo.configuration.view_component_path}/avo/fields/#{singular_name}_field"
13
- template "field/%singular_name%_field.rb.tt", "app/avo/fields/#{singular_name}_field.rb"
14
+ return field_from_template if field_template.present?
15
+
16
+ directory "field/components", destination_components_path
17
+ template "field/%singular_name%_field.rb.tt", destination_field_path
18
+ end
19
+
20
+ no_tasks do
21
+ def field_from_template
22
+ if !File.file? ::Avo::Engine.root.join(template_field_path)
23
+ return say("Failed to find the `#{field_template}` template field.", :yellow)
24
+ end
25
+
26
+ if !Dir.exist? ::Avo::Engine.root.join(template_components_path)
27
+ return say("Failed to find the `#{field_template}` template field components.", :yellow)
28
+ end
29
+
30
+ directory ::Avo::Engine.root.join(template_components_path), destination_components_path
31
+ copy_file ::Avo::Engine.root.join(template_field_path), destination_field_path
32
+
33
+ Dir.glob("#{destination_components_path}/*").push(destination_field_path).each do |file|
34
+ modified_content = File.read(file).gsub("#{field_template.camelize}Field", "#{singular_name.camelize}Field")
35
+
36
+ File.open(file, "w") do |open_file|
37
+ open_file.puts modified_content
38
+ end
39
+ end
40
+ end
41
+
42
+ def field_template
43
+ options["field-template"]
44
+ end
45
+
46
+ def template_field_path
47
+ "lib/avo/fields/#{field_template}_field.rb"
48
+ end
49
+
50
+ def template_components_path
51
+ "app/components/avo/fields/#{field_template}_field"
52
+ end
53
+
54
+ def destination_components_path
55
+ "#{::Avo.configuration.view_component_path}/avo/fields/#{singular_name}_field"
56
+ end
57
+
58
+ def destination_field_path
59
+ "app/avo/fields/#{singular_name}_field.rb"
60
+ end
14
61
  end
15
62
  end
16
63
  end
@@ -1,16 +1,19 @@
1
1
  require_relative "named_base_generator"
2
+ require_relative "concerns/parent_controller"
2
3
 
3
4
  module Generators
4
5
  module Avo
5
6
  class ResourceGenerator < NamedBaseGenerator
7
+ include Generators::Avo::Concerns::ParentController
8
+
6
9
  source_root File.expand_path("templates", __dir__)
7
10
 
8
11
  namespace "avo:resource"
9
12
 
10
13
  class_option "model-class",
14
+ desc: "The name of the model.",
11
15
  type: :string,
12
- required: false,
13
- desc: "The name of the model."
16
+ required: false
14
17
 
15
18
  def create
16
19
  template "resource/resource.tt", "app/avo/resources/#{resource_name}.rb"
@@ -66,6 +66,7 @@ Avo.configure do |config|
66
66
  # config.disabled_features = []
67
67
  # config.buttons_on_form_footers = true
68
68
  # config.field_wrapper_layout = true
69
+ # config.resource_parent_controller = "Avo::ResourcesController"
69
70
 
70
71
  ## == Branding ==
71
72
  # config.branding = {
@@ -1,4 +1,4 @@
1
1
  # This controller has been generated to enable Rails' resource routes.
2
2
  # More information on https://docs.avohq.io/2.0/controllers.html
3
- class <%= controller_class %> < Avo::ResourcesController
3
+ class <%= controller_class %> < <%= parent_controller %>
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avo
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1.beta2
4
+ version: 3.0.1.beta4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Marin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-08-07 00:00:00.000000000 Z
12
+ date: 2023-08-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -1846,6 +1846,7 @@ files:
1846
1846
  - lib/generators/avo/action_generator.rb
1847
1847
  - lib/generators/avo/base_generator.rb
1848
1848
  - lib/generators/avo/card_generator.rb
1849
+ - lib/generators/avo/concerns/parent_controller.rb
1849
1850
  - lib/generators/avo/controller_generator.rb
1850
1851
  - lib/generators/avo/dashboard_generator.rb
1851
1852
  - lib/generators/avo/eject_generator.rb