mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-11-15 13:45:25 +08:00
ffddf3fd94
Fix editing of inventory rows with existing files [SCI-2394]
1252 lines
40 KiB
Text
1252 lines
40 KiB
Text
//= require jquery-ui/widgets/sortable
|
|
|
|
var RepositoryDatatable = (function(global) {
|
|
'use strict';
|
|
|
|
var TABLE_ID = '';
|
|
var TABLE = {};
|
|
|
|
// Extend datatables API with searchable options
|
|
// (http://stackoverflow.com/questions/39912395/datatables-dynamically-set-columns-searchable)
|
|
$.fn.dataTable.Api.register('isColumnSearchable()', function(colSelector) {
|
|
var idx = this.column(colSelector).index();
|
|
return this.settings()[0].aoColumns[idx].bSearchable;
|
|
});
|
|
$.fn.dataTable.Api
|
|
.register('setColumnSearchable()', function(colSelector, value) {
|
|
if (value !== this.isColumnSearchable(colSelector)) {
|
|
var idx = this.column(colSelector).index();
|
|
this.settings()[0].aoColumns[idx].bSearchable = value;
|
|
if (value === true) {
|
|
this.rows().invalidate();
|
|
}
|
|
}
|
|
return value;
|
|
});
|
|
|
|
var rowsSelected = [];
|
|
|
|
// Tells whether we're currently viewing or editing table
|
|
var currentMode = 'viewMode';
|
|
|
|
// Tells what action will execute by pressing on save button (update/create)
|
|
var saveAction = 'update';
|
|
var selectedRecord;
|
|
|
|
// Helps saving correct table state
|
|
var myData;
|
|
var loadFirstTime = true;
|
|
|
|
var originalHeader;
|
|
|
|
// Tells whether to filter only assigned repository records
|
|
var viewAssigned;
|
|
|
|
function dataTableInit() {
|
|
// Make a copy of original repository table header
|
|
originalHeader = $(TABLE_ID + ' thead').children().clone();
|
|
viewAssigned = 'assigned';
|
|
TABLE = $(TABLE_ID).DataTable({
|
|
dom: "R<'row'<'col-sm-9-custom toolbar'l><'col-sm-3-custom'f>>tpi",
|
|
stateSave: true,
|
|
processing: true,
|
|
serverSide: true,
|
|
sScrollX: '100%',
|
|
sScrollXInner: '100%',
|
|
scrollY: '64vh',
|
|
scrollCollapse: true,
|
|
colReorder: {
|
|
fixedColumnsLeft: 2,
|
|
realtime: false
|
|
},
|
|
destroy: true,
|
|
ajax: {
|
|
url: $(TABLE_ID).data('source'),
|
|
data: function(d) {
|
|
d.assigned = viewAssigned;
|
|
},
|
|
global: false,
|
|
type: 'POST'
|
|
},
|
|
columnDefs: [{
|
|
// Checkbox column needs special handling
|
|
targets: 0,
|
|
searchable: false,
|
|
orderable: false,
|
|
className: 'dt-body-center',
|
|
sWidth: '1%',
|
|
render: function() {
|
|
return "<input class='repository-row-selector' type='checkbox'>";
|
|
}
|
|
}, {
|
|
// Assigned column is not searchable
|
|
targets: 1,
|
|
searchable: false,
|
|
orderable: true,
|
|
sWidth: '1%'
|
|
}, {
|
|
// Name column is clickable
|
|
targets: 3,
|
|
render: function(data, type, row) {
|
|
return "<a href='" + row.recordInfoUrl + "'" +
|
|
"class='record-info-link'>" + data + '</a>';
|
|
}
|
|
}],
|
|
oLanguage: {
|
|
sSearch: "Filter:"
|
|
},
|
|
rowCallback: function(row, data) {
|
|
// Get row ID
|
|
var rowId = data.DT_RowId;
|
|
// If row ID is in the list of selected row IDs
|
|
if ($.inArray(rowId, rowsSelected) !== -1) {
|
|
$(row).find('input[type="checkbox"]').prop('checked', true);
|
|
$(row).addClass('selected');
|
|
}
|
|
},
|
|
<% # Next 2 options are provided by server-side default state
|
|
# (and get overriden once state load from server kicks in) %>
|
|
order: <%= default_table_order_as_js_array %>,
|
|
columns: (function() {
|
|
var numOfColumns = $(TABLE_ID).data('num-columns');
|
|
var columns = <%= default_table_columns %>;
|
|
for (var i = 0; i < numOfColumns; i++) {
|
|
if (columns[i] == undefined) {
|
|
// This should only occur for custom columns
|
|
columns[i] = { visible: true, searchable: true };
|
|
}
|
|
columns[i].data = String(i);
|
|
columns[i].defaultContent = '';
|
|
}
|
|
return columns;
|
|
})(),
|
|
fnDrawCallback: function() {
|
|
animateSpinner(this, false);
|
|
changeToViewMode();
|
|
updateButtons();
|
|
updateDataTableSelectAllCtrl();
|
|
// Prevent row toggling when selecting user smart annotation link
|
|
SmartAnnotation.preventPropagation('.atwho-user-popover');
|
|
|
|
// Show number of selected rows near pages info
|
|
$('#repository-table_info').append('<span id="selected_info"></span>');
|
|
$('#selected_info').html(' (' +
|
|
rowsSelected.length +
|
|
' entries selected)');
|
|
initRowSelection();
|
|
},
|
|
preDrawCallback: function() {
|
|
animateSpinner(this);
|
|
$('.record-info-link').off('click');
|
|
},
|
|
stateLoadCallback: function() {
|
|
// Send an Ajax request to the server to get the data. Note that
|
|
// this is a synchronous request since the data is expected back from the
|
|
// function
|
|
var repositoryId = $(TABLE_ID).data('repository-id');
|
|
$.ajax({
|
|
url: '/repositories/' + repositoryId + '/state_load',
|
|
data: {},
|
|
async: false,
|
|
dataType: 'json',
|
|
type: 'POST',
|
|
success: function(json) {
|
|
myData = json.state;
|
|
|
|
// Fix the order - convert it from index-keyed JS object that
|
|
// is returned from the server state into true JS array;
|
|
// e.g. {0: [2, 'asc'], 1: [3, 'desc']}
|
|
// is converted into [[2, 'asc'], [3, 'desc']]
|
|
myData.order = _.toArray(myData.order);
|
|
}
|
|
});
|
|
return myData;
|
|
},
|
|
stateSaveCallback: function(settings, data) {
|
|
// Send an Ajax request to the server with the state object
|
|
var repositoryId = $(TABLE_ID).data('repository-id');
|
|
// Save correct data
|
|
if (loadFirstTime === true) {
|
|
data = myData;
|
|
}
|
|
$.ajax({
|
|
url: '/repositories/' + repositoryId + '/state_save',
|
|
data: { state: data },
|
|
dataType: 'json',
|
|
type: 'POST'
|
|
});
|
|
loadFirstTime = false;
|
|
},
|
|
fnInitComplete: function(oSettings) {
|
|
// First two columns are fixed
|
|
TABLE.column(0).visible(true);
|
|
TABLE.column(1).visible(true);
|
|
|
|
// Reload correct column order and visibility (if you refresh page)
|
|
for (var i = 2; i < TABLE.columns()[0].length; i++) {
|
|
var visibility = false;
|
|
if (myData.columns && myData.columns[i]) {
|
|
visibility = myData.columns[i].visible;
|
|
}
|
|
if (typeof (visibility) === 'string') {
|
|
visibility = (visibility === 'true');
|
|
}
|
|
TABLE.column(i).visible(visibility);
|
|
TABLE.setColumnSearchable(i, visibility);
|
|
}
|
|
|
|
// Re-order table as per loaded state
|
|
if (myData.order) {
|
|
TABLE.order(myData.order);
|
|
TABLE.draw();
|
|
}
|
|
|
|
// Datatables triggers this action about 3 times
|
|
// sometimes on the first iteration the oSettings._colReorder is null
|
|
// and the fnOrder rises an error that breaks the table
|
|
// here I added a null guard for that case.
|
|
// @todo we need to find out why the tables are loaded multiple times
|
|
if( oSettings._colReorder ) {
|
|
oSettings._colReorder.fnOrder(myData.ColReorder);
|
|
}
|
|
initRowSelection();
|
|
bindExportActions();
|
|
disableCheckboxToggleOnAssetDownload();
|
|
initPreviewModal();
|
|
}
|
|
});
|
|
|
|
// Handle click on table cells with checkboxes
|
|
$(TABLE_ID).on('click', 'tbody td', function(e) {
|
|
if ($(e.target).is('.repository-row-selector')) {
|
|
// Skip if clicking on selector checkbox
|
|
return;
|
|
}
|
|
if (!$(e.target).is('.record-info-link')) {
|
|
// Skip if clicking on samples info link
|
|
$(this).parent().find('.repository-row-selector').trigger('click');
|
|
}
|
|
});
|
|
|
|
TABLE.on('column-reorder', function() {
|
|
initRowSelection();
|
|
});
|
|
|
|
$('#assignRepositories, #unassignRepositories').click(function() {
|
|
animateLoading();
|
|
});
|
|
|
|
// Timeout for table header scrolling
|
|
setTimeout(function() {
|
|
TABLE.columns.adjust();
|
|
|
|
// Append button to inner toolbar in table
|
|
$('div.toolbarButtons').appendTo('div.toolbar');
|
|
$('div.toolbarButtons').show();
|
|
}, 10);
|
|
|
|
return TABLE;
|
|
}
|
|
|
|
// Enables noSearchHidden plugin
|
|
$.fn.dataTable.defaults.noSearchHidden = true;
|
|
|
|
function bindExportActions() {
|
|
$('form#form-export').submit(function() {
|
|
var form = this;
|
|
if (currentMode === 'viewMode') {
|
|
// Remove all hidden fields
|
|
$(form).find('input[name=row_ids\\[\\]]').remove();
|
|
$(form).find('input[name=header_ids\\[\\]]').remove();
|
|
|
|
// Append visible column information
|
|
$('table' + TABLE_ID + ' thead tr th').each(function() {
|
|
var th = $(this);
|
|
var val;
|
|
switch ($(th).attr('id')) {
|
|
case 'checkbox':
|
|
val = -1;
|
|
break;
|
|
case 'assigned':
|
|
val = -2;
|
|
break;
|
|
case 'row-id':
|
|
val = -3;
|
|
break
|
|
case 'row-name':
|
|
val = -4;
|
|
break;
|
|
case 'added-by':
|
|
val = -5;
|
|
break;
|
|
case 'added-on':
|
|
val = -6;
|
|
break;
|
|
default:
|
|
val = th.attr('id');
|
|
}
|
|
|
|
if (val) {
|
|
appendInput(form, val, 'header_ids[]');
|
|
}
|
|
});
|
|
|
|
// Append records
|
|
$.each(rowsSelected, function(index, rowId) {
|
|
appendInput(form, rowId, 'row_ids[]');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
function disableCheckboxToggleOnAssetDownload() {
|
|
$('.file-preview-link').on('click', function(ev) {
|
|
ev.stopPropagation();
|
|
});
|
|
}
|
|
|
|
function appendInput(form, val, name) {
|
|
$(form).append(
|
|
$('<input>')
|
|
.attr('type', 'hidden')
|
|
.attr('name', name)
|
|
.val(val)
|
|
);
|
|
}
|
|
|
|
function initRowSelection() {
|
|
// Handle clicks on checkbox
|
|
$('.dt-body-center .repository-row-selector').change(function(e) {
|
|
if (currentMode !== 'viewMode') {
|
|
return false;
|
|
}
|
|
// Get row ID
|
|
var $row = $(this).closest('tr');
|
|
var data = TABLE.row($row).data();
|
|
var rowId = data.DT_RowId;
|
|
|
|
// Determine whether row ID is in the list of selected row IDs
|
|
var index = $.inArray(rowId, rowsSelected);
|
|
|
|
// If checkbox is checked and row ID is not in list of selected row IDs
|
|
if (this.checked && index === -1) {
|
|
rowsSelected.push(rowId);
|
|
// Otherwise, if checkbox is not checked and row ID is in list of selected row IDs
|
|
} else if (!this.checked && index !== -1) {
|
|
rowsSelected.splice(index, 1);
|
|
}
|
|
|
|
if (this.checked) {
|
|
$row.addClass('selected');
|
|
} else {
|
|
$row.removeClass('selected');
|
|
}
|
|
|
|
updateDataTableSelectAllCtrl();
|
|
|
|
e.stopPropagation();
|
|
updateButtons();
|
|
// Update number of selected records info
|
|
$('#selected_info').html(' (' + rowsSelected.length + ' entries selected)');
|
|
});
|
|
|
|
// Handle click on "Select all" control
|
|
$('.dataTables_scrollHead input[name="select_all"]').change(function(e) {
|
|
if (this.checked) {
|
|
$('.repository-row-selector:not(:checked)').trigger('click');
|
|
} else {
|
|
$('.repository-row-selector:checked').trigger('click');
|
|
}
|
|
// Prevent click event from propagating to parent
|
|
e.stopPropagation();
|
|
});
|
|
}
|
|
|
|
// Updates "Select all" control in a data table
|
|
function updateDataTableSelectAllCtrl() {
|
|
var $table = TABLE.table().node();
|
|
var $header = TABLE.table().header();
|
|
var $chkboxAll = $('.repository-row-selector', $table);
|
|
var $chkboxChecked = $('.repository-row-selector:checked', $table);
|
|
var chkboxSelectAll = $('input[name="select_all"]', $header).get(0);
|
|
|
|
// If none of the checkboxes are checked
|
|
if ($chkboxChecked.length === 0) {
|
|
chkboxSelectAll.checked = false;
|
|
if ('indeterminate' in chkboxSelectAll) {
|
|
chkboxSelectAll.indeterminate = false;
|
|
}
|
|
|
|
// If all of the checkboxes are checked
|
|
} else if ($chkboxChecked.length === $chkboxAll.length) {
|
|
chkboxSelectAll.checked = true;
|
|
if ('indeterminate' in chkboxSelectAll) {
|
|
chkboxSelectAll.indeterminate = false;
|
|
}
|
|
|
|
// If some of the checkboxes are checked
|
|
} else {
|
|
chkboxSelectAll.checked = true;
|
|
if ('indeterminate' in chkboxSelectAll) {
|
|
chkboxSelectAll.indeterminate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
global.onClickAddRecord = function() {
|
|
changeToEditMode();
|
|
updateButtons();
|
|
|
|
saveAction = 'create';
|
|
var tr = document.createElement('tr');
|
|
if (TABLE.column(1).visible() === false) {
|
|
TABLE.column(1).visible(true);
|
|
}
|
|
$('table' + TABLE_ID + ' thead tr').children('th').each(function() {
|
|
var th = $(this);
|
|
var td;
|
|
var input;
|
|
if ($(th).attr('id') === 'checkbox') {
|
|
td = createTdElement('');
|
|
$(td).html($('#saveRecord').clone());
|
|
tr.appendChild(td);
|
|
} else if ($(th).attr('id') === 'assigned') {
|
|
td = createTdElement('');
|
|
$(td).html($('#cancelSave').clone());
|
|
tr.appendChild(td);
|
|
} else if ($(th).attr('id') === 'row-name') {
|
|
input = changeToInputField('repository_row', 'name', '');
|
|
tr.appendChild(createTdElement(input));
|
|
} else if ($(th).hasClass('repository-column') &&
|
|
$(th).attr('data-type') === 'RepositoryTextValue') {
|
|
input = changeToInputField('repository_cell', th.attr('id'), '');
|
|
tr.appendChild(createTdElement(input));
|
|
} else if ($(th).hasClass('repository-column') &&
|
|
$(th).attr('data-type') === 'RepositoryListValue') {
|
|
input = initialListItemsRequest($(th).attr('id'));
|
|
tr.appendChild(createTdElement(input));
|
|
} else if ($(th).hasClass('repository-column') &&
|
|
$(th).attr('data-type') === 'RepositoryAssetValue') {
|
|
input = changeToInputFileField('repository_cell_file', th.attr('id'), '');
|
|
tr.appendChild(createTdElement(input));
|
|
} else {
|
|
// Column we don't care for, just add empty td
|
|
tr.appendChild(createTdElement(''));
|
|
}
|
|
});
|
|
|
|
$('table' + TABLE_ID).prepend(tr);
|
|
selectedRecord = tr;
|
|
|
|
// initialize smart annotation
|
|
_.each($('[data-object="repository_cell"]'), function(el) {
|
|
if (_.isUndefined($(el).data('atwho'))) {
|
|
SmartAnnotation.init(el);
|
|
}
|
|
});
|
|
// Adjust columns width in table header
|
|
adjustTableHeader();
|
|
// Init selectpicker
|
|
_initSelectPicker();
|
|
}
|
|
|
|
global.onClickToggleAssignedRecords = function() {
|
|
$('.repository-assign-group > .btn').click(function() {
|
|
$('.btn-group > .btn').removeClass('active btn-primary');
|
|
$('.btn-group > .btn').addClass('btn-default');
|
|
$(this).addClass('active btn-primary');
|
|
});
|
|
|
|
$('#assigned-repo-records').on('click', function() {
|
|
var promiseReload;
|
|
viewAssigned = 'assigned';
|
|
promiseReload = new Promise(function(resolve) {
|
|
resolve(TABLE.ajax.reload());
|
|
});
|
|
promiseReload.then(function() {
|
|
initRowSelection();
|
|
})
|
|
});
|
|
$('#all-repo-records').on('click', function() {
|
|
var promiseReload;
|
|
viewAssigned = 'all';
|
|
promiseReload = new Promise(function(resolve) {
|
|
resolve(TABLE.ajax.reload());
|
|
});
|
|
promiseReload.then(function() {
|
|
initRowSelection();
|
|
})
|
|
});
|
|
};
|
|
|
|
global.openAssignRecordsModal = function() {
|
|
$.post(
|
|
$('#assignRepositoryRecords').data('assign-url-modal'),
|
|
{ selected_rows: rowsSelected })
|
|
.done(
|
|
function(data) {
|
|
$(data.html).appendTo('body').promise().done(function() {
|
|
$('#assignRepositoryRecordModal').modal('show');
|
|
});
|
|
}
|
|
);
|
|
}
|
|
|
|
global.hideAssignUnasignModal = function(id) {
|
|
$(id).modal('hide').promise().done(
|
|
function() {
|
|
$(id).remove();
|
|
}
|
|
)
|
|
}
|
|
|
|
global.submitAssignRepositoryRecord = function(option) {
|
|
animateSpinner();
|
|
$.ajax({
|
|
url: $('#assignRepositoryRecordModal').data('assign-url'),
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: { selected_rows: rowsSelected,
|
|
downstream: (option === 'downstream') },
|
|
success: function(data) {
|
|
hideAssignUnasignModal('#assignRepositoryRecordModal');
|
|
HelperModule.flashAlertMsg(data.flash, 'success');
|
|
onClickCancel();
|
|
clearRowSelection();
|
|
},
|
|
error: function(data) {
|
|
hideAssignUnasignModal('#assignRepositoryRecordModal');
|
|
HelperModule.flashAlertMsg(data.responseJSON.flash, 'danger');
|
|
onClickCancel();
|
|
clearRowSelection();
|
|
}
|
|
});
|
|
}
|
|
|
|
global.openUnassignRecordsModal = function() {
|
|
$.post(
|
|
$('#unassignRepositoryRecords').data('unassign-url'),
|
|
{ selected_rows: rowsSelected })
|
|
.done(
|
|
function(data) {
|
|
$(data.html).appendTo('body').promise().done(function() {
|
|
$('#unassignRepositoryRecordModal').modal('show');
|
|
});
|
|
}
|
|
);
|
|
}
|
|
|
|
global.submitUnassignRepositoryRecord = function(option) {
|
|
animateSpinner();
|
|
$.ajax({
|
|
url: $('#unassignRepositoryRecordModal').data('unassign-url'),
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: { selected_rows: rowsSelected,
|
|
downstream: (option === 'downstream') },
|
|
success: function(data) {
|
|
hideAssignUnasignModal('#unassignRepositoryRecordModal');
|
|
HelperModule.flashAlertMsg(data.flash, 'success');
|
|
onClickCancel();
|
|
clearRowSelection();
|
|
},
|
|
error: function(data) {
|
|
hideAssignUnasignModal('#unassignRepositoryRecordModal');
|
|
HelperModule.flashAlertMsg(data.responseJSON.flash, 'danger');
|
|
onClickCancel();
|
|
clearRowSelection();
|
|
}
|
|
});
|
|
}
|
|
|
|
global.onClickDeleteRecord = function() {
|
|
animateSpinner();
|
|
$.ajax({
|
|
url: $('table' + TABLE_ID).data('delete-record'),
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: {selected_rows: rowsSelected},
|
|
success: function(data) {
|
|
HelperModule.flashAlertMsg(data.flash, data.color);
|
|
rowsSelected = [];
|
|
onClickCancel();
|
|
},
|
|
error: function(e) {
|
|
if (e.status === 403) {
|
|
HelperModule.flashAlertMsg(
|
|
I18n.t('repositories.js.permission_error'), e.responseJSON.style
|
|
);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
global.onClickCopyRepositoryRecords = function() {
|
|
animateSpinner();
|
|
$.ajax({
|
|
url: $('table' + TABLE_ID).data('copy-records'),
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: { selected_rows: rowsSelected },
|
|
success: function(data) {
|
|
HelperModule.flashAlertMsg(data.flash, 'success');
|
|
rowsSelected = [];
|
|
onClickCancel();
|
|
},
|
|
error: function(e) {
|
|
if (e.status === 403) {
|
|
HelperModule.flashAlertMsg(
|
|
I18n.t('repositories.js.permission_error'), e.responseJSON.style
|
|
);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Edit record
|
|
global.onClickEdit = function() {
|
|
if (rowsSelected.length !== 1) {
|
|
return;
|
|
}
|
|
|
|
var row = TABLE.row('#' + rowsSelected[0]);
|
|
var node = row.node();
|
|
var rowData = row.data();
|
|
|
|
$(node).find('td input').trigger('click');
|
|
selectedRecord = node;
|
|
|
|
clearAllErrors();
|
|
changeToEditMode();
|
|
updateButtons();
|
|
saveAction = 'update';
|
|
|
|
$.ajax({
|
|
url: rowData.recordEditUrl,
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
success: function(data) {
|
|
if (TABLE.column(1).visible() === false) {
|
|
TABLE.column(1).visible(true);
|
|
}
|
|
// Show save and cancel buttons in first two columns
|
|
$(node).children('td').eq(0).html($('#saveRecord').clone());
|
|
$(node).children('td').eq(1).html($('#cancelSave').clone());
|
|
|
|
// Record name column
|
|
var colIndex = getColumnIndex('#row-name');
|
|
if (colIndex) {
|
|
$(node).children('td').eq(colIndex)
|
|
.html(changeToInputField('repository_row', 'name',
|
|
data.repository_row.name));
|
|
}
|
|
|
|
// Take care of custom cells
|
|
var cells = data.repository_row.repository_cells;
|
|
var list_columns = data.repository_row.repository_column_items;
|
|
$(node).children('td').each(function(i) {
|
|
var td = $(this);
|
|
var rawIndex = TABLE.column.index('fromVisible', i);
|
|
var colHeader = TABLE.column(rawIndex).header();
|
|
if ($(colHeader).hasClass('repository-column')) {
|
|
var type = $(colHeader).attr('data-type');
|
|
// Check if cell on this record exists
|
|
var cell = cells[$(colHeader).attr('id')] || '';
|
|
td.html(changeToFormField('repository_cell',
|
|
$(colHeader).attr('id'),
|
|
type,
|
|
cell,
|
|
list_columns));
|
|
_addSelectedFile(type, cell, $(this).find('input')[0]);
|
|
_initSelectPicker();
|
|
}
|
|
});
|
|
|
|
// initialize smart annotation
|
|
_.each($('[data-object="repository_cell"]'), function(el) {
|
|
if (_.isUndefined($(el).data('atwho'))) {
|
|
SmartAnnotation.init(el);
|
|
}
|
|
});
|
|
// Adjust columns width in table header
|
|
adjustTableHeader();
|
|
updateButtons();
|
|
},
|
|
error: function(e) {
|
|
if (e.status === 403) {
|
|
HelperModule.flashAlertMsg(
|
|
I18n.t('repositories.js.permission_error'), e.responseJSON.style
|
|
);
|
|
changeToViewMode();
|
|
updateButtons();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Save record
|
|
global.onClickSave = function() {
|
|
var node;
|
|
var rowData;
|
|
if (saveAction === 'update') {
|
|
var row = TABLE.row(selectedRecord);
|
|
node = row.node();
|
|
rowData = row.data();
|
|
} else if (saveAction === 'create') {
|
|
node = selectedRecord;
|
|
}
|
|
// First fetch all the data in input fields
|
|
var formData = new FormData();
|
|
formData.append('request_url', $(TABLE_ID).data('current-uri'));
|
|
formData.append('repository_row_id', $(selectedRecord).attr('id'));
|
|
|
|
// Direct record attributes
|
|
// Record name
|
|
formData.append('repository_row_name', $('td input[data-object = repository_row]').val());
|
|
|
|
// Custom cells text type
|
|
$(node).find('td input[data-object = repository_cell]').each(function() {
|
|
// Send data only and only if cell is not empty
|
|
if ($(this).val().trim()) {
|
|
formData.append('repository_cells[' + $(this).attr('name') + ']', $(this).val());
|
|
}
|
|
});
|
|
// Custom cells file type
|
|
$(node).find('td input[data-object = repository_cell_file]').each(function() {
|
|
// Send data only and only if cell is not empty
|
|
if ($(this).context.files.length == 1 ) {
|
|
if ($(this).data('changed')) {
|
|
formData.append('repository_cells[' + $(this).attr('name') + ']',
|
|
$(this).context.files[0]);
|
|
} else {
|
|
formData.append('repository_cells[' + $(this).attr('name') + ']', '');
|
|
}
|
|
}
|
|
});
|
|
// Custom cells list type
|
|
$(node).find('td[column_id]').each(function(index, el) {
|
|
var value = $(el).attr('list_item_id');
|
|
formData.append('repository_cells[' + $(el).attr('column_id') + ']', value);
|
|
});
|
|
|
|
var url;
|
|
var type;
|
|
if (saveAction === 'update') {
|
|
url = rowData.recordUpdateUrl;
|
|
type = 'PUT';
|
|
} else {
|
|
type = 'POST';
|
|
url = $('table' + TABLE_ID).data('create-record');
|
|
}
|
|
$.ajax({
|
|
url: url,
|
|
type: type,
|
|
dataType: 'json',
|
|
data: formData,
|
|
processData: false,
|
|
contentType: false,
|
|
success: function(data) {
|
|
HelperModule.flashAlertMsg(data.flash, 'success');
|
|
SmartAnnotation.closePopup();
|
|
onClickCancel();
|
|
},
|
|
error: function(e) {
|
|
SmartAnnotation.closePopup();
|
|
var data = e.responseJSON;
|
|
clearAllErrors();
|
|
|
|
if (e.status === 404) {
|
|
HelperModule.flashAlertMsg(
|
|
I18n.t('repositories.js.not_found_error'), 'danger'
|
|
);
|
|
changeToViewMode();
|
|
updateButtons();
|
|
} else if (e.status === 403) {
|
|
HelperModule.flashAlertMsg(
|
|
I18n.t('repositories.js.permission_error'), 'danger'
|
|
);
|
|
changeToViewMode();
|
|
updateButtons();
|
|
} else if (e.status === 400) {
|
|
if (data.default_fields) {
|
|
var defaultFields = data.default_fields;
|
|
|
|
// Validate record name
|
|
if (defaultFields.name) {
|
|
var input = $(selectedRecord).find('input[name = name]');
|
|
|
|
if (input) {
|
|
input.closest('.form-group').addClass('has-error');
|
|
input.parent().append("<span class='help-block'>" +
|
|
defaultFields.name + '<br /></span>');
|
|
}
|
|
}
|
|
}
|
|
|
|
// Validate custom cells
|
|
$.each(data.repository_cells || [], function(key, val) {
|
|
$.each(val, function(key, val) {
|
|
var input = $(selectedRecord).find('input[name=' + key + ']');
|
|
if (input) {
|
|
var message = Array.isArray(val.data) ? val.data[0] : val.data;
|
|
input.closest('.form-group').addClass('has-error');
|
|
input.parent().append("<span class='help-block'>" +
|
|
message + '<br /></span>');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Enable/disable edit button
|
|
function updateButtons() {
|
|
if (currentMode === 'viewMode') {
|
|
$('#addRepositoryRecord').removeClass('disabled');
|
|
$('#addRepositoryRecord').prop('disabled', false);
|
|
$('#addNewColumn').removeClass('disabled');
|
|
$('#addNewColumn').prop('disabled', false);
|
|
$('#repository-columns-dropdown')
|
|
.find('.dropdown-toggle')
|
|
.prop('disabled', false);
|
|
$('th').removeClass('disable-click');
|
|
$('.repository-row-selector').removeClass('disabled');
|
|
$('.repository-row-selector').prop('disabled', false);
|
|
if (rowsSelected.length === 0) {
|
|
$('#copyRepositoryRecords').prop('disabled', true);
|
|
$('#copyRepositoryRecords').addClass('disabled');
|
|
$('#editRepositoryRecord').prop('disabled', true);
|
|
$('#editRepositoryRecord').addClass('disabled');
|
|
$('#deleteRepositoryRecordsButton').prop('disabled', true);
|
|
$('#deleteRepositoryRecordsButton').addClass('disabled');
|
|
$('#exportRepositoriesButton').parent('li').addClass('disabled');
|
|
$('#exportRepositoriesButton').prop('disabled', true);
|
|
$('#exportRepositoriesButton').off('click');
|
|
$('#export-repositories').off('click');
|
|
$('#assignRepositoryRecords').addClass('disabled');
|
|
$('#assignRepositoryRecords').prop('disabled', true);
|
|
$('#unassignRepositoryRecords').addClass('disabled');
|
|
$('#unassignRepositoryRecords').prop('disabled', true);
|
|
} else {
|
|
if (rowsSelected.length === 1 &&
|
|
$('#exportRepositoriesButton').get(0)) {
|
|
$('#editRepositoryRecord').prop('disabled', false);
|
|
$('#editRepositoryRecord').removeClass('disabled');
|
|
|
|
// If we switched from 2 selections to 1, then this is not needed
|
|
var events = $._data($('#exportRepositoriesButton').get(0), 'events');
|
|
if (!events || !events.click) {
|
|
$('#exportRepositoriesButton').parent('li').removeClass('disabled');
|
|
$('#exportRepositoriesButton').prop('disabled', false);
|
|
$('#exportRepositoriesButton').off('click').on('click', function() {
|
|
$('#exportRepositoryModal').modal('show');
|
|
});
|
|
$('#export-repositories').off('click').on('click', function() {
|
|
animateSpinner(null, true);
|
|
$('#form-export').submit();
|
|
});
|
|
}
|
|
} else {
|
|
$('#editRepositoryRecord').prop('disabled', true);
|
|
$('#editRepositoryRecord').addClass('disabled');
|
|
}
|
|
$('#deleteRepositoryRecordsButton').prop('disabled', false);
|
|
$('#deleteRepositoryRecordsButton').removeClass('disabled');
|
|
$('#copyRepositoryRecords').prop('disabled', false);
|
|
$('#copyRepositoryRecords').removeClass('disabled');
|
|
$('#assignRepositoryRecords').removeClass('disabled');
|
|
$('#assignRepositoryRecords').prop('disabled', false);
|
|
$('#unassignRepositoryRecords').removeClass('disabled');
|
|
$('#unassignRepositoryRecords').prop('disabled', false);
|
|
}
|
|
} else if (currentMode === 'editMode') {
|
|
$('#addRepositoryRecord').addClass('disabled');
|
|
$('#addRepositoryRecord').prop('disabled', true);
|
|
$('#editRepositoryRecord').addClass('disabled');
|
|
$('#editRepositoryRecord').prop('disabled', true);
|
|
$('#addNewColumn').addClass('disabled');
|
|
$('#addNewColumn').prop('disabled', true);
|
|
$('#deleteRepositoryRecordsButton').addClass('disabled');
|
|
$('#deleteRepositoryRecordsButton').prop('disabled', true);
|
|
$('#exportRepositoriesButton').addClass('disabled');
|
|
$('#exportRepositoriesButton').off('click');
|
|
$('#export-repositories').off('click');
|
|
$('#assignRepositoryRecords').addClass('disabled');
|
|
$('#assignRepositoryRecords').prop('disabled', true);
|
|
$('#unassignRepositoryRecords').addClass('disabled');
|
|
$('#unassignRepositoryRecords').prop('disabled', true);
|
|
$('#repository-columns-dropdown').find('.dropdown-toggle')
|
|
.prop('disabled', true);
|
|
$('th').addClass('disable-click');
|
|
$('.repository-row-selector').addClass('disabled');
|
|
$('.repository-row-selector').prop('disabled', true);
|
|
}
|
|
}
|
|
|
|
// Clear all has-error tags
|
|
function clearAllErrors() {
|
|
// Remove any validation errors
|
|
$(selectedRecord).find('.has-error').each(function() {
|
|
$(this).removeClass('has-error');
|
|
$(this).find('span').remove();
|
|
});
|
|
// Remove any alerts
|
|
$('#alert-container').find('div').remove();
|
|
}
|
|
|
|
function clearRowSelection() {
|
|
$('.dt-body-center .repository-row-selector').prop('checked', false);
|
|
$('.dt-body-center .repository-row-selector').closest('tr')
|
|
.removeClass('selected');
|
|
rowsSelected = [];
|
|
}
|
|
|
|
// Restore previous table
|
|
global.onClickCancel = function() {
|
|
if ($('#assigned').text().length === 0) {
|
|
TABLE.column(1).visible(false);
|
|
}
|
|
TABLE.ajax.reload(function() {
|
|
initRowSelection();
|
|
}, false);
|
|
changeToViewMode();
|
|
updateButtons();
|
|
SmartAnnotation.closePopup();
|
|
animateSpinner(null, false);
|
|
}
|
|
|
|
// Handle enter key
|
|
$(document).off('keypress').keypress(function(event) {
|
|
var keycode = (event.keyCode ? event.keyCode : event.which);
|
|
if (currentMode === 'editMode' && keycode === '13') {
|
|
$('#saveRecord').click();
|
|
return false;
|
|
}
|
|
});
|
|
|
|
// Helper functions
|
|
function _listItemDropdown(options, current_value, column_id) {
|
|
var html = '<select class="form-control selectpicker" ';
|
|
html += 'data-abs-min-length="2" data-live-search="true" ';
|
|
html += 'column_id="' + column_id +'">';
|
|
html += '<option value="-1"></option>';
|
|
$.each(options, function(index, value) {
|
|
var selected = (current_value === value[1]) ? 'selected' : '';
|
|
html += '<option value="' + value[0] + '" ' + selected + '>';
|
|
html += value[1] + '</option>';
|
|
});
|
|
html += '</select>';
|
|
return html;
|
|
}
|
|
|
|
function initialListItemsRequest(column_id) {
|
|
var massage_response = [];
|
|
$.ajax({
|
|
url: '<%= Rails.application.routes.url_helpers.repository_list_items_path %>',
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
async: false,
|
|
data: {
|
|
q: '',
|
|
column_id: column_id
|
|
}
|
|
}).done(function(data) {
|
|
$.each(data.list_items, function(index, el) {
|
|
massage_response.push([el.id, el.data]);
|
|
})
|
|
});
|
|
return _listItemDropdown(massage_response, '-1', column_id);
|
|
}
|
|
|
|
function _addSelectedFile(type, cell, input) {
|
|
if (type === 'RepositoryAssetValue' && cell.value != null) {
|
|
const dT = new ClipboardEvent('').clipboardData || // Firefox workaround exploiting https://bugzilla.mozilla.org/show_bug.cgi?id=1422655
|
|
new DataTransfer(); // specs compliant (as of March 2018 only Chrome)
|
|
dT.items.add(new File([_], cell.value.file_file_name));
|
|
input.files = dT.files;
|
|
$(input).on('change', function(){
|
|
this.dataset.changed = 'true';
|
|
});
|
|
}
|
|
}
|
|
|
|
function _initSelectPicker() {
|
|
$('.selectpicker')
|
|
.selectpicker({liveSearch: true})
|
|
.ajaxSelectPicker({
|
|
ajax: {
|
|
url: '<%= Rails.application.routes.url_helpers.repository_list_items_path %>',
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data: function () {
|
|
var params = {
|
|
q: '{{{q}}}',
|
|
column_id: $(this.valueOf().plugin.$element).attr('column_id')
|
|
};
|
|
|
|
return params;
|
|
}
|
|
},
|
|
locale: {
|
|
emptyTitle: 'Nothing selected'
|
|
},
|
|
preprocessData: function(data){
|
|
var items = [];
|
|
if(data.hasOwnProperty('list_items')){
|
|
items.push({
|
|
'value': '-1',
|
|
'text': '',
|
|
'disabled': false
|
|
});
|
|
$.each(data.list_items, function(index, el) {
|
|
items.push(
|
|
{
|
|
'value': el.id,
|
|
'text': el.data,
|
|
'disabled': false
|
|
}
|
|
)
|
|
});
|
|
}
|
|
return items;
|
|
},
|
|
emptyRequest: true,
|
|
clearOnEmpty: false,
|
|
preserveSelected: false
|
|
}).on('change.bs.select', function(el) {
|
|
$(this).closest('td').attr('list_item_id', el.target.value);
|
|
$(this).closest('td').attr('column_id', $(this).attr('column_id'));
|
|
});;
|
|
}
|
|
|
|
function getColumnIndex(id) {
|
|
if (id < 0) {
|
|
return false;
|
|
}
|
|
return TABLE.column(id).index('visible');
|
|
}
|
|
|
|
// Takes object and surrounds it with input
|
|
function changeToInputField(object, name, value) {
|
|
return "<div class='form-group'><input class='form-control' data-object='" +
|
|
object + "' name='" + name + "' value='" + value + "'></input></div>";
|
|
}
|
|
|
|
// Takes object and surrounds it with input
|
|
function changeToInputFileField(object, name, value) {
|
|
return "<div class='form-group'><input type='file' class='form-control' data-object='" +
|
|
object + "' name='" + name + "' value='" + value + "'></input></div>";
|
|
}
|
|
|
|
// Takes an object and creates custom html element
|
|
function changeToFormField(object, name, column_type, cell, list_columns) {
|
|
var value = cell.value || '';
|
|
if (column_type === 'RepositoryListValue') {
|
|
var column = _.findWhere(list_columns, { column_id: parseInt(name) });
|
|
var list_items = column.list_items || cell.list_items;
|
|
return _listItemDropdown(list_items, value, parseInt(name));
|
|
} else if (column_type === 'RepositoryAssetValue') {
|
|
return changeToInputFileField('repository_cell_file', name, value);
|
|
} else {
|
|
return changeToInputField(object, name, value);
|
|
}
|
|
}
|
|
|
|
// Return td element with content
|
|
function createTdElement(content) {
|
|
var td = document.createElement('td');
|
|
td.innerHTML = content;
|
|
return td;
|
|
}
|
|
|
|
// Adjust columns width in table header
|
|
function adjustTableHeader() {
|
|
TABLE.columns.adjust();
|
|
$('.dropdown-menu').parent()
|
|
.on('shown.bs.dropdown hidden.bs.dropdown', function() {
|
|
TABLE.columns.adjust();
|
|
});
|
|
}
|
|
|
|
function changeToViewMode() {
|
|
currentMode = 'viewMode';
|
|
// Table specific stuff
|
|
TABLE.button(0).enable(true);
|
|
}
|
|
|
|
function changeToEditMode() {
|
|
currentMode = 'editMode';
|
|
// Table specific stuff
|
|
TABLE.button(0).enable(false);
|
|
}
|
|
|
|
/*
|
|
* Repository columns dropdown
|
|
*/
|
|
|
|
var dropdown, dropdownList;
|
|
|
|
// loads the columns names in the dropdown list
|
|
function loadColumnsNames() {
|
|
// Save scroll position
|
|
var scrollPosition = dropdownList.scrollTop();
|
|
// Clear the list
|
|
dropdownList.find('li[data-position]').remove();
|
|
_.each(TABLE.columns().header(), function(el, index) {
|
|
if (index > 1) {
|
|
var colIndex = $(el).attr('data-column-index');
|
|
var visible = TABLE.column(colIndex).visible();
|
|
|
|
var visClass = (visible) ? 'glyphicon-eye-open' : 'glyphicon-eye-close';
|
|
var visLi = (visible) ? '' : 'col-invisible';
|
|
|
|
var thederName;
|
|
if ($(el).find('.modal-tooltiptext').length > 0) {
|
|
thederName = $(el).find('.modal-tooltiptext').text();
|
|
} else {
|
|
thederName = el.innerText;
|
|
}
|
|
|
|
var listItem = dropdownList
|
|
.find('.repository-columns-list-template')
|
|
.clone();
|
|
|
|
listItem.attr('data-position', colIndex);
|
|
listItem.attr('data-id', $(el).attr('id'));
|
|
listItem.addClass(visLi);
|
|
listItem.removeClass('repository-columns-list-template hide');
|
|
listItem.find('.text').text(generateColumnNameTooltip(thederName));
|
|
listItem.find('.vis').addClass(visClass);
|
|
listItem.find('.vis')
|
|
.attr('title', $(TABLE_ID).data('columns-visibility-text'));
|
|
|
|
dropdownList.append(listItem);
|
|
}
|
|
});
|
|
// Restore scroll position
|
|
dropdownList.scrollTop(scrollPosition);
|
|
toggleColumnVisibility();
|
|
// toggles grip img
|
|
customLiHoverEffect();
|
|
}
|
|
|
|
function customLiHoverEffect() {
|
|
var liEl = dropdownList.find('li');
|
|
liEl.mouseover(function() {
|
|
$(this)
|
|
.find('.grippy')
|
|
.addClass('grippy-img');
|
|
}).mouseout(function() {
|
|
$(this)
|
|
.find('.grippy')
|
|
.removeClass('grippy-img');
|
|
});
|
|
}
|
|
|
|
function toggleColumnVisibility() {
|
|
var lis = dropdownList.find('.vis');
|
|
lis.on('click', function(event) {
|
|
event.stopPropagation();
|
|
var self = $(this);
|
|
var li = self.closest('li');
|
|
var column = TABLE.column(li.attr('data-position'));
|
|
|
|
if (column.visible()) {
|
|
self.addClass('glyphicon-eye-close');
|
|
self.removeClass('glyphicon-eye-open');
|
|
li.addClass('col-invisible');
|
|
column.visible(false);
|
|
TABLE.setColumnSearchable(column.index(), false);
|
|
} else {
|
|
self.addClass('glyphicon-eye-open');
|
|
self.removeClass('glyphicon-eye-close');
|
|
li.removeClass('col-invisible');
|
|
column.visible(true);
|
|
TABLE.setColumnSearchable(column.index(), true);
|
|
}
|
|
|
|
// Re-filter/search if neccesary
|
|
var searchText = $('div.dataTables_filter input').val();
|
|
if (!_.isEmpty(searchText)) {
|
|
TABLE.search(searchText).draw();
|
|
}
|
|
initRowSelection();
|
|
initPreviewModal();
|
|
});
|
|
}
|
|
|
|
function initSorting() {
|
|
dropdownList.sortable({
|
|
items: 'li:not(.repository-columns-list-template)',
|
|
cancel: '.new-repository-column',
|
|
axis: 'y',
|
|
update: function() {
|
|
var reorderer = TABLE.colReorder;
|
|
var listIds = [];
|
|
// We skip first two columns
|
|
listIds.push(0, 1);
|
|
dropdownList.find('li[data-position]').each(function() {
|
|
listIds.push($(this).first().data('position'));
|
|
});
|
|
reorderer.order(listIds, false);
|
|
loadColumnsNames();
|
|
}
|
|
});
|
|
}
|
|
|
|
// calculate the max height of window and adjust dropdown max-height
|
|
function dropdownOverflow() {
|
|
var windowHeight = $(window).height();
|
|
var offset = windowHeight - dropdownList.offset().top;
|
|
|
|
if (dropdownList.height() >= offset) {
|
|
dropdownList.css('maxHeight', offset);
|
|
}
|
|
}
|
|
|
|
function generateColumnNameTooltip(name) {
|
|
var maxLength = $(TABLE_ID).data('max-dropdown-length');
|
|
if ($.trim(name).length > maxLength) {
|
|
return '<div class="modal-tooltip">' +
|
|
truncateLongString(name, maxLength) +
|
|
'<span class="modal-tooltiptext">' + name + '</span></div>';
|
|
}
|
|
return name;
|
|
}
|
|
|
|
// initialze dropdown after the table is loaded
|
|
function initDropdown() {
|
|
TABLE.on('init.dt', function() {
|
|
dropdown = $('#repository-columns-dropdown');
|
|
dropdownList = $('#repository-columns-list');
|
|
initSorting();
|
|
toggleColumnVisibility();
|
|
});
|
|
$('#repository-columns-dropdown').on('show.bs.dropdown', function() {
|
|
loadColumnsNames();
|
|
dropdownList.sortable('enable');
|
|
});
|
|
|
|
$('#repository-columns-dropdown').on('shown.bs.dropdown', function() {
|
|
dropdownOverflow();
|
|
});
|
|
}
|
|
|
|
function init(id) {
|
|
TABLE_ID = id;
|
|
TABLE = dataTableInit();
|
|
initDropdown();
|
|
}
|
|
|
|
function destroy() {
|
|
TABLE = {};
|
|
TABLE_ID = '';
|
|
}
|
|
|
|
return Object.freeze({
|
|
init: init,
|
|
destroy: destroy
|
|
});
|
|
})(window);
|