avo 4.1.4 → 4.1.6

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.
@@ -15,7 +15,7 @@
15
15
  opacity: 0;
16
16
  visibility: hidden;
17
17
  pointer-events: none;
18
- transform: translateX(-50%) translateY(-0.5rem);
18
+ transform: translateX(-50%) translateY(0.5rem);
19
19
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
20
20
 
21
21
  &:hover {
@@ -81,3 +81,23 @@
81
81
  }
82
82
  }
83
83
  }
84
+
85
+ /* Resource color on the initials chip: reuses the avatar component's --bg/--text
86
+ tint variables, so the existing color-mix keeps it readable in both themes. */
87
+ .breadcrumb-element--color-red .cado-avatar--initials { --bg: var(--color-red-400); --text: var(--color-red-600); }
88
+ .breadcrumb-element--color-orange .cado-avatar--initials { --bg: var(--color-orange-400); --text: var(--color-orange-600); }
89
+ .breadcrumb-element--color-amber .cado-avatar--initials { --bg: var(--color-amber-400); --text: var(--color-amber-600); }
90
+ .breadcrumb-element--color-yellow .cado-avatar--initials { --bg: var(--color-yellow-400); --text: var(--color-yellow-600); }
91
+ .breadcrumb-element--color-lime .cado-avatar--initials { --bg: var(--color-lime-400); --text: var(--color-lime-600); }
92
+ .breadcrumb-element--color-green .cado-avatar--initials { --bg: var(--color-green-400); --text: var(--color-green-600); }
93
+ .breadcrumb-element--color-emerald .cado-avatar--initials { --bg: var(--color-emerald-400); --text: var(--color-emerald-600); }
94
+ .breadcrumb-element--color-teal .cado-avatar--initials { --bg: var(--color-teal-400); --text: var(--color-teal-600); }
95
+ .breadcrumb-element--color-cyan .cado-avatar--initials { --bg: var(--color-cyan-400); --text: var(--color-cyan-600); }
96
+ .breadcrumb-element--color-sky .cado-avatar--initials { --bg: var(--color-sky-400); --text: var(--color-sky-600); }
97
+ .breadcrumb-element--color-blue .cado-avatar--initials { --bg: var(--color-blue-400); --text: var(--color-blue-600); }
98
+ .breadcrumb-element--color-indigo .cado-avatar--initials { --bg: var(--color-indigo-400); --text: var(--color-indigo-600); }
99
+ .breadcrumb-element--color-violet .cado-avatar--initials { --bg: var(--color-violet-400); --text: var(--color-violet-600); }
100
+ .breadcrumb-element--color-purple .cado-avatar--initials { --bg: var(--color-purple-400); --text: var(--color-purple-600); }
101
+ .breadcrumb-element--color-fuchsia .cado-avatar--initials { --bg: var(--color-fuchsia-400); --text: var(--color-fuchsia-600); }
102
+ .breadcrumb-element--color-pink .cado-avatar--initials { --bg: var(--color-pink-400); --text: var(--color-pink-600); }
103
+ .breadcrumb-element--color-rose .cado-avatar--initials { --bg: var(--color-rose-400); --text: var(--color-rose-600); }
@@ -210,6 +210,52 @@
210
210
 
211
211
  .sidebar-link__icon-wrapper {
212
212
  @apply shrink-0 flex items-center justify-center;
213
+ color: var(--sidebar-icon-color, currentColor);
214
+ }
215
+
216
+ /* Resource color: tints only the icon stroke. Each modifier sets a scoped
217
+ variable that only the icon wrapper consumes; the link's own color, hover
218
+ and active rules stay untouched. Light theme uses the 600 shade (700 for
219
+ the yellow family, which cannot reach 3:1 non-text contrast on the light
220
+ sidebar otherwise); dark theme overrides to the 400 shade below. */
221
+ .sidebar-link--color-red { --sidebar-icon-color: var(--color-red-600); }
222
+ .sidebar-link--color-orange { --sidebar-icon-color: var(--color-orange-600); }
223
+ .sidebar-link--color-amber { --sidebar-icon-color: var(--color-amber-700); }
224
+ .sidebar-link--color-yellow { --sidebar-icon-color: var(--color-yellow-700); }
225
+ .sidebar-link--color-lime { --sidebar-icon-color: var(--color-lime-700); }
226
+ .sidebar-link--color-green { --sidebar-icon-color: var(--color-green-600); }
227
+ .sidebar-link--color-emerald { --sidebar-icon-color: var(--color-emerald-600); }
228
+ .sidebar-link--color-teal { --sidebar-icon-color: var(--color-teal-600); }
229
+ .sidebar-link--color-cyan { --sidebar-icon-color: var(--color-cyan-600); }
230
+ .sidebar-link--color-sky { --sidebar-icon-color: var(--color-sky-600); }
231
+ .sidebar-link--color-blue { --sidebar-icon-color: var(--color-blue-600); }
232
+ .sidebar-link--color-indigo { --sidebar-icon-color: var(--color-indigo-600); }
233
+ .sidebar-link--color-violet { --sidebar-icon-color: var(--color-violet-600); }
234
+ .sidebar-link--color-purple { --sidebar-icon-color: var(--color-purple-600); }
235
+ .sidebar-link--color-fuchsia { --sidebar-icon-color: var(--color-fuchsia-600); }
236
+ .sidebar-link--color-pink { --sidebar-icon-color: var(--color-pink-600); }
237
+ .sidebar-link--color-rose { --sidebar-icon-color: var(--color-rose-600); }
238
+
239
+ /* Dark theme: lift the tints to the 400 shade so they stay legible on the
240
+ dark sidebar background. */
241
+ .dark {
242
+ .sidebar-link--color-red { --sidebar-icon-color: var(--color-red-400); }
243
+ .sidebar-link--color-orange { --sidebar-icon-color: var(--color-orange-400); }
244
+ .sidebar-link--color-amber { --sidebar-icon-color: var(--color-amber-400); }
245
+ .sidebar-link--color-yellow { --sidebar-icon-color: var(--color-yellow-400); }
246
+ .sidebar-link--color-lime { --sidebar-icon-color: var(--color-lime-400); }
247
+ .sidebar-link--color-green { --sidebar-icon-color: var(--color-green-400); }
248
+ .sidebar-link--color-emerald { --sidebar-icon-color: var(--color-emerald-400); }
249
+ .sidebar-link--color-teal { --sidebar-icon-color: var(--color-teal-400); }
250
+ .sidebar-link--color-cyan { --sidebar-icon-color: var(--color-cyan-400); }
251
+ .sidebar-link--color-sky { --sidebar-icon-color: var(--color-sky-400); }
252
+ .sidebar-link--color-blue { --sidebar-icon-color: var(--color-blue-400); }
253
+ .sidebar-link--color-indigo { --sidebar-icon-color: var(--color-indigo-400); }
254
+ .sidebar-link--color-violet { --sidebar-icon-color: var(--color-violet-400); }
255
+ .sidebar-link--color-purple { --sidebar-icon-color: var(--color-purple-400); }
256
+ .sidebar-link--color-fuchsia { --sidebar-icon-color: var(--color-fuchsia-400); }
257
+ .sidebar-link--color-pink { --sidebar-icon-color: var(--color-pink-400); }
258
+ .sidebar-link--color-rose { --sidebar-icon-color: var(--color-rose-400); }
213
259
  }
214
260
 
215
261
  /* Reserve same width when group has icons but this link has none (alignment) */
@@ -1,5 +1,6 @@
1
1
  <%= wrapper_element class: class_names(
2
2
  "breadcrumb-element",
3
+ color_class,
3
4
  "breadcrumb-element--link": link?
4
5
  ) do %>
5
6
  <% if @avatar.present? %>
@@ -6,6 +6,16 @@ class Avo::BreadcrumbElementComponent < Avo::BaseComponent
6
6
  prop :icon, default: nil
7
7
  prop :initials, default: nil
8
8
  prop :avatar
9
+ # Resource color: tints the initials chip, same palette as the sidebar icon.
10
+ prop :color, default: nil do |value|
11
+ next nil if value.blank?
12
+ value = value.to_sym if value.respond_to?(:to_sym)
13
+ Avo::Sidebar::LinkComponent::PALETTE_COLORS.include?(value) ? value : nil
14
+ end
15
+
16
+ def color_class
17
+ "breadcrumb-element--color-#{@color}" if @color.present?
18
+ end
9
19
 
10
20
  def link?
11
21
  @url.present?
@@ -8,7 +8,8 @@
8
8
  url: item.path,
9
9
  icon: item.icon,
10
10
  avatar: item.avatar,
11
- initials: item.initials
11
+ initials: item.initials,
12
+ color: item.respond_to?(:color) ? item.color : nil
12
13
  ) %>
13
14
 
14
15
  <% unless is_last %>
@@ -6,6 +6,10 @@ require "view_component/version"
6
6
  # about menus; callers pass the path, label and resolved `active` (a match mode
7
7
  # like :inclusive, or a boolean to force it).
8
8
  class Avo::Sidebar::LinkComponent < Avo::BaseComponent
9
+ # The raw Tailwind palette names accepted for the tinted sidebar icon. Each
10
+ # has a matching `.sidebar-link--color-<name>` rule in css/sidebar.css.
11
+ PALETTE_COLORS = (Avo::UI::BadgeComponent::VALID_COLORS - %i[neutral success info warning danger]).freeze unless defined?(PALETTE_COLORS)
12
+
9
13
  prop :label
10
14
  prop :path
11
15
  prop :active, default: :inclusive do |value|
@@ -19,6 +23,14 @@ class Avo::Sidebar::LinkComponent < Avo::BaseComponent
19
23
  prop :reserve_icon_space, default: false
20
24
  prop :args, kind: :**, default: {}.freeze
21
25
  prop :hotkey, default: nil
26
+ # Resource color: tints only the icon stroke via a CSS modifier; unknown or
27
+ # blank values normalize to nil, which emits no modifier at all.
28
+ prop :color, default: nil do |value|
29
+ next nil if value.blank?
30
+
31
+ normalized = value.to_s.to_sym
32
+ PALETTE_COLORS.include?(normalized) ? normalized : nil
33
+ end
22
34
  prop :variant, default: :default
23
35
  prop :bar_class, default: ""
24
36
 
@@ -27,11 +39,15 @@ class Avo::Sidebar::LinkComponent < Avo::BaseComponent
27
39
  end
28
40
 
29
41
  def root_css_class
30
- return "sidebar-link" unless subitem?
42
+ return ["sidebar-link", color_class].reject(&:blank?).join(" ") unless subitem?
31
43
 
32
44
  ["sidebar-subitem", @bar_class].reject(&:blank?).join(" ")
33
45
  end
34
46
 
47
+ def color_class
48
+ "sidebar-link--color-#{@color}" if @color.present?
49
+ end
50
+
35
51
  # Sub-items don't show icons (for now); top-level links do.
36
52
  def show_icon?
37
53
  return false if subitem?
@@ -21,7 +21,7 @@
21
21
  <%= render Avo::Sidebar::HeadingComponent.new title: t('avo.dashboards'), icon: "tabler/outline/layout-dashboard" %>
22
22
 
23
23
  <% dashboards.sort_by { |r| r.navigation_label }.each do |dashboard| %>
24
- <%= render Avo::Sidebar::LinkComponent.new label: dashboard.navigation_label, path: helpers.avo_dashboards.dashboard_path(dashboard), hotkey: dashboard.try(:hotkey).presence %>
24
+ <%= render Avo::Sidebar::LinkComponent.new label: dashboard.navigation_label, path: helpers.avo_dashboards.dashboard_path(dashboard), hotkey: dashboard.try(:hotkey).presence, color: dashboard.try(:color) %>
25
25
  <% end %>
26
26
  </div>
27
27
  <% end %>
@@ -30,7 +30,7 @@
30
30
  <%= render Avo::Sidebar::HeadingComponent.new title: t('avo.resources'), icon: "tabler/outline/topology-star-3" %>
31
31
 
32
32
  <% resources.sort_by { |r| r.navigation_label }.each do |resource| %>
33
- <%= render Avo::Sidebar::LinkComponent.new label: resource.navigation_label, path: helpers.resources_path(resource: resource), icon: resource.icon, hotkey: resource.try(:hotkey).presence %>
33
+ <%= render Avo::Sidebar::LinkComponent.new label: resource.navigation_label, path: helpers.resources_path(resource: resource), icon: resource.icon, hotkey: resource.try(:hotkey).presence, color: resource.try(:color) %>
34
34
  <% end %>
35
35
  </div>
36
36
 
@@ -27,8 +27,12 @@ module Avo
27
27
  end
28
28
 
29
29
  def destroy
30
- if authorized_to :delete
31
- attachment = ActiveStorage::Attachment.find(params[:attachment_id])
30
+ if attachment_name.blank?
31
+ flash[:error] = t("avo.failed_to_find_attachment")
32
+ elsif !authorized_to(:delete)
33
+ flash[:notice] = t("avo.not_authorized")
34
+ else
35
+ attachment = attachment_to_destroy
32
36
 
33
37
  if attachment.present?
34
38
  ActiveRecord::Base.transaction do
@@ -47,10 +51,8 @@ module Avo
47
51
  flash[:error] = @record.errors.full_messages.join(", ")
48
52
  end
49
53
  else
50
- t("avo.failed_to_find_attachment")
54
+ flash[:error] = t("avo.failed_to_find_attachment")
51
55
  end
52
- else
53
- flash[:notice] = t("avo.not_authorized")
54
56
  end
55
57
 
56
58
  respond_to do |format|
@@ -62,8 +64,30 @@ module Avo
62
64
 
63
65
  private
64
66
 
67
+ # The attachment association named in the URL, validated against the record
68
+ # it is being requested on. Blank when the name is not an attachment on this
69
+ # record, which keeps `params[:attachment_name]` out of the policy method
70
+ # name below.
71
+ def attachment_name
72
+ return @attachment_name if defined?(@attachment_name)
73
+
74
+ @attachment_name = BaseResource.valid_attachment_name(@record, params[:attachment_name])
75
+ end
76
+
77
+ # Resolve the attachment through the record and association that were
78
+ # authorized. `params[:attachment_id]` is attacker-controlled and
79
+ # independent of `params[:id]`, so an unscoped lookup here would let a user
80
+ # authorized on one record destroy any attachment in the application.
81
+ def attachment_to_destroy
82
+ ActiveStorage::Attachment.find_by(
83
+ id: params[:attachment_id],
84
+ record: @record,
85
+ name: attachment_name
86
+ )
87
+ end
88
+
65
89
  def authorized_to(action)
66
- @resource.authorization.authorize_action("#{action}_#{params[:attachment_name]}?", record: @record, raise_exception: false)
90
+ @resource.authorization.authorize_action("#{action}_#{attachment_name}?", record: @record, raise_exception: false)
67
91
  end
68
92
 
69
93
  def authorized_to_upload(attachment_name)
@@ -24,10 +24,10 @@ module Avo
24
24
  if @reflection.present? && !turbo_frame_request?
25
25
  # A good rule of thumb is that the resource name entry (Users) gets just the initials
26
26
  # The record name gets initials and avatar
27
- add_breadcrumb title: @record.class.to_s.pluralize, path: resources_path(resource: @parent_resource), initials: @parent_resource.class.initials
28
- add_breadcrumb title: @parent_resource.record_title, path: resource_path(record: @record, resource: @parent_resource), initials: @parent_resource.initials, avatar: @parent_resource.avatar
27
+ add_breadcrumb title: @record.class.to_s.pluralize, path: resources_path(resource: @parent_resource), initials: @parent_resource.class.initials, color: @parent_resource.class.color
28
+ add_breadcrumb title: @parent_resource.record_title, path: resource_path(record: @record, resource: @parent_resource), initials: @parent_resource.initials, avatar: @parent_resource.avatar, color: @parent_resource.class.color
29
29
  end
30
- add_breadcrumb title: @resource.plural_name, initials: @resource.class.initials
30
+ add_breadcrumb title: @resource.plural_name, initials: @resource.class.initials, color: @resource.class.color
31
31
 
32
32
  set_applied_filters
33
33
  set_index_params
@@ -97,7 +97,7 @@ module Avo
97
97
 
98
98
  add_via_breadcrumbs
99
99
 
100
- add_breadcrumb title: @resource.record_title, path: nil, avatar: @resource.avatar, initials: @resource.initials
100
+ add_breadcrumb title: @resource.record_title, path: nil, avatar: @resource.avatar, initials: @resource.initials, color: @resource.class.color
101
101
  add_breadcrumb title: I18n.t("avo.details").upcase_first, path: nil
102
102
 
103
103
  set_component_for __method__
@@ -117,12 +117,12 @@ module Avo
117
117
  via_record = via_resource.find_record params[:via_record_id], params: params
118
118
  via_resource = via_resource.new record: via_record
119
119
 
120
- add_breadcrumb title: via_resource.plural_name, path: resources_path(resource: via_resource), initials: via_resource.class.initials
121
- add_breadcrumb title: via_resource.record_title, path: resource_path(record: via_record, resource: via_resource), avatar: via_resource.avatar, initials: via_resource.initials
120
+ add_breadcrumb title: via_resource.plural_name, path: resources_path(resource: via_resource), initials: via_resource.class.initials, color: via_resource.class.color
121
+ add_breadcrumb title: via_resource.record_title, path: resource_path(record: via_record, resource: via_resource), avatar: via_resource.avatar, initials: via_resource.initials, color: via_resource.class.color
122
122
 
123
- add_breadcrumb title: @resource.plural_name, initials: @resource.class.initials
123
+ add_breadcrumb title: @resource.plural_name, initials: @resource.class.initials, color: @resource.class.color
124
124
  else
125
- add_breadcrumb title: @resource.plural_name, path: resources_path(resource: @resource), initials: @resource.class.initials
125
+ add_breadcrumb title: @resource.plural_name, path: resources_path(resource: @resource), initials: @resource.class.initials, color: @resource.class.color
126
126
  end
127
127
 
128
128
  add_breadcrumb title: t("avo.new").humanize
@@ -168,8 +168,8 @@ module Avo
168
168
  saved = save_record
169
169
  @resource.hydrate(record: @record, view: Avo::ViewInquirer.new(:new), user: _current_user)
170
170
 
171
- add_breadcrumb title: @resource.plural_name, path: resources_path(resource: @resource), initials: @resource.class.initials
172
- add_breadcrumb title: t("avo.new").humanize, path: nil, avatar: @resource.avatar, initials: @resource.initials
171
+ add_breadcrumb title: @resource.plural_name, path: resources_path(resource: @resource), initials: @resource.class.initials, color: @resource.class.color
172
+ add_breadcrumb title: t("avo.new").humanize, path: nil, avatar: @resource.avatar, initials: @resource.initials, color: @resource.class.color
173
173
  set_actions
174
174
 
175
175
  set_component_for :edit
@@ -416,7 +416,7 @@ module Avo
416
416
  # Go through all filters
417
417
  @resource.get_filters
418
418
  .select do |filter|
419
- filter[:class].instance_methods(false).include? :react
419
+ filter[:class].method_defined?(:react, false)
420
420
  end
421
421
  .each do |filter|
422
422
  # Run the react method if it's present
@@ -446,19 +446,19 @@ module Avo
446
446
  via_record = via_resource.find_record params[:via_record_id], params: params
447
447
  via_resource = via_resource.new record: via_record
448
448
 
449
- add_breadcrumb title: via_resource.plural_name, path: resources_path(resource: @resource), initials: via_resource.class.initials
450
- add_breadcrumb title: via_resource.record_title, path: resource_path(record: via_record, resource: via_resource), avatar: via_resource.avatar, initials: via_resource.initials
449
+ add_breadcrumb title: via_resource.plural_name, path: resources_path(resource: @resource), initials: via_resource.class.initials, color: via_resource.class.color
450
+ add_breadcrumb title: via_resource.record_title, path: resource_path(record: via_record, resource: via_resource), avatar: via_resource.avatar, initials: via_resource.initials, color: via_resource.class.color
451
451
 
452
452
  last_crumb_args = {
453
453
  via_resource_class: params[:via_resource_class],
454
454
  via_record_id: params[:via_record_id]
455
455
  }
456
- add_breadcrumb title: @resource.plural_name, initials: @resource.class.initials
456
+ add_breadcrumb title: @resource.plural_name, initials: @resource.class.initials, color: @resource.class.color
457
457
  else
458
- add_breadcrumb title: @resource.plural_name, path: resources_path(resource: @resource), initials: @resource.class.initials
458
+ add_breadcrumb title: @resource.plural_name, path: resources_path(resource: @resource), initials: @resource.class.initials, color: @resource.class.color
459
459
  end
460
460
 
461
- add_breadcrumb title: @resource.record_title, path: resource_path(record: @resource.record, resource: @resource, **last_crumb_args), avatar: @resource.avatar, initials: @resource.initials
461
+ add_breadcrumb title: @resource.record_title, path: resource_path(record: @resource.record, resource: @resource, **last_crumb_args), avatar: @resource.avatar, initials: @resource.initials, color: @resource.class.color
462
462
  add_breadcrumb title: t("avo.edit").humanize
463
463
  end
464
464
 
@@ -611,7 +611,7 @@ module Avo
611
611
 
612
612
  # Set pagy locale from params or from avo configuration, if both nil locale = "en"
613
613
  def set_pagy_locale
614
- @pagy_locale = locale.to_s || Avo.configuration.default_locale || "en"
614
+ @pagy_locale = locale.to_s
615
615
  Pagy::I18n.locale = @pagy_locale if defined?(Pagy::I18n) && Pagy::I18n.respond_to?(:locale=)
616
616
  end
617
617
 
@@ -738,12 +738,12 @@ module Avo
738
738
  via_record = via_resource.find_record params[:via_record_id], params: params
739
739
  via_resource = via_resource.new record: via_record
740
740
 
741
- add_breadcrumb title: via_resource.plural_name, path: resources_path(resource: via_resource), initials: via_resource.class.initials
742
- add_breadcrumb title: via_resource.record_title, path: resource_path(record: via_record, resource: via_resource), avatar: via_resource.avatar, initials: via_resource.initials
741
+ add_breadcrumb title: via_resource.plural_name, path: resources_path(resource: via_resource), initials: via_resource.class.initials, color: via_resource.class.color
742
+ add_breadcrumb title: via_resource.record_title, path: resource_path(record: via_record, resource: via_resource), avatar: via_resource.avatar, initials: via_resource.initials, color: via_resource.class.color
743
743
 
744
- add_breadcrumb title: @resource.plural_name, path: nil, initials: @resource.class.initials
744
+ add_breadcrumb title: @resource.plural_name, path: nil, initials: @resource.class.initials, color: @resource.class.color
745
745
  else
746
- add_breadcrumb title: @resource.plural_name, path: resources_path(resource: @resource), initials: @resource.class.initials
746
+ add_breadcrumb title: @resource.plural_name, path: resources_path(resource: @resource), initials: @resource.class.initials, color: @resource.class.color
747
747
  end
748
748
  end
749
749
 
@@ -3,7 +3,8 @@ import { Controller } from '@hotwired/stimulus'
3
3
  export default class extends Controller {
4
4
  refresh() {
5
5
  const frame = this.context.scope.element.closest('turbo-frame')
6
- this.element.querySelector('svg').classList.add('animate-spin')
6
+ // The tabler refresh icon's arrows point counterclockwise, so the spin must run in reverse to match.
7
+ this.element.querySelector('svg').classList.add('animate-spin', '[animation-direction:reverse]')
7
8
  if (frame) {
8
9
  frame.classList.add('opacity-50')
9
10
  frame.addEventListener('turbo:frame-load', () => {
@@ -15,7 +15,7 @@ module Avo
15
15
  helper_method :add_breadcrumb, :avo_breadcrumbs
16
16
  end
17
17
 
18
- Crumb = Data.define(:title, :path, :avatar, :initials, :icon) unless defined?(Crumb)
18
+ Crumb = Data.define(:title, :path, :avatar, :initials, :icon, :color) unless defined?(Crumb)
19
19
 
20
20
  class Builder
21
21
  extend PropInitializer::Properties
@@ -26,8 +26,8 @@ module Avo
26
26
  def breadcrumbs = context.avo_breadcrumbs
27
27
  end
28
28
 
29
- def add_breadcrumb(title: nil, path: nil, avatar: nil, initials: nil, icon: nil)
30
- avo_breadcrumbs << Crumb.new(title:, path:, avatar:, initials:, icon:)
29
+ def add_breadcrumb(title: nil, path: nil, avatar: nil, initials: nil, icon: nil, color: nil)
30
+ avo_breadcrumbs << Crumb.new(title:, path:, avatar:, initials:, icon:, color:)
31
31
  end
32
32
 
33
33
  def avo_breadcrumbs
@@ -76,6 +76,7 @@ module Avo
76
76
  class_attribute :confirm_on_save, default: false
77
77
  class_attribute :visible_on_sidebar, default: true
78
78
  class_attribute :hotkey, default: nil
79
+ class_attribute :color, default: nil
79
80
  class_attribute :index_query, default: -> {
80
81
  query
81
82
  }
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "4.1.4" unless const_defined?(:VERSION)
2
+ VERSION = "4.1.6" unless const_defined?(:VERSION)
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avo
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.4
4
+ version: 4.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Marin