Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: actions download #2269

Merged
merged 16 commits into from Jan 8, 2024
Merged
74 changes: 37 additions & 37 deletions app/controllers/avo/actions_controller.rb
Expand Up @@ -30,7 +30,8 @@ def handle
(resource_ids.any? ? @resource.find_record(resource_ids, params: params) : [])
)

respond performed_action.response
@response = performed_action.response
respond
end

private
Expand All @@ -55,44 +56,53 @@ def action_class
end
end

def respond(response)
messages = get_messages response
return keep_modal_open(messages) if response[:keep_modal_open]

response[:type] ||= :reload

if response[:type] == :download
return send_data response[:path], filename: response[:filename]
end
def respond
Paul-Bob marked this conversation as resolved.
Show resolved Hide resolved
# Flash the messages collected from the action
flash_messages

respond_to do |format|
format.turbo_stream do
# Flash the messages collected from the action
flash_messages messages

if response[:type] == :redirect
render turbo_stream: turbo_stream.redirect_to(
Avo::ExecutionContext.new(target: response[:path]).handle,
nil,
response[:redirect_args][:turbo_frame],
**response[:redirect_args].except(:turbo_frame)
)
else
redirect_back fallback_location: resources_path(resource: @resource)
case @response[:type]
# Only render the flash messages if the action keeps the modal open
when :keep_modal_open
turbo_stream.flash_alerts

# Trigger download, removes modal and flash the messages
when :download
render turbo_stream: [
turbo_stream.download(content: @response[:path], filename: @response[:filename]),
turbo_stream.remove("actions_show"),
turbo_stream.flash_alerts
]

# Turbo redirect to the path
when :redirect
render turbo_stream: turbo_stream.redirect_to(
Avo::ExecutionContext.new(
target: @response[:path]
).handle,
nil,
@response[:redirect_args][:turbo_frame],
**@response[:redirect_args].except(:turbo_frame)
)

# Reload the page
else
redirect_back fallback_location: resources_path(resource: @resource)
end
end
end
end

def get_messages(response)
def get_messages
default_message = {
type: :info,
body: I18n.t("avo.action_ran_successfully")
}

return [default_message] if response[:messages].blank?
return [default_message] if @response[:messages].blank?

response[:messages].select do |message|
@response[:messages].select do |message|
# Remove the silent placeholder messages
message[:type] != :silent
end
Expand All @@ -114,22 +124,12 @@ def decrypted_arguments
)
end

def flash_messages(messages)
messages.each do |message|
def flash_messages
get_messages.each do |message|
flash[message[:type]] = message[:body]
end
end

def keep_modal_open(messages)
flash_messages messages

respond_to do |format|
format.turbo_stream do
render partial: "avo/partials/flash_alerts"
end
end
end

def verify_authorization
raise Avo::NotAuthorizedError.new unless @action.authorized?
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/avo/base_controller.rb
Expand Up @@ -515,7 +515,7 @@ def destroy_fail_action
flash[:error] = destroy_fail_message

respond_to do |format|
format.turbo_stream { render partial: "avo/partials/flash_alerts" }
format.turbo_stream { turbo_stream.flash_alerts }
end
end

Expand Down
15 changes: 15 additions & 0 deletions app/helpers/avo/turbo_stream_actions_helper.rb
@@ -0,0 +1,15 @@
module Avo
module TurboStreamActionsHelper
def download(content:, filename:)
turbo_stream_action_tag :download, content: content, filename: filename
end

def flash_alerts
turbo_stream_action_tag :append, target: "alerts" do
render Avo::FlashAlertsComponent.new flashes: flash.discard
end
end
end
end

Turbo::Streams::TagBuilder.prepend(Avo::TurboStreamActionsHelper)
2 changes: 0 additions & 2 deletions app/javascript/js/controllers.js
Expand Up @@ -19,7 +19,6 @@ import ItemSelectorController from './controllers/item_selector_controller'
import KeyValueController from './controllers/fields/key_value_controller'
import LoadingButtonController from './controllers/loading_button_controller'
import MenuController from './controllers/menu_controller'
import ModalController from './controllers/modal_controller'
import MultipleSelectFilterController from './controllers/multiple_select_filter_controller'
import PerPageController from './controllers/per_page_controller'
import PreviewController from './controllers/preview_controller'
Expand Down Expand Up @@ -53,7 +52,6 @@ application.register('item-select-all', ItemSelectAllController)
application.register('item-selector', ItemSelectorController)
application.register('loading-button', LoadingButtonController)
application.register('menu', MenuController)
application.register('modal', ModalController)
application.register('multiple-select-filter', MultipleSelectFilterController)
application.register('per-page', PerPageController)
application.register('preview', PreviewController)
Expand Down
9 changes: 0 additions & 9 deletions app/javascript/js/controllers/modal_controller.js
Expand Up @@ -8,13 +8,4 @@ export default class extends Controller {

document.dispatchEvent(new Event('actions-modal:close'))
}

