From ede744849b077024d5776a4fb9218936bca01a3c Mon Sep 17 00:00:00 2001 From: rekonder Date: Tue, 6 Jun 2017 16:12:34 +0200 Subject: [PATCH] Export repository [aj-SCI-1275] --- Gemfile.lock | 6 +- .../repositories/repository_datatable.js | 74 ++++++++++++++++++ app/controllers/repositories_controller.rb | 76 ++++++++++++++++++- app/models/zip_export.rb | 3 +- .../_export_repository_modal.html.erb | 21 +++++ app/views/repositories/_repository.html.erb | 15 ++++ config/locales/en.yml | 6 +- config/routes.rb | 1 + 8 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 app/views/repositories/_export_repository_modal.html.erb diff --git a/Gemfile.lock b/Gemfile.lock index f0a7e09df..40a51e8f3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,8 +1,8 @@ GIT - remote: git://github.com/einzige/sneaky-save.git - revision: 03866e838f62a4b13e15784974fcc13e14cd9502 + remote: https://github.com/einzige/sneaky-save + revision: e7c77674abe74d598dfd58db7c680dd85936f207 specs: - sneaky-save (0.1.1) + sneaky-save (0.1.2) activerecord (>= 3.2.0) GEM diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index 042d8b83b..e33823dae 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -214,6 +214,54 @@ setTimeout(function() { // Enables noSearchHidden plugin $.fn.dataTable.defaults.noSearchHidden = true; +$('form#form-export').submit(function(e) { + var form = this; + + if (currentMode === 'viewMode') { + // Remove all hidden fields + $('#form-export').find('input[name=row_ids\\[\\]]').remove(); + $('#form-export').find('input[name=header_ids\\[\\]]').remove(); + + // Append samples + appendSamplesIdToForm(form); + + // Append visible column information + $('table#repository-table thead tr').children('th').each(function(i) { + var th = $(this); + var val; + if ($(th).attr('id') === 'checkbox' || $(th).attr('id') === 'assigned') + val = -1 + else if ($(th).attr('id') === 'row-name') + val = -2; + else if ($(th).attr('id') === 'added-by') + val = -3; + else if ($(th).attr('id') === 'added-on') + val = -4; + else + val = th.attr('id'); + + if (val) + $(form).append( + $('') + .attr('type', 'hidden') + .attr('name', 'header_ids[]') + .val(val) + ); + }); + } +}); + +function appendSamplesIdToForm(form) { + $.each(rowsSelected, function(index, rowId) { + $(form).append( + $('') + .attr('type', 'hidden') + .attr('name', 'row_ids[]') + .val(rowId) + ); + }); +} + function initRowSelection() { // Handle clicks on checkbox $('.dt-body-center .repository-row-selector').change(function(e) { @@ -642,6 +690,16 @@ function updateButtons() { $('#editRepositoryRecord').removeClass('disabled'); $('#deleteRepositoryRecordsButton').prop('disabled', false); $('#deleteRepositoryRecordsButton').removeClass('disabled'); + $('#exportRepositoriesButton').removeClass('disabled'); + $('#exportRepositoriesButton').prop('disabled', false); + $('#exportRepositoriesButton').on('click', function() { + $('#exportRepositoryModal') + .modal('show') + }); + $('#export-repositories').on('click', function() { + animateSpinner(null, true); + $('#form-export').submit(); + }); $('#assignRepositoryRecords').removeClass('disabled'); $('#assignRepositoryRecords').prop('disabled', false); $('#unassignRepositoryRecords').removeClass('disabled'); @@ -651,6 +709,10 @@ function updateButtons() { $('#editRepositoryRecord').addClass('disabled'); $('#deleteRepositoryRecordsButton').prop('disabled', true); $('#deleteRepositoryRecordsButton').addClass('disabled'); + $('#exportRepositoriesButton').addClass('disabled'); + $('#exportRepositoriesButton').prop('disabled', true); + $('#exportRepositoriesButton').off('click'); + $('#export-repositories').off('click'); $('#assignRepositoryRecords').addClass('disabled'); $('#assignRepositoryRecords').prop('disabled', true); $('#unassignRepositoryRecords').addClass('disabled'); @@ -660,6 +722,16 @@ function updateButtons() { $('#editRepositoryRecord').addClass('disabled'); $('#deleteRepositoryRecordsButton').prop('disabled', false); $('#deleteRepositoryRecordsButton').removeClass('disabled'); + $('#exportRepositoriesButton').removeClass('disabled'); + $('#exportRepositoriesButton').prop('disabled', false); + $('#exportRepositoriesButton').on('click', function() { + $('#exportRepositoryModal') + .modal('show') + }); + $('#export-repositories').on('click', function() { + animateSpinner(null, true); + $('#form-export').submit(); + }); $('#assignRepositoryRecords').removeClass('disabled'); $('#assignRepositoryRecords').prop('disabled', false); $('#unassignRepositoryRecords').removeClass('disabled'); @@ -674,6 +746,8 @@ function updateButtons() { $('#addNewColumn').prop('disabled', true); $('#deleteRepositoryRecordsButton').addClass('disabled'); $('#deleteRepositoryRecordsButton').prop('disabled', true); + $('#exportRepositoriesButton').addClass('disabled'); + $('#exportRepositoriesButton').off('click'); $('#assignRepositoryRecords').addClass('disabled'); $('#assignRepositoryRecords').prop('disabled', true); $('#unassignRepositoryRecords').addClass('disabled'); diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index b1724734b..c8f9b55c0 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -1,5 +1,5 @@ class RepositoriesController < ApplicationController - before_action :load_vars, except: :repository_table_index + before_action :load_vars, except: [:repository_table_index, :export_repository] before_action :check_view_all_permissions, only: :index before_action :check_edit_and_destroy_permissions, only: %(destroy destroy_modal rename_modal update) @@ -7,6 +7,7 @@ class RepositoriesController < ApplicationController %(copy_modal copy) before_action :check_create_permissions, only: %(create_new_modal create) + before_action :generate_zip, only: :export_repository def index render('repositories/index') @@ -185,6 +186,15 @@ class RepositoriesController < ApplicationController end end + def export_repository + if params[:row_ids] && params[:header_ids] + generate_zip + else + flash[:alert] = t('zip_export.export_error') + end + redirect_to :back + end + private def load_vars @@ -212,4 +222,68 @@ class RepositoriesController < ApplicationController def repository_params params.require(:repository).permit(:name) end + + def generate_zip + zip = ZipExport.create(user: current_user) + zip.generate_exportable_zip( + current_user, + to_csv(RepositoryRow.where(id: params[:row_ids]), params[:header_ids]), + :repositories + ) + end + + def to_csv(rows, headers) + require 'csv' + + # Parse headers (magic numbers should be refactored - see + # sample-datatable.js) + header_names = [] + headers.each do |header| + if header == '-1' + next + elsif header == '-2' + header_names << I18n.t('repositories.table.row_name') + elsif header == '-3' + header_names << I18n.t('repositories.table.added_by') + elsif header == '-4' + header_names << I18n.t('repositories.table.added_on') + else + rc = RepositoryColumn.find_by_id(header) + if rc + header_names << rc.name + else + header_names << nil + end + end + end + + CSV.generate do |csv| + csv << header_names + rows.each do |row| + sample_row = [] + row_record = RepositoryRow.where(repository_rows: { id: row }) + headers.each do |header| + if header == '-1' + next + elsif header == '-2' + sample_row << row.name + elsif header == '-3' + sample_row << row.created_by.full_name + elsif header == '-4' + sample_row << I18n.l(row.created_at, format: :full) + else + record = row_record.joins(:repository_columns, :repository_cells) + .where(repository_columns: { id: header }) + .take + if record + sample_row << record.repository_cells.take.value.data + else + sample_row << nil + end + end + end + csv << sample_row + end + end + end end diff --git a/app/models/zip_export.rb b/app/models/zip_export.rb index 38e92d44e..117f9817d 100644 --- a/app/models/zip_export.rb +++ b/app/models/zip_export.rb @@ -102,8 +102,7 @@ class ZipExport < ActiveRecord::Base end end - # generates zip export file for samples - def generate_samples_zip(tmp_dir, data, options = {}) + def generate_repositories_zip(tmp_dir, data, options = {}) file = FileUtils.touch("#{tmp_dir}/export.csv").first File.open(file, 'wb') { |f| f.write(data) } end diff --git a/app/views/repositories/_export_repository_modal.html.erb b/app/views/repositories/_export_repository_modal.html.erb new file mode 100644 index 000000000..f49935e22 --- /dev/null +++ b/app/views/repositories/_export_repository_modal.html.erb @@ -0,0 +1,21 @@ + diff --git a/app/views/repositories/_repository.html.erb b/app/views/repositories/_repository.html.erb index 3d26baaf2..bf4bd9b81 100644 --- a/app/views/repositories/_repository.html.erb +++ b/app/views/repositories/_repository.html.erb @@ -1,8 +1,16 @@ <%= render partial: "repositories/delete_record_modal.html.erb" %> <%= render partial: "repositories/delete_column_modal.html.erb" %> +<%= render partial: 'repositories/export_repository_modal.html.erb', + locals: { repository: repository } %>
+<% if can_view_repository(repository) %> + <%= bootstrap_form_tag(url: export_repository_team_path(repository), + html: { id: 'form-export', class: 'hidden' }) do |f| %> + <% end %> +<% end %> +
<% if can_create_repository_records(repository) %> @@ -12,6 +20,13 @@ <% end %> + <% if can_view_repository(repository) %> + + + + + <% end %> +