avo 2.0.0 → 2.1.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +3 -3
  4. data/app/assets/svgs/save.svg +8 -1
  5. data/app/components/avo/actions_component.html.erb +1 -1
  6. data/app/components/avo/alert_component.rb +5 -5
  7. data/app/components/avo/blank_field_component.html.erb +0 -0
  8. data/app/components/avo/blank_field_component.rb +4 -0
  9. data/app/components/avo/fields/badge_field/index_component.html.erb +1 -1
  10. data/app/components/avo/fields/boolean_field/index_component.html.erb +1 -1
  11. data/app/components/avo/fields/external_image_field/index_component.html.erb +1 -2
  12. data/app/components/avo/fields/file_field/index_component.html.erb +3 -3
  13. data/app/components/avo/fields/file_field/index_component.rb +11 -0
  14. data/app/components/avo/fields/gravatar_field/index_component.html.erb +1 -1
  15. data/app/components/avo/fields/progress_bar_field/index_component.html.erb +1 -1
  16. data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
  17. data/app/components/avo/index/field_wrapper_component.rb +12 -1
  18. data/app/components/avo/index/resource_controls_component.html.erb +5 -1
  19. data/app/components/avo/index/resource_table_component.html.erb +1 -1
  20. data/app/components/avo/panel_component.html.erb +10 -2
  21. data/app/components/avo/panel_component.rb +9 -0
  22. data/app/components/avo/referrer_params_component.html.erb +4 -0
  23. data/app/components/avo/referrer_params_component.rb +9 -0
  24. data/app/components/avo/sidebar_component.rb +3 -1
  25. data/app/components/avo/views/resource_edit_component.html.erb +14 -1
  26. data/app/components/avo/views/resource_new_component.html.erb +13 -0
  27. data/app/components/avo/views/resource_show_component.html.erb +1 -0
  28. data/app/controllers/avo/application_controller.rb +1 -1
  29. data/app/controllers/avo/base_controller.rb +57 -27
  30. data/app/controllers/avo/dashboards_controller.rb +1 -1
  31. data/app/controllers/avo/search_controller.rb +5 -1
  32. data/app/javascript/avo.js +4 -3
  33. data/app/views/avo/actions/show.html.erb +1 -0
  34. data/app/views/avo/associations/new.html.erb +1 -0
  35. data/app/views/avo/home/failed_to_load.html.erb +21 -1
  36. data/app/views/layouts/avo/application.html.erb +7 -0
  37. data/bin/dev +7 -6
  38. data/lib/avo/app.rb +8 -1
  39. data/lib/avo/base_action.rb +4 -4
  40. data/lib/avo/base_resource.rb +26 -7
  41. data/lib/avo/configuration.rb +2 -0
  42. data/lib/avo/dashboards/base_dashboard.rb +17 -0
  43. data/lib/avo/dashboards/chartkick_card.rb +1 -1
  44. data/lib/avo/fields/base_field.rb +19 -6
  45. data/lib/avo/fields/belongs_to_field.rb +1 -1
  46. data/lib/avo/fields/external_image_field.rb +2 -2
  47. data/lib/avo/hosts/dashboard_visibility.rb +19 -0
  48. data/lib/avo/licensing/pro_license.rb +1 -0
  49. data/lib/avo/version.rb +1 -1
  50. data/lib/generators/avo/templates/dashboards/dashboard.tt +4 -1
  51. data/public/avo-assets/avo.css +37 -21
  52. data/public/avo-assets/avo.js +166 -165
  53. data/public/avo-assets/avo.js.map +3 -3
  54. metadata +7 -3
  55. data/app/views/avo/partials/_failed_state.html.erb +0 -16
data/bin/dev CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
- if ! command -v foreman &> /dev/null
4
- then
5
- echo "Installing foreman..."
6
- gem install foreman
7
- fi
3
+ PORT="${PORT:-3030}"
4
+ export PORT
8
5
 
9
- foreman start -f Procfile.dev
6
+ if command -v overmind &> /dev/null; then
7
+ overmind start -f Procfile.dev "$@"
8
+ else
9
+ foreman start -f Procfile.dev "$@"
10
+ fi
data/lib/avo/app.rb CHANGED
@@ -10,6 +10,8 @@ module Avo
10
10
  class_attribute :current_user, default: nil
