From c58d5734adc24253edf0f1ff94b242d1aa46cb1b Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Thu, 21 Jan 2021 19:42:25 +0100 Subject: [PATCH 1/4] Implement the option of deleting empty folders [SCI-5311] --- app/assets/javascripts/projects/index.js | 45 ++++++++++++++++++- app/assets/stylesheets/projects.scss | 4 ++ app/controllers/project_folders_controller.rb | 22 +++++++++ app/views/projects/index.html.erb | 1 + .../projects/index/_folder_card.html.erb | 3 +- app/views/projects/index/_toolbar.html.erb | 10 +++++ .../modals/_project_folder_delete.html.erb | 24 ++++++++++ config/initializers/extends.rb | 2 +- config/locales/en.yml | 9 ++++ config/locales/global_activities/en.yml | 4 +- config/routes.rb | 1 + 11 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 app/views/projects/index/modals/_project_folder_delete.html.erb diff --git a/app/assets/javascripts/projects/index.js b/app/assets/javascripts/projects/index.js index d1c997aa6..b77fdb2de 100644 --- a/app/assets/javascripts/projects/index.js +++ b/app/assets/javascripts/projects/index.js @@ -7,10 +7,10 @@ // - refresh project users tab after manage user modal is closed // - refactor view handling using library, ex. backbone.js -/* global animateSpinner HelperModule dropdownSelector Sidebar Turbolinks */ +/* global animateSpinner HelperModule dropdownSelector Sidebar Turbolinks I18n*/ (function() { - const PERMISSIONS = ['editable', 'archivable', 'restorable', 'moveable']; + const PERMISSIONS = ['editable', 'archivable', 'restorable', 'moveable', 'deletable']; var projectsWrapper = '#projectsWrapper'; var toolbarWrapper = '#toolbarWrapper'; var cardsWrapper = '#cardsWrapper'; @@ -97,6 +97,41 @@ }); } + // init project toolbar delete folders function + function initDeleteFoldersToolbarButton() { + $(projectsWrapper).on('click', '.delete-folders-form', function(e) { + e.preventDefault(); + e.stopPropagation(); + $.ajax({ + url: $(this).attr('action'), + type: 'POST', + dataType: 'json', + data: { project_folders_ids: selectedProjectFolders }, + beforeSend: function(element, ajaxSettings) { + var deleteModal = $('.modal-project-folder-delete'); + var ajax = ajaxSettings; + ajax.beforeSend = null; + deleteModal.find('.folder-confirmation-description') + .html(I18n.t('projects.index.modal_delete_folders.description_1', { number: selectedProjectFolders.length })); + deleteModal.find('.confirm-button').attr('disabled', false); + deleteModal.modal('show'); + deleteModal.off('click', '.confirm-button').one('click', '.confirm-button', { ajax: ajax }, function(button) { + $(this).attr('disabled', true); + $.ajax(button.data.ajax); + }); + return false; + }, + success: function(data) { + HelperModule.flashAlertMsg(data.message, 'success'); + refreshCurrentView(); + }, + error: function(data) { + HelperModule.flashAlertMsg(data.responseJSON.message, 'danger'); + } + }); + }); + } + // init project toolbar archive/restore functions function initArchiveRestoreToolbarButtons() { $(projectsWrapper) @@ -312,6 +347,8 @@ projectsToolbar.find('.single-object-action, .multiple-object-action').removeClass('hidden'); if (selectedProjectFolders.length === 1) { projectsToolbar.find('.project-only-action').addClass('hidden'); + } else { + projectsToolbar.find('.folders-only-action').addClass('hidden'); } } else { projectsToolbar.find('.single-object-action').addClass('hidden'); @@ -319,6 +356,9 @@ if (selectedProjectFolders.length > 0) { projectsToolbar.find('.project-only-action').addClass('hidden'); } + if (selectedProjects.length > 0) { + projectsToolbar.find('.folder-only-action').addClass('hidden'); + } } PERMISSIONS.forEach((permission) => { if (!checkActionPermission(permission)) { @@ -705,6 +745,7 @@ initManageUsersModal(); initExportProjectsModal(); initExportProjects(); + initDeleteFoldersToolbarButton(); initArchiveRestoreToolbarButtons(); initManageProjectUsersLink(); initAddUserForm(); diff --git a/app/assets/stylesheets/projects.scss b/app/assets/stylesheets/projects.scss index 616f0c70e..f0a9b9dd1 100644 --- a/app/assets/stylesheets/projects.scss +++ b/app/assets/stylesheets/projects.scss @@ -554,6 +554,10 @@ li.module-hover { display: inline-block; } + .delete-folders-form { + display: inline-block; + } + .header-actions { align-items: center; display: flex; diff --git a/app/controllers/project_folders_controller.rb b/app/controllers/project_folders_controller.rb index 7a83f1ff3..b4b2b4a9b 100644 --- a/app/controllers/project_folders_controller.rb +++ b/app/controllers/project_folders_controller.rb @@ -102,6 +102,28 @@ class ProjectFoldersController < ApplicationController log_activity(:archive_project_folder, folder, project_folder: folder.id) 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 def load_project_folder diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb index 6a1b79307..5139e2a75 100644 --- a/app/views/projects/index.html.erb +++ b/app/views/projects/index.html.erb @@ -19,6 +19,7 @@ <%= render partial: 'projects/index/modals/move_to_modal' %> <%= render partial: 'projects/index/modals/manage_users' %> <%= render partial: 'projects/index/modals/export_projects' %> + <%= render partial: 'projects/index/modals/project_folder_delete' %>
diff --git a/app/views/projects/index/_folder_card.html.erb b/app/views/projects/index/_folder_card.html.erb index 33c05a031..e08511f2f 100644 --- a/app/views/projects/index/_folder_card.html.erb +++ b/app/views/projects/index/_folder_card.html.erb @@ -4,7 +4,8 @@ data-editable="<%= can_update_team?(current_team) %>" data-moveable="<%= can_update_team?(current_team) %>" data-archivable="false" - data-restorable="false"> + data-restorable="false" + data-deletable="<%= !folder.projects.exists? && !folder.project_folders.exists? && can_update_team?(current_team) %>">
diff --git a/app/views/projects/index/_toolbar.html.erb b/app/views/projects/index/_toolbar.html.erb index 6404446eb..4b85bc532 100644 --- a/app/views/projects/index/_toolbar.html.erb +++ b/app/views/projects/index/_toolbar.html.erb @@ -46,6 +46,16 @@ <% end %> + <%= button_to destroy_project_folders_path, + class: 'btn btn-light delete-folders-btn multiple-object-action folders-only-action hidden', + form_class: 'delete-folders-form', + data: { for: :deletable }, + remote: true, + method: :delete do %> + + + <% end %> +