From 1c937fea5b6990a6357d34ea30484722289ac5f9 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Tue, 4 Oct 2016 14:25:28 +0200 Subject: [PATCH] Add content exporting to TXT, CSV, and JSON --- app/controllers/export_controller.rb | 124 +++++++++++++++++++++++++++ app/helpers/export_helper.rb | 2 + app/views/export/csv.html.erb | 2 + app/views/export/html.html.erb | 2 + app/views/export/index.html.erb | 35 ++++++++ app/views/export/json.html.erb | 2 + app/views/export/outline.html.erb | 2 + app/views/export/pdf.html.erb | 2 + app/views/export/scrivener.html.erb | 2 + app/views/export/xml.html.erb | 2 + app/views/layouts/_navbar.html.erb | 2 + config/application.rb | 1 + config/routes.rb | 18 +++- 13 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 app/controllers/export_controller.rb create mode 100644 app/helpers/export_helper.rb create mode 100644 app/views/export/csv.html.erb create mode 100644 app/views/export/html.html.erb create mode 100644 app/views/export/index.html.erb create mode 100644 app/views/export/json.html.erb create mode 100644 app/views/export/outline.html.erb create mode 100644 app/views/export/pdf.html.erb create mode 100644 app/views/export/scrivener.html.erb create mode 100644 app/views/export/xml.html.erb diff --git a/app/controllers/export_controller.rb b/app/controllers/export_controller.rb new file mode 100644 index 000000000..adf00b7c2 --- /dev/null +++ b/app/controllers/export_controller.rb @@ -0,0 +1,124 @@ +class ExportController < ApplicationController + + def index + end + + # Formats + + def universes_csv + send_data to_csv(current_user.universes), filename: "universes-#{Date.today}.csv" + end + + def characters_csv + send_data to_csv(current_user.characters), filename: "characters-#{Date.today}.csv" + end + + def locations_csv + send_data to_csv(current_user.locations), filename: "locations-#{Date.today}.csv" + end + + def items_csv + send_data to_csv(current_user.items), filename: "items-#{Date.today}.csv" + end + + def outline + send_data content_to_outline, filename: "notebook-#{Date.today}.txt" + end + + def notebook_json + json_dump = current_user.content.map { |_, content| to_json(content) }.to_json + send_data json_dump, filename: "notebook-#{Date.today}.json" + end + + def pdf + end + + def html + end + + def xml + end + + def scrivener + end + + private + + def to_csv ar_relation + ar_class = ar_relation.build.class + attributes = ar_class.attribute_categories.flat_map { |k, v| v[:attributes] } + + CSV.generate(headers: true) do |csv| + csv << attributes + + ar_relation.each do |content| + csv << attributes.map do |attr| + value = content.send(attr) + + if value.is_a?(ActiveRecord::Associations::CollectionProxy) + value = value.map(&:name).to_sentence + elsif attr.end_with?('_id') && value.present? + value = Universe.find(value.to_i).name + end + + value + end + end + end + end + + def to_json ar_relation + ar_class = ar_relation.build.class + attributes = ar_class.attribute_categories.flat_map { |k, v| v[:attributes] } + + ar_relation.map do |content| + content_json = {} + + attributes.each do |attr| + value = content.send(attr) + + if value.is_a?(ActiveRecord::Associations::CollectionProxy) + value = value.map(&:name).to_sentence + elsif attr.end_with?('_id') && value.present? + value = Universe.find(value.to_i).name + end + + content_json[attr] = value + end + + content_json + end + end + + def content_to_outline + content_types = %w(universes characters locations items) + + text = "" + content_types.each do |content_type| + ar_class = current_user.send(content_type).build.class + attributes = ar_class.attribute_categories.flat_map { |k, v| v[:attributes] } + + text << "\n#{content_type.upcase}\n" + current_user.send(content_type).each do |content| + text << " #{content.name}\n" + + attributes.each do |attr| + value = content.send(attr) + next if value.nil? || value.blank? || (value.respond_to?(:empty) && value.empty?) + + if value.is_a?(ActiveRecord::Associations::CollectionProxy) + value = value.map(&:name).to_sentence + elsif attr.end_with?('_id') && value.present? + value = Universe.find(value.to_i).name + end + + text << " #{attr}: #{value.split("\n").join("\n ")}\n" + end + + text << "\n" + end + end + + text + end +end diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb new file mode 100644 index 000000000..34acf5f1a --- /dev/null +++ b/app/helpers/export_helper.rb @@ -0,0 +1,2 @@ +module ExportHelper +end diff --git a/app/views/export/csv.html.erb b/app/views/export/csv.html.erb new file mode 100644 index 000000000..b82f29024 --- /dev/null +++ b/app/views/export/csv.html.erb @@ -0,0 +1,2 @@ +

Export#csv

+

Find me in app/views/export/csv.html.erb

diff --git a/app/views/export/html.html.erb b/app/views/export/html.html.erb new file mode 100644 index 000000000..5f9f00d5b --- /dev/null +++ b/app/views/export/html.html.erb @@ -0,0 +1,2 @@ +

Export#html

+

Find me in app/views/export/html.html.erb