delayedClose() {
const vm = this

setTimeout(() => {
vm.modalTarget.remove()
document.dispatchEvent(new Event('actions-modal:close'))
}, 500)
}
}
11 changes: 11 additions & 0 deletions app/javascript/js/custom-stream-actions.js
@@ -1,5 +1,6 @@
/* eslint-disable camelcase */
import { StreamActions } from '@hotwired/turbo'
import { saveAs } from 'file-saver'

// TODO: move these to the avo_filters gem

Expand All @@ -13,3 +14,13 @@ StreamActions.open_filter = function () {
document.querySelector(`[data-filter-id="${id}"] .pill`).click()
}, 150)
}
// END TODO: move these to the avo_filters gem

StreamActions.download = function () {
Paul-Bob marked this conversation as resolved.
Show resolved Hide resolved
saveAs(
new Blob(
[this.getAttribute('content')],
),
this.getAttribute('filename'),
)
}
2 changes: 1 addition & 1 deletion app/views/avo/actions/show.html.erb
Expand Up @@ -49,7 +49,7 @@
size: :sm,
data: {
target: :submit_action,
**@action.class.submit_button_data_attributes
action_target: "submit"
} do %>
<%= @action.confirm_button_label %>
<% end %>
Expand Down
3 changes: 0 additions & 3 deletions app/views/avo/partials/_flash_alerts.turbo_stream.erb

This file was deleted.

29 changes: 10 additions & 19 deletions lib/avo/base_action.rb
Expand Up @@ -10,7 +10,7 @@ class BaseAction
class_attribute :no_confirmation, default: false
class_attribute :standalone, default: false
class_attribute :visible
class_attribute :may_download_file, default: false
class_attribute :may_download_file
class_attribute :turbo
class_attribute :authorize, default: true

Expand All @@ -36,23 +36,10 @@ class << self
delegate :context, to: ::Avo::Current

def form_data_attributes
# We can't respond with a file download from Turbo se we disable it on the form
if may_download_file
{turbo: turbo || false, remote: false}
else
{turbo: turbo, turbo_frame: :_top}.compact
end
end

# We can't respond with a file download from Turbo se we disable close the modal manually after a while (it's a hack, we know)
def submit_button_data_attributes
attributes = { action_target: "submit" }

if may_download_file
attributes[:action] = "click->modal#delayedClose"
end

attributes
{
turbo: turbo,
turbo_frame: :_top
}.compact
end

def to_param
Expand Down Expand Up @@ -99,6 +86,10 @@ def initialize(record: nil, resource: nil, user: nil, view: nil, arguments: {})

@response ||= {}
@response[:messages] = []

if self.may_download_file.present?
puts "[Avo->] WARNING! Since version 3.2.2 'may_download_file' is unecessary and deprecated on actions. Can be safely removed from #{self.class.name}"
end
end

# Blank method
Expand Down Expand Up @@ -193,7 +184,7 @@ def warn(text)
end

def keep_modal_open
response[:keep_modal_open] = true
response[:type] = :keep_modal_open

self
end
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -41,6 +41,7 @@
"eslint-config-airbnb": "^19.0.4",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-sort-imports-es6-autofix": "^0.6.0",
"file-saver": "^2.0.5",
"flatpickr": "^4.6.13",
"heroicons": "^2.1.1",
"js-cookie": "^3.0.5",
Expand Down
1 change: 0 additions & 1 deletion spec/dummy/app/avo/actions/download_file.rb
@@ -1,7 +1,6 @@
class Avo::Actions::DownloadFile < Avo::BaseAction
self.name = "Download file"
self.standalone = true
self.may_download_file = true

# TODO: fix fields for actions
def fields
Expand Down
1 change: 0 additions & 1 deletion spec/dummy/app/avo/actions/export_csv.rb
@@ -1,7 +1,6 @@
class Avo::Actions::ExportCsv < Avo::BaseAction
self.name = "Export csv"
self.no_confirmation = false
self.may_download_file = true

def handle(**args)
records, resource = args.values_at(:records, :resource)
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Expand Up @@ -2636,6 +2636,11 @@ file-entry-cache@^6.0.1:
dependencies:
flat-cache "^3.0.4"

file-saver@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38"
integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==

fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
Expand Down