From 37d221bbf90a5bda0b6e18d18be5e53888f54e7b Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Sun, 19 Jan 2025 13:51:16 +0200 Subject: [PATCH] wip --- Gemfile.lock | 8 ++-- .../discreet_information_component.html.erb | 2 +- .../avo/discreet_information_component.rb | 2 + .../avo/turbo_stream_actions_helper.rb | 4 ++ app/javascript/avo.base.js | 2 +- app/javascript/js/custom-stream-actions.js | 5 +++ app/views/avo/actions/show.html.erb | 2 +- lib/avo/base_action.rb | 20 ++++++++-- lib/avo/discreet_information.rb | 19 ++++++--- .../dummy/app/avo/actions/toggle_published.rb | 1 + spec/dummy/app/avo/resources/post.rb | 13 +++++- spec/dummy/app/avo/resources/product.rb | 4 -- yarn.lock | 40 ++++++++++++++----- 13 files changed, 91 insertions(+), 31 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8a0fa2569f..e2f1983218 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -178,7 +178,7 @@ GEM logger (~> 1.5) coercible (1.0.0) descendants_tracker (~> 0.0.1) - concurrent-ruby (1.3.4) + concurrent-ruby (1.3.5) connection_pool (2.5.0) countries (7.1.0) unaccent (~> 0.3) @@ -370,7 +370,7 @@ GEM listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - logger (1.6.4) + logger (1.6.5) loofah (2.24.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -431,7 +431,7 @@ GEM prettier_print (1.2.1) prop_initializer (0.2.0) zeitwerk (>= 2.6.18) - psych (5.2.2) + psych (5.2.3) date stringio public_suffix (6.0.1) @@ -492,7 +492,7 @@ GEM rb-inotify (0.11.1) ffi (~> 1.0) rbs (2.8.4) - rdoc (6.10.0) + rdoc (6.11.0) psych (>= 4.0.0) redis (5.3.0) redis-client (>= 0.22.0) diff --git a/app/components/avo/discreet_information_component.html.erb b/app/components/avo/discreet_information_component.html.erb index a0f0ff638f..a584da6c09 100644 --- a/app/components/avo/discreet_information_component.html.erb +++ b/app/components/avo/discreet_information_component.html.erb @@ -1,6 +1,6 @@
<% items.each do |item| %> - <%= content_tag element_tag(item), **element_attributes(item), class: "flex gap-1 text-xs font-normal text-gray-600 hover:text-gray-900", title: item.tooltip, data: {tippy: :tooltip} do %> + <%= content_tag element_tag(item), **element_attributes(item), class: "flex gap-1 text-xs font-normal text-gray-600 hover:text-gray-900", title: item.tooltip, data: {tippy: :tooltip, **data(item)} do %> <%= item.label if item.label.present? %> <%= helpers.svg item.icon, class: "text-2xl h-4" %> <% end %> <% end %> diff --git a/app/components/avo/discreet_information_component.rb b/app/components/avo/discreet_information_component.rb index 9429ef8624..b356c22d51 100644 --- a/app/components/avo/discreet_information_component.rb +++ b/app/components/avo/discreet_information_component.rb @@ -22,4 +22,6 @@ def element_attributes(item) {} end end + + def data(item) = item.data || {} end diff --git a/app/helpers/avo/turbo_stream_actions_helper.rb b/app/helpers/avo/turbo_stream_actions_helper.rb index a274f02dcb..c888e35303 100644 --- a/app/helpers/avo/turbo_stream_actions_helper.rb +++ b/app/helpers/avo/turbo_stream_actions_helper.rb @@ -15,6 +15,10 @@ def avo_close_modal target: Avo::MODAL_FRAME_ID, template: @view_context.turbo_frame_tag(Avo::MODAL_FRAME_ID) end + + def avo_turbo_reload + turbo_stream_action_tag :turbo_reload + end end end diff --git a/app/javascript/avo.base.js b/app/javascript/avo.base.js index fda5eca80e..127aa9112c 100644 --- a/app/javascript/avo.base.js +++ b/app/javascript/avo.base.js @@ -25,7 +25,7 @@ Mousetrap.bind('r r r', () => { // Cpture scroll position scrollTop = document.scrollingElement.scrollTop - Turbo.visit(window.location.href, { action: 'replace' }) + window.StreamActions.turbo_reload() }) function isMac() { diff --git a/app/javascript/js/custom-stream-actions.js b/app/javascript/js/custom-stream-actions.js index 205f5b965b..bab75873dd 100644 --- a/app/javascript/js/custom-stream-actions.js +++ b/app/javascript/js/custom-stream-actions.js @@ -8,6 +8,11 @@ StreamActions.close_filters_dropdown = function () { document.querySelector('.filters-dropdown-selector').classList.add('hidden') } +// Uses Turbo to refresh the page +StreamActions.turbo_reload = function () { + window.Turbo.visit(window.location.href, { action: 'replace' }) +} + StreamActions.open_filter = function () { const id = this.getAttribute('unique-id') setTimeout(() => { diff --git a/app/views/avo/actions/show.html.erb b/app/views/avo/actions/show.html.erb index c56ce68fa3..9f8ef5ca61 100644 --- a/app/views/avo/actions/show.html.erb +++ b/app/views/avo/actions/show.html.erb @@ -5,7 +5,7 @@ <%= turbo_frame_tag Avo::MODAL_FRAME_ID do %>
" - data-action-no-confirmation-value="<%= @action.no_confirmation %>" + data-action-no-confirmation-value="<%= @action.no_confirmation? %>" data-action-resource-name-value="<%= @resource.model_key %>" data-resource-id="<%= params[:id] %>" class="hidden text-slate-800" diff --git a/lib/avo/base_action.rb b/lib/avo/base_action.rb index 53641a6b8b..3b31de11bd 100644 --- a/lib/avo/base_action.rb +++ b/lib/avo/base_action.rb @@ -4,6 +4,8 @@ class BaseAction include Avo::Concerns::HasActionStimulusControllers include Avo::Concerns::Hydration + DATA_ATTRIBUTES = {turbo_frame: Avo::MODAL_FRAME_ID} + class_attribute :name, default: nil class_attribute :message class_attribute :confirm_button_label @@ -52,8 +54,8 @@ def to_param to_s end - def link_arguments(resource:, arguments: {}, **args) - path = Avo::Services::URIService.parse(resource.record&.persisted? ? resource.record_path : resource.records_path) + def path(resource:, arguments: {}, **args) + Avo::Services::URIService.parse(resource.record&.persisted? ? resource.record_path : resource.records_path) .append_paths("actions") .append_query( **{ @@ -63,8 +65,10 @@ def link_arguments(resource:, arguments: {}, **args) }.compact ) .to_s + end - [path, {turbo_frame: Avo::MODAL_FRAME_ID}] + def link_arguments(resource:, arguments: {}, **args) + [path(resource:, arguments:, **args), DATA_ATTRIBUTES] end # Encrypt the arguments so we can pass sensible data as a query param. @@ -365,6 +369,16 @@ def disabled? !enabled? end + def no_confirmation? + Avo::ExecutionContext.new( + target: no_confirmation, + action: self, + resource: @resource, + view: @view, + arguments: + ).handle + end + private def add_message(body, type = :info) diff --git a/lib/avo/discreet_information.rb b/lib/avo/discreet_information.rb index 4269d35999..3e56f7f3d4 100644 --- a/lib/avo/discreet_information.rb +++ b/lib/avo/discreet_information.rb @@ -42,14 +42,21 @@ def timestamp_item(item) def parse_payload(item) return unless item.is_a?(Hash) + args = { + record:, + resource:, + view: + } + DiscreetInformationItem.new( - tooltip: Avo::ExecutionContext.new(target: item[:tooltip], record: record, resource: self, view: view).handle, - icon: Avo::ExecutionContext.new(target: item[:icon], record: record, resource: self, view: view).handle, - url: Avo::ExecutionContext.new(target: item[:url], record: record, resource: self, view: view).handle, - url_target: Avo::ExecutionContext.new(target: item[:url_target], record: record, resource: self, view: view).handle, - label: Avo::ExecutionContext.new(target: item[:label], record: record, resource: self, view: view).handle + tooltip: Avo::ExecutionContext.new(target: item[:tooltip], **args).handle, + icon: Avo::ExecutionContext.new(target: item[:icon], **args).handle, + url: Avo::ExecutionContext.new(target: item[:url], **args).handle, + url_target: Avo::ExecutionContext.new(target: item[:url_target], **args).handle, + data: Avo::ExecutionContext.new(target: item[:data], **args).handle, + label: Avo::ExecutionContext.new(target: item[:label], **args).handle ) end - DiscreetInformationItem = Struct.new(:tooltip, :icon, :url, :url_target, :label, keyword_init: true) unless defined?(DiscreetInformationItem) + DiscreetInformationItem = Struct.new(:tooltip, :icon, :url, :url_target, :data, :label, keyword_init: true) unless defined?(DiscreetInformationItem) end diff --git a/spec/dummy/app/avo/actions/toggle_published.rb b/spec/dummy/app/avo/actions/toggle_published.rb index 03e4d98026..9f0b136bf9 100644 --- a/spec/dummy/app/avo/actions/toggle_published.rb +++ b/spec/dummy/app/avo/actions/toggle_published.rb @@ -3,6 +3,7 @@ class Avo::Actions::TogglePublished < Avo::BaseAction self.message = "Are you sure, sure?" self.confirm_button_label = "Toggle" self.cancel_button_label = "Don't toggle yet" + self.no_confirmation = -> { arguments[:no_confirmation] || false } def fields field :notify_user, as: :boolean, default: true diff --git a/spec/dummy/app/avo/resources/post.rb b/spec/dummy/app/avo/resources/post.rb index b307c91f83..a84b25c998 100644 --- a/spec/dummy/app/avo/resources/post.rb +++ b/spec/dummy/app/avo/resources/post.rb @@ -41,8 +41,17 @@ class Avo::Resources::Post < Avo::BaseResource }, { label: -> { record.published_at ? "✅" : "🙄" }, - url: -> { "https://avohq.io" }, - url_target: :_blank + tooltip: -> { "Post is #{record.published_at ? "published" : "draft"}. Click to toggle." }, + url: -> { + Avo::Actions::TogglePublished.path( + resource: resource, + arguments: { + records: Array.wrap(record.id), + no_confirmation: true + } + ) + }, + data: Avo::BaseAction::DATA_ATTRIBUTES, } ] diff --git a/spec/dummy/app/avo/resources/product.rb b/spec/dummy/app/avo/resources/product.rb index 88b0f68fd7..92e60daeec 100644 --- a/spec/dummy/app/avo/resources/product.rb +++ b/spec/dummy/app/avo/resources/product.rb @@ -35,10 +35,6 @@ class Avo::Resources::Product < Avo::BaseResource }, :timestamps ] - # self.discreet_information = { - # tooltip: -> { sanitize("Product is #{record.status}", tags: %w[strong]) }, - # icon: "heroicons/outline/bold" - # } self.profile_photo = { source: -> { record.image.attached? ? main_app.url_for(record.image.variant(resize_to_fill: [300, 300])) : nil } } diff --git a/yarn.lock b/yarn.lock index 8aaff3b01b..76ca2c8fbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1504,9 +1504,9 @@ prettier ">=2.3.0" "@rails/actioncable@^7.0": - version "7.0.4" - resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-7.0.4.tgz#70a3ca56809f7aaabb80af2f9c01ae51e1a8ed41" - integrity sha512-tz4oM+Zn9CYsvtyicsa/AwzKZKL+ITHWkhiu7x+xF77clh2b4Rm+s6xnOgY/sGDWoFWZmtKsE95hxBPkgQQNnQ== + version "7.2.201" + resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-7.2.201.tgz#bfb3da01b3e2462f5a18f372c52dedd7de76037f" + integrity sha512-wsTdWoZ5EfG5k3t7ORdyQF0ZmDEgN4aVPCanHAiNEwCROqibSZMXXmCbH7IDJUVri4FOeAVwwbPINI7HVHPKBw== "@rails/activestorage@^6.1.710": version "6.1.710" @@ -5103,8 +5103,16 @@ stimulus-use@^0.50.0: dependencies: hotkeys-js ">=3" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0: - name string-width-cjs +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5204,8 +5212,14 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - name strip-ansi-cjs +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -5605,8 +5619,16 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - name wrap-ansi-cjs +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==