- New delete "linked connection" options added to the "signature table", closed #803
- Fixed a bug where "signature reader" updates don´t respect changed sig. `groupId` changes, closed #838 - Fixed some minor CSS glitches in "modals/popups" - Upgraded "[_BootboxJS_](http://bootboxjs.com)" js lib `v4.4.0` → `v5.2.0` - Upgraded "[_hoverIntent_](http://briancherne.github.io/jquery-hoverIntent/)" js lib `v1.9.0` → `v1.10.0`
This commit is contained in:
@@ -18,7 +18,8 @@ Mapping tool for [*EVE ONLINE*](https://www.eveonline.com)
|
||||
- [wiki](https://github.com/exodus4d/pathfinder/wiki)
|
||||
- Developer [Slack](https://slack.com) chat:
|
||||
- https://pathfinder-eve-online.slack.com
|
||||
- Please send me a mail for invite: pathfinder@exodus4d.de
|
||||
- Join channel [pathfinder-eve-online.slack.com](https://join.slack.com/t/pathfinder-eve-online/shared_invite/enQtMzMyOTkyMjczMTA3LWI2NGE1OTY5ODBmNDZlMDY3MDIzYjk5ZTljM2JjZjIwNDRkNzMyMTEwMDUzOGQwM2E3ZjE1NGEwNThlMzYzY2Y)
|
||||
- Can´t join? pathfinder@exodus4d.de
|
||||
|
||||
**Feel free to check the code for bugs and security issues.
|
||||
Issues should be reported in the [Issue](https://github.com/exodus4d/pathfinder/issues) section.**
|
||||
@@ -49,7 +50,7 @@ Issues should be reported in the [Issue](https://github.com/exodus4d/pathfinder/
|
||||
|-- app.js --> require.js config (!required for production!)
|
||||
|-- [0777] logs/ --> log files
|
||||
|-- ...
|
||||
| -- node_modules/ --> node.js modules (not used for production)
|
||||
|-- node_modules/ --> node.js modules (not used for production)
|
||||
|-- ...
|
||||
|-- [0755] public/ --> frontend source
|
||||
|-- css/ --> CSS dist/build folder (minified)
|
||||
|
||||
@@ -56,7 +56,7 @@ class Signature extends AbstractRestController {
|
||||
$data['groupId'] == 5 ||
|
||||
$data['typeId'] == 0
|
||||
){
|
||||
unset( $data['typeId'] );
|
||||
unset($data['typeId']);
|
||||
}
|
||||
|
||||
// "sig reader" should not overwrite signature group information
|
||||
@@ -65,6 +65,7 @@ class Signature extends AbstractRestController {
|
||||
$signature->groupId > 0
|
||||
){
|
||||
unset($data['groupId']);
|
||||
unset($data['typeId']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,13 +79,20 @@ class Signature extends AbstractRestController {
|
||||
|
||||
// delete "old" signatures ----------------------------------------------------------------------------
|
||||
if((bool)$requestData['deleteOld']){
|
||||
// if linked ConnectionModels should be deleted as well
|
||||
$deleteConnectionId = (bool)$requestData['deleteConnection'];
|
||||
|
||||
$updatedSignatureIds = array_column($signaturesData, 'id');
|
||||
$signatures = $system->getSignatures();
|
||||
foreach($signatures as $signature){
|
||||
if(!in_array($signature->_id, $updatedSignatureIds)){
|
||||
// set if potential linked ConnectionModel should be deleted as well
|
||||
$signature->virtual('connectionIdDeleteCascade', $deleteConnectionId);
|
||||
if($signature->delete()){
|
||||
$updateSignaturesHistory = true;
|
||||
}
|
||||
// clear temp virtual field as well
|
||||
$signature->clearVirtual('connectionIdDeleteCascade');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,6 +198,9 @@ class Signature extends AbstractRestController {
|
||||
$system->getById($systemId);
|
||||
|
||||
if($system->hasAccess($activeCharacter)){
|
||||
// if linked ConnectionModels should be deleted as well
|
||||
$deleteConnectionId = (bool)$requestData['deleteConnection'];
|
||||
|
||||
// if there is any changed/deleted/updated signature
|
||||
// -> we need to update signature history data for the system
|
||||
$updateSignaturesHistory = false;
|
||||
@@ -202,11 +213,15 @@ class Signature extends AbstractRestController {
|
||||
$signature->getById($signatureId);
|
||||
// make sure signature belongs to main system (user has access)
|
||||
if($signature->get('systemId', true) == $systemId){
|
||||
// set if potential linked ConnectionModel should be deleted as well
|
||||
$signature->virtual('connectionIdDeleteCascade', $deleteConnectionId);
|
||||
if($signature->delete()){
|
||||
$deletedSignatureIds[] = $signatureId;
|
||||
$updateSignaturesHistory = true;
|
||||
}
|
||||
$signature->reset();
|
||||
// clear temp virtual field as well
|
||||
$signature->clearVirtual('connectionIdDeleteCascade');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -278,6 +278,13 @@ class SystemSignatureModel extends AbstractMapTrackingModel {
|
||||
*/
|
||||
public function afterEraseEvent($self, $pkeys){
|
||||
$self->logActivity('signatureDelete');
|
||||
|
||||
if(
|
||||
$self->connectionIdDeleteCascade === true &&
|
||||
($connection = $self->getConnection())
|
||||
){
|
||||
$connection->erase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,11 +42,11 @@ requirejs.config({
|
||||
xEditable: 'lib/bootstrap-editable.min', // v1.5.1 X-editable - in placed editing
|
||||
morris: 'lib/morris.min', // v0.5.1 Morris.js - graphs and charts
|
||||
raphael: 'lib/raphael.min', // v2.2.8 Raphaël - required for morris - https://dmitrybaranovskiy.github.io/raphael
|
||||
bootbox: 'lib/bootbox.min', // v4.4.0 Bootbox.js - custom dialogs - http://bootboxjs.com
|
||||
bootbox: 'lib/bootbox.min', // v5.2.0 Bootbox.js - custom dialogs - http://bootboxjs.com
|
||||
easyPieChart: 'lib/jquery.easypiechart.min', // v2.1.6 Easy Pie Chart - HTML 5 pie charts - http://rendro.github.io/easy-pie-chart
|
||||
peityInlineChart: 'lib/jquery.peity.min', // v3.2.1 Inline Chart - http://benpickles.github.io/peity/
|
||||
dragToSelect: 'lib/jquery.dragToSelect', // v1.1 Drag to Select - http://andreaslagerkvist.com/jquery/drag-to-select
|
||||
hoverIntent: 'lib/jquery.hoverIntent.min', // v1.9.0 Hover intention - http://cherne.net/brian/resources/jquery.hoverIntent.html
|
||||
hoverIntent: 'lib/jquery.hoverIntent.min', // v1.10.0 Hover intention - http://cherne.net/brian/resources/jquery.hoverIntent.html
|
||||
select2: 'lib/select2.min', // v4.0.3 Drop Down customization - https://select2.github.io
|
||||
validator: 'lib/validator.min', // v0.10.1 Validator for Bootstrap 3 - https://github.com/1000hz/bootstrap-validator
|
||||
lazylinepainter: 'lib/jquery.lazylinepainter-1.5.1.min', // v1.5.1 SVG line animation plugin - http://lazylinepainter.info
|
||||
|
||||
@@ -45,6 +45,7 @@ define([
|
||||
table.destroyTimestampCounter(true);
|
||||
});
|
||||
|
||||
// Status Plugin ==============================================================================================
|
||||
let StatusTable = function(settings){
|
||||
let me = this;
|
||||
me.statusContainer = $('<div>', {
|
||||
|
||||
@@ -141,15 +141,14 @@ define([
|
||||
|
||||
// show Cookie accept hint on SSO login button
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'bottom',
|
||||
btnOkClass: 'btn btn-sm btn-default',
|
||||
btnOkLabel: 'dismiss',
|
||||
btnOkIcon: 'fas fa-fw fa-sign-in-alt',
|
||||
title: 'Accept cookies',
|
||||
btnCancelClass: 'btn btn-sm btn-success',
|
||||
btnCancelLabel: 'accept',
|
||||
btnCancelIcon: 'fas fa-fw fa-check',
|
||||
btnOkClass: 'btn btn-sm btn-default',
|
||||
btnOkLabel: 'dismiss',
|
||||
btnOkIcon: 'fas fa-fw fa-sign-in-alt',
|
||||
onCancel: function(e, target){
|
||||
// "Accept cookies"
|
||||
setAcceptCookie();
|
||||
|
||||
@@ -31,6 +31,9 @@ define([
|
||||
// set default dialog config
|
||||
Util.initDefaultBootboxConfig();
|
||||
|
||||
// set default confirmation popover config
|
||||
Util.initDefaultConfirmationConfig();
|
||||
|
||||
// set default select2 config
|
||||
Util.initDefaultSelect2Config();
|
||||
|
||||
|
||||
@@ -853,6 +853,10 @@ define([
|
||||
let modalElement = $(e.target);
|
||||
modalElement.destroyTimestampCounter(true);
|
||||
|
||||
// destroy all form validators
|
||||
// -> does not work properly. validation functions still used (js error) after 'destroy'
|
||||
//modalElement.find('form').filter((i, form) => $(form).data('bs.validator')).validator('destroy');
|
||||
|
||||
// destroy all popovers
|
||||
modalElement.find('.' + Util.config.popoverTriggerClass).popover('destroy');
|
||||
|
||||
|
||||
@@ -77,11 +77,9 @@ define([
|
||||
|
||||
// show "discard" changes confirmation
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'top',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
title: 'discard changes',
|
||||
btnCancelIcon: '',
|
||||
btnOkClass: 'btn btn-sm btn-warning',
|
||||
btnOkLabel: 'discard',
|
||||
btnOkIcon: 'fas fa-fw fa-ban',
|
||||
|
||||
@@ -56,18 +56,6 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
// confirmation dialog settings (e.g. delete row)
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times'
|
||||
};
|
||||
|
||||
/**
|
||||
* get icon that marks a table cell as clickable
|
||||
* @returns {string}
|
||||
@@ -456,44 +444,49 @@ define([
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let tempTableElement = this;
|
||||
|
||||
let tempConfirmationSettings = confirmationSettings;
|
||||
tempConfirmationSettings.title = 'Delete system';
|
||||
tempConfirmationSettings.onConfirm = function(e, target){
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
let confirmationSettings = {
|
||||
placement: 'left',
|
||||
title: 'Delete system',
|
||||
template: Util.getConfirmationTemplate(null, {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm: function(e, target){
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
let systemElement = $('#' + MapUtil.getSystemId(mapData.config.id, rowData.id) );
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
let systemElement = $('#' + MapUtil.getSystemId(mapData.config.id, rowData.id) );
|
||||
|
||||
if(systemElement.length){
|
||||
// trigger system delete event
|
||||
activeMap.trigger('pf:deleteSystems', [{
|
||||
systems: [systemElement[0]],
|
||||
callback: function(deletedSystems){
|
||||
// callback function after ajax "delete" success
|
||||
// check if system was deleted
|
||||
if(deletedSystems.length === 1){
|
||||
// remove table row
|
||||
tempTableElement.DataTable().rows(deleteRowElement).remove().draw();
|
||||
if(systemElement.length){
|
||||
// trigger system delete event
|
||||
activeMap.trigger('pf:deleteSystems', [{
|
||||
systems: [systemElement[0]],
|
||||
callback: function(deletedSystems){
|
||||
// callback function after ajax "delete" success
|
||||
// check if system was deleted
|
||||
if(deletedSystems.length === 1){
|
||||
// remove table row
|
||||
tempTableElement.DataTable().rows(deleteRowElement).remove().draw();
|
||||
|
||||
Util.showNotify({title: 'System deleted', text: rowData.name, type: 'success'});
|
||||
Util.showNotify({title: 'System deleted', text: rowData.name, type: 'success'});
|
||||
|
||||
// refresh connection table (connections might have changed) --------------
|
||||
let connectionsElement = $('#' + config.mapInfoConnectionsId);
|
||||
let mapDataNew = activeMap.getMapDataFromClient(['hasId']);
|
||||
// refresh connection table (connections might have changed) --------------
|
||||
let connectionsElement = $('#' + config.mapInfoConnectionsId);
|
||||
let mapDataNew = activeMap.getMapDataFromClient(['hasId']);
|
||||
|
||||
connectionsElement.initConnectionInfoTable(mapDataNew);
|
||||
}else{
|
||||
// error
|
||||
Util.showNotify({title: 'Failed to delete system', text: rowData.name, type: 'error'});
|
||||
connectionsElement.initConnectionInfoTable(mapDataNew);
|
||||
}else{
|
||||
// error
|
||||
Util.showNotify({title: 'Failed to delete system', text: rowData.name, type: 'error'});
|
||||
}
|
||||
}
|
||||
}
|
||||
}]);
|
||||
}]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// init confirmation dialog
|
||||
$(cell).confirmation(tempConfirmationSettings);
|
||||
|
||||
$(cell).confirmation(confirmationSettings);
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -652,23 +645,29 @@ define([
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let tempTableElement = this;
|
||||
|
||||
let tempConfirmationSettings = confirmationSettings;
|
||||
tempConfirmationSettings.title = 'Delete connection';
|
||||
tempConfirmationSettings.onConfirm = function(e, target){
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
let confirmationSettings = {
|
||||
placement: 'left',
|
||||
title: 'Delete connection',
|
||||
template: Util.getConfirmationTemplate(null, {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm: function(e, target){
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
|
||||
// deleteSignatures(row);
|
||||
let connection = $().getConnectionById(mapData.config.id, rowData.id);
|
||||
// deleteSignatures(row);
|
||||
let connection = $().getConnectionById(mapData.config.id, rowData.id);
|
||||
|
||||
MapUtil.deleteConnections([connection], () => {
|
||||
// callback function after ajax "delete" success
|
||||
// remove table row
|
||||
tempTableElement.DataTable().rows(deleteRowElement).remove().draw();
|
||||
});
|
||||
MapUtil.deleteConnections([connection], () => {
|
||||
// callback function after ajax "delete" success
|
||||
// remove table row
|
||||
tempTableElement.DataTable().rows(deleteRowElement).remove().draw();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// init confirmation dialog
|
||||
$(cell).confirmation(tempConfirmationSettings);
|
||||
$(cell).confirmation(confirmationSettings);
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -189,7 +189,7 @@ define([
|
||||
html: '<i class="fas fa-fw fa-question-circle"></i>'
|
||||
}),
|
||||
$('<td>', {
|
||||
text: scopeLabel.charAt(0).toUpperCase() + scopeLabel.slice(1)
|
||||
text: scopeLabel.capitalize()
|
||||
}),
|
||||
$('<td>', {
|
||||
class: ['text-right', config.connectionInfoTableCellConnectionClass].join(' ')
|
||||
@@ -883,15 +883,11 @@ define([
|
||||
|
||||
if(rowData.active){
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
title: 'delete jump log',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times',
|
||||
template: Util.getConfirmationTemplate(null, {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm : function(e, target){
|
||||
// get current row data (important!)
|
||||
// -> "rowData" param is not current state, values are "on createCell()" state
|
||||
|
||||
@@ -569,15 +569,11 @@ define([
|
||||
$(cell).find('i').tooltip();
|
||||
}else{
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
title: 'delete structure',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times',
|
||||
template: Util.getConfirmationTemplate(null, {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm : function(e, target){
|
||||
// get current row data (important!)
|
||||
// -> "rowData" param is not current state, values are "on createCell()" state
|
||||
|
||||
@@ -88,6 +88,12 @@ define([
|
||||
return cachedData;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param mapIds
|
||||
* @param sourceName
|
||||
* @param targetName
|
||||
* @returns {string}
|
||||
*/
|
||||
let getRouteDataCacheKey = (mapIds, sourceName, targetName) => {
|
||||
return [mapIds.join('_'), sourceName.toLowerCase(), targetName.toLowerCase()].join('###');
|
||||
};
|
||||
@@ -245,8 +251,7 @@ define([
|
||||
* show route dialog. User can search for systems and jump-info for each system is added to a data table
|
||||
* @param dialogData
|
||||
*/
|
||||
let showFindRouteDialog = (dialogData) => {
|
||||
|
||||
let showFindRouteDialog = dialogData => {
|
||||
let mapSelectOptions = [];
|
||||
let currentMapData = Util.getCurrentMapData();
|
||||
if(currentMapData !== false){
|
||||
@@ -548,12 +553,12 @@ define([
|
||||
* set event observer for route finder dialog
|
||||
* @param routeDialog
|
||||
*/
|
||||
let setDialogObserver = (routeDialog) => {
|
||||
let wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
|
||||
let wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
|
||||
let wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
|
||||
let wormholeEolCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesEOL"]');
|
||||
let wormholeSizeSelect = routeDialog.find('#' + config.routeDialogSizeSelectId);
|
||||
let setDialogObserver = routeDialog => {
|
||||
let wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
|
||||
let wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
|
||||
let wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
|
||||
let wormholeEolCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesEOL"]');
|
||||
let wormholeSizeSelect = routeDialog.find('#' + config.routeDialogSizeSelectId);
|
||||
|
||||
// store current "checked" state for each box ---------------------------------------------
|
||||
let storeCheckboxStatus = function(){
|
||||
@@ -1127,15 +1132,11 @@ define([
|
||||
let tempTableElement = this;
|
||||
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
title: 'delete route',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times',
|
||||
template: Util.getConfirmationTemplate(null, {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm : function(e, target){
|
||||
let deleteRowElement = $(cell).parents('tr');
|
||||
tempTableElement.api().rows(deleteRowElement).remove().draw();
|
||||
|
||||
@@ -31,10 +31,14 @@ define([
|
||||
moduleHeadlineIconLazyClass: 'pf-module-icon-button-lazy', // class for "lazy delete" toggle icon
|
||||
moduleHeadlineProgressBarClass: 'pf-system-progress-scanned', // class for signature progress bar
|
||||
|
||||
// fonts
|
||||
fontUppercaseClass: 'pf-font-uppercase', // class for "uppercase" font
|
||||
|
||||
// tables
|
||||
tableToolsActionClass: 'pf-table-tools-action', // class for "new signature" table (hidden)
|
||||
|
||||
// table toolbar
|
||||
tableToolbarStatusClass: 'pf-table-toolbar-status', // class for "status" DataTable Toolbar
|
||||
sigTableClearButtonClass: 'pf-sig-table-clear-button', // class for "clear" signatures button
|
||||
|
||||
// signature table
|
||||
@@ -42,6 +46,7 @@ define([
|
||||
sigTableClass: 'pf-sig-table', // Table class for all Signature Tables
|
||||
sigTablePrimaryClass: 'pf-sig-table-primary', // class for primary sig table
|
||||
sigTableSecondaryClass: 'pf-sig-table-secondary', // class for secondary sig table
|
||||
sigTableInfoClass: 'pf-sig-table-info', // class for info sig table
|
||||
sigTableRowIdPrefix: 'pf-sig-row_', // id prefix for table rows
|
||||
|
||||
sigTableEditSigNameInput: 'pf-sig-table-edit-name-input', // class for editable fields (sig name)
|
||||
@@ -52,12 +57,23 @@ define([
|
||||
tableCellActionClass: 'pf-table-action-cell', // class for "action" cells
|
||||
|
||||
// xEditable
|
||||
editableNameInputClass: 'pf-editable-name', // class for "name" input
|
||||
editableDescriptionInputClass: 'pf-editable-description', // class for "description" textarea
|
||||
editableUnknownInputClass: 'pf-editable-unknown', // class for input fields (e.g. checkboxes) with "unknown" status
|
||||
|
||||
signatureGroupsLabels: Util.getSignatureGroupOptions('label'),
|
||||
signatureGroupsNames: Util.getSignatureGroupOptions('name')
|
||||
signatureGroupsNames: Util.getSignatureGroupOptions('name'),
|
||||
|
||||
// signature reader dialog
|
||||
sigReaderDialogClass: 'pf-sig-reader-dialog', // class for "signature reader" dialog
|
||||
sigInfoId: 'pf-sig-info', // id for "signature info" table area
|
||||
sigInfoTextareaId: 'pf-sig-info-textarea', // id for signature reader "textarea"
|
||||
sigReaderLazyUpdateId: 'pf-sig-reader-lazy-update', // id for "lazy update" checkbox
|
||||
sigReaderConnectionDeleteId: 'pf-sig-reader-delete-connection', // id for "delete connection" checkbox
|
||||
|
||||
sigInfoCountSigNewId: 'pf-sig-info-count-sig-new', // id for "signature new" counter
|
||||
sigInfoCountSigChangeId: 'pf-sig-info-count-sig-change', // id for "signature change" counter
|
||||
sigInfoCountSigDeleteId: 'pf-sig-info-count-sig-delete', // id for "signature delete" counter
|
||||
sigInfoCountConDeleteId: 'pf-sig-info-count-con-delete' // id for "connection delete" counter
|
||||
};
|
||||
|
||||
let sigNameCache = {}; // cache signature names
|
||||
@@ -84,6 +100,13 @@ define([
|
||||
typeId: 0
|
||||
};
|
||||
|
||||
let emptySignatureReaderCounterData = {
|
||||
added: 0,
|
||||
changed: 0,
|
||||
deleted: 0,
|
||||
deleteCon: 0
|
||||
};
|
||||
|
||||
let editableDefaults = { // xEditable default options for signature fields
|
||||
url: function(params){
|
||||
let saveExecutor = (resolve, reject) => {
|
||||
@@ -518,9 +541,9 @@ define([
|
||||
*/
|
||||
let updateScannedSignaturesBar = (tableApi, options) => {
|
||||
let tableElement = tableApi.table().node();
|
||||
let moduleElement = $(tableElement).parents('.' + config.moduleTypeClass);
|
||||
let progressBar = moduleElement.find('.progress-bar');
|
||||
let progressBarLabel = moduleElement.find('.progress-label-right');
|
||||
let parentElement = $(tableElement).parents('.' + config.moduleTypeClass + ', .' + config.sigReaderDialogClass);
|
||||
let progressBar = parentElement.find('.progress-bar');
|
||||
let progressBarLabel = parentElement.find('.progress-label-right');
|
||||
|
||||
let percent = 0;
|
||||
let progressBarType = '';
|
||||
@@ -557,17 +580,168 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* load existing (current) signature data into info table (preview)
|
||||
* @param infoTableApi
|
||||
* @param mapId
|
||||
* @param systemId
|
||||
* @param draw
|
||||
*/
|
||||
let initTableDataWithCurrentSignatureData = (infoTableApi, mapId, systemId, draw = false) => {
|
||||
// reset/clear infoTable
|
||||
infoTableApi.clear();
|
||||
|
||||
let primaryTableApi = getDataTableInstance(mapId, systemId, 'primary');
|
||||
if(primaryTableApi){
|
||||
infoTableApi.rows.add(primaryTableApi.data().toArray());
|
||||
if(draw){
|
||||
infoTableApi.draw();
|
||||
}
|
||||
}else{
|
||||
console.warn('Signature table not found. mapId: %d; systemId: %d', mapId, systemId);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* set "signature reader" dialog observer
|
||||
* @param dialogElement
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
*/
|
||||
let setSignatureReaderDialogObserver = (dialogElement, mapId, systemData) => {
|
||||
let systemId = systemData.id;
|
||||
let form = dialogElement.find('form').first();
|
||||
let textarea = form.find('#' + config.sigInfoTextareaId);
|
||||
let deleteOutdatedCheckbox = form.find('#' + config.sigReaderLazyUpdateId);
|
||||
let deleteConnectionsCheckbox = form.find('#' + config.sigReaderConnectionDeleteId);
|
||||
let errorClipboardValidation = 'No signatures found in scan result';
|
||||
let tableStatusElement = dialogElement.find('.' + config.tableToolbarStatusClass);
|
||||
|
||||
form.initFormValidation({
|
||||
delay: 0,
|
||||
feedback: {
|
||||
success: 'fa-check',
|
||||
error: 'fa-times'
|
||||
},
|
||||
custom: {
|
||||
clipboard: function(textarea){
|
||||
let signatureData = parseSignatureString(systemData, textarea.val());
|
||||
tableStatusElement.text(signatureData.length + ' signatures parsed');
|
||||
if(signatureData.length === 0){
|
||||
return errorClipboardValidation;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let updatePreviewSection = (mapId, systemId, formData) => {
|
||||
let infoTableApi = getDataTableInstance(mapId, systemId, 'info');
|
||||
if(infoTableApi){
|
||||
// init 'infoTable' with existing signature rows
|
||||
// infoTableApi.draw() not necessary at this point!
|
||||
initTableDataWithCurrentSignatureData(infoTableApi, mapId, systemId);
|
||||
|
||||
let signatureData = parseSignatureString(systemData, formData.clipboard);
|
||||
if(signatureData.length > 0){
|
||||
// valid signature data parsed
|
||||
// -> add some default data (e.g. currentCharacter data) to parsed signatureData
|
||||
// -> not required, just for filling up some more columns
|
||||
signatureData = enrichParsedSignatureData(signatureData);
|
||||
|
||||
updateSignatureInfoTable(infoTableApi, signatureData, Boolean(formData.deleteOld), Boolean(formData.deleteConnection));
|
||||
}else{
|
||||
// no signatures pasted -> draw current signature rows
|
||||
infoTableApi.draw();
|
||||
// reset counter elements
|
||||
updateSignatureReaderCounters(emptySignatureReaderCounterData);
|
||||
|
||||
updateScannedSignaturesBar(infoTableApi, {showNotice: false});
|
||||
|
||||
console.info(errorClipboardValidation);
|
||||
}
|
||||
}else{
|
||||
console.warn('Signature "preview" table not found. mapId: %d; systemId: %d', mapId, systemId);
|
||||
}
|
||||
};
|
||||
|
||||
// changes in 'scan result' textarea -> update preview table --------------------------------------------------
|
||||
let oldValue = '';
|
||||
textarea.on('change keyup paste', function(){
|
||||
let formData = form.getFormValues();
|
||||
let currentValue = formData.clipboard;
|
||||
if(currentValue === oldValue){
|
||||
return; //check to prevent multiple simultaneous triggers
|
||||
}
|
||||
oldValue = currentValue;
|
||||
|
||||
updatePreviewSection(mapId, systemId, formData);
|
||||
});
|
||||
|
||||
textarea.on('focus', function(e){
|
||||
this.select();
|
||||
});
|
||||
|
||||
// en/disable 'lazy update' toggles dependent checkbox --------------------------------------------------------
|
||||
let onDeleteOutdatedCheckboxChange = function(){
|
||||
deleteConnectionsCheckbox.prop('disabled', !this.checked);
|
||||
deleteConnectionsCheckbox.prop('checked', false);
|
||||
}.bind(deleteOutdatedCheckbox[0]);
|
||||
|
||||
deleteOutdatedCheckbox.on('change', onDeleteOutdatedCheckboxChange);
|
||||
onDeleteOutdatedCheckboxChange();
|
||||
|
||||
// en/disable checkboxes -> update preview table --------------------------------------------------------------
|
||||
deleteOutdatedCheckbox.add(deleteConnectionsCheckbox).on('change', function(){
|
||||
let formData = form.getFormValues();
|
||||
if(formData.clipboard.length){
|
||||
updatePreviewSection(mapId, systemId, form.getFormValues());
|
||||
}
|
||||
});
|
||||
|
||||
// listen 'primary' sig table updates -> update 'preview' sig table in the dialog -----------------------------
|
||||
dialogElement.on('pf:updateSignatureReaderDialog', function(e){
|
||||
updatePreviewSection(mapId, systemId, form.getFormValues());
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* open "signature reader" dialog for signature table
|
||||
* @param systemData
|
||||
*/
|
||||
$.fn.showSignatureReaderDialog = function(systemData){
|
||||
let moduleElement = $(this);
|
||||
let mapId = moduleElement.data('mapId');
|
||||
let systemId = moduleElement.data('systemId');
|
||||
|
||||
requirejs([
|
||||
'text!templates/dialog/signature_reader.html',
|
||||
'text!templates/form/progress.html',
|
||||
'mustache'
|
||||
], (TplDialog, TplProgress, Mustache) => {
|
||||
let data = {
|
||||
sigInfoId: config.sigInfoId,
|
||||
sigReaderLazyUpdateId: config.sigReaderLazyUpdateId,
|
||||
sigReaderConnectionDeleteId: config.sigReaderConnectionDeleteId,
|
||||
sigInfoTextareaId: config.sigInfoTextareaId,
|
||||
sigInfoLazyUpdateStatus: getLazyUpdateToggleStatus(moduleElement),
|
||||
sigInfoCountSigNewId: config.sigInfoCountSigNewId,
|
||||
sigInfoCountSigChangeId: config.sigInfoCountSigChangeId,
|
||||
sigInfoCountSigDeleteId: config.sigInfoCountSigDeleteId,
|
||||
sigInfoCountConDeleteId: config.sigInfoCountConDeleteId,
|
||||
sigInfoProgressElement : Mustache.render(TplProgress, {
|
||||
label: true,
|
||||
wrapperClass: config.moduleHeadlineProgressBarClass,
|
||||
class: ['progress-bar-success'].join(' '),
|
||||
percent: 0
|
||||
})
|
||||
};
|
||||
|
||||
requirejs(['text!templates/dialog/signature_reader.html', 'mustache'], (template, Mustache) => {
|
||||
let signatureReaderDialog = bootbox.dialog({
|
||||
className: config.sigReaderDialogClass,
|
||||
title: 'Signature reader',
|
||||
message: Mustache.render(template, {}),
|
||||
size: 'large',
|
||||
message: Mustache.render(TplDialog, data),
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
@@ -578,21 +752,42 @@ define([
|
||||
className: 'btn-success',
|
||||
callback: function(){
|
||||
let form = this.find('form');
|
||||
let formData = form.getFormValues();
|
||||
let signatureOptions = {
|
||||
deleteOld: (formData.deleteOld) ? 1 : 0
|
||||
};
|
||||
|
||||
let mapId = moduleElement.data('mapId');
|
||||
let systemId = moduleElement.data('systemId');
|
||||
let tableApi = getDataTableInstance(mapId, systemId, 'primary');
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
|
||||
updateSignatureTableByClipboard(tableApi, systemData, formData.clipboard, signatureOptions);
|
||||
// check whether the form is valid
|
||||
if(form.isValidForm()){
|
||||
// get form data
|
||||
let formData = form.getFormValues();
|
||||
|
||||
let signatureOptions = {
|
||||
deleteOld: (formData.deleteOld) ? 1 : 0,
|
||||
deleteConnection: (formData.deleteConnection) ? 1 : 0
|
||||
};
|
||||
|
||||
let tableApi = getDataTableInstance(mapId, systemId, 'primary');
|
||||
|
||||
updateSignatureTableByClipboard(tableApi, systemData, formData.clipboard, signatureOptions);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
signatureReaderDialog.on('show.bs.modal', function(e) {
|
||||
let dialogElement = $(this);
|
||||
let infoTableApi = drawSignatureTableInfo(this, mapId, systemData);
|
||||
// init 'infoTable' with existing signature rows
|
||||
initTableDataWithCurrentSignatureData(infoTableApi, mapId, systemId, true);
|
||||
|
||||
updateScannedSignaturesBar(infoTableApi, {showNotice: false});
|
||||
|
||||
setSignatureReaderDialogObserver(dialogElement, mapId, systemData);
|
||||
});
|
||||
|
||||
// dialog shown event
|
||||
signatureReaderDialog.on('shown.bs.modal', function(e){
|
||||
signatureReaderDialog.initTooltips();
|
||||
@@ -600,9 +795,36 @@ define([
|
||||
// set focus on sig-input textarea
|
||||
signatureReaderDialog.find('textarea').focus();
|
||||
});
|
||||
|
||||
// show dialog
|
||||
signatureReaderDialog.modal('show');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Parsed scan result data (from EVE client) should be enriched with some data
|
||||
* -> fill up more columns in the 'preview' signature tab.e
|
||||
* @param signatureData
|
||||
* @returns {*}
|
||||
*/
|
||||
let enrichParsedSignatureData = signatureData => {
|
||||
let characterData = Util.getObjVal(Util.getCurrentUserData(), 'character');
|
||||
let timestamp = Math.floor((new Date()).getTime() / 1000);
|
||||
|
||||
for(let i = 0; i < signatureData.length; i++){
|
||||
signatureData[i].created = {
|
||||
created: timestamp,
|
||||
character: characterData
|
||||
};
|
||||
signatureData[i].updated = {
|
||||
updated: timestamp,
|
||||
character: characterData
|
||||
};
|
||||
}
|
||||
|
||||
return signatureData;
|
||||
};
|
||||
|
||||
/**
|
||||
* parses a copy&paste string from ingame scanning window
|
||||
* @param systemData
|
||||
@@ -712,7 +934,8 @@ define([
|
||||
[],
|
||||
{
|
||||
signatures: signatureData,
|
||||
deleteOld: options.deleteOld,
|
||||
deleteOld: options.deleteOld || 0,
|
||||
deleteConnection: options.deleteConnection || 0,
|
||||
systemId: parseInt(systemData.id)
|
||||
},
|
||||
{
|
||||
@@ -764,17 +987,19 @@ define([
|
||||
* deletes signature rows from signature table
|
||||
* @param tableApi
|
||||
* @param rows
|
||||
* @param deleteOptions
|
||||
*/
|
||||
let deleteSignatures = (tableApi, rows) => {
|
||||
let deleteSignatures = (tableApi, rows, deleteOptions = {}) => {
|
||||
// get unique id array from rows -> in case there are 2 rows with same id -> you never know
|
||||
let signatureIds = [...new Set(rows.data().toArray().map(rowData => rowData.id))];
|
||||
let metaData = getTableMetaData(tableApi);
|
||||
let data = Object.assign(deleteOptions, {
|
||||
systemId: metaData.systemId
|
||||
});
|
||||
|
||||
let processRequestPromise = tableApi.newProcess('request');
|
||||
|
||||
Util.request('DELETE', 'signature', signatureIds, {
|
||||
systemId: metaData.systemId
|
||||
}, {
|
||||
Util.request('DELETE', 'signature', signatureIds, data, {
|
||||
tableApi: tableApi,
|
||||
processRequestPromise: processRequestPromise
|
||||
},
|
||||
@@ -841,7 +1066,11 @@ define([
|
||||
*/
|
||||
let checkConnectionConflicts = () => {
|
||||
setTimeout(() => {
|
||||
let connectionSelects = $('.' + config.tableCellConnectionClass + '.editable');
|
||||
let connectionSelectsSelector = [config.sigTablePrimaryClass, config.sigTableSecondaryClass].map(
|
||||
tableClass => '.' + tableClass + ' .' + config.tableCellConnectionClass + '.editable'
|
||||
).join(', ');
|
||||
|
||||
let connectionSelects = $(connectionSelectsSelector);
|
||||
let connectionIds = [];
|
||||
let duplicateConnectionIds = [];
|
||||
let groupedSelects = [];
|
||||
@@ -1216,6 +1445,47 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get HTML for "delete connection" confirmation popover
|
||||
* @returns {string}
|
||||
*/
|
||||
let getConfirmationContent = () => {
|
||||
let checkOptions = [{
|
||||
name: 'deleteConnection',
|
||||
value: '1',
|
||||
label: 'delete connection',
|
||||
class: 'pf-editable-warn',
|
||||
checked: true
|
||||
}];
|
||||
|
||||
let getChecklist = checkOptions => {
|
||||
let html = '<form class="form-inline editableform popover-content-inner">';
|
||||
html += '<div class="control-group form-group">';
|
||||
html += '<div class="editable-input">';
|
||||
html += '<div class="editable-checklist">';
|
||||
|
||||
for(let option of checkOptions){
|
||||
html += '<div><label>';
|
||||
html += '<input type="checkbox" name="' + option.name + '" value="' + option.value + '" ';
|
||||
html += 'class="' + option.class + '" ' + (option.checked ? 'checked' : '') + '>';
|
||||
html += '<span>' + option.label + '</span>';
|
||||
html += '</label></div>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
html += '</form>';
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
let html = '';
|
||||
html += getChecklist(checkOptions);
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
/**
|
||||
* get dataTables default options for signature tables
|
||||
* @param mapId
|
||||
@@ -1281,7 +1551,7 @@ define([
|
||||
title: 'id',
|
||||
type: 'string',
|
||||
width: 12,
|
||||
class: [config.tableCellFocusClass, config.sigTableEditSigNameInput].join(' '),
|
||||
class: [config.tableCellFocusClass, config.sigTableEditSigNameInput, config.fontUppercaseClass].join(' '),
|
||||
data: 'name',
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let tableApi = this.api();
|
||||
@@ -1299,7 +1569,7 @@ define([
|
||||
pk: rowData.id || null,
|
||||
emptytext: '? ? ?',
|
||||
value: cellData,
|
||||
inputclass: config.editableNameInputClass,
|
||||
inputclass: config.fontUppercaseClass,
|
||||
display: function(value){
|
||||
// change display value to first 3 letters
|
||||
$(this).text($.trim( value.substr(0, 3) ).toLowerCase());
|
||||
@@ -1634,7 +1904,7 @@ define([
|
||||
let diff = Math.floor((new Date()).getTime()) - cellData * 1000;
|
||||
|
||||
// age > 1 day
|
||||
if( diff > 86400000){
|
||||
if(diff > 86400000){
|
||||
$(cell).addClass('txt-color txt-color-warning');
|
||||
}
|
||||
}
|
||||
@@ -1679,22 +1949,43 @@ define([
|
||||
if(rowData.id){
|
||||
// delete signature -----------------------------------------------------------------------
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
title: 'delete signature',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times',
|
||||
title: 'Delete signature',
|
||||
template: Util.getConfirmationTemplate(getConfirmationContent(), {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm: function(e, target){
|
||||
// top scroll to top
|
||||
e.preventDefault();
|
||||
|
||||
// get form data (check if form tag is not hidden!) from confirmation popover
|
||||
let tip = target.data('bs.confirmation').tip();
|
||||
let form = tip.find('form:not(.hidden)').first();
|
||||
let formData = form.getFormValues();
|
||||
let deleteOptions = Util.getObjVal(formData, 'deleteConnection') ? formData : {};
|
||||
|
||||
// add "processing" state or connection that will be deleted as well
|
||||
if(deleteOptions.deleteConnection){
|
||||
let connectionId = tableApi.cell(rowIndex, 'connection:name').data();
|
||||
if(connectionId){
|
||||
let metaData = getTableMetaData(tableApi);
|
||||
let connection = $().getConnectionById(metaData.mapId, connectionId);
|
||||
if(connection){
|
||||
connection.addType('state_process');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
let row = tableApi.rows(deleteRowElement);
|
||||
deleteSignatures(tableApi, row);
|
||||
deleteSignatures(tableApi, row, deleteOptions);
|
||||
},
|
||||
onShow: function(e, target){
|
||||
// hide "deleteConnection" checkbox if no connectionId linked
|
||||
let tip = target.data('bs.confirmation').tip();
|
||||
let form = tip.find('form').first();
|
||||
let connectionId = tableApi.cell(rowIndex, 'connection:name').data();
|
||||
form.toggleClass('hidden', !connectionId);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1867,6 +2158,51 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* draw signature 'info' (preview) table in 'signatureReader' dialog
|
||||
* @param dialogElement
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
* @returns {jQuery}
|
||||
*/
|
||||
let drawSignatureTableInfo = (dialogElement, mapId, systemData) => {
|
||||
let infoElement = $(dialogElement).find('#' + config.sigInfoId);
|
||||
|
||||
let table = $('<table>', {
|
||||
id: getTableId(mapId, systemData.id, 'info'),
|
||||
class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTableInfoClass].join(' ')
|
||||
});
|
||||
|
||||
infoElement.append(table);
|
||||
|
||||
let dataTableOptions = {
|
||||
tabIndex: -1,
|
||||
dom: '<"row"<"col-xs-3"l><"col-xs-5 ' + config.tableToolbarStatusClass + '"><"col-xs-4"f>>' +
|
||||
'<"row"<"col-xs-12"tr>>' +
|
||||
'<"row"<"col-xs-5"i><"col-xs-7"p>>',
|
||||
initComplete: function(settings, json){
|
||||
let tableApi = this.api();
|
||||
|
||||
initCharacterInfoTooltip(this, tableApi);
|
||||
|
||||
tableApi.columns(['action:name']).visible(false);
|
||||
|
||||
Counter.initTableCounter(this, ['created:name', 'updated:name']);
|
||||
}
|
||||
};
|
||||
|
||||
$.extend(true, dataTableOptions, getSignatureDataTableDefaults(mapId, systemData));
|
||||
|
||||
let tableApi = table.DataTable(dataTableOptions);
|
||||
|
||||
tableApi.on('draw.dt', function(e, settings){
|
||||
// xEditable cells should not be editable in this table
|
||||
$(dialogElement).find('.' + config.sigTableInfoClass).find('td.editable').editable('disable');
|
||||
});
|
||||
|
||||
return tableApi;
|
||||
};
|
||||
|
||||
/**
|
||||
* draw signature table toolbar (add signature button, scan progress bar
|
||||
* @param moduleElement
|
||||
@@ -2020,8 +2356,6 @@ define([
|
||||
editable.input.$input.first().prop('disabled', true);
|
||||
// preselect second option
|
||||
//editable.input.$input.eq(1).prop('checked', true);
|
||||
//editable.setValue('ad78172b72d0327b237c4a7dc1daa5d7');
|
||||
|
||||
|
||||
// "fake" radio button behaviour
|
||||
editable.input.$input.attr('name', 'test').attr('type', 'radio');
|
||||
@@ -2162,6 +2496,30 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init character info Tooltips
|
||||
* -> e.g. table cell 'question mark' icon
|
||||
* @param element
|
||||
* @param tableApi
|
||||
*/
|
||||
let initCharacterInfoTooltip = (element, tableApi) => {
|
||||
element.hoverIntent({
|
||||
over: function(e){
|
||||
let cellElement = $(this);
|
||||
let rowData = tableApi.row(cellElement.parents('tr')).data();
|
||||
cellElement.addCharacterInfoTooltip(rowData, {
|
||||
trigger: 'manual',
|
||||
placement: 'top',
|
||||
show: true
|
||||
});
|
||||
},
|
||||
out: function(e){
|
||||
$(this).destroyPopover();
|
||||
},
|
||||
selector: 'td.' + Util.config.helpClass
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* draw empty signature table
|
||||
* @param moduleElement
|
||||
@@ -2213,6 +2571,7 @@ define([
|
||||
initComplete: function(settings, json){
|
||||
let tableApi = this.api();
|
||||
|
||||
initCharacterInfoTooltip(this, tableApi);
|
||||
initGroupFilterButton(tableApi);
|
||||
initUndoButton(tableApi);
|
||||
initSelectAllButton(tableApi);
|
||||
@@ -2386,13 +2745,13 @@ define([
|
||||
|
||||
// event listener for global "paste" signatures into the page -------------------------------------------------
|
||||
moduleElement.on('pf:updateSystemSignatureModuleByClipboard', {tableApi: primaryTableApi}, function(e, clipboard){
|
||||
let lazyUpdateToggle = moduleElement.find('.' + config.moduleHeadlineIconLazyClass);
|
||||
let signatureOptions = {
|
||||
deleteOld: lazyUpdateToggle.hasClass('active') ? 1 : 0
|
||||
deleteOld: getLazyUpdateToggleStatus(moduleElement),
|
||||
deleteConnection: 0
|
||||
};
|
||||
|
||||
// "disable" lazy update icon -> prevents accidental removal for next paste #724
|
||||
lazyUpdateToggle.toggleClass('active', false);
|
||||
getLazyUpdateToggleElement(moduleElement).toggleClass('active', false);
|
||||
|
||||
updateSignatureTableByClipboard(e.data.tableApi, systemData, clipboard, signatureOptions);
|
||||
});
|
||||
@@ -2402,23 +2761,38 @@ define([
|
||||
moduleElement.find('.' + config.sigTableClass),
|
||||
'.editable-click:not(.editable-open) span[class^="pf-system-sec-"]'
|
||||
);
|
||||
};
|
||||
|
||||
// signature column - "info" popover --------------------------------------------------------------------------
|
||||
moduleElement.find('.' + config.sigTablePrimaryClass).hoverIntent({
|
||||
over: function(e){
|
||||
let cellElement = $(this);
|
||||
let rowData = primaryTableApi.row(cellElement.parents('tr')).data();
|
||||
cellElement.addCharacterInfoTooltip(rowData, {
|
||||
trigger: 'manual',
|
||||
placement: 'top',
|
||||
show: true
|
||||
});
|
||||
},
|
||||
out: function(e){
|
||||
$(this).destroyPopover();
|
||||
},
|
||||
selector: 'td.' + Util.config.helpClass
|
||||
});
|
||||
/**
|
||||
* get "lazy delete" toggle element
|
||||
* @param moduleElement
|
||||
* @returns {*}
|
||||
*/
|
||||
let getLazyUpdateToggleElement = moduleElement => moduleElement.find('.' + config.moduleHeadlineIconLazyClass);
|
||||
|
||||
/**
|
||||
* get status for "lazy delete" toggle
|
||||
* @param moduleElement
|
||||
* @returns {number}
|
||||
*/
|
||||
let getLazyUpdateToggleStatus = moduleElement => getLazyUpdateToggleElement(moduleElement).hasClass('active') ? 1 : 0;
|
||||
|
||||
/**
|
||||
* update 'counter' UI elements in 'signature reader' dialog
|
||||
* @param data
|
||||
*/
|
||||
let updateSignatureReaderCounters = data => {
|
||||
let counterElement = $('#' + config.sigInfoCountSigNewId).text(data.added || 0);
|
||||
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.added));
|
||||
|
||||
counterElement = $('#' + config.sigInfoCountSigChangeId).text(data.changed || 0);
|
||||
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.changed));
|
||||
|
||||
counterElement = $('#' + config.sigInfoCountSigDeleteId).text(data.deleted || 0);
|
||||
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.deleted));
|
||||
|
||||
counterElement = $('#' + config.sigInfoCountConDeleteId).text(data.deleteCon || 0);
|
||||
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.deleteCon));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2435,6 +2809,181 @@ define([
|
||||
return row;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param action
|
||||
* @param rowId
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
let getPromiseForRow = (action, rowId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve({action: action, rowId: rowId});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* callback for a changed row
|
||||
* @param rowIndex
|
||||
* @param colIndex
|
||||
* @param tableLoopCount
|
||||
* @param cellLoopCount
|
||||
* @param options CUSTOM parameter (not DataTables specific)!
|
||||
*/
|
||||
let rowUpdate = function(rowIndex, colIndex, tableLoopCount, cellLoopCount, options){
|
||||
let cell = this;
|
||||
let node = cell.nodes().to$();
|
||||
if(node.data('editable')){
|
||||
// xEditable is active -> should always be active!
|
||||
// set new value even if no change -> e.g. render selected Ids as text labels
|
||||
let oldValue = node.editable('getValue', true);
|
||||
|
||||
// ... some editable cells depend on each other (e.g. group->type, group->connection)
|
||||
switch(node.data('editable').options.name){
|
||||
case 'typeId':
|
||||
// ... disable if no type options found
|
||||
editableSelectCheck(node);
|
||||
break;
|
||||
case 'connectionId':
|
||||
// disables if no wormhole group set
|
||||
let groupId = cell.cell(rowIndex, 'group:name').data();
|
||||
if(groupId === 5){
|
||||
// wormhole
|
||||
editableEnable(node);
|
||||
}else{
|
||||
editableDisable(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// values should be set AFTER en/disabling of a field
|
||||
node.editable('setValue', cell.data());
|
||||
|
||||
if(oldValue !== cell.data()){
|
||||
// highlight cell on data change
|
||||
node.pulseBackgroundColor('changed', Util.getObjVal(options, 'keepVisible') || false);
|
||||
}
|
||||
}else if(node.hasClass(config.tableCellCounterClass)){
|
||||
// "updated" timestamp always changed
|
||||
node.pulseBackgroundColor('changed', Util.getObjVal(options, 'keepVisible') || false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* update 'info' (preview) signature table (inside 'signature reader' dialog)
|
||||
* @param tableApi
|
||||
* @param signaturesDataOrig
|
||||
* @param deleteOutdatedSignatures
|
||||
* @param deleteConnections
|
||||
*/
|
||||
let updateSignatureInfoTable = (tableApi, signaturesDataOrig, deleteOutdatedSignatures = false, deleteConnections = false) => {
|
||||
// clone signature array because of further manipulation
|
||||
let signaturesData = $.extend([], signaturesDataOrig);
|
||||
|
||||
let rowIdsExist = [];
|
||||
|
||||
let promisesAdded = [];
|
||||
let promisesChanged = [];
|
||||
let promisesDeleted = [];
|
||||
|
||||
let allRows = tableApi.rows();
|
||||
|
||||
let rowUpdateCallback = function(){
|
||||
rowUpdate.apply(this, [...arguments, {keepVisible: true}]);
|
||||
};
|
||||
|
||||
// update rows ------------------------------------------------------------------------------------------------
|
||||
allRows.every(function(rowIdx, tableLoop, rowLoop){
|
||||
let row = this;
|
||||
let rowData = row.data();
|
||||
|
||||
for(let i = 0; i < signaturesData.length; i++){
|
||||
if(signaturesData[i].name === rowData.name){
|
||||
let rowId = row.id(true);
|
||||
|
||||
// check if row was updated
|
||||
if(signaturesData[i].updated.updated > rowData.updated.updated){
|
||||
// set new row data -> draw() is executed after all changes made
|
||||
let newRowData = signaturesData[i];
|
||||
// keep "description" must not be replaced
|
||||
newRowData.description = rowData.description;
|
||||
// existing "groupId" must not be removed
|
||||
if(!newRowData.groupId){
|
||||
newRowData.groupId = rowData.groupId;
|
||||
newRowData.typeId = rowData.typeId;
|
||||
}else if(newRowData.groupId === rowData.groupId){
|
||||
if(!newRowData.typeId){
|
||||
newRowData.typeId = rowData.typeId;
|
||||
}
|
||||
}
|
||||
|
||||
// "created" timestamp will not change -> use existing
|
||||
newRowData.created = rowData.created;
|
||||
row.data(newRowData);
|
||||
|
||||
// bind new signature dataTable data() -> to xEditable inputs
|
||||
row.cells(row.id(true), ['id:name', 'group:name', 'type:name', 'description:name', 'connection:name', 'updated:name'])
|
||||
.every(rowUpdateCallback);
|
||||
|
||||
promisesChanged.push(getPromiseForRow('changed', rowId));
|
||||
}
|
||||
|
||||
rowIdsExist.push(rowIdx);
|
||||
|
||||
// remove signature data -> all left signatures will be added
|
||||
signaturesData.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// delete rows ------------------------------------------------------------------------------------------------
|
||||
if(deleteOutdatedSignatures){
|
||||
let rows = tableApi.rows((rowIdx, rowData, node) => !rowIdsExist.includes(rowIdx));
|
||||
rows.every(function(rowIdx, tableLoop, rowLoop){
|
||||
let row = this;
|
||||
let rowId = row.id(true);
|
||||
let rowElement = row.nodes().to$();
|
||||
let rowData = row.data();
|
||||
|
||||
rowElement.pulseBackgroundColor('deleted', true);
|
||||
|
||||
promisesChanged.push(getPromiseForRow('deleted', rowId));
|
||||
|
||||
// check if there is a connectionId.
|
||||
if(deleteConnections && Util.getObjVal(rowData, 'connection.id')){
|
||||
promisesChanged.push(getPromiseForRow('deleteCon', rowId));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// add rows ---------------------------------------------------------------------------------------------------
|
||||
for(let signatureData of signaturesData){
|
||||
let row = addSignatureRow(tableApi, signatureData);
|
||||
let rowElement = row.nodes().to$();
|
||||
rowElement.pulseBackgroundColor('added', true);
|
||||
|
||||
promisesAdded.push(getPromiseForRow('added', row.index()));
|
||||
}
|
||||
|
||||
// done -------------------------------------------------------------------------------------------------------
|
||||
Promise.all(promisesAdded.concat(promisesChanged, promisesDeleted)).then(payloads => {
|
||||
if(payloads.length){
|
||||
// table data changed -> draw() table changes
|
||||
tableApi.draw();
|
||||
|
||||
// no notifications if table was empty just progressbar notification is needed
|
||||
// sum payloads by "action"
|
||||
let notificationCounter = payloads.reduce((acc, payload) => {
|
||||
acc[payload.action]++;
|
||||
return acc;
|
||||
}, Object.assign({}, emptySignatureReaderCounterData));
|
||||
|
||||
updateSignatureReaderCounters(notificationCounter);
|
||||
|
||||
updateScannedSignaturesBar(tableApi, {showNotice: false});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* update signature table with new signatures
|
||||
* -> add/update/delete rows
|
||||
@@ -2463,51 +3012,6 @@ define([
|
||||
let allRows = tableApi.rows();
|
||||
let updateEmptyTable = !allRows.any();
|
||||
|
||||
let rowUpdate = function(rowIndex, colIndex, tableLoopCount, cellLoopCount){
|
||||
let cell = this;
|
||||
let node = cell.nodes().to$();
|
||||
if(node.data('editable')){
|
||||
// xEditable is active -> should always be active!
|
||||
// set new value even if no change -> e.g. render selected Ids as text labels
|
||||
let oldValue = node.editable('getValue', true);
|
||||
|
||||
// ... some editable cells depend on each other (e.g. group->type, group->connection)
|
||||
switch(node.data('editable').options.name){
|
||||
case 'typeId':
|
||||
// ... disable if no type options found
|
||||
editableSelectCheck(node);
|
||||
break;
|
||||
case 'connectionId':
|
||||
// disables if no wormhole group set
|
||||
let groupId = cell.cell(rowIndex, 'group:name').data();
|
||||
if(groupId === 5){
|
||||
// wormhole
|
||||
editableEnable(node);
|
||||
}else{
|
||||
editableDisable(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// values should be set AFTER en/disabling of a field
|
||||
node.editable('setValue', cell.data());
|
||||
|
||||
if(oldValue !== cell.data()){
|
||||
// highlight cell on data change
|
||||
node.pulseBackgroundColor('changed');
|
||||
}
|
||||
}else if(node.hasClass(config.tableCellCounterClass)){
|
||||
// "updated" timestamp always changed
|
||||
node.pulseBackgroundColor('changed');
|
||||
}
|
||||
};
|
||||
|
||||
let getPromiseForRow = (action, rowId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve({action: action, rowId: rowId});
|
||||
});
|
||||
};
|
||||
|
||||
// update signatures ------------------------------------------------------------------------------------------
|
||||
allRows.every(function(rowIdx, tableLoop, rowLoop){
|
||||
let row = this;
|
||||
@@ -2588,7 +3092,7 @@ define([
|
||||
}
|
||||
acc[payload.action]++;
|
||||
return acc;
|
||||
}, {});
|
||||
}, Object.assign({}, emptySignatureReaderCounterData));
|
||||
|
||||
let notification = '';
|
||||
if(notificationCounter.added > 0){
|
||||
@@ -2606,6 +3110,13 @@ define([
|
||||
}
|
||||
|
||||
updateScannedSignaturesBar(tableApi, {showNotice: true});
|
||||
|
||||
// at this point the 'primary' signature table update is done
|
||||
// we need to check if there is an open 'signature reader' dialog,
|
||||
// that needs to update its 'preview' signature table
|
||||
// -> to use DataTables "drawCallback" option or "draw.dt" event is not the *best* option:
|
||||
// Both are called to frequently (e.g. after filter/sort actions)
|
||||
$('.' + config.sigReaderDialogClass + '.in').trigger('pf:updateSignatureReaderDialog');
|
||||
}
|
||||
|
||||
// unlock table
|
||||
|
||||
139
js/app/util.js
139
js/app/util.js
@@ -75,13 +75,11 @@ define([
|
||||
select2ImageLazyLoadClass: 'pf-select2-image-lazyLoad',
|
||||
|
||||
// animation
|
||||
animationPulseSuccessClass: 'pf-animation-pulse-success', // animation class
|
||||
animationPulseWarningClass: 'pf-animation-pulse-warning', // animation class
|
||||
animationPulseDangerClass: 'pf-animation-pulse-danger', // animation class
|
||||
animationPulseClassPrefix: 'pf-animation-pulse-', // class prefix for "pulse" background animation
|
||||
|
||||
// popover
|
||||
popoverTriggerClass: 'pf-popover-trigger', // class for "popover" trigger elements
|
||||
popoverSmallClass: 'pf-popover-small', // class for small "popover"
|
||||
popoverSmallClass: 'popover-small', // class for small "popover"
|
||||
popoverCharacterClass: 'pf-popover-character', // class for character "popover"
|
||||
|
||||
// Summernote
|
||||
@@ -765,28 +763,30 @@ define([
|
||||
/**
|
||||
* highlight jquery elements
|
||||
* add/remove css class for keyframe animation
|
||||
* @returns {any|JQuery|*}
|
||||
* @param status
|
||||
* @param keepVisible
|
||||
* @param clear
|
||||
* @returns {void|*|undefined}
|
||||
*/
|
||||
$.fn.pulseBackgroundColor = function(status, clear){
|
||||
|
||||
let animationClass = '';
|
||||
$.fn.pulseBackgroundColor = function(status, keepVisible = false, clear = false){
|
||||
let animationClass = config.animationPulseClassPrefix;
|
||||
switch(status){
|
||||
case 'added':
|
||||
animationClass = config.animationPulseSuccessClass;
|
||||
break;
|
||||
case 'changed':
|
||||
animationClass = config.animationPulseWarningClass;
|
||||
break;
|
||||
case 'deleted':
|
||||
animationClass = config.animationPulseDangerClass;
|
||||
break;
|
||||
case 'added': animationClass += 'success'; break;
|
||||
case 'changed': animationClass += 'warning'; break;
|
||||
case 'deleted': animationClass += 'danger'; break;
|
||||
default: console.warn('Invalid status: %s', status);
|
||||
}
|
||||
|
||||
// if keepVisible -> background color animation class will not be deleted
|
||||
if(keepVisible){
|
||||
animationClass += '-keep';
|
||||
}
|
||||
|
||||
let clearTimer = element => {
|
||||
element.removeClass( animationClass );
|
||||
element.removeClass(animationClass);
|
||||
let currentTimer = element.data('animationTimer');
|
||||
|
||||
if( animationTimerCache.hasOwnProperty(currentTimer) ){
|
||||
if(animationTimerCache.hasOwnProperty(currentTimer)){
|
||||
clearTimeout( currentTimer );
|
||||
delete animationTimerCache[currentTimer];
|
||||
element.removeData('animationTimer');
|
||||
@@ -796,18 +796,20 @@ define([
|
||||
return this.each(function(){
|
||||
let element = $(this);
|
||||
|
||||
if( element.hasClass(animationClass) ){
|
||||
if(element.hasClass(animationClass)){
|
||||
// clear timer -> set new timer
|
||||
clearTimer(element);
|
||||
}
|
||||
|
||||
if(clear !== true){
|
||||
if(!clear){
|
||||
element.addClass(animationClass);
|
||||
let timer = setTimeout(clearTimer, 1500, element);
|
||||
element.data('animationTimer', timer);
|
||||
animationTimerCache[timer] = true;
|
||||
// remove class after animation finish, if not 'keepVisible'
|
||||
if(!keepVisible){
|
||||
let timer = setTimeout(clearTimer, 1500, element);
|
||||
element.data('animationTimer', timer);
|
||||
animationTimerCache[timer] = true;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
@@ -971,6 +973,14 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* capitalize first letter
|
||||
* @returns {string}
|
||||
*/
|
||||
String.prototype.capitalize = function(){
|
||||
return this.charAt(0).toUpperCase() + this.slice(1);
|
||||
};
|
||||
|
||||
/**
|
||||
* get hash from string
|
||||
* @returns {number}
|
||||
@@ -1158,6 +1168,52 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get template for Bootstrap "Confirmation" popover plugin
|
||||
* -> if HTML 'content' not set, we expect the default template
|
||||
* https://www.npmjs.com/package/bs-confirmation
|
||||
* -> options.size for "small" popover layout
|
||||
* -> options.noTitle for hide title element
|
||||
* @param content
|
||||
* @param options
|
||||
* @returns {string}
|
||||
*/
|
||||
let getConfirmationTemplate = (content, options) => {
|
||||
let getButtons = () => {
|
||||
let buttonHtml = '<div class="btn-group">';
|
||||
buttonHtml += '<a data-apply="confirmation">Yes</a>';
|
||||
buttonHtml += '<a data-dismiss="confirmation">No</a>';
|
||||
buttonHtml += '</div>';
|
||||
return buttonHtml;
|
||||
};
|
||||
|
||||
let getContent = content => {
|
||||
let contentHtml = content ? content : '';
|
||||
contentHtml += '<div class="popover-footer">';
|
||||
contentHtml += getButtons();
|
||||
contentHtml += '</div>';
|
||||
return contentHtml;
|
||||
};
|
||||
|
||||
let popoverClass = ['popover'];
|
||||
if('small' === getObjVal(options, 'size')){
|
||||
popoverClass.push('popover-small');
|
||||
}
|
||||
|
||||
let contentClass = ['popover-content', 'no-padding'];
|
||||
|
||||
let html = '<div class="' + popoverClass.join(' ') + '">';
|
||||
html += '<div class="arrow"></div>';
|
||||
if(true !== getObjVal(options, 'noTitle')){
|
||||
html += '<h3 class="popover-title"></h3>';
|
||||
}
|
||||
html += '<div class="' + contentClass.join(' ') + '">';
|
||||
html += getContent(content);
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
return html;
|
||||
};
|
||||
|
||||
/**
|
||||
* convert XEditable Select <option> data into Select2 data format
|
||||
* -> "prepend" (empty) options get added, too
|
||||
@@ -1239,7 +1295,7 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set default configuration for "Bootbox"
|
||||
* set default configuration for "Bootbox" plugin
|
||||
*/
|
||||
let initDefaultBootboxConfig = () => {
|
||||
bootbox.setDefaults({
|
||||
@@ -1248,7 +1304,22 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set default configuration for "Select2"
|
||||
* set default configuration for "Confirmation" popover plugin
|
||||
*/
|
||||
let initDefaultConfirmationConfig = () => {
|
||||
$.fn.confirmation.Constructor.DEFAULTS.placement = 'left';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.container = 'body';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnCancelClass = 'btn btn-sm btn-default';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnCancelLabel = 'cancel';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnCancelIcon = 'fas fa-fw fa-ban';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnOkClass = 'btn btn-sm btn-danger';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnOkLabel = 'delete';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnOkIcon = 'fas fa-fw fa-times';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.template = getConfirmationTemplate();
|
||||
};
|
||||
|
||||
/**
|
||||
* set default configuration for "Select2" plugin
|
||||
*/
|
||||
let initDefaultSelect2Config = () => {
|
||||
$.fn.select2.defaults.set('theme', 'pathfinder');
|
||||
@@ -1372,7 +1443,7 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set default configuration for "xEditable"
|
||||
* set default configuration for "xEditable" plugin
|
||||
*/
|
||||
let initDefaultEditableConfig = () => {
|
||||
// use fontAwesome buttons template
|
||||
@@ -1462,7 +1533,7 @@ define([
|
||||
// Server is running with GMT/UTC (EVE Time)
|
||||
let localDate = new Date();
|
||||
|
||||
let serverDate= new Date(
|
||||
let serverDate = new Date(
|
||||
localDate.getUTCFullYear(),
|
||||
localDate.getUTCMonth(),
|
||||
localDate.getUTCDate(),
|
||||
@@ -1766,8 +1837,8 @@ define([
|
||||
* Request data from Server
|
||||
* -> This function should be used (in future) for all Ajax and REST API calls
|
||||
* -> works as a "wrapper" for jQueries ajax() method
|
||||
* @param action
|
||||
* @param entity
|
||||
* @param {String} action
|
||||
* @param {String} entity
|
||||
* @param ids
|
||||
* @param data
|
||||
* @param context
|
||||
@@ -1779,7 +1850,7 @@ define([
|
||||
let requestExecutor = (resolve, reject) => {
|
||||
let payload = {
|
||||
action: 'request',
|
||||
name: action.toLowerCase() + entity.charAt(0).toUpperCase() + entity.slice(1)
|
||||
name: action.toLowerCase() + entity.capitalize()
|
||||
};
|
||||
|
||||
// build request url --------------------------------------------------------------------------------------
|
||||
@@ -2206,7 +2277,7 @@ define([
|
||||
let typeClass = '';
|
||||
let matches = regex.exec(typeName.toLowerCase());
|
||||
if(matches && matches[1]){
|
||||
typeName = matches[1].charAt(0).toUpperCase() + matches[1].slice(1);
|
||||
typeName = matches[1].capitalize();
|
||||
typeClass = getPlanetInfo(matches[1]);
|
||||
}
|
||||
|
||||
@@ -3356,6 +3427,7 @@ define([
|
||||
showVersionInfo: showVersionInfo,
|
||||
initPrototypes: initPrototypes,
|
||||
initDefaultBootboxConfig: initDefaultBootboxConfig,
|
||||
initDefaultConfirmationConfig: initDefaultConfirmationConfig,
|
||||
initDefaultSelect2Config: initDefaultSelect2Config,
|
||||
initDefaultEditableConfig: initDefaultEditableConfig,
|
||||
getCurrentTriggerDelay: getCurrentTriggerDelay,
|
||||
@@ -3410,6 +3482,7 @@ define([
|
||||
getCurrentCharacterLog: getCurrentCharacterLog,
|
||||
findInViewport: findInViewport,
|
||||
initScrollSpy: initScrollSpy,
|
||||
getConfirmationTemplate: getConfirmationTemplate,
|
||||
convertXEditableOptionsToSelect2: convertXEditableOptionsToSelect2,
|
||||
flattenXEditableSelectArray: flattenXEditableSelectArray,
|
||||
getCharacterDataBySystemId: getCharacterDataBySystemId,
|
||||
|
||||
4
js/lib/bootbox.min.js
vendored
4
js/lib/bootbox.min.js
vendored
File diff suppressed because one or more lines are too long
6
js/lib/jquery.hoverIntent.min.js
vendored
6
js/lib/jquery.hoverIntent.min.js
vendored
@@ -1,9 +1,9 @@
|
||||
/*!
|
||||
* hoverIntent v1.9.0 // 2017.09.01 // jQuery v1.7.0+
|
||||
* hoverIntent v1.10.0 // 2019.02.25 // jQuery v1.7.0+
|
||||
* http://briancherne.github.io/jquery-hoverIntent/
|
||||
*
|
||||
* You may use hoverIntent under the terms of the MIT license. Basically that
|
||||
* means you are free to use hoverIntent as long as this header is left intact.
|
||||
* Copyright 2007-2017 Brian Cherne
|
||||
* Copyright 2007-2019 Brian Cherne
|
||||
*/
|
||||
!function(factory){"use strict";"function"==typeof define&&define.amd?define(["jquery"],factory):jQuery&&!jQuery.fn.hoverIntent&&factory(jQuery)}(function($){"use strict";var cX,cY,_cfg={interval:100,sensitivity:6,timeout:0},INSTANCE_COUNT=0,track=function(ev){cX=ev.pageX,cY=ev.pageY},compare=function(ev,$el,s,cfg){if(Math.sqrt((s.pX-cX)*(s.pX-cX)+(s.pY-cY)*(s.pY-cY))<cfg.sensitivity)return $el.off(s.event,track),delete s.timeoutId,s.isActive=!0,ev.pageX=cX,ev.pageY=cY,delete s.pX,delete s.pY,cfg.over.apply($el[0],[ev]);s.pX=cX,s.pY=cY,s.timeoutId=setTimeout(function(){compare(ev,$el,s,cfg)},cfg.interval)},delay=function(ev,$el,s,out){return delete $el.data("hoverIntent")[s.id],out.apply($el[0],[ev])};$.fn.hoverIntent=function(handlerIn,handlerOut,selector){var instanceId=INSTANCE_COUNT++,cfg=$.extend({},_cfg);$.isPlainObject(handlerIn)?(cfg=$.extend(cfg,handlerIn),$.isFunction(cfg.out)||(cfg.out=cfg.over)):cfg=$.isFunction(handlerOut)?$.extend(cfg,{over:handlerIn,out:handlerOut,selector:selector}):$.extend(cfg,{over:handlerIn,out:handlerIn,selector:handlerOut});var handleHover=function(e){var ev=$.extend({},e),$el=$(this),hoverIntentData=$el.data("hoverIntent");hoverIntentData||$el.data("hoverIntent",hoverIntentData={});var state=hoverIntentData[instanceId];state||(hoverIntentData[instanceId]=state={id:instanceId}),state.timeoutId&&(state.timeoutId=clearTimeout(state.timeoutId));var mousemove=state.event="mousemove.hoverIntent.hoverIntent"+instanceId;if("mouseenter"===e.type){if(state.isActive)return;state.pX=ev.pageX,state.pY=ev.pageY,$el.off(mousemove,track).on(mousemove,track),state.timeoutId=setTimeout(function(){compare(ev,$el,state,cfg)},cfg.interval)}else{if(!state.isActive)return;$el.off(mousemove,track),state.timeoutId=setTimeout(function(){delay(ev,$el,state,cfg.out)},cfg.timeout)}};return this.on({"mouseenter.hoverIntent":handleHover,"mouseleave.hoverIntent":handleHover},cfg.selector)}});
|
||||
!function(factory){"use strict";"function"==typeof define&&define.amd?define(["jquery"],factory):"object"==typeof module&&module.exports?module.exports=factory(require("jquery")):jQuery&&!jQuery.fn.hoverIntent&&factory(jQuery)}(function($){"use strict";var cX,cY,_cfg={interval:100,sensitivity:6,timeout:0},INSTANCE_COUNT=0,track=function(ev){cX=ev.pageX,cY=ev.pageY},compare=function(ev,$el,s,cfg){if(Math.sqrt((s.pX-cX)*(s.pX-cX)+(s.pY-cY)*(s.pY-cY))<cfg.sensitivity)return $el.off(s.event,track),delete s.timeoutId,s.isActive=!0,ev.pageX=cX,ev.pageY=cY,delete s.pX,delete s.pY,cfg.over.apply($el[0],[ev]);s.pX=cX,s.pY=cY,s.timeoutId=setTimeout(function(){compare(ev,$el,s,cfg)},cfg.interval)};$.fn.hoverIntent=function(handlerIn,handlerOut,selector){var instanceId=INSTANCE_COUNT++,cfg=$.extend({},_cfg);$.isPlainObject(handlerIn)?(cfg=$.extend(cfg,handlerIn),$.isFunction(cfg.out)||(cfg.out=cfg.over)):cfg=$.isFunction(handlerOut)?$.extend(cfg,{over:handlerIn,out:handlerOut,selector:selector}):$.extend(cfg,{over:handlerIn,out:handlerIn,selector:handlerOut});var handleHover=function(e){var ev=$.extend({},e),$el=$(this),hoverIntentData=$el.data("hoverIntent");hoverIntentData||$el.data("hoverIntent",hoverIntentData={});var state=hoverIntentData[instanceId];state||(hoverIntentData[instanceId]=state={id:instanceId}),state.timeoutId&&(state.timeoutId=clearTimeout(state.timeoutId));var mousemove=state.event="mousemove.hoverIntent.hoverIntent"+instanceId;if("mouseenter"===e.type){if(state.isActive)return;state.pX=ev.pageX,state.pY=ev.pageY,$el.off(mousemove,track).on(mousemove,track),state.timeoutId=setTimeout(function(){compare(ev,$el,state,cfg)},cfg.interval)}else{if(!state.isActive)return;$el.off(mousemove,track),state.timeoutId=setTimeout(function(){!function(ev,$el,s,out){delete $el.data("hoverIntent")[s.id],out.apply($el[0],[ev])}(ev,$el,state,cfg.out)},cfg.timeout)}};return this.on({"mouseenter.hoverIntent":handleHover,"mouseleave.hoverIntent":handleHover},cfg.selector)}});
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -42,11 +42,11 @@ requirejs.config({
|
||||
xEditable: 'lib/bootstrap-editable.min', // v1.5.1 X-editable - in placed editing
|
||||
morris: 'lib/morris.min', // v0.5.1 Morris.js - graphs and charts
|
||||
raphael: 'lib/raphael.min', // v2.2.8 Raphaël - required for morris - https://dmitrybaranovskiy.github.io/raphael
|
||||
bootbox: 'lib/bootbox.min', // v4.4.0 Bootbox.js - custom dialogs - http://bootboxjs.com
|
||||
bootbox: 'lib/bootbox.min', // v5.2.0 Bootbox.js - custom dialogs - http://bootboxjs.com
|
||||
easyPieChart: 'lib/jquery.easypiechart.min', // v2.1.6 Easy Pie Chart - HTML 5 pie charts - http://rendro.github.io/easy-pie-chart
|
||||
peityInlineChart: 'lib/jquery.peity.min', // v3.2.1 Inline Chart - http://benpickles.github.io/peity/
|
||||
dragToSelect: 'lib/jquery.dragToSelect', // v1.1 Drag to Select - http://andreaslagerkvist.com/jquery/drag-to-select
|
||||
hoverIntent: 'lib/jquery.hoverIntent.min', // v1.9.0 Hover intention - http://cherne.net/brian/resources/jquery.hoverIntent.html
|
||||
hoverIntent: 'lib/jquery.hoverIntent.min', // v1.10.0 Hover intention - http://cherne.net/brian/resources/jquery.hoverIntent.html
|
||||
select2: 'lib/select2.min', // v4.0.3 Drop Down customization - https://select2.github.io
|
||||
validator: 'lib/validator.min', // v0.10.1 Validator for Bootstrap 3 - https://github.com/1000hz/bootstrap-validator
|
||||
lazylinepainter: 'lib/jquery.lazylinepainter-1.5.1.min', // v1.5.1 SVG line animation plugin - http://lazylinepainter.info
|
||||
|
||||
@@ -45,6 +45,7 @@ define([
|
||||
table.destroyTimestampCounter(true);
|
||||
});
|
||||
|
||||
// Status Plugin ==============================================================================================
|
||||
let StatusTable = function(settings){
|
||||
let me = this;
|
||||
me.statusContainer = $('<div>', {
|
||||
|
||||
@@ -141,15 +141,14 @@ define([
|
||||
|
||||
// show Cookie accept hint on SSO login button
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'bottom',
|
||||
btnOkClass: 'btn btn-sm btn-default',
|
||||
btnOkLabel: 'dismiss',
|
||||
btnOkIcon: 'fas fa-fw fa-sign-in-alt',
|
||||
title: 'Accept cookies',
|
||||
btnCancelClass: 'btn btn-sm btn-success',
|
||||
btnCancelLabel: 'accept',
|
||||
btnCancelIcon: 'fas fa-fw fa-check',
|
||||
btnOkClass: 'btn btn-sm btn-default',
|
||||
btnOkLabel: 'dismiss',
|
||||
btnOkIcon: 'fas fa-fw fa-sign-in-alt',
|
||||
onCancel: function(e, target){
|
||||
// "Accept cookies"
|
||||
setAcceptCookie();
|
||||
|
||||
@@ -31,6 +31,9 @@ define([
|
||||
// set default dialog config
|
||||
Util.initDefaultBootboxConfig();
|
||||
|
||||
// set default confirmation popover config
|
||||
Util.initDefaultConfirmationConfig();
|
||||
|
||||
// set default select2 config
|
||||
Util.initDefaultSelect2Config();
|
||||
|
||||
|
||||
@@ -853,6 +853,10 @@ define([
|
||||
let modalElement = $(e.target);
|
||||
modalElement.destroyTimestampCounter(true);
|
||||
|
||||
// destroy all form validators
|
||||
// -> does not work properly. validation functions still used (js error) after 'destroy'
|
||||
//modalElement.find('form').filter((i, form) => $(form).data('bs.validator')).validator('destroy');
|
||||
|
||||
// destroy all popovers
|
||||
modalElement.find('.' + Util.config.popoverTriggerClass).popover('destroy');
|
||||
|
||||
|
||||
@@ -77,11 +77,9 @@ define([
|
||||
|
||||
// show "discard" changes confirmation
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'top',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
title: 'discard changes',
|
||||
btnCancelIcon: '',
|
||||
btnOkClass: 'btn btn-sm btn-warning',
|
||||
btnOkLabel: 'discard',
|
||||
btnOkIcon: 'fas fa-fw fa-ban',
|
||||
|
||||
@@ -56,18 +56,6 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
// confirmation dialog settings (e.g. delete row)
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times'
|
||||
};
|
||||
|
||||
/**
|
||||
* get icon that marks a table cell as clickable
|
||||
* @returns {string}
|
||||
@@ -456,44 +444,49 @@ define([
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let tempTableElement = this;
|
||||
|
||||
let tempConfirmationSettings = confirmationSettings;
|
||||
tempConfirmationSettings.title = 'Delete system';
|
||||
tempConfirmationSettings.onConfirm = function(e, target){
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
let confirmationSettings = {
|
||||
placement: 'left',
|
||||
title: 'Delete system',
|
||||
template: Util.getConfirmationTemplate(null, {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm: function(e, target){
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
let systemElement = $('#' + MapUtil.getSystemId(mapData.config.id, rowData.id) );
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
let systemElement = $('#' + MapUtil.getSystemId(mapData.config.id, rowData.id) );
|
||||
|
||||
if(systemElement.length){
|
||||
// trigger system delete event
|
||||
activeMap.trigger('pf:deleteSystems', [{
|
||||
systems: [systemElement[0]],
|
||||
callback: function(deletedSystems){
|
||||
// callback function after ajax "delete" success
|
||||
// check if system was deleted
|
||||
if(deletedSystems.length === 1){
|
||||
// remove table row
|
||||
tempTableElement.DataTable().rows(deleteRowElement).remove().draw();
|
||||
if(systemElement.length){
|
||||
// trigger system delete event
|
||||
activeMap.trigger('pf:deleteSystems', [{
|
||||
systems: [systemElement[0]],
|
||||
callback: function(deletedSystems){
|
||||
// callback function after ajax "delete" success
|
||||
// check if system was deleted
|
||||
if(deletedSystems.length === 1){
|
||||
// remove table row
|
||||
tempTableElement.DataTable().rows(deleteRowElement).remove().draw();
|
||||
|
||||
Util.showNotify({title: 'System deleted', text: rowData.name, type: 'success'});
|
||||
Util.showNotify({title: 'System deleted', text: rowData.name, type: 'success'});
|
||||
|
||||
// refresh connection table (connections might have changed) --------------
|
||||
let connectionsElement = $('#' + config.mapInfoConnectionsId);
|
||||
let mapDataNew = activeMap.getMapDataFromClient(['hasId']);
|
||||
// refresh connection table (connections might have changed) --------------
|
||||
let connectionsElement = $('#' + config.mapInfoConnectionsId);
|
||||
let mapDataNew = activeMap.getMapDataFromClient(['hasId']);
|
||||
|
||||
connectionsElement.initConnectionInfoTable(mapDataNew);
|
||||
}else{
|
||||
// error
|
||||
Util.showNotify({title: 'Failed to delete system', text: rowData.name, type: 'error'});
|
||||
connectionsElement.initConnectionInfoTable(mapDataNew);
|
||||
}else{
|
||||
// error
|
||||
Util.showNotify({title: 'Failed to delete system', text: rowData.name, type: 'error'});
|
||||
}
|
||||
}
|
||||
}
|
||||
}]);
|
||||
}]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// init confirmation dialog
|
||||
$(cell).confirmation(tempConfirmationSettings);
|
||||
|
||||
$(cell).confirmation(confirmationSettings);
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -652,23 +645,29 @@ define([
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let tempTableElement = this;
|
||||
|
||||
let tempConfirmationSettings = confirmationSettings;
|
||||
tempConfirmationSettings.title = 'Delete connection';
|
||||
tempConfirmationSettings.onConfirm = function(e, target){
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
let confirmationSettings = {
|
||||
placement: 'left',
|
||||
title: 'Delete connection',
|
||||
template: Util.getConfirmationTemplate(null, {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm: function(e, target){
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
|
||||
// deleteSignatures(row);
|
||||
let connection = $().getConnectionById(mapData.config.id, rowData.id);
|
||||
// deleteSignatures(row);
|
||||
let connection = $().getConnectionById(mapData.config.id, rowData.id);
|
||||
|
||||
MapUtil.deleteConnections([connection], () => {
|
||||
// callback function after ajax "delete" success
|
||||
// remove table row
|
||||
tempTableElement.DataTable().rows(deleteRowElement).remove().draw();
|
||||
});
|
||||
MapUtil.deleteConnections([connection], () => {
|
||||
// callback function after ajax "delete" success
|
||||
// remove table row
|
||||
tempTableElement.DataTable().rows(deleteRowElement).remove().draw();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// init confirmation dialog
|
||||
$(cell).confirmation(tempConfirmationSettings);
|
||||
$(cell).confirmation(confirmationSettings);
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -189,7 +189,7 @@ define([
|
||||
html: '<i class="fas fa-fw fa-question-circle"></i>'
|
||||
}),
|
||||
$('<td>', {
|
||||
text: scopeLabel.charAt(0).toUpperCase() + scopeLabel.slice(1)
|
||||
text: scopeLabel.capitalize()
|
||||
}),
|
||||
$('<td>', {
|
||||
class: ['text-right', config.connectionInfoTableCellConnectionClass].join(' ')
|
||||
@@ -883,15 +883,11 @@ define([
|
||||
|
||||
if(rowData.active){
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
title: 'delete jump log',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times',
|
||||
template: Util.getConfirmationTemplate(null, {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm : function(e, target){
|
||||
// get current row data (important!)
|
||||
// -> "rowData" param is not current state, values are "on createCell()" state
|
||||
|
||||
@@ -569,15 +569,11 @@ define([
|
||||
$(cell).find('i').tooltip();
|
||||
}else{
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
title: 'delete structure',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times',
|
||||
template: Util.getConfirmationTemplate(null, {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm : function(e, target){
|
||||
// get current row data (important!)
|
||||
// -> "rowData" param is not current state, values are "on createCell()" state
|
||||
|
||||
@@ -88,6 +88,12 @@ define([
|
||||
return cachedData;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param mapIds
|
||||
* @param sourceName
|
||||
* @param targetName
|
||||
* @returns {string}
|
||||
*/
|
||||
let getRouteDataCacheKey = (mapIds, sourceName, targetName) => {
|
||||
return [mapIds.join('_'), sourceName.toLowerCase(), targetName.toLowerCase()].join('###');
|
||||
};
|
||||
@@ -245,8 +251,7 @@ define([
|
||||
* show route dialog. User can search for systems and jump-info for each system is added to a data table
|
||||
* @param dialogData
|
||||
*/
|
||||
let showFindRouteDialog = (dialogData) => {
|
||||
|
||||
let showFindRouteDialog = dialogData => {
|
||||
let mapSelectOptions = [];
|
||||
let currentMapData = Util.getCurrentMapData();
|
||||
if(currentMapData !== false){
|
||||
@@ -548,12 +553,12 @@ define([
|
||||
* set event observer for route finder dialog
|
||||
* @param routeDialog
|
||||
*/
|
||||
let setDialogObserver = (routeDialog) => {
|
||||
let wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
|
||||
let wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
|
||||
let wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
|
||||
let wormholeEolCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesEOL"]');
|
||||
let wormholeSizeSelect = routeDialog.find('#' + config.routeDialogSizeSelectId);
|
||||
let setDialogObserver = routeDialog => {
|
||||
let wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
|
||||
let wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
|
||||
let wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
|
||||
let wormholeEolCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesEOL"]');
|
||||
let wormholeSizeSelect = routeDialog.find('#' + config.routeDialogSizeSelectId);
|
||||
|
||||
// store current "checked" state for each box ---------------------------------------------
|
||||
let storeCheckboxStatus = function(){
|
||||
@@ -1127,15 +1132,11 @@ define([
|
||||
let tempTableElement = this;
|
||||
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
title: 'delete route',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times',
|
||||
template: Util.getConfirmationTemplate(null, {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm : function(e, target){
|
||||
let deleteRowElement = $(cell).parents('tr');
|
||||
tempTableElement.api().rows(deleteRowElement).remove().draw();
|
||||
|
||||
@@ -31,10 +31,14 @@ define([
|
||||
moduleHeadlineIconLazyClass: 'pf-module-icon-button-lazy', // class for "lazy delete" toggle icon
|
||||
moduleHeadlineProgressBarClass: 'pf-system-progress-scanned', // class for signature progress bar
|
||||
|
||||
// fonts
|
||||
fontUppercaseClass: 'pf-font-uppercase', // class for "uppercase" font
|
||||
|
||||
// tables
|
||||
tableToolsActionClass: 'pf-table-tools-action', // class for "new signature" table (hidden)
|
||||
|
||||
// table toolbar
|
||||
tableToolbarStatusClass: 'pf-table-toolbar-status', // class for "status" DataTable Toolbar
|
||||
sigTableClearButtonClass: 'pf-sig-table-clear-button', // class for "clear" signatures button
|
||||
|
||||
// signature table
|
||||
@@ -42,6 +46,7 @@ define([
|
||||
sigTableClass: 'pf-sig-table', // Table class for all Signature Tables
|
||||
sigTablePrimaryClass: 'pf-sig-table-primary', // class for primary sig table
|
||||
sigTableSecondaryClass: 'pf-sig-table-secondary', // class for secondary sig table
|
||||
sigTableInfoClass: 'pf-sig-table-info', // class for info sig table
|
||||
sigTableRowIdPrefix: 'pf-sig-row_', // id prefix for table rows
|
||||
|
||||
sigTableEditSigNameInput: 'pf-sig-table-edit-name-input', // class for editable fields (sig name)
|
||||
@@ -52,12 +57,23 @@ define([
|
||||
tableCellActionClass: 'pf-table-action-cell', // class for "action" cells
|
||||
|
||||
// xEditable
|
||||
editableNameInputClass: 'pf-editable-name', // class for "name" input
|
||||
editableDescriptionInputClass: 'pf-editable-description', // class for "description" textarea
|
||||
editableUnknownInputClass: 'pf-editable-unknown', // class for input fields (e.g. checkboxes) with "unknown" status
|
||||
|
||||
signatureGroupsLabels: Util.getSignatureGroupOptions('label'),
|
||||
signatureGroupsNames: Util.getSignatureGroupOptions('name')
|
||||
signatureGroupsNames: Util.getSignatureGroupOptions('name'),
|
||||
|
||||
// signature reader dialog
|
||||
sigReaderDialogClass: 'pf-sig-reader-dialog', // class for "signature reader" dialog
|
||||
sigInfoId: 'pf-sig-info', // id for "signature info" table area
|
||||
sigInfoTextareaId: 'pf-sig-info-textarea', // id for signature reader "textarea"
|
||||
sigReaderLazyUpdateId: 'pf-sig-reader-lazy-update', // id for "lazy update" checkbox
|
||||
sigReaderConnectionDeleteId: 'pf-sig-reader-delete-connection', // id for "delete connection" checkbox
|
||||
|
||||
sigInfoCountSigNewId: 'pf-sig-info-count-sig-new', // id for "signature new" counter
|
||||
sigInfoCountSigChangeId: 'pf-sig-info-count-sig-change', // id for "signature change" counter
|
||||
sigInfoCountSigDeleteId: 'pf-sig-info-count-sig-delete', // id for "signature delete" counter
|
||||
sigInfoCountConDeleteId: 'pf-sig-info-count-con-delete' // id for "connection delete" counter
|
||||
};
|
||||
|
||||
let sigNameCache = {}; // cache signature names
|
||||
@@ -84,6 +100,13 @@ define([
|
||||
typeId: 0
|
||||
};
|
||||
|
||||
let emptySignatureReaderCounterData = {
|
||||
added: 0,
|
||||
changed: 0,
|
||||
deleted: 0,
|
||||
deleteCon: 0
|
||||
};
|
||||
|
||||
let editableDefaults = { // xEditable default options for signature fields
|
||||
url: function(params){
|
||||
let saveExecutor = (resolve, reject) => {
|
||||
@@ -518,9 +541,9 @@ define([
|
||||
*/
|
||||
let updateScannedSignaturesBar = (tableApi, options) => {
|
||||
let tableElement = tableApi.table().node();
|
||||
let moduleElement = $(tableElement).parents('.' + config.moduleTypeClass);
|
||||
let progressBar = moduleElement.find('.progress-bar');
|
||||
let progressBarLabel = moduleElement.find('.progress-label-right');
|
||||
let parentElement = $(tableElement).parents('.' + config.moduleTypeClass + ', .' + config.sigReaderDialogClass);
|
||||
let progressBar = parentElement.find('.progress-bar');
|
||||
let progressBarLabel = parentElement.find('.progress-label-right');
|
||||
|
||||
let percent = 0;
|
||||
let progressBarType = '';
|
||||
@@ -557,17 +580,168 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* load existing (current) signature data into info table (preview)
|
||||
* @param infoTableApi
|
||||
* @param mapId
|
||||
* @param systemId
|
||||
* @param draw
|
||||
*/
|
||||
let initTableDataWithCurrentSignatureData = (infoTableApi, mapId, systemId, draw = false) => {
|
||||
// reset/clear infoTable
|
||||
infoTableApi.clear();
|
||||
|
||||
let primaryTableApi = getDataTableInstance(mapId, systemId, 'primary');
|
||||
if(primaryTableApi){
|
||||
infoTableApi.rows.add(primaryTableApi.data().toArray());
|
||||
if(draw){
|
||||
infoTableApi.draw();
|
||||
}
|
||||
}else{
|
||||
console.warn('Signature table not found. mapId: %d; systemId: %d', mapId, systemId);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* set "signature reader" dialog observer
|
||||
* @param dialogElement
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
*/
|
||||
let setSignatureReaderDialogObserver = (dialogElement, mapId, systemData) => {
|
||||
let systemId = systemData.id;
|
||||
let form = dialogElement.find('form').first();
|
||||
let textarea = form.find('#' + config.sigInfoTextareaId);
|
||||
let deleteOutdatedCheckbox = form.find('#' + config.sigReaderLazyUpdateId);
|
||||
let deleteConnectionsCheckbox = form.find('#' + config.sigReaderConnectionDeleteId);
|
||||
let errorClipboardValidation = 'No signatures found in scan result';
|
||||
let tableStatusElement = dialogElement.find('.' + config.tableToolbarStatusClass);
|
||||
|
||||
form.initFormValidation({
|
||||
delay: 0,
|
||||
feedback: {
|
||||
success: 'fa-check',
|
||||
error: 'fa-times'
|
||||
},
|
||||
custom: {
|
||||
clipboard: function(textarea){
|
||||
let signatureData = parseSignatureString(systemData, textarea.val());
|
||||
tableStatusElement.text(signatureData.length + ' signatures parsed');
|
||||
if(signatureData.length === 0){
|
||||
return errorClipboardValidation;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let updatePreviewSection = (mapId, systemId, formData) => {
|
||||
let infoTableApi = getDataTableInstance(mapId, systemId, 'info');
|
||||
if(infoTableApi){
|
||||
// init 'infoTable' with existing signature rows
|
||||
// infoTableApi.draw() not necessary at this point!
|
||||
initTableDataWithCurrentSignatureData(infoTableApi, mapId, systemId);
|
||||
|
||||
let signatureData = parseSignatureString(systemData, formData.clipboard);
|
||||
if(signatureData.length > 0){
|
||||
// valid signature data parsed
|
||||
// -> add some default data (e.g. currentCharacter data) to parsed signatureData
|
||||
// -> not required, just for filling up some more columns
|
||||
signatureData = enrichParsedSignatureData(signatureData);
|
||||
|
||||
updateSignatureInfoTable(infoTableApi, signatureData, Boolean(formData.deleteOld), Boolean(formData.deleteConnection));
|
||||
}else{
|
||||
// no signatures pasted -> draw current signature rows
|
||||
infoTableApi.draw();
|
||||
// reset counter elements
|
||||
updateSignatureReaderCounters(emptySignatureReaderCounterData);
|
||||
|
||||
updateScannedSignaturesBar(infoTableApi, {showNotice: false});
|
||||
|
||||
console.info(errorClipboardValidation);
|
||||
}
|
||||
}else{
|
||||
console.warn('Signature "preview" table not found. mapId: %d; systemId: %d', mapId, systemId);
|
||||
}
|
||||
};
|
||||
|
||||
// changes in 'scan result' textarea -> update preview table --------------------------------------------------
|
||||
let oldValue = '';
|
||||
textarea.on('change keyup paste', function(){
|
||||
let formData = form.getFormValues();
|
||||
let currentValue = formData.clipboard;
|
||||
if(currentValue === oldValue){
|
||||
return; //check to prevent multiple simultaneous triggers
|
||||
}
|
||||
oldValue = currentValue;
|
||||
|
||||
updatePreviewSection(mapId, systemId, formData);
|
||||
});
|
||||
|
||||
textarea.on('focus', function(e){
|
||||
this.select();
|
||||
});
|
||||
|
||||
// en/disable 'lazy update' toggles dependent checkbox --------------------------------------------------------
|
||||
let onDeleteOutdatedCheckboxChange = function(){
|
||||
deleteConnectionsCheckbox.prop('disabled', !this.checked);
|
||||
deleteConnectionsCheckbox.prop('checked', false);
|
||||
}.bind(deleteOutdatedCheckbox[0]);
|
||||
|
||||
deleteOutdatedCheckbox.on('change', onDeleteOutdatedCheckboxChange);
|
||||
onDeleteOutdatedCheckboxChange();
|
||||
|
||||
// en/disable checkboxes -> update preview table --------------------------------------------------------------
|
||||
deleteOutdatedCheckbox.add(deleteConnectionsCheckbox).on('change', function(){
|
||||
let formData = form.getFormValues();
|
||||
if(formData.clipboard.length){
|
||||
updatePreviewSection(mapId, systemId, form.getFormValues());
|
||||
}
|
||||
});
|
||||
|
||||
// listen 'primary' sig table updates -> update 'preview' sig table in the dialog -----------------------------
|
||||
dialogElement.on('pf:updateSignatureReaderDialog', function(e){
|
||||
updatePreviewSection(mapId, systemId, form.getFormValues());
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* open "signature reader" dialog for signature table
|
||||
* @param systemData
|
||||
*/
|
||||
$.fn.showSignatureReaderDialog = function(systemData){
|
||||
let moduleElement = $(this);
|
||||
let mapId = moduleElement.data('mapId');
|
||||
let systemId = moduleElement.data('systemId');
|
||||
|
||||
requirejs([
|
||||
'text!templates/dialog/signature_reader.html',
|
||||
'text!templates/form/progress.html',
|
||||
'mustache'
|
||||
], (TplDialog, TplProgress, Mustache) => {
|
||||
let data = {
|
||||
sigInfoId: config.sigInfoId,
|
||||
sigReaderLazyUpdateId: config.sigReaderLazyUpdateId,
|
||||
sigReaderConnectionDeleteId: config.sigReaderConnectionDeleteId,
|
||||
sigInfoTextareaId: config.sigInfoTextareaId,
|
||||
sigInfoLazyUpdateStatus: getLazyUpdateToggleStatus(moduleElement),
|
||||
sigInfoCountSigNewId: config.sigInfoCountSigNewId,
|
||||
sigInfoCountSigChangeId: config.sigInfoCountSigChangeId,
|
||||
sigInfoCountSigDeleteId: config.sigInfoCountSigDeleteId,
|
||||
sigInfoCountConDeleteId: config.sigInfoCountConDeleteId,
|
||||
sigInfoProgressElement : Mustache.render(TplProgress, {
|
||||
label: true,
|
||||
wrapperClass: config.moduleHeadlineProgressBarClass,
|
||||
class: ['progress-bar-success'].join(' '),
|
||||
percent: 0
|
||||
})
|
||||
};
|
||||
|
||||
requirejs(['text!templates/dialog/signature_reader.html', 'mustache'], (template, Mustache) => {
|
||||
let signatureReaderDialog = bootbox.dialog({
|
||||
className: config.sigReaderDialogClass,
|
||||
title: 'Signature reader',
|
||||
message: Mustache.render(template, {}),
|
||||
size: 'large',
|
||||
message: Mustache.render(TplDialog, data),
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
@@ -578,21 +752,42 @@ define([
|
||||
className: 'btn-success',
|
||||
callback: function(){
|
||||
let form = this.find('form');
|
||||
let formData = form.getFormValues();
|
||||
let signatureOptions = {
|
||||
deleteOld: (formData.deleteOld) ? 1 : 0
|
||||
};
|
||||
|
||||
let mapId = moduleElement.data('mapId');
|
||||
let systemId = moduleElement.data('systemId');
|
||||
let tableApi = getDataTableInstance(mapId, systemId, 'primary');
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
|
||||
updateSignatureTableByClipboard(tableApi, systemData, formData.clipboard, signatureOptions);
|
||||
// check whether the form is valid
|
||||
if(form.isValidForm()){
|
||||
// get form data
|
||||
let formData = form.getFormValues();
|
||||
|
||||
let signatureOptions = {
|
||||
deleteOld: (formData.deleteOld) ? 1 : 0,
|
||||
deleteConnection: (formData.deleteConnection) ? 1 : 0
|
||||
};
|
||||
|
||||
let tableApi = getDataTableInstance(mapId, systemId, 'primary');
|
||||
|
||||
updateSignatureTableByClipboard(tableApi, systemData, formData.clipboard, signatureOptions);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
signatureReaderDialog.on('show.bs.modal', function(e) {
|
||||
let dialogElement = $(this);
|
||||
let infoTableApi = drawSignatureTableInfo(this, mapId, systemData);
|
||||
// init 'infoTable' with existing signature rows
|
||||
initTableDataWithCurrentSignatureData(infoTableApi, mapId, systemId, true);
|
||||
|
||||
updateScannedSignaturesBar(infoTableApi, {showNotice: false});
|
||||
|
||||
setSignatureReaderDialogObserver(dialogElement, mapId, systemData);
|
||||
});
|
||||
|
||||
// dialog shown event
|
||||
signatureReaderDialog.on('shown.bs.modal', function(e){
|
||||
signatureReaderDialog.initTooltips();
|
||||
@@ -600,9 +795,36 @@ define([
|
||||
// set focus on sig-input textarea
|
||||
signatureReaderDialog.find('textarea').focus();
|
||||
});
|
||||
|
||||
// show dialog
|
||||
signatureReaderDialog.modal('show');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Parsed scan result data (from EVE client) should be enriched with some data
|
||||
* -> fill up more columns in the 'preview' signature tab.e
|
||||
* @param signatureData
|
||||
* @returns {*}
|
||||
*/
|
||||
let enrichParsedSignatureData = signatureData => {
|
||||
let characterData = Util.getObjVal(Util.getCurrentUserData(), 'character');
|
||||
let timestamp = Math.floor((new Date()).getTime() / 1000);
|
||||
|
||||
for(let i = 0; i < signatureData.length; i++){
|
||||
signatureData[i].created = {
|
||||
created: timestamp,
|
||||
character: characterData
|
||||
};
|
||||
signatureData[i].updated = {
|
||||
updated: timestamp,
|
||||
character: characterData
|
||||
};
|
||||
}
|
||||
|
||||
return signatureData;
|
||||
};
|
||||
|
||||
/**
|
||||
* parses a copy&paste string from ingame scanning window
|
||||
* @param systemData
|
||||
@@ -712,7 +934,8 @@ define([
|
||||
[],
|
||||
{
|
||||
signatures: signatureData,
|
||||
deleteOld: options.deleteOld,
|
||||
deleteOld: options.deleteOld || 0,
|
||||
deleteConnection: options.deleteConnection || 0,
|
||||
systemId: parseInt(systemData.id)
|
||||
},
|
||||
{
|
||||
@@ -764,17 +987,19 @@ define([
|
||||
* deletes signature rows from signature table
|
||||
* @param tableApi
|
||||
* @param rows
|
||||
* @param deleteOptions
|
||||
*/
|
||||
let deleteSignatures = (tableApi, rows) => {
|
||||
let deleteSignatures = (tableApi, rows, deleteOptions = {}) => {
|
||||
// get unique id array from rows -> in case there are 2 rows with same id -> you never know
|
||||
let signatureIds = [...new Set(rows.data().toArray().map(rowData => rowData.id))];
|
||||
let metaData = getTableMetaData(tableApi);
|
||||
let data = Object.assign(deleteOptions, {
|
||||
systemId: metaData.systemId
|
||||
});
|
||||
|
||||
let processRequestPromise = tableApi.newProcess('request');
|
||||
|
||||
Util.request('DELETE', 'signature', signatureIds, {
|
||||
systemId: metaData.systemId
|
||||
}, {
|
||||
Util.request('DELETE', 'signature', signatureIds, data, {
|
||||
tableApi: tableApi,
|
||||
processRequestPromise: processRequestPromise
|
||||
},
|
||||
@@ -841,7 +1066,11 @@ define([
|
||||
*/
|
||||
let checkConnectionConflicts = () => {
|
||||
setTimeout(() => {
|
||||
let connectionSelects = $('.' + config.tableCellConnectionClass + '.editable');
|
||||
let connectionSelectsSelector = [config.sigTablePrimaryClass, config.sigTableSecondaryClass].map(
|
||||
tableClass => '.' + tableClass + ' .' + config.tableCellConnectionClass + '.editable'
|
||||
).join(', ');
|
||||
|
||||
let connectionSelects = $(connectionSelectsSelector);
|
||||
let connectionIds = [];
|
||||
let duplicateConnectionIds = [];
|
||||
let groupedSelects = [];
|
||||
@@ -1216,6 +1445,47 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get HTML for "delete connection" confirmation popover
|
||||
* @returns {string}
|
||||
*/
|
||||
let getConfirmationContent = () => {
|
||||
let checkOptions = [{
|
||||
name: 'deleteConnection',
|
||||
value: '1',
|
||||
label: 'delete connection',
|
||||
class: 'pf-editable-warn',
|
||||
checked: true
|
||||
}];
|
||||
|
||||
let getChecklist = checkOptions => {
|
||||
let html = '<form class="form-inline editableform popover-content-inner">';
|
||||
html += '<div class="control-group form-group">';
|
||||
html += '<div class="editable-input">';
|
||||
html += '<div class="editable-checklist">';
|
||||
|
||||
for(let option of checkOptions){
|
||||
html += '<div><label>';
|
||||
html += '<input type="checkbox" name="' + option.name + '" value="' + option.value + '" ';
|
||||
html += 'class="' + option.class + '" ' + (option.checked ? 'checked' : '') + '>';
|
||||
html += '<span>' + option.label + '</span>';
|
||||
html += '</label></div>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
html += '</form>';
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
let html = '';
|
||||
html += getChecklist(checkOptions);
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
/**
|
||||
* get dataTables default options for signature tables
|
||||
* @param mapId
|
||||
@@ -1281,7 +1551,7 @@ define([
|
||||
title: 'id',
|
||||
type: 'string',
|
||||
width: 12,
|
||||
class: [config.tableCellFocusClass, config.sigTableEditSigNameInput].join(' '),
|
||||
class: [config.tableCellFocusClass, config.sigTableEditSigNameInput, config.fontUppercaseClass].join(' '),
|
||||
data: 'name',
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let tableApi = this.api();
|
||||
@@ -1299,7 +1569,7 @@ define([
|
||||
pk: rowData.id || null,
|
||||
emptytext: '? ? ?',
|
||||
value: cellData,
|
||||
inputclass: config.editableNameInputClass,
|
||||
inputclass: config.fontUppercaseClass,
|
||||
display: function(value){
|
||||
// change display value to first 3 letters
|
||||
$(this).text($.trim( value.substr(0, 3) ).toLowerCase());
|
||||
@@ -1634,7 +1904,7 @@ define([
|
||||
let diff = Math.floor((new Date()).getTime()) - cellData * 1000;
|
||||
|
||||
// age > 1 day
|
||||
if( diff > 86400000){
|
||||
if(diff > 86400000){
|
||||
$(cell).addClass('txt-color txt-color-warning');
|
||||
}
|
||||
}
|
||||
@@ -1679,22 +1949,43 @@ define([
|
||||
if(rowData.id){
|
||||
// delete signature -----------------------------------------------------------------------
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fas fa-fw fa-ban',
|
||||
title: 'delete signature',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fas fa-fw fa-times',
|
||||
title: 'Delete signature',
|
||||
template: Util.getConfirmationTemplate(getConfirmationContent(), {
|
||||
size: 'small',
|
||||
noTitle: true
|
||||
}),
|
||||
onConfirm: function(e, target){
|
||||
// top scroll to top
|
||||
e.preventDefault();
|
||||
|
||||
// get form data (check if form tag is not hidden!) from confirmation popover
|
||||
let tip = target.data('bs.confirmation').tip();
|
||||
let form = tip.find('form:not(.hidden)').first();
|
||||
let formData = form.getFormValues();
|
||||
let deleteOptions = Util.getObjVal(formData, 'deleteConnection') ? formData : {};
|
||||
|
||||
// add "processing" state or connection that will be deleted as well
|
||||
if(deleteOptions.deleteConnection){
|
||||
let connectionId = tableApi.cell(rowIndex, 'connection:name').data();
|
||||
if(connectionId){
|
||||
let metaData = getTableMetaData(tableApi);
|
||||
let connection = $().getConnectionById(metaData.mapId, connectionId);
|
||||
if(connection){
|
||||
connection.addType('state_process');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let deleteRowElement = $(target).parents('tr');
|
||||
let row = tableApi.rows(deleteRowElement);
|
||||
deleteSignatures(tableApi, row);
|
||||
deleteSignatures(tableApi, row, deleteOptions);
|
||||
},
|
||||
onShow: function(e, target){
|
||||
// hide "deleteConnection" checkbox if no connectionId linked
|
||||
let tip = target.data('bs.confirmation').tip();
|
||||
let form = tip.find('form').first();
|
||||
let connectionId = tableApi.cell(rowIndex, 'connection:name').data();
|
||||
form.toggleClass('hidden', !connectionId);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1867,6 +2158,51 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* draw signature 'info' (preview) table in 'signatureReader' dialog
|
||||
* @param dialogElement
|
||||
* @param mapId
|
||||
* @param systemData
|
||||
* @returns {jQuery}
|
||||
*/
|
||||
let drawSignatureTableInfo = (dialogElement, mapId, systemData) => {
|
||||
let infoElement = $(dialogElement).find('#' + config.sigInfoId);
|
||||
|
||||
let table = $('<table>', {
|
||||
id: getTableId(mapId, systemData.id, 'info'),
|
||||
class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTableInfoClass].join(' ')
|
||||
});
|
||||
|
||||
infoElement.append(table);
|
||||
|
||||
let dataTableOptions = {
|
||||
tabIndex: -1,
|
||||
dom: '<"row"<"col-xs-3"l><"col-xs-5 ' + config.tableToolbarStatusClass + '"><"col-xs-4"f>>' +
|
||||
'<"row"<"col-xs-12"tr>>' +
|
||||
'<"row"<"col-xs-5"i><"col-xs-7"p>>',
|
||||
initComplete: function(settings, json){
|
||||
let tableApi = this.api();
|
||||
|
||||
initCharacterInfoTooltip(this, tableApi);
|
||||
|
||||
tableApi.columns(['action:name']).visible(false);
|
||||
|
||||
Counter.initTableCounter(this, ['created:name', 'updated:name']);
|
||||
}
|
||||
};
|
||||
|
||||
$.extend(true, dataTableOptions, getSignatureDataTableDefaults(mapId, systemData));
|
||||
|
||||
let tableApi = table.DataTable(dataTableOptions);
|
||||
|
||||
tableApi.on('draw.dt', function(e, settings){
|
||||
// xEditable cells should not be editable in this table
|
||||
$(dialogElement).find('.' + config.sigTableInfoClass).find('td.editable').editable('disable');
|
||||
});
|
||||
|
||||
return tableApi;
|
||||
};
|
||||
|
||||
/**
|
||||
* draw signature table toolbar (add signature button, scan progress bar
|
||||
* @param moduleElement
|
||||
@@ -2020,8 +2356,6 @@ define([
|
||||
editable.input.$input.first().prop('disabled', true);
|
||||
// preselect second option
|
||||
//editable.input.$input.eq(1).prop('checked', true);
|
||||
//editable.setValue('ad78172b72d0327b237c4a7dc1daa5d7');
|
||||
|
||||
|
||||
// "fake" radio button behaviour
|
||||
editable.input.$input.attr('name', 'test').attr('type', 'radio');
|
||||
@@ -2162,6 +2496,30 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init character info Tooltips
|
||||
* -> e.g. table cell 'question mark' icon
|
||||
* @param element
|
||||
* @param tableApi
|
||||
*/
|
||||
let initCharacterInfoTooltip = (element, tableApi) => {
|
||||
element.hoverIntent({
|
||||
over: function(e){
|
||||
let cellElement = $(this);
|
||||
let rowData = tableApi.row(cellElement.parents('tr')).data();
|
||||
cellElement.addCharacterInfoTooltip(rowData, {
|
||||
trigger: 'manual',
|
||||
placement: 'top',
|
||||
show: true
|
||||
});
|
||||
},
|
||||
out: function(e){
|
||||
$(this).destroyPopover();
|
||||
},
|
||||
selector: 'td.' + Util.config.helpClass
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* draw empty signature table
|
||||
* @param moduleElement
|
||||
@@ -2213,6 +2571,7 @@ define([
|
||||
initComplete: function(settings, json){
|
||||
let tableApi = this.api();
|
||||
|
||||
initCharacterInfoTooltip(this, tableApi);
|
||||
initGroupFilterButton(tableApi);
|
||||
initUndoButton(tableApi);
|
||||
initSelectAllButton(tableApi);
|
||||
@@ -2386,13 +2745,13 @@ define([
|
||||
|
||||
// event listener for global "paste" signatures into the page -------------------------------------------------
|
||||
moduleElement.on('pf:updateSystemSignatureModuleByClipboard', {tableApi: primaryTableApi}, function(e, clipboard){
|
||||
let lazyUpdateToggle = moduleElement.find('.' + config.moduleHeadlineIconLazyClass);
|
||||
let signatureOptions = {
|
||||
deleteOld: lazyUpdateToggle.hasClass('active') ? 1 : 0
|
||||
deleteOld: getLazyUpdateToggleStatus(moduleElement),
|
||||
deleteConnection: 0
|
||||
};
|
||||
|
||||
// "disable" lazy update icon -> prevents accidental removal for next paste #724
|
||||
lazyUpdateToggle.toggleClass('active', false);
|
||||
getLazyUpdateToggleElement(moduleElement).toggleClass('active', false);
|
||||
|
||||
updateSignatureTableByClipboard(e.data.tableApi, systemData, clipboard, signatureOptions);
|
||||
});
|
||||
@@ -2402,23 +2761,38 @@ define([
|
||||
moduleElement.find('.' + config.sigTableClass),
|
||||
'.editable-click:not(.editable-open) span[class^="pf-system-sec-"]'
|
||||
);
|
||||
};
|
||||
|
||||
// signature column - "info" popover --------------------------------------------------------------------------
|
||||
moduleElement.find('.' + config.sigTablePrimaryClass).hoverIntent({
|
||||
over: function(e){
|
||||
let cellElement = $(this);
|
||||
let rowData = primaryTableApi.row(cellElement.parents('tr')).data();
|
||||
cellElement.addCharacterInfoTooltip(rowData, {
|
||||
trigger: 'manual',
|
||||
placement: 'top',
|
||||
show: true
|
||||
});
|
||||
},
|
||||
out: function(e){
|
||||
$(this).destroyPopover();
|
||||
},
|
||||
selector: 'td.' + Util.config.helpClass
|
||||
});
|
||||
/**
|
||||
* get "lazy delete" toggle element
|
||||
* @param moduleElement
|
||||
* @returns {*}
|
||||
*/
|
||||
let getLazyUpdateToggleElement = moduleElement => moduleElement.find('.' + config.moduleHeadlineIconLazyClass);
|
||||
|
||||
/**
|
||||
* get status for "lazy delete" toggle
|
||||
* @param moduleElement
|
||||
* @returns {number}
|
||||
*/
|
||||
let getLazyUpdateToggleStatus = moduleElement => getLazyUpdateToggleElement(moduleElement).hasClass('active') ? 1 : 0;
|
||||
|
||||
/**
|
||||
* update 'counter' UI elements in 'signature reader' dialog
|
||||
* @param data
|
||||
*/
|
||||
let updateSignatureReaderCounters = data => {
|
||||
let counterElement = $('#' + config.sigInfoCountSigNewId).text(data.added || 0);
|
||||
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.added));
|
||||
|
||||
counterElement = $('#' + config.sigInfoCountSigChangeId).text(data.changed || 0);
|
||||
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.changed));
|
||||
|
||||
counterElement = $('#' + config.sigInfoCountSigDeleteId).text(data.deleted || 0);
|
||||
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.deleted));
|
||||
|
||||
counterElement = $('#' + config.sigInfoCountConDeleteId).text(data.deleteCon || 0);
|
||||
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.deleteCon));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2435,6 +2809,181 @@ define([
|
||||
return row;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param action
|
||||
* @param rowId
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
let getPromiseForRow = (action, rowId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve({action: action, rowId: rowId});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* callback for a changed row
|
||||
* @param rowIndex
|
||||
* @param colIndex
|
||||
* @param tableLoopCount
|
||||
* @param cellLoopCount
|
||||
* @param options CUSTOM parameter (not DataTables specific)!
|
||||
*/
|
||||
let rowUpdate = function(rowIndex, colIndex, tableLoopCount, cellLoopCount, options){
|
||||
let cell = this;
|
||||
let node = cell.nodes().to$();
|
||||
if(node.data('editable')){
|
||||
// xEditable is active -> should always be active!
|
||||
// set new value even if no change -> e.g. render selected Ids as text labels
|
||||
let oldValue = node.editable('getValue', true);
|
||||
|
||||
// ... some editable cells depend on each other (e.g. group->type, group->connection)
|
||||
switch(node.data('editable').options.name){
|
||||
case 'typeId':
|
||||
// ... disable if no type options found
|
||||
editableSelectCheck(node);
|
||||
break;
|
||||
case 'connectionId':
|
||||
// disables if no wormhole group set
|
||||
let groupId = cell.cell(rowIndex, 'group:name').data();
|
||||
if(groupId === 5){
|
||||
// wormhole
|
||||
editableEnable(node);
|
||||
}else{
|
||||
editableDisable(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// values should be set AFTER en/disabling of a field
|
||||
node.editable('setValue', cell.data());
|
||||
|
||||
if(oldValue !== cell.data()){
|
||||
// highlight cell on data change
|
||||
node.pulseBackgroundColor('changed', Util.getObjVal(options, 'keepVisible') || false);
|
||||
}
|
||||
}else if(node.hasClass(config.tableCellCounterClass)){
|
||||
// "updated" timestamp always changed
|
||||
node.pulseBackgroundColor('changed', Util.getObjVal(options, 'keepVisible') || false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* update 'info' (preview) signature table (inside 'signature reader' dialog)
|
||||
* @param tableApi
|
||||
* @param signaturesDataOrig
|
||||
* @param deleteOutdatedSignatures
|
||||
* @param deleteConnections
|
||||
*/
|
||||
let updateSignatureInfoTable = (tableApi, signaturesDataOrig, deleteOutdatedSignatures = false, deleteConnections = false) => {
|
||||
// clone signature array because of further manipulation
|
||||
let signaturesData = $.extend([], signaturesDataOrig);
|
||||
|
||||
let rowIdsExist = [];
|
||||
|
||||
let promisesAdded = [];
|
||||
let promisesChanged = [];
|
||||
let promisesDeleted = [];
|
||||
|
||||
let allRows = tableApi.rows();
|
||||
|
||||
let rowUpdateCallback = function(){
|
||||
rowUpdate.apply(this, [...arguments, {keepVisible: true}]);
|
||||
};
|
||||
|
||||
// update rows ------------------------------------------------------------------------------------------------
|
||||
allRows.every(function(rowIdx, tableLoop, rowLoop){
|
||||
let row = this;
|
||||
let rowData = row.data();
|
||||
|
||||
for(let i = 0; i < signaturesData.length; i++){
|
||||
if(signaturesData[i].name === rowData.name){
|
||||
let rowId = row.id(true);
|
||||
|
||||
// check if row was updated
|
||||
if(signaturesData[i].updated.updated > rowData.updated.updated){
|
||||
// set new row data -> draw() is executed after all changes made
|
||||
let newRowData = signaturesData[i];
|
||||
// keep "description" must not be replaced
|
||||
newRowData.description = rowData.description;
|
||||
// existing "groupId" must not be removed
|
||||
if(!newRowData.groupId){
|
||||
newRowData.groupId = rowData.groupId;
|
||||
newRowData.typeId = rowData.typeId;
|
||||
}else if(newRowData.groupId === rowData.groupId){
|
||||
if(!newRowData.typeId){
|
||||
newRowData.typeId = rowData.typeId;
|
||||
}
|
||||
}
|
||||
|
||||
// "created" timestamp will not change -> use existing
|
||||
newRowData.created = rowData.created;
|
||||
row.data(newRowData);
|
||||
|
||||
// bind new signature dataTable data() -> to xEditable inputs
|
||||
row.cells(row.id(true), ['id:name', 'group:name', 'type:name', 'description:name', 'connection:name', 'updated:name'])
|
||||
.every(rowUpdateCallback);
|
||||
|
||||
promisesChanged.push(getPromiseForRow('changed', rowId));
|
||||
}
|
||||
|
||||
rowIdsExist.push(rowIdx);
|
||||
|
||||
// remove signature data -> all left signatures will be added
|
||||
signaturesData.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// delete rows ------------------------------------------------------------------------------------------------
|
||||
if(deleteOutdatedSignatures){
|
||||
let rows = tableApi.rows((rowIdx, rowData, node) => !rowIdsExist.includes(rowIdx));
|
||||
rows.every(function(rowIdx, tableLoop, rowLoop){
|
||||
let row = this;
|
||||
let rowId = row.id(true);
|
||||
let rowElement = row.nodes().to$();
|
||||
let rowData = row.data();
|
||||
|
||||
rowElement.pulseBackgroundColor('deleted', true);
|
||||
|
||||
promisesChanged.push(getPromiseForRow('deleted', rowId));
|
||||
|
||||
// check if there is a connectionId.
|
||||
if(deleteConnections && Util.getObjVal(rowData, 'connection.id')){
|
||||
promisesChanged.push(getPromiseForRow('deleteCon', rowId));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// add rows ---------------------------------------------------------------------------------------------------
|
||||
for(let signatureData of signaturesData){
|
||||
let row = addSignatureRow(tableApi, signatureData);
|
||||
let rowElement = row.nodes().to$();
|
||||
rowElement.pulseBackgroundColor('added', true);
|
||||
|
||||
promisesAdded.push(getPromiseForRow('added', row.index()));
|
||||
}
|
||||
|
||||
// done -------------------------------------------------------------------------------------------------------
|
||||
Promise.all(promisesAdded.concat(promisesChanged, promisesDeleted)).then(payloads => {
|
||||
if(payloads.length){
|
||||
// table data changed -> draw() table changes
|
||||
tableApi.draw();
|
||||
|
||||
// no notifications if table was empty just progressbar notification is needed
|
||||
// sum payloads by "action"
|
||||
let notificationCounter = payloads.reduce((acc, payload) => {
|
||||
acc[payload.action]++;
|
||||
return acc;
|
||||
}, Object.assign({}, emptySignatureReaderCounterData));
|
||||
|
||||
updateSignatureReaderCounters(notificationCounter);
|
||||
|
||||
updateScannedSignaturesBar(tableApi, {showNotice: false});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* update signature table with new signatures
|
||||
* -> add/update/delete rows
|
||||
@@ -2463,51 +3012,6 @@ define([
|
||||
let allRows = tableApi.rows();
|
||||
let updateEmptyTable = !allRows.any();
|
||||
|
||||
let rowUpdate = function(rowIndex, colIndex, tableLoopCount, cellLoopCount){
|
||||
let cell = this;
|
||||
let node = cell.nodes().to$();
|
||||
if(node.data('editable')){
|
||||
// xEditable is active -> should always be active!
|
||||
// set new value even if no change -> e.g. render selected Ids as text labels
|
||||
let oldValue = node.editable('getValue', true);
|
||||
|
||||
// ... some editable cells depend on each other (e.g. group->type, group->connection)
|
||||
switch(node.data('editable').options.name){
|
||||
case 'typeId':
|
||||
// ... disable if no type options found
|
||||
editableSelectCheck(node);
|
||||
break;
|
||||
case 'connectionId':
|
||||
// disables if no wormhole group set
|
||||
let groupId = cell.cell(rowIndex, 'group:name').data();
|
||||
if(groupId === 5){
|
||||
// wormhole
|
||||
editableEnable(node);
|
||||
}else{
|
||||
editableDisable(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// values should be set AFTER en/disabling of a field
|
||||
node.editable('setValue', cell.data());
|
||||
|
||||
if(oldValue !== cell.data()){
|
||||
// highlight cell on data change
|
||||
node.pulseBackgroundColor('changed');
|
||||
}
|
||||
}else if(node.hasClass(config.tableCellCounterClass)){
|
||||
// "updated" timestamp always changed
|
||||
node.pulseBackgroundColor('changed');
|
||||
}
|
||||
};
|
||||
|
||||
let getPromiseForRow = (action, rowId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve({action: action, rowId: rowId});
|
||||
});
|
||||
};
|
||||
|
||||
// update signatures ------------------------------------------------------------------------------------------
|
||||
allRows.every(function(rowIdx, tableLoop, rowLoop){
|
||||
let row = this;
|
||||
@@ -2588,7 +3092,7 @@ define([
|
||||
}
|
||||
acc[payload.action]++;
|
||||
return acc;
|
||||
}, {});
|
||||
}, Object.assign({}, emptySignatureReaderCounterData));
|
||||
|
||||
let notification = '';
|
||||
if(notificationCounter.added > 0){
|
||||
@@ -2606,6 +3110,13 @@ define([
|
||||
}
|
||||
|
||||
updateScannedSignaturesBar(tableApi, {showNotice: true});
|
||||
|
||||
// at this point the 'primary' signature table update is done
|
||||
// we need to check if there is an open 'signature reader' dialog,
|
||||
// that needs to update its 'preview' signature table
|
||||
// -> to use DataTables "drawCallback" option or "draw.dt" event is not the *best* option:
|
||||
// Both are called to frequently (e.g. after filter/sort actions)
|
||||
$('.' + config.sigReaderDialogClass + '.in').trigger('pf:updateSignatureReaderDialog');
|
||||
}
|
||||
|
||||
// unlock table
|
||||
|
||||
@@ -75,13 +75,11 @@ define([
|
||||
select2ImageLazyLoadClass: 'pf-select2-image-lazyLoad',
|
||||
|
||||
// animation
|
||||
animationPulseSuccessClass: 'pf-animation-pulse-success', // animation class
|
||||
animationPulseWarningClass: 'pf-animation-pulse-warning', // animation class
|
||||
animationPulseDangerClass: 'pf-animation-pulse-danger', // animation class
|
||||
animationPulseClassPrefix: 'pf-animation-pulse-', // class prefix for "pulse" background animation
|
||||
|
||||
// popover
|
||||
popoverTriggerClass: 'pf-popover-trigger', // class for "popover" trigger elements
|
||||
popoverSmallClass: 'pf-popover-small', // class for small "popover"
|
||||
popoverSmallClass: 'popover-small', // class for small "popover"
|
||||
popoverCharacterClass: 'pf-popover-character', // class for character "popover"
|
||||
|
||||
// Summernote
|
||||
@@ -765,28 +763,30 @@ define([
|
||||
/**
|
||||
* highlight jquery elements
|
||||
* add/remove css class for keyframe animation
|
||||
* @returns {any|JQuery|*}
|
||||
* @param status
|
||||
* @param keepVisible
|
||||
* @param clear
|
||||
* @returns {void|*|undefined}
|
||||
*/
|
||||
$.fn.pulseBackgroundColor = function(status, clear){
|
||||
|
||||
let animationClass = '';
|
||||
$.fn.pulseBackgroundColor = function(status, keepVisible = false, clear = false){
|
||||
let animationClass = config.animationPulseClassPrefix;
|
||||
switch(status){
|
||||
case 'added':
|
||||
animationClass = config.animationPulseSuccessClass;
|
||||
break;
|
||||
case 'changed':
|
||||
animationClass = config.animationPulseWarningClass;
|
||||
break;
|
||||
case 'deleted':
|
||||
animationClass = config.animationPulseDangerClass;
|
||||
break;
|
||||
case 'added': animationClass += 'success'; break;
|
||||
case 'changed': animationClass += 'warning'; break;
|
||||
case 'deleted': animationClass += 'danger'; break;
|
||||
default: console.warn('Invalid status: %s', status);
|
||||
}
|
||||
|
||||
// if keepVisible -> background color animation class will not be deleted
|
||||
if(keepVisible){
|
||||
animationClass += '-keep';
|
||||
}
|
||||
|
||||
let clearTimer = element => {
|
||||
element.removeClass( animationClass );
|
||||
element.removeClass(animationClass);
|
||||
let currentTimer = element.data('animationTimer');
|
||||
|
||||
if( animationTimerCache.hasOwnProperty(currentTimer) ){
|
||||
if(animationTimerCache.hasOwnProperty(currentTimer)){
|
||||
clearTimeout( currentTimer );
|
||||
delete animationTimerCache[currentTimer];
|
||||
element.removeData('animationTimer');
|
||||
@@ -796,18 +796,20 @@ define([
|
||||
return this.each(function(){
|
||||
let element = $(this);
|
||||
|
||||
if( element.hasClass(animationClass) ){
|
||||
if(element.hasClass(animationClass)){
|
||||
// clear timer -> set new timer
|
||||
clearTimer(element);
|
||||
}
|
||||
|
||||
if(clear !== true){
|
||||
if(!clear){
|
||||
element.addClass(animationClass);
|
||||
let timer = setTimeout(clearTimer, 1500, element);
|
||||
element.data('animationTimer', timer);
|
||||
animationTimerCache[timer] = true;
|
||||
// remove class after animation finish, if not 'keepVisible'
|
||||
if(!keepVisible){
|
||||
let timer = setTimeout(clearTimer, 1500, element);
|
||||
element.data('animationTimer', timer);
|
||||
animationTimerCache[timer] = true;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
@@ -971,6 +973,14 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* capitalize first letter
|
||||
* @returns {string}
|
||||
*/
|
||||
String.prototype.capitalize = function(){
|
||||
return this.charAt(0).toUpperCase() + this.slice(1);
|
||||
};
|
||||
|
||||
/**
|
||||
* get hash from string
|
||||
* @returns {number}
|
||||
@@ -1158,6 +1168,52 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get template for Bootstrap "Confirmation" popover plugin
|
||||
* -> if HTML 'content' not set, we expect the default template
|
||||
* https://www.npmjs.com/package/bs-confirmation
|
||||
* -> options.size for "small" popover layout
|
||||
* -> options.noTitle for hide title element
|
||||
* @param content
|
||||
* @param options
|
||||
* @returns {string}
|
||||
*/
|
||||
let getConfirmationTemplate = (content, options) => {
|
||||
let getButtons = () => {
|
||||
let buttonHtml = '<div class="btn-group">';
|
||||
buttonHtml += '<a data-apply="confirmation">Yes</a>';
|
||||
buttonHtml += '<a data-dismiss="confirmation">No</a>';
|
||||
buttonHtml += '</div>';
|
||||
return buttonHtml;
|
||||
};
|
||||
|
||||
let getContent = content => {
|
||||
let contentHtml = content ? content : '';
|
||||
contentHtml += '<div class="popover-footer">';
|
||||
contentHtml += getButtons();
|
||||
contentHtml += '</div>';
|
||||
return contentHtml;
|
||||
};
|
||||
|
||||
let popoverClass = ['popover'];
|
||||
if('small' === getObjVal(options, 'size')){
|
||||
popoverClass.push('popover-small');
|
||||
}
|
||||
|
||||
let contentClass = ['popover-content', 'no-padding'];
|
||||
|
||||
let html = '<div class="' + popoverClass.join(' ') + '">';
|
||||
html += '<div class="arrow"></div>';
|
||||
if(true !== getObjVal(options, 'noTitle')){
|
||||
html += '<h3 class="popover-title"></h3>';
|
||||
}
|
||||
html += '<div class="' + contentClass.join(' ') + '">';
|
||||
html += getContent(content);
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
return html;
|
||||
};
|
||||
|
||||
/**
|
||||
* convert XEditable Select <option> data into Select2 data format
|
||||
* -> "prepend" (empty) options get added, too
|
||||
@@ -1239,7 +1295,7 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set default configuration for "Bootbox"
|
||||
* set default configuration for "Bootbox" plugin
|
||||
*/
|
||||
let initDefaultBootboxConfig = () => {
|
||||
bootbox.setDefaults({
|
||||
@@ -1248,7 +1304,22 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set default configuration for "Select2"
|
||||
* set default configuration for "Confirmation" popover plugin
|
||||
*/
|
||||
let initDefaultConfirmationConfig = () => {
|
||||
$.fn.confirmation.Constructor.DEFAULTS.placement = 'left';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.container = 'body';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnCancelClass = 'btn btn-sm btn-default';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnCancelLabel = 'cancel';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnCancelIcon = 'fas fa-fw fa-ban';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnOkClass = 'btn btn-sm btn-danger';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnOkLabel = 'delete';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.btnOkIcon = 'fas fa-fw fa-times';
|
||||
$.fn.confirmation.Constructor.DEFAULTS.template = getConfirmationTemplate();
|
||||
};
|
||||
|
||||
/**
|
||||
* set default configuration for "Select2" plugin
|
||||
*/
|
||||
let initDefaultSelect2Config = () => {
|
||||
$.fn.select2.defaults.set('theme', 'pathfinder');
|
||||
@@ -1372,7 +1443,7 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set default configuration for "xEditable"
|
||||
* set default configuration for "xEditable" plugin
|
||||
*/
|
||||
let initDefaultEditableConfig = () => {
|
||||
// use fontAwesome buttons template
|
||||
@@ -1462,7 +1533,7 @@ define([
|
||||
// Server is running with GMT/UTC (EVE Time)
|
||||
let localDate = new Date();
|
||||
|
||||
let serverDate= new Date(
|
||||
let serverDate = new Date(
|
||||
localDate.getUTCFullYear(),
|
||||
localDate.getUTCMonth(),
|
||||
localDate.getUTCDate(),
|
||||
@@ -1766,8 +1837,8 @@ define([
|
||||
* Request data from Server
|
||||
* -> This function should be used (in future) for all Ajax and REST API calls
|
||||
* -> works as a "wrapper" for jQueries ajax() method
|
||||
* @param action
|
||||
* @param entity
|
||||
* @param {String} action
|
||||
* @param {String} entity
|
||||
* @param ids
|
||||
* @param data
|
||||
* @param context
|
||||
@@ -1779,7 +1850,7 @@ define([
|
||||
let requestExecutor = (resolve, reject) => {
|
||||
let payload = {
|
||||
action: 'request',
|
||||
name: action.toLowerCase() + entity.charAt(0).toUpperCase() + entity.slice(1)
|
||||
name: action.toLowerCase() + entity.capitalize()
|
||||
};
|
||||
|
||||
// build request url --------------------------------------------------------------------------------------
|
||||
@@ -2206,7 +2277,7 @@ define([
|
||||
let typeClass = '';
|
||||
let matches = regex.exec(typeName.toLowerCase());
|
||||
if(matches && matches[1]){
|
||||
typeName = matches[1].charAt(0).toUpperCase() + matches[1].slice(1);
|
||||
typeName = matches[1].capitalize();
|
||||
typeClass = getPlanetInfo(matches[1]);
|
||||
}
|
||||
|
||||
@@ -3356,6 +3427,7 @@ define([
|
||||
showVersionInfo: showVersionInfo,
|
||||
initPrototypes: initPrototypes,
|
||||
initDefaultBootboxConfig: initDefaultBootboxConfig,
|
||||
initDefaultConfirmationConfig: initDefaultConfirmationConfig,
|
||||
initDefaultSelect2Config: initDefaultSelect2Config,
|
||||
initDefaultEditableConfig: initDefaultEditableConfig,
|
||||
getCurrentTriggerDelay: getCurrentTriggerDelay,
|
||||
@@ -3410,6 +3482,7 @@ define([
|
||||
getCurrentCharacterLog: getCurrentCharacterLog,
|
||||
findInViewport: findInViewport,
|
||||
initScrollSpy: initScrollSpy,
|
||||
getConfirmationTemplate: getConfirmationTemplate,
|
||||
convertXEditableOptionsToSelect2: convertXEditableOptionsToSelect2,
|
||||
flattenXEditableSelectArray: flattenXEditableSelectArray,
|
||||
getCharacterDataBySystemId: getCharacterDataBySystemId,
|
||||
|
||||
4
public/js/v1.5.4/lib/bootbox.min.js
vendored
4
public/js/v1.5.4/lib/bootbox.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,9 +1,9 @@
|
||||
/*!
|
||||
* hoverIntent v1.9.0 // 2017.09.01 // jQuery v1.7.0+
|
||||
* hoverIntent v1.10.0 // 2019.02.25 // jQuery v1.7.0+
|
||||
* http://briancherne.github.io/jquery-hoverIntent/
|
||||
*
|
||||
* You may use hoverIntent under the terms of the MIT license. Basically that
|
||||
* means you are free to use hoverIntent as long as this header is left intact.
|
||||
* Copyright 2007-2017 Brian Cherne
|
||||
* Copyright 2007-2019 Brian Cherne
|
||||
*/
|
||||
!function(factory){"use strict";"function"==typeof define&&define.amd?define(["jquery"],factory):jQuery&&!jQuery.fn.hoverIntent&&factory(jQuery)}(function($){"use strict";var cX,cY,_cfg={interval:100,sensitivity:6,timeout:0},INSTANCE_COUNT=0,track=function(ev){cX=ev.pageX,cY=ev.pageY},compare=function(ev,$el,s,cfg){if(Math.sqrt((s.pX-cX)*(s.pX-cX)+(s.pY-cY)*(s.pY-cY))<cfg.sensitivity)return $el.off(s.event,track),delete s.timeoutId,s.isActive=!0,ev.pageX=cX,ev.pageY=cY,delete s.pX,delete s.pY,cfg.over.apply($el[0],[ev]);s.pX=cX,s.pY=cY,s.timeoutId=setTimeout(function(){compare(ev,$el,s,cfg)},cfg.interval)},delay=function(ev,$el,s,out){return delete $el.data("hoverIntent")[s.id],out.apply($el[0],[ev])};$.fn.hoverIntent=function(handlerIn,handlerOut,selector){var instanceId=INSTANCE_COUNT++,cfg=$.extend({},_cfg);$.isPlainObject(handlerIn)?(cfg=$.extend(cfg,handlerIn),$.isFunction(cfg.out)||(cfg.out=cfg.over)):cfg=$.isFunction(handlerOut)?$.extend(cfg,{over:handlerIn,out:handlerOut,selector:selector}):$.extend(cfg,{over:handlerIn,out:handlerIn,selector:handlerOut});var handleHover=function(e){var ev=$.extend({},e),$el=$(this),hoverIntentData=$el.data("hoverIntent");hoverIntentData||$el.data("hoverIntent",hoverIntentData={});var state=hoverIntentData[instanceId];state||(hoverIntentData[instanceId]=state={id:instanceId}),state.timeoutId&&(state.timeoutId=clearTimeout(state.timeoutId));var mousemove=state.event="mousemove.hoverIntent.hoverIntent"+instanceId;if("mouseenter"===e.type){if(state.isActive)return;state.pX=ev.pageX,state.pY=ev.pageY,$el.off(mousemove,track).on(mousemove,track),state.timeoutId=setTimeout(function(){compare(ev,$el,state,cfg)},cfg.interval)}else{if(!state.isActive)return;$el.off(mousemove,track),state.timeoutId=setTimeout(function(){delay(ev,$el,state,cfg.out)},cfg.timeout)}};return this.on({"mouseenter.hoverIntent":handleHover,"mouseleave.hoverIntent":handleHover},cfg.selector)}});
|
||||
!function(factory){"use strict";"function"==typeof define&&define.amd?define(["jquery"],factory):"object"==typeof module&&module.exports?module.exports=factory(require("jquery")):jQuery&&!jQuery.fn.hoverIntent&&factory(jQuery)}(function($){"use strict";var cX,cY,_cfg={interval:100,sensitivity:6,timeout:0},INSTANCE_COUNT=0,track=function(ev){cX=ev.pageX,cY=ev.pageY},compare=function(ev,$el,s,cfg){if(Math.sqrt((s.pX-cX)*(s.pX-cX)+(s.pY-cY)*(s.pY-cY))<cfg.sensitivity)return $el.off(s.event,track),delete s.timeoutId,s.isActive=!0,ev.pageX=cX,ev.pageY=cY,delete s.pX,delete s.pY,cfg.over.apply($el[0],[ev]);s.pX=cX,s.pY=cY,s.timeoutId=setTimeout(function(){compare(ev,$el,s,cfg)},cfg.interval)};$.fn.hoverIntent=function(handlerIn,handlerOut,selector){var instanceId=INSTANCE_COUNT++,cfg=$.extend({},_cfg);$.isPlainObject(handlerIn)?(cfg=$.extend(cfg,handlerIn),$.isFunction(cfg.out)||(cfg.out=cfg.over)):cfg=$.isFunction(handlerOut)?$.extend(cfg,{over:handlerIn,out:handlerOut,selector:selector}):$.extend(cfg,{over:handlerIn,out:handlerIn,selector:handlerOut});var handleHover=function(e){var ev=$.extend({},e),$el=$(this),hoverIntentData=$el.data("hoverIntent");hoverIntentData||$el.data("hoverIntent",hoverIntentData={});var state=hoverIntentData[instanceId];state||(hoverIntentData[instanceId]=state={id:instanceId}),state.timeoutId&&(state.timeoutId=clearTimeout(state.timeoutId));var mousemove=state.event="mousemove.hoverIntent.hoverIntent"+instanceId;if("mouseenter"===e.type){if(state.isActive)return;state.pX=ev.pageX,state.pY=ev.pageY,$el.off(mousemove,track).on(mousemove,track),state.timeoutId=setTimeout(function(){compare(ev,$el,state,cfg)},cfg.interval)}else{if(!state.isActive)return;$el.off(mousemove,track),state.timeoutId=setTimeout(function(){!function(ev,$el,s,out){delete $el.data("hoverIntent")[s.id],out.apply($el[0],[ev])}(ev,$el,state,cfg.out)},cfg.timeout)}};return this.on({"mouseenter.hoverIntent":handleHover,"mouseleave.hoverIntent":handleHover},cfg.selector)}});
|
||||
@@ -1,32 +1,79 @@
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="form-group" style="margin-bottom: 0;">
|
||||
<label class="col-sm-2 control-label" for="form_result">Scan result</label>
|
||||
<div class="col-xs-4 col-sm-3 col-md-2">
|
||||
<h4><i class="fas fa-fw fa-cogs"></i> Update options</h4>
|
||||
|
||||
<div class="checkbox checkbox-warning">
|
||||
<input id="{{sigReaderLazyUpdateId}}" name="deleteOld" value="1" type="checkbox" {{#sigInfoLazyUpdateStatus}}checked=""{{/sigInfoLazyUpdateStatus}}>
|
||||
<label for="{{sigReaderLazyUpdateId}}">'lazy' delete
|
||||
(<i class="fas fa-fw fa-exchange-alt"></i>)
|
||||
<i class="fas fa-fw fa-question-circle pf-help-light" title="Delete saved signatures, not found in scan result"></i>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<i class="fas fa-tree-child"></i>
|
||||
|
||||
<div class="checkbox checkbox-danger">
|
||||
<input id="{{sigReaderConnectionDeleteId}}" name="deleteConnection" value="1" type="checkbox">
|
||||
<label for="{{sigReaderConnectionDeleteId}}">Delete 'leads to'
|
||||
<i class="fas fa-fw fa-question-circle pf-help-light" title="Delete 'leads to' connections from map, on signature delete"></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-8 col-sm-9 col-md-10">
|
||||
<div class="form-group has-feedback" style="margin-bottom: 0;">
|
||||
<label for="{{sigInfoTextareaId}}" class="col-sm-2 control-label">Scan result</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea style="resize: vertical" rows="3" id="form_result" name="clipboard" class="form-control custom-scroll" autofocus></textarea>
|
||||
<span class="help-block">
|
||||
Copy and paste signatures from your probe scanning window.<br>
|
||||
Hit <kbd>ctrl</kbd> + <kbd>c</kbd> (copy) then <kbd>ctrl</kbd> + <kbd>v</kbd> (paste).
|
||||
This tool can add and update signatures.
|
||||
</span>
|
||||
<textarea id="{{sigInfoTextareaId}}" name="clipboard" class="form-control" rows="4" data-clipboard="rdd" data-required-error="Scan result can not be empty" required></textarea>
|
||||
<div class="help-block with-errors">
|
||||
Copy ( <kbd>ctrl</kbd> + <kbd>c</kbd> ) and paste ( <kbd>ctrl</kbd> + <kbd>v</kbd> ) scan result.
|
||||
</div>
|
||||
<span class="fas form-control-feedback" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h4>
|
||||
<i class="fas fa-eye fa-fw"></i> Preview
|
||||
<span class="label label-default txt-color txt-color-warning bg-color bg-color-grayDarker">beta</span>
|
||||
{{{sigInfoProgressElement}}}
|
||||
<span class="progress-label-right">0%</span>
|
||||
</h4>
|
||||
|
||||
<div id="{{sigInfoId}}" class="pf-dynamic-area"></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-8">
|
||||
<div class="well well-sm">
|
||||
<div class="row">
|
||||
<div class="col-xs-3">Signatures:</div>
|
||||
<div class="col-xs-3 text-right" title="New signatures found">
|
||||
new
|
||||
<kbd id="{{sigInfoCountSigNewId}}" class="txt-color" data-class="txt-color-success">0</kbd>
|
||||
</div>
|
||||
<div class="col-xs-3 text-right" title="Update signatures">
|
||||
change
|
||||
<kbd id="{{sigInfoCountSigChangeId}}" class="txt-color" data-class="txt-color-warning">0</kbd>
|
||||
</div>
|
||||
<div class="col-xs-3 text-right" title="Delete signatures">
|
||||
delete
|
||||
<kbd id="{{sigInfoCountSigDeleteId}}" class="txt-color" data-class="txt-color-red">0</kbd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="form-group" style="margin-bottom: 0;">
|
||||
<div class="col-sm-offset-2 col-sm-10 col-xs-9">
|
||||
<div class="checkbox checkbox-warning">
|
||||
<input id="form_delete" name="deleteOld" value="1" type="checkbox">
|
||||
<label for="form_delete" title="delete saved signatures not found in scan result">'lazy' delete
|
||||
(<i class="fas fa-fw fa-exchange-alt"></i>)
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="well well-sm">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">Connections:</div>
|
||||
<div class="col-xs-6 text-right" title="Delete linked connections">
|
||||
delete
|
||||
<kbd id="{{sigInfoCountConDeleteId}}" class="txt-color" data-class="txt-color-red">0</kbd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
&.bg-color-lighten { background-color: $lighten !important; }
|
||||
&.bg-color-white { background-color: $white !important; }
|
||||
&.bg-color-gray { background-color: $gray !important; }
|
||||
&.bg-color-grayDark { background-color: $greyDark !important; }
|
||||
&.bg-color-grayDark { background-color: $gray-dark !important; }
|
||||
&.bg-color-grayDarker { background-color: $gray-darker !important; }
|
||||
&.bg-color-magenta { background-color: $magenta !important; }
|
||||
&.bg-color-tealLighter { background-color: $teal-lighter !important; }
|
||||
|
||||
@@ -546,7 +546,7 @@ $modal-title-padding: 14px;
|
||||
$modal-title-line-height: $line-height-base;
|
||||
|
||||
$modal-content-bg: $gray;
|
||||
$modal-content-border-color: rgba(0,0,0,.2);
|
||||
$modal-content-border-color: transparent;
|
||||
$modal-content-fallback-border-color: #999;
|
||||
|
||||
$modal-backdrop-bg: #000;
|
||||
|
||||
@@ -53,8 +53,9 @@
|
||||
.modal-content {
|
||||
position: relative;
|
||||
background-color: $modal-content-bg;
|
||||
border: 1px solid $modal-content-fallback-border-color; //old browsers fallback (ie8 etc)
|
||||
border: 1px solid $modal-content-border-color;
|
||||
//border: 1px solid $modal-content-fallback-border-color; //old browsers fallback (ie8 etc)
|
||||
//border: 1px solid $modal-content-border-color;
|
||||
border: none;
|
||||
//border-radius: $border-radius-large;
|
||||
@include box-shadow(0 3px 9px rgba(0,0,0,.5));
|
||||
background-clip: padding-box;
|
||||
@@ -106,6 +107,8 @@
|
||||
position: relative;
|
||||
padding: $modal-inner-padding;
|
||||
color: $gray-lighter;
|
||||
border-left: 1px solid $modal-content-bg;
|
||||
border-right: 1px solid $modal-content-bg;
|
||||
}
|
||||
|
||||
// Footer (for actions)
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
z-index: $zindex-popover;
|
||||
display: none;
|
||||
max-width: $popover-max-width;
|
||||
padding: 1px;
|
||||
//padding: 1px;
|
||||
padding: 0;
|
||||
text-align: left; // Reset given new insertion method
|
||||
background-color: $popover-bg;
|
||||
background-clip: padding-box;
|
||||
@@ -36,8 +37,8 @@
|
||||
font-weight: normal;
|
||||
line-height: 18px;
|
||||
background-color: $popover-title-bg;
|
||||
border-bottom: 1px solid darken($popover-title-bg, 5%);
|
||||
border-radius: 5px 5px 0 0;
|
||||
border-bottom: 1px solid darken($popover-bg, 5%);
|
||||
@include border-top-radius(($border-radius-large - 1));
|
||||
color: $gray-light
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@import "_function";
|
||||
@import "_animation";
|
||||
@import "_fonts";
|
||||
@import "_main";
|
||||
|
||||
@@ -94,86 +94,77 @@
|
||||
}
|
||||
|
||||
// pulse-out ======================================================================================
|
||||
.pf-animation-pulse-success{
|
||||
@include animation( pulseBackgroundSuccess 1s 1 );
|
||||
@include animation-timing-function( cubic-bezier(0.53, -0.03, 0.68, 0.38) );
|
||||
@mixin pf-pulse-keyframes($name, $color, $backgroundColor, $keepVisible: false){
|
||||
@include keyframes($name){
|
||||
0% {
|
||||
@if $keepVisible {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
10% {
|
||||
background-color: $backgroundColor;
|
||||
color: $color;
|
||||
}
|
||||
100% {
|
||||
@if $keepVisible {
|
||||
background-color: rgba($backgroundColor, 0.3);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
.sorting_1{
|
||||
@include animation( pulseBackgroundSuccessActive 1s 1 );
|
||||
@include animation-timing-function( cubic-bezier(0.53, -0.03, 0.68, 0.38) );
|
||||
@mixin pf-pulse-Background($status, $keepVisible: false){
|
||||
$statusMap: (
|
||||
success: (
|
||||
color: $gray-dark,
|
||||
backgroundColor: $green-dark
|
||||
),
|
||||
warning: (
|
||||
color: $gray-darker,
|
||||
backgroundColor: $orange
|
||||
),
|
||||
danger: (
|
||||
color: $gray-darker,
|
||||
backgroundColor: $red
|
||||
)
|
||||
);
|
||||
|
||||
$map: map-get($statusMap, $status);
|
||||
|
||||
$name: pulseBackground + capitalize($status);
|
||||
$nameActive: $name + 'Active';
|
||||
|
||||
$className: 'pf-animation-pulse-' + $status;
|
||||
@if $keepVisible {
|
||||
$className: str-insert($className, '-keep', -1);
|
||||
$name: str-insert($name, 'Keep', -1);
|
||||
$nameActive: str-insert($nameActive, 'Keep', -1);
|
||||
}
|
||||
|
||||
@include pf-pulse-keyframes($name, map-get($map, 'color'), map-get($map, 'backgroundColor'), $keepVisible);
|
||||
@include pf-pulse-keyframes($nameActive, map-get($map, 'color'), darken(map-get($map, 'backgroundColor'), 5%), $keepVisible);
|
||||
|
||||
.#{$className}{
|
||||
@include animation($name 1s 1);
|
||||
@include animation-timing-function(cubic-bezier(0.53, -0.03, 0.68, 0.38));
|
||||
will-change: color, background-color;
|
||||
animation-fill-mode: forwards;
|
||||
|
||||
.sorting_1{
|
||||
@include animation($nameActive 1s 1);
|
||||
@include animation-timing-function(cubic-bezier(0.53, -0.03, 0.68, 0.38));
|
||||
will-change: color, background-color;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pf-animation-pulse-warning{
|
||||
@include animation( pulseBackgroundWarning 1s 1 );
|
||||
@include animation-timing-function( cubic-bezier(0.53, -0.03, 0.68, 0.38) );
|
||||
|
||||
.sorting_1{
|
||||
@include animation( pulseBackgroundWarningActive 1s 1 );
|
||||
@include animation-timing-function( cubic-bezier(0.53, -0.03, 0.68, 0.38) );
|
||||
}
|
||||
}
|
||||
|
||||
.pf-animation-pulse-danger{
|
||||
@include animation( pulseBackgroundDanger 1s 1 );
|
||||
@include animation-timing-function( cubic-bezier(0.53, -0.03, 0.68, 0.38) );
|
||||
|
||||
.sorting_1{
|
||||
@include animation( pulseBackgroundDangerActive 1s 1 );
|
||||
@include animation-timing-function( cubic-bezier(0.53, -0.03, 0.68, 0.38) );
|
||||
}
|
||||
}
|
||||
|
||||
@include keyframes(pulseBackgroundSuccess){
|
||||
0% {}
|
||||
10% {
|
||||
background-color: $green-dark;
|
||||
color: $gray-dark;
|
||||
}
|
||||
100% {}
|
||||
};
|
||||
@include keyframes(pulseBackgroundSuccessActive){
|
||||
0% {}
|
||||
10% {
|
||||
background-color: darken($green-dark, 5%);
|
||||
color: $gray-dark;
|
||||
}
|
||||
100% {}
|
||||
};
|
||||
|
||||
@include keyframes(pulseBackgroundWarning){
|
||||
0% {}
|
||||
10% {
|
||||
background-color: $orange;
|
||||
color: $gray-darker;
|
||||
}
|
||||
100% {}
|
||||
};
|
||||
@include keyframes(pulseBackgroundWarningActive){
|
||||
0% {}
|
||||
10% {
|
||||
background-color: darken($orange, 5%);
|
||||
color: $gray-darker;
|
||||
}
|
||||
100% {}
|
||||
};
|
||||
|
||||
@include keyframes(pulseBackgroundDanger){
|
||||
0% {}
|
||||
10% {
|
||||
background-color: $red;
|
||||
color: $gray-darker;
|
||||
}
|
||||
100% {}
|
||||
};
|
||||
@include keyframes(pulseBackgroundDangerActive){
|
||||
0% {}
|
||||
10% {
|
||||
background-color: darken($red, 5%);
|
||||
color: $gray-darker;
|
||||
}
|
||||
100% {}
|
||||
};
|
||||
@include pf-pulse-Background('success');
|
||||
@include pf-pulse-Background('success', true);
|
||||
@include pf-pulse-Background('warning');
|
||||
@include pf-pulse-Background('warning', true);
|
||||
@include pf-pulse-Background('danger');
|
||||
@include pf-pulse-Background('danger', true);
|
||||
|
||||
// rotate =========================================================================================
|
||||
.pf-animate-rotate{
|
||||
|
||||
@@ -246,6 +246,49 @@
|
||||
}
|
||||
}
|
||||
|
||||
// signature reader dialog ====================================================
|
||||
.pf-sig-reader-dialog{
|
||||
h4 {
|
||||
margin-top: 8px;
|
||||
|
||||
.pf-system-progress-scanned{
|
||||
display: inline-block;
|
||||
margin-left: 20px;
|
||||
width: calc(100% - 255px);
|
||||
|
||||
.progress{
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-label-right{
|
||||
margin-left: 8px;
|
||||
vertical-align: middle;
|
||||
font-size: 11px;
|
||||
opacity: 0.65;
|
||||
}
|
||||
}
|
||||
|
||||
.fa-tree-child + .checkbox{
|
||||
margin-left: 5px; // "delete connections" checkbox
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#pf-sig-info{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.pf-sig-table-info{
|
||||
tbody{
|
||||
pointer-events: none; // disables "hover" effect for rows/cells
|
||||
}
|
||||
// disabled xEditable table cells should have the "enabled" color
|
||||
.editable-click.editable-disabled{
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// jump info dialog ===========================================================
|
||||
.pf-jump-info-dialog{
|
||||
blockquote{
|
||||
|
||||
3
sass/layout/_function.scss
Normal file
3
sass/layout/_function.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
@function capitalize($string) {
|
||||
@return to-upper-case(str-slice($string, 1, 1)) + str-slice($string, 2);
|
||||
}
|
||||
@@ -627,6 +627,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
.badge{
|
||||
color: $gray-lighter;
|
||||
background-color: $gray-darker;
|
||||
}
|
||||
|
||||
// table
|
||||
table tr td {
|
||||
line-height: 1;
|
||||
|
||||
@@ -40,6 +40,10 @@ em{
|
||||
}
|
||||
}
|
||||
|
||||
.pf-font-uppercase{
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.pf-font-capitalize{
|
||||
text-transform: capitalize;
|
||||
}
|
||||
@@ -56,6 +60,15 @@ em{
|
||||
}
|
||||
}
|
||||
|
||||
.fa-tree-child{
|
||||
@extend .fa-fw;
|
||||
@extend .fa-lg;
|
||||
@extend .fa-level-up-alt;
|
||||
@extend .fa-rotate-90;
|
||||
color: $gray-light;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.no-scroll{
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -141,6 +154,7 @@ em{
|
||||
|
||||
.pf-help-default{
|
||||
cursor: help;
|
||||
pointer-events: auto; // enable mouse events even if a parent was set to 'none' (e.g. disabled xEditable cells in sig-reader dialog table)
|
||||
@include transition( color 0.08s ease-out );
|
||||
|
||||
&:hover{
|
||||
@@ -196,10 +210,6 @@ a{
|
||||
// form fields custom styles ======================================================================
|
||||
.editable-input{
|
||||
|
||||
.pf-editable-name{
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
optgroup[label]{
|
||||
background-color: $gray;
|
||||
color: $gray-light;
|
||||
@@ -230,6 +240,10 @@ a{
|
||||
.pf-editable-unknown[value='0'] + span {
|
||||
color: $red;
|
||||
}
|
||||
|
||||
.pf-editable-warn + span {
|
||||
color: $orange;
|
||||
}
|
||||
}
|
||||
}
|
||||
select:active, select:hover {
|
||||
@@ -285,6 +299,12 @@ select:active, select:hover {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.pf-table-toolbar-status{
|
||||
text-align: center;
|
||||
line-height: 22px;
|
||||
color: $gray-light;
|
||||
}
|
||||
|
||||
.dt-buttons,
|
||||
.dt-stats{
|
||||
display: inline-block;
|
||||
|
||||
@@ -22,6 +22,19 @@
|
||||
|
||||
.popover-content {
|
||||
font-family: $font-family-readable;
|
||||
|
||||
> .hidden + .popover-footer, // first content child is .hidden -> border radius to footer
|
||||
> .popover-footer:first-child { // no content -> border radius to footer
|
||||
@include border-top-radius(($border-radius-large - 1));
|
||||
}
|
||||
}
|
||||
|
||||
.popover-footer{
|
||||
margin: 0; // reset heading margin
|
||||
padding: 8px 14px; // same as popover-title
|
||||
background-color: $popover-title-bg;
|
||||
border-top: 1px solid darken($popover-bg, 5%);
|
||||
@include border-bottom-radius(($border-radius-large - 1));
|
||||
}
|
||||
|
||||
// image in popover
|
||||
@@ -53,13 +66,22 @@
|
||||
}
|
||||
|
||||
// smaller variant ----------------------------------------------------------------------------------------------------
|
||||
.pf-popover-small{
|
||||
.popover-small{
|
||||
.popover-title {
|
||||
padding: 3px 6px;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
.popover-content {
|
||||
padding: 6px 1px 3px;
|
||||
padding: 4px 2px 4px;
|
||||
}
|
||||
|
||||
// "special" content wrapper for popups with "footer" (.popover-footer) element
|
||||
.popover-content-inner{
|
||||
padding: 7px 6px 0;
|
||||
}
|
||||
|
||||
.popover-footer{
|
||||
padding: 6px 6px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -145,10 +145,6 @@
|
||||
.pf-sig-table{
|
||||
font-size: 10px;
|
||||
|
||||
.pf-sig-table-edit-name-input{
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
// textarea field
|
||||
// overwrite some styles in order to make <textarea> 100% width
|
||||
.editable-container.editable-inline {
|
||||
|
||||
@@ -438,10 +438,10 @@ table.dataTable td {
|
||||
.dataTables_wrapper .dataTables_info,
|
||||
.dataTables_wrapper .dataTables_paginate {
|
||||
float: none;
|
||||
text-align: center;
|
||||
//text-align: center;
|
||||
}
|
||||
.dataTables_wrapper .dataTables_paginate {
|
||||
margin-top: 0.5em;
|
||||
//margin-top: 0.5em;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 640px) {
|
||||
|
||||
Reference in New Issue
Block a user