mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-12-26 17:51:13 +08:00
Add export project modal
Closes [SCI-2645]
This commit is contained in:
parent
b9bb0db62d
commit
26df1e5a98
12 changed files with 204 additions and 31 deletions
|
@ -27,6 +27,10 @@
|
|||
var projectActionsModalBody = null;
|
||||
var projectActionsModalFooter = null;
|
||||
|
||||
var exportProjectsModal = null;
|
||||
var exportProjectsModalHeader = null;
|
||||
var exportProjectsModalBody = null;
|
||||
|
||||
var projectsViewMode = 'cards';
|
||||
var projectsViewFilter = $('.projects-view-filter.active').data('filter');
|
||||
var projectsViewFilterChanged = false;
|
||||
|
@ -210,6 +214,44 @@
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the JS for export projects modal to work.
|
||||
*/
|
||||
function initExportProjectsModal() {
|
||||
$exportProjectsBtn = $('#export-projects-button')
|
||||
$exportProjectsBtn.click(function() {
|
||||
|
||||
// Load HTML to refresh users list
|
||||
$.ajax({
|
||||
url: $exportProjectsBtn.data('export-projects-url'),
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
project_ids: selectedProjects
|
||||
},
|
||||
success: function(data) {
|
||||
// Update modal title
|
||||
exportProjectsModalHeader.html(data.title);
|
||||
|
||||
// Set modal body
|
||||
exportProjectsModalBody.html(data.html);
|
||||
|
||||
// Show the modal
|
||||
exportProjectsModal.modal('show');
|
||||
},
|
||||
error: function() {
|
||||
// TODO
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Remove modal content when modal window is closed.
|
||||
exportProjectsModal.on('hidden.bs.modal', function() {
|
||||
exportProjectsModalHeader.html('');
|
||||
exportProjectsModalBody.html('');
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize reloading manage user modal content after posting new
|
||||
// user.
|
||||
|
||||
|
@ -295,10 +337,15 @@
|
|||
projectActionsModalBody = projectActionsModal.find('.modal-body');
|
||||
projectActionsModalFooter = projectActionsModal.find('.modal-footer');
|
||||
|
||||
exportProjectsModal = $('#export-projects-modal');
|
||||
exportProjectsModalHeader = exportProjectsModal.find('.modal-title');
|
||||
exportProjectsModalBody = exportProjectsModal.find('.modal-body');
|
||||
|
||||
updateSelectedCards();
|
||||
initNewProjectModal();
|
||||
initEditProjectModal();
|
||||
initManageUsersModal();
|
||||
initExportProjectsModal();
|
||||
Comments.initCommentOptions('ul.content-comments', true);
|
||||
Comments.initEditComments('.panel-project .tab-content');
|
||||
Comments.initDeleteComments('.panel-project .tab-content');
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
class TeamsController < ApplicationController
|
||||
before_action :load_vars, only: %i(:parse_sheet :import_samples
|
||||
:export_samples :export_all)
|
||||
before_action :load_vars, only: %i(parse_sheet import_samples
|
||||
export_samples export_projects)
|
||||
|
||||
before_action :check_create_samples_permissions, only: %i(parse_sheet
|
||||
import_samples)
|
||||
before_action :check_view_samples_permission, only: [:export_samples]
|
||||
before_action :check_export_all_permission, only: [:export_all]
|
||||
before_action :check_export_projects_permissions, only: [:export_projects]
|
||||
|
||||
def parse_sheet
|
||||
session[:return_to] ||= request.referer
|
||||
|
@ -225,9 +225,36 @@ class TeamsController < ApplicationController
|
|||
redirect_back(fallback_location: root_path)
|
||||
end
|
||||
|
||||
def export_all
|
||||
if export_params[:project_ids]
|
||||
TeamZipExporter.generate_zip(export_params, @team, current_user)
|
||||
def export_projects
|
||||
if export_projects_params[:project_ids]
|
||||
# Check if user has enough requests for the day
|
||||
limit = ENV['EXPORT_ALL_LIMIT_24_HOURS'].to_i || 3
|
||||
if current_user.export_vars['num_of_export_all_last_24_hours'] >= limit
|
||||
render json: {
|
||||
html: render_to_string(
|
||||
partial: 'projects/export/error.html.erb',
|
||||
locals: { limit: limit }
|
||||
),
|
||||
title: t('projects.export_projects.modal_title_error')
|
||||
}
|
||||
else
|
||||
current_user.export_vars['num_of_export_all_last_24_hours'] += 1
|
||||
current_user.save
|
||||
|
||||
ids = generate_export_projects_zip
|
||||
curr_num = current_user.export_vars['num_of_export_all_last_24_hours']
|
||||
|
||||
render json: {
|
||||
html: render_to_string(
|
||||
partial: 'projects/export/success.html.erb',
|
||||
locals: { num_projects: ids.length,
|
||||
limit: limit,
|
||||
num_of_requests_left: limit - curr_num }
|
||||
),
|
||||
title: t('projects.export_projects.modal_title_success')
|
||||
}
|
||||
end
|
||||
return
|
||||
else
|
||||
flash[:alert] = t('zip_export.export_error')
|
||||
end
|
||||
|
@ -270,6 +297,10 @@ class TeamsController < ApplicationController
|
|||
params.permit(sample_ids: [], header_ids: []).to_h
|
||||
end
|
||||
|
||||
def export_projects_params
|
||||
params.permit(:id, project_ids: []).to_h
|
||||
end
|
||||
|
||||
def check_create_samples_permissions
|
||||
render_403 unless can_create_samples?(@team)
|
||||
end
|
||||
|
@ -280,13 +311,13 @@ class TeamsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def check_export_all_permission
|
||||
def check_export_projects_permissions
|
||||
render_403 unless can_read_team?(@team)
|
||||
|
||||
if export_params[:project_ids]
|
||||
projects = Project.where(id: export_params[:project_ids])
|
||||
if export_projects_params[:project_ids]
|
||||
projects = Project.where(id: export_projects_params[:project_ids])
|
||||
projects.each do |project|
|
||||
render_403 unless can_read_project(current_user, project)
|
||||
render_403 unless can_read_project?(current_user, project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -302,4 +333,20 @@ class TeamsController < ApplicationController
|
|||
:samples
|
||||
)
|
||||
end
|
||||
|
||||
def generate_export_projects_zip
|
||||
ids = Project.where(id: export_projects_params[:project_ids],
|
||||
team_id: @team)
|
||||
.index_by(&:id)
|
||||
|
||||
options = { team: @team }
|
||||
zip = TeamZipExport.create(user: current_user)
|
||||
zip.generate_exportable_zip(
|
||||
current_user,
|
||||
ids,
|
||||
:teams,
|
||||
options
|
||||
)
|
||||
ids
|
||||
end
|
||||
end
|
||||
|
|
22
app/models/concerns/variables_model.rb
Normal file
22
app/models/concerns/variables_model.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
module VariablesModel
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
@@default_variables = HashWithIndifferentAccess.new
|
||||
|
||||
included do
|
||||
serialize :variables, JsonbHashSerializer
|
||||
after_initialize :init_default_variables, if: :new_record?
|
||||
end
|
||||
|
||||
class_methods do
|
||||
def default_variables(dfs)
|
||||
@@default_variables.merge!(dfs)
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def init_default_variables
|
||||
self.variables = @@default_variables
|
||||
end
|
||||
end
|
|
@ -1,5 +1,5 @@
|
|||
class User < ApplicationRecord
|
||||
include SearchableModel, SettingsModel
|
||||
include SearchableModel, SettingsModel, VariablesModel
|
||||
include User::TeamRoles, User::ProjectRoles
|
||||
|
||||
acts_as_token_authenticatable
|
||||
|
@ -47,6 +47,14 @@ class User < ApplicationRecord
|
|||
}
|
||||
)
|
||||
|
||||
store_accessor :variables, :export_vars
|
||||
|
||||
default_variables(
|
||||
export_vars: {
|
||||
num_of_export_all_last_24_hours: 0
|
||||
}
|
||||
)
|
||||
|
||||
# Relations
|
||||
has_many :user_identities, inverse_of: :user
|
||||
has_many :user_teams, inverse_of: :user
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
module TeamZipExporter
|
||||
def self.generate_zip(params, team, current_user)
|
||||
Rails.logger.info('Exporting team zip')
|
||||
|
||||
project_ids = params[:project_ids]
|
||||
ids = Project.where(id: project_ids,
|
||||
team_id: team)
|
||||
.index_by(&:id)
|
||||
|
||||
options = { team: team }
|
||||
zip = TeamZipExport.create(user: current_user)
|
||||
zip.generate_exportable_zip(
|
||||
current_user,
|
||||
ids,
|
||||
:team,
|
||||
options
|
||||
)
|
||||
end
|
||||
end
|
6
app/views/projects/export/_error.html.erb
Normal file
6
app/views/projects/export/_error.html.erb
Normal file
|
@ -0,0 +1,6 @@
|
|||
<p>
|
||||
It looks like you have exceeded your daily export limit. The number of exports is <strong>limited to <%= limit %> requests per day </strong>- you currently have 0 export requests left.
|
||||
</p>
|
||||
|
||||
<p>Please repeat the desired action <strong>tomorrow</strong>, when your daily limit will rise back to <%= limit %> export requests.
|
||||
</p>
|
12
app/views/projects/export/_success.html.erb
Normal file
12
app/views/projects/export/_success.html.erb
Normal file
|
@ -0,0 +1,12 @@
|
|||
<p>Your export request for <strong><%= num_projects %> projects in <%= @team.name %> </strong> team is being processed and will soon be exported in a .zip file format. It may take anywhere from 5 minutes up to several hours, depending on the file size. Please also note, that any new data in the projects from this point will not be included in the exported file.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When it's ready, you will receive a confirmation e-mail and the <strong> link </strong> to your file will appear in your <strong>SciNote notifications</strong>. For security reasons, the link will <strong>expire in 7 days</strong>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<i>
|
||||
Please note that the number of exports is limited to <%= limit %> requests per day - you currently have <%= num_of_requests_left %> more.
|
||||
</i>
|
||||
</p>
|
|
@ -77,6 +77,23 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Export projects modal -->
|
||||
<div class="modal" id="export-projects-modal" tabindex="-1" role="dialog" aria-labelledby="export-projects-modal-label">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="export-projects-modal-label"></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal"><%=t "general.cancel" %></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="projects-toolbar">
|
||||
|
||||
<form class="form-inline" action="<%= projects_path %>">
|
||||
|
@ -115,6 +132,14 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- export projects button -->
|
||||
<button type="button" class="btn btn-default pull-right"
|
||||
id="export-projects-button"
|
||||
data-export-projects-url="<%= export_projects_team_path(current_team) %>">
|
||||
<span class="fas fa-file-export"></span>
|
||||
<span class="hidden-xs-custom"><%= t("projects.export_projects.export_button") %></span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -283,6 +283,10 @@ en:
|
|||
invite_users_link: "Invite users"
|
||||
invite_users_details: "to team %{team}."
|
||||
contact_admins: "To invite additional users to team %{team}, contact its administrator/s."
|
||||
export_projects:
|
||||
export_button: "Export projects..."
|
||||
modal_title_success: 'Your export is being prepared'
|
||||
modal_title_error: 'Your export is denied'
|
||||
table:
|
||||
status: "Status"
|
||||
name: "Project name"
|
||||
|
|
|
@ -178,6 +178,7 @@ Rails.application.routes.draw do
|
|||
# post 'import_samples'
|
||||
# post 'export_samples'
|
||||
post 'export_repository', to: 'repositories#export_repository'
|
||||
post 'export_projects'
|
||||
# Used for atwho (smart annotations)
|
||||
get 'atwho_users', to: 'at_who#users'
|
||||
get 'atwho_repositories', to: 'at_who#repositories'
|
||||
|
|
19
db/migrate/20180930205254_add_variables_to_users.rb
Normal file
19
db/migrate/20180930205254_add_variables_to_users.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
class AddVariablesToUsers < ActiveRecord::Migration[5.1]
|
||||
def up
|
||||
add_column :users, :variables, :jsonb, default: {}, null: false
|
||||
|
||||
User.find_each do |user|
|
||||
variables = {
|
||||
export_vars: {
|
||||
num_of_export_all_last_24_hours: 0
|
||||
}
|
||||
}
|
||||
|
||||
user.update(variables: variables)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :users, :variables, :jsonb
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20180524091143) do
|
||||
ActiveRecord::Schema.define(version: 20180930205254) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -786,6 +786,7 @@ ActiveRecord::Schema.define(version: 20180524091143) do
|
|||
t.integer "current_team_id"
|
||||
t.string "authentication_token", limit: 30
|
||||
t.jsonb "settings", default: {}, null: false
|
||||
t.jsonb "variables", default: {}, null: false
|
||||
t.index "trim_html_tags((full_name)::text) gin_trgm_ops", name: "index_users_on_full_name", using: :gin
|
||||
t.index ["authentication_token"], name: "index_users_on_authentication_token", unique: true
|
||||
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
|
||||
|
|
Loading…
Reference in a new issue