scinote-web/app/assets/javascripts/repositories/repository_datatable.js.erb

1360 lines
44 KiB
Text
Raw Normal View History

2017-06-23 14:50:12 +08:00
//= require jquery-ui/widgets/sortable
//= require repositories/forms/repository_item_edit.js
2017-06-06 23:35:29 +08:00
var RepositoryDatatable = (function(global) {
'use strict';
2017-06-06 23:35:29 +08:00
2018-07-19 23:56:42 +08:00
var TABLE_ID = '';
var TABLE = null;
/**
* This variable is declared on window object,
* it holds the objects of edited rows, probably we can use this also
* for multi row editing in the future.
*/
global.SCINOTE_REPOSITORY_EDITED_ROWS = []; // an array of edited rows
2017-06-06 23:35:29 +08:00
// 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();
2017-06-06 23:35:29 +08:00
}
}
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({
2019-07-29 22:39:23 +08:00
dom: "R<'row'<'col-sm-6 toolbar'l><'col-sm-6'f>><'row'<'col-sm-12't>><'row'<'col-sm-7'i><'col-sm-5'p>>",
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,
2017-06-06 23:35:29 +08:00
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'>";
2017-06-06 23:35:29 +08:00
}
}, {
// Assigned column is not searchable
targets: 1,
searchable: false,
orderable: true,
sWidth: '1%'
}, {
// Name column is clickable
targets: 3,
visible: true,
render: function(data, type, row) {
return "<a href='" + row.recordInfoUrl + "'" +
"class='record-info-link'>" + data + '</a>';
}
}],
oLanguage: {
2018-05-16 20:32:15 +08:00
sSearch: I18n.t('general.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');
2017-06-06 23:35:29 +08:00
}
},
2018-04-20 15:22:23 +08:00
<% # 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');
2018-04-20 15:22:23 +08:00
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();
FilePreviewModal.init();
// 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;
2018-04-20 15:22:23 +08:00
// 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);
2018-04-20 15:22:23 +08:00
// 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);
}
2018-04-20 15:22:23 +08:00
// 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();
FilePreviewModal.init();
initHeaderTooltip();
2017-06-06 23:35:29 +08:00
}
});
2017-06-06 23:35:29 +08:00
// 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');
}
});
2017-06-06 23:35:29 +08:00
TABLE.on('column-reorder', function() {
initRowSelection();
});
$('#assignRepositories, #unassignRepositories').click(function() {
2017-06-06 23:35:29 +08:00
animateLoading();
});
2017-06-06 23:35:29 +08:00
// Timeout for table header scrolling
setTimeout(function() {
TABLE.columns.adjust();
// Append button to inner toolbar in table
2019-07-29 22:39:23 +08:00
$('div.toolbarButtonsDatatable').appendTo('div.toolbar');
$('div.toolbarButtonsDatatable').show();
}, 10);
2017-06-06 23:35:29 +08:00
return TABLE;
}
2017-06-06 23:35:29 +08:00
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
2018-04-05 15:32:34 +08:00
$('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');
}
2017-06-06 23:35:29 +08:00
if (val) {
appendInput(form, val, 'header_ids[]');
}
});
2017-06-06 23:35:29 +08:00
// Append records
$.each(rowsSelected, function(index, rowId) {
appendInput(form, rowId, 'row_ids[]');
});
}
});
}
2017-06-06 22:12:34 +08:00
function disableCheckboxToggleOnAssetDownload() {
$('.file-preview-link').on('click', function(ev) {
ev.stopPropagation();
});
}
2017-06-06 22:12:34 +08:00
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)');
});
2017-06-06 22:12:34 +08:00
// 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();
2017-06-06 22:12:34 +08:00
});
}
2017-06-06 23:35:29 +08:00
// 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
2017-06-06 23:35:29 +08:00
} else {
chkboxSelectAll.checked = true;
if ('indeterminate' in chkboxSelectAll) {
chkboxSelectAll.indeterminate = true;
}
2017-06-06 23:35:29 +08:00
}
}
2017-06-06 23:35:29 +08:00
2018-06-29 16:29:39 +08:00
function checkAvailableColumns() {
$.ajax({
url: $(TABLE_ID).data('available-columns'),
type: 'GET',
dataType: 'json',
success: function(data) {
var columns_ids = data.columns;
var present_columns = $(TABLE_ID).data('repository-columns-ids');
2018-06-18 19:36:56 +08:00
if( !_.isEqual(columns_ids.sort(), present_columns.sort()) ) {
alert($(TABLE_ID).data('columns-changed'));
animateSpinner();
location.reload();
}
},
error: function(data) {
location.reload();
}
});
}
global.onClickAddRecord = function() {
2018-06-29 16:29:39 +08:00
checkAvailableColumns();
changeToEditMode();
updateButtons();
2017-06-06 23:35:29 +08:00
saveAction = 'create';
var tr = document.createElement('tr');
if (TABLE.column(1).visible() === false) {
TABLE.column(1).visible(true);
2017-06-06 23:35:29 +08:00
}
$('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'), '');
td = createTdElement(input);
tr.appendChild(td);
_addSelectedFile($(th).attr('data-type'), '', $(td).find('input')[0]);
} else {
// Column we don't care for, just add empty td
tr.appendChild(createTdElement(''));
}
});
$('table' + TABLE_ID).prepend(tr);
selectedRecord = tr;
2017-06-06 23:35:29 +08:00
// initialize smart annotation
_.each($('[data-object="repository_cell"]'), function(el) {
if (_.isUndefined($(el).data('atwho'))) {
SmartAnnotation.init(el);
}
});
// Init selectpicker
_initSelectPicker();
// Adjust columns width in table header
adjustTableHeader();
2017-06-06 23:35:29 +08:00
}
global.onClickToggleAssignedRecords = function() {
$('.repository-assign-group > .btn').click(function() {
2018-05-23 17:20:42 +08:00
$('.btn-group > .btn').removeClass('active btn-toggle');
$('.btn-group > .btn').addClass('btn-default');
2018-05-23 17:20:42 +08:00
$(this).addClass('active btn-toggle');
});
2017-06-06 23:35:29 +08:00
$('#assigned-repo-records').on('click', function() {
2018-02-15 18:06:59 +08:00
var promiseReload;
viewAssigned = 'assigned';
2018-02-15 18:06:59 +08:00
promiseReload = new Promise(function(resolve) {
resolve(TABLE.ajax.reload());
});
promiseReload.then(function() {
initRowSelection();
})
});
$('#all-repo-records').on('click', function() {
2018-02-15 18:06:59 +08:00
var promiseReload;
viewAssigned = 'all';
2018-02-15 18:06:59 +08:00
promiseReload = new Promise(function(resolve) {
resolve(TABLE.ajax.reload());
});
promiseReload.then(function() {
initRowSelection();
})
});
};
2017-06-06 23:35:29 +08:00
global.openAssignRecordsModal = function() {
$.post(
$('#assignRepositoryRecords').data('assign-url-modal'),
{ selected_rows: rowsSelected })
.done(
function(data) {
$(data.html).appendTo('body').promise().done(function() {
2018-04-26 20:13:46 +08:00
$('#assignRepositoryRecordModal').modal('show');
});
}
);
}
global.hideAssignUnasignModal = function(id) {
$(id).modal('hide').promise().done(
function() {
$(id).remove();
}
)
}
global.submitAssignRepositoryRecord = function(option) {
animateSpinner();
$.ajax({
2018-04-26 20:13:46 +08:00
url: $('#assignRepositoryRecordModal').data('assign-url'),
type: 'POST',
dataType: 'json',
data: { selected_rows: rowsSelected,
downstream: (option === 'downstream') },
success: function(data) {
2018-04-26 20:13:46 +08:00
hideAssignUnasignModal('#assignRepositoryRecordModal');
HelperModule.flashAlertMsg(data.flash, 'success');
onClickCancel();
clearRowSelection();
},
error: function(data) {
2018-04-26 20:13:46 +08:00
hideAssignUnasignModal('#assignRepositoryRecordModal');
HelperModule.flashAlertMsg(data.responseJSON.flash, 'danger');
onClickCancel();
clearRowSelection();
}
});
2017-06-07 19:36:39 +08:00
}
2017-06-06 23:35:29 +08:00
global.openUnassignRecordsModal = function() {
$.post(
$('#unassignRepositoryRecords').data('unassign-url'),
{ selected_rows: rowsSelected })
.done(
function(data) {
$(data.html).appendTo('body').promise().done(function() {
2018-04-26 20:13:46 +08:00
$('#unassignRepositoryRecordModal').modal('show');
});
}
);
}
global.submitUnassignRepositoryRecord = function(option) {
animateSpinner();
$.ajax({
2018-04-26 20:13:46 +08:00
url: $('#unassignRepositoryRecordModal').data('unassign-url'),
type: 'POST',
dataType: 'json',
data: { selected_rows: rowsSelected,
downstream: (option === 'downstream') },
success: function(data) {
2018-04-26 20:13:46 +08:00
hideAssignUnasignModal('#unassignRepositoryRecordModal');
HelperModule.flashAlertMsg(data.flash, 'success');
onClickCancel();
clearRowSelection();
},
error: function(data) {
2018-04-26 20:13:46 +08:00
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
);
}
2017-06-06 23:35:29 +08:00
}
});
}
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() {
2018-06-29 16:29:39 +08:00
checkAvailableColumns();
if (rowsSelected.length !== 1) {
return;
2017-06-06 23:35:29 +08:00
}
var row = TABLE.row('#' + rowsSelected[0]);
var node = row.node();
var rowData = row.data();
2017-06-06 23:35:29 +08:00
$(node).find('td input').trigger('click');
selectedRecord = node;
2017-06-06 23:35:29 +08:00
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);
2017-06-06 23:35:29 +08:00
}
// 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());
var editForm = new RepositoryItemEditForm(data, node);
editForm.renderForm(TABLE);
_initSelectPicker();
2018-07-04 23:38:16 +08:00
editForm.initializeSelectpickerValues(node);
// 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();
2017-06-06 23:35:29 +08:00
updateButtons();
SCINOTE_REPOSITORY_EDITED_ROWS.push(editForm);
},
error: function(e) {
if (e.status === 403) {
HelperModule.flashAlertMsg(
I18n.t('repositories.js.permission_error'), e.responseJSON.style
);
changeToViewMode();
updateButtons();
}
2017-06-06 23:35:29 +08:00
}
});
2017-06-06 23:35:29 +08:00
}
// Save record
global.onClickSave = function() {
var node;
var rowData;
var formData;
if (saveAction === 'update') {
var row = TABLE.row(selectedRecord);
node = row.node();
rowData = row.data();
formData = SCINOTE_REPOSITORY_EDITED_ROWS[0].parseToFormObject(
TABLE_ID, selectedRecord
);
} else if (saveAction === 'create') {
node = selectedRecord;
// First fetch all the data in input fields
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);
});
}
2017-06-06 23:35:29 +08:00
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();
SCINOTE_REPOSITORY_EDITED_ROWS = [];
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>');
}
2017-06-06 23:35:29 +08:00
}
}
// 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;
// handle custom input field
if(input.attr('type') === 'file') {
var container = input.closest('.repository-input-file-field');
$(container.find('.form-group')[0]).addClass('has-error');
container.addClass('has-error');
container.append("<span class='help-block'>" +
message + '<br /></span>');
} else {
input.closest('.form-group').addClass('has-error');
input.parent().append("<span class='help-block'>" +
message + '<br /></span>');
}
}
});
2017-06-06 23:35:29 +08:00
});
}
}
});
};
// Delete record
global.onClickDelete = function() {
$('#deleteRepositoryRecord').modal('show');
};
// Enable/disable edit button
function updateButtons() {
if (currentMode === 'viewMode') {
$('#addRepositoryRecord').removeClass('disabled');
$('#addRepositoryRecord').prop('disabled', false);
$('.dataTables_length select').prop('disabled', false);
$('#repository-acitons-dropdown').removeClass('disabled');
$('#repository-acitons-dropdown').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');
2018-04-05 15:32:34 +08:00
$('#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) {
2018-04-05 15:32:34 +08:00
$('#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);
2017-06-06 23:35:29 +08:00
}
} else if (currentMode === 'editMode') {
$('#repository-acitons-dropdown').addClass('disabled');
$('#repository-acitons-dropdown').prop('disabled', true);
$('.dataTables_length select').prop('disabled', true);
$('#addRepositoryRecord').addClass('disabled');
$('#addRepositoryRecord').prop('disabled', true);
2017-06-06 23:35:29 +08:00
$('#editRepositoryRecord').addClass('disabled');
$('#editRepositoryRecord').prop('disabled', true);
$('#addNewColumn').addClass('disabled');
$('#addNewColumn').prop('disabled', true);
2017-06-06 23:35:29 +08:00
$('#deleteRepositoryRecordsButton').addClass('disabled');
$('#deleteRepositoryRecordsButton').prop('disabled', true);
2017-06-06 22:12:34 +08:00
$('#exportRepositoriesButton').off('click');
$('#export-repositories').off('click');
2017-06-06 23:35:29 +08:00
$('#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);
2017-06-06 23:35:29 +08:00
}
}
// 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();
SCINOTE_REPOSITORY_EDITED_ROWS = [];
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;
}
2017-06-06 23:35:29 +08:00
});
// Helper functions
function _listItemDropdown(options, current_value, column_id) {
var html = '<select class="form-control selectpicker repository-dropdown" ';
html += 'data-abs-min-length="2" data-live-search="true" ';
html += 'data-container="body" 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') {
if (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'));
}).trigger('change.bs.select');
}
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) {
2018-07-09 18:54:02 +08:00
return "<div class='repository-input-file-field'>"+
"<div class='new-input-file-field-div'><div class='form-group'>" +
"<input type='file' class='form-control' data-object='" +
object + "' name='" + name + "' value='" + value + "'></div>" +
"<a onClick='clearFileInput(this)'>" +
"<i class='fas fa-times'></i>" +
2018-07-09 18:54:02 +08:00
"</a></div></div>";
}
global.clearFileInput = function (el) {
var parent = $(el).closest('div.repository-input-file-field');
var input = parent.find('input:file')[0];
// hide clear button
$(parent.find('a[data-action="removeAsset"]')[0]).hide();
// reset value
input.value = '';
// add flag
$(input).attr('remove', true);
// clear fileName
2018-07-04 21:23:41 +08:00
$(parent.find('.file-name-label')[0])
.text(I18n.t('general.file.no_file_chosen'));
$(parent.find('.form-group')[0]).removeClass('has-error');
parent.removeClass('has-error');
$(parent.find('.help-block')[0]).remove();
}
// 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;
2017-06-06 23:35:29 +08:00
}
// 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();
});
2017-06-06 23:35:29 +08:00
}
function changeToViewMode() {
currentMode = 'viewMode';
// Table specific stuff
TABLE.button(0).enable(true);
FilePreviewModal.init();
2017-06-06 23:35:29 +08:00
}
function changeToEditMode() {
currentMode = 'editMode';
// Table specific stuff
TABLE.button(0).enable(false);
}
function initHeaderTooltip() {
// Fix compatibility of fixed table header and column names modal-tooltip
$('.modal-tooltip').off();
$('.modal-tooltip').hover(function() {
var $tooltip = $(this).find('.modal-tooltiptext');
var offsetLeft = $tooltip.offset().left;
(offsetLeft + 200) > $(window).width() ? offsetLeft -= 150 : offsetLeft;
var offsetTop = $tooltip.offset().top;
$('body').append($tooltip);
$tooltip.css('background-color', '#d2d2d2');
$tooltip.css('border-radius', '6px');
$tooltip.css('color', '#333');
$tooltip.css('display', 'block');
$tooltip.css('left', offsetLeft + 'px');
$tooltip.css('padding', '5px');
$tooltip.css('position', 'absolute');
$tooltip.css('text-align', 'center');
$tooltip.css('top', offsetTop + 'px');
$tooltip.css('visibility', 'visible');
$tooltip.css('width', '200px');
$tooltip.css('word-wrap', 'break-word');
$(this).data('dropdown-tooltip', $tooltip);
}, function() {
$(this).append($(this).data('dropdown-tooltip'));
$(this).data('dropdown-tooltip').removeAttr('style');
});
}
/*
* Repository columns dropdown
*/
var dropdown, dropdownList;
2017-06-06 23:35:29 +08:00
// 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) {
2017-06-06 23:35:29 +08:00
if (index > 1) {
var colIndex = $(el).attr('data-column-index');
var visible = TABLE.column(colIndex).visible();
2017-06-06 23:35:29 +08:00
var visClass = (visible) ? 'fa-eye' : 'fa-eye-slash';
2017-06-06 23:35:29 +08:00
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').html(generateColumnNameTooltip(thederName));
if(thederName !== 'Name') {
listItem.find('.vis').addClass(visClass);
listItem.find('.vis')
.attr('title', $(TABLE_ID).data('columns-visibility-text'));
}
dropdownList.append(listItem);
2017-06-06 23:35:29 +08:00
}
});
// 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'));
2017-06-06 23:35:29 +08:00
if(column.header.id !== 'row-name') {
if (column.visible()) {
self.addClass('fa-eye-slash');
self.removeClass('fa-eye');
li.addClass('col-invisible');
column.visible(false);
TABLE.setColumnSearchable(column.index(), false);
} else {
self.addClass('fa-eye');
self.removeClass('fa-eye-slash');
li.removeClass('col-invisible');
column.visible(true);
TABLE.setColumnSearchable(column.index(), true);
}
2017-06-06 23:35:29 +08:00
}
// Re-filter/search if neccesary
var searchText = $('div.dataTables_filter input').val();
if (!_.isEmpty(searchText)) {
TABLE.search(searchText).draw();
2017-06-06 23:35:29 +08:00
}
initRowSelection();
FilePreviewModal.init();
2017-06-06 23:35:29 +08:00
});
}
function initSorting() {
dropdownList.sortable({
items: 'li:not(.repository-columns-list-template)',
2017-06-06 23:35:29 +08:00
cancel: '.new-repository-column',
axis: 'y',
update: function() {
var reorderer = TABLE.colReorder;
2017-06-06 23:35:29 +08:00
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();
initRowSelection();
2017-06-06 23:35:29 +08:00
}
});
2018-06-29 16:29:39 +08:00
$('.sorting').on('click', checkAvailableColumns);
2017-06-06 23:35:29 +08:00
}
// 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');
2017-06-06 23:35:29 +08:00
if ($.trim(name).length > maxLength) {
return '<div class="modal-tooltip">' +
truncateLongString(name, maxLength) +
2017-06-06 23:35:29 +08:00
'<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');
2017-06-06 23:35:29 +08:00
initSorting();
toggleColumnVisibility();
});
$('#repository-columns-dropdown').on('show.bs.dropdown', function() {
loadColumnsNames();
dropdownList.sortable('enable');
2018-06-29 16:29:39 +08:00
checkAvailableColumns();
2017-06-06 23:35:29 +08:00
});
$('#repository-columns-dropdown').on('shown.bs.dropdown', function() {
dropdownOverflow();
});
}
function init(id) {
TABLE_ID = id;
TABLE = dataTableInit();
initDropdown();
}
function destroy() {
2018-07-19 23:56:42 +08:00
if (TABLE !== null) {
TABLE.destroy();
TABLE = null;
}
TABLE_ID = '';
}
function redrawTableOnSidebarToggle() {
$('#sidebar-arrow').on('click', function() {
setTimeout(function() {
TABLE.draw();
}, 250);
});
}
return Object.freeze({
init: init,
destroy: destroy,
redrawTableOnSidebarToggle: redrawTableOnSidebarToggle
});
})(window);