avo 2.10.2 → 2.10.3.pre.1

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +64 -62
  3. data/app/components/avo/fields/country_field/edit_component.html.erb +9 -3
  4. data/app/components/avo/fields/date_field/edit_component.html.erb +26 -8
  5. data/app/components/avo/fields/date_field/index_component.html.erb +7 -1
  6. data/app/components/avo/fields/date_field/show_component.html.erb +7 -1
  7. data/app/components/avo/fields/date_time_field/edit_component.html.erb +26 -10
  8. data/app/components/avo/fields/date_time_field/index_component.html.erb +9 -1
  9. data/app/components/avo/fields/date_time_field/show_component.html.erb +9 -1
  10. data/app/components/avo/fields/file_field/edit_component.html.erb +1 -0
  11. data/app/components/avo/fields/files_field/edit_component.html.erb +1 -0
  12. data/app/components/avo/fields/select_field/edit_component.html.erb +14 -10
  13. data/app/components/avo/index/ordering/button_component.rb +1 -5
  14. data/app/components/avo/views/resource_index_component.html.erb +1 -1
  15. data/app/controllers/avo/application_controller.rb +15 -9
  16. data/app/controllers/avo/base_controller.rb +11 -3
  17. data/app/controllers/avo/reorder_controller.rb +25 -0
  18. data/app/helpers/avo/application_helper.rb +6 -0
  19. data/app/helpers/avo/url_helpers.rb +0 -4
  20. data/app/javascript/js/controllers/fields/date_field_controller.js +98 -24
  21. data/app/javascript/js/controllers/search_controller.js +3 -0
  22. data/app/views/avo/partials/_javascript.html.erb +1 -1
  23. data/config/routes.rb +5 -4
  24. data/db/factories.rb +1 -0
  25. data/lib/avo/app.rb +1 -3
  26. data/lib/avo/base_resource.rb +5 -3
  27. data/lib/avo/concerns/handles_field_args.rb +1 -1
  28. data/lib/avo/concerns/has_fields.rb +2 -0
  29. data/lib/avo/configuration.rb +2 -12
  30. data/lib/avo/fields/base_field.rb +2 -0
  31. data/lib/avo/fields/country_field.rb +2 -0
  32. data/lib/avo/fields/date_field.rb +12 -10
  33. data/lib/avo/fields/date_time_field.rb +21 -9
  34. data/lib/avo/fields/field_extensions/has_include_blank.rb +17 -0
  35. data/lib/avo/fields/file_field.rb +2 -0
  36. data/lib/avo/fields/files_field.rb +2 -0
  37. data/lib/avo/fields/select_field.rb +2 -0
  38. data/lib/avo/licensing/h_q.rb +2 -0
  39. data/lib/avo/services/uri_service.rb +4 -0
  40. data/lib/avo/version.rb +1 -1
  41. data/lib/generators/avo/action_generator.rb +3 -2
  42. data/lib/generators/avo/base_generator.rb +14 -0
  43. data/lib/generators/avo/card/chartkick_generator.rb +18 -0
  44. data/lib/generators/avo/card/metric_generator.rb +18 -0
  45. data/lib/generators/avo/card/partial_generator.rb +19 -0
  46. data/lib/generators/avo/controller_generator.rb +9 -3
  47. data/lib/generators/avo/dashboard_generator.rb +2 -2
  48. data/lib/generators/avo/eject_generator.rb +2 -3
  49. data/lib/generators/avo/field_generator.rb +2 -2
  50. data/lib/generators/avo/filter_generator.rb +3 -2
  51. data/lib/generators/avo/install_generator.rb +2 -2
  52. data/lib/generators/avo/locales_generator.rb +2 -2
  53. data/lib/generators/avo/named_base_generator.rb +14 -0
  54. data/lib/generators/avo/resource_generator.rb +2 -2
  55. data/lib/generators/avo/resource_tool_generator.rb +4 -4
  56. data/lib/generators/avo/tool_generator.rb +4 -4
  57. data/lib/generators/avo/version_generator.rb +23 -0
  58. data/public/avo-assets/avo.css +4 -0
  59. data/public/avo-assets/avo.js +69 -69
  60. data/public/avo-assets/avo.js.map +2 -2
  61. metadata +12 -11
  62. data/db/migrate/20210421064037_add_color_to_teams.rb +0 -5
  63. data/db/migrate/20210423075924_add_progress_to_projects.rb +0 -5
  64. data/db/migrate/20210525143134_add_slug_to_users.rb +0 -6
  65. data/lib/avo/fields/currency_field.rb +0 -15
  66. data/lib/generators/avo/chartkick_card_generator.rb +0 -16
  67. data/lib/generators/avo/metric_card_generator.rb +0 -16
  68. data/lib/generators/avo/partial_card_generator.rb +0 -17
@@ -2,63 +2,137 @@ import { Controller } from '@hotwired/stimulus'
2
2
  import { DateTime } from 'luxon'
3
3
  import flatpickr from 'flatpickr'
4
4
 
5
- import { castBoolean } from '../../helpers/cast_boolean'
6
-
7
5
  // Get the DateTime with the TZ offset applied.
8
6
  function universalTimestamp(timestampStr) {
9
7
  return new Date(new Date(timestampStr).getTime() + (new Date(timestampStr).getTimezoneOffset() * 60 * 1000))
10
8
  }
11
9
 
12
10
  export default class extends Controller {
13
- static targets = ['input']
11
+ static targets = ['input', 'fakeInput']
12
+
13
+ static values = {
14
+ view: String,
15
+ timezone: String,
16
+ format: String,
17
+ enableTime: Boolean,
18
+ pickerFormat: String,
19
+ firstDayOfWeek: Number,
20
+ time24Hr: Boolean,
21
+ disableMobile: Boolean,
22
+ }
23
+
24
+ get browserZone() {
25
+ const time = DateTime.local()
26
+
27
+ return time.zoneName
28
+ }
29
+
30
+ get initialValue() {
31
+ if (this.isOnShow || this.isOnIndex) {
32
+ return this.context.element.innerText
33
+ } if (this.isOnEdit) {
34
+ return this.inputTarget.value
35
+ }
36
+
37
+ return null
38
+ }
39
+
40
+ get isOnIndex() {
41
+ return this.viewValue === 'index'
42
+ }
43
+
44
+ get isOnEdit() {
45
+ return this.viewValue === 'edit'
46
+ }
47
+
48
+ get isOnShow() {
49
+ return this.viewValue === 'show'
50
+ }
51
+
52
+ // Parse the time as if it were UTC
53
+ get parsedValue() {
54
+ return DateTime.fromISO(this.initialValue, { zone: 'UTC' })
55
+ }
56
+
57
+ get displayTimezone() {
58
+ return this.timezoneValue || this.browserZone
59
+ }
14
60
 
15
61
  connect() {
62
+ if (this.isOnShow || this.isOnIndex) {
63
+ this.initShow()
64
+ } else if (this.isOnEdit) {
65
+ this.initEdit()
66
+ }
67
+ }
68
+
69
+ // Turns the value in the controller wrapper into the timezone of the browser
70
+ initShow() {
71
+ this.context.element.innerText = this.parsedValue.setZone(this.displayTimezone).toFormat(this.formatValue)
72
+ }
73
+
74
+ initEdit() {
16
75
  const options = {
17
76
  enableTime: false,
18
77
  enableSeconds: false,
19
78
  // eslint-disable-next-line camelcase
20
- time_24hr: false,
79
+ time_24hr: this.time24HrValue,
21
80
  locale: {
22
81
  firstDayOfWeek: 0,
23
82
  },
24
83
  altInput: true,
84
+ onChange: this.onChange.bind(this),
25
85
  }
26
- const enableTime = castBoolean(this.inputTarget.dataset.enableTime)
27
86
 
28
87
  // Set the format of the displayed input field.
29
- options.altFormat = this.inputTarget.dataset.pickerFormat
88
+ options.altFormat = this.pickerFormatValue
30
89
 
31
90
  // Disable native input in mobile browsers
32
- options.disableMobile = this.inputTarget.dataset.disableMobile
91
+ options.disableMobile = this.disableMobileValue
33
92
 
34
93
  // Set first day of the week.
35
- options.locale.firstDayOfWeek = this.inputTarget.dataset.firstDayOfWeek
94
+ options.locale.firstDayOfWeek = this.firstDayOfWeekValue
36
95
 
37
96
  // Enable time if needed.
38
- options.enableTime = enableTime
39
- options.enableSeconds = enableTime
40
-
41
- let currentValue
97
+ options.enableTime = this.enableTimeValue
98
+ options.enableSeconds = this.enableTimeValue
42
99
 
43
100
  // enable timezone display
44
- if (enableTime) {
45
- currentValue = DateTime.fromISO(this.inputTarget.value, { zone: window.Avo.configuration.timezone })
46
- currentValue = currentValue.setZone(this.inputTarget.dataset.timezone)
47
- currentValue = currentValue.toISO()
101
+ if (this.enableTimeValue) {
102
+ options.defaultDate = this.parsedValue.setZone(this.displayTimezone).toISO()
48
103
 
49
104
  options.dateFormat = 'Y-m-d H:i:S'
50
- // eslint-disable-next-line camelcase
51
- options.time_24hr = castBoolean(this.inputTarget.dataset.time24hr)
52
- // this.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
53
- options.appTimezone = this.inputTarget.dataset.timezone
54
105
  } else {
55
- // Because the browser treats the date like a timestamp and updates it ot 00:00 hour, when on a western timezone the date will be converted with one day offset.
106
+ // Because the browser treats the date like a timestamp and updates it at 00:00 hour, when on a western timezone the date will be converted with one day offset.
56
107
  // Ex: 2022-01-30 will render as 2022-01-29 on an American timezone
57
- currentValue = universalTimestamp(this.inputTarget.value)
108
+ options.defaultDate = universalTimestamp(this.initialValue)
58
109
  }
59
110
 
60
- options.defaultDate = currentValue
111
+ flatpickr(this.fakeInputTarget, options)
112
+
113
+ this.updateRealInput(this.parsedValue.setZone(this.displayTimezone).toISO())
114
+ }
115
+
116
+ onChange(selectedDates) {
117
+ let time
118
+ let args = {}
119
+
120
+ if (this.timezoneValue) {
121
+ args = { keepLocalTime: true }
122
+ } else {
123
+ args = { keepLocalTime: false }
124
+ }
125
+
126
+ if (this.enableTimeValue) {
127
+ time = DateTime.fromISO(selectedDates[0].toISOString()).setZone('UTC', args)
128
+ } else {
129
+ time = DateTime.fromISO(selectedDates[0].toISOString()).setZone('UTC', { keepLocalTime: true })
130
+ }
131
+
132
+ this.updateRealInput(time)
133
+ }
61
134
 
62
- flatpickr(this.inputTarget, options)
135
+ updateRealInput(value) {
136
+ this.inputTarget.value = value
63
137
  }
64
138
  }
@@ -147,6 +147,9 @@ export default class extends Controller {
147
147
  case 'rounded':
148
148
  classes = 'rounded'
149
149
  break
150
+ case 'square':
151
+ classes = 'rounded-none'
152
+ break
150
153
  }
151
154
 
152
155
  children.push(
@@ -1,6 +1,6 @@
1
1
  <%= javascript_tag nonce: true do %>
2
2
  window.Avo = window.Avo || { configuration: {} }
3
3
  Avo.configuration.timezone = '<%= Avo.configuration.timezone %>'
4
- Avo.configuration.root_path = '<%= Avo.configuration.root_path %>'
4
+ Avo.configuration.root_path = '<%= root_path_without_url %>'
5
5
  Avo.configuration.search_debounce = '<%= Avo.configuration.search_debounce %>'
6
6
  <% end %>
data/config/routes.rb CHANGED
@@ -16,16 +16,17 @@ Avo::Engine.routes.draw do
16
16
  post "/resources/:resource_name/:id/attachments/", to: "attachments#create"
17
17
  end
18
18
 
19
+ # Records ordering
20
+ scope "reorder", as: "reorder" do
21
+ patch "/:resource_name/:id", to: "reorder#order", as: "order"
22
+ end
23
+
19
24
  get "failed_to_load", to: "home#failed_to_load"
20
25
 
21
26
  scope "resources", as: "resources" do
22
27
  # Attachments
23
28
  delete "/:resource_name/:id/active_storage_attachments/:attachment_name/:attachment_id", to: "attachments#destroy"
24
29
 
25
- # Ordering
26
- patch "/:resource_name/:id/order", to: "resources#order", as: "order"
27
- patch "/:resource_name/:id/:related_name/:related_id/order", to: "associations#order", as: "associations_order"
28
-
29
30
  # Actions
30
31
  get "/:resource_name(/:id)/actions/:action_id", to: "actions#show"
31
32
  post "/:resource_name(/:id)/actions/:action_id", to: "actions#handle"
data/db/factories.rb CHANGED
@@ -44,6 +44,7 @@ FactoryBot.define do
44
44
 
45
45
  factory :comment do
46
46
  body { Faker::Lorem.paragraphs(number: rand(4...10)).join(" ") }
47
+ posted_at { Time.now - rand(10...365).days }
47
48
  end
48
49
 
49
50
  factory :review do
data/lib/avo/app.rb CHANGED
@@ -20,8 +20,6 @@ module Avo
20
20
  def boot
21
21
  init_fields
22
22
 
23
- I18n.locale = Avo.configuration.language_code
24
-
25
23
  if Rails.cache.instance_of?(ActiveSupport::Cache::NullStore)
26
24
  self.cache_store ||= ActiveSupport::Cache::MemoryStore.new
27
25
  else
@@ -172,7 +170,7 @@ module Avo
172
170
  payload[:license_abilities] = Avo::App&.license&.abilities
173
171
  payload[:cache_store] = self.cache_store&.class&.to_s
174
172
  payload[:avo_metadata] = hq&.avo_metadata
175
- payload[:app_timezone] = Time.now.zone
173
+ payload[:app_timezone] = Time.current.zone
176
174
  payload[:cache_key] = Avo::Licensing::HQ.cache_key
177
175
  payload[:cache_key_contents] = hq&.cached_response
178
176
 
@@ -10,6 +10,8 @@ module Avo
10
10
  include Avo::Concerns::ModelClassConstantized
11
11
 
12
12
  delegate :view_context, to: ::Avo::App
13
+ delegate :current_user, to: ::Avo::App
14
+ delegate :params, to: ::Avo::App
13
15
  delegate :simple_format, :content_tag, to: :view_context
14
16
  delegate :main_app, to: :view_context
15
17
  delegate :avo, to: :view_context
@@ -101,7 +103,7 @@ module Avo
101
103
 
102
104
  def initialize
103
105
  unless self.class.model_class.present?
104
- if model_class.present?
106
+ if model_class.present? && model_class.respond_to?(:base_class)
105
107
  self.class.model_class = model_class.base_class
106
108
  end
107
109
  end
@@ -153,7 +155,7 @@ module Avo
153
155
  end
154
156
 
155
157
  def class_name_without_resource
156
- self.class.name.demodulize.chomp("Resource")
158
+ self.class.name.demodulize.delete_suffix("Resource")
157
159
  end
158
160
 
159
161
  def model_class
@@ -199,7 +201,7 @@ module Avo
199
201
  end
200
202
 
201
203
  def name
202
- default = class_name_without_resource.titlecase
204
+ default = class_name_without_resource.to_s.gsub('::', ' ').underscore.humanize
203
205
 
204
206
  return @name if @name.present?
205
207
 
@@ -28,7 +28,7 @@ module Avo
28
28
  add_prop_from_args args, name: name, default: default, type: :array
29
29
  end
30
30
 
31
- def add_string_prop(args, name, default = [])
31
+ def add_string_prop(args, name, default = nil)
32
32
  add_prop_from_args args, name: name, default: default, type: :string
33
33
  end
34
34
  end
@@ -183,6 +183,7 @@ module Avo
183
183
  if field.is_a?(Avo::Fields::BelongsToField)
184
184
  if field.respond_to?(:foreign_key) &&
185
185
  reflection.inverse_of.present? &&
186
+ reflection.inverse_of.respond_to?(:foreign_key) &&
186
187
  reflection.inverse_of.foreign_key == field.foreign_key
187
188
  is_valid = false
188
189
  end
@@ -191,6 +192,7 @@ module Avo
191
192
  if field.respond_to?(:foreign_key) &&
192
193
  field.is_polymorphic? &&
193
194
  reflection.respond_to?(:polymorphic?) &&
195
+ reflection.inverse_of.respond_to?(:foreign_key) &&
194
196
  reflection.inverse_of.foreign_key == field.reflection.foreign_key
195
197
  is_valid = false
196
198
  end
@@ -40,7 +40,7 @@ module Avo
40
40
  @per_page = 24
41
41
  @per_page_steps = [12, 24, 48, 72]
42
42
  @via_per_page = 8
43
- @locale = "en-US"
43
+ @locale = nil
44
44
  @currency = "USD"
45
45
  @default_view_type = :table
46
46
  @license = "community"
@@ -78,16 +78,6 @@ module Avo
78
78
  @profile_menu = nil
79
79
  end
80
80
 
81
- def locale_tag
82
- ::ISO::Tag.new(locale)
83
- end
84
-
85
- def language_code
86
- locale_tag.language.code
87
- rescue
88
- "en"
89
- end
90
-
91
81
  def current_user_method(&block)
92
82
  @current_user = block if block.present?
93
83
  end
@@ -123,7 +113,7 @@ module Avo
123
113
  end
124
114
 
125
115
  def computed_root_path
126
- Avo::App.root_path
116
+ Avo.configuration.root_path
127
117
  end
128
118
 
129
119
  def feature_enabled?(feature)
@@ -76,6 +76,8 @@ module Avo
76
76
  @index_text_align = args[:index_text_align] || :left
77
77
  @html = args[:html] || nil
78
78
 
79
+ @args = args
80
+
79
81
  @updatable = true
80
82
  @computable = true
81
83
  @computed = block.present?
@@ -1,6 +1,8 @@
1
1
  module Avo
2
2
  module Fields
3
3
  class CountryField < BaseField
4
+ include Avo::Fields::FieldExtensions::HasIncludeBlank
5
+
4
6
  attr_reader :countries
5
7
  attr_reader :display_code
6
8
 
@@ -10,21 +10,23 @@ module Avo
10
10
  def initialize(id, **args, &block)
11
11
  super(id, **args, &block)
12
12
 
13
- @first_day_of_week = args[:first_day_of_week].present? ? args[:first_day_of_week].to_i : 0
14
- @picker_format = args[:picker_format].present? ? args[:picker_format] : "Y-m-d"
15
- @format = args[:format].present? ? args[:format] : :long
16
- @relative = args[:relative].present? ? args[:relative] : false
17
- @disable_mobile = args[:disable_mobile].present? ? args[:disable_mobile] : false
13
+ add_string_prop args, :first_day_of_week, 0
14
+ add_string_prop args, :picker_format, "Y-m-d"
15
+ add_string_prop args, :format, "yyyy-LL-dd"
16
+ add_boolean_prop args, :relative
17
+ add_boolean_prop args, :disable_mobile
18
18
  end
19
19
 
20
20
  def formatted_value
21
21
  return if value.blank?
22
22
 
23
- if @format.is_a?(Symbol)
24
- value.to_formatted_s(@format)
25
- else
26
- value.strftime(@format)
27
- end
23
+ value.iso8601
24
+ end
25
+
26
+ def edit_formatted_value
27
+ return nil if value.nil?
28
+
29
+ value.iso8601
28
30
  end
29
31
  end
30
32
  end
@@ -2,25 +2,29 @@ module Avo
2
2
  module Fields
3
3
  class DateTimeField < DateField
4
4
  attr_reader :format
5
+ attr_reader :picker_format
5
6
  attr_reader :time_24hr
6
7
  attr_reader :timezone
7
8
 
8
9
  def initialize(id, **args, &block)
9
10
  super(id, **args, &block)
10
11
 
11
- @picker_format = args[:picker_format].present? ? args[:picker_format] : "Y-m-d H:i:S"
12
- @time_24hr = args[:time_24hr].present? ? args[:time_24hr] : false
13
- @timezone = args[:timezone].present? ? args[:timezone] : Rails.application.config.time_zone
12
+ add_boolean_prop args, :time_24hr
13
+ add_string_prop args, :picker_format, "Y-m-d H:i:S"
14
+ add_string_prop args, :format, "yyyy-LL-dd TT"
15
+ add_string_prop args, :timezone
14
16
  end
15
17
 
16
18
  def formatted_value
17
19
  return nil if value.nil?
18
20
 
19
- if @format.is_a?(Symbol)
20
- value.to_time.in_time_zone(timezone).to_formatted_s(@format)
21
- else
22
- value.to_time.in_time_zone(timezone).strftime(@format)
23
- end
21
+ value.utc.to_time.iso8601
22
+ end
23
+
24
+ def edit_formatted_value
25
+ return nil if value.nil?
26
+
27
+ value.utc.iso8601
24
28
  end
25
29
 
26
30
  def fill_field(model, key, value, params)
@@ -32,10 +36,18 @@ module Avo
32
36
 
33
37
  return model if value.blank?
34
38
 
35
- model[id] = value.to_time.in_time_zone(Rails.application.config.time_zone)
39
+ model[id] = utc_time(value)
36
40
 
37
41
  model
38
42
  end
43
+
44
+ def utc_time(value)
45
+ if timezone.present?
46
+ ActiveSupport::TimeZone.new(timezone).local_to_utc(Time.parse(value))
47
+ else
48
+ value
49
+ end
50
+ end
39
51
  end
40
52
  end
41
53
  end
@@ -0,0 +1,17 @@
1
+ module Avo
2
+ module Fields
3
+ module FieldExtensions
4
+ module HasIncludeBlank
5
+ def include_blank
6
+ if @args[:include_blank] == true
7
+ placeholder || '—'
8
+ elsif @args[:include_blank] == false
9
+ false
10
+ else
11
+ @args[:include_blank]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -6,6 +6,7 @@ module Avo
6
6
  attr_accessor :is_image
7
7
  attr_accessor :is_audio
8
8
  attr_accessor :direct_upload
9
+ attr_accessor :accept
9
10
 
10
11
  def initialize(id, **args, &block)
11
12
  super(id, **args, &block)
@@ -15,6 +16,7 @@ module Avo
15
16
  @is_image = args[:is_image].present? ? args[:is_image] : @is_avatar
16
17
  @is_audio = args[:is_audio].present? ? args[:is_audio] : false
17
18
  @direct_upload = args[:direct_upload].present? ? args[:direct_upload] : false
19
+ @accept = args[:accept].present? ? args[:accept] : nil
18
20
  end
19
21
 
20
22
  def path
@@ -4,6 +4,7 @@ module Avo
4
4
  attr_accessor :is_audio
5
5
  attr_accessor :is_image
6
6
  attr_accessor :direct_upload
7
+ attr_accessor :accept
7
8
 
8
9
  def initialize(id, **args, &block)
9
10
  super(id, **args, &block)
@@ -11,6 +12,7 @@ module Avo
11
12
  @is_audio = args[:is_audio].present? ? args[:is_audio] : false
12
13
  @is_image = args[:is_image].present? ? args[:is_image] : @is_avatar
13
14
  @direct_upload = args[:direct_upload].present? ? args[:direct_upload] : false
15
+ @accept = args[:accept].present? ? args[:accept] : nil
14
16
  end
15
17
 
16
18
  def view_component_name
@@ -1,6 +1,8 @@
1
1
  module Avo
2
2
  module Fields
3
3
  class SelectField < BaseField
4
+ include Avo::Fields::FieldExtensions::HasIncludeBlank
5
+
4
6
  attr_reader :options
5
7
  attr_reader :enum
6
8
  attr_reader :display_value
@@ -121,6 +121,8 @@ module Avo
121
121
  cache_and_return_error "HTTP connection reset error.", exception.message
122
122
  rescue Errno::ECONNREFUSED => exception
123
123
  cache_and_return_error "HTTP connection refused error.", exception.message
124
+ rescue OpenSSL::SSL::SSLError => exception
125
+ cache_and_return_error "OpenSSL error.", exception.message
124
126
  rescue HTTParty::Error => exception
125
127
  cache_and_return_error "HTTP client error.", exception.message
126
128
  rescue Net::OpenTimeout => exception
@@ -13,6 +13,10 @@ module Avo
13
13
  @uri = Addressable::URI.parse(path)
14
14
  end
15
15
 
16
+ def call
17
+ to_s
18
+ end
19
+
16
20
  def append_paths(*paths)
17
21
  paths = Array.wrap(paths).flatten
18
22
 
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.10.2" unless const_defined?(:VERSION)
2
+ VERSION = "2.10.3.pre.1" unless const_defined?(:VERSION)
3
3
  end
@@ -1,9 +1,10 @@
1
- require "rails/generators"
1
+ require_relative "named_base_generator"
2
2
 
3
3
  module Generators
4
4
  module Avo
5
- class ActionGenerator < Rails::Generators::NamedBase
5
+ class ActionGenerator < NamedBaseGenerator
6
6
  source_root File.expand_path("templates", __dir__)
7
+
7
8
  class_option :standalone, type: :boolean
8
9
 
9
10
  namespace "avo:action"
@@ -0,0 +1,14 @@
1
+ require "rails/generators"
2
+
3
+ module Generators
4
+ module Avo
5
+ class BaseGenerator < ::Rails::Generators::Base
6
+ hide!
7
+
8
+ def initialize(*args)
9
+ super(*args)
10
+ invoke "avo:version", *args
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "../named_base_generator"
2
+
3
+ module Generators
4
+ module Avo
5
+ module Card
6
+ class ChartkickGenerator < Generators::Avo::NamedBaseGenerator
7
+ source_root File.expand_path("../templates", __dir__)
8
+
9
+ namespace "avo:card:chartkick"
10
+ desc "Add a chartkick card for your Avo dashboard."
11
+
12
+ def handle
13
+ template "cards/chartkick_card_sample.tt", "app/avo/cards/#{name.underscore}.rb"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "../named_base_generator"
2
+
3
+ module Generators
4
+ module Avo
5
+ module Card
6
+ class MetricGenerator < Generators::Avo::NamedBaseGenerator
7
+ source_root File.expand_path("../templates", __dir__)
8
+
9
+ namespace "avo:card:metric"
10
+ desc "Add a metric card for your Avo dashboard."
11
+
12
+ def handle
13
+ template "cards/metric_card_sample.tt", "app/avo/cards/#{name.underscore}.rb"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "../named_base_generator"
2
+
3
+ module Generators
4
+ module Avo
5
+ module Card
6
+ class PartialGenerator < Generators::Avo::NamedBaseGenerator
7
+ source_root File.expand_path("../templates", __dir__)
8
+
9
+ namespace "avo:card:partial"
10
+ desc "Add a partial card for your Avo dashboard."
11
+
12
+ def handle
13
+ template "cards/partial_card_sample.tt", "app/avo/cards/#{name.underscore}.rb"
14
+ template "cards/partial_card_partial.tt", "app/views/avo/cards/_#{name.underscore}.html.erb"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,19 +1,25 @@
1
- require "rails/generators"
1
+ require_relative "named_base_generator"
2
2
 
3
3
  module Generators
4
4
  module Avo
5
- class ControllerGenerator < Rails::Generators::NamedBase
5
+ class ControllerGenerator < NamedBaseGenerator
6
6
  source_root File.expand_path("templates", __dir__)
7
7
 
8
8
  namespace "avo:controller"
9
9
 
10
10
  def create
11
- template "resource/%plural_name%_controller.tt", "app/controllers/avo/#{controller_name}.rb"
11
+ template "resource/controller.tt", "app/controllers/avo/#{controller_name}.rb"
12
12
  end
13
13
 
14
+ private
15
+
14
16
  def controller_name
15
17
  "#{plural_name}_controller"
16
18
  end
19
+
20
+ def controller_class
21
+ "Avo::#{class_name.camelize.pluralize}Controller"
22
+ end
17
23
  end
18
24
  end
19
25
  end
@@ -1,8 +1,8 @@
1
- require "rails/generators"
1
+ require_relative "named_base_generator"
2
2
 
3
3
  module Generators
4
4
  module Avo
5
- class DashboardGenerator < ::Rails::Generators::NamedBase
5
+ class DashboardGenerator < NamedBaseGenerator
6
6
  source_root File.expand_path("templates", __dir__)
7
7
 
8
8
  namespace "avo:dashboard"