avo 1.18.2 → 1.19.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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +6 -6
  4. data/app/components/avo/fields/belongs_to_field/index_component.html.erb +1 -1
  5. data/app/components/avo/fields/belongs_to_field/show_component.html.erb +1 -1
  6. data/app/components/avo/fields/common/multiple_file_viewer_component.html.erb +1 -1
  7. data/app/components/avo/fields/common/single_file_viewer_component.html.erb +1 -2
  8. data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
  9. data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -1
  10. data/app/components/avo/fields/has_one_field/show_component.rb +6 -1
  11. data/app/components/avo/fields/index_component.rb +2 -2
  12. data/app/components/avo/fields/trix_field/edit_component.html.erb +1 -1
  13. data/app/components/avo/index/grid_item_component.html.erb +4 -4
  14. data/app/components/avo/index/resource_controls_component.html.erb +1 -1
  15. data/app/components/avo/index/resource_controls_component.rb +22 -6
  16. data/app/components/avo/index/resource_table_component.html.erb +1 -1
  17. data/app/components/avo/panel_component.rb +3 -4
  18. data/app/components/avo/resource_component.rb +5 -1
  19. data/app/components/avo/views/resource_edit_component.html.erb +2 -2
  20. data/app/components/avo/views/resource_edit_component.rb +3 -3
  21. data/app/components/avo/views/resource_index_component.html.erb +2 -8
  22. data/app/components/avo/views/resource_index_component.rb +7 -15
  23. data/app/components/avo/views/resource_new_component.html.erb +2 -2
  24. data/app/components/avo/views/resource_new_component.rb +6 -2
  25. data/app/components/avo/views/resource_show_component.html.erb +5 -4
  26. data/app/components/avo/views/resource_show_component.rb +11 -6
  27. data/app/controllers/avo/actions_controller.rb +1 -1
  28. data/app/controllers/avo/application_controller.rb +2 -61
  29. data/app/controllers/avo/attachments_controller.rb +3 -2
  30. data/app/controllers/avo/base_controller.rb +28 -21
  31. data/app/controllers/avo/home_controller.rb +5 -1
  32. data/app/controllers/avo/relations_controller.rb +3 -3
  33. data/app/controllers/avo/search_controller.rb +1 -1
  34. data/app/helpers/avo/application_helper.rb +5 -11
  35. data/app/helpers/avo/resources_helper.rb +1 -1
  36. data/app/helpers/avo/url_helpers.rb +77 -0
  37. data/app/packs/entrypoints/application.css +1 -0
  38. data/app/packs/entrypoints/application.js +7 -0
  39. data/app/packs/js/controllers/loading_button_controller.js +22 -0
  40. data/app/packs/stylesheets/components/status.css +22 -15
  41. data/app/packs/stylesheets/spinner.css +49 -0
  42. data/app/views/avo/actions/show.html.erb +2 -2
  43. data/app/views/avo/base/_actions.html.erb +3 -3
  44. data/app/views/avo/base/_filters.html.erb +1 -1
  45. data/app/views/avo/home/failed_to_load.html.erb +3 -0
  46. data/app/views/avo/partials/_failed_state.html.erb +16 -0
  47. data/app/views/avo/partials/_paginator.html.erb +2 -2
  48. data/app/views/avo/relations/new.html.erb +0 -2
  49. data/app/views/avo/sidebar/_sidebar.html.erb +1 -1
  50. data/app/views/kaminari/_page.html.erb +1 -1
  51. data/config/routes.rb +7 -5
  52. data/lib/avo/app.rb +4 -8
  53. data/lib/avo/base_action.rb +9 -1
  54. data/lib/avo/base_resource.rb +33 -7
  55. data/lib/avo/configuration.rb +2 -0
  56. data/lib/avo/fields/base_field.rb +8 -2
  57. data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -19
  58. data/lib/avo/fields/has_base_field.rb +35 -0
  59. data/lib/avo/fields/has_many_field.rb +1 -19
  60. data/lib/avo/fields/has_one_field.rb +3 -19
  61. data/lib/avo/services/authorization_service.rb +8 -4
  62. data/lib/avo/version.rb +1 -1
  63. data/lib/generators/avo/templates/locales/avo.en.yml +2 -0
  64. data/public/avo-packs/css/{application-f9191617.css → application-c3b50b28.css} +54 -12
  65. data/public/avo-packs/css/application-c3b50b28.css.br +0 -0
  66. data/public/avo-packs/css/{application-f9191617.css.gz → application-c3b50b28.css.gz} +0 -0
  67. data/public/avo-packs/css/application-c3b50b28.css.map +1 -0
  68. data/public/avo-packs/css/application-c3b50b28.css.map.br +0 -0
  69. data/public/avo-packs/css/application-c3b50b28.css.map.gz +0 -0
  70. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js +2 -0
  71. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.br +0 -0
  72. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.gz +0 -0
  73. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map +1 -0
  74. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map.br +0 -0
  75. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map.gz +0 -0
  76. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js +26 -0
  77. data/public/avo-packs/js/{application-cc89f096028eb1d4d971.js.LICENSE.txt → application-6fc968cfa52976c4582b.js.LICENSE.txt} +0 -0
  78. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.br +0 -0
  79. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.gz +0 -0
  80. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map +1 -0
  81. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map.br +0 -0
  82. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map.gz +0 -0
  83. data/public/avo-packs/manifest.json +21 -21
  84. metadata +27 -21
  85. data/public/avo-packs/css/application-f9191617.css.br +0 -0
  86. data/public/avo-packs/css/application-f9191617.css.map +0 -1
  87. data/public/avo-packs/css/application-f9191617.css.map.br +0 -0
  88. data/public/avo-packs/css/application-f9191617.css.map.gz +0 -0
  89. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js +0 -2
  90. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.br +0 -0
  91. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.gz +0 -0
  92. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.map +0 -1
  93. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.map.br +0 -0
  94. data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.map.gz +0 -0
  95. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js +0 -26
  96. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.br +0 -0
  97. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.gz +0 -0
  98. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.map +0 -1
  99. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.map.br +0 -0
  100. data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.map.gz +0 -0
@@ -14,6 +14,7 @@ module Avo
14
14
  class_attribute :resource
15
15
  class_attribute :fields
16
16
  class_attribute :standalone, default: false
17
+ class_attribute :visible
17
18
 
18
19
  attr_accessor :response
19
20
  attr_accessor :model
@@ -27,10 +28,11 @@ module Avo
27
28
  self.class.to_s.demodulize.underscore.humanize(keep_id_suffix: true)
28
29
  end
29
30
 
30
- def initialize(model: nil, resource: nil, user: nil)
31
+ def initialize(model: nil, resource: nil, user: nil, view: nil)
31
32
  self.class.model = model if model.present?
32
33
  self.class.resource = resource if resource.present?
33
34
  self.class.user = user if user.present?
35
+ self.class.view = view if view.present?
34
36
 
35
37
  self.class.message ||= I18n.t("avo.are_you_sure_you_want_to_run_this_option")
36
38
  self.class.confirm_button_label ||= I18n.t("avo.run")
@@ -96,6 +98,12 @@ module Avo
96
98
  self
97
99
  end
98
100
 
101
+ def visible_in_view
102
+ return true unless visible.present?
103
+
104
+ instance_exec(resource: self.class.resource, view: view, &visible)
105
+ end
106
+
99
107
  def param_id
100
108
  self.class.to_s.demodulize.underscore.tr "/", "_"
101
109
  end
@@ -4,6 +4,14 @@ module Avo
4
4
  extend FieldsCollector
5
5
  extend HasContext
6
6
 
7
+ include ActionView::Helpers::UrlHelper
8
+
9
+ delegate :view_context, to: 'Avo::App'
10
+ delegate :main_app, to: :view_context
11
+ delegate :avo, to: :view_context
12
+ delegate :resource_path, to: :view_context
13
+ delegate :resources_path, to: :view_context
14
+
7
15
  attr_accessor :view
8
16
  attr_accessor :model
9
17
  attr_accessor :user
@@ -74,7 +82,9 @@ module Avo
74
82
  end
75
83
 
76
84
  def initialize
77
- self.class.model_class = model_class.base_class
85
+ unless self.class.model_class.present?
86
+ self.class.model_class = model_class.base_class
87
+ end
78
88
  end
79
89
 
80
90
  def hydrate(model: nil, view: nil, user: nil, params: nil)
@@ -256,10 +266,6 @@ module Avo
256
266
  view_types
257
267
  end
258
268
 
259
- def route_key
260
- model_class.model_name.route_key
261
- end
262
-
263
269
  def context
264
270
  self.class.context
265
271
  end
@@ -358,8 +364,28 @@ module Avo
358
364
  end
