diff --git a/app/controllers/admin/settings/exports_controller.rb b/app/controllers/admin/settings/exports_controller.rb new file mode 100644 index 000000000..e9733f109 --- /dev/null +++ b/app/controllers/admin/settings/exports_controller.rb @@ -0,0 +1,23 @@ +class Admin::Settings::ExportsController < Admin::BaseController + include ActionController::Live + + def index + end + + def create + now = Time.current.rfc3339 + filename = "all-items-#{now}.csv" + + send_file_headers!( + type: "text/csv", + disposition: "attachment", + filename: filename + ) + response.headers["Last-Modified"] = Time.now.httpdate + + exporter = ItemExporter.new(Item.all) + exporter.export(response.stream) + ensure + response.stream.close + end +end diff --git a/app/lib/item_exporter.rb b/app/lib/item_exporter.rb new file mode 100644 index 000000000..5a4145cb1 --- /dev/null +++ b/app/lib/item_exporter.rb @@ -0,0 +1,38 @@ +require "csv" + +class ItemExporter + def initialize(items) + @items = items + end + + def export(stream) + columns = %w[ + id name description size brand model serial strength power_source + other_names quantity checkout_notice status + location_area location_shelf + purchase_link purchase_price myturn_item_type url + created_at updated_at + ] + headers = [ + "complete_number", + "code", + "number", + "categories", + "item_url", + *columns + ] + stream.write(CSV.generate_line(headers)) + @items.includes(:borrow_policy, :category_nodes, :rich_text_description).in_batches(of: 100) do |items| + items.each do |item| + stream.write(CSV.generate_line([ + item.complete_number, + item.borrow_policy.code, + item.number, + item.category_nodes.map { |cn| cn.path_names.join("//") }.sort.join("; "), + "https://app.chicagotoollibrary.org/admin/items/#{item.id}", + *columns.map { |c| item.send(c) } + ])) + end + end + end +end diff --git a/app/views/admin/settings/exports/index.html.erb b/app/views/admin/settings/exports/index.html.erb new file mode 100644 index 000000000..35be55283 --- /dev/null +++ b/app/views/admin/settings/exports/index.html.erb @@ -0,0 +1,12 @@ +<%= content_for :header do %> + <%= index_header "Item Export" %> +<% end %> + +

Export all items to CSV

+ +<%= link_to "Download CSV", admin_settings_exports_path, method: :post, class: "btn btn-lg", data: {turbolinks: false} %> + +
+
+
+
diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb index a132fb137..d868ba049 100644 --- a/app/views/layouts/admin.html.erb +++ b/app/views/layouts/admin.html.erb @@ -59,8 +59,9 @@ <% if current_user.admin? %> + + <% end %> - <% if current_user.admin? %> @@ -151,6 +152,7 @@ <% if current_user.has_role?(:admin) %> + <% end %> <% if current_user.has_role?(:admin) %> diff --git a/config/routes.rb b/config/routes.rb index 1c68ea71a..2a0857549 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -139,6 +139,7 @@ get :preview, on: :member end resources :library_updates + resources :exports, only: [:index, :create] end resources :holds, only: [:index] diff --git a/lib/tasks/export.rake b/lib/tasks/export.rake index d09b835cb..1d902c80d 100644 --- a/lib/tasks/export.rake +++ b/lib/tasks/export.rake @@ -101,37 +101,6 @@ namespace :export do end end - desc "Export items to CSV" - task items_to_csv: :environment do - now = Time.current.rfc3339 - path = Rails.root + "exports" + "all-items-#{now}.csv" - puts "writing items to #{path}" - columns = %w[ - id name description size brand model serial strength - quantity checkout_notice status created_at updated_at - ] - CSV.open(path, "wb") do |csv| - csv << [ - "complete_number", - "code", - "number", - "categories", - *columns - ] - Item.includes(:borrow_policy, :category_nodes).in_batches(of: 100) do |items| - items.each do |item| - csv << [ - item.complete_number, - item.borrow_policy.code, - item.number, - item.category_nodes.map { |cn| cn.path_names.join("//") }.sort.join("; "), - *item.attributes.values_at(*columns) - ] - end - end - end - end - desc "Export seeds to CSV" task seeds_to_csv: :environment do now = Time.current.rfc3339 @@ -173,16 +142,14 @@ namespace :export do csv << [ "id", "name", - "complete_name", - "items_count" + "complete_name" ] CategoryNode.in_batches(of: 100) do |nodes| nodes.each do |node| csv << [ node.id, node.name, - node.path_names.join("//"), - node.categorizations_count + node.path_names.join("//") ] end end diff --git a/test/lib/item_exporter_test.rb b/test/lib/item_exporter_test.rb new file mode 100644 index 000000000..f0b381f12 --- /dev/null +++ b/test/lib/item_exporter_test.rb @@ -0,0 +1,18 @@ +require "test_helper" + +class ItemExporterTest < ActiveSupport::TestCase + setup do + end + + test "exports items" do + create(:item) + + exporter = ItemExporter.new(Item.all) + stream = StringIO.new + exporter.export(stream) + + stream.rewind + + assert_equal 2, stream.read.lines.size + end +end