mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-01-27 18:21:50 +08:00
Merge pull request #3113 from mlorb/ml-sci-5311
Implement the option of deleting empty folders [SCI-5311]
This commit is contained in:
commit
20dc9967f5
11 changed files with 136 additions and 4 deletions
|
@ -7,10 +7,10 @@
|
||||||
// - refresh project users tab after manage user modal is closed
|
// - refresh project users tab after manage user modal is closed
|
||||||
// - refactor view handling using library, ex. backbone.js
|
// - refactor view handling using library, ex. backbone.js
|
||||||
|
|
||||||
/* global animateSpinner HelperModule dropdownSelector Sidebar Turbolinks filterDropdown */
|
/* global HelperModule dropdownSelector Sidebar Turbolinks filterDropdown */
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
const PERMISSIONS = ['editable', 'archivable', 'restorable', 'moveable'];
|
const PERMISSIONS = ['editable', 'archivable', 'restorable', 'moveable', 'deletable'];
|
||||||
var projectsWrapper = '#projectsWrapper';
|
var projectsWrapper = '#projectsWrapper';
|
||||||
var toolbarWrapper = '#toolbarWrapper';
|
var toolbarWrapper = '#toolbarWrapper';
|
||||||
var cardsWrapper = '#cardsWrapper';
|
var cardsWrapper = '#cardsWrapper';
|
||||||
|
@ -97,6 +97,42 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init delete project folders
|
||||||
|
function initDeleteFoldersToolbarButton() {
|
||||||
|
$(projectsWrapper)
|
||||||
|
.on('ajax:before', '.delete-folders-btn', function() {
|
||||||
|
let buttonForm = $(this);
|
||||||
|
buttonForm.find('input[name="project_folders_ids[]"]').remove();
|
||||||
|
selectedProjectFolders.forEach(function(id) {
|
||||||
|
$('<input>').attr({
|
||||||
|
type: 'hidden',
|
||||||
|
name: 'project_folders_ids[]',
|
||||||
|
value: id
|
||||||
|
}).appendTo(buttonForm);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.on('ajax:success', '.delete-folders-btn', function(ev, data) {
|
||||||
|
// Add and show modal
|
||||||
|
let deleteModal = $(data.html);
|
||||||
|
$(projectsWrapper).append(deleteModal);
|
||||||
|
deleteModal.modal('show');
|
||||||
|
// Remove modal when it gets closed
|
||||||
|
deleteModal.on('hidden.bs.modal', function() {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(projectsWrapper)
|
||||||
|
.on('ajax:success', '.delete-folders-form', function(ev, data) {
|
||||||
|
$('.modal-project-folder-delete').modal('hide');
|
||||||
|
HelperModule.flashAlertMsg(data.message, 'success');
|
||||||
|
refreshCurrentView();
|
||||||
|
})
|
||||||
|
.on('ajax:error', '.delete-folders-form', function(ev, data) {
|
||||||
|
HelperModule.flashAlertMsg(data.responseJSON.message, 'danger');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// init project toolbar archive/restore functions
|
// init project toolbar archive/restore functions
|
||||||
function initArchiveRestoreToolbarButtons() {
|
function initArchiveRestoreToolbarButtons() {
|
||||||
$(projectsWrapper)
|
$(projectsWrapper)
|
||||||
|
@ -322,6 +358,8 @@
|
||||||
projectsToolbar.find('.single-object-action, .multiple-object-action').removeClass('hidden');
|
projectsToolbar.find('.single-object-action, .multiple-object-action').removeClass('hidden');
|
||||||
if (selectedProjectFolders.length === 1) {
|
if (selectedProjectFolders.length === 1) {
|
||||||
projectsToolbar.find('.project-only-action').addClass('hidden');
|
projectsToolbar.find('.project-only-action').addClass('hidden');
|
||||||
|
} else {
|
||||||
|
projectsToolbar.find('.folders-only-action').addClass('hidden');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
projectsToolbar.find('.single-object-action').addClass('hidden');
|
projectsToolbar.find('.single-object-action').addClass('hidden');
|
||||||
|
@ -329,6 +367,9 @@
|
||||||
if (selectedProjectFolders.length > 0) {
|
if (selectedProjectFolders.length > 0) {
|
||||||
projectsToolbar.find('.project-only-action').addClass('hidden');
|
projectsToolbar.find('.project-only-action').addClass('hidden');
|
||||||
}
|
}
|
||||||
|
if (selectedProjects.length > 0) {
|
||||||
|
projectsToolbar.find('.folder-only-action').addClass('hidden');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PERMISSIONS.forEach((permission) => {
|
PERMISSIONS.forEach((permission) => {
|
||||||
if (!checkActionPermission(permission)) {
|
if (!checkActionPermission(permission)) {
|
||||||
|
@ -637,6 +678,7 @@
|
||||||
initManageUsersModal();
|
initManageUsersModal();
|
||||||
initExportProjectsModal();
|
initExportProjectsModal();
|
||||||
initExportProjects();
|
initExportProjects();
|
||||||
|
initDeleteFoldersToolbarButton();
|
||||||
initArchiveRestoreToolbarButtons();
|
initArchiveRestoreToolbarButtons();
|
||||||
initViewProjectUsersLink();
|
initViewProjectUsersLink();
|
||||||
initManageProjectUsersLink();
|
initManageProjectUsersLink();
|
||||||
|
|
|
@ -475,6 +475,11 @@ li.module-hover {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.delete-folders-form,
|
||||||
|
.delete-folders-btn {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.filter-container {
|
.filter-container {
|
||||||
.projects-filters {
|
.projects-filters {
|
||||||
.select-block {
|
.select-block {
|
||||||
|
|
|
@ -96,6 +96,35 @@ class ProjectFoldersController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def destroy_modal
|
||||||
|
render json: {
|
||||||
|
html: render_to_string(partial: 'projects/index/modals/project_folder_delete.html.erb',
|
||||||
|
locals: { project_folders_ids: params[:project_folders_ids] })
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
project_folders = current_team.project_folders.where(id: params[:project_folders_ids])
|
||||||
|
counter = 0
|
||||||
|
project_folders.each do |folder|
|
||||||
|
next if folder.projects.exists? || folder.project_folders.exists? || !can_update_team?(current_team)
|
||||||
|
|
||||||
|
folder.transaction do
|
||||||
|
log_activity(:delete_project_folder, folder, project_folder: folder.id)
|
||||||
|
folder.destroy!
|
||||||
|
counter += 1
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.error e.message
|
||||||
|
raise ActiveRecord::Rollback
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if counter.positive?
|
||||||
|
render json: { message: t('projects.delete_folders.success_flash', number: counter) }
|
||||||
|
else
|
||||||
|
render json: { message: t('projects.delete_folders.error_flash') }, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_project_folder
|
def load_project_folder
|
||||||
|
|
|
@ -97,3 +97,10 @@ Canaid::Permissions.register_for(ProjectComment) do
|
||||||
user.is_owner_of_project?(project_comment.project))
|
user.is_owner_of_project?(project_comment.project))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Canaid::Permissions.register_for(ProjectFolder) do
|
||||||
|
# ProjectFolder: delete
|
||||||
|
can :delete_project_folder do |_, project_folder|
|
||||||
|
!project_folder.projects.exists? && !project_folder.project_folders.exists?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
data-editable="<%= can_update_team?(current_team) %>"
|
data-editable="<%= can_update_team?(current_team) %>"
|
||||||
data-moveable="<%= can_update_team?(current_team) %>"
|
data-moveable="<%= can_update_team?(current_team) %>"
|
||||||
data-archivable="false"
|
data-archivable="false"
|
||||||
data-restorable="false">
|
data-restorable="false"
|
||||||
|
data-deletable="<%= can_delete_project_folder?(folder) && can_update_team?(current_team) %>">
|
||||||
<div class="checkbox-cell table-cell">
|
<div class="checkbox-cell table-cell">
|
||||||
<div class="sci-checkbox-container">
|
<div class="sci-checkbox-container">
|
||||||
<input value="1" type="checkbox" class="sci-checkbox folder-card-selector">
|
<input value="1" type="checkbox" class="sci-checkbox folder-card-selector">
|
||||||
|
|
|
@ -46,6 +46,15 @@
|
||||||
<span class="fas fa-undo" aria-hidden="true"></span>
|
<span class="fas fa-undo" aria-hidden="true"></span>
|
||||||
<span class="hidden-xs"><%= t('projects.index.restore_button') %></span>
|
<span class="hidden-xs"><%= t('projects.index.restore_button') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<%= button_to destroy_modal_project_folders_url,
|
||||||
|
class: 'btn btn-light multiple-object-action folders-only-action hidden',
|
||||||
|
form_class: 'delete-folders-btn',
|
||||||
|
data: { for: :deletable },
|
||||||
|
remote: true,
|
||||||
|
method: :post do %>
|
||||||
|
<span class="fas fa-trash" aria-hidden="true"></span>
|
||||||
|
<span class="hidden-xs"><%= t('projects.index.delete_button') %></span>
|
||||||
|
<% end %>
|
||||||
<!-- export projects button -->
|
<!-- export projects button -->
|
||||||
<a href="#" class="btn btn-light export-projects-btn multiple-object-action hidden"
|
<a href="#" class="btn btn-light export-projects-btn multiple-object-action hidden"
|
||||||
data-export-projects-modal-url="<%= export_projects_modal_team_path(current_team) %>">
|
data-export-projects-modal-url="<%= export_projects_modal_team_path(current_team) %>">
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<div class="modal modal-project-folder-delete" role="dialog" aria-hidden="true" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<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>
|
||||||
|
<h2 class="modal-title"><%= t('projects.index.modal_delete_folders.title') %></h2>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p><%= t('projects.index.modal_delete_folders.description_1_html', number: project_folders_ids.size) %></p>
|
||||||
|
<p><%= t('projects.index.modal_delete_folders.description_2') %></p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type='button' class='btn btn-default' data-dismiss='modal'><%= t('general.cancel')%></button>
|
||||||
|
<%= button_to t('projects.index.modal_delete_folders.confirm_button'),
|
||||||
|
destroy_project_folders_path,
|
||||||
|
class: 'btn btn-danger',
|
||||||
|
form_class: 'delete-folders-form',
|
||||||
|
params: { project_folders_ids: project_folders_ids },
|
||||||
|
remote: true %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -380,7 +380,8 @@ class Extends
|
||||||
move_project: 158,
|
move_project: 158,
|
||||||
create_project_folder: 159,
|
create_project_folder: 159,
|
||||||
move_project_folder: 160,
|
move_project_folder: 160,
|
||||||
rename_project_folder: 161
|
rename_project_folder: 161,
|
||||||
|
delete_project_folder: 162
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTIVITY_GROUPS = {
|
ACTIVITY_GROUPS = {
|
||||||
|
|
|
@ -369,6 +369,7 @@ en:
|
||||||
move_button: "Move"
|
move_button: "Move"
|
||||||
archive_button: "Archive"
|
archive_button: "Archive"
|
||||||
restore_button: "Restore"
|
restore_button: "Restore"
|
||||||
|
delete_button: "Delete"
|
||||||
edit_option: "Edit"
|
edit_option: "Edit"
|
||||||
archive_option: "Archive"
|
archive_option: "Archive"
|
||||||
archive_confirm: "Are you sure you want to archive this project?"
|
archive_confirm: "Are you sure you want to archive this project?"
|
||||||
|
@ -417,6 +418,11 @@ en:
|
||||||
projects: 'projects'
|
projects: 'projects'
|
||||||
folders: 'folders'
|
folders: 'folders'
|
||||||
projects_and_folders: 'projects & folders'
|
projects_and_folders: 'projects & folders'
|
||||||
|
modal_delete_folders:
|
||||||
|
title: "Delete project folder(s)"
|
||||||
|
description_1_html: "You are about to delete <strong>%{number}</strong> selected project folder(s)"
|
||||||
|
description_2: "Are you sure you want to continue?"
|
||||||
|
confirm_button: "Delete folder(s)"
|
||||||
modal_manage_users:
|
modal_manage_users:
|
||||||
modal_title: "Manage users for %{name}"
|
modal_title: "Manage users for %{name}"
|
||||||
no_users: "No users!"
|
no_users: "No users!"
|
||||||
|
@ -472,6 +478,9 @@ en:
|
||||||
restore:
|
restore:
|
||||||
success_flash: "Project <strong>%{name}</strong> successfully restored."
|
success_flash: "Project <strong>%{name}</strong> successfully restored."
|
||||||
error_flash: "Project <strong>%{name}</strong> not restored."
|
error_flash: "Project <strong>%{name}</strong> not restored."
|
||||||
|
delete_folders:
|
||||||
|
success_flash: "<strong>%{number}</strong> project folder(s) successfully deleted."
|
||||||
|
error_flash: "Failed to delete project folder(s)."
|
||||||
show:
|
show:
|
||||||
head_title: "%{project}"
|
head_title: "%{project}"
|
||||||
reports:
|
reports:
|
||||||
|
|
|
@ -180,6 +180,7 @@ en:
|
||||||
|
|
||||||
create_project_folder_html: "%{user} created project folder %{project_folder}."
|
create_project_folder_html: "%{user} created project folder %{project_folder}."
|
||||||
rename_project_folder_html: "%{user} renamed project folder %{project_folder}."
|
rename_project_folder_html: "%{user} renamed project folder %{project_folder}."
|
||||||
|
delete_project_folder_html: "%{user} deleted project folder %{project_folder}."
|
||||||
move_project_folder_html: "%{user} moved folder %{project_folder} from folder %{project_folder_from}</strong> to folder %{project_folder_to}."
|
move_project_folder_html: "%{user} moved folder %{project_folder} from folder %{project_folder_from}</strong> to folder %{project_folder_to}."
|
||||||
|
|
||||||
activity_name:
|
activity_name:
|
||||||
|
@ -325,6 +326,7 @@ en:
|
||||||
move_project: "Project moved"
|
move_project: "Project moved"
|
||||||
create_project_folder: "Project folder created"
|
create_project_folder: "Project folder created"
|
||||||
rename_project_folder: "Project folder renamed"
|
rename_project_folder: "Project folder renamed"
|
||||||
|
delete_project_folder: "Project folder deleted"
|
||||||
move_project_folder: "Project folder moved"
|
move_project_folder: "Project folder moved"
|
||||||
|
|
||||||
activity_group:
|
activity_group:
|
||||||
|
|
|
@ -310,6 +310,8 @@ Rails.application.routes.draw do
|
||||||
collection do
|
collection do
|
||||||
post 'move_to', to: 'project_folders#move_to', defaults: { format: 'json' }
|
post 'move_to', to: 'project_folders#move_to', defaults: { format: 'json' }
|
||||||
get 'move_to_modal', to: 'project_folders#move_to_modal', defaults: { format: 'json' }
|
get 'move_to_modal', to: 'project_folders#move_to_modal', defaults: { format: 'json' }
|
||||||
|
post 'destroy', to: 'project_folders#destroy', as: 'destroy', defaults: { format: 'json' }
|
||||||
|
post 'destroy_modal', to: 'project_folders#destroy_modal', defaults: { format: 'json' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
get 'project_folders/:project_folder_id', to: 'projects#index', as: :project_folder_projects
|
get 'project_folders/:project_folder_id', to: 'projects#index', as: :project_folder_projects
|
||||||
|
|
Loading…
Reference in a new issue