avo 2.9.1.pre5 → 2.9.1.pre6

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.

@@ -43,10 +43,14 @@ class Avo::ActionsComponent < ViewComponent::Base
43
43
  end
44
44
 
45
45
  def single_record_path(id)
46
- "#{@resource.record_path}/actions/#{id}"
46
+ Avo::Services::URIService.parse(@resource.record_path)
47
+ .append_paths("actions", id)
48
+ .to_s
47
49
  end
48
50
 
49
51
  def many_records_path(id)
50
- "#{@resource.records_path}/actions/#{id}"
52
+ Avo::Services::URIService.parse(@resource.records_path)
53
+ .append_paths("actions", id)
54
+ .to_s
51
55
  end
52
56
  end
@@ -3,7 +3,7 @@
3
3
  data-key-value-target="controller"
4
4
  data-options="<%= @field.options.to_json %>"
5
5
  data-input-classes="<%= input_classes %>"
6
- data-editable="<%= @view.in?([:edit, :create]) %>"
6
+ data-editable="<%= @view.in?([:edit, :new]) %>"
7
7
  >
8
8
  <div class="w-full flex flex-col">
9
9
  <div class="flex w-full">
@@ -14,7 +14,7 @@
14
14
  <div class="w-1/2 py-3 px-3 uppercase font-semibold text-xs text-white">
15
15
  <%= @field.value_label %>
16
16
  </div>
17
- <% if @view.in?([:edit, :create]) %>
17
+ <% if @view.in?([:edit, :new]) %>
18
18
  <div class="flex items-center justify-center p-2 px-3 border-l border-gray-600">
19
19
  <a href="javascript:void(0);"
20
20
  title="<%= @field.action_text %>"
@@ -10,7 +10,7 @@ class Avo::Fields::Common::SingleFileViewerComponent < ViewComponent::Base
10
10
  end
11
11
 
12
12
  def destroy_path
13
- "#{@resource.record_path}/active_storage_attachments/#{id}/#{file.id}"
13
+ Avo::Services::URIService.parse(@resource.record_path).append_paths("active_storage_attachments", id, file.id).to_s
14
14
  end
15
15
 
16
16
  def id
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Index::Ordering::ButtonComponent < Avo::Index::Ordering::BaseComponent
4
+ delegate :view_context, to: ::Avo::App
5
+
4
6
  attr_accessor :resource
5
7
  attr_accessor :reflection
6
8
  attr_accessor :direction
@@ -18,20 +20,10 @@ class Avo::Index::Ordering::ButtonComponent < Avo::Index::Ordering::BaseComponen
18
20
  end
19
21
 
20
22
  def order_path(args)
21
- if reflection.present?
22
- path = "#{::Avo::App.root_path}/resources/#{reflection_parent_resource.route_key}/#{params[:id]}/#{field.id}/#{resource.model.id}/order"
23
+ if reflection.present?
24
+ view_context.avo.associations_order_path(reflection_parent_resource.route_key, params[:id], field.id, resource.model.id, **args)
23
25
  else
24
- path = "#{::Avo::App.root_path}/resources/#{resource.route_key}/#{resource.model.id}/order"
26
+ view_context.avo.resources_order_path(resource.route_key, resource.model.id, **args)
25
27
  end
26
-
27
- if args.present?
28
- string_args = args.map do |key, value|
29
- "#{key}=#{value}"
30
- end.join('&')
31
-
32
- path = "#{path}?#{string_args}"
33
- end
34
-
35
- path
36
28
  end
37
29
  end
@@ -46,7 +46,7 @@
46
46
  }
47
47
  %>
48
48
  <%= hidden_field_tag :turbo_frame, params[:turbo_frame], id: "turbo_frame_detach_#{@resource.model.id}" if params[:turbo_frame] %>
49
- <%= hidden_field_tag :referrer, request.fullpath, id: "referrer_detach_#{@resource.model.id}" if params[:turbo_frame] %>
49
+ <%= hidden_field_tag :referrer, referrer_path, id: "referrer_detach_#{@resource.model.id}" if params[:turbo_frame] %>
50
50
  <% end %>
51
51
  <% end %>
52
52
 
@@ -71,7 +71,7 @@
71
71
  %>
72
72
  <%= form.hidden_field :view_type, value: params[:view_type], id: "turbo_view_type_#{@resource.model.id}" if params[:view_type] %>
73
73
  <%= form.hidden_field :turbo_frame, value: params[:turbo_frame], id: "turbo_frame_destroy_#{@resource.model.id}" if params[:turbo_frame] %>
74
- <%= form.hidden_field :referrer, value: request.fullpath, id: "referrer_destroy_#{@resource.model.id}" if params[:turbo_frame] %>
74
+ <%= form.hidden_field :referrer, value: referrer_path, id: "referrer_destroy_#{@resource.model.id}" if params[:turbo_frame] %>
75
75
  <% end %>
76
76
  <% end %>
77
77
  </div>
@@ -41,7 +41,7 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
41
41
  end
42
42
 
43
43
  def edit_path
44
- #Add the `view` param to let Avo know where to redirect back when the user clicks the `Cancel` button.
44
+ # Add the `view` param to let Avo know where to redirect back when the user clicks the `Cancel` button.
45
45
  args = {via_view: 'index'}
46
46
 
47
47
  if @parent_model.present?
@@ -71,4 +71,8 @@ class Avo::Index::ResourceControlsComponent < Avo::ResourceComponent
71
71
  def is_has_many_association
72
72
  @reflection.is_a?(::ActiveRecord::Reflection::HasManyReflection) || @reflection.is_a?(::ActiveRecord::Reflection::ThroughReflection)
73
73
  end
74
+
75
+ def referrer_path
76
+ Avo::App.root_path(paths: ['resources', params[:resource_name], params[:id], params[:related_name]], query: request.query_parameters.to_h)
77
+ end
74
78
  end
@@ -117,7 +117,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
117
117
  end
118
118
 
119
119
  def attach_path
120
- "#{Avo::App.root_path}#{request.env["PATH_INFO"]}/new"
120
+ Avo::App.root_path(paths: [request.env["PATH_INFO"], "new"])
121
121
  end
122
122
 
123
123
  def singular_resource_name
@@ -145,7 +145,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
145
145
  @reflection.active_record.to_s
146
146
  end
147
147
 
148
- def name
148
+ def name
149
149
  field.custom_name? ? field.name : field.plural_name
150
150
  end
151
151
 
@@ -13,7 +13,8 @@ module Avo
13
13
  protect_from_forgery with: :exception
14
14
  before_action :init_app
15
15
  before_action :check_avo_license
16
- before_action :set_locale
16
+ before_action :set_default_locale
17
+ around_action :set_force_locale
17
18
  before_action :set_authorization
18
19
  before_action :_authenticate!
19
20
  before_action :set_container_classes
@@ -27,7 +28,7 @@ module Avo
27
28
  add_flash_types :info, :warning, :success, :error
28
29
 
29
30
  def init_app
30
- Avo::App.init request: request, context: context, root_path: avo.root_path.delete_suffix("/"), current_user: _current_user, view_context: view_context, params: params
31
+ Avo::App.init request: request, context: context, current_user: _current_user, view_context: view_context, params: params
31
32
 
32
33
  @license = Avo::App.license
33
34
  end
@@ -287,10 +288,30 @@ module Avo
287
288
  @resource.form_scope
288
289
  end
289
290
 
290
- def set_locale
291
+ def set_default_locale
291
292
  I18n.locale = params[:set_locale] || I18n.default_locale
292
293
 
293
294
  I18n.default_locale = I18n.locale
294
295
  end
296
+
297
+ # Temporary set the locale
298
+ def set_force_locale
299
+ if params[:force_locale].present?
300
+ initial_locale = I18n.locale.to_s.dup
301
+ I18n.locale = params[:force_locale]
302
+ yield
303
+ I18n.locale = initial_locale
304
+ else
305
+ yield
306
+ end
307
+ end
308
+
309
+ def default_url_options
310
+ if params[:force_locale].present?
311
+ { **super, force_locale: params[:force_locale] }
312
+ else
313
+ super
314
+ end
315
+ end
295
316
  end
296
317
  end
@@ -74,7 +74,11 @@ document.addEventListener('turbo:frame-load', () => {
74
74
  document.addEventListener('turbo:before-fetch-response', async (e) => {
75
75
  if (e.detail.fetchResponse.response.status === 500) {
76
76
  const { id, src } = e.target
77
- e.target.src = `${window.Avo.configuration.root_path}/failed_to_load?turbo_frame=${id}&src=${src}`
77
+ // Don't try to redirect to failed to load if this is alread a redirection to failed to load and crashed somewhere.
78
+ // You'll end up with a request loop.
79
+ if (!e.detail.fetchResponse?.response?.url?.includes('/failed_to_load')) {
80
+ e.target.src = `${window.Avo.configuration.root_path}/failed_to_load?turbo_frame=${id}&src=${src}`
81
+ }
78
82
  }
79
83
  })
80
84
 
@@ -0,0 +1,80 @@
1
+ import { AttributeObserver } from '@stimulus/mutation-observers'
2
+ import { Controller } from '@hotwired/stimulus'
3
+ import { castBoolean } from '../helpers/cast_boolean'
4
+
5
+ export default class extends Controller {
6
+ static targets = ['tab'];
7
+
8
+ static values = {
9
+ activeTab: String,
10
+ };
11
+
12
+ get currentTab() {
13
+ return this.tabTargets.find(
14
+ (element) => element.dataset.tabId === this.activeTabValue,
15
+ )
16
+ }
17
+
18
+ targetTab(id) {
19
+ return this.tabTargets.find((element) => element.dataset.tabId === id)
20
+ }
21
+
22
+ changeTab(e) {
23
+ e.preventDefault()
24
+
25
+ const { params } = e
26
+ const { id } = params
27
+
28
+ this.setTheTargetPanelHeight(id)
29
+
30
+ this.hideTabs()
31
+ this.showTab(id)
32
+ this.markTabLoaded(id)
33
+
34
+ this.activeTabValue = id
35
+ }
36
+
37
+ /**
38
+ * Sets the target container height to the previous panel height so we don't get jerky tab changes.
39
+ */
40
+ setTheTargetPanelHeight(id) {
41
+ // We don't need to add a height to this panel because it was loaded before
42
+ if (castBoolean(this.targetTab(id).dataset.loaded)) {
43
+ return
44
+ }
45
+
46
+ // Get the height of the active panel
47
+ const { height } = this.currentTab.getBoundingClientRect()
48
+ // Set it to the target panel
49
+ this.targetTab(id).style.height = `${height}px`
50
+
51
+ // Wait until the panel loaded it's content and then remove the forced height
52
+ const observer = new AttributeObserver(this.targetTab(id), 'busy', {
53
+ elementUnmatchedAttribute: () => {
54
+ // The content is not available in an instant so delay the height reset a bit.
55
+ setTimeout(() => {
56
+ this.targetTab(id).style.height = ''
57
+ }, 300)
58
+ if (observer) observer.stop()
59
+ },
60
+ })
61
+ observer.start()
62
+ }
63
+
64
+ markTabLoaded(id) {
65
+ this.targetTab(id).dataset.loaded = true
66
+ }
67
+
68
+ showTab(id) {
69
+ this.tabTargets.forEach((element) => {
70
+ if (element.dataset.tabId === id) {
71
+ element.classList.remove('hidden')
72
+ }
73
+ })
74
+ // this.tabTargets.map((element) => element.clasList.add('hidden'))
75
+ }
76
+
77
+ hideTabs() {
78
+ this.tabTargets.map((element) => element.classList.add('hidden'))
79
+ }
80
+ }
@@ -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::App.root_path %>'
4
+ Avo.configuration.root_path = '<%= Avo.configuration.root_path %>'
5
5
  Avo.configuration.search_debounce = '<%= Avo.configuration.search_debounce %>'
6
6
  <% end %>
data/config/routes.rb CHANGED
@@ -23,7 +23,7 @@ Avo::Engine.routes.draw do
23
23
  delete "/:resource_name/:id/active_storage_attachments/:attachment_name/:attachment_id", to: "attachments#destroy"
24
24
 
25
25
  # Ordering
26
- patch "/:resource_name/:id/order", to: "resources#order"
26
+ patch "/:resource_name/:id/order", to: "resources#order", as: "order"
27
27
  patch "/:resource_name/:id/:related_name/:related_id/order", to: "associations#order", as: "associations_order"
28
28
 
29
29
  # Actions
data/lib/avo/app.rb CHANGED
@@ -29,13 +29,20 @@ module Avo
29
29
  end
30
30
  end
31
31
 
32
- def init(request:, context:, current_user:, root_path:, view_context:, params:)
32
+ # Renerate a dynamic root path using the URIService
33
+ def root_path(paths: [], query: {}, **args)
34
+ Avo::Services::URIService.parse(view_context.avo.root_url.to_s)
35
+ .append_paths(paths)
36
+ .append_query(query)
37
+ .to_s
38
+ end
39
+
40
+ def init(request:, context:, current_user:, view_context:, params:)
33
41
  self.error_messages = []
34
42
  self.context = context
35
43
  self.current_user = current_user
36
44
  self.params = params
37
45
  self.request = request
38
- self.root_path = root_path
39
46
  self.view_context = view_context
40
47
 
41
48
  self.license = Licensing::LicenseManager.new(Licensing::HQ.new(request).response).license
data/lib/avo/base_card.rb CHANGED
@@ -59,13 +59,7 @@ module Avo
59
59
  def frame_url(enforced_range: nil, params: {})
60
60
  enforced_range ||= initial_range || ranges.first
61
61
 
62
- # append the parent params to the card request
63
- begin
64
- other_params = "&#{params.permit!.to_h.map { |k, v| "#{k}=#{v}" }.join("&")}"
65
- rescue
66
- end
67
-
68
- "#{Avo::App.root_path}/dashboards/#{dashboard.id}/cards/#{id}?turbo_frame=#{turbo_frame}&index=#{index}&range=#{enforced_range}#{other_params}"
62
+ Avo::App.view_context.avo.dashboard_card_path(dashboard.id, id, turbo_frame: turbo_frame, index: index, range: enforced_range, **params.permit!)
69
63
  end
70
64
 
71
65
  def card_classes
@@ -65,7 +65,7 @@ module Avo
65
65
  end
66
66
 
67
67
  def navigation_path
68
- "#{Avo::App.root_path}/dashboards/#{id}"
68
+ Avo::App.view_context.avo.dashboard_path id
69
69
  end
70
70
 
71
71
  def is_visible?
@@ -29,7 +29,9 @@ module Avo
29
29
  end
30
30
 
31
31
  def frame_url
32
- "#{@resource.record_path}/#{id}?turbo_frame=#{turbo_frame}"
32
+ Avo::Services::URIService.parse(@resource.record_path)
33
+ .append_path(id.to_s)
34
+ .append_query(turbo_frame: turbo_frame.to_s).to_s
33
35
  end
34
36
 
35
37
  # The value
@@ -22,7 +22,10 @@ module Avo
22
22
  end
23
23
 
24
24
  def frame_url
25
- "#{@resource.record_path}/#{id}/#{value.id}?turbo_frame=#{turbo_frame}"
25
+ Avo::Services::URIService.parse(@resource.record_path)
26
+ .append_paths(id, value.id)
27
+ .append_query(turbo_frame: turbo_frame)
28
+ .to_s
26
29
  end
27
30
 
28
31
  def fill_field(model, key, value, params)
@@ -67,7 +67,7 @@ class Avo::Menu::Builder
67
67
  # Add all the tools
68
68
  def all_tools(**args)
69
69
  Avo::App.tools_for_navigation.each do |tool|
70
- link tool.humanize, path: "#{root_path}/#{tool}"
70
+ link tool.humanize, path: root_path(paths: [tool])
71
71
  end
72
72
  end
73
73
 
@@ -0,0 +1,71 @@
1
+ module Avo
2
+ module Services
3
+ class URIService
4
+ class << self
5
+ def parse(path)
6
+ self.new path
7
+ end
8
+ end
9
+
10
+ attr_reader :uri
11
+
12
+ def initialize(path = '')
13
+ @uri = Addressable::URI.parse(path)
14
+ end
15
+
16
+ def append_paths(*paths)
17
+ paths = Array.wrap(paths).flatten
18
+
19
+ return self if paths.blank?
20
+
21
+ # Add the intermediary forward slash
22
+ @uri.path = @uri.path.concat("/") unless @uri.path.ends_with? "/"
23
+
24
+ # Add the paths to the URI
25
+ @uri.merge!(path: @uri.path.concat(join_paths(paths)))
26
+
27
+ self
28
+ end
29
+ alias_method :append_path, :append_paths
30
+
31
+ def append_query(params)
32
+ params = if params.is_a? Hash
33
+ params.map do |key, value|
34
+ "#{key}=#{value}"
35
+ end
36
+ else
37
+ {}
38
+ end
39
+
40
+ return self if params.blank?
41
+
42
+ # Add the query params to the URI
43
+ @uri.merge!(query: [@uri.query, *params].compact.join("&"))
44
+
45
+ self
46
+ end
47
+
48
+ def to_s
49
+ @uri.to_s
50
+ end
51
+
52
+ private
53
+
54
+ def join_paths(paths)
55
+ paths.map do |path|
56
+ sanitize_path path
57
+ end
58
+ .join("/")
59
+ end
60
+
61
+ # Removes the forward slash if it's present at the start of the path
62
+ def sanitize_path(path)
63
+ if path.to_s.starts_with? '/'
64
+ path = path[1..-1]
65
+ end
66
+
67
+ path
68
+ end
69
+ end
70
+ end
71
+ end
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.9.1.pre5" unless const_defined?(:VERSION)
2
+ VERSION = "2.9.1.pre6" unless const_defined?(:VERSION)
3
3
  end
data/lib/avo.rb CHANGED
@@ -5,6 +5,7 @@ require_relative "avo/engine" if defined?(Rails)
5
5
  loader = Zeitwerk::Loader.for_gem
6
6
  loader.inflector.inflect(
7
7
  "html" => "HTML",
8
+ "uri_service" => "URIService",
8
9
  "has_html_attributes" => "HasHTMLAttributes"
9
10
  )
10
11
  loader.ignore("#{__dir__}/generators")
@@ -413,7 +413,7 @@ function print() { __p += __j.call(arguments, '') }
413
413
  %t [data-trix-cursor-target=right] {
414
414
  vertical-align: bottom !important;
415
415
  margin-right: -1px !important;
416
- }`,trixId:{get:function(){return this.hasAttribute("trix-id")?this.getAttribute("trix-id"):(this.setAttribute("trix-id",++T),this.trixId)}},labels:{get:function(){var D,M,P;return M=[],this.id&&this.ownerDocument&&M.push.apply(M,this.ownerDocument.querySelectorAll("label[for='"+this.id+"']")),(D=i(this,{matchingSelector:"label"}))&&((P=D.control)===this||P===null)&&M.push(D),M}},toolbarElement:{get:function(){var D,M,P;return this.hasAttribute("toolbar")?(M=this.ownerDocument)!=null?M.getElementById(this.getAttribute("toolbar")):void 0:this.parentNode?(P="trix-toolbar-"+this.trixId,this.setAttribute("toolbar",P),D=s("trix-toolbar",{id:P}),this.parentNode.insertBefore(D,this),D):void 0}},inputElement:{get:function(){var D,M,P;return this.hasAttribute("input")?(P=this.ownerDocument)!=null?P.getElementById(this.getAttribute("input")):void 0:this.parentNode?(M="trix-input-"+this.trixId,this.setAttribute("input",M),D=s("input",{type:"hidden",id:M}),this.parentNode.insertBefore(D,this.nextElementSibling),D):void 0}},editor:{get:function(){var D;return(D=this.editorController)!=null?D.editor:void 0}},name:{get:function(){var D;return(D=this.inputElement)!=null?D.name:void 0}},value:{get:function(){var D;return(D=this.inputElement)!=null?D.value:void 0},set:function(D){var M;return this.defaultValue=D,(M=this.editor)!=null?M.loadHTML(this.defaultValue):void 0}},notify:function(D,M){return this.editorController?u("trix-"+D,{onElement:this,attributes:M}):void 0},setInputElementValue:function(D){var M;return(M=this.inputElement)!=null?M.value=D:void 0},initialize:function(){return this.hasAttribute("data-trix-internal")?void 0:(k(this),f(this),w(this))},connect:function(){return this.hasAttribute("data-trix-internal")?void 0:(this.editorController||(u("trix-before-initialize",{onElement:this}),this.editorController=new e.EditorController({editorElement:this,html:this.defaultValue=this.value}),requestAnimationFrame(function(D){return function(){return u("trix-initialize",{onElement:D})}}(this))),this.editorController.registerSelectionManager(),this.registerResetListener(),this.registerClickListener(),p(this))},disconnect:function(){var D;return(D=this.editorController)!=null&&D.unregisterSelectionManager(),this.unregisterResetListener(),this.unregisterClickListener()},registerResetListener:function(){return this.resetListener=this.resetBubbled.bind(this),window.addEventListener("reset",this.resetListener,!1)},unregisterResetListener:function(){return window.removeEventListener("reset",this.resetListener,!1)},registerClickListener:function(){return this.clickListener=this.clickBubbled.bind(this),window.addEventListener("click",this.clickListener,!1)},unregisterClickListener:function(){return window.removeEventListener("click",this.clickListener,!1)},resetBubbled:function(D){var M;if(!D.defaultPrevented&&D.target===((M=this.inputElement)!=null?M.form:void 0))return this.reset()},clickBubbled:function(D){var M;if(!(D.defaultPrevented||this.contains(D.target)||!(M=i(D.target,{matchingSelector:"label"}))||c.call(this.labels,M)<0))return this.focus()},reset:function(){return this.value=this.defaultValue}}}())}.call(this),function(){}.call(this)}).call(this),typeof Ch=="object"&&Ch.exports?Ch.exports=e:typeof define=="function"&&define.amd&&define(e)}.call(Eh)});var ZMt,yC,$fe=se(()=>{ZMt=Vr(Vfe());Nr();Qg();yC=class extends At{get resourceId(){return this.controllerTarget.dataset.resourceId}get resourceName(){return this.controllerTarget.dataset.resourceName}get attachmentKey(){return this.controllerTarget.dataset.attachmentKey}get attachmentsDisabled(){return fo(this.controllerTarget.dataset.attachmentsDisabled)}get hideAttachmentFilename(){return fo(this.controllerTarget.dataset.hideAttachmentFilename)}get hideAttachmentFilesize(){return fo(this.controllerTarget.dataset.hideAttachmentFilesize)}get hideAttachmentUrl(){return fo(this.controllerTarget.dataset.hideAttachmentUrl)}get uploadUrl(){return`${window.location.origin}${window.Avo.configuration.root_path}/avo_api/resources/${this.resourceName}/${this.resourceId}/attachments`}connect(){this.attachmentsDisabled&&this.controllerTarget.querySelector(".trix-button-group--file-tools").remove(),window.addEventListener("trix-file-accept",t=>{if(t.target===this.editorTarget){if(this.attachmentsDisabled){t.preventDefault(),window.toastr.warning("This field has attachments disabled.");return}if(this.resourceId===""){t.preventDefault(),window.toastr.warning("You can't upload files into the Trix editor until you save the resource.");return}this.attachmentKey===""&&(t.preventDefault(),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."))}}),window.addEventListener("trix-attachment-add",t=>{t.target===this.editorTarget&&t.attachment.file&&this.uploadFileAttachment(t.attachment)})}uploadFileAttachment(t){this.uploadFile(t.file,e=>t.setUploadProgress(e),e=>t.setAttributes(e))}uploadFile(t,e,r){let n=this.createFormData(t),i=new XMLHttpRequest;i.open("POST",this.uploadUrl,!0),i.setRequestHeader("X-CSRF-Token",document.querySelector('meta[name="csrf-token"]').content),i.upload.addEventListener("progress",o=>{let a=o.loaded/o.total*100;e(a)}),i.addEventListener("load",()=>{if(i.status===200){let o;try{o=JSON.parse(i.response)}catch(s){o={}}let a={url:o.url,href:o.href};this.hideAttachmentFilename&&(a.filename=null),this.hideAttachmentFilesize&&(a.filesize=null),this.hideAttachmentUrl&&(a.href=null),r(a)}}),i.send(n)}createFormData(t){let e=new FormData;return e.append("Content-Type",t.type),e.append("file",t),e.append("filename",t.name),e.append("attachment_key",this.attachmentKey),e}};Ct(yC,"targets",["editor","controller"])});var Yfe=se(()=>{wre();_re();Mre();Ire();Lre();jre();Gne();Xne();Qne();goe();em();moe();voe();yoe();boe();xoe();woe();_oe();Soe();koe();Eoe();lse();use();cse();Ece();Ace();Tce();yfe();Cfe();Afe();Tfe();Ufe();$fe();xr.register("action",m1);xr.register("actions-picker",n0);xr.register("attachments",_1);xr.register("boolean-filter",T1);xr.register("copy-to-clipboard",rq);xr.register("dashboard-card",L1);xr.register("filter",Ca);xr.register("hidden-input",rE);xr.register("item-select-all",nE);xr.register("item-selector",iE);xr.register("loading-button",eF);xr.register("menu",aE);xr.register("mobile",sE);xr.register("modal",lE);xr.register("multiple-select-filter",uE);xr.register("per-page",cE);xr.register("resource-edit",w0);xr.register("resource-index",oF);xr.register("resource-show",aF);xr.register("search",qE);xr.register("select",FE);xr.register("select-filter",NE);xr.register("tags-field",dC);xr.register("text-filter",hC);xr.register("tippy",pC);xr.register("toggle-panel",vC);xr.register("belongs-to-field",S1);xr.register("code-field",I1);xr.register("date-field",tE);xr.register("key-value",oE);xr.register("simple-mde",fC);xr.register("trix-field",yC)});var Trt=Z(Qfe=>{var qIt=Vr(JG()),FIt=Vr(eX()),Kfe=Vr(rX()),Gfe=Vr(aL());CL();var Xfe=Vr(JX());nP();zte();Hte();Yfe();Xfe.default.start();window.Turbolinks=Vd;var bC=null;Gfe.bind("r r r",()=>{bC=document.scrollingElement.scrollTop,Vd.visit(window.location.href,{action:"replace"})});function Art(){window.navigator.userAgent.indexOf("Mac OS X")?(document.body.classList.add("os-mac"),document.body.classList.remove("os-pc")):(document.body.classList.add("os-pc"),document.body.classList.remove("os-mac"))}function rN(){$S('[data-tippy="tooltip"]',{theme:"light",content(t){let e=t.getAttribute("title");return t.removeAttribute("title"),t.removeAttribute("data-tippy"),e}})}window.initTippy=rN;Kfe.start();document.addEventListener("turbo:load",()=>{document.body.classList.remove("turbo-loading"),rN(),Art(),bC&&setTimeout(()=>{document.scrollingElement.scrollTo(0,bC),bC=0},50)});document.addEventListener("turbo:frame-load",()=>{rN()});document.addEventListener("turbo:before-fetch-response",t=>jN(Qfe,null,function*(){if(t.detail.fetchResponse.response.status===500){let{id:e,src:r}=t.target;t.target.src=`${window.Avo.configuration.root_path}/failed_to_load?turbo_frame=${e}&src=${r}`}}));document.addEventListener("turbo:visit",()=>document.body.classList.add("turbo-loading"));document.addEventListener("turbo:submit-start",()=>document.body.classList.add("turbo-loading"));document.addEventListener("turbo:submit-end",()=>document.body.classList.remove("turbo-loading"));document.addEventListener("turbo:before-cache",()=>{document.querySelectorAll("[data-turbo-remove-before-cache]").forEach(t=>t.remove())});window.Avo=window.Avo||{configuration:{}};window.Avo.menus={resetCollapsedState(){Array.from(document.querySelectorAll("[data-menu-key-param]")).map(t=>t.getAttribute("data-menu-key-param")).filter(Boolean).forEach(t=>{window.localStorage.removeItem(t)})}}});Trt();})();
416
+ }`,trixId:{get:function(){return this.hasAttribute("trix-id")?this.getAttribute("trix-id"):(this.setAttribute("trix-id",++T),this.trixId)}},labels:{get:function(){var D,M,P;return M=[],this.id&&this.ownerDocument&&M.push.apply(M,this.ownerDocument.querySelectorAll("label[for='"+this.id+"']")),(D=i(this,{matchingSelector:"label"}))&&((P=D.control)===this||P===null)&&M.push(D),M}},toolbarElement:{get:function(){var D,M,P;return this.hasAttribute("toolbar")?(M=this.ownerDocument)!=null?M.getElementById(this.getAttribute("toolbar")):void 0:this.parentNode?(P="trix-toolbar-"+this.trixId,this.setAttribute("toolbar",P),D=s("trix-toolbar",{id:P}),this.parentNode.insertBefore(D,this),D):void 0}},inputElement:{get:function(){var D,M,P;return this.hasAttribute("input")?(P=this.ownerDocument)!=null?P.getElementById(this.getAttribute("input")):void 0:this.parentNode?(M="trix-input-"+this.trixId,this.setAttribute("input",M),D=s("input",{type:"hidden",id:M}),this.parentNode.insertBefore(D,this.nextElementSibling),D):void 0}},editor:{get:function(){var D;return(D=this.editorController)!=null?D.editor:void 0}},name:{get:function(){var D;return(D=this.inputElement)!=null?D.name:void 0}},value:{get:function(){var D;return(D=this.inputElement)!=null?D.value:void 0},set:function(D){var M;return this.defaultValue=D,(M=this.editor)!=null?M.loadHTML(this.defaultValue):void 0}},notify:function(D,M){return this.editorController?u("trix-"+D,{onElement:this,attributes:M}):void 0},setInputElementValue:function(D){var M;return(M=this.inputElement)!=null?M.value=D:void 0},initialize:function(){return this.hasAttribute("data-trix-internal")?void 0:(k(this),f(this),w(this))},connect:function(){return this.hasAttribute("data-trix-internal")?void 0:(this.editorController||(u("trix-before-initialize",{onElement:this}),this.editorController=new e.EditorController({editorElement:this,html:this.defaultValue=this.value}),requestAnimationFrame(function(D){return function(){return u("trix-initialize",{onElement:D})}}(this))),this.editorController.registerSelectionManager(),this.registerResetListener(),this.registerClickListener(),p(this))},disconnect:function(){var D;return(D=this.editorController)!=null&&D.unregisterSelectionManager(),this.unregisterResetListener(),this.unregisterClickListener()},registerResetListener:function(){return this.resetListener=this.resetBubbled.bind(this),window.addEventListener("reset",this.resetListener,!1)},unregisterResetListener:function(){return window.removeEventListener("reset",this.resetListener,!1)},registerClickListener:function(){return this.clickListener=this.clickBubbled.bind(this),window.addEventListener("click",this.clickListener,!1)},unregisterClickListener:function(){return window.removeEventListener("click",this.clickListener,!1)},resetBubbled:function(D){var M;if(!D.defaultPrevented&&D.target===((M=this.inputElement)!=null?M.form:void 0))return this.reset()},clickBubbled:function(D){var M;if(!(D.defaultPrevented||this.contains(D.target)||!(M=i(D.target,{matchingSelector:"label"}))||c.call(this.labels,M)<0))return this.focus()},reset:function(){return this.value=this.defaultValue}}}())}.call(this),function(){}.call(this)}).call(this),typeof Ch=="object"&&Ch.exports?Ch.exports=e:typeof define=="function"&&define.amd&&define(e)}.call(Eh)});var ZMt,yC,$fe=se(()=>{ZMt=Vr(Vfe());Nr();Qg();yC=class extends At{get resourceId(){return this.controllerTarget.dataset.resourceId}get resourceName(){return this.controllerTarget.dataset.resourceName}get attachmentKey(){return this.controllerTarget.dataset.attachmentKey}get attachmentsDisabled(){return fo(this.controllerTarget.dataset.attachmentsDisabled)}get hideAttachmentFilename(){return fo(this.controllerTarget.dataset.hideAttachmentFilename)}get hideAttachmentFilesize(){return fo(this.controllerTarget.dataset.hideAttachmentFilesize)}get hideAttachmentUrl(){return fo(this.controllerTarget.dataset.hideAttachmentUrl)}get uploadUrl(){return`${window.location.origin}${window.Avo.configuration.root_path}/avo_api/resources/${this.resourceName}/${this.resourceId}/attachments`}connect(){this.attachmentsDisabled&&this.controllerTarget.querySelector(".trix-button-group--file-tools").remove(),window.addEventListener("trix-file-accept",t=>{if(t.target===this.editorTarget){if(this.attachmentsDisabled){t.preventDefault(),window.toastr.warning("This field has attachments disabled.");return}if(this.resourceId===""){t.preventDefault(),window.toastr.warning("You can't upload files into the Trix editor until you save the resource.");return}this.attachmentKey===""&&(t.preventDefault(),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."))}}),window.addEventListener("trix-attachment-add",t=>{t.target===this.editorTarget&&t.attachment.file&&this.uploadFileAttachment(t.attachment)})}uploadFileAttachment(t){this.uploadFile(t.file,e=>t.setUploadProgress(e),e=>t.setAttributes(e))}uploadFile(t,e,r){let n=this.createFormData(t),i=new XMLHttpRequest;i.open("POST",this.uploadUrl,!0),i.setRequestHeader("X-CSRF-Token",document.querySelector('meta[name="csrf-token"]').content),i.upload.addEventListener("progress",o=>{let a=o.loaded/o.total*100;e(a)}),i.addEventListener("load",()=>{if(i.status===200){let o;try{o=JSON.parse(i.response)}catch(s){o={}}let a={url:o.url,href:o.href};this.hideAttachmentFilename&&(a.filename=null),this.hideAttachmentFilesize&&(a.filesize=null),this.hideAttachmentUrl&&(a.href=null),r(a)}}),i.send(n)}createFormData(t){let e=new FormData;return e.append("Content-Type",t.type),e.append("file",t),e.append("filename",t.name),e.append("attachment_key",this.attachmentKey),e}};Ct(yC,"targets",["editor","controller"])});var Yfe=se(()=>{wre();_re();Mre();Ire();Lre();jre();Gne();Xne();Qne();goe();em();moe();voe();yoe();boe();xoe();woe();_oe();Soe();koe();Eoe();lse();use();cse();Ece();Ace();Tce();yfe();Cfe();Afe();Tfe();Ufe();$fe();xr.register("action",m1);xr.register("actions-picker",n0);xr.register("attachments",_1);xr.register("boolean-filter",T1);xr.register("copy-to-clipboard",rq);xr.register("dashboard-card",L1);xr.register("filter",Ca);xr.register("hidden-input",rE);xr.register("item-select-all",nE);xr.register("item-selector",iE);xr.register("loading-button",eF);xr.register("menu",aE);xr.register("mobile",sE);xr.register("modal",lE);xr.register("multiple-select-filter",uE);xr.register("per-page",cE);xr.register("resource-edit",w0);xr.register("resource-index",oF);xr.register("resource-show",aF);xr.register("search",qE);xr.register("select",FE);xr.register("select-filter",NE);xr.register("tags-field",dC);xr.register("text-filter",hC);xr.register("tippy",pC);xr.register("toggle-panel",vC);xr.register("belongs-to-field",S1);xr.register("code-field",I1);xr.register("date-field",tE);xr.register("key-value",oE);xr.register("simple-mde",fC);xr.register("trix-field",yC)});var Trt=Z(Qfe=>{var qIt=Vr(JG()),FIt=Vr(eX()),Kfe=Vr(rX()),Gfe=Vr(aL());CL();var Xfe=Vr(JX());nP();zte();Hte();Yfe();Xfe.default.start();window.Turbolinks=Vd;var bC=null;Gfe.bind("r r r",()=>{bC=document.scrollingElement.scrollTop,Vd.visit(window.location.href,{action:"replace"})});function Art(){window.navigator.userAgent.indexOf("Mac OS X")?(document.body.classList.add("os-mac"),document.body.classList.remove("os-pc")):(document.body.classList.add("os-pc"),document.body.classList.remove("os-mac"))}function rN(){$S('[data-tippy="tooltip"]',{theme:"light",content(t){let e=t.getAttribute("title");return t.removeAttribute("title"),t.removeAttribute("data-tippy"),e}})}window.initTippy=rN;Kfe.start();document.addEventListener("turbo:load",()=>{document.body.classList.remove("turbo-loading"),rN(),Art(),bC&&setTimeout(()=>{document.scrollingElement.scrollTo(0,bC),bC=0},50)});document.addEventListener("turbo:frame-load",()=>{rN()});document.addEventListener("turbo:before-fetch-response",t=>jN(Qfe,null,function*(){var e,r,n;if(t.detail.fetchResponse.response.status===500){let{id:i,src:o}=t.target;(n=(r=(e=t.detail.fetchResponse)==null?void 0:e.response)==null?void 0:r.url)!=null&&n.includes("/failed_to_load")||(t.target.src=`${window.Avo.configuration.root_path}/failed_to_load?turbo_frame=${i}&src=${o}`)}}));document.addEventListener("turbo:visit",()=>document.body.classList.add("turbo-loading"));document.addEventListener("turbo:submit-start",()=>document.body.classList.add("turbo-loading"));document.addEventListener("turbo:submit-end",()=>document.body.classList.remove("turbo-loading"));document.addEventListener("turbo:before-cache",()=>{document.querySelectorAll("[data-turbo-remove-before-cache]").forEach(t=>t.remove())});window.Avo=window.Avo||{configuration:{}};window.Avo.menus={resetCollapsedState(){Array.from(document.querySelectorAll("[data-menu-key-param]")).map(t=>t.getAttribute("data-menu-key-param")).filter(Boolean).forEach(t=>{window.localStorage.removeItem(t)})}}});Trt();})();
417
417
  /*!
418
418
  * @kurkle/color v0.1.9
419
419
  * https://github.com/kurkle/color#readme