diff --git a/app/views/export/index.html.erb b/app/views/export/index.html.erb new file mode 100644 index 000000000..f78b2e59d --- /dev/null +++ b/app/views/export/index.html.erb @@ -0,0 +1,35 @@ +
+
+
    +
  • +

    Download your Notebook

    +
    We offer the following download formats, with more coming soon.
    +
  • +
  • + file_download +
    Outline (TXT)
    +
      +
    • <%= link_to "notebook.txt", notebook_outline_path %>
    • +
    +
  • +
  • + file_download +
    Excel (CSV)
    +
      +
    • <%= link_to "universes.csv", universes_csv_path %>
    • +
    • <%= link_to "characters.csv", characters_csv_path %>
    • +
    • <%= link_to "locations.csv", locations_csv_path %>
    • +
    • <%= link_to "items.csv", items_csv_path %>
    • +
    +
  • +
  • + file_download +
    JSON
    +
      +
    • <%= link_to "notebook.json", notebook_json_path %>
    • +
    +
  • +
+ +
+
\ No newline at end of file diff --git a/app/views/export/json.html.erb b/app/views/export/json.html.erb new file mode 100644 index 000000000..7a7b1ee63 --- /dev/null +++ b/app/views/export/json.html.erb @@ -0,0 +1,2 @@ +

Export#json

+

Find me in app/views/export/json.html.erb

diff --git a/app/views/export/outline.html.erb b/app/views/export/outline.html.erb new file mode 100644 index 000000000..5e9586d8a --- /dev/null +++ b/app/views/export/outline.html.erb @@ -0,0 +1,2 @@ +

Export#outline

+

Find me in app/views/export/outline.html.erb

diff --git a/app/views/export/pdf.html.erb b/app/views/export/pdf.html.erb new file mode 100644 index 000000000..19e3f07d3 --- /dev/null +++ b/app/views/export/pdf.html.erb @@ -0,0 +1,2 @@ +

Export#pdf

+

Find me in app/views/export/pdf.html.erb

diff --git a/app/views/export/scrivener.html.erb b/app/views/export/scrivener.html.erb new file mode 100644 index 000000000..bccdea041 --- /dev/null +++ b/app/views/export/scrivener.html.erb @@ -0,0 +1,2 @@ +

Export#scrivener

+

Find me in app/views/export/scrivener.html.erb

diff --git a/app/views/export/xml.html.erb b/app/views/export/xml.html.erb new file mode 100644 index 000000000..d70d803d7 --- /dev/null +++ b/app/views/export/xml.html.erb @@ -0,0 +1,2 @@ +

Export#xml

+

Find me in app/views/export/xml.html.erb

diff --git a/app/views/layouts/_navbar.html.erb b/app/views/layouts/_navbar.html.erb index 5c0f5ff06..4f427522d 100644 --- a/app/views/layouts/_navbar.html.erb +++ b/app/views/layouts/_navbar.html.erb @@ -6,6 +6,7 @@
  • <%= link_to 'Request a feature', 'https://docs.google.com/forms/d/e/1FAIpQLScOhSMdDqWqJu9HGPQdmd0R9s90_AcSo0g6_Nc1qNjQIbSaXA/viewform', target: '_new' %>
  • <%= link_to 'Leave feedback', 'https://docs.google.com/forms/d/e/1FAIpQLScZWEVMgm8hBWIIVj1LPzo0GqflmWUrLQlc4TAYqsaS087oAA/viewform', target: '_new' %>
  • +
  • <%= link_to 'Notebook downloads', notebook_export_path %>
  • <%= link_to 'Privacy policy', privacy_policy_path %>
  • <%= link_to "Sign out", destroy_user_session_path %>
  • @@ -24,6 +25,7 @@
  • <%= link_to 'Request a feature', 'https://docs.google.com/forms/d/e/1FAIpQLScOhSMdDqWqJu9HGPQdmd0R9s90_AcSo0g6_Nc1qNjQIbSaXA/viewform', target: '_new' %>
  • <%= link_to 'Leave feedback', 'https://docs.google.com/forms/d/e/1FAIpQLScZWEVMgm8hBWIIVj1LPzo0GqflmWUrLQlc4TAYqsaS087oAA/viewform', target: '_new' %>
  • +
  • <%= link_to 'Notebook downloads', notebook_export_path %>
  • <%= link_to 'Privacy policy', privacy_policy_path %>
  • <%= link_to "Sign out", destroy_user_session_path %>
  • diff --git a/config/application.rb b/config/application.rb index 14bcb5bea..a5a181069 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,6 +1,7 @@ require File.expand_path('../boot', __FILE__) require 'rails/all' +require 'csv' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. diff --git a/config/routes.rb b/config/routes.rb index d19234972..eab878e77 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -39,10 +39,6 @@ get '/plots', to: 'main#comingsoon' end - scope '/scene/:scene_id' do - get 'editor', to: 'write#editor' - end - scope 'admin' do get '/', to: 'admin#dashboard', as: :admin_dashboard get '/universes', to: 'admin#universes', as: :admin_universes @@ -51,6 +47,20 @@ get '/items', to: 'admin#items', as: :admin_items end + scope 'export' do + get '/', to: 'export#index', as: :notebook_export + get '/universes.csv', to: 'export#universes_csv', as: :universes_csv + get '/characters.csv', to: 'export#characters_csv', as: :characters_csv + get '/locations.csv', to: 'export#locations_csv', as: :locations_csv + get '/items.csv', to: 'export#items_csv', as: :items_csv + get '/outline', to: 'export#outline', as: :notebook_outline + get '/notebook.json', to: 'export#notebook_json', as: :notebook_json + end + + scope '/scene/:scene_id' do + get 'editor', to: 'write#editor' + end + # API Endpoints scope '/generate' do # General information