avo 2.13.0 → 2.13.2.pre.2

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +3 -1
  3. data/app/assets/stylesheets/avo.css +1 -1
  4. data/app/assets/stylesheets/css/fields/progress.css +3 -3
  5. data/app/assets/stylesheets/css/pagination.css +0 -4
  6. data/app/assets/stylesheets/css/search.css +1 -1
  7. data/app/assets/stylesheets/css/sidebar.css +1 -1
  8. data/app/assets/stylesheets/css/tags.css +7 -0
  9. data/app/assets/svgs/failed_to_load.svg +4 -5
  10. data/app/assets/svgs/grid-empty-state.svg +10 -11
  11. data/app/assets/svgs/table-empty-state.svg +11 -12
  12. data/app/components/avo/actions_component.html.erb +2 -2
  13. data/app/components/avo/actions_component.rb +1 -1
  14. data/app/components/avo/button_component.rb +3 -3
  15. data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -1
  16. data/app/components/avo/fields/progress_bar_field/index_component.html.erb +1 -1
  17. data/app/components/avo/fields/progress_bar_field/show_component.html.erb +1 -1
  18. data/app/components/avo/fields/tags_field/edit_component.html.erb +1 -1
  19. data/app/components/avo/fields/tags_field/show_component.rb +2 -0
  20. data/app/components/avo/profile_item_component.html.erb +1 -1
  21. data/app/components/avo/tab_group_component.html.erb +1 -1
  22. data/app/components/avo/tab_switcher_component.rb +2 -2
  23. data/app/components/avo/views/resource_edit_component.rb +1 -1
  24. data/app/components/avo/views/resource_index_component.html.erb +2 -2
  25. data/app/components/avo/views/resource_index_component.rb +0 -17
  26. data/app/components/avo/views/resource_show_component.html.erb +1 -2
  27. data/app/controllers/avo/base_controller.rb +11 -8
  28. data/app/controllers/avo/search_controller.rb +20 -57
  29. data/app/helpers/avo/resources_helper.rb +2 -2
  30. data/app/javascript/avo.js +0 -1
  31. data/app/javascript/js/controllers/fields/trix_field_controller.js +4 -3
  32. data/app/javascript/js/controllers/item_selector_controller.js +1 -1
  33. data/app/javascript/js/controllers/menu_controller.js +2 -2
  34. data/app/javascript/js/controllers/search_controller.js +15 -42
  35. data/app/views/avo/associations/new.html.erb +2 -3
  36. data/app/views/avo/base/_multiple_select_filter.html.erb +1 -1
  37. data/app/views/avo/base/_text_filter.html.erb +1 -1
  38. data/app/views/avo/partials/_branding.html.erb +5 -0
  39. data/app/views/avo/partials/_header.html.erb +1 -1
  40. data/app/views/avo/partials/_logo.html.erb +2 -2
  41. data/app/views/avo/partials/_resource_search.html.erb +0 -6
  42. data/app/views/avo/private/_links_and_buttons.html.erb +1 -1
  43. data/app/views/avo/private/design.html.erb +3 -3
  44. data/app/views/layouts/avo/application.html.erb +1 -0
  45. data/lib/avo/concerns/has_editable_controls.rb +1 -1
  46. data/lib/avo/configuration/branding.rb +65 -0
  47. data/lib/avo/configuration.rb +5 -0
  48. data/lib/avo/dashboards/chartkick_card.rb +1 -1
  49. data/lib/avo/fields/base_field.rb +1 -1
  50. data/lib/avo/fields/has_base_field.rb +0 -2
  51. data/lib/avo/licensing/pro_license.rb +1 -0
  52. data/lib/avo/version.rb +1 -1
  53. data/lib/generators/avo/templates/initializer/avo.tt +14 -0
  54. data/lib/generators/avo/templates/resource/resource.tt +1 -1
  55. data/public/avo-assets/avo.css +286 -248
  56. data/public/avo-assets/avo.js +47 -47
  57. data/public/avo-assets/avo.js.map +2 -2
  58. metadata +6 -13
  59. data/app/components/avo/button_component.html.erb +0 -1
  60. data/app/helpers/avo/actions_helper.rb +0 -4
  61. data/app/helpers/avo/attachments_helper.rb +0 -4
  62. data/app/views/kaminari/_first_page.html.erb +0 -3
  63. data/app/views/kaminari/_last_page.html.erb +0 -3
  64. data/app/views/kaminari/_next_page.html.erb +0 -9
  65. data/app/views/kaminari/_page.html.erb +0 -12
  66. data/app/views/kaminari/_prev_page.html.erb +0 -9
  67. data/lib/avo/hosts/search_scope_host.rb +0 -7
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-alert */
1
2
  import 'trix'
2
3
  import { Controller } from '@hotwired/stimulus'
3
4
  import { castBoolean } from '../../helpers/cast_boolean'
@@ -48,7 +49,7 @@ export default class extends Controller {
48
49
  // Prevent file uploads for fields that have attachments disabled.
49
50
  if (this.attachmentsDisabled) {
50
51
  event.preventDefault()
51
- window.toastr.warning('This field has attachments disabled.')
52
+ alert('This field has attachments disabled.')
52
53
 
53
54
  return
54
55
  }
@@ -56,7 +57,7 @@ export default class extends Controller {
56
57
  // Prevent file uploads for resources that haven't been saved yet.
57
58
  if (this.resourceId === '') {
58
59
  event.preventDefault()
59
- window.toastr.warning("You can't upload files into the Trix editor until you save the resource.")
60
+ alert("You can't upload files into the Trix editor until you save the resource.")
60
61
 
61
62
  return
62
63
  }
@@ -64,7 +65,7 @@ export default class extends Controller {
64
65
  // Prevent file uploads for fields without an attachment key.
65
66
  if (this.attachmentKey === '') {
66
67
  event.preventDefault()
67
- window.toastr.warning("You haven't set an <a href='https://google.com' class='!text-blue-700 underline'>attachment_key</a> to this Trix field.")
68
+ alert("You haven't set an `attachment_key` to this Trix field.")
68
69
  }
69
70
  }
70
71
  })
@@ -5,7 +5,7 @@ export default class extends Controller {
5
5
 
6
6
  checkbox = {};
7
7
 
8
- enabledClasses = ['text-black', 'hover:bg-blue-500', 'hover:text-white']
8
+ enabledClasses = ['text-black']
9
9
 
10
10
  disabledClasses = ['text-gray-500']
11
11
 
@@ -22,8 +22,8 @@ export default class extends Controller {
22
22
  }
23
23
 
24
24
  get initiallyCollapsed() {
25
- if (!this.userState) {
26
- return this.defaultState === 'collapsed'
25
+ if (this.defaultState === 'collapsed') {
26
+ return this.userState === 'collapsed'
27
27
  }
28
28
 
29
29
  return this.userState === 'collapsed'
@@ -48,10 +48,6 @@ export default class extends Controller {
48
48
  return this.dataset.viaAssociation === 'belongs_to'
49
49
  }
50
50
 
51
- get isHasManySearch() {
52
- return this.dataset.viaAssociation === 'has_many'
53
- }
54
-
55
51
  get isGlobalSearch() {
56
52
  return this.dataset.searchResource === 'global'
57
53
  }
@@ -87,50 +83,27 @@ export default class extends Controller {
87
83
  params.global = true
88
84
  }
89
85
 
90
- if (this.isBelongsToSearch || this.isHasManySearch) {
91
- params = this.addAssociationParams(params)
92
- params = this.addReflectionParams(params)
93
-
94
- if (this.isBelongsToSearch) {
95
- params = {
96
- ...params,
97
- // eslint-disable-next-line camelcase
98
- via_parent_resource_id: this.dataset.viaParentResourceId,
99
- // eslint-disable-next-line camelcase
100
- via_parent_resource_class: this.dataset.viaParentResourceClass,
101
- // eslint-disable-next-line camelcase
102
- via_relation: this.dataset.viaRelation,
103
- }
86
+ if (this.isBelongsToSearch) {
87
+ params = {
88
+ ...params,
89
+ // eslint-disable-next-line camelcase
90
+ via_association_id: this.dataset.viaAssociationId,
91
+ // eslint-disable-next-line camelcase
92
+ via_reflection_class: this.dataset.viaReflectionClass,
93
+ // eslint-disable-next-line camelcase
94
+ via_reflection_id: this.dataset.viaReflectionId,
95
+ // eslint-disable-next-line camelcase
96
+ via_parent_resource_id: this.dataset.viaParentResourceId,
97
+ // eslint-disable-next-line camelcase
98
+ via_parent_resource_class: this.dataset.viaParentResourceClass,
99
+ // eslint-disable-next-line camelcase
100
+ via_relation: this.dataset.viaRelation,
104
101
  }
105
102
  }
106
103
 
107
104
  return params
108
105
  }
109
106
 
110
- addAssociationParams(params) {
111
- params = {
112
- ...params,
113
- // eslint-disable-next-line camelcase
114
- via_association: this.dataset.viaAssociation,
115
- // eslint-disable-next-line camelcase
116
- via_association_id: this.dataset.viaAssociationId,
117
- }
118
-
119
- return params
120
- }
121
-
122
- addReflectionParams(params) {
123
- params = {
124
- ...params,
125
- // eslint-disable-next-line camelcase
126
- via_reflection_class: this.dataset.viaReflectionClass,
127
- // eslint-disable-next-line camelcase
128
- via_reflection_id: this.dataset.viaReflectionId,
129
- }
130
-
131
- return params
132
- }
133
-
134
107
  handleOnSelect({ item }) {
135
108
  if (this.isBelongsToSearch) {
136
109
  this.updateFieldAttribute(this.hiddenIdTarget, 'value', item._id)
@@ -13,7 +13,6 @@
13
13
  <div class="flex-1 flex items-center justify-center px-0 lg:px-8 text-lg mt-8 mb-12">
14
14
  <% if @field.searchable %>
15
15
  <%= render Avo::Fields::BelongsToField::AutocompleteComponent.new form: form,
16
- classes: input_classes("w-full"),
17
16
  field: @field,
18
17
  model_key: @field.target_resource&.model_key,
19
18
  foreign_key: 'related_id',
@@ -35,10 +34,10 @@
35
34
  </div>
36
35
 
37
36
  <% c.controls do %>
38
- <%= a_button 'data-action': 'click->modal#close', size: :sm do %>
37
+ <%= a_button 'data-action': 'click->modal#close', size: :sm, style: :outline, color: :primary do %>
39
38
  <%= t('avo.cancel') %>
40
39
  <% end %>
41
- <%= a_button type: :submit, color: :green, size: :sm do %>
40
+ <%= a_button type: :submit, style: :primary, color: :primary, size: :sm do %>
42
41
  <%= t('avo.attach') %>
43
42
  <% end %>
44
43
  <% end %>
@@ -12,7 +12,7 @@
12
12
  'data-multiple-select-filter-target': 'selector'
13
13
  %>
14
14
  <div class="flex justify-end">
15
- <%= a_button class: 'mt-4', color: :blue, size: :xs, data: { action: "multiple-select-filter#changeFilter" } do %>
15
+ <%= a_button class: 'mt-4', color: :primary, size: :xs, data: { action: "multiple-select-filter#changeFilter" } do %>
16
16
  Filter by <%=filter.name %>
17
17
  <% end %>
18
18
  </div>
@@ -13,7 +13,7 @@
13
13
  'data-action': 'keypress->text-filter#tryToSubmit'
14
14
  %>
15
15
  <div class="flex justify-end">
16
- <%= a_button class: 'mt-4', color: :blue, data: { action: "text-filter#changeFilter" }, size: :xs do %>
16
+ <%= a_button class: 'mt-4', color: :primary, data: { action: "text-filter#changeFilter" }, size: :xs do %>
17
17
  <%= filter.button_label || "Filter by #{filter.name}" %>
18
18
  <% end %>
19
19
  </div>
@@ -0,0 +1,5 @@
1
+ <style>
2
+ :root {
3
+ <%= Avo.configuration.branding.css_colors %>
4
+ }
5
+ </style>
@@ -1 +1 @@
1
- <%= link_to Avo.configuration.app_name, '/', class: 'text-blue-500 font-semibold', target: :_blank %>
1
+ <%= link_to Avo.configuration.app_name, '/', class: 'text-primary-500 font-semibold', target: :_blank %>
@@ -1,4 +1,4 @@
1
1
  <%= link_to root_path, class: 'logo-placeholder h-full w-full flex justify-start' do %>
2
- <%= image_tag '/avo-assets/logo.png', class: 'hidden sm:block object-contain', title: 'Avo' %>
3
- <%= image_tag '/avo-assets/logomark.png', class: 'sm:hidden object-contain', title: 'Avo' %>
2
+ <%= image_tag Avo.configuration.branding.logo, class: 'hidden sm:block object-contain', title: 'Avo' %>
3
+ <%= image_tag Avo.configuration.branding.logomark, class: 'sm:hidden object-contain', title: 'Avo' %>
4
4
  <% end %>
@@ -3,12 +3,6 @@
3
3
  data-search-target="autocomplete"
4
4
  data-search-resource="<%= resource %>"
5
5
  data-translation-keys='{"no_item_found": "<%= I18n.translate 'avo.no_item_found' %>"}'
6
- <% if via_reflection.present? %>
7
- data-via-association="<%= via_reflection[:association] %>"
8
- data-via-association-id="<%= via_reflection[:association_id] %>"
9
- data-via-reflection-class="<%= via_reflection[:class] %>"
10
- data-via-reflection-id="<%= via_reflection[:id] %>"
11
- <% end %>
12
6
  >
13
7
  </div>
14
8
  <div class="hidden relative inline-flex text-gray-400 text-sm border border-gray-300 rounded cursor-pointer" data-search-target="button"></div>
@@ -2,7 +2,7 @@
2
2
  entities = [:button, :link]
3
3
  sizes = [:xl, :lg, :md, :sm, :xs].reverse
4
4
  styles = [:primary, :outline, :text]
5
- colors = [:primary, :gray, :red, :orange, :green]
5
+ colors = [:primary, :blue, :gray, :red, :orange, :green]
6
6
  states = [:regular, :hover, :disabled, :active]
7
7
  %>
8
8
  <div class="px-6 space-y-4">
@@ -6,15 +6,15 @@
6
6
  <% end %>
7
7
 
8
8
  <%= a_link('/admin', icon: 'arrow-left', style: :outline, is_link: true) do %>
9
- Secondary
9
+ Outline
10
10
  <% end %>
11
11
 
12
12
  <%= a_link('/admin', icon: 'arrow-left', style: :outline, color: :red, is_link: true) do %>
13
13
  Red
14
14
  <% end %>
15
15
 
16
- <%= a_link('/admin', icon: 'arrow-left', style: :outline, color: :orange, is_link: true) do %>
17
- Red
16
+ <%= a_link('/admin', icon: 'arrow-left', style: :text, color: :orange, is_link: true) do %>
17
+ Text
18
18
  <% end %>
19
19
  <% end %>
20
20
 
@@ -7,6 +7,7 @@
7
7
  <%= csp_meta_tag %>
8
8
  <%= render partial: 'avo/partials/javascript' %>
9
9
  <%= render partial: 'avo/partials/head' %>
10
+ <%= render partial: 'avo/partials/branding' %>
10
11
  <% if Avo::PACKED %>
11
12
  <%= javascript_include_tag "/avo-assets/avo", "data-turbo-track": "reload", defer: true %>
12
13
  <%= stylesheet_link_tag "/avo-assets/avo", "data-turbo-track": "reload", defer: true %>
@@ -24,7 +24,7 @@ module Avo
24
24
  resource: self,
25
25
  record: model,
26
26
  view: view
27
- ).handle&.items || []
27
+ ).handle.items
28
28
  else
29
29
  []
30
30
  end
@@ -0,0 +1,65 @@
1
+ class Avo::Configuration::Branding
2
+ def initialize(colors: nil, chart_colors: nil, logo: nil, logomark: nil)
3
+ @colors = colors
4
+ @chart_colors = chart_colors
5
+ @logo = logo
6
+ @logomark = logomark
7
+
8
+ @default_colors = {
9
+ 100 => "206 231 248",
10
+ 400 => "57 158 229",
11
+ 500 => "8 134 222",
12
+ 600 => "6 107 178"
13
+ }
14
+ @default_chart_colors = ["#0B8AE2", "#34C683", "#2AB1EE", "#34C6A8"]
15
+ @default_logo = "/avo-assets/logo.png"
16
+ @default_logomark = "/avo-assets/logomark.png"
17
+ end
18
+
19
+ def css_colors
20
+ rgb_colors.map do |color, value|
21
+ "--color-primary-#{color}: #{value};"
22
+ end.join("\n")
23
+ end
24
+
25
+ def logo
26
+ return @default_logo if Avo::App.license.lacks_with_trial(:branding)
27
+
28
+ @logo || @default_logo
29
+ end
30
+
31
+ def logomark
32
+ return @default_logomark if Avo::App.license.lacks_with_trial(:branding)
33
+
34
+ @logomark || @default_logomark
35
+ end
36
+
37
+ def chart_colors
38
+ return @default_chart_colors if Avo::App.license.lacks_with_trial(:branding)
39
+
40
+ @chart_colors || @default_chart_colors
41
+ end
42
+
43
+ private
44
+
45
+ def colors
46
+ return @default_colors if Avo::App.license.lacks_with_trial(:branding)
47
+
48
+ @colors || @default_colors
49
+ end
50
+
51
+ def rgb_colors
52
+ colors.map do |key, value|
53
+ rgb_value = is_hex?(value) ? hex_to_rgb(value) : value
54
+ [key, rgb_value]
55
+ end.to_h
56
+ end
57
+
58
+ def is_hex?(value)
59
+ value.include? "#"
60
+ end
61
+
62
+ def hex_to_rgb(value)
63
+ value.to_s.match(/^#(..)(..)(..)$/).captures.map(&:hex).join(" ")
64
+ end
65
+ end
@@ -34,6 +34,7 @@ module Avo
34
34
  attr_accessor :buttons_on_form_footers
35
35
  attr_accessor :main_menu
36
36
  attr_accessor :profile_menu
37
+ attr_writer :branding
37
38
 
38
39
  def initialize
39
40
  @root_path = "/avo"
@@ -121,6 +122,10 @@ module Avo
121
122
  def feature_enabled?(feature)
122
123
  !@disabled_features.map(&:to_sym).include?(feature.to_sym)
123
124
  end
125
+
126
+ def branding
127
+ Avo::Configuration::Branding.new(**@branding || {})
128
+ end
124
129
  end
125
130
 
126
131
  def self.configuration
@@ -29,7 +29,7 @@ module Avo
29
29
  default = {
30
30
  # figure our the available height for the chart
31
31
  height: "#{(rows * card_height) - card_heading}px",
32
- colors: %w[#0B8AE2 #34C683 #2AB1EE #34C6A8],
32
+ colors: ::Avo.configuration.branding.chart_colors,
33
33
  library: {
34
34
  discrete: false,
35
35
  points: false,
@@ -160,7 +160,7 @@ module Avo
160
160
  final_value = @model.send(property) if (model_or_class(@model) == "model") && @model.respond_to?(property)
161
161
 
162
162
  # On new views and actions modals we need to prefill the fields
163
- if @view.in?([:new, :create]) || @action.present?
163
+ if (@view === :new) || @action.present?
164
164
  if default.present?
165
165
  final_value = if default.respond_to?(:call)
166
166
  default.call
@@ -6,7 +6,6 @@ module Avo
6
6
  attr_accessor :attach_scope
7
7
  attr_accessor :description
8
8
  attr_accessor :discreet_pagination
9
- attr_accessor :hide_search_input
10
9
 
11
10
  def initialize(id, **args, &block)
12
11
  super(id, **args, &block)
@@ -15,7 +14,6 @@ module Avo
15
14
  @attach_scope = args[:attach_scope].present? ? args[:attach_scope] : nil
16
15
  @display = args[:display].present? ? args[:display] : :show
17
16
  @searchable = args[:searchable] == true
18
- @hide_search_input = args[:hide_search_input] || false
19
17
  @description = args[:description]
20
18
  @use_resource = args[:use_resource] || nil
21
19
  @discreet_pagination = args[:discreet_pagination] || false
@@ -16,6 +16,7 @@ module Avo
16
16
  :menu_editor,
17
17
  :stimulus_js_integration,
18
18
  :resource_show_controls,
19
+ :branding,
19
20
  :advanced_fields
20
21
  ]
21
22
  end
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.13.0" unless const_defined?(:VERSION)
2
+ VERSION = "2.13.2.pre.2" unless const_defined?(:VERSION)
3
3
  end
@@ -52,6 +52,20 @@ Avo.configure do |config|
52
52
  # config.display_license_request_timeout_error = true
53
53
  # config.disabled_features = []
54
54
  # config.resource_controls = :right
55
+ # config.buttons_on_form_footers = true
56
+
57
+ ## == Branding ==
58
+ # config.branding = {
59
+ # colors: {
60
+ # 100 => "#CEE7F8",
61
+ # 400 => "#399EE5",
62
+ # 500 => "#0886DE",
63
+ # 600 => "#066BB2",
64
+ # },
65
+ # chart_colors: ["#0B8AE2", "#34C683", "#2AB1EE", "#34C6A8"],
66
+ # logo: "/avo-assets/logo.png"
67
+ # logomark: "/avo-assets/logomark.png",
68
+ # }
55
69
 
56
70
 
57
71
  ## == Breadcrumbs ==
@@ -1,7 +1,7 @@
1
1
  class <%= resource_class %> < Avo::BaseResource
2
2
  self.title = :id
3
3
  self.includes = []
4
- # self.search_query = -> do
4
+ # self.search_query = ->(params:) do
5
5
  # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false)
6
6
  # end
7
7