avo 2.1.2.pre2 → 2.2.2

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -2
  3. data/Gemfile.lock +11 -5
  4. data/app/assets/svgs/{dashboards-icon.svg → dashboards.svg} +1 -1
  5. data/app/assets/svgs/{resources-icon.svg → resources.svg} +0 -0
  6. data/app/assets/svgs/{tools-icon.svg → tools.svg} +0 -0
  7. data/app/components/avo/button_component.rb +6 -2
  8. data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +1 -0
  9. data/app/components/avo/fields/belongs_to_field/edit_component.rb +5 -2
  10. data/app/components/avo/index/field_wrapper_component.rb +13 -0
  11. data/app/components/avo/index/grid_item_component.html.erb +3 -1
  12. data/app/components/avo/index/table_row_component.html.erb +7 -5
  13. data/app/components/avo/panel_component.html.erb +4 -4
  14. data/app/components/avo/profile_item_component.html.erb +2 -2
  15. data/app/components/avo/profile_item_component.rb +6 -0
  16. data/app/components/avo/sidebar/base_item_component.rb +31 -0
  17. data/app/components/avo/sidebar/group_component.html.erb +28 -0
  18. data/app/components/avo/sidebar/group_component.rb +4 -0
  19. data/app/components/avo/sidebar/heading_component.html.erb +14 -0
  20. data/app/components/avo/sidebar/heading_component.rb +15 -0
  21. data/app/components/avo/sidebar/item_switcher_component.html.erb +16 -0
  22. data/app/components/avo/sidebar/item_switcher_component.rb +15 -0
  23. data/app/components/avo/sidebar/link_component.html.erb +12 -0
  24. data/app/components/avo/sidebar/link_component.rb +28 -0
  25. data/app/components/avo/sidebar/section_component.html.erb +15 -0
  26. data/app/components/avo/sidebar/section_component.rb +9 -0
  27. data/app/components/avo/sidebar_component.html.erb +33 -24
  28. data/app/components/avo/sidebar_component.rb +3 -9
  29. data/app/components/avo/sidebar_profile_component.html.erb +10 -1
  30. data/app/components/avo/views/resource_edit_component.html.erb +2 -2
  31. data/app/components/avo/views/resource_new_component.html.erb +2 -2
  32. data/app/components/avo/views/resource_show_component.html.erb +2 -2
  33. data/app/controllers/avo/application_controller.rb +1 -2
  34. data/app/controllers/avo/base_controller.rb +1 -1
  35. data/app/helpers/avo/application_helper.rb +2 -0
  36. data/app/javascript/js/controllers/loading_button_controller.js +47 -10
  37. data/app/javascript/js/controllers/menu_controller.js +60 -0
  38. data/app/javascript/js/controllers/search_controller.js +28 -10
  39. data/app/javascript/js/controllers.js +2 -0
  40. data/app/views/avo/base/_boolean_filter.html.erb +1 -1
  41. data/app/views/avo/base/_multiple_select_filter.html.erb +7 -4
  42. data/app/views/avo/base/_select_filter.html.erb +1 -1
  43. data/app/views/avo/base/_text_filter.html.erb +1 -1
  44. data/app/views/avo/partials/_table_header.html.erb +12 -13
  45. data/app/views/layouts/avo/application.html.erb +3 -0
  46. data/avo.gemspec +1 -0
  47. data/bin/helpers.rb +7 -1
  48. data/bin/init +2 -2
  49. data/lib/avo/app.rb +8 -86
  50. data/lib/avo/base_resource.rb +1 -3
  51. data/lib/avo/concerns/fetches_things.rb +127 -0
  52. data/lib/avo/configuration.rb +4 -0
  53. data/lib/avo/dynamic_router.rb +1 -1
  54. data/lib/avo/engine.rb +0 -1
  55. data/lib/avo/fields/base_field.rb +2 -0
  56. data/lib/avo/fields/belongs_to_field.rb +2 -0
  57. data/lib/avo/hosts/base_host.rb +20 -0
  58. data/lib/avo/licensing/pro_license.rb +2 -1
  59. data/lib/avo/menu/base_item.rb +20 -0
  60. data/lib/avo/menu/builder.rb +77 -0
  61. data/lib/avo/menu/dashboard.rb +17 -0
  62. data/lib/avo/menu/group.rb +2 -0
  63. data/lib/avo/menu/link.rb +4 -0
  64. data/lib/avo/menu/menu.rb +2 -0
  65. data/lib/avo/menu/resource.rb +9 -0
  66. data/lib/avo/menu/section.rb +2 -0
  67. data/lib/avo/reloader.rb +15 -7
  68. data/lib/avo/version.rb +1 -1
  69. data/lib/generators/avo/filter_generator.rb +2 -0
  70. data/lib/generators/avo/templates/filters/boolean_filter.tt +1 -1
  71. data/lib/generators/avo/templates/filters/multiple_select_filter.tt +11 -0
  72. data/lib/generators/avo/templates/filters/select_filter.tt +1 -1
  73. data/lib/generators/avo/templates/filters/text_filter.tt +1 -1
  74. data/lib/generators/avo/templates/tool/sidebar_item.tt +1 -1
  75. data/public/avo-assets/avo.css +23 -6
  76. data/public/avo-assets/avo.js +63 -63
  77. data/public/avo-assets/avo.js.map +3 -3
  78. metadata +44 -14
  79. data/app/assets/builds/avo.css +0 -8810
  80. data/app/assets/builds/avo.js +0 -423
  81. data/app/assets/builds/avo.js.map +0 -7
  82. data/app/components/avo/sidebar_heading_component.html.erb +0 -3
  83. data/app/components/avo/sidebar_heading_component.rb +0 -11
  84. data/app/components/avo/sidebar_item_component.html.erb +0 -3
  85. data/app/components/avo/sidebar_item_component.rb +0 -10
