Add edit modal for project folders [SCI-5265] (#3002)

Add edit modal for project folders [SCI-5265]
This commit is contained in:
aignatov-bio 2020-12-14 15:54:18 +01:00 committed by GitHub
parent 691072f519
commit 30cfe78805
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 155 additions and 119 deletions

View file

@ -16,10 +16,7 @@
var newProjectModalBody = null;
var newProjectBtn = null;
var editProjectModal = null;
var editProjectModalTitle = null;
var editProjectModalBody = null;
var editProjectBtn = null;
var editProjectModal = '#edit-modal';
var projectActionsModal = null;
var projectActionsModalHeader = null;
@ -140,61 +137,6 @@
});
}
function initEditProjectButton(el) {
el.find(".dropdown-menu a[data-action='edit']").off()
.on('ajax:success', function(ev, data) {
// Update modal title
editProjectModalTitle.html(data.title);
// Set modal body
editProjectModalBody.html(data.html);
// Add modal body's submit handler
editProjectModal.find('form').off()
.on('ajax:beforeSend', function() {
animateSpinner(this);
})
.on('ajax:success', function(ev2, data2) {
projectsChanged = true;
// Hide modal
editProjectModal.modal('hide');
HelperModule.flashAlertMsg(data2.message, 'success');
// Project saved, reload view
refreshCurrentView();
})
.on('ajax:error', function(ev2, data2) {
$(this).renderFormErrors('project', data2.responseJSON.errors);
})
.on('ajax:complete', function() {
animateSpinner(this, false);
});
// Show the modal
editProjectModal.modal('show');
})
.on('ajax:error', function() {
// TODO
});
}
/**
* Initialize the JS for edit project modal to work.
*/
function initEditProjectModal() {
// Edit button click handler
editProjectBtn.off().click(function() {
// Submit the modal body's form
editProjectModalBody.find('form').submit();
});
// On hide modal handler
editProjectModal.off().on('hidden.bs.modal', function() {
editProjectModalBody.html('');
});
}
function initManageUsersModal() {
// Reload users tab HTML element when modal is closed
projectActionsModal.off('hide.bs.modal').on('hide.bs.modal', function() {
@ -381,15 +323,15 @@
let projectsToolbar = $('#projectsToolbar');
if (selectedProjects.length === 0 && selectedProjectFolders.length === 0) {
projectsToolbar.find('.single-project-action, .multiple-projects-action').addClass('hidden');
projectsToolbar.find('.new-project-actions').removeClass('hidden');
} else if (selectedProjects.length === 1 && selectedProjectFolders.length === 0) {
projectsToolbar.find('.new-project-actions').addClass('hidden');
projectsToolbar.find('.single-project-action, .multiple-projects-action').removeClass('hidden');
projectsToolbar.find('.single-object-action, .multiple-object-action').addClass('hidden');
projectsToolbar.find('.new-object-actions').removeClass('hidden');
} else if (selectedProjects.length + selectedProjectFolders.length === 1) {
projectsToolbar.find('.new-object-actions').addClass('hidden');
projectsToolbar.find('.single-object-action, .multiple-object-action').removeClass('hidden');
} else {
projectsToolbar.find('.new-project-actions').addClass('hidden');
projectsToolbar.find('.single-project-action').addClass('hidden');
projectsToolbar.find('.multiple-projects-action').removeClass('hidden');
projectsToolbar.find('.new-object-actions').addClass('hidden');
projectsToolbar.find('.single-object-action').addClass('hidden');
projectsToolbar.find('.multiple-object-action').removeClass('hidden');
}
}
@ -412,11 +354,6 @@
newProjectModalBody = newProjectModal.find('.modal-body');
newProjectBtn = $('.new-project-btn');
editProjectModal = $('#edit-project-modal');
editProjectModalTitle = editProjectModal.find('#edit-project-modal-label');
editProjectModalBody = editProjectModal.find('.modal-body');
editProjectBtn = editProjectModal.find(".btn[data-action='submit']");
projectActionsModal = $('#project-actions-modal');
projectActionsModalHeader = projectActionsModal.find('.modal-title');
projectActionsModalBody = projectActionsModal.find('.modal-body');
@ -431,13 +368,11 @@
updateSelectedCards();
initNewProjectFolderModal();
initNewProjectModal();
initEditProjectModal();
initManageUsersModal();
initExportProjectsModal();
initExportProjects();
initFormSubmitLinks($('.project-card'));
initEditProjectButton($('.project-card'));
initArchiveRestoreButton($('.project-card'));
$('#cards-wrapper').on('click', '.folder-card-selector', function() {
@ -533,6 +468,38 @@
});
}
function initEditButton() {
function loadEditModal(url) {
$.get(url, function(result) {
$(editProjectModal).find('.modal-content').html(result.html);
$(editProjectModal).modal('show');
$(editProjectModal).find('form')
.on('ajax:success', function(ev, data) {
$(editProjectModal).modal('hide');
HelperModule.flashAlertMsg(data.message, 'success');
refreshCurrentView();
}).on('ajax:error', function(ev, data) {
HelperModule.flashAlertMsg(data.responseJSON.message, 'danger');
$(this).renderFormErrors('project', data.responseJSON.errors);
$(this).renderFormErrors('project_folder', data.responseJSON.errors);
});
});
}
$('.project-actions .edit-btn').on('click', function(e) {
var editUrl = $(`.project-card[data-id=${selectedProjects[0]}]`).data('edit-url') ||
$(`.folder-card[data-id=${selectedProjectFolders[0]}]`).data('edit-url');
e.preventDefault();
loadEditModal(editUrl);
});
$('.projects-container').on('click', '.edit-project-btn', function(e) {
var editUrl = $(this).attr('href');
e.preventDefault();
loadEditModal(editUrl);
});
}
function loadCardsView() {
// Load HTML with projects list
var viewContainer = $('#cards-wrapper');
@ -552,6 +519,9 @@
viewContainer.data('projects-cards-url', data.projects_cards_url);
viewContainer.find('.card, .projects-group').remove();
viewContainer.append(data.cards_html);
selectedProjects.length = 0;
selectedProjectFolders.length = 0;
refreshProjectsToolbar();
Sidebar.reload();
init();
},
@ -707,6 +677,7 @@
});
}
initEditButton();
initProjectsViewModeSwitch();
initSorting();
loadCardsView();