359
365
  end
360
366
 
361
- def avo_path
362
- "#{Avo::App.root_path}/resources/#{model_class.model_name.route_key}/#{model.id}"
367
+ def route_key
368
+ model_class.model_name.route_key
369
+ end
370
+
371
+ # This is used as the model class ID
372
+ # We use this instead of the route_key to maintain compatibility with uncountable models
373
+ # With uncountable models route key appends an _index suffix (Fish->fish_index)
374
+ # Example: User->users, MediaItem->medie_items, Fish->fish
375
+ def model_key
376
+ model_class.model_name.plural
377
+ end
378
+
379
+ def singular_model_key
380
+ model_class.model_name.singular
381
+ end
382
+
383
+ def record_path
384
+ resource_path(model: model, resource: self)
385
+ end
386
+
387
+ def records_path
388
+ resources_path(resource: self)
363
389
  end
364
390
 
365
391
  def label_field
@@ -26,6 +26,7 @@ module Avo
26
26
  attr_accessor :view_component_path
27
27
  attr_accessor :display_license_request_timeout_error
28
28
  attr_accessor :current_user_resource_name
29
+ attr_accessor :raise_error_on_missing_policy
29
30
 
30
31
  def initialize
31
32
  @root_path = "/avo"
@@ -64,6 +65,7 @@ module Avo
64
65
  @view_component_path = "app/components"
65
66
  @display_license_request_timeout_error = true
66
67
  @current_user_resource_name = "user"
68
+ @raise_error_on_missing_policy = false
67
69
  end
68
70
 
69
71
  def locale_tag
@@ -3,8 +3,14 @@ module Avo
3
3
  class BaseField
4
4
  extend ActiveSupport::DescendantsTracker
5
5
  extend Avo::Fields::FieldExtensions::HasFieldName
6
+
7
+ include ActionView::Helpers::UrlHelper
6
8
  include Avo::Fields::FieldExtensions::VisibleInDifferentViews
7
9
 
10
+ delegate :view_context, to: 'Avo::App'
11
+ delegate :main_app, to: :view_context
12
+ delegate :avo, to: :view_context
13
+
8
14
  attr_reader :id
9
15
  attr_reader :block
10
16
  attr_reader :required
@@ -121,11 +127,11 @@ module Avo
121
127
 
122
128
  # Run callback block if present
123
129
  if computable && block.present?
124
- final_value = block.call @model, @resource, @view, self
130
+ final_value = instance_exec(@model, @resource, @view, self, &block)
125
131
  end
126
132
 
127
133
  # Run the value through resolver if present
128
- final_value = @format_using.call final_value if @format_using.present?
134
+ final_value = instance_exec(final_value, &@format_using) if @format_using.present?
129
135
 
130
136
  final_value
131
137
  end
@@ -1,6 +1,6 @@
1
1
  module Avo
2
2
  module Fields
3
- class HasAndBelongsToManyField < BaseField
3
+ class HasAndBelongsToManyField < HasBaseField
4
4
  def initialize(id, **args, &block)
5
5
  args[:updatable] = false
6
6
 
@@ -13,24 +13,6 @@ module Avo
13
13
  def view_component_name
14
14
  "HasManyField"
15
15
  end
16
-
17
- def turbo_frame
18
- "#{self.class.name.demodulize.to_s.underscore}_#{id}"
19
- end
20
-
21
- def frame_url
22
- "#{Avo::App.root_path}/resources/#{@model.model_name.route_key}/#{@model.id}/#{id}?turbo_frame=#{turbo_frame}"
23
- end
24
-
25
- def target_resource
26
- if @model._reflections[id.to_s].klass.present?
27
- Avo::App.get_resource_by_model_name @model._reflections[id.to_s].klass.to_s
28
- elsif @model._reflections[id.to_s].options[:class_name].present?
29
- Avo::App.get_resource_by_model_name @model._reflections[id.to_s].options[:class_name]
30
- else
31
- Avo::App.get_resource_by_name id.to_s
32
- end
33
- end
34
16
  end
35
17
  end
36
18
  end
