avo 3.0.0.pre12 → 3.0.0.pre14

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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +2 -1
  4. data/app/assets/stylesheets/avo.base.css +1 -1
  5. data/app/components/avo/actions_component.html.erb +1 -1
  6. data/app/components/avo/actions_component.rb +40 -16
  7. data/app/components/avo/alert_component.html.erb +1 -1
  8. data/app/components/avo/base_component.rb +7 -7
  9. data/app/components/avo/field_wrapper_component.html.erb +2 -2
  10. data/app/components/avo/field_wrapper_component.rb +1 -1
  11. data/app/components/avo/fields/area_field/edit_component.html.erb +1 -1
  12. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +5 -5
  13. data/app/components/avo/fields/belongs_to_field/edit_component.rb +4 -4
  14. data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -0
  15. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
  16. data/app/components/avo/fields/code_field/edit_component.html.erb +1 -0
  17. data/app/components/avo/fields/common/heading_component.html.erb +1 -1
  18. data/app/components/avo/fields/country_field/edit_component.html.erb +1 -0
  19. data/app/components/avo/fields/file_field/index_component.rb +2 -2
  20. data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -0
  21. data/app/components/avo/fields/index_component.rb +1 -0
  22. data/app/components/avo/fields/location_field/show_component.html.erb +1 -1
  23. data/app/components/avo/fields/markdown_field/edit_component.html.erb +4 -3
  24. data/app/components/avo/fields/markdown_field/show_component.html.erb +3 -3
  25. data/app/components/avo/fields/number_field/edit_component.html.erb +1 -0
  26. data/app/components/avo/fields/password_field/edit_component.html.erb +1 -0
  27. data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +1 -0
  28. data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
  29. data/app/components/avo/fields/text_field/edit_component.html.erb +1 -1
  30. data/app/components/avo/fields/textarea_field/edit_component.html.erb +1 -0
  31. data/app/components/avo/fields/trix_field/edit_component.html.erb +2 -1
  32. data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
  33. data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
  34. data/app/components/avo/index/grid_item_component.html.erb +9 -35
  35. data/app/components/avo/index/grid_item_component.rb +36 -10
  36. data/app/components/avo/index/resource_controls_component.rb +6 -6
  37. data/app/components/avo/item_switcher_component.html.erb +9 -4
  38. data/app/components/avo/item_switcher_component.rb +2 -1
  39. data/app/components/avo/panel_component.html.erb +1 -1
  40. data/app/components/avo/profile_item_component.html.erb +17 -2
  41. data/app/components/avo/profile_item_component.rb +13 -1
  42. data/app/components/avo/resource_component.rb +6 -3
  43. data/app/components/avo/resource_sidebar_component.rb +1 -1
  44. data/app/components/avo/row_component.html.erb +3 -0
  45. data/app/components/avo/row_component.rb +12 -0
  46. data/app/components/avo/sidebar/link_component.html.erb +2 -0
  47. data/app/components/avo/sidebar/link_component.rb +5 -3
  48. data/app/components/avo/sidebar_component.html.erb +3 -3
  49. data/app/components/avo/sidebar_component.rb +4 -4
  50. data/app/components/avo/sidebar_profile_component.html.erb +27 -27
  51. data/app/components/avo/views/resource_edit_component.rb +1 -1
  52. data/app/components/avo/views/resource_index_component.html.erb +1 -1
  53. data/app/components/avo/views/resource_index_component.rb +8 -8
  54. data/app/controllers/avo/actions_controller.rb +22 -8
  55. data/app/controllers/avo/application_controller.rb +71 -66
  56. data/app/controllers/avo/associations_controller.rb +4 -6
  57. data/app/controllers/avo/attachments_controller.rb +1 -1
  58. data/app/controllers/avo/base_controller.rb +36 -17
  59. data/app/controllers/avo/home_controller.rb +1 -1
  60. data/app/controllers/avo/search_controller.rb +18 -20
  61. data/app/controllers/concerns/avo/initializes_avo.rb +2 -5
  62. data/app/javascript/js/controllers/fields/{simple_mde_controller.js → easy_mde_controller.js} +4 -3
  63. data/app/javascript/js/controllers/search_controller.js +3 -1
  64. data/app/javascript/js/controllers.js +2 -2
  65. data/app/views/avo/actions/show.html.erb +2 -1
  66. data/app/views/avo/associations/new.html.erb +1 -1
  67. data/app/views/avo/debug/status.html.erb +1 -1
  68. data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
  69. data/app/views/avo/partials/_footer.html.erb +1 -1
  70. data/app/views/avo/partials/_javascript.html.erb +1 -1
  71. data/app/views/avo/partials/_navbar.html.erb +1 -1
  72. data/app/views/avo/partials/_profile_menu_extra.html.erb +2 -0
  73. data/app/views/layouts/avo/application.html.erb +2 -2
  74. data/avo.gemspec +1 -0
  75. data/config/initializers/pagy.rb +12 -10
  76. data/config/routes.rb +3 -3
  77. data/db/factories.rb +2 -1
  78. data/lib/avo/base_action.rb +12 -2
  79. data/lib/avo/base_resource.rb +178 -178
  80. data/lib/avo/concerns/filters_session_handler.rb +0 -1
  81. data/lib/avo/concerns/has_item_type.rb +4 -0
  82. data/lib/avo/concerns/has_items.rb +28 -23
  83. data/lib/avo/concerns/model_class_constantized.rb +0 -2
  84. data/lib/avo/configuration.rb +6 -2
  85. data/lib/avo/current.rb +22 -1
  86. data/lib/avo/dsl/field_parser.rb +1 -1
  87. data/lib/avo/dynamic_router.rb +12 -1
  88. data/lib/avo/engine.rb +8 -6
  89. data/lib/avo/fields/base_field.rb +25 -7
  90. data/lib/avo/fields/belongs_to_field.rb +20 -13
  91. data/lib/avo/fields/concerns/is_searchable.rb +1 -1
  92. data/lib/avo/fields/concerns/use_resource.rb +1 -1
  93. data/lib/avo/fields/field_manager.rb +13 -3
  94. data/lib/avo/fields/has_base_field.rb +5 -5
  95. data/lib/avo/fields/has_one_field.rb +1 -1
  96. data/lib/avo/fields/location_field.rb +18 -1
  97. data/lib/avo/licensing/h_q.rb +11 -6
  98. data/lib/avo/licensing/license.rb +1 -1
  99. data/lib/avo/licensing/license_manager.rb +1 -1
  100. data/lib/avo/licensing/{null_license.rb → nil_license.rb} +1 -1
  101. data/lib/avo/loaders/fields_loader.rb +7 -1
  102. data/lib/avo/plugin_manager.rb +2 -4
  103. data/lib/avo/reloader.rb +1 -1
  104. data/lib/avo/resources/controls/actions_list.rb +2 -1
  105. data/lib/avo/resources/items/holder.rb +5 -1
  106. data/lib/avo/resources/items/item_group.rb +1 -0
  107. data/lib/avo/resources/items/row.rb +54 -0
  108. data/lib/avo/resources/resource_manager.rb +4 -7
  109. data/lib/avo/services/debug_service.rb +6 -6
  110. data/lib/avo/services/telemetry_service.rb +3 -3
  111. data/lib/avo/version.rb +1 -1
  112. data/lib/avo.rb +107 -25
  113. data/lib/generators/avo/action_generator.rb +8 -8
  114. data/lib/generators/avo/card_generator.rb +27 -0
  115. data/lib/generators/avo/eject_generator.rb +1 -0
  116. data/lib/generators/avo/filter_generator.rb +8 -8
  117. data/lib/generators/avo/install_generator.rb +0 -1
  118. data/lib/generators/avo/resource_generator.rb +4 -1
  119. data/lib/generators/avo/templates/action.tt +3 -3
  120. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  121. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  122. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  123. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  124. data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
  125. data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
  126. data/lib/generators/avo/templates/dashboards/dashboard.tt +1 -1
  127. data/lib/generators/avo/templates/resource/resource.tt +3 -4
  128. data/lib/generators/avo/templates/scope.tt +1 -1
  129. data/lib/tasks/avo_tasks.rake +1 -1
  130. data/public/avo-assets/avo.base.css +295 -165
  131. data/public/avo-assets/avo.base.js +307 -278
  132. data/public/avo-assets/avo.base.js.map +3 -3
  133. metadata +23 -10
  134. data/lib/avo/app.rb +0 -170
  135. data/lib/avo/grid_collector.rb +0 -40
  136. data/lib/generators/avo/card/chartkick_generator.rb +0 -18
  137. data/lib/generators/avo/card/metric_generator.rb +0 -18
  138. data/lib/generators/avo/card/partial_generator.rb +0 -19
  139. data/lib/generators/avo/templates/standalone_action.tt +0 -15
@@ -6,7 +6,7 @@ module Avo
6
6
  end
7
7
 
8
8
  def method_missing(method, *args, &block)
9
- matched_field = Avo::App.fields.find do |field|
9
+ matched_field = Avo.field_manager.find do |field|
10
10
  field[:name].to_s == method.to_s
11
11
  end
12
12
 
@@ -22,6 +22,12 @@ module Avo
22
22
  add_field field
23
23
  end
24
24
  end
25
+
26
+ def respond_to_missing?(method)
27
+ Avo.field_manager.find do |field|
28
+ field[:name].to_s == method.to_s
29
+ end
30
+ end
25
31
  end
26
32
  end
27
33
  end
@@ -25,15 +25,13 @@ module Avo
25
25
  end
26
26
 
27
27
  def register_field(method_name, klass)
28
- Avo::App.fields.load_field method_name, klass
28
+ Avo.field_manager.load_field method_name, klass
29
29
  end
30
30
 
31
31
  def register_resource_tool
32
- # puts ["register_resource_tool->"].inspect
33
32
  end
34
33
 
35
34
  def register_tool
36
- # puts ["register_tool->"].inspect
37
35
  end
38
36
 
39
37
  def as_json(*arg)
@@ -47,7 +45,7 @@ module Avo
47
45
 
48
46
  def installed?(name)
49
47
  plugins.any? do |plugin|
50
- plugin.klass.to_s.split("::").first.underscore == name.to_s || plugin.klass.to_s.split("::").first == name.to_s
48
+ plugin.klass.to_s.chomp("::Plugin").underscore.tr("/", "-") == name.to_s
51
49
  end
52
50
  end
53
51
  end
data/lib/avo/reloader.rb CHANGED
@@ -46,7 +46,7 @@ class Avo::Reloader
46
46
  if reload_lib?
47
47
  dirs[Avo::Engine.root.join("lib", "avo").to_s] = ["rb"]
48
48
  if Avo.avo_filters_installed?
49
- dirs[AvoFilters::Engine.root.join("lib", "avo_filters").to_s] = ["rb"]
49
+ dirs[Avo::DynamicFilters::Engine.root.join("lib", "avo", "dynamic_filters").to_s] = ["rb"]
50
50
  end
51
51
  end
52
52
 
@@ -2,13 +2,14 @@ module Avo
2
2
  module Resources
3
3
  module Controls
4
4
  class ActionsList < BaseControl
5
- attr_reader :color, :exclude, :style
5
+ attr_reader :color, :exclude, :include, :style
6
6
 
7
7
  def initialize(**args)
8
8
  super(**args)
9
9
 
10
10
  @color = args[:color] || :primary
11
11
  @exclude = args[:exclude] || []
12
+ @include = args[:include] || []
12
13
  @style = args[:style] || :outline
13
14
  end
14
15
  end
@@ -22,7 +22,7 @@ class Avo::Resources::Items::Holder
22
22
  name: field_name,
23
23
  as: as,
24
24
  # resource: resource_class.name,
25
- message: "There's an invalid field configuration for this resource. <br/> <code class='px-1 py-px rounded bg-red-600'>field :#{field_name}, as: #{as}</code>"
25
+ message: "There's an invalid field configuration for this resource. <br/> <code class='px-1 py-px rounded bg-red-600'>field :#{field_name}, as: :#{as}</code>"
26
26
  })
27
27
  end
28
28
 
@@ -41,6 +41,10 @@ class Avo::Resources::Items::Holder
41
41
  add_item Avo::Resources::Items::Tab::Builder.parse_block(name: name, **args, &block)
42
42
  end
43
43
 
44
+ def row(**args, &block)
45
+ add_item Avo::Resources::Items::Row::Builder.parse_block(**args, &block)
46
+ end
47
+
44
48
  def tool(klass, **args)
45
49
  instance = klass.new(**args)
46
50
  add_item instance
@@ -30,6 +30,7 @@ class Avo::Resources::Items::ItemGroup
30
30
 
31
31
  delegate :heading, to: :items_holder
32
32
  delegate :field, to: :items_holder
33
+ delegate :row, to: :items_holder
33
34
  delegate :items, to: :items_holder
34
35
 
35
36
  attr_reader :items_holder
