avo 2.1.1 → 2.1.2.pre1

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.

@@ -10,7 +10,7 @@
10
10
  </div>
11
11
  <div class="ml-3 w-0 flex-1 pt-0.5">
12
12
  <p class="text-sm leading-5 font-semibold">
13
- <%= message %>
13
+ <%== message %>
14
14
  </p>
15
15
  </div>
16
16
  <div class="ml-4 flex-shrink-0 flex">
@@ -18,7 +18,7 @@ class Avo::AlertComponent < ViewComponent::Base
18
18
  end
19
19
 
20
20
  def classes
21
- result = "max-w-sm w-full shadow-lg rounded px-4 py-3 rounded relative border text-white pointer-events-auto"
21
+ result = "max-w-lg w-full shadow-lg rounded px-4 py-3 rounded relative border text-white pointer-events-auto"
22
22
 
23
23
  result += if is_error?
24
24
  " bg-red-400 border-red-700"
@@ -1,4 +1,9 @@
1
- <div class="relative flex-1 flex flex-col justify-between h-full" data-controller="dashboard-card" data-dashboard-card-target="card" data-refresh-every="<%= @card.refresh_every %>" data-card-id="<%= @card.id %>">
1
+ <div class="relative flex-1 flex flex-col justify-between h-full"
2
+ data-controller="dashboard-card"
3
+ data-dashboard-card-target="card"
4
+ data-refresh-every="<%= @card.refresh_every %>"
5
+ data-card-id="<%= @card.id %>"
6
+ data-card-index="<%= @card.index %>">
2
7
  <% if @card.class.display_header %>
3
8
  <div class="px-4 pt-4">
4
9
  <div class="flex justify-between items-center min-h-6">
@@ -7,7 +12,7 @@
7
12
  </div>
8
13
  <div data-controller="select">
9
14
  <% if @card.type == :metric && @card.parsed_ranges.present? %>
10
- <%= select_tag "#{@card.id}_range", options_for_select(@card.parsed_ranges, @card.range),
15
+ <%= select_tag "#{@card.id}_#{@card.index}_range", options_for_select(@card.parsed_ranges, @card.range),
11
16
  class: 'appearance-none inline-flex bg-blue-gray-100 disabled:bg-blue-gray-300 disabled:cursor-not-allowed focus:bg-white text-sm text-blue-gray-700 disabled:text-blue-gray-700 leading-none rounded-md py-px px-2 leading-tight border outline-none outline w-24',
12
17
  data: {
13
18
  target: 'select',
@@ -19,9 +19,11 @@
19
19
  <% end %>
20
20
  </div>
21
21
 
22
- <div class="flex-1 w-full flex flex-col sm:flex-row xl:justify-end sm:items-end space-y-2 sm:space-y-0 sm:space-x-2 mt-4 xl:mt-0">
23
- <%= tools %>
24
- </div>
22
+ <% if tools.present? %>
23
+ <div class="flex-1 w-full flex flex-col sm:flex-row xl:justify-end sm:items-end space-y-2 sm:space-y-0 sm:space-x-2 mt-4 xl:mt-0">
24
+ <%= tools %>
25
+ </div>
26
+ <% end %>
25
27
  </div>
26
28
  <% end %>
27
29
 
@@ -43,6 +43,8 @@
43
43
  </div>
44
44
  </div>
45
45
  <% end %>
46
+
47
+ <%= render partial: "/avo/partials/sidebar_extra" %>
46
48
  </div>
47
49
  </div>
48
50
  <%= helpers.render_license_warnings %>
@@ -84,4 +84,14 @@
84
84
  <% end %>
85
85
  <% end %>
86
86
  <% end %>
87
+
88
+ <% if should_display_invalid_fields_errors? %>
89
+ <turbo-stream action="append" target="alerts">
90
+ <template>
91
+ <% @resource.invalid_fields.each do |error| %>
92
+ <%= render Avo::AlertComponent.new :error, error[:message] %>
93
+ <% end %>
94
+ </template>
95
+ </turbo-stream>
96
+ <% end %>
87
97
  </div>
@@ -90,4 +90,9 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
90
90
  end
91
91
  end
92
92
  end
93
+
94
+ # In development and test environments we shoudl show the invalid field errors
95
+ def should_display_invalid_fields_errors?
96
+ (Rails.env.development? || Rails.env.test?) && @resource.invalid_fields.present?
97
+ end
93
98
  end
@@ -44,7 +44,7 @@ module Avo
44
44
  unless @index_params[:sort_by].eql? :created_at
45
45
  @query = @query.unscope(:order)
46
46
  end
47
- @query = @query.order("#{@resource.model_class.table_name}.#{@index_params[:sort_by]} #{@index_params[:sort_direction]}")
47
+ @query = @query.order(Arel.sql("#{@resource.model_class.table_name}.#{@index_params[:sort_by]} #{@index_params[:sort_direction]}"))
48
48
  end
49
49
 
50
50
  # Apply filters
@@ -128,14 +128,7 @@ module Avo
128
128
 
129
129
  respond_to do |format|
130
130
  if saved
131
- redirect_path = resource_path(model: @model, resource: @resource)
132
-
133
- if params[:via_relation_class].present? && params[:via_resource_id].present?
134
- parent_resource = ::Avo::App.get_resource_by_model_name params[:via_relation_class].safe_constantize
135
- redirect_path = resource_path(model: params[:via_relation_class].safe_constantize, resource: parent_resource, resource_id: params[:via_resource_id])
136
- end
137
-
138
- format.html { redirect_to redirect_path, notice: "#{@model.class.name} #{t("avo.was_successfully_created")}." }
131
+ format.html { redirect_to after_create_path, notice: "#{@model.class.name} #{t("avo.was_successfully_created")}." }
139
132
  else
140
133
  flash.now[:error] = t "avo.you_missed_something_check_form"
141
134
  format.html { render :new, status: :unprocessable_entity }
@@ -153,7 +146,7 @@ module Avo
153
146
 
154
147
  respond_to do |format|
155
148
  if saved
156
- format.html { redirect_to params[:referrer] || resource_path(model: @model, resource: @resource), notice: "#{@model.class.name} #{t("avo.was_successfully_updated")}." }
149
+ format.html { redirect_to after_update_path, notice: "#{@model.class.name} #{t("avo.was_successfully_updated")}." }
157
150
  else
158
151
  flash.now[:error] = t "avo.you_missed_something_check_form"
159
152
  format.html { render :edit, status: :unprocessable_entity }
@@ -357,5 +350,32 @@ module Avo
357
350
  add_breadcrumb @resource.model_title, resource_path(model: @resource.model, resource: @resource)
358
351
  add_breadcrumb t("avo.edit").humanize
359
352
  end
353
+
354
+ def after_create_path
355
+ # If this is an associated record return to the association show page
356
+ if params[:via_relation_class].present? && params[:via_resource_id].present?
357
+ parent_resource = ::Avo::App.get_resource_by_model_name params[:via_relation_class].safe_constantize
358
+
359
+ return resource_path(model: params[:via_relation_class].safe_constantize, resource: parent_resource, resource_id: params[:via_resource_id])
360
+ end
361
+
362
+ redirect_path_from_resource_option || resource_path(model: @model, resource: @resource)
363
+ end
364
+
365
+ def after_update_path
366
+ return params[:referrer] if params[:referrer].present?
367
+
368
+ redirect_path_from_resource_option || resource_path(model: @model, resource: @resource)
369
+ end
370
+
371
+ def redirect_path_from_resource_option
372
+ return nil if @resource.class.after_update_path.blank?
373
+
374
+ if @resource.class.after_create_path == :index
375
+ resources_path(resource: @resource)
376
+ else
377
+ resource_path(model: @model, resource: @resource)
378
+ end
379
+ end
360
380
  end
361
381
  end
@@ -8,11 +8,7 @@ module Avo
8
8
  end
9
9
 
10
10
  def card
11
- @card = @dashboard.items.find do |item|
12
- next unless item.is_card?
13
-
14
- item.id.to_s == params[:card_id]
15
- end.tap do |card|
11
+ @card = @dashboard.item_at_index(params[:index].to_i).tap do |card|
16
12
  card.hydrate(dashboard: @dashboard, params: params)
17
13
  end
18
14
  end
@@ -12,8 +12,12 @@ module Avo
12
12
  end
13
13
  end
14
14
 
15
- # This entry uses `route_key` instead of `model_key` because it's rails that needs `fish_index` to build the correct path
16
- avo.send :"resources_#{resource.route_key}_path", **existing_params, **args
15
+ # Create the `route_key` from the model key so the namespaced models get the proper path (SomeModule::Post -> some_module_post).
16
+ # Add the `_index` suffix for the uncountable models so they get the correct path (`fish_index`)
17
+ route_key = resource.model_key
18
+ route_key << "_index" if resource.model_name.singular == resource.model_name.plural
19
+
20
+ avo.send :"resources_#{route_key}_path", **existing_params, **args
17
21
  end
18
22
 
19
23
  def resource_path(
@@ -8,7 +8,10 @@
8
8
  <%= render Avo::Dashboards::DividerComponent.new(divider: item) %>
9
9
  <% elsif item.is_card? %>
10
10
  <%= content_tag(:div, class: "relative bg-white rounded shadow-panel space-y-2 #{item.card_classes} overflow-hidden") do %>
11
- <turbo-frame id="<%= item.turbo_frame %>" src="<%= item.frame_url(enforced_range: @range) %>">
11
+ <turbo-frame id="<%= item.turbo_frame %>"
12
+ src="<%= item.frame_url(enforced_range: @range, params: params) %>"
13
+ data-card-index="<%= item.index %>"
14
+ >
12
15
  <%= render(Avo::LoadingComponent.new(title: item.label)) %>
13
16
  </turbo-frame>
14
17
  <% end %>
File without changes
@@ -13,6 +13,7 @@ module Avo
13
13
  class_attribute :user
14
14
  class_attribute :resource
15
15
  class_attribute :fields
16
+ class_attribute :invalid_fields
16
17
  class_attribute :standalone, default: false
17
18
  class_attribute :visible
18
19
  class_attribute :may_download_file, default: false
@@ -0,0 +1,175 @@
1
+ module Avo
2
+ class BaseCard
3
+ class_attribute :id
4
+ class_attribute :label
5
+ class_attribute :description
6
+ class_attribute :cols, default: 1
7
+ class_attribute :rows, default: 1
8
+ class_attribute :initial_range
9
+ class_attribute :ranges, default: []
10
+ class_attribute :refresh_every
11
+ class_attribute :display_header, default: true
12
+ # private
13
+ class_attribute :result_data
14
+ class_attribute :query_block
15
+
16
+ attr_accessor :dashboard
17
+ attr_accessor :options
18
+ attr_accessor :index
19
+ attr_accessor :params
20
+
21
+ delegate :context, to: ::Avo::App
22
+
23
+ class << self
24
+ def query(&block)
25
+ self.query_block = block
26
+ end
27
+ end
28
+
29
+ def initialize(dashboard:, options: {}, index: 0, cols: nil, rows: nil, label: nil, description: nil, refresh_every: nil)
30
+ @dashboard = dashboard
31
+ @options = options
32
+ @index = index
33
+ @cols = cols
34
+ @rows = rows
35
+ @label = label
36
+ @refresh_every = refresh_every
37
+ @description = description
38
+ end
39
+
40
+ def label
41
+ return @label.to_s if @label.present?
42
+ return self.class.label.to_s if self.class.label.present?
43
+
44
+ self.class.id.to_s.humanize
45
+ end
46
+
47
+ def description
48
+ @description || self.class.description
49
+ end
50
+
51
+ def refresh_every
52
+ @refresh_every || self.class.refresh_every
53
+ end
54
+
55
+ def translated_range(range)
56
+ return "#{range} days" if range.is_a? Integer
57
+
58
+ case range
59
+ when "MTD"
60
+ "Month to date"
61
+ when "QTD"
62
+ "Quarter to date"
63
+ when "YTD"
64
+ "Year to date"
65
+ when "TODAY"
66
+ "Today"
67
+ else
68
+ range
69
+ end
70
+ end
71
+
72
+ def parsed_ranges
73
+ return unless ranges.present?
74
+
75
+ ranges.map { |range| [translated_range(range), range] }
76
+ end
77
+
78
+ def turbo_frame
79
+ "#{dashboard.id}_#{id}"
80
+ end
81
+
82
+ def frame_url(enforced_range: nil, params: {})
83
+ enforced_range ||= initial_range || ranges.first
84
+
85
+ # append the parent params to the card request
86
+ begin
87
+ other_params = "&#{params.permit!.to_h.map { |k, v| "#{k}=#{v}" }.join("&")}"
88
+ rescue
89
+ end
90
+
91
+ "#{Avo::App.root_path}/dashboards/#{dashboard.id}/cards/#{id}?turbo_frame=#{turbo_frame}&index=#{index}&range=#{enforced_range}#{other_params}"
92
+ end
93
+
94
+ def card_classes
95
+ result = ""
96
+
97
+ # Writing down the classes so TailwindCSS knows not to purge them
98
+ classes_for_cols = {
99
+ 1 => " sm:col-span-1",
100
+ 2 => " sm:col-span-2",
101
+ 3 => " sm:col-span-3",
102
+ 4 => " sm:col-span-4",
103
+ 5 => " sm:col-span-5",
104
+ 6 => " sm:col-span-6"
105
+ }
106
+
107
+ classes_for_rows = {
108
+ 1 => " h-36",
109
+ 2 => " h-72",
110
+ 3 => " h-[27rem]",
111
+ 4 => " h-[36rem]",
112
+ 5 => " h-[45rem]",
113
+ 6 => " h-[54rem]"
114
+ }
115
+ # puts ["cols->", cols, classes_for_cols, classes_for_rows, classes_for_cols[cols.to_i]].inspect
116
+
117
+ result += classes_for_cols[cols.to_i] if classes_for_cols[cols.to_i].present?
118
+ result += classes_for_rows[rows.to_i] if classes_for_rows[rows.to_i].present?
119
+
120
+ result
121
+ end
122
+
123
+ def type
124
+ return :metric if self.class.superclass == ::Avo::Dashboards::MetricCard
125
+ return :chartkick if self.class.superclass == ::Avo::Dashboards::ChartkickCard
126
+ return :partial if self.class.superclass == ::Avo::Dashboards::PartialCard
127
+ end
128
+
129
+ def compute_result
130
+ Avo::Hosts::DashboardCard.new(card: self, dashboard: dashboard, params: params, context: context, range: range, options: options)
131
+ .compute_result
132
+
133
+ self
134
+ end
135
+
136
+ def hydrate(dashboard: nil, params: nil)
137
+ @dashboard = dashboard if dashboard.present?
138
+ @params = params if params.present?
139
+
140
+ self
141
+ end
142
+
143
+ def range
144
+ return params[:range] if params.dig(:range).present?
145
+
146
+ return initial_range if initial_range.present?
147
+
148
+ ranges.first
149
+ end
150
+
151
+ def result(data)
152
+ self.result_data = data
153
+
154
+ self
155
+ end
156
+
157
+ def is_card?
158
+ true
159
+ end
160
+
161
+ def is_divider?
162
+ false
163
+ end
164
+
165
+ private
166
+
167
+ def cols
168
+ @cols || self.class.cols
169
+ end
170
+
171
+ def rows
172
+ @rows || self.class.rows
173
+ end
174
+ end
175
+ end
@@ -40,6 +40,9 @@ module Avo
40
40
  class_attribute :resolve_find_scope
41
41
  class_attribute :ordering
42
42
  class_attribute :hide_from_global_search, default: false
43
+ class_attribute :after_create_path, default: :show
44
+ class_attribute :after_update_path, default: :show
45
+ class_attribute :invalid_fields
43
46
 
44
47
  class << self
45
48
  delegate :t, to: ::I18n
@@ -427,11 +430,15 @@ module Avo
427
430
  # This is used as the model class ID
428
431
  # We use this instead of the route_key to maintain compatibility with uncountable models
429
432
  # With uncountable models route key appends an _index suffix (Fish->fish_index)
430
- # Example: User->users, MediaItem->medie_items, Fish->fish
433
+ # Example: User->users, MediaItem->media_items, Fish->fish
431
434
  def model_key
432
435
  model_class.model_name.plural
433
436
  end
434
437
 
438
+ def model_name
439
+ model_class.model_name
440
+ end
441
+
435
442
  def singular_model_key
436
443
  model_class.model_name.singular
437
444
  end
@@ -9,12 +9,30 @@ module Avo
9
9
  class_attribute :items_holder
10
10
  class_attribute :grid_cols, default: 3
11
11
  class_attribute :visible, default: true
12
+ class_attribute :index, default: 0
12
13
 
13
14
  class << self
14
- def card(klass)
15
+ def card(klass, label: nil, description: nil, cols: nil, rows: nil, refresh_every: nil, options: {})
15
16
  self.items_holder ||= []
16
17
 
17
- self.items_holder << klass.new(dashboard: self)
18
+ self.items_holder << klass.new(dashboard: self,
19
+ label: label,
20
+ description: description,
21
+ cols: cols,
22
+ rows: rows,
23
+ refresh_every: refresh_every,
24
+ options: options,
25
+ index: index
26
+ )
27
+ self.index += 1
28
+ end
29
+
30
+ def item_at_index(index)
31
+ items.find do |item|
32
+ next if item.index.blank?
33
+
34
+ item.index == index
35
+ end
18
36
  end
19
37
 
20
38
  def divider(**args)
@@ -3,12 +3,14 @@ module Avo
3
3
  class BaseDivider
4
4
  attr_reader :label
5
5
  attr_reader :invisible
6
+ attr_reader :index
6
7
 
7
8
  class_attribute :id
8
9
 
9
- def initialize(label: nil, invisible: false)
10
+ def initialize(label: nil, invisible: false, index: nil)
10
11
  @label = label
11
12
  @invisible = invisible
13
+ @index = index
12
14
  end
13
15
 
14
16
  def is_divider?
@@ -0,0 +1,6 @@
1
+ module Avo
2
+ module Dashboards
3
+ class DashboardCard < Avo::BaseCard
4
+ end
5
+ end
6
+ end
@@ -1,6 +1,6 @@
1
1
  module Avo
2
2
  module Dashboards
3
- class PartialCard < BaseCard
3
+ class PartialCard < Avo::BaseCard
4
4
  class_attribute :partial
5
5
  end
6
6
  end
@@ -104,7 +104,7 @@ module Avo
104
104
 
105
105
  return @name if @name.present?
106
106
 
107
- return t(translation_key, count: 1, default: default).capitalize if @translation_key
107
+ return t(translation_key, count: 1, default: default).capitalize if translation_key
108
108
 
109
109
  default
110
110
  end
@@ -112,7 +112,7 @@ module Avo
112
112
  def plural_name
113
113
  default = name.pluralize
114
114
 
115
- return t(translation_key, count: 2, default: default).capitalize if @translation_key
115
+ return t(translation_key, count: 2, default: default).capitalize if translation_key
116
116
 
117
117
  default
118
118
  end
@@ -19,7 +19,7 @@ module Avo
19
19
  return if value.blank?
20
20
 
21
21
  if @format.is_a?(Symbol)
22
- value.to_s(@format)
22
+ value.to_formatted_s(@format)
23
23
  else
24
24
  value.strftime(@format)
25
25
  end
@@ -2,14 +2,19 @@ module Avo
2
2
  module FieldsCollector
3
3
  def field(field_name, as:, **args, &block)
4
4
  self.fields ||= []
5
+ self.invalid_fields ||= []
5
6
 
6
7
  field_instance = parse_field(field_name, as: as, **args, &block)
7
8
 
8
9
  if field_instance.present?
9
10
  self.fields << field_instance
10
11
  else
11
- message = "[Avo] The #{field_name} field, as: #{as} from #{self.name} has an invalid configuration."
12
- ::Rails.logger.warn message
12
+ self.invalid_fields << ({
13
+ name: field_name,
14
+ as: as,
15
+ resource: name,
16
+ message: "There's an invalid field configuration for this resource. <br/> <code class='px-1 py-px rounded bg-red-600'>field :#{field_name}, as: #{as}</code>"
17
+ })
13
18
  end
14
19
  end
15
20
 
@@ -10,6 +10,7 @@ module Avo
10
10
  option :dashboard
11
11
  option :card
12
12
  option :params
13
+ option :options
13
14
 
14
15
  delegate :result, to: :card
15
16
 
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.1.1"
2
+ VERSION = "2.1.2.pre1"
3
3
  end
@@ -6685,8 +6685,8 @@ progress[value]::-moz-progress-bar{
6685
6685
  max-width:100%
6686
6686
  }
6687
6687
 
6688
- .max-w-sm{
6689
- max-width:24rem
6688
+ .max-w-lg{
6689
+ max-width:32rem
6690
6690
  }
6691
6691
 
6692
6692
  .max-w-xs{
@@ -7174,6 +7174,11 @@ progress[value]::-moz-progress-bar{
7174
7174
  border-color:rgb(87 93 102 / var(--tw-border-opacity))
7175
7175
  }
7176
7176
 
7177
+ .bg-red-600{
7178
+ --tw-bg-opacity:1;
7179
+ background-color:rgb(220 38 38 / var(--tw-bg-opacity))
7180
+ }
7181
+
7177
7182
  .bg-white{
7178
7183
  --tw-bg-opacity:1;
7179
7184
  background-color:rgb(255 255 255 / var(--tw-bg-opacity))
@@ -7291,6 +7296,16 @@ progress[value]::-moz-progress-bar{
7291
7296
  padding:0.25rem
7292
7297
  }
7293
7298
 
7299
+ .px-1{
7300
+ padding-left:0.25rem;
7301
+ padding-right:0.25rem
7302
+ }
7303
+
7304
+ .py-px{
7305
+ padding-top:1px;
7306
+ padding-bottom:1px
7307
+ }
7308
+
7294
7309
  .px-2{
7295
7310
  padding-left:0.5rem;
7296
7311
  padding-right:0.5rem
@@ -7356,21 +7371,11 @@ progress[value]::-moz-progress-bar{
7356
7371
  padding-bottom:0px
7357
7372
  }
7358
7373
 
7359
- .px-1{
7360
- padding-left:0.25rem;
7361
- padding-right:0.25rem
7362
- }
7363
-
7364
7374
  .py-4{
7365
7375
  padding-top:1rem;
7366
7376
  padding-bottom:1rem
7367
7377
  }
7368
7378
 
7369
- .py-px{
7370
- padding-top:1px;
7371
- padding-bottom:1px
7372
- }
7373
-
7374
7379
  .py-24{
7375
7380
  padding-top:6rem;
7376
7381
  padding-bottom:6rem
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: 2.1.1
4
+ version: 2.1.2.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Marin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-04-01 00:00:00.000000000 Z
12
+ date: 2022-04-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -234,6 +234,9 @@ files:
234
234
  - Gemfile.lock
235
235
  - README.md
236
236
  - Rakefile
237
+ - app/assets/builds/avo.css
238
+ - app/assets/builds/avo.js
239
+ - app/assets/builds/avo.js.map
237
240
  - app/assets/config/avo_manifest.js
238
241
  - app/assets/stylesheets/avo.css
239
242
  - app/assets/stylesheets/css/active-storage.css
@@ -1085,6 +1088,7 @@ files:
1085
1088
  - app/views/avo/partials/_navbar.html.erb
1086
1089
  - app/views/avo/partials/_resource_search.html.erb
1087
1090
  - app/views/avo/partials/_scripts.html.erb
1091
+ - app/views/avo/partials/_sidebar_extra.html.erb
1088
1092
  - app/views/avo/partials/_sortable_component.html.erb
1089
1093
  - app/views/avo/partials/_table_header.html.erb
1090
1094
  - app/views/avo/partials/_view_toggle_button.html.erb
@@ -1120,12 +1124,13 @@ files:
1120
1124
  - lib/avo/action_model.rb
1121
1125
  - lib/avo/app.rb
1122
1126
  - lib/avo/base_action.rb
1127
+ - lib/avo/base_card.rb
1123
1128
  - lib/avo/base_resource.rb
1124
1129
  - lib/avo/configuration.rb
1125
- - lib/avo/dashboards/base_card.rb
1126
1130
  - lib/avo/dashboards/base_dashboard.rb
1127
1131
  - lib/avo/dashboards/base_divider.rb
1128
1132
  - lib/avo/dashboards/chartkick_card.rb
1133
+ - lib/avo/dashboards/dashboard_card.rb
1129
1134
  - lib/avo/dashboards/metric_card.rb
1130
1135
  - lib/avo/dashboards/partial_card.rb
1131
1136
  - lib/avo/dynamic_router.rb
@@ -1280,9 +1285,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
1280
1285
  version: 2.4.0
1281
1286
  required_rubygems_version: !ruby/object:Gem::Requirement
1282
1287
  requirements:
1283
- - - ">="
1288
+ - - ">"
1284
1289
  - !ruby/object:Gem::Version
1285
- version: '0'
1290
+ version: 1.3.1
1286
1291
  requirements: []
1287
1292
  rubygems_version: 3.3.3
1288
1293
  signing_key: