avo 4.0.26 → 4.1.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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +8 -1
  3. data/app/assets/builds/avo/application.css +9 -21
  4. data/app/assets/builds/avo/application.js +71 -71
  5. data/app/assets/builds/avo/application.js.map +3 -3
  6. data/app/assets/builds/avo/avo.custom.js +6 -0
  7. data/app/assets/builds/avo/avo.custom.js.map +7 -0
  8. data/app/assets/stylesheets/css/components/modal.css +7 -1
  9. data/app/assets/stylesheets/css/components/ui/tabs.css +10 -0
  10. data/app/components/avo/modal_component.html.erb +0 -1
  11. data/app/components/avo/modal_component.rb +1 -1
  12. data/app/components/avo/row_selector_component.rb +3 -3
  13. data/app/controllers/avo/actions_controller.rb +1 -3
  14. data/app/controllers/avo/appearance_settings_controller.rb +1 -1
  15. data/app/controllers/avo/array_controller.rb +1 -1
  16. data/app/controllers/avo/associations_controller.rb +1 -3
  17. data/app/controllers/avo/attachments_controller.rb +1 -3
  18. data/app/controllers/avo/base_controller.rb +1 -3
  19. data/app/controllers/avo/charts_controller.rb +1 -3
  20. data/app/controllers/avo/debug_controller.rb +1 -3
  21. data/app/controllers/avo/home_controller.rb +1 -3
  22. data/app/controllers/avo/media_library_controller.rb +1 -1
  23. data/app/controllers/avo/private_controller.rb +1 -3
  24. data/app/controllers/avo/resources_controller.rb +1 -3
  25. data/app/controllers/avo/search_controller.rb +1 -3
  26. data/app/javascript/js/controllers/modal_size_controller.js +9 -49
  27. data/app/javascript/js/controllers/record_selector_controller.js +25 -8
  28. data/app/views/avo/media_library/index.html.erb +4 -1
  29. data/avo.gemspec +1 -1
  30. data/lib/avo/version.rb +1 -1
  31. metadata +4 -2
@@ -1,7 +1,5 @@
1
- require_dependency "avo/application_controller"
2
-
3
1
  module Avo
4
- class AttachmentsController < ApplicationController
2
+ class AttachmentsController < Avo::ApplicationController
5
3
  before_action :set_resource_name, only: [:destroy, :create]
6
4
  before_action :set_resource, only: [:destroy, :create]
7
5
  before_action :set_record, only: [:destroy, :create]
@@ -1,7 +1,5 @@
1
- require_dependency "avo/application_controller"
2
-
3
1
  module Avo
4
- class BaseController < ApplicationController
2
+ class BaseController < Avo::ApplicationController
5
3
  include Avo::Concerns::FiltersSessionHandler
6
4
  include Avo::Concerns::AssociationQueryScope
7
5
  include Avo::Concerns::SafeCall
@@ -1,7 +1,5 @@
1
- require_dependency "avo/base_controller"
2
-
3
1
  module Avo
4
- class ChartsController < BaseController
2
+ class ChartsController < Avo::BaseController
5
3
  # Summarizable charts reuse the index query pipeline (including policy scope via
6
4
  # `query_scope`). They were never meant to require `distribution_chart?` /
7
5
  # `distribution_chart_full?` policy methods — those only surfaced once
@@ -1,7 +1,5 @@
1
- require_dependency "avo/application_controller"
2
-
3
1
  module Avo
4
- class DebugController < ApplicationController
2
+ class DebugController < Avo::ApplicationController
5
3
  before_action :authenticate_developer_or_admin!
6
4
 
7
5
  def status
@@ -1,7 +1,5 @@
1
- require_dependency "avo/application_controller"
2
-
3
1
  module Avo
4
- class HomeController < ApplicationController
2
+ class HomeController < Avo::ApplicationController
5
3
  def index
6
4
  if Avo.configuration.home_path.present?
7
5
  # If the home_path is a block run it, if not, just use it
@@ -1,5 +1,5 @@
1
1
  module Avo
2
- class MediaLibraryController < ApplicationController
2
+ class MediaLibraryController < Avo::ApplicationController
3
3
  include Pagy::Method
4
4
 
5
5
  before_action :authorize_access!
@@ -1,7 +1,5 @@
1
- require_dependency "avo/application_controller"
2
-
3
1
  module Avo
4
- class PrivateController < ApplicationController
2
+ class PrivateController < Avo::ApplicationController
5
3
  before_action :authenticate_developer_or_admin!
6
4
 
7
5
  def design
@@ -1,6 +1,4 @@
1
- require_dependency "avo/base_controller"
2
-
3
1
  module Avo
4
- class ResourcesController < BaseController
2
+ class ResourcesController < Avo::BaseController
5
3
  end
6
4
  end
@@ -3,10 +3,8 @@
3
3
  # This controller is currently only used for searchable fields, it keeps the old search controller without any changes
4
4
  # Possibly have much more logic that it uses, but it's not worth the effort to refactor it since we're going to replace it with a new searchable fields way
5
5
 
6
- require_dependency "avo/application_controller"
7
-
8
6
  module Avo
9
- class SearchController < ApplicationController
7
+ class SearchController < Avo::ApplicationController
10
8
  include Rails.application.routes.url_helpers
11
9
  include ActionView::Helpers::TextHelper
12
10
 
@@ -2,8 +2,6 @@ import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  // Connects to data-controller="modal-size"
4
4
  export default class extends Controller {
5
- static targets = ['container']
6
-
7
5
  static values = {
8
6
  currentWidth: String,
9
7
  currentHeight: String,
@@ -28,56 +26,18 @@ export default class extends Controller {
28
26
  }
29
27
 
30
28
  updateWidthClass(width) {
31
- // Remove all modal width classes from the modal element
32
- this.modalElement.classList.remove(
33
- 'modal--width-sm',
34
- 'modal--width-md',
35
- 'modal--width-lg',
36
- 'modal--width-xl',
37
- 'modal--width-2xl',
38
- 'modal--width-3xl',
39
- 'modal--width-4xl',
40
- 'modal--width-full',
41
- 'modal--width-25',
42
- 'modal--width-50',
43
- 'modal--width-75',
44
- 'modal--width-100',
45
- )
46
-
47
- // Remove all width classes from the container
48
- this.containerTarget.classList.remove('w-sm', 'w-md', 'w-lg', 'w-xl', 'w-2xl', 'w-3xl', 'w-4xl', 'w-full')
49
-
50
- // Add the new modal width class to the modal element
51
- this.modalElement.classList.add(`modal--width-${width}`)
52
-
53
- // Add the corresponding width class to the container
54
- if (width === 'full') {
55
- this.containerTarget.classList.add('w-full')
56
- } else {
57
- this.containerTarget.classList.add(`w-${width}`)
58
- }
29
+ this.#swapModifier('modal--width-', width)
59
30
  }
60
31
 
61
32
  updateHeightClass(height) {
62
- // Remove all modal height classes from the modal element
63
- this.modalElement.classList.remove(
64
- 'modal--height-auto',
65
- 'modal--height-sm',
66
- 'modal--height-md',
67
- 'modal--height-lg',
68
- 'modal--height-xl',
69
- 'modal--height-2xl',
70
- 'modal--height-3xl',
71
- 'modal--height-4xl',
72
- 'modal--height-full',
73
- 'modal--height-25',
74
- 'modal--height-50',
75
- 'modal--height-75',
76
- 'modal--height-100',
77
- )
33
+ this.#swapModifier('modal--height-', height)
34
+ }
78
35
 
79
- // Add the new modal height class to the modal element
80
- // The CSS will handle applying the appropriate height to .modal__card
81
- this.modalElement.classList.add(`modal--height-${height}`)
36
+ // The CSS owns the sizes: each `modal--width-*` / `modal--height-*` modifier
37
+ // sizes `.modal__card`. Swapping by prefix means a new size token is a CSS
38
+ // rule and nothing else — no list here to keep in sync with the stylesheet.
39
+ #swapModifier(prefix, value) {
40
+ this.modalElement.classList.remove(...[...this.modalElement.classList].filter((name) => name.startsWith(prefix)))
41
+ this.modalElement.classList.add(`${prefix}${value}`)
82
42
  }
83
43
  }
@@ -9,8 +9,19 @@ export default class extends Controller {
9
9
 
10
10
  autoClicking = false
11
11
 
12
+ // Every lookup in here is scoped to this controller's element. A page can hold several tables (a
13
+ // show page renders one per has_many association) and each numbers its rows from zero, so a
14
+ // document-wide lookup by index always lands in the first table.
12
15
  get itemSelectorCells() {
13
- return document.querySelectorAll('.item-selector-cell')
16
+ return this.element.querySelectorAll('.item-selector-cell')
17
+ }
18
+
19
+ #rowAt(index) {
20
+ return this.element.querySelector(`tr[data-index="${index}"]`)
21
+ }
22
+
23
+ #checkboxAt(index) {
24
+ return this.element.querySelector(`input[type="checkbox"][data-index="${index}"]`)
14
25
  }
15
26
 
16
27
  get hasLastCheckedIndex() {
@@ -32,6 +43,12 @@ export default class extends Controller {
32
43
  return
33
44
  }
34
45
 
46
+ // Ranges are addressed by row. Index view types outside a table (avo-notifications renders one)
47
+ // give this component an index but no row to walk up to, so there's nothing to span.
48
+ if (!event.target.closest('tr')) {
49
+ return
50
+ }
51
+
35
52
  // If there's no last checked index and the shift key isn't pressed, set the starting index
36
53
  if (!this.hasLastCheckedIndex) {
37
54
  this.#setStartingIndex(event)
@@ -57,7 +74,7 @@ export default class extends Controller {
57
74
 
58
75
  // Loop through the range of rows and toggle the checkboxes
59
76
  theRange.forEach((index) => {
60
- const checkbox = document.querySelector(`input[type="checkbox"][data-index="${index}"]`)
77
+ const checkbox = this.#checkboxAt(index)
61
78
 
62
79
  // Toggle the checkbox if it's not in the same state as the target checkbox
63
80
  if (checkbox.checked !== state) {
@@ -110,7 +127,8 @@ export default class extends Controller {
110
127
  #selectorMouseenterHandler(event) {
111
128
  // Add the highlighted-row class to the row that the mouse is over
112
129
  event.target.closest('tr').classList.add('highlighted-row')
113
- if (this.lastCheckedIndex) {
130
+ // Check against null, not truthiness — index 0 is a valid anchor
131
+ if (this.hasLastCheckedIndex) {
114
132
  // Highlight the range of rows between the last checked index and the current index
115
133
  this.#highlightRange(this.lastCheckedIndex, parseInt(event.target.closest('tr').dataset.index))
116
134
  }
@@ -120,17 +138,16 @@ export default class extends Controller {
120
138
  // Remove the highlighted-row class from the row that the mouse is over
121
139
  event.target.closest('tr').classList.remove('highlighted-row')
122
140
  // Remove the highlighted-row class from all rows
123
- document.querySelectorAll('tr[data-index]').forEach((tr) => {
141
+ this.element.querySelectorAll('tr[data-index]').forEach((tr) => {
124
142
  tr.classList.remove('highlighted-row')
125
143
  })
126
144
  }
127
145
 
128
146
  // Highlight the range of rows between the start index and the end index
129
147
  #highlightRange(startIndex, endIndex) {
130
- const theRange = difference(range(startIndex, endIndex))
131
- theRange.forEach((index) => {
132
- const tr = document.querySelector(`tr[data-index="${index}"]`)
133
- tr.classList.add('highlighted-row')
148
+ // `range` excludes the end index, but the hovered row is highlighted by the caller
149
+ range(startIndex, endIndex).forEach((index) => {
150
+ this.#rowAt(index).classList.add('highlighted-row')
134
151
  })
135
152
  }
136
153
 
@@ -1,6 +1,9 @@
1
1
  <%= render Avo::TurboFrameWrapperComponent.new(turbo_frame_request_id) do %>
2
2
  <% if turbo_frame_request_id %>
3
- <%= render Avo::ModalComponent.new(title: t("avo.media_library.title")) do |c| %>
3
+ <%# The library is a grid of media cards (13rem floor per card), so the default
4
+ :xl modal fits two columns and 4xl three, leaving a ragged last row. 5xl
5
+ fits four, so a page of 12 lands as three full rows. %>
6
+ <%= render Avo::ModalComponent.new(title: t("avo.media_library.title"), width: :"5xl") do |c| %>
4
7
  <div class="p-4">
5
8
  <%= render Avo::MediaLibrary::ListComponent.new attaching: @attaching %>
6
9
  </div>
data/avo.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  "public gem pushes."
29
29
  end
30
30
 
31
- spec.required_ruby_version = ">= 3.0.0"
31
+ spec.required_ruby_version = ">= 3.2.0"
32
32
  spec.post_install_message = "Thank you for using Avo 💪 Docs are available at https://docs.avohq.io"
33
33
 
34
34
  # NOTE: `public/` is rejected below — Avo 4 ships precompiled assets from
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "4.0.26" unless const_defined?(:VERSION)
2
+ VERSION = "4.1.0" 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.0.26
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Marin
@@ -224,6 +224,8 @@ files:
224
224
  - app/assets/builds/avo/application.css
225
225
  - app/assets/builds/avo/application.js
226
226
  - app/assets/builds/avo/application.js.map
227
+ - app/assets/builds/avo/avo.custom.js
228
+ - app/assets/builds/avo/avo.custom.js.map
227
229
  - app/assets/builds/avo/dependencies.css
228
230
  - app/assets/builds/avo/late-registration.js
229
231
  - app/assets/builds/avo/late-registration.js.map
@@ -1187,7 +1189,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
1187
1189
  requirements:
1188
1190
  - - ">="
1189
1191
  - !ruby/object:Gem::Version
1190
- version: 3.0.0
1192
+ version: 3.2.0
1191
1193
  required_rubygems_version: !ruby/object:Gem::Requirement
1192
1194
  requirements:
1193
1195
  - - ">="