@@ -29,6 +29,8 @@ module Avo
29
29
  attr_accessor :raise_error_on_missing_policy
30
30
  attr_accessor :disabled_features
31
31
  attr_accessor :buttons_on_form_footers
32
+ attr_accessor :main_menu
33
+ attr_accessor :profile_menu
32
34
 
33
35
  def initialize
34
36
  @root_path = "/avo"
@@ -70,6 +72,8 @@ module Avo
70
72
  @raise_error_on_missing_policy = false
71
73
  @disabled_features = []
72
74
  @buttons_on_form_footers = false
75
+ @main_menu = nil
76
+ @profile_menu = nil
73
77
  end
74
78
 
75
79
  def locale_tag
@@ -1,7 +1,7 @@
1
1
  module Avo
2
2
  module DynamicRouter
3
3
  def self.routes(router)
4
- Rails.application.eager_load! if Rails.env.development?
4
+ Rails.application.eager_load! unless Rails.env.production?
5
5
 
6
6
  BaseResource.descendants
7
7
  .select do |resource|
data/lib/avo/engine.rb CHANGED
@@ -19,7 +19,6 @@ module Avo
19
19
 
20
20
  config.i18n.load_path += Dir[Avo::Engine.root.join('lib', 'generators', 'avo', 'templates', 'locales', '*.{rb,yml}')]
21
21
 
22
- # initializer "avo.autoload", before: :set_autoload_paths do |app|
23
22
  initializer "avo.autoload" do |app|
24
23
  [
25
24
  ["app", "avo", "fields"],
@@ -26,6 +26,7 @@ module Avo
26
26
  attr_reader :as_label
27
27
  attr_reader :as_avatar
28
28
  attr_reader :as_description
29
+ attr_reader :index_text_align
29
30
 
30
31
  # Private options
31
32
  attr_reader :updatable
@@ -64,6 +65,7 @@ module Avo
64
65
  @as_label = args[:as_label] || false
65
66
  @as_avatar = args[:as_avatar] || false
66
67
  @as_description = args[:as_description] || false
68
+ @index_text_align = args[:index_text_align] || :left
67
69
 
68
70
  @updatable = true
69
71
  @computable = true
@@ -61,6 +61,7 @@ module Avo
61
61
  attr_reader :polymorphic_as
62
62
  attr_reader :relation_method
63
63
  attr_reader :types # for Polymorphic associations
64
+ attr_reader :allow_via_detaching
64
65
 
65
66
  def initialize(id, **args, &block)
66
67
  args[:placeholder] ||= I18n.t("avo.choose_an_option")
@@ -71,6 +72,7 @@ module Avo
71
72
  @polymorphic_as = args[:polymorphic_as]
72
73
  @types = args[:types]
73
74
  @relation_method = id.to_s.parameterize.underscore
75
+ @allow_via_detaching = args[:allow_via_detaching] == true
74
76
  end
75
77
 
76
78
  def searchable
@@ -0,0 +1,20 @@
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 Hosts
6
+ class BaseHost
7
+ extend Dry::Initializer
8
+
9
+ option :context, default: proc { Avo::App.context }
10
+ option :params, default: proc { Avo::App.params }
11
+ option :view_context, default: proc { Avo::App.view_context }
12
+ option :current_user, default: proc { Avo::App.current_user }
13
+ option :block, optional: true
14
+
15
+ def handle
16
+ instance_exec(&block)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -11,7 +11,8 @@ module Avo
11
11
  :enhanced_search_results,
12
12
  :searchable_associations,
13
13
  :resource_ordering,
14
- :dashboards
14
+ :dashboards,
15
+ :menu_editor
15
16
  ]
16
17
  end
17
18
  end
@@ -0,0 +1,20 @@
1
+ require "dry-initializer"
2
+
3
+ class Avo::Menu::BaseItem
4
+ extend Dry::Initializer
5
+
6
+ option :collapsable, default: proc { false }
7
+ option :collapsed, default: proc { false }
8
+ option :icon, optional: true
9
+ option :items, default: proc { [] }
10
+ option :name, default: proc { "" }
11
+ option :visible, default: proc { true }
12
+
13
+ def visible?
14
+ return visible if visible.in? [true, false]
15
+
16
+ if visible.respond_to? :call
17
+ Avo::Hosts::BaseHost.new(block: visible).handle
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,77 @@
1
+ class Avo::Menu::Builder
2
+ class << self
3
+ def parse_menu(&block)
4
+ Docile.dsl_eval(Avo::Menu::Builder.new, &block).build
5
+ end
6
+ end
7
+
8
+ def initialize(name: nil, items: [])
9
+ @menu = Avo::Menu::Menu.new
10
+
11
+ @menu.name = name
12
+ @menu.items = items
13
+ end
14
+
15
+ # Adds a link
16
+ def link(name, **args)
17
+ @menu.items << Avo::Menu::Link.new(name: name, **args)
18
+ end
19
+
20
+ # Validates and adds a resource
21
+ def resource(name, **args)
22
+ name = name.to_s.singularize
23
+ res = Avo::App.guess_resource(name)
24
+
25
+ if res.present?
26
+ @menu.items << Avo::Menu::Resource.new(resource: name, **args)
27
+ end
28
+ end
29
+ alias_method :resources, :resource
30
+
31
+ # Adds a dashboard
32
+ def dashboard(dashboard, **args)
33
+ @menu.items << Avo::Menu::Dashboard.new(dashboard: dashboard, **args)
34
+ end
35
+
36
+ # Adds a section
37
+ def section(name = nil, **args, &block)
38
+ @menu.items << Avo::Menu::Section.new(name: name, **args, items: self.class.parse_menu(&block).items)
39
+ end
40
+
41
+ # Adds a group
42
+ def group(name = nil, **args, &block)
43
+ @menu.items << Avo::Menu::Group.new(name: name, **args, items: self.class.parse_menu(&block).items)
44
+ end
45
+
46
+ # Add all the resources
47
+ def all_resources(**args)
48
+ Avo::App.resources_for_navigation.each do |res|
49
+ resource res.model_class, **args
50
+ end
51
+ end
52
+
53
+ # Add all the dashboards
54
+ def all_dashboards(**args)
55
+ Avo::App.dashboards_for_navigation.each do |dash|
56
+ dashboard dash.id, **args
57
+ end
58
+ end
59
+
60
+ # Add all the tools
61
+ def all_tools(**args)
62
+ Avo::App.tools_for_navigation.each do |tool|
63
+ link tool.humanize, path: "#{root_path}/#{tool}"
64
+ end
65
+ end
66
+
67
+ # Fetch the menu
68
+ def build
69
+ @menu
70
+ end
71
+
72
+ protected
73
+
74
+ def root_path
75
+ Avo::App.root_path
76
+ end
77
+ end
@@ -0,0 +1,17 @@
1
+ class Avo::Menu::Dashboard < Avo::Menu::BaseItem
2
+ extend Dry::Initializer
3
+
4
+ option :dashboard
5
+
6
+ def parsed_dashboard
7
+ dashboard_by_id || dashboard_by_name
8
+ end
9
+
10
+ def dashboard_by_name
11
+ Avo::App.get_dashboard_by_name dashboard.to_s
12
+ end
13
+
14
+ def dashboard_by_id
15
+ Avo::App.get_dashboard_by_id dashboard.to_s
16
+ end
17
+ end
@@ -0,0 +1,2 @@
1
+ class Avo::Menu::Group < Avo::Menu::BaseItem
2
+ end
@@ -0,0 +1,4 @@
1
+ class Avo::Menu::Link < Avo::Menu::BaseItem
2
+ option :path, default: proc { "" }
3
+ option :target, optional: true
4
+ end
@@ -0,0 +1,2 @@
1
+ class Avo::Menu::Menu < OpenStruct
2
+ end
@@ -0,0 +1,9 @@
1
+ class Avo::Menu::Resource < Avo::Menu::BaseItem
2
+ extend Dry::Initializer
3
+
4
+ option :resource
5
+
6
+ def parsed_resource
7
+ Avo::App.guess_resource resource.to_s
8
+ end
9
+ end
@@ -0,0 +1,2 @@
1
+ class Avo::Menu::Section < Avo::Menu::BaseItem
2
+ end
data/lib/avo/reloader.rb CHANGED
@@ -3,31 +3,39 @@ class Avo::Reloader
3
3
 