View file

@ -669,6 +669,20 @@ li.module-hover {
}
}
.cards-wrapper {
align-items: center;
display: grid;
grid-auto-rows: 2em;
grid-column-gap: 1em;
grid-row-gap: 1em;
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
width: 100%;
.table-header {
display: none;
}
}
&.archived {
[data-view-mode="active"] {
display: none;

View file

@ -4,6 +4,7 @@ class ProjectFoldersController < ApplicationController
include InputSanitizeHelper
before_action :load_current_folder, only: %i(new)
before_action :load_folder, only: %i(edit update)
before_action :check_create_permissions, only: %i(new create)
before_action :check_manage_permissions, only: %i(move_to)
@ -26,7 +27,7 @@ class ProjectFoldersController < ApplicationController
respond_to do |format|
format.json do
if project_folder.save
log_activity(:create_project_folder, project_folder, { project_folder: project_folder.id })
log_activity(:create_project_folder, project_folder, project_folder: project_folder.id)
message = t('projects.index.modal_new_project_folder.success_flash',
name: escape_input(project_folder.name))
render json: { message: message }
@ -55,20 +56,38 @@ class ProjectFoldersController < ApplicationController
end
end
def update
folder = current_team.project_folders.find(params[:id])
def edit
render json: {
html: render_to_string(partial: 'projects/index/modals/edit_folder_contents.html.erb',
locals: { folder: @folder })
log_activity(:rename_project_folder, folder, { project_folder: folder.id })
}
end
def update
if @folder.update(project_folders_params)
log_activity(:rename_project_folder, @folder, project_folder: @folder.id)
render json: { message: t('projects.update.success_flash', name: escape_input(@folder.name)) }
else
render json: { message: t('projects.update.error_flash', name: escape_input(@folder.name)),
errors: @folder.errors }, status: :unprocessable_entity
end
end
def archive
folder = current_team.project_folders.find(params[:id])
log_activity(:archive_project_folder, folder, { project_folder: folder.id })
log_activity(:archive_project_folder, folder, project_folder: folder.id)
end
private
def load_folder
@folder = current_team.project_folders.find_by(id: params[:id])
render_404 unless @folder
end
def load_current_folder
if params[:project_folder_id].present?
@current_folder = current_team.project_folders.find_by(id: params[:project_folder_id])
@ -102,9 +121,9 @@ class ProjectFoldersController < ApplicationController
project.update!(project_folder: destination_folder)
destination_folder_name = project.project_folder&.name || I18n.t('global_activities.root_folder_level')
log_activity(:move_project, project, { project: project.id,
log_activity(:move_project, project, project: project.id,
destination_folder: destination_folder_name,
source_folder: source_folder_name })
source_folder: source_folder_name)
end
end
@ -117,9 +136,9 @@ class ProjectFoldersController < ApplicationController
folder.update!(parent_folder: destination_folder)
destination_folder_name = folder.parent_folder&.name || I18n.t('global_activities.root_folder_level')
log_activity(:move_project_folder, folder, { project_folder: folder.id,
log_activity(:move_project_folder, folder, project_folder: folder.id,
destination_folder: destination_folder_name,
source_folder: source_folder_name })
source_folder: source_folder_name)
end
end

View file

@ -90,8 +90,9 @@ class ProjectsController < ApplicationController
def edit
render json: {
html: render_to_string({ partial: 'edit.html.erb', locals: { project: @project } }),
title: t('projects.index.modal_edit_project.modal_title', project: escape_input(@project.name))
html: render_to_string(partial: 'projects/index/modals/edit_project_contents.html.erb',
locals: { project: @project })
}
end

View file

@ -1,9 +0,0 @@
<%= bootstrap_form_for @project, url: project_path(@project ,format: :json), method: :put, remote: true do |f| %>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<%= f.text_field :name, label: t("projects.index.modal_new_project.name"), autofocus: true, placeholder: t("projects.index.modal_new_project.name_placeholder") %>
</div>
</div>
<%= f.enum_btn_group :visibility, label: t("projects.index.modal_new_project.visibility"), btn_names: { hidden: t("projects.index.modal_new_project.visibility_hidden"), visible: t("projects.index.modal_new_project.visibility_visible") } %>
<% end %>

View file

@ -18,7 +18,7 @@
<span style="display: none;" data-hook="projects-index-html"></span>
<%= render partial: 'projects/index/modals/new_project' %>
<%= render partial: 'projects/index/modals/edit_project' %>
<%= render partial: 'projects/index/modals/edit_modal' %>
<%= render partial: 'projects/index/modals/manage_users' %>
<%= render partial: 'projects/index/modals/export_projects' %>

View file

@ -1,4 +1,4 @@
<div class="card folder-card" data-id="<%= folder %>">
<div class="card folder-card" data-id="<%= folder.id %>" data-edit-url="<%= edit_project_folder_path(folder) %>">
<div class="checkbox-cell">
<div class="sci-checkbox-container">
<input value="1" type="checkbox" class="sci-checkbox folder-card-selector">

View file

@ -15,6 +15,7 @@
<% if active && can_manage_project?(project) %>
<li>
<a href="<%= edit_project_path(project, format: :json) %>"
class="edit-project-btn"
data-action="edit"
data-remote="true">
<i class="fas fa-pen"></i>

View file

@ -1,4 +1,4 @@
<div class="card project-card" data-id="<%= project.id %>">
<div class="card project-card" data-id="<%= project.id %>" data-edit-url="<%= edit_project_path(project) %>">
<div class="checkbox-cell">
<div class="sci-checkbox-container">
<input value="1" type="checkbox" class="sci-checkbox project-card-selector">

View file

@ -4,7 +4,7 @@
<div class="form-group">
<div class="new-project-actions pull-left">
<div class="new-object-actions pull-left">
<!-- new project button -->
<% if current_team && can_create_projects?(current_team) %>
<a href="#" class="btn btn-primary new-project-btn" data-view-mode="active">
@ -24,20 +24,20 @@
</div>
<div class="project-actions pull-left">
<a href="#" class="btn btn-secondary edit-project-btn single-project-action hidden" data-view-mode="active">
<a href="#" class="btn btn-secondary edit-btn single-object-action hidden" data-view-mode="active">
<span class="fas fa-folder" aria-hidden="true"></span>
<span class="hidden-xs"><%= t('projects.index.edit_button') %></span>
</a>
<a href="#" class="btn btn-secondary move-projects-btn multiple-projects-action hidden" >
<a href="#" class="btn btn-secondary move-projects-btn multiple-object-action hidden">
<span class="fas fa-arrow-right" aria-hidden="true"></span>
<span class="hidden-xs"><%= t('projects.index.move_button') %></span>
</a>
<a href="#" class="btn btn-secondary archive-projects-btn multiple-projects-action project-only-action hidden" data-view-mode="active">
<a href="#" class="btn btn-secondary archive-projects-btn multiple-object-action project-only-action hidden" data-view-mode="active">
<span class="fas fa-archive" aria-hidden="true"></span>
<span class="hidden-xs"><%= t('projects.index.archive_button') %></span>
</a>
<!-- export projects button -->
<a href="#" class="btn btn-secondary export-projects-btn multiple-projects-action project-only-action hidden"
<a href="#" class="btn btn-secondary export-projects-btn multiple-object-action project-only-action hidden"
data-export-projects-modal-url="<%= export_projects_modal_team_path(current_team) %>">
<span class="fas fa-file-export"></span>
<span class="hidden-xs-custom"><%= t('projects.export_projects.export_button') %></span>

View file

@ -0,0 +1,21 @@
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">
<%= t('projects.index.modal_edit_folder.title', folder: folder.name) %>
</h4>
</div>
<%= bootstrap_form_for folder, url: project_folder_path(folder ,format: :json), method: :put, remote: true do |f| %>
<div class="modal-body">
<p><%= t('projects.index.modal_edit_folder.description') %></p>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<%= f.text_field :name, label: t('projects.index.modal_edit_folder.folder_name_field'), autofocus: true %>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.cancel" %></button>
<button class="btn btn-primary" type="submit"><%=t "projects.index.modal_edit_folder.submit" %></button>
</div>
<% end %>

View file

@ -0,0 +1,6 @@
<div class="modal" id="edit-modal" tabindex="-1" role="dialog" aria-labelledby="edit-project-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
</div>
</div>
</div>

View file

@ -1,16 +0,0 @@
<div class="modal" id="edit-project-modal" tabindex="-1" role="dialog" aria-labelledby="edit-project-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">&times;</span></button>
<h4 class="modal-title" id="edit-project-modal-label"></h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.cancel" %></button>
<button type="button" class="btn btn-primary" data-action="submit"><%=t "projects.index.modal_edit_project.submit" %></button>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,23 @@
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="edit-project-modal-label">
<%= t('projects.index.modal_edit_project.modal_title', project: @project.name) %>
</h4>
</div>
<%= bootstrap_form_for @project, url: project_path(@project ,format: :json), method: :put, remote: true do |f| %>
<div class="modal-body">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<%= f.text_field :name, label: t("projects.index.modal_new_project.name"), autofocus: true, placeholder: t("projects.index.modal_new_project.name_placeholder") %>
</div>
</div>
<%= f.enum_btn_group :visibility, label: t("projects.index.modal_new_project.visibility"), btn_names: { hidden: t("projects.index.modal_new_project.visibility_hidden"), visible: t("projects.index.modal_new_project.visibility_visible") } %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%=t "general.cancel" %></button>
<button class="btn btn-primary" type="submit"><%=t "projects.index.modal_edit_project.submit" %></button>
</div>
<% end %>

View file

@ -385,6 +385,11 @@ en:
modal_edit_project:
modal_title: "Edit project %{project}"
submit: "Save"
modal_edit_folder:
title: "Edit folder %{folder}"
description: "Rename your folder"
folder_name_field: "Folder name"
submit: "Save"
modal_manage_users:
modal_title_html: "Manage users for <span id='manage-users-modal-project'>%{name}</span>"
no_users: "No users!"

View file

@ -302,7 +302,7 @@ Rails.application.routes.draw do
end
end
resources :project_folders, only: %i(create new update) do
resources :project_folders, only: %i(create new update edit) do
member do
post 'archive', to: 'project_folders#archive'
end