@@ -0,0 +1,54 @@
1
+ class Avo::Resources::Items::Row
2
+ include Avo::Concerns::IsResourceItem
3
+ include Avo::Concerns::HasItems
4
+ include Avo::Concerns::HasItemType
5
+ include Avo::Concerns::IsVisible
6
+
7
+ class_attribute :item_type, default: :row
8
+
9
+ attr_reader :view
10
+ attr_accessor :items_holder
11
+
12
+ delegate :items, :add_item, to: :items_holder
13
+
14
+ def initialize(view: nil)
15
+ @view = view
16
+ @items_holder = Avo::Resources::Items::Holder.new
17
+ end
18
+
19
+ def hydrate(view: nil, resource: nil, **args)
20
+ @view = view
21
+ @resource = resource
22
+
23
+ self
24
+ end
25
+
26
+ def has_items?
27
+ @items.present?
28
+ end
29
+
30
+ class Builder
31
+ class << self
32
+ def parse_block(**args, &block)
33
+ Docile.dsl_eval(new(**args), &block).build
34
+ end
35
+ end
36
+
37
+ attr_reader :items_holder
38
+
39
+ delegate :field, to: :items_holder
40
+ delegate :tool, to: :items_holder
41
+ delegate :items, to: :items_holder
42
+
43
+ def initialize(**args)
44
+ @row = Avo::Resources::Items::Row.new(**args)
45
+ @items_holder = Avo::Resources::Items::Holder.new
46
+ end
47
+
48
+ # Fetch the tab
49
+ def build
50
+ @row.items_holder = @items_holder
51
+ @row
52
+ end
53
+ end
54
+ end
@@ -66,9 +66,6 @@ module Avo
66
66
  # We need to de-duplicate them
67
67
  klass.name
68
68
  end
69
- .map do |resource|
70
- resource.new if resource.is_a? Class
71
- end
72
69
  end
73
70
 
74
71
  def check_bad_resources
@@ -76,13 +73,13 @@ module Avo
76
73
  has_model = resource.model_class.present?
77
74
 
78
75
  unless has_model
79
- possible_model = resource.class.to_s.gsub "Avo::Resources::", ""
76
+ possible_model = resource.to_s.gsub "Avo::Resources::", ""
80
77
  possible_model = possible_model.gsub "Resource", ""
81
78
 
82
- Avo::App.errors.add({
79
+ Avo.error_manager.add({
83
80
  url: "https://docs.avohq.io/2.0/resources.html#custom-model-class",
84
81
  target: "_blank",
85
- message: "#{resource.class} does not have a valid model assigned. It failed to find the #{possible_model} model. \n\r Please create that model or assign one using self.model_class = YOUR_MODEL"
82
+ message: "#{resource} does not have a valid model assigned. It failed to find the #{possible_model} model. \n\r Please create that model or assign one using self.model_class = YOUR_MODEL"
86
83
  })
87
84
  end
88
85
  end
@@ -100,7 +97,7 @@ module Avo
100
97
  resource = "Avo::Resources::#{resource}" unless resource.to_s.starts_with?("Avo::Resources::")
101
98
 
102
99
  resources.find do |available_resource|
103
- resource.to_s == available_resource.class.to_s
100
+ resource.to_s == available_resource.to_s
104
101
  end
105
102
  end
106
103
 
@@ -12,7 +12,7 @@ class Avo::Services::DebugService
12
12
  payload[:hq_payload] = hq&.payload
13
13
  payload[:thread_count] = get_thread_count
14
14
  payload[:license_abilities] = Avo::Current&.license&.abilities
15
- payload[:cache_store] = Avo::App.cache_store&.class&.to_s
15
+ payload[:cache_store] = Avo.cache_store&.class&.to_s
16
16
  payload[:avo_metadata] = avo_metadata
17
17
  payload[:app_timezone] = Time.current.zone
18
18
  payload[:cache_key] = Avo::Licensing::HQ.cache_key
@@ -31,8 +31,8 @@ class Avo::Services::DebugService
31
31
  end
32
32
 
33
33
  def avo_metadata
34
- resources = Avo::Current.app.resource_manager.all
35
- dashboards = defined?(AvoDashboards) ? AvoDashboards.dashboard_manager.all : []
34
+ resources = Avo.resource_manager.all
35
+ dashboards = defined?(Avo::Dashboards) ? Avo::Dashboards.dashboard_manager.all : []
36
36
  field_definitions = resources.map(&:get_field_definitions)
37
37
  fields_count = field_definitions.map(&:count).sum
38
38
  fields_per_resource = sprintf("%0.01f", fields_count / (resources.count + 0.0))
@@ -55,11 +55,11 @@ class Avo::Services::DebugService
55
55
  fields_per_resource: fields_per_resource,
56
56
  custom_fields_count: custom_fields_count,
57
57
  field_types: field_types,
58
- **other_metadata(:actions),
58
+ # **other_metadata(:actions), # TODO: this is fetching actions without hydration
59
59
  **other_metadata(:filters),
60
60
  main_menu_present: Avo.configuration.main_menu.present?,
61
61
  profile_menu_present: Avo.configuration.profile_menu.present?,
62
- cache_store: Avo::App.cache_store&.class&.to_s,
62
+ cache_store: Avo.cache_store&.class&.to_s,
63
63
  **config_metadata
64
64
  }
65
65
  # rescue => error
@@ -69,7 +69,7 @@ class Avo::Services::DebugService
69
69
  end
70
70
 
71
71
  def other_metadata(type = :actions)
72
- resources = Avo::Current.app.resource_manager.all
72
+ resources = Avo.resource_manager.all
73
73
 
74
74
  types = resources.map(&:"get_#{type}")
75
75
  type_count = types.flatten.uniq.count
@@ -23,7 +23,7 @@ class Avo::Services::TelemetryService
23
23
  end
24
24
 
25
25
  def avo_metadata
26
- resources = Avo::Current.app.resource_manager.all
26
+ resources = Avo.resource_manager.all
27
27
  dashboards = Avo::Current.app.dashboard_manager.all
28
28
  field_definitions = resources.map(&:get_field_definitions)
29
29
  fields_count = field_definitions.map(&:count).sum
@@ -51,7 +51,7 @@ class Avo::Services::TelemetryService
51
51
  **other_metadata(:filters),
52
52
  main_menu_present: Avo.configuration.main_menu.present?,
53
53
  profile_menu_present: Avo.configuration.profile_menu.present?,
54
- cache_store: Avo::App.cache_store&.class&.to_s,
54
+ cache_store: Avo.cache_store&.class&.to_s,
55
55
  **config_metadata
56
56
  }