11
11
  class_attribute :root_path, default: nil
12
12
  class_attribute :view_context, default: nil
13
+ class_attribute :params, default: {}
14
+ class_attribute :translation_enabled, default: false
13
15
 
14
16
  class << self
15
17
  def boot
@@ -24,14 +26,16 @@ module Avo
24
26
  end
25
27
  end
26
28
 
27
- def init(request:, context:, current_user:, root_path:, view_context:)
29
+ def init(request:, context:, current_user:, root_path:, view_context:, params:)
28
30
  self.request = request
29
31
  self.context = context
30
32
  self.current_user = current_user
31
33
  self.root_path = root_path
32
34
  self.view_context = view_context
35
+ self.params = params
33
36
 
34
37
  self.license = Licensing::LicenseManager.new(Licensing::HQ.new(request).response).license
38
+ self.translation_enabled = license.has(:localization)
35
39
 
36
40
  # Set the current host for ActiveStorage
37
41
  begin
@@ -89,6 +93,9 @@ module Avo
89
93
  .select do |dashboard|
90
94
  dashboard != Dashboards::BaseDashboard
91
95
  end
96
+ .uniq do |dashboard|
97
+ dashboard.id
98
+ end
92
99
  end
93
100
 
94
101
  # Returns the Avo dashboard by id
@@ -27,16 +27,16 @@ module Avo
27
27
  def form_data_attributes
28
28
  # We can't respond with a file download from Turbo se we disable it on the form
29
29
  if may_download_file
30
- { 'turbo': false }
30
+ {turbo: false, remote: false}
31
31
  else
32
- { 'turbo-frame': '_top', 'action-target': 'form' }
32
+ {"turbo-frame": "_top", "action-target": "form"}
33
33
  end
34
34
  end
35
35
 
36
36
  # We can't respond with a file download from Turbo se we disable close the modal manually after a while (it's a hack, we know)
37
37
  def submit_button_data_attributes
38
38
  if may_download_file
39
- { action: 'click->modal#delayedClose' }
39
+ {action: "click->modal#delayedClose"}
40
40
  else
41
41
  {}
42
42
  end
@@ -109,7 +109,7 @@ module Avo
109
109
  args = {
110
110
  fields: processed_fields,
111
111
  current_user: current_user,
112
- resource: resource,
112
+ resource: resource
113
113
  }
114
114
 
115
115
  args[:models] = models unless standalone
@@ -11,6 +11,7 @@ module Avo
11
11
  delegate :avo, to: :view_context
12
12
  delegate :resource_path, to: :view_context
13
13
  delegate :resources_path, to: :view_context
14
+ delegate :t, to: ::I18n
14
15
 
15
16
  attr_accessor :view
16
17
  attr_accessor :model
@@ -26,7 +27,7 @@ module Avo
26
27
  class_attribute :includes, default: []
27
28
  class_attribute :model_class
28
29
  class_attribute :translation_key
29
- class_attribute :translation_enabled
30
+ class_attribute :translation_enabled, default: false
30
31
  class_attribute :default_view_type, default: :table
31
32
  class_attribute :devise_password_optional, default: false
32
33
  class_attribute :actions_loader
@@ -38,8 +39,11 @@ module Avo
38
39
  class_attribute :resolve_query_scope
39
40
  class_attribute :resolve_find_scope
40
41
  class_attribute :ordering
42
+ class_attribute :search_hide_from_global_search, default: false
41
43
 
42
44
  class << self
45
+ delegate :t, to: ::I18n
46
+
43
47
  def grid(&block)
44
48
  grid_collector = GridCollector.new
45
49
  grid_collector.instance_eval(&block)
@@ -96,6 +100,8 @@ module Avo
96
100
  self.class.model_class = model_class.base_class
97
101
  end
98
102
  end
103
+
104
+ self.class.translation_enabled = ::Avo::App.translation_enabled
99
105
  end
100
106
 
101
107
  def hydrate(model: nil, view: nil, user: nil, params: nil)
@@ -215,7 +221,7 @@ module Avo
215
221
  when :edit
216
222
  model_title
217
223
  when :new
218
- I18n.t("avo.create_new_item", item: name.downcase).upcase_first
224
+ t("avo.create_new_item", item: name.downcase).upcase_first
219
225
  end