4
4
  def reload!
5
5
  # reload all files declared in paths
6
- paths.each { |path| load path }
6
+ files.each do |file|
7
+ if File.exist? file
8
+ load file
9
+ end
10
+ end
7
11
 
8
12
  # reload all files declared in each directory
9
13
  directories.keys.each do |dir|
10
- Dir.glob("#{dir}/**/*.rb".to_s).each { |c| load c }
14
+ Dir.glob("#{dir}/**/*.rb".to_s).each do |file|
15
+ if File.exist? file
16
+ load file
17
+ end
18
+ end
11
19
  end
12
20
  end
13
21
 
14
22
  private
15
23
  def updater
16
- @updater ||= config.file_watcher.new(paths, directories) { reload! }
24
+ @updater ||= config.file_watcher.new(files, directories) { reload! }
17
25
  end
18
26
 
19
- def paths
27
+ def files
20
28
  # we want to watch some files no matter what
21
- files = [
29
+ paths = [
22
30
  Rails.root.join("config", "initializers", "avo.rb"),
23
31
  ]
24
32
 
25
33
  # we want to watch some files only in Avo development
26
34
  if reload_lib?
27
- files += []
35
+ paths += []
28
36
  end
29
37
 
30
- files
38
+ paths
31
39
  end
32
40
 
33
41
  def directories
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.1.2.pre2"
2
+ VERSION = "2.2.2"
3
3
  end
@@ -4,6 +4,7 @@ module Generators
4
4
  module Avo
5
5
  class FilterGenerator < ::Rails::Generators::NamedBase
6
6
  source_root File.expand_path("templates", __dir__)
7
+ class_option :multiple_select, type: :boolean
7
8
  class_option :select, type: :boolean
8
9
  class_option :text, type: :boolean
9
10
 
@@ -12,6 +13,7 @@ module Generators
12
13
  def create_resource_file
13
14
  type = "boolean"
14
15
 
16
+ type = "multiple_select" if options[:multiple_select]
15
17
  type = "select" if options[:select]
16
18
  type = "text" if options[:text]
17
19
 
@@ -1,5 +1,5 @@
1
1
  class <%= class_name.camelize %> < Avo::Filters::BooleanFilter
2
- self.name = '<%= name.underscore.humanize %>'
2
+ self.name = "<%= name.underscore.humanize %>"
3
3
 
4
4
  def apply(request, query, values)
5
5
  query
@@ -0,0 +1,11 @@
1
+ class <%= class_name.camelize %> < Avo::Filters::MultipleSelectFilter
2
+ self.name = "<%= name.underscore.humanize %>"
3
+
4
+ def apply(request, query, value)
5
+ query
6
+ end
7
+
8
+ def options
9
+ {}
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
1
  class <%= class_name.camelize %> < Avo::Filters::SelectFilter
2
- self.name = '<%= name.underscore.humanize %>'
2
+ self.name = "<%= name.underscore.humanize %>"
3
3
 
4
4
  def apply(request, query, value)
5
5
  query
@@ -1,5 +1,5 @@
1
1
  class <%= class_name.camelize %> < Avo::Filters::TextFilter
2
- self.name = '<%= name.underscore.humanize %>'
2
+ self.name = "<%= name.underscore.humanize %>"
3
3
  self.button_label = 'Filter by <%= class_name.underscore.humanize.downcase.gsub(' filter', '') %>'
4
4
 
5
5
  def apply(request, query, value)
@@ -1 +1 @@
1
- <%%= render Avo::SidebarItemComponent.new label: '<%= human_name %>', path: "#{avo.root_path}<%= file_name %>" %>
1
+ <%%= render Avo::Sidebar::LinkComponent.new label: '<%= human_name %>', path: "#{avo.root_path}<%= file_name %>" %>
@@ -6449,6 +6449,10 @@ progress[value]::-moz-progress-bar{
6449
6449
  margin-left:50%
6450
6450
  }
6451
6451
 
6452
+ .ml-auto{
6453
+ margin-left:auto
6454
+ }
6455
+
6452
6456
  .-mb-2{
6453
6457
  margin-bottom:-0.5rem
6454
6458
  }
@@ -6677,6 +6681,10 @@ progress[value]::-moz-progress-bar{
6677
6681
  min-width:200px
6678
6682
  }
6679
6683
 
6684
+ .min-w-\[20px\]{
6685
+ min-width:20px
6686
+ }
6687
+
6680
6688
  .max-w-168{
6681
6689
  max-width:42rem
6682
6690
  }
@@ -7381,6 +7389,11 @@ progress[value]::-moz-progress-bar{
7381
7389
  padding-bottom:6rem
7382
7390
  }
7383
7391
 
7392
+ .px-10{
7393
+ padding-left:2.5rem;
7394
+ padding-right:2.5rem
7395
+ }
7396
+
7384
7397
  .py-8{
7385
7398
  padding-top:2rem;
7386
7399
  padding-bottom:2rem
@@ -7418,6 +7431,10 @@ progress[value]::-moz-progress-bar{
7418
7431
  padding-bottom:75%
7419
7432
  }
7420
7433
 
7434
+ .pt-2{
7435
+ padding-top:0.5rem
7436
+ }
7437
+
7421
7438
  .text-left{
7422
7439
  text-align:left
7423
7440
  }
@@ -8007,14 +8024,14 @@ trix-editor {
8007
8024
  background-color:rgb(6 95 158 / var(--tw-bg-opacity))
8008
8025
  }
8009
8026
 
8010
- .hover\:bg-gray-150:hover{
8027
+ .hover\:bg-blue-50:hover{
8011
8028
  --tw-bg-opacity:1;
8012
- background-color:rgb(233 234 236 / var(--tw-bg-opacity))
8029
+ background-color:rgb(251 253 255 / var(--tw-bg-opacity))
8013
8030
  }
8014
8031
 
8015
- .hover\:bg-blue-50:hover{
8032
+ .hover\:bg-gray-150:hover{
8016
8033
  --tw-bg-opacity:1;
8017
- background-color:rgb(251 253 255 / var(--tw-bg-opacity))
8034
+ background-color:rgb(233 234 236 / var(--tw-bg-opacity))
8018
8035
  }
8019
8036
 
8020
8037
  .hover\:text-gray-500:hover{
@@ -8484,8 +8501,8 @@ trix-editor {
8484
8501
  opacity:0.5
8485
8502
  }
8486
8503
 
8487
- .disabled\:opacity-30:disabled{
8488
- opacity:0.3
8504
+ .disabled\:opacity-70:disabled{
8505
+ opacity:0.7
8489
8506
  }
8490
8507
 
8491
8508
  .group:hover .group-hover\:block{