57
57
  # rescue => error
@@ -61,7 +61,7 @@ class Avo::Services::TelemetryService
61
61
  end
62
62
 
63
63
  def other_metadata(type = :actions)
64
- resources = Avo::Current.app.resource_manager.all
64
+ resources = Avo.resource_manager.all
65
65
 
66
66
  types = resources.map(&:"get_#{type}")
67
67
  type_count = types.flatten.uniq.count
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "3.0.0.pre12" unless const_defined?(:VERSION)
2
+ VERSION = "3.0.0.pre14" unless const_defined?(:VERSION)
3
3
  end
data/lib/avo.rb CHANGED
@@ -11,31 +11,9 @@ loader.inflector.inflect(
11
11
  loader.ignore("#{__dir__}/generators")
12
12
  loader.setup
13
13
 
14
- # .//*,,.....,,*/(*
15
- # **,,..............,*#.
16
- # ,*,,..... .....*/#.
17
- # **,,.... ....,*/%%
18
- # ,**,,....... . ....*/#&%
19
- # **,,,...... . . ....*/#&&%
20
- # **,,........ . . ...,//#&&&.
21
- # */*,,..*//***,,,,*/(,.. .. .....*//%&%&*
22
- # ,/**,..**/******,,***/(###,...........,//(%&&%.
23
- # /**,,..((//*****////((##%%%%%*.........*//%%&&%
24
- # ****,...#/**,,,*,*/(#%##%%%%&&&(*,.....,*/(%&&&/
25
- # /**,....(/*,,,,,,,*(##%%%%%&&&&&(,.....,*(#&&&&.
26
- # ,//*,.....(/*,,**//(##%%%%&&&&@&&%/,....,*((&&&&*
27
- # .//*,,.....(((//(((##%%%&&&&&&&&@#/,....,*/#%&&&#
28
- # (/**,,......###%%%%%&&&&&&&&&&@#/,,...,,*/#&&&&&
29
- # (/**,,........%%%%%&&&&&&&&@%(*,...,,,*//(&&&&%.
30
- # ///*,,,.........,*#&&&&#(/,,.....,,,*//(%&&&&%*
31
- # (//**,,,.....................,,,,*//(%&&&&&&*
32
- # *(///**,,,,............,,,,,,**/((&&&&&&&%.
33
- # ((///*****,,,,,,,,,,,,***//((&&&&&%&%&#
34
- # .((((////********///(((%&%&&&&%%%%%
35
- # (############%%%%%%%%%%%%%%%*
36
- # ,(############%%%%%#*
37
-
38
14
  module Avo
15
+ extend ActiveSupport::LazyLoadHooks
16
+
39
17
  ROOT_PATH = Pathname.new(File.join(__dir__, ".."))
40
18
  IN_DEVELOPMENT = ENV["AVO_IN_DEVELOPMENT"] == "1"
41
19
  PACKED = !IN_DEVELOPMENT
@@ -64,8 +42,112 @@ module Avo
64
42
  class DeprecatedAPIError < StandardError; end
65
43
 
66
44
  class << self
45
+ attr_reader :logger
46
+ attr_reader :cache_store
47
+ attr_reader :field_manager
48
+
49
+ delegate :license, :app, :error_manager, :tool_manager, :resource_manager, to: Avo::Current
50
+
51
+ def boot
52
+ boot_logger
53
+ boot_fields
54
+ @cache_store = get_cache_store
55
+ plugin_manager.boot_plugins
56
+ Avo.run_load_hooks(:boot, self)
57
+ end
58
+
59
+ def init
60
+ Avo::Current.error_manager = Avo::ErrorManager.build
61
+ Avo::Current.resource_manager = Avo::Resources::ResourceManager.build
62
+ Avo::Current.tool_manager = Avo::Tools::ToolManager.build
63
+
64
+ Avo.run_load_hooks(:init, self)
65
+ end
66
+
67
+ # Renerate a dynamic root path using the URIService
68
+ def root_path(paths: [], query: {}, **args)
69
+ Avo::Services::URIService.parse(Avo::Current.view_context.avo.root_url.to_s)
70
+ .append_paths(paths)
71
+ .append_query(query)
72
+ .to_s
73
+ end
74
+
75
+ def mount_path
76
+ Avo::Engine.routes.find_script_name({})
77
+ end
78
+
79
+ def main_menu
80
+ return unless Avo.plugin_manager.installed?("avo-menu")
81
+
82
+ # Return empty menu if the app doesn't have the profile menu configured
83
+ return Avo::Menu::Builder.new.build unless has_main_menu?
84
+
85
+ Avo::Menu::Builder.parse_menu(&Avo.configuration.main_menu)
86
+ end
87
+
88
+ def profile_menu
89
+ return unless Avo.plugin_manager.installed?("avo-menu")
90
+
91
+ # Return empty menu if the app doesn't have the profile menu configured
92
+ return Avo::Menu::Builder.new.build unless has_profile_menu?
93
+
94
+ Avo::Menu::Builder.parse_menu(&Avo.configuration.profile_menu)
95
+ end
96
+
97
+ def app_status
98
+ license.valid?
99
+ end
100
+
67
101
  def avo_filters_installed?
68
- defined?(AvoFilters).present?
102
+ defined?(Avo::DynamicFilters).present?
103
+ end
104
+
105
+ def has_main_menu?
106
+ return false if Avo.license.lacks_with_trial(:menu_editor)
107
+ return false if Avo.configuration.main_menu.nil?
108
+
109
+ true
110
+ end
111
+
112
+ def has_profile_menu?
113
+ return false if Avo.license.lacks_with_trial(:menu_editor)
114
+ return false if Avo.configuration.profile_menu.nil?
115
+
116
+ true
117
+ end
118
+
119
+ private
120
+
121
+ def boot_logger
122
+ file_logger = ActiveSupport::Logger.new(Rails.root.join("log", "avo.log"))
123
+
124
+ file_logger.datetime_format = "%Y-%m-%d %H:%M:%S"
125
+ file_logger.formatter = proc do |severity, time, progname, msg|
126
+ "[Avo] #{time}: #{msg}\n".tap do |i|
127
+ puts i
128
+ end
129
+ end
130
+
131
+ @logger = file_logger
132
+ end
133
+
134
+ def boot_fields
135
+ @field_manager = Avo::Fields::FieldManager.build
136
+ end
137
+
138
+ def get_cache_store
139
+ if Rails.env.production?
140
+ case Rails.cache.class.to_s
141
+ when "ActiveSupport::Cache::MemCacheStore", "ActiveSupport::Cache::RedisCacheStore"
142
+ Rails.cache
143
+ else
144
+ ActiveSupport::Cache.lookup_store(:file_store, Rails.root.join("tmp", "cache"))
145
+ end
146
+ elsif Rails.env.test?
147
+ Rails.cache
148
+ else
149
+ ActiveSupport::Cache.lookup_store(:memory_store)
150
+ end
69
151
  end
70
152
  end
71
153
  end
@@ -5,20 +5,20 @@ module Generators
5
5
  class ActionGenerator < NamedBaseGenerator
6
6
  source_root File.expand_path("templates", __dir__)
7
7
 
8
- class_option :standalone, type: :boolean
8
+ class_option :standalone, type: :boolean, default: false
9
+ class_option :name, type: :string
9
10
 
10
11
  namespace "avo:action"
11
12
 
12
13
  def create_resource_file
13
- type = "resource"
14
+ template "action.tt", "app/avo/actions/#{singular_name}.rb"
15
+ end
14
16
 
15
- type = "standalone" if options[:standalone]
17
+ def configuration_options
18
+ configuration = " self.name = \"#{options[:name] || name.titleize}\""
19
+ configuration += "\n self.standalone = true" if options[:standalone]
16
20
 
17
- if type == "standalone"
18
- template "standalone_action.tt", "app/avo/actions/#{singular_name}.rb"
19
- else
20
- template "action.tt", "app/avo/actions/#{singular_name}.rb"
21
- end
21
+ configuration
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,27 @@
1
+ require_relative "named_base_generator"
2
+
3
+ module Generators
4
+ module Avo
5
+ class Card < NamedBaseGenerator
6
+ namespace "avo:card"
7
+ source_root File.expand_path("templates", __dir__)
8
+ class_option :type, type: :string
9
+
10
+ def handle
11
+ raise "Invalid card type '#{options[:type]}'" unless card_types.include? options[:type]
12
+
13
+ template "cards/#{options[:type]}_card_sample.tt", "app/avo/cards/#{name.underscore}.rb"
14
+
15
+ if options[:type].to_sym == :partial
16
+ template "cards/partial_card_partial.tt", "app/views/avo/cards/_#{name.underscore}.html.erb"
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def card_types
23
+ %w[metric chartkick partial]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -17,6 +17,7 @@ module Generators
17
17
  pre_head: "app/views/avo/partials/_pre_head.html.erb",
18
18
  scripts: "app/views/avo/partials/_scripts.html.erb",
19
19
  sidebar_extra: "app/views/avo/partials/_sidebar_extra.html.erb",
20
+ profile_menu_extra: "app/views/avo/partials/_profile_menu_extra.html.erb",
20
21
  }
21
22
 
22
23
  def handle
@@ -5,20 +5,20 @@ module Generators
5
5
  class FilterGenerator < NamedBaseGenerator
6
6
  source_root File.expand_path("templates", __dir__)
7
7
 
8
- class_option :multiple_select, type: :boolean
9
- class_option :select, type: :boolean
10
- class_option :text, type: :boolean
8
+ class_option :type, type: :string, default: "boolean"
11
9
 
12
10
  namespace "avo:filter"
13
11
 
14
12
  def create_resource_file
15
- type = "boolean"
13
+ raise "Invalid filter type '#{options[:type]}'" unless filter_types.include? options[:type]
16
14
 
17
- type = "multiple_select" if options[:multiple_select]
18
- type = "select" if options[:select]
19
- type = "text" if options[:text]
15
+ template "filters/#{options[:type]}_filter.tt", "app/avo/filters/#{singular_name}.rb"
16
+ end
17
+
18
+ private
20
19
 
21
- template "filters/#{type}_filter.tt", "app/avo/filters/#{singular_name}.rb"
20
+ def filter_types
21
+ %w[boolean select text multiple_select]
22
22
  end
23
23
  end
24
24
  end
@@ -13,7 +13,6 @@ module Generators
13
13
  route "mount Avo::Engine, at: Avo.configuration.root_path"