220
226
  end
221
227
 
@@ -244,9 +250,18 @@ module Avo
244
250
  class_name_without_resource.safe_constantize
245
251
  end
246
252
 
253
+ def model_id
254
+ @model.send id
255
+ end
256
+
247
257
  def model_title
248
- return @model.send title if @model.present?
258
+ return name if @model.nil?
249
259
 
260
+ the_title = @model.send title
261
+ return the_title if the_title.present?
262
+
263
+ model_id
264
+ rescue
250
265
  name
251
266
  end
252
267
 
@@ -267,11 +282,13 @@ module Avo
267
282
  end
268
283
 
269
284
  def name
285
+ default = class_name_without_resource.titlecase
286
+
270
287
  return @name if @name.present?
271
288
 
272
- return I18n.t(translation_key, count: 1).capitalize if translation_key
289
+ return t(translation_key, count: 1, default: default).capitalize if translation_key
273
290
 
274
- class_name_without_resource.titlecase
291
+ default
275
292
  end
276
293
 
277
294
  def singular_name
@@ -279,9 +296,11 @@ module Avo
279
296
  end
280
297
 
281
298
  def plural_name
282
- return I18n.t(translation_key, count: 2).capitalize if translation_key
299
+ default = name.pluralize
300
+
301
+ return t(translation_key, count: 2, default: default).capitalize if translation_key
283
302
 
284
- name.pluralize
303
+ default
285
304
  end
286
305
 
287
306
  def underscore_name
@@ -28,6 +28,7 @@ module Avo
28
28
  attr_accessor :current_user_resource_name
29
29
  attr_accessor :raise_error_on_missing_policy
30
30
  attr_accessor :disabled_features
31
+ attr_accessor :buttons_on_form_footers
31
32
 
32
33
  def initialize
33
34
  @root_path = "/avo"
@@ -68,6 +69,7 @@ module Avo
68
69
  @current_user_resource_name = "user"
69
70
  @raise_error_on_missing_policy = false
70
71
  @disabled_features = []
72
+ @buttons_on_form_footers = false
71
73
  end
72
74
 
73
75
  def locale_tag
@@ -8,6 +8,7 @@ module Avo
8
8
  class_attribute :description
9
9
  class_attribute :items_holder
10
10
  class_attribute :grid_cols, default: 3
11
+ class_attribute :visible, default: true
11
12
 
12
13
  class << self
13
14
  def card(klass)
@@ -48,6 +49,22 @@ module Avo
48
49
  def navigation_path
49
50
  "#{Avo::App.root_path}/dashboards/#{id}"
50
51
  end
52
+
53
+ def is_visible?
54
+ # Default is true
55
+ return true if visible == true
56
+
57
+ # Hide if false
58
+ return false if visible == false
59
+
60
+ if visible.respond_to? :call
61
+ ::Avo::Hosts::DashboardVisibility.new(block: visible, dashboard: self).handle
62
+ end
63
+ end
64
+
65
+ def is_hidden?
66
+ !is_visible?
67
+ end
51
68
  end
52
69
  end
53
70
  end
@@ -24,7 +24,7 @@ module Avo
24
24
 
25
25
  def chartkick_options
26
26
  card_height = 144
27
- card_heading = 32
27
+ card_heading = 40
28
28
 
29
29
  default = {
30
30
  # figure our the available height for the chart
@@ -10,6 +10,7 @@ module Avo
10
10
  delegate :view_context, to: "Avo::App"
11
11
  delegate :main_app, to: :view_context
12
12
  delegate :avo, to: :view_context
13
+ delegate :t, to: ::I18n
13
14
 
14
15
  attr_reader :id
15
16
  attr_reader :block
@@ -48,7 +49,7 @@ module Avo
48
49
  @id = id
49
50
  @name = args[:name]
50
51
  @translation_key = args[:translation_key]
51
- @translation_enabled = false
52
+ @translation_enabled = ::Avo::App.translation_enabled
52
53
  @block = block
53
54
  @required = args[:required] || false
54
55
  @readonly = args[:readonly] || false
@@ -94,18 +95,26 @@ module Avo
94
95
  @translation_key
95
96
  end
96
97
 
98
+ # Getting the name of the resource (user/users, post/posts)
99
+ # We'll first check to see if the user passed a name
100
+ # Secondly we'll try to find a translation key
101
+ # We'll fallback to humanizing the id
97
102
  def name
103
+ default = @id.to_s.humanize(keep_id_suffix: true)
104
+
98
105
  return @name if @name.present?
99
106
 
100
- return I18n.t(translation_key, count: 1).capitalize if translation_key
107
+ return t(translation_key, count: 1, default: default).capitalize if @translation_key
101
108
 
102
- @id.to_s.humanize(keep_id_suffix: true)
109
+ default
103
110
  end
104
111
 
105
112
  def plural_name
106
- return I18n.t(translation_key, count: 2).capitalize if translation_key
113
+ default = name.pluralize
114
+
115
+ return t(translation_key, count: 2, default: default).capitalize if @translation_key
107
116
 
108
- name.pluralize
117
+ default
109
118
  end
110
119
 
111
120
  def placeholder
@@ -181,8 +190,12 @@ module Avo
181
190
  "#{type.camelize}Field"
182
191
  end
183
192
 
193
+ # Try and build the component class or fallback to a blank one
184
194
  def component_for_view(view = :index)
185
- "Avo::Fields::#{view_component_name}::#{view.to_s.camelize}Component".safe_constantize
195
+ component_class = "::Avo::Fields::#{view_component_name}::#{view.to_s.camelize}Component"
196
+ component_class.constantize
197
+ rescue
198
+ ::Avo::BlankFieldComponent
186
199
  end
187
200
 
188
201
  def model_errors
@@ -70,7 +70,7 @@ module Avo
70
70
  @searchable = args[:searchable] == true
71
71
  @polymorphic_as = args[:polymorphic_as]
72
72
  @types = args[:types]
73
- @relation_method = name.to_s.parameterize.underscore
73
+ @relation_method = id.to_s.parameterize.underscore
74
74
  end
75
75
 
76
76
  def searchable
@@ -11,8 +11,8 @@ module Avo
11
11
 
12
12
  @link_to_resource = args[:link_to_resource].present? ? args[:link_to_resource] : false
13
13
 
14
- @width = args[:width].present? ? args[:width] : 32
15
- @height = args[:height].present? ? args[:height] : 32
14
+ @width = args[:width].present? ? args[:width] : 40
15
+ @height = args[:height].present? ? args[:height] : 40
16
16
  @radius = args[:radius].present? ? args[:radius] : 0
17
17
  end
18
18
 
@@ -0,0 +1,19 @@
1
+ require "dry-initializer"
2
+
3
+ module Avo
4
+ module Hosts
5
+ class DashboardVisibility
6
+ extend Dry::Initializer
7
+
8
+ option :block, default: proc { proc {} }
9
+ option :current_user, default: proc { ::Avo::App.current_user }
10
+ option :context, default: proc { ::Avo::App.context }
11
+ option :dashboard
12
+ option :params, default: proc { ::Avo::App.params }
13
+
14
+ def handle
15
+ instance_exec(&block)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -4,6 +4,7 @@ module Avo
4
4
  def abilities
5
5
  [
6
6
  :authorization,
7
+ :localization,
7
8
  :custom_tools,
8
9
  :custom_fields,
9
10
  :global_search,
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.0.0"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -3,7 +3,10 @@ class <%= class_name.camelize %> < Avo::Dashboards::BaseDashboard
3
3
  self.name = "<%= name.underscore.humanize %>"
4
4
  # self.description = "Tiny dashboard description"
5
5
  # self.grid_cols = 3
6
+ # self.visible = -> do
7
+ # true
8
+ # end
6
9
 
7
10
  # cards go here
8
- # card metric: UsersCount
11
+ # card UsersCount
9
12
  end
@@ -6220,10 +6220,6 @@ progress[value]::-moz-progress-bar{
6220
6220
  left:0px
6221
6221
  }
6222
6222
 
6223
- .bottom-0{
6224
- bottom:0px
6225
- }
6226
-
6227
6223
  .left-1\/2{
6228
6224
  left:50%
6229
6225
  }
@@ -6232,6 +6228,10 @@ progress[value]::-moz-progress-bar{
6232
6228
  top:50%
6233
6229
  }
6234
6230
 
6231
+ .bottom-0{
6232
+ bottom:0px
6233
+ }
6234
+
6235
6235
  .left-auto{
6236
6236
  left:auto
6237
6237
  }
@@ -6377,14 +6377,6 @@ progress[value]::-moz-progress-bar{
6377
6377
  margin-top:0.25rem
6378
6378
  }
6379
6379
 
6380
- .mb-4{
6381
- margin-bottom:1rem
6382
- }
6383
-
6384
- .mr-1{
6385
- margin-right:0.25rem
6386
- }
6387
-
6388
6380
  .-ml-20{
6389
6381
  margin-left:-5rem
6390
6382
  }
@@ -6413,6 +6405,14 @@ progress[value]::-moz-progress-bar{
6413
6405
  margin-top:-2.5rem
6414
6406
  }
6415
6407
 
6408
+ .mb-4{
6409
+ margin-bottom:1rem
6410
+ }
6411
+
6412
+ .mr-1{
6413
+ margin-right:0.25rem
6414
+ }
6415
+
6416
6416
  .mr-4{
6417
6417
  margin-right:1rem
6418
6418
  }
@@ -6437,6 +6437,10 @@ progress[value]::-moz-progress-bar{
6437
6437
  margin-bottom:0.5rem
6438
6438
  }
6439
6439
 
6440
+ .mt-6{
6441
+ margin-top:1.5rem
6442
+ }
6443
+
6440
6444
  .mt-3{
6441
6445
  margin-top:0.75rem
6442
6446
  }
@@ -6545,10 +6549,6 @@ progress[value]::-moz-progress-bar{
6545
6549
  height:100%
6546
6550
  }
6547
6551
 
6548
- .h-6{
6549
- height:1.5rem
6550
- }
6551
-
6552
6552
  .h-40{
6553
6553
  height:10rem
6554
6554
  }
@@ -6561,6 +6561,10 @@ progress[value]::-moz-progress-bar{
6561
6561
  height:2rem
6562
6562
  }
6563
6563
 
6564
+ .h-6{
6565
+ height:1.5rem
6566
+ }
6567
+
6564
6568
  .h-\[250px\]{
6565
6569
  height:250px
6566
6570
  }
@@ -6991,6 +6995,10 @@ progress[value]::-moz-progress-bar{
6991
6995
  border-width:1px
6992
6996
  }
6993
6997
 
6998
+ .border-b-2{
6999
+ border-bottom-width:2px
7000
+ }
7001
+
6994
7002
  .border-b{
6995
7003
  border-bottom-width:1px
6996
7004
  }
@@ -7007,6 +7015,10 @@ progress[value]::-moz-progress-bar{
7007
7015
  border-left-width:1px
7008
7016
  }
7009
7017
 
7018
+ .border-dashed{
7019
+ border-style:dashed
7020
+ }
7021
+
7010
7022
  .border-slate-500{
7011
7023
  --tw-border-opacity:1;
7012
7024
  border-color:rgb(100 116 139 / var(--tw-border-opacity))
@@ -7314,6 +7326,11 @@ progress[value]::-moz-progress-bar{
7314
7326
  padding-right:0px
7315
7327
  }
7316
7328
 
7329
+ .py-12{
7330
+ padding-top:3rem;
7331
+ padding-bottom:3rem
7332
+ }
7333
+
7317
7334
  .py-6{
7318
7335
  padding-top:1.5rem;
7319
7336
  padding-bottom:1.5rem
@@ -7324,11 +7341,6 @@ progress[value]::-moz-progress-bar{
7324
7341
  padding-right:1.5rem
7325
7342
  }
7326
7343
 
7327
- .py-12{
7328
- padding-top:3rem;
7329
- padding-bottom:3rem
7330
- }
7331
-
7332
7344
  .py-0\.5{
7333
7345
  padding-top:0.125rem;
7334
7346
  padding-bottom:0.125rem
@@ -8712,6 +8724,10 @@ trix-editor {
8712
8724
  }
8713
8725
 
8714
8726
  @media (min-width: 1280px){
8727
+ .xl\:right-0{
8728
+ right:0px
8729
+ }
8730
+
8715
8731
  .xl\:mt-0{
8716
8732
  margin-top:0px
8717
8733
  }