@@ -0,0 +1,35 @@
1
+ module Avo
2
+ module Fields
3
+ class HasBaseField < BaseField
4
+ attr_accessor :display
5
+
6
+ def initialize(id, **args, &block)
7
+ super(id, **args, &block)
8
+
9
+ @display = args[:display].present? ? args[:display] : :show
10
+ end
11
+
12
+ def resource
13
+ Avo::App.get_resource_by_model_name @model.class
14
+ end
15
+
16
+ def turbo_frame
17
+ "#{self.class.name.demodulize.to_s.underscore}_#{display}_#{id}"
18
+ end
19
+
20
+ def frame_url
21
+ "#{@resource.record_path}/#{id}?turbo_frame=#{turbo_frame}"
22
+ end
23
+
24
+ def target_resource
25
+ if @model._reflections[id.to_s].klass.present?
26
+ Avo::App.get_resource_by_model_name @model._reflections[id.to_s].klass.to_s
27
+ elsif @model._reflections[id.to_s].options[:class_name].present?
28
+ Avo::App.get_resource_by_model_name @model._reflections[id.to_s].options[:class_name]
29
+ else
30
+ Avo::App.get_resource_by_name id.to_s
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,6 +1,6 @@
1
1
  module Avo
2
2
  module Fields
3
- class HasManyField < BaseField
3
+ class HasManyField < HasBaseField
4
4
  def initialize(id, **args, &block)
5
5
  args[:updatable] = false
6
6
 
@@ -9,24 +9,6 @@ module Avo
9
9
  hide_on :all
10
10
  show_on :show
11
11
  end
12
-
13
- def turbo_frame
14
- "#{self.class.name.demodulize.to_s.underscore}_#{id}"
15
- end
16
-
17
- def frame_url
18
- "#{Avo::App.root_path}/resources/#{@model.model_name.route_key}/#{@model.id}/#{id}?turbo_frame=#{turbo_frame}"
19
- end
20
-
21
- def target_resource
22
- if @model._reflections[id.to_s].klass.present?
23
- Avo::App.get_resource_by_model_name @model._reflections[id.to_s].klass.to_s
24
- elsif @model._reflections[id.to_s].options[:class_name].present?
25
- Avo::App.get_resource_by_model_name @model._reflections[id.to_s].options[:class_name]
26
- else
27
- Avo::App.get_resource_by_name id.to_s
28
- end
29
- end
30
12
  end
31
13
  end
32
14
  end
@@ -1,8 +1,7 @@
1
1
  module Avo
2
2
  module Fields
3
- class HasOneField < BaseField
3
+ class HasOneField < HasBaseField
4
4
  attr_accessor :relation_method
5
- attr_accessor :display
6
5
 
7
6
  def initialize(id, **args, &block)
8
7
  super(id, **args, &block)
@@ -12,7 +11,6 @@ module Avo
12
11
  @placeholder ||= I18n.t "avo.choose_an_option"
13
12
 
14
13
  @relation_method = name.to_s.parameterize.underscore
15
- @display = args[:display].present? ? args[:display] : :show
16
14
  end
17
15
 
18
16
  def label
@@ -20,25 +18,11 @@ module Avo
20
18
  end
21
19
 
22
20
  def resource
23
- target_resource
24
- end
25
-
26
- def turbo_frame
27
- "#{self.class.name.demodulize.to_s.underscore}_#{display}_#{id}"
21
+ Avo::App.get_resource_by_model_name @model.class
28
22
  end
29
23
 
30
24
  def frame_url
31
- "#{Avo::App.root_path}/resources/#{@model.model_name.route_key}/#{@model.id}/#{id}/#{value.id}?turbo_frame=#{turbo_frame}"
32
- end
33
-
34
- def target_resource
35
- if @model._reflections[id.to_s].klass.present?
36
- Avo::App.get_resource_by_model_name @model._reflections[id.to_s].klass.to_s
37
- elsif @model._reflections[id.to_s].options[:class_name].present?
38
- Avo::App.get_resource_by_model_name @model._reflections[id.to_s].options[:class_name]
39
- else
40
- Avo::App.get_resource_by_name id.to_s
41
- end
25
+ "#{@resource.record_path}/#{id}/#{value.id}?turbo_frame=#{turbo_frame}"
42
26
  end
43
27
 
44
28
  def fill_field(model, key, value, params)
@@ -48,8 +48,10 @@ module Avo
48
48
  end
49
49
 
50
50
  true
51
- rescue Pundit::NotDefinedError
52
- false
51
+ rescue Pundit::NotDefinedError => e
52
+ return false unless Avo.configuration.raise_error_on_missing_policy
53
+
54
+ raise e
53
55
  rescue => error
54
56
  if args[:raise_exception] == false
55
57
  false
@@ -73,8 +75,10 @@ module Avo
73
75
 
74
76
  begin
75
77
  Pundit.policy_scope! user, model
76
- rescue
77
- model
78
+ rescue Pundit::NotDefinedError => e
79
+ return model unless Avo.configuration.raise_error_on_missing_policy
80
+
81
+ raise e
78
82
  end
79
83
  end
80
84
 
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "1.18.2"
2
+ VERSION = "1.19.0"
3
3
  end
@@ -84,3 +84,5 @@ en:
84
84
  placeholder: 'Search'
85
85
  cancel_button: 'Cancel'
86
86
  sign_out: 'Sign out'
87
+ failed: 'Failed'
88
+ failed_to_load: 'Failed to load'
@@ -3258,6 +3258,43 @@ input[type=file][data-direct-upload-url][disabled] {
3258
3258
  display: none;
3259
3259
  }
3260
3260
 
3261
+ .button-spinner {
3262
+ width: 24px;
3263
+ height: 24px;
3264
+
3265
+ position: relative;
3266
+ margin: 100px auto;
3267
+ }
3268
+
3269
+ .button-spinner > .double-bounce1,
3270
+ .button-spinner > .double-bounce2 {
3271
+ width: 100%;
3272
+ height: 100%;
3273
+ border-radius: 50%;
3274
+ background-color: #333;
3275
+ opacity: 0.5;
3276
+ position: absolute;
3277
+ top: 0;
3278
+ left: 0;
3279
+ animation: sk-bounce 2s infinite ease-in-out;
3280
+ }
3281
+
3282
+ .button-spinner > .double-bounce2 {
3283
+ animation-delay: -1s;
3284
+ }
3285
+
3286
+ @keyframes sk-bounce {
3287
+ 0%,
3288
+ 100% {
3289
+ transform: scale(0);
3290
+ -webkit-transform: scale(0);
3291
+ }
3292
+ 50% {
3293
+ transform: scale(1);
3294
+ -webkit-transform: scale(1);
3295
+ }
3296
+ }
3297
+
3261
3298
  .spinner {
3262
3299
  width: 16px;
3263
3300
  height: 16px;
@@ -3265,8 +3302,8 @@ input[type=file][data-direct-upload-url][disabled] {
3265
3302
  position: relative;
3266
3303
  }
3267
3304
 
3268
-
3269
- .double-bounce1, .double-bounce2 {
3305
+ .spinner .double-bounce1,
3306
+ .spinner .double-bounce2 {
3270
3307
  width: 100%;
3271
3308
  height: 100%;
3272
3309
  border-radius: 50%;
@@ -3275,20 +3312,22 @@ input[type=file][data-direct-upload-url][disabled] {
3275
3312
  position: absolute;
3276
3313
  top: 0;
3277
3314
  left: 0;
3278
- animation: sk-bounce 2.0s infinite ease-in-out;
3315
+ animation: sk-bounce 2s infinite ease-in-out;
3279
3316
  }
3280
3317
 
3281
- .double-bounce2 {
3282
- animation-delay: -1.0s;
3318
+ .spinner .double-bounce2 {
3319
+ animation-delay: -1s;
3283
3320
  }
3284
3321
 
3285
3322
  @keyframes sk-bounce {
3286
- 0%, 100% {
3287
- transform: scale(0.0);
3288
- -webkit-transform: scale(0.0);
3289
- } 50% {
3290
- transform: scale(1.0);
3291
- -webkit-transform: scale(1.0);
3323
+ 0%,
3324
+ 100% {
3325
+ transform: scale(0);
3326
+ -webkit-transform: scale(0);
3327
+ }
3328
+ 50% {
3329
+ transform: scale(1);
3330
+ -webkit-transform: scale(1);
3292
3331
  }
3293
3332
  }
3294
3333
 
@@ -4997,6 +5036,9 @@ progress[value]::-moz-progress-bar {
4997
5036
  .h-8 {
4998
5037
  height: 2rem
4999
5038
  }
5039
+ .h-40 {
5040
+ height: 10rem
5041
+ }
5000
5042
  .h-full {
5001
5043
  height: 100%
5002
5044
  }
@@ -6284,4 +6326,4 @@ html, body{
6284
6326
  }
6285
6327
 
6286
6328
 
6287
- /*# sourceMappingURL=application-f9191617.css.map*/
6329
+ /*# sourceMappingURL=application-c3b50b28.css.map*/