14
14
 
15
15
  template "initializer/avo.tt", "config/initializers/avo.rb"
16
- directory File.join(__dir__, "templates", "locales"), "config/locales"
17
16
  create_resources
18
17
  end
19
18
 
@@ -135,6 +135,9 @@ module Generators
135
135
  fields_string = ""
136
136
 
137
137
  fields.each do |field_name, field_options|
138
+ # if field_options are not available (likely a missing resource for an association), skip the field
139
+ fields_string += "\n # Could not generate a field for #{field_name}" and next unless field_options
140
+
138
141
  options = ""
139
142
  field_options[:options].each { |k, v| options += ", #{k}: #{v}" } if field_options[:options].present?
140
143
 
@@ -181,7 +184,7 @@ module Generators
181
184
  end
182
185
 
183
186
  def field_from_through_association(association)
184
- if association.through_reflection.is_a? ActiveRecord::Reflection::HasManyReflection
187
+ if association.through_reflection.is_a?(ActiveRecord::Reflection::HasManyReflection) || association.through_reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
185
188
  {
186
189
  field: "has_many",
187
190
  options: {
@@ -1,5 +1,5 @@
1
1
  class Avo::Actions::<%= class_name.camelize %> < Avo::BaseAction
2
- self.name = "<%= name.underscore.humanize %>"
2
+ <%= configuration_options %>
3
3
  # self.visible = -> do
4
4
  # true
5
5
  # end
@@ -8,8 +8,8 @@ class Avo::Actions::<%= class_name.camelize %> < Avo::BaseAction
8
8
  # # Add Action fields here
9
9
  # end
10
10
 
11
- def handle(records:, fields:, current_user:, resource:)
12
- records.each do |model|
11
+ def handle(records:, fields:, current_user:, resource:, **args)
12
+ records.each do |record|
13
13
  # Do something with your records.
14
14
  end
15
15
  end
@@ -1,4 +1,4 @@
1
- class Avo::Cards::<%= class_name.camelize %> < AvoDashboards::ChartkickCard
1
+ class Avo::Cards::<%= class_name.camelize %> < Avo::Dashboards::ChartkickCard
2
2
  self.id = "<%= name.underscore %>"
3
3
  self.label = "<%= name.underscore.humanize %>"
4
4
  self.chart_type = :area_chart
@@ -1,4 +1,4 @@
1
- class Avo::Cards::<%= class_name.camelize %> < AvoDashboards::ChartkickCard
1
+ class Avo::Cards::<%= class_name.camelize %> < Avo::Dashboards::ChartkickCard
2
2
  self.id = "<%= name.underscore %>"
3
3
  self.label = "<%= name.underscore.humanize %>"
4
4
  self.chart_type = :area_chart
@@ -1,4 +1,4 @@
1
- class Avo::Cards::<%= class_name.camelize %> < AvoDashboards::MetricCard
1
+ class Avo::Cards::<%= class_name.camelize %> < Avo::Dashboards::MetricCard
2
2
  self.id = "<%= name.underscore %>"
3
3
  self.label = "<%= name.underscore.humanize %>"
4
4
 
@@ -1,4 +1,4 @@
1
- class Avo::Cards::<%= class_name.camelize %> < AvoDashboards::MetricCard
1
+ class Avo::Cards::<%= class_name.camelize %> < Avo::Dashboards::MetricCard
2
2
  self.id = "<%= name.underscore %>"
3
3
  self.label = "<%= name.underscore.humanize %>"
4
4
  # self.description = "Some description"
@@ -1,4 +1,4 @@
1
- class Avo::Cards::<%= class_name.camelize %> < AvoDashboards::PartialCard
1
+ class Avo::Cards::<%= class_name.camelize %> < Avo::Dashboards::PartialCard
2
2
  self.id = "<%= name.underscore %>"
3
3
  self.label = "<%= name.underscore.humanize %>"
4
4
  self.partial = "avo/cards/<%= name.underscore %>"
@@ -1,4 +1,4 @@
1
- class Avo::Cards::<%= class_name.camelize %> < AvoDashboards::PartialCard
1
+ class Avo::Cards::<%= class_name.camelize %> < Avo::Dashboards::PartialCard
2
2
  self.id = "<%= name.underscore %>"
3
3
  self.label = "<%= name.underscore.humanize %>"
4
4
  self.partial = "avo/cards/<%= name.underscore %>"
@@ -1,4 +1,4 @@
1
- class Avo::Dashboards::<%= class_name.camelize %> < AvoDashboards::BaseDashboard
1
+ class Avo::Dashboards::<%= class_name.camelize %> < Avo::Dashboards::BaseDashboard
2
2
  self.id = "<%= name.underscore %>"
3
3
  self.name = "<%= name.underscore.humanize %>"
4
4
  # self.description = "Tiny dashboard description"
@@ -1,9 +1,8 @@
1
1
  class Avo::Resources::<%= resource_class %> < Avo::BaseResource
2
- self.title = :id
3
2
  self.includes = []<%= model_class_from_args %>
4
- # self.search_query = -> do
5
- # query.ransack(id_eq: params[:q], m: "or").result(distinct: false)
6
- # end
3
+ # self.search = {
4
+ # query: -> { query.ransack(id_eq: params[:q], m: "or").result(distinct: false) }
5
+ # }
7
6
 
8
7
  def fields
9
8
  field :id, as: :id<%= generate_fields %>
@@ -1,4 +1,4 @@
1
- class Avo::Scopes::<%= class_name.camelize %> < AvoPro::Scopes::BaseScope
1
+ class Avo::Scopes::<%= class_name.camelize %> < Avo::Pro::Scopes::BaseScope
2
2
  self.name = "<%= name.underscore.humanize %>"
3
3
  self.description = "<%= name.underscore.humanize %>"
4
4
  self.scope = -> { query.all }
@@ -5,7 +5,7 @@
5
5
 
6
6
  desc "Runs the update command for all Avo gems."
7
7
  task "avo:update" do
8
- system "bundle update avo avo_pro avo_advanced avo_dashboards avo_filters avo_menu avo_upgrade"
8
+ system "bundle update avo avo-pro avo-advanced avo-dashboards avo_filters avo-menu avo_upgrade"
9
9
  end
10
10
 
11
11
  desc "Installs Avo assets and bundles them for when you want to use the GitHub repo in your app"