diff --git a/app/controllers/admin/api_controller.rb b/app/controllers/admin/api_controller.rb index a1021c316..e3cc75e91 100644 --- a/app/controllers/admin/api_controller.rb +++ b/app/controllers/admin/api_controller.rb @@ -345,48 +345,6 @@ class ApiController < ApplicationController config.autocomplete_path = 'suggest' end - # Admin CSV stream of Database data - def tableau_export - headers.delete("Content-Length") - headers["Cache-Control"] = "no-cache" - headers["Content-Type"] = "text/csv" - headers["Content-Disposition"] = "attachment; filename=\"geoportal_tableau_export.csv\"" - headers["X-Accel-Buffering"] = "no" - response.status = 200 - self.response_body = csv_enumerator - end - - def csv_enumerator - @csv_enumerator ||= Enumerator.new do |yielder| - yielder << CSV.generate_line([ - "Title", - "Provider", - "Resource Class", - "Resource Type", - "Index Year", - "Spatial Coverage", - "B1G Image", - "ID", - "Download", - "Language" - ]) - Document.find_each do |row| - yielder << CSV.generate_line([ - row.title, - row.schema_provider_s, - row.gbl_resourceClass_sm&.join("|"), - row.gbl_resourceType_sm&.join("|"), - row.gbl_indexYear_im&.join("|"), - row.dct_spatial_sm&.join("|"), - row.b1g_image_ss, - row.geomg_id_s, - row.dct_references_s.find { |ref| ref.category == "download" }&.value, - row.dct_language_sm&.join("|") - ]) - end - end - end - # Administrative view of document # - Sidecar Image # - URIs @@ -425,5 +383,11 @@ def advanced_search_facets end end end + + # Tableau Export + def tableau_export + ExportTableauJob.perform_later(current_user) + head :no_content + end end end diff --git a/app/jobs/export_tableau_job.rb b/app/jobs/export_tableau_job.rb new file mode 100644 index 000000000..168df1f42 --- /dev/null +++ b/app/jobs/export_tableau_job.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require "csv" + +# ExportTableauJob +class ExportTableauJob < ApplicationJob + queue_as :priority + + def perform(current_user) + logger.debug("\n\n Background Job: ♞") + logger.debug("User: #{current_user.inspect}") + logger.debug("Export Service: Tableau Export") + logger.debug("\n\n") + + # Test broadcast + ActionCable.server.broadcast("export_channel", {data: "Hello from Export Tableau Job!"}) + + # Send progress + file_content = ExportTableauService.call + + # Write into tempfile + @tempfile = Tempfile.new(["export-#{Time.zone.today}", ".csv"]).tap do |file| + CSV.open(file, "wb") do |csv| + file_content.each do |row| + csv << row + end + end + end + + # Create notification + # Message: "Download Type|Row Count|Button Label" + notification = ExportNotification.with(message: "CSV (Tableau)|#{ActionController::Base.helpers.number_with_delimiter(file_content.size - 1)} rows|CSV") + + # Deliver notification + notification.deliver(current_user) + + # Attach CSV file (can only attach after persisted) + notification.record.file.attach(io: @tempfile, filename: "geomg-export-#{Time.zone.today}.csv", + content_type: "text/csv") + + # Update UI + ActionCable.server.broadcast("export_channel", { + data: "Notification ready!", + actions: [ + { + method: "RefreshNotifications", + payload: current_user.notifications.unread.count + } + ] + }) + end +end diff --git a/app/services/export_tableau_service.rb b/app/services/export_tableau_service.rb new file mode 100644 index 000000000..6cce043e9 --- /dev/null +++ b/app/services/export_tableau_service.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +# ExportTableauService +class ExportTableauService + def self.call + ActionCable.server.broadcast("export_channel", {progress: 0}) + + total = Document.count + count = 0 + slice_count = 1000 + csv_file = [] + + Rails.logger.debug { "\n\nExportTableauService: #{total}\n\n" } + + csv_file << [ + "Title", + "Provider", + "Resource Class", + "Resource Type", + "Index Year", + "Spatial Coverage", + "B1G Image", + "ID", + "Download", + "Language" + ] + + Document.in_batches do |slice| + # Broadcast progress percentage + count += slice_count + progress = ((count.to_f / total) * 100).round + progress = 100 if progress > 100 + + slice.each do |row| + csv_file << [ + row.title, + row.schema_provider_s, + row.gbl_resourceClass_sm&.join("|"), + row.gbl_resourceType_sm&.join("|"), + row.gbl_indexYear_im&.join("|"), + row.dct_spatial_sm&.join("|"), + row.b1g_image_ss, + row.geomg_id_s, + row.dct_references_s.find { |ref| ref.category == "download" }&.value, + row.dct_language_sm&.join("|") + ] + end + + ActionCable.server.broadcast("export_channel", {progress: progress}) + end + + csv_file + end +end