mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-31 00:19:20 +08:00
Add delete custom field functionality
This commit is contained in:
parent
7e32c13d27
commit
1a8b141b95
8 changed files with 209 additions and 26 deletions
|
|
@ -842,7 +842,11 @@ function changeToEditMode() {
|
||||||
$('#samples').data('num-columns',
|
$('#samples').data('num-columns',
|
||||||
$('#samples').data('num-columns') + 1);
|
$('#samples').data('num-columns') + 1);
|
||||||
originalHeader.append(
|
originalHeader.append(
|
||||||
'<th class="custom-field" id="' + data.id + '" data-editable data-deletable>' +
|
'<th class="custom-field" id="' + data.id + '" ' +
|
||||||
|
'data-editable data-deletable ' +
|
||||||
|
'data-edit-url="' + data.edit_url + '" ' +
|
||||||
|
'data-destroy-html-url="' + data.destroy_html_url + '"' +
|
||||||
|
'>' +
|
||||||
data.name + '</th>');
|
data.name + '</th>');
|
||||||
var colOrder = table.colReorder.order();
|
var colOrder = table.colReorder.order();
|
||||||
colOrder.push(colOrder.length);
|
colOrder.push(colOrder.length);
|
||||||
|
|
@ -916,6 +920,8 @@ function changeToEditMode() {
|
||||||
'<li ' +
|
'<li ' +
|
||||||
'data-position="' + colIndex + '" ' +
|
'data-position="' + colIndex + '" ' +
|
||||||
'data-id="' + $(el).attr('id') + '" ' +
|
'data-id="' + $(el).attr('id') + '" ' +
|
||||||
|
'data-edit-url=' + $(el).attr('data-edit-url') + ' ' +
|
||||||
|
'data-destroy-html-url=' + $(el).attr('data-destroy-html-url') + ' ' +
|
||||||
'class="' + visLi + '"' +
|
'class="' + visLi + '"' +
|
||||||
'>' +
|
'>' +
|
||||||
'<i class="grippy"></i> ' +
|
'<i class="grippy"></i> ' +
|
||||||
|
|
@ -1002,6 +1008,29 @@ function changeToEditMode() {
|
||||||
columnEditMode = false;
|
columnEditMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function editColumn(li) {
|
||||||
|
var id = li.attr('data-id');
|
||||||
|
var text = li.find('.text');
|
||||||
|
var textEdit = li.find('.text-edit');
|
||||||
|
var newName = textEdit.val().trim();
|
||||||
|
var url = li.attr('data-edit-url');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
type: 'PUT',
|
||||||
|
data: {custom_field: {name: newName}},
|
||||||
|
dataType: 'json',
|
||||||
|
success: function() {
|
||||||
|
text.text(newName);
|
||||||
|
$(table.columns().header()).filter('#' + id).text(newName);
|
||||||
|
cancelEditMode();
|
||||||
|
},
|
||||||
|
error: function(xhr) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// On edit buttons click (bind onto master dropdown list)
|
// On edit buttons click (bind onto master dropdown list)
|
||||||
dropdownList.on('click', '.edit:not(.disabled)', function(event) {
|
dropdownList.on('click', '.edit:not(.disabled)', function(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
@ -1040,28 +1069,19 @@ function changeToEditMode() {
|
||||||
// On ok buttons click
|
// On ok buttons click
|
||||||
dropdownList.on('click', '.ok', function(event) {
|
dropdownList.on('click', '.ok', function(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
var self = $(this);
|
var self = $(this);
|
||||||
var li = self.closest('li');
|
var li = self.closest('li');
|
||||||
var id = li.attr('data-id');
|
editColumn(li);
|
||||||
var text = li.find('.text');
|
});
|
||||||
var textEdit = li.find('.text-edit');
|
|
||||||
var newName = textEdit.val().trim();
|
|
||||||
|
|
||||||
$.ajax({
|
// On enter click while editing column text
|
||||||
url: '/organizations/1/custom_fields/' + id,
|
dropdownList.on('keydown', 'input.text-edit', function(event) {
|
||||||
type: 'PUT',
|
if (event.keyCode === 13) {
|
||||||
data: {custom_field: {name: newName}},
|
event.preventDefault();
|
||||||
dataType: 'json',
|
var self = $(this);
|
||||||
success: function() {
|
var li = self.closest('li');
|
||||||
text.text(newName);
|
editColumn(li);
|
||||||
$(table.columns().header()).filter('#' + id).text(newName);
|
}
|
||||||
cancelEditMode();
|
|
||||||
},
|
|
||||||
error: function(xhr) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// On cancel buttons click
|
// On cancel buttons click
|
||||||
|
|
@ -1080,6 +1100,90 @@ function changeToEditMode() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initDeleteColumns() {
|
||||||
|
var modal = $('#deleteCustomField');
|
||||||
|
|
||||||
|
dropdownList.on('click', '.del', function(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
var self = $(this);
|
||||||
|
var li = self.closest('li');
|
||||||
|
var url = li.attr('data-destroy-html-url');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
type: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
var modalBody = modal.find('.modal-body');
|
||||||
|
|
||||||
|
// Inject the body's HTML into modal
|
||||||
|
modalBody.html(data.html);
|
||||||
|
|
||||||
|
// Show the modal
|
||||||
|
modal.modal('show');
|
||||||
|
},
|
||||||
|
error: function(xhr) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.find('.modal-footer [data-action=delete]').on('click', function() {
|
||||||
|
var modalBody = modal.find('.modal-body');
|
||||||
|
var form = modalBody.find('[data-role=destroy-custom-field-form]');
|
||||||
|
var id = form.attr('data-id');
|
||||||
|
|
||||||
|
form
|
||||||
|
.on('ajax:success', function() {
|
||||||
|
// Destroy datatable
|
||||||
|
table.destroy();
|
||||||
|
|
||||||
|
// Subtract number of columns
|
||||||
|
$('#samples').data(
|
||||||
|
'num-columns',
|
||||||
|
$('#samples').data('num-columns') - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
// Remove column from table (=table header) & rows
|
||||||
|
var th = originalHeader.find('#' + id);
|
||||||
|
var index = th.index();
|
||||||
|
th.remove();
|
||||||
|
$('#samples tbody td:nth-child(' + (index + 1) + ')').remove();
|
||||||
|
|
||||||
|
// Remove all event handlers as we re-initialize them later with
|
||||||
|
// new table
|
||||||
|
$('#samples').off();
|
||||||
|
$('#samples thead').empty();
|
||||||
|
$('#samples thead').append(originalHeader);
|
||||||
|
|
||||||
|
// Preserve save/delete buttons as we need them after new table
|
||||||
|
// will be created
|
||||||
|
$('div.toolbarButtons').appendTo('div.samples-table');
|
||||||
|
$('div.toolbarButtons').hide();
|
||||||
|
|
||||||
|
// Re-initialize datatable
|
||||||
|
table = dataTableInit();
|
||||||
|
loadColumnsNames();
|
||||||
|
|
||||||
|
// Hide modal
|
||||||
|
modal.modal('hide');
|
||||||
|
})
|
||||||
|
.on('ajax:error', function() {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
form.submit();
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.on('hidden.bs.modal', function() {
|
||||||
|
// Remove event handlers, clear contents
|
||||||
|
var modalBody = modal.find('.modal-body');
|
||||||
|
modalBody.off();
|
||||||
|
modalBody.html('');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// initialze dropdown after the table is loaded
|
// initialze dropdown after the table is loaded
|
||||||
function initDropdown() {
|
function initDropdown() {
|
||||||
table.on('init.dt', function() {
|
table.on('init.dt', function() {
|
||||||
|
|
@ -1088,6 +1192,7 @@ function changeToEditMode() {
|
||||||
initSorting();
|
initSorting();
|
||||||
toggleColumnVisibility();
|
toggleColumnVisibility();
|
||||||
initEditColumns();
|
initEditColumns();
|
||||||
|
initDeleteColumns();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
class CustomFieldsController < ApplicationController
|
class CustomFieldsController < ApplicationController
|
||||||
before_action :load_vars, only: :update
|
before_action :load_vars, only: [:update, :destroy, :destroy_html]
|
||||||
before_action :load_vars_nested, only: [:create]
|
before_action :load_vars_nested, only: [:create, :destroy_html]
|
||||||
before_action :check_create_permissions, only: [:create]
|
before_action :check_create_permissions, only: :create
|
||||||
before_action :check_update_permissions, only: :update
|
before_action :check_update_permissions, only: :update
|
||||||
|
before_action :check_destroy_permissions, only: [:destroy, :destroy_html]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@custom_field = CustomField.new(custom_field_params)
|
@custom_field = CustomField.new(custom_field_params)
|
||||||
|
|
@ -14,7 +15,13 @@ class CustomFieldsController < ApplicationController
|
||||||
format.json do
|
format.json do
|
||||||
render json: {
|
render json: {
|
||||||
id: @custom_field.id,
|
id: @custom_field.id,
|
||||||
name: @custom_field.name
|
name: @custom_field.name,
|
||||||
|
edit_url:
|
||||||
|
organization_custom_field_path(@organization, @custom_field),
|
||||||
|
destroy_html_url:
|
||||||
|
organization_custom_field_destroy_html_path(
|
||||||
|
@organization, @custom_field
|
||||||
|
)
|
||||||
},
|
},
|
||||||
status: :ok
|
status: :ok
|
||||||
end
|
end
|
||||||
|
|
@ -41,10 +48,37 @@ class CustomFieldsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def destroy_html
|
||||||
|
respond_to do |format|
|
||||||
|
format.json do
|
||||||
|
render json: {
|
||||||
|
html: render_to_string(
|
||||||
|
partial: 'samples/delete_custom_field_modal_body.html.erb'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
respond_to do |format|
|
||||||
|
format.json do
|
||||||
|
if @custom_field.destroy
|
||||||
|
render json: { status: :ok }
|
||||||
|
else
|
||||||
|
render json: { status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_vars
|
def load_vars
|
||||||
@custom_field = CustomField.find_by_id(params[:id])
|
@custom_field = CustomField.find_by_id(params[:id])
|
||||||
|
@custom_field = CustomField.find_by_id(
|
||||||
|
params[:custom_field_id]
|
||||||
|
) unless @custom_field
|
||||||
render_404 unless @custom_field
|
render_404 unless @custom_field
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -61,6 +95,10 @@ class CustomFieldsController < ApplicationController
|
||||||
render_403 unless can_edit_custom_field(@custom_field)
|
render_403 unless can_edit_custom_field(@custom_field)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_destroy_permissions
|
||||||
|
render_403 unless can_delete_custom_field(@custom_field)
|
||||||
|
end
|
||||||
|
|
||||||
def custom_field_params
|
def custom_field_params
|
||||||
params.require(:custom_field).permit(:name)
|
params.require(:custom_field).permit(:name)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class CustomField < ActiveRecord::Base
|
||||||
belongs_to :last_modified_by,
|
belongs_to :last_modified_by,
|
||||||
foreign_key: 'last_modified_by_id',
|
foreign_key: 'last_modified_by_id',
|
||||||
class_name: 'User'
|
class_name: 'User'
|
||||||
has_many :sample_custom_fields, inverse_of: :custom_field
|
has_many :sample_custom_fields, inverse_of: :custom_field, dependent: :destroy
|
||||||
|
|
||||||
after_create :update_samples_table_state
|
after_create :update_samples_table_state
|
||||||
|
|
||||||
|
|
|
||||||
16
app/views/samples/_delete_custom_field_modal.html.erb
Normal file
16
app/views/samples/_delete_custom_field_modal.html.erb
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<div class="modal fade" id="deleteCustomField" tabindex="-1" role="dialog" aria-labelledby="deleteCustomFieldLabel">
|
||||||
|
<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"><%= t("samples.modal_delete_custom_field.title") %></h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-primary" data-action="delete"><%= t("samples.modal_delete_custom_field.delete") %></button>
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t("general.cancel")%></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
12
app/views/samples/_delete_custom_field_modal_body.html.erb
Normal file
12
app/views/samples/_delete_custom_field_modal_body.html.erb
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<%= bootstrap_form_for @custom_field, url: organization_custom_field_path(@organization, @custom_field, format: :json), remote: :true, method: :delete, data: { role: "destroy-custom-field-form", id: @custom_field.id } do |f| %>
|
||||||
|
<p><%= t("samples.modal_delete_custom_field.message", cf: @custom_field.name) %></p>
|
||||||
|
<div class="alert alert-danger" role="alert">
|
||||||
|
<span class="glyphicon glyphicon-exclamation-sign"></span>
|
||||||
|
|
||||||
|
<%= t("samples.modal_delete_custom_field.alert_heading") %>
|
||||||
|
<ul>
|
||||||
|
<li><%= t("samples.modal_delete_custom_field.alert_line_1", nr: @custom_field.sample_custom_fields.count) %></li>
|
||||||
|
<li><%= t("samples.modal_delete_custom_field.alert_line_2") %></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<%= render partial: "samples/import_samples_modal" %>
|
<%= render partial: "samples/import_samples_modal" %>
|
||||||
<%= render partial: "samples/delete_samples_modal" %>
|
<%= render partial: "samples/delete_samples_modal" %>
|
||||||
<%= render partial: "samples/create_sample_group_modal" %>
|
<%= render partial: "samples/create_sample_group_modal" %>
|
||||||
|
<%= render partial: "samples/delete_custom_field_modal" %>
|
||||||
<!-- Modal for parsing sample sheets should be empty at first -->
|
<!-- Modal for parsing sample sheets should be empty at first -->
|
||||||
<div class="modal fade" id="modal-parse-samples" tabindex="-1" role="dialog" aria-labelledby=="modal-parse-samples-label"></div>
|
<div class="modal fade" id="modal-parse-samples" tabindex="-1" role="dialog" aria-labelledby=="modal-parse-samples-label"></div>
|
||||||
|
|
||||||
|
|
@ -140,6 +141,8 @@
|
||||||
id="<%= cf.id %>"
|
id="<%= cf.id %>"
|
||||||
<%= 'data-editable' if can_edit_custom_field(cf) %>
|
<%= 'data-editable' if can_edit_custom_field(cf) %>
|
||||||
<%= 'data-deletable' if can_delete_custom_field(cf) %>
|
<%= 'data-deletable' if can_delete_custom_field(cf) %>
|
||||||
|
<%= "data-edit-url='#{organization_custom_field_path(@organization, cf)}'" %>
|
||||||
|
<%= "data-destroy-html-url='#{organization_custom_field_destroy_html_path(@organization, cf)}'" %>
|
||||||
>
|
>
|
||||||
<%= cf.name %>
|
<%= cf.name %>
|
||||||
</th>
|
</th>
|
||||||
|
|
|
||||||
|
|
@ -832,6 +832,13 @@ en:
|
||||||
modal_add_custom_field:
|
modal_add_custom_field:
|
||||||
title_html: "Add new column to team <strong>%{organization}</strong>"
|
title_html: "Add new column to team <strong>%{organization}</strong>"
|
||||||
create: "Add new column"
|
create: "Add new column"
|
||||||
|
modal_delete_custom_field:
|
||||||
|
title: "Delete a column"
|
||||||
|
message: "Are you sure you wish to permanently delete selected column %{cf}? This action is irreversible."
|
||||||
|
alert_heading: "Deleting a column has following consequences:"
|
||||||
|
alert_line_1: "you will lose information in this column for %{nr} samples;"
|
||||||
|
alert_line_2: "the column will be deleted for all team members."
|
||||||
|
delete: "Delete column"
|
||||||
modal_add_new_sample_group:
|
modal_add_new_sample_group:
|
||||||
title_html: "Add new sample group to team <strong>%{organization}</strong>"
|
title_html: "Add new sample group to team <strong>%{organization}</strong>"
|
||||||
create: "Add new sample group"
|
create: "Add new sample group"
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,9 @@ Rails.application.routes.draw do
|
||||||
get 'sample_group_element', to: 'sample_groups#sample_group_element'
|
get 'sample_group_element', to: 'sample_groups#sample_group_element'
|
||||||
get 'destroy_confirmation', to: 'sample_groups#destroy_confirmation'
|
get 'destroy_confirmation', to: 'sample_groups#destroy_confirmation'
|
||||||
end
|
end
|
||||||
resources :custom_fields, only: [:create, :update]
|
resources :custom_fields, only: [:create, :update, :destroy] do
|
||||||
|
get 'destroy_html'
|
||||||
|
end
|
||||||
member do
|
member do
|
||||||
post 'parse_sheet'
|
post 'parse_sheet'
|
||||||
post 'import_samples'
|
post 'import_samples'
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue