avo 2.16.1.pre.1.nativefields → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -2
  3. data/Gemfile.lock +3 -1
  4. data/README.md +1 -1
  5. data/app/assets/config/avo_manifest.js +1 -0
  6. data/app/assets/svgs/placeholder.svg +1 -0
  7. data/app/components/avo/actions_component.html.erb +3 -3
  8. data/app/components/avo/base_component.rb +7 -4
  9. data/app/components/avo/field_wrapper_component.html.erb +8 -10
  10. data/app/components/avo/field_wrapper_component.rb +14 -12
  11. data/app/components/avo/fields/badge_field/index_component.html.erb +1 -1
  12. data/app/components/avo/fields/belongs_to_field/edit_component.rb +9 -3
  13. data/app/components/avo/fields/belongs_to_field/index_component.html.erb +1 -1
  14. data/app/components/avo/fields/belongs_to_field/show_component.html.erb +1 -1
  15. data/app/components/avo/fields/belongs_to_field/show_component.rb +1 -1
  16. data/app/components/avo/fields/boolean_field/index_component.html.erb +1 -1
  17. data/app/components/avo/fields/boolean_field/show_component.html.erb +1 -1
  18. data/app/components/avo/fields/boolean_group_field/index_component.html.erb +1 -1
  19. data/app/components/avo/fields/boolean_group_field/show_component.html.erb +1 -1
  20. data/app/components/avo/fields/code_field/show_component.html.erb +1 -1
  21. data/app/components/avo/fields/common/heading_component.html.erb +5 -4
  22. data/app/components/avo/fields/common/heading_component.rb +6 -1
  23. data/app/components/avo/fields/country_field/index_component.html.erb +1 -1
  24. data/app/components/avo/fields/date_field/index_component.html.erb +1 -1
  25. data/app/components/avo/fields/date_time_field/index_component.html.erb +1 -1
  26. data/app/components/avo/fields/edit_component.rb +6 -4
  27. data/app/components/avo/fields/external_image_field/index_component.html.erb +1 -1
  28. data/app/components/avo/fields/file_field/edit_component.html.erb +2 -1
  29. data/app/components/avo/fields/file_field/index_component.html.erb +1 -1
  30. data/app/components/avo/fields/files_field/edit_component.html.erb +2 -1
  31. data/app/components/avo/fields/files_field/index_component.html.erb +1 -1
  32. data/app/components/avo/fields/files_field/show_component.html.erb +1 -1
  33. data/app/components/avo/fields/gravatar_field/index_component.html.erb +1 -1
  34. data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
  35. data/app/components/avo/fields/heading_field/edit_component.html.erb +1 -1
  36. data/app/components/avo/fields/heading_field/show_component.html.erb +1 -1
  37. data/app/components/avo/fields/id_field/index_component.html.erb +1 -1
  38. data/app/components/avo/fields/index_component.rb +11 -2
  39. data/app/components/avo/fields/number_field/index_component.html.erb +1 -1
  40. data/app/components/avo/fields/progress_bar_field/index_component.html.erb +1 -1
  41. data/app/components/avo/fields/select_field/index_component.html.erb +1 -1
  42. data/app/components/avo/fields/show_component.rb +7 -1
  43. data/app/components/avo/fields/status_field/index_component.html.erb +1 -1
  44. data/app/components/avo/fields/tags_field/index_component.html.erb +1 -1
  45. data/app/components/avo/fields/text_field/edit_component.html.erb +3 -1
  46. data/app/components/avo/fields/text_field/index_component.html.erb +1 -1
  47. data/app/components/avo/fields/trix_field/edit_component.html.erb +1 -1
  48. data/app/components/avo/filters_component.html.erb +2 -2
  49. data/app/components/avo/index/grid_cover_empty_state_component.html.erb +1 -1
  50. data/app/components/avo/index/grid_item_component.html.erb +15 -13
  51. data/app/components/avo/index/grid_item_component.rb +1 -1
  52. data/app/components/avo/index/ordering/buttons_component.html.erb +1 -1
  53. data/app/components/avo/index/resource_controls_component.rb +2 -2
  54. data/app/components/avo/index/table_row_component.html.erb +1 -1
  55. data/app/components/avo/panel_component.html.erb +11 -2
  56. data/app/components/avo/panel_component.rb +1 -0
  57. data/app/components/avo/resource_component.rb +18 -0
  58. data/app/components/avo/resource_sidebar_component.html.erb +19 -0
  59. data/app/components/avo/resource_sidebar_component.rb +26 -0
  60. data/app/components/avo/sidebar_profile_component.html.erb +1 -1
  61. data/app/components/avo/tab_switcher_component.html.erb +2 -2
  62. data/app/components/avo/views/resource_edit_component.html.erb +31 -25
  63. data/app/components/avo/views/resource_edit_component.rb +1 -1
  64. data/app/components/avo/views/resource_show_component.html.erb +8 -2
  65. data/app/components/avo/views/resource_show_component.rb +1 -1
  66. data/app/controllers/avo/actions_controller.rb +10 -2
  67. data/app/controllers/avo/application_controller.rb +4 -2
  68. data/app/controllers/avo/associations_controller.rb +10 -5
  69. data/app/controllers/avo/attachments_controller.rb +2 -1
  70. data/app/controllers/avo/base_controller.rb +6 -4
  71. data/app/controllers/avo/search_controller.rb +13 -4
  72. data/app/helpers/avo/application_helper.rb +3 -3
  73. data/app/helpers/avo/resources_helper.rb +2 -2
  74. data/app/javascript/avo.base.js +3 -1
  75. data/app/javascript/js/controllers/action_controller.js +1 -4
  76. data/app/javascript/js/controllers/actions_picker_controller.js +8 -9
  77. data/app/javascript/js/controllers/tabs_controller.js +14 -27
  78. data/app/views/avo/actions/show.html.erb +2 -2
  79. data/app/views/avo/home/failed_to_load.html.erb +3 -2
  80. data/config/brakeman.ignore +40 -0
  81. data/db/factories.rb +20 -0
  82. data/lib/avo/base_resource.rb +26 -0
  83. data/lib/avo/concerns/fetches_things.rb +1 -1
  84. data/lib/avo/concerns/has_fields.rb +22 -0
  85. data/lib/avo/concerns/is_resource_item.rb +4 -0
  86. data/lib/avo/configuration/branding.rb +9 -1
  87. data/lib/avo/fields/belongs_to_field.rb +3 -0
  88. data/lib/avo/fields/heading_field.rb +15 -0
  89. data/lib/avo/items_holder.rb +4 -0
  90. data/lib/avo/licensing/pro_license.rb +1 -0
  91. data/lib/avo/menu/builder.rb +1 -1
  92. data/lib/avo/menu/menu.rb +0 -2
  93. data/lib/avo/reloader.rb +27 -26
  94. data/lib/avo/services/encryption_service.rb +1 -1
  95. data/lib/avo/sidebar.rb +60 -0
  96. data/lib/avo/sidebar_builder.rb +24 -0
  97. data/lib/avo/version.rb +1 -1
  98. data/lib/generators/avo/templates/field/components/index_component.html.erb.tt +1 -1
  99. data/lib/generators/avo/templates/initializer/avo.tt +2 -1
  100. data/lib/generators/avo/templates/locales/avo.en.yml +0 -1
  101. data/lib/generators/avo/templates/locales/{avo.nb-NO.yml → avo.nb.yml} +35 -10
  102. data/lib/generators/avo/templates/locales/avo.nn.yml +118 -0
  103. data/lib/generators/avo/templates/locales/avo.tr.yml +119 -0
  104. data/public/avo-assets/avo.base.css +57 -75
  105. data/public/avo-assets/avo.base.js +63 -63
  106. data/public/avo-assets/avo.base.js.map +3 -3
  107. metadata +13 -7
  108. data/app/views/avo/home/failed_to_load.html copy.erb +0 -23
  109. data/config/master.key +0 -1
@@ -1,5 +1,5 @@
1
- import { castBoolean } from '../helpers/cast_boolean'
2
1
  import { Controller } from '@hotwired/stimulus'
2
+ import { castBoolean } from '../helpers/cast_boolean'
3
3
 
4
4
  export default class extends Controller {
5
5
  static targets = ['controllerDiv', 'resourceIds', 'form', 'selectedAllQuery']
@@ -7,8 +7,6 @@ export default class extends Controller {
7
7
  connect() {
8
8
  this.resourceIdsTarget.value = this.resourceIds
9
9
 
10
- console.log('something')
11
-
12
10
  // This value is picked up from the DOM so we check true/false as strings
13
11
  if (this.selectionOptions.itemSelectAllSelectedAllValue === 'true') {
14
12
  this.selectedAllQueryTarget.value = this.selectionOptions.itemSelectAllSelectedAllQueryValue
@@ -43,6 +41,5 @@ export default class extends Controller {
43
41
  } catch (error) {
44
42
  return []
45
43
  }
46
-
47
44
  }
48
45
  }
@@ -1,4 +1,3 @@
1
- import { AttributeObserver } from '@stimulus/mutation-observers'
2
1
  import { Controller } from '@hotwired/stimulus'
3
2
 
4
3
  export default class extends Controller {
@@ -12,6 +11,10 @@ export default class extends Controller {
12
11
  return this.target.dataset.disabled === 'true'
13
12
  }
14
13
 
14
+ get actionsShowTurboFrame() {
15
+ return document.querySelector('turbo-frame#actions_show')
16
+ }
17
+
15
18
  enableTarget() {
16
19
  if (this.targetIsDisabled) {
17
20
  this.target.classList.remove(...this.disabledClasses)
@@ -36,13 +39,9 @@ export default class extends Controller {
36
39
  }
37
40
 
38
41
  this.disableTarget()
39
-
40
- const observer = new AttributeObserver(document.querySelector('turbo-frame#actions_show'), 'busy', {
41
- elementUnmatchedAttribute: () => {
42
- this.enableTarget(this.target)
43
- if (observer) observer.stop()
44
- },
45
- })
46
- observer.start()
42
+ const that = this
43
+ setTimeout(() => {
44
+ this.actionsShowTurboFrame.loaded.then(() => that.enableTarget(that.target))
45
+ }, 1)
47
46
  }
48
47
  }
@@ -1,4 +1,3 @@
1
- import { AttributeObserver } from '@stimulus/mutation-observers'
2
1
  import { Controller } from '@hotwired/stimulus'
3
2
  import { castBoolean } from '../helpers/cast_boolean'
4
3
 
@@ -16,24 +15,22 @@ export default class extends Controller {
16
15
  )
17
16
  }
18
17
 
19
- targetTab(id) {
20
- return this.tabTargets.find((element) => element.dataset.tabsIdParam === id)
21
- }
22
-
23
18
  targetTabPanel(id) {
24
19
  return this.tabPanelTargets.find((element) => element.dataset.tabId === id)
25
20
  }
26
21
 
27
- changeTab(e) {
22
+ async changeTab(e) {
23
+ // Stopping the link execution.
24
+ // We're going to reveal a lazy-loaded frame to fulfill the tab change.
28
25
  e.preventDefault()
29
26
 
30
27
  const { params } = e
31
28
  const { id } = params
32
29
 
33
- this.setTheTargetPanelHeight(id)
30
+ await this.setTheTargetPanelHeight(id)
34
31
 
35
- this.hideTabs()
36
- this.showTab(id)
32
+ this.hideAllTabs()
33
+ this.revealTab(id)
37
34
  this.markTabLoaded(id)
38
35
 
39
36
  this.activeTabValue = id
@@ -42,7 +39,7 @@ export default class extends Controller {
42
39
  /**
43
40
  * Sets the target container height to the previous panel height so we don't get jerky tab changes.
44
41
  */
45
- setTheTargetPanelHeight(id) {
42
+ async setTheTargetPanelHeight(id) {
46
43
  // Ignore this on edit.
47
44
  // All tabs are loaded beforehand, they have their own height, and the page won't jiggle when the user toggles between them.
48
45
  if (this.viewValue === 'edit' || this.viewValue === 'new') {
@@ -60,31 +57,21 @@ export default class extends Controller {
60
57
  this.targetTabPanel(id).style.height = `${height}px`
61
58
 
62
59
  // Wait until the panel loaded it's content and then remove the forced height
63
- const observer = new AttributeObserver(this.targetTabPanel(id), 'busy', {
64
- elementUnmatchedAttribute: () => {
65
- // The content is not available in an instant so delay the height reset a bit.
66
- setTimeout(() => {
67
- this.targetTab(id).style.height = ''
68
- }, 300)
69
- if (observer) observer.stop()
70
- },
71
- })
72
- observer.start()
60
+ await this.targetTabPanel(id).loaded
61
+ this.targetTabPanel(id).style.height = ''
73
62
  }
74
63
 
64
+ // Marking tab as loaded so we know to skip some things the next time the user clicks on it
75
65
  markTabLoaded(id) {
76
66
  this.targetTabPanel(id).dataset.loaded = true
77
67
  }
78
68
 
79
- showTab(id) {
80
- this.tabPanelTargets.forEach((element) => {
81
- if (element.dataset.tabId === id) {
82
- element.classList.remove('hidden')
83
- }
84
- })
69
+ // We're revealing the new tab that's lazy loaded by Turbo.
70
+ revealTab(id) {
71
+ this.targetTabPanel(id).classList.remove('hidden')
85
72
  }
86
73
 
87
- hideTabs() {
74
+ hideAllTabs() {
88
75
  this.tabPanelTargets.map((element) => element.classList.add('hidden'))
89
76
  }
90
77
  }
@@ -23,12 +23,12 @@
23
23
  <%= form.hidden_field :avo_resource_ids, value: params[:resource_ids], 'data-action-target': 'resourceIds' %>
24
24
  <%= form.hidden_field :avo_selected_query, 'data-action-target': 'selectedAllQuery' %>
25
25
  <% if @action.get_fields.present? %>
26
- <div class="mt-4">
26
+ <div class="my-4 -mx-6">
27
27
  <% @action.get_fields.each_with_index do |field, index| %>
28
28
  <%= render field
29
29
  .hydrate(resource: @resource, model: @resource.model, user: @resource.user, view: @view)
30
30
  .component_for_view(:edit)
31
- .new(field: field, resource: @resource, index: index, form: form, displayed_in_modal: true)
31
+ .new(field: field, resource: @resource, index: index, form: form, compact: true)
32
32
  %>
33
33
  <% end %>
34
34
  </div>
@@ -2,15 +2,16 @@
2
2
  <%
3
3
  classes = 'absolute inset-auto left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2'
4
4
  label = t 'avo.failed_to_load'
5
+ src_url = params[:src].present? && !params[:src].starts_with?('http://') ? params.permit(:src).fetch(:src) : nil
5
6
  %>
6
7
  <div class="relative flex-1 py-4">
7
8
  <div class="relative block text-gray-300 h-64 w-full">
8
9
  <%= svg 'failed_to_load', class: "#{classes} h-52 text-gray-400" %>
9
10
  </div>
10
11
  <div class="relative block text-center text-lg text-gray-400 font-semibold pb-6"><%= label %> <span class="border-b-2 border-dashed"><%= params[:turbo_frame].to_s.humanize.downcase if params[:turbo_frame].present? %></span> frame</div>
11
- <% if Rails.env.development? %>
12
+ <% if Rails.env.development? && src_url %>
12
13
  <div class="text-center text-sm w-full pb-3">
13
- This is not an issue with Avo. Use <%= link_to 'this page', params[:src], target: :_blank %> to see why this frame failed to load.
14
+ This is not an issue with Avo. Use <%= link_to 'this page', src_url, target: :_blank %> to see why this frame failed to load.
14
15
  </div>
15
16
  <% end %>
16
17
  </div>
@@ -0,0 +1,40 @@
1
+ {
2
+ "ignored_warnings": [
3
+ {
4
+ "warning_type": "Cross-Site Scripting",
5
+ "warning_code": 4,
6
+ "fingerprint": "590cf164dd928ef0bd277c5369426130af896d9fdec6389084d9d4a27076ef13",
7
+ "check_name": "LinkToHref",
8
+ "message": "Unsafe parameter value in `link_to` href",
9
+ "file": "app/views/avo/home/failed_to_load.html.erb",
10
+ "line": 15,
11
+ "link": "https://brakemanscanner.org/docs/warning_types/link_to_href",
12
+ "code": "link_to(\"this page\", (params.permit(:src).fetch(:src) or nil), :target => :_blank)",
13
+ "render_path": [
14
+ {
15
+ "type": "controller",
16
+ "class": "Avo::HomeController",
17
+ "method": "failed_to_load",
18
+ "line": 23,
19
+ "file": "app/controllers/avo/home_controller.rb",
20
+ "rendered": {
21
+ "name": "avo/home/failed_to_load",
22
+ "file": "app/views/avo/home/failed_to_load.html.erb"
23
+ }
24
+ }
25
+ ],
26
+ "location": {
27
+ "type": "template",
28
+ "template": "avo/home/failed_to_load"
29
+ },
30
+ "user_input": "params.permit(:src).fetch(:src)",
31
+ "confidence": "High",
32
+ "cwe_id": [
33
+ 79
34
+ ],
35
+ "note": ""
36
+ }
37
+ ],
38
+ "updated": "2022-10-05 13:24:40 +0300",
39
+ "brakeman_version": "5.3.1"
40
+ }
data/db/factories.rb CHANGED
@@ -75,4 +75,24 @@ FactoryBot.define do
75
75
  link { Faker::Internet.url }
76
76
  course { create :course }
77
77
  end
78
+
79
+ factory :city do
80
+ name { Faker::Address.city }
81
+ population { rand(10000..999000) }
82
+ is_capital { [true, false].sample }
83
+ features { Faker::Address.community }
84
+ metadata { Faker::Address.community }
85
+ # image_url { "MyString" }
86
+ description { Faker::Address.community }
87
+ status { ["open", "closed"].sample }
88
+ tiny_description { Faker::Address.community }
89
+ end
90
+
91
+ factory :product do
92
+ title { "MyString" }
93
+ description { "MyText" }
94
+ price { 1 }
95
+ status { "MyString" }
96
+ category { "MyString" }
97
+ end
78
98
  end
@@ -101,6 +101,32 @@ module Avo
101
101
 
102
102
  ordering.dig(:actions) || {}
103
103
  end
104
+
105
+ def get_record_associations(record)
106
+ record._reflections
107
+ end
108
+
109
+ def valid_association_name(record, association_name)
110
+ get_record_associations(record).keys.find do |name|
111
+ name == association_name
112
+ end
113
+ end
114
+
115
+ def valid_attachment_name(record, association_name)
116
+ get_record_associations(record).keys.each do |name|
117
+ return association_name if name == "#{association_name}_attachment" || name == "#{association_name}_attachments"
118
+ end
119
+ end
120
+
121
+ def get_available_models
122
+ ApplicationRecord.descendants
123
+ end
124
+
125
+ def valid_model_class(model_class)
126
+ get_available_models.find do |m|
127
+ m.to_s == model_class.to_s
128
+ end
129
+ end
104
130
  end
105
131
 
106
132
  def initialize
@@ -36,7 +36,7 @@ module Avo
36
36
  possible_resource = "#{resource}Resource".gsub "ResourceResource", "Resource"
37
37
 
38
38
  resources.find do |available_resource|
39
- possible_resource.safe_constantize == available_resource.class
39
+ possible_resource.to_s == available_resource.class.to_s
40
40
  end
41
41
  end
42
42
 
@@ -43,6 +43,12 @@ module Avo
43
43
 
44
44
  items_holder.heading body, **args
45
45
  end
46
+
47
+ def sidebar(**args, &block)
48
+ ensure_items_holder_initialized
49
+
50
+ items_holder.sidebar Avo::SidebarBuilder.parse_block(**args, &block)
51
+ end
46
52
  # END DSL methods
47
53
 
48
54
  def items
@@ -76,6 +82,11 @@ module Avo
76
82
  fields << extract_fields_from_items(tab)
77
83
  end
78
84
  end
85
+
86
+ # Dive into sidebar to fetch their fields
87
+ if item.is_sidebar?
88
+ fields << extract_fields_from_items(item)
89
+ end
79
90
  end
80
91
 
81
92
  if item.is_field?
@@ -277,6 +288,17 @@ module Avo
277
288
  end
278
289
  end
279
290
 
291
+ # Make sure all tabs panelfull_items are setted as inside tabs
292
+ panelfull_items.grep(Avo::TabGroup).each do |tab_group|
293
+ tab_group.items.grep(Avo::Tab).each do |tab|
294
+ tab.items.grep(Avo::Panel).each do |panel|
295
+ panel.items.grep(Avo::Fields::BelongsToField).each do |field|
296
+ field.target = :_top
297
+ end
298
+ end
299
+ end
300
+ end
301
+
280
302
  # Add all the panelles fields to a new panel
281
303
  main_panel_holder = Avo::ItemsHolder.new
282
304
  main_panel_holder.items = panelless_items
@@ -31,6 +31,10 @@ module Avo
31
31
  def is_tab_group?
32
32
  self.class.item_type == :tab_group
33
33
  end
34
+
35
+ def is_sidebar?
36
+ self.class.item_type == :sidebar
37
+ end
34
38
  end
35
39
  end
36
40
  end
@@ -1,9 +1,10 @@
1
1
  class Avo::Configuration::Branding
2
- def initialize(colors: nil, chart_colors: nil, logo: nil, logomark: nil)
2
+ def initialize(colors: nil, chart_colors: nil, logo: nil, logomark: nil, placeholder: nil)
3
3
  @colors = colors || {}
4
4
  @chart_colors = chart_colors
5
5
  @logo = logo
6
6
  @logomark = logomark
7
+ @placeholder = placeholder
7
8
 
8
9
  @default_colors = {
9
10
  background: "#F6F6F7",
@@ -15,6 +16,7 @@ class Avo::Configuration::Branding
15
16
  @default_chart_colors = ["#0B8AE2", "#34C683", "#2AB1EE", "#34C6A8"]
16
17
  @default_logo = "/avo-assets/logo.png"
17
18
  @default_logomark = "/avo-assets/logomark.png"
19
+ @default_placeholder = "placeholder.svg"
18
20
  end
19
21
 
20
22
  def css_colors
@@ -39,6 +41,12 @@ class Avo::Configuration::Branding
39
41
  @logomark || @default_logomark
40
42
  end
41
43
 
44
+ def placeholder
45
+ return @default_placeholder if Avo::App.license.lacks_with_trial(:branding)
46
+
47
+ @placeholder || @default_placeholder
48
+ end
49
+
42
50
  def chart_colors
43
51
  return @default_chart_colors if Avo::App.license.lacks_with_trial(:branding)
44
52
 
@@ -58,6 +58,8 @@ module Avo
58
58
  # - is_disabled?
59
59
 
60
60
  class BelongsToField < BaseField
61
+ attr_accessor :target
62
+
61
63
  attr_reader :polymorphic_as
62
64
  attr_reader :relation_method
63
65
  attr_reader :types # for Polymorphic associations
@@ -77,6 +79,7 @@ module Avo
77
79
  @allow_via_detaching = args[:allow_via_detaching] == true
78
80
  @attach_scope = args[:attach_scope]
79
81
  @polymorphic_help = args[:polymorphic_help]
82
+ @target = args[:target]
80
83
  end
81
84
 
82
85
  def searchable
@@ -1,9 +1,17 @@
1
+ require 'securerandom'
2
+
1
3
  module Avo
2
4
  module Fields
3
5
  class HeadingField < BaseField
4
6
  attr_reader :as_html
7
+ attr_reader :empty
5
8
 
6
9
  def initialize(content, **args, &block)
10
+ # Mark the field as empty if there's no content passed
11
+ @empty = content.blank?
12
+ # Add dummy content
13
+ content ||= SecureRandom.hex
14
+
7
15
  args[:updatable] = false
8
16
 
9
17
  super(content, **args, &block)
@@ -16,6 +24,13 @@ module Avo
16
24
  def id
17
25
  "heading_#{name.to_s.parameterize.underscore}"
18
26
  end
27
+
28
+ # Override the value method if the field is empty
29
+ def value
30
+ return nil if empty
31
+
32
+ super
33
+ end
19
34
  end
20
35
  end
21
36
  end
@@ -55,6 +55,10 @@ module Avo
55
55
  add_item field
56
56
  end
57
57
 
58
+ def sidebar(instance)
59
+ add_item instance
60
+ end
61
+
58
62
  def add_item(instance)
59
63
  @items << instance
60
64
 
@@ -17,6 +17,7 @@ module Avo
17
17
  :stimulus_js_integration,
18
18
  :resource_show_controls,
19
19
  :branding,
20
+ :resource_sidebar,
20
21
  :advanced_fields
21
22
  ]
22
23
  end
@@ -57,7 +57,7 @@ class Avo::Menu::Builder
57
57
  # Add all the resources
58
58
  def all_resources(**args)
59
59
  Avo::App.resources_for_navigation.each do |res|
60
- resource res.model_class, **args
60
+ resource res.route_key, **args
61
61
  end
62
62
  end
63
63
 
data/lib/avo/menu/menu.rb CHANGED
@@ -1,4 +1,2 @@
1
1
  class Avo::Menu::Menu < OpenStruct
2
-
3
-
4
2
  end
data/lib/avo/reloader.rb CHANGED
@@ -20,40 +20,41 @@ class Avo::Reloader
20
20
  end
21
21
 
22
22
  private
23
- def updater
24
- @updater ||= config.file_watcher.new(files, directories) { reload! }
25
- end
26
23
 
27
- def files
28
- # we want to watch some files no matter what
29
- paths = [
30
- Rails.root.join("config", "initializers", "avo.rb"),
31
- ]
24
+ def updater
25
+ @updater ||= config.file_watcher.new(files, directories) { reload! }
26
+ end
32
27
 
33
- # we want to watch some files only in Avo development
34
- if reload_lib?
35
- paths += []
36
- end
28
+ def files
29
+ # we want to watch some files no matter what
30
+ paths = [
31
+ Rails.root.join("config", "initializers", "avo.rb"),
32
+ ]
37
33
 
38
- paths
34
+ # we want to watch some files only in Avo development
35
+ if reload_lib?
36
+ paths += []
39
37
  end
40
38
 
41
- def directories
42
- dirs = {}
39
+ paths
40
+ end
43
41
 
44
- # watch the lib directory in Avo development
45
- if reload_lib?
46
- dirs[Avo::Engine.root.join("lib", "avo").to_s] = ["rb"]
47
- end
42
+ def directories
43
+ dirs = {}
48
44
 
49
- dirs
45
+ # watch the lib directory in Avo development
46
+ if reload_lib?
47
+ dirs[Avo::Engine.root.join("lib", "avo").to_s] = ["rb"]
50
48
  end
51
49
 
52
- def config
53
- Rails.application.config
54
- end
50
+ dirs
51
+ end
55
52
 
56
- def reload_lib?
57
- Avo::IN_DEVELOPMENT || ENV['AVO_RELOAD_LIB_DIR']
58
- end
53
+ def config
54
+ Rails.application.config
55
+ end
56
+
57
+ def reload_lib?
58
+ Avo::IN_DEVELOPMENT || ENV["AVO_RELOAD_LIB_DIR"]
59
+ end
59
60
  end
@@ -40,7 +40,7 @@ module Avo
40
40
  end
41
41
 
42
42
  def secret_key_base
43
- ENV['SECRET_KEY_BASE'] || Rails.application.credentials.secret_key_base || Rails.application.secrets.secret_key_base
43
+ ENV["SECRET_KEY_BASE"] || Rails.application.credentials.secret_key_base || Rails.application.secrets.secret_key_base
44
44
  end
45
45
  end
46
46
  end
@@ -0,0 +1,60 @@
1
+ class Avo::Sidebar
2
+ include Avo::Concerns::IsResourceItem
3
+ include Avo::Fields::FieldExtensions::VisibleInDifferentViews
4
+
5
+ class_attribute :item_type, default: :sidebar
6
+ delegate :items, :add_item, to: :items_holder
7
+
8
+ attr_reader :name
9
+ attr_reader :view
10
+ attr_accessor :items_holder
11
+
12
+ def initialize(name: nil, view: nil, **args)
13
+ # Initialize the visibility markers
14
+ super
15
+
16
+ @name = name
17
+ @items_holder = Avo::ItemsHolder.new
18
+ @view = view
19
+
20
+ show_on args[:show_on] if args[:show_on].present?
21
+ hide_on args[:hide_on] if args[:hide_on].present?
22
+ only_on args[:only_on] if args[:only_on].present?
23
+ except_on args[:except_on] if args[:except_on].present?
24
+ end
25
+
26
+ def hydrate(view: nil)
27
+ @view = view
28
+
29
+ self
30
+ end
31
+
32
+ def empty?
33
+ visible_items.blank?
34
+ end
35
+
36
+ def items
37
+ if self.items_holder.present?
38
+ self.items_holder.items
39
+ else
40
+ []
41
+ end
42
+ end
43
+
44
+ def visible_items
45
+ items.map do |item|
46
+ # Remove the fields that shouldn't be visible in this view
47
+ # eg: has_many fields on edit
48
+ if not_visible_field(item)
49
+ nil
50
+ else
51
+ item
52
+ end
53
+ end
54
+ .compact
55
+ end
56
+
57
+ def not_visible_field(item)
58
+ item.is_field? && !item.visible_on?(view)
59
+ end
60
+ end
@@ -0,0 +1,24 @@
1
+ class Avo::SidebarBuilder
2
+ class << self
3
+ def parse_block(**args, &block)
4
+ Docile.dsl_eval(new(**args), &block).build
5
+ end
6
+ end
7
+
8
+ attr_reader :items_holder
9
+
10
+ delegate :field, to: :items_holder
11
+ delegate :items, to: :items_holder
12
+ delegate :heading, to: :items_holder
13
+
14
+ def initialize(name: nil, **args)
15
+ @sidebar = Avo::Sidebar.new(**args)
16
+ @items_holder = Avo::ItemsHolder.new
17
+ end
18
+
19
+ # Fetch the sidebar
20
+ def build
21
+ @sidebar.items_holder = @items_holder
22
+ @sidebar
23
+ end
24
+ end
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.16.1.pre.1.nativefields" unless const_defined?(:VERSION)
2
+ VERSION = "2.17.0" unless const_defined?(:VERSION)
3
3
  end
@@ -1,3 +1,3 @@
1
- <%%= index_field_wrapper field: @field, resource: @resource do %>
1
+ <%%= index_field_wrapper **field_wrapper_args do %>
2
2
  <%%= @field.value %>
3
3
  <%% end %>
@@ -35,7 +35,7 @@ Avo.configure do |config|
35
35
  # config.locale = 'en-US'
36
36
 
37
37
  ## == Resource options ==
38
- # config.resource_controls = :right
38
+ # config.resource_controls_placement = :right
39
39
  # config.model_resource_mapping = {}
40
40
  # config.default_view_type = :table
41
41
  # config.per_page = 24
@@ -71,6 +71,7 @@ Avo.configure do |config|
71
71
  # chart_colors: ["#0B8AE2", "#34C683", "#2AB1EE", "#34C6A8"],
72
72
  # logo: "/avo-assets/logo.png",
73
73
  # logomark: "/avo-assets/logomark.png"
74
+ # placeholder: "/avo-assets/placeholder.svg"
74
75
  # }
75
76
 
76
77
  ## == Breadcrumbs ==
@@ -50,7 +50,6 @@ en:
50
50
  per_page: 'Per page'
51
51
  more: 'More'
52
52
  attach: 'Attach'
53
- cancel: 'Cancel'
54
53
  save: 'Save'
55
54
  attach_and_attach_another: 'Attach & Attach another'
56
55
  hide_content: 'Hide content'