/** * Connection info module */ define([ 'jquery', 'app/init', 'app/util', 'bootbox', 'app/map/util' ], ($, Init, Util, bootbox, MapUtil) => { 'use strict'; let config = { // module info modulePosition: 1, moduleName: 'connectionInfo', moduleHeadClass: 'pf-module-head', // class for module header moduleHandlerClass: 'pf-module-handler-drag', // class for "drag" handler // connection info module moduleTypeClass: 'pf-connection-info-module', // class for this module // headline toolbar moduleHeadlineIconClass: 'pf-module-icon-button', // class for toolbar icons in the head moduleHeadlineIconRefreshClass: 'pf-module-icon-button-refresh', // class for "refresh" icon moduleHeadlineIconCurrentMassClass: 'pf-module-icon-button-mass', // class for "current ship mass" toggle icon connectionInfoPanelClass: 'pf-connection-info-panel', // class for connection info panels connectionInfoPanelId: 'pf-connection-info-panel-', // id prefix for connection info panels controlAreaClass: 'pf-module-control-area', // class for "control" areas // info table moduleTableClass: 'pf-module-table', // class for module tables connectionInfoTableLabelSourceClass: 'pf-connection-info-label-source', // class for source label connectionInfoTableLabelTargetClass: 'pf-connection-info-label-target', // class for target label connectionInfoTableRowMassLogClass: 'pf-connection-info-row-mass-log', // class for "logged mass" table row connectionInfoTableRowMassShipClass: 'pf-connection-info-row-mass-ship', // class for "current ship mass" table row connectionInfoTableCellConnectionClass: 'pf-connection-info-connection', // class for connection "fake" table cell connectionInfoTableCellMassTotalTooltipClass: 'pf-connection-info-mass-total-tooltip', // class for "mass total tooltip" table cell connectionInfoTableCellMassTotalClass: 'pf-connection-info-mass-total', // class for "mass total" table cell connectionInfoTableCellMassLogClass: 'pf-connection-info-mass-log', // class for "mass logged" table cell connectionInfoTableCellMassShipClass: 'pf-connection-info-mass-ship', // class for "current ship mass" table cell connectionInfoTableCellMassLeftClass: 'pf-connection-info-mass-left', // class for "mass left" table cell // dataTable tableToolbarCondensedClass: 'pf-dataTable-condensed-toolbar', // class for condensed table toolbar connectionInfoTableClass: 'pf-connection-info-table', // class for connection tables tableCellImageClass: 'pf-table-image-cell', // class for table "image" cells tableCellCounterClass: 'pf-table-counter-cell', // class for table "counter" cells tableCellActionClass: 'pf-table-action-cell', // class for "action" cells // connection dialog connectionDialogId: 'pf-connection-info-dialog', // id for "connection" dialog typeSelectId: 'pf-connection-info-dialog-type-select', // id for "ship type" select shipMassId: 'pf-connection-info-dialog-mass', // id for "ship mass" input characterSelectId: 'pf-connection-info-dialog-character-select', // id for "character" select // config showShip: true // default for "show current ship mass" toggle }; /** * get module toolbar element * @returns {*|jQuery|HTMLElement|void} */ let getHeadlineToolbar = () => { let headlineToolbar = $('
| ', { class: ['pf-table-cell-20', 'text-right', Util.config.helpClass, 'pf-pie-chart'].join(' ') }).attr('data-toggle', 'tooltip').attr('data-percent', '-100').easyPieChart({ barColor: (percent) => { let color = '#e28a0d'; if((percent * -1) >= 100){ color = '#a52521'; } return color; }, overrideOptions: 'signed', trackColor: '#5cb85c', size: 14, scaleColor: false, lineWidth: 2, lineCap: 'butt', animate: false }), $(' | ', {
class: ['text-right'].join(' ')
}).attr('colspan', 2).append(
$('', {
class: 'pf-link',
html: connectionData.sourceAlias + ' '
}).on('click', function(){
Util.triggerMenuAction(Util.getMapModule().getActiveMap(), 'SelectSystem', {systemId: connectionData.source});
}),
$('', {
class: [config.connectionInfoTableLabelSourceClass].join(' ')
}),
$('', {
class: 'fas fa-fw fa-angle-double-right'
}),
$('', {
class: [config.connectionInfoTableLabelTargetClass].join(' ')
}),
$('', {
class: 'pf-link',
html: ' ' + connectionData.targetAlias
}).on('click', function(){
Util.triggerMenuAction(Util.getMapModule().getActiveMap(), 'SelectSystem', {systemId: connectionData.target});
})
)
)
),
$('').append(
$('| ', {
class: ['text-right', Util.config.helpClass, config.connectionInfoTableCellMassTotalTooltipClass].join(' '),
html: ''
}),
$(' | ', {
text: scopeLabel.charAt(0).toUpperCase() + scopeLabel.slice(1)
}),
$(' | ', {
class: ['text-right', config.connectionInfoTableCellConnectionClass].join(' ')
}).append(
$(' | ', {
class: MapUtil.getConnectionFakeClassesByTypes(connectionData.type).join(' ')
})
)
),
$(' ', {
class: ['text-right', Util.config.helpClass].join(' '),
html: '',
title: 'initial mass. From signature table'
}).attr('data-toggle', 'tooltip'),
$(' | ', {
text: 'Total mass'
}),
$(' | ', {
class: ['text-right', 'txt-color', config.connectionInfoTableCellMassTotalClass].join(' ')
})
),
$(' | ', {
class: ['text-right', Util.config.helpClass].join(' '),
title: 'recorded total jump mass'
}).attr('data-toggle', 'tooltip').append(
$('', {
class: [
'fas', 'fa-fw', 'fa-question-circle'
].join(' ')
}),
$('', {
class: [
'fas', 'fa-fw', 'fa-adjust',
'txt-color', 'txt-color-warning',
'hidden'
].join(' ')
}),
$('', {
class: [
'far', 'fa-fw', 'fa-circle',
'txt-color', 'txt-color-danger',
'hidden'
].join(' ')
})
),
$(' | ', {
text: 'Logged mass'
}),
$(' | ', {
class: ['text-right', config.connectionInfoTableCellMassLogClass].join(' ')
})
),
$(' | ', {
class: ['text-right', Util.config.helpClass].join(' '),
title: 'current ship mass'
}).attr('data-toggle', 'tooltip').append(
$('', {
class: ['fas', 'fa-fw', 'fa-question-circle'].join(' ')
}),
$('', {
class: [
'fas', 'fa-fw', 'fa-exclamation-triangle',
'txt-color', 'txt-color-danger',
'hidden'
].join(' ')
})
),
$(' | ', {
class: ['pf-table-cell-ellipses-auto'].join(' '),
text: 'Ship mass'
}),
$(' | ', {
class: ['text-right', 'txt-color', config.connectionInfoTableCellMassShipClass].join(' ')
})
),
$(' | ', {
class: ['text-right', Util.config.helpClass].join(' '),
html: '',
title: 'max. mass left'
}).attr('data-toggle', 'tooltip'),
$(' | ', {
text: 'Mass left'
}),
$(' | ', {
class: ['text-right', 'txt-color', config.connectionInfoTableCellMassLeftClass].join(' ')
})
)
)
).on('pf:updateInfoTable', function(e, data){
// update information table -------------------------------------------------------
let tableElement = $(this);
let connectionData = tableElement.data('connectionData');
if(connectionData){
if(connectionData.scope === 'wh'){
// update signature information -------------------------------------------
let sourceLabelElement = tableElement.find('.' + config.connectionInfoTableLabelSourceClass);
let targetLabelElement = tableElement.find('.' + config.connectionInfoTableLabelTargetClass);
// get related jsPlumb connection
let connection = $().getConnectionById(data.mapId, data.connectionId);
let signatureTypeNames = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
let sourceLabels = signatureTypeNames.source.labels;
let targetLabels = signatureTypeNames.target.labels;
sourceLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(sourceLabels));
targetLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(targetLabels));
// remove K162
sourceLabels = sourceLabels.diff(['K162']);
targetLabels = targetLabels.diff(['K162']);
// get static wormhole data by endpoint Labels
let wormholeName = '';
let wormholeData = null;
if(sourceLabels.length === 1 && targetLabels.length === 0){
wormholeName = sourceLabels[0];
}else if(sourceLabels.length === 0 && targetLabels.length === 1){
wormholeName = targetLabels[0];
}
if(
wormholeName &&
Init.wormholes.hasOwnProperty(wormholeName)
){
wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
// init wormhole tooltip ----------------------------------------------
let massTotalTooltipCell = tableElement.find('.' + config.connectionInfoTableCellMassTotalTooltipClass);
massTotalTooltipCell.addWormholeInfoTooltip(wormholeData);
}
// all required data is set -> re-calculate rows
tableElement.data('wormholeData', wormholeData);
tableElement.trigger('pf:calcInfoTable');
}
}
}).on('pf:calcInfoTable', function(e){
// re-calculate information table from .data() cell values ------------------------
let tableElement = $(this);
let connectionData = tableElement.data('connectionData');
let massChartCell = tableElement.find('[data-percent]');
let wormholeData = tableElement.data('wormholeData');
let shipData = null;
let shipName = '';
let showShip = Boolean(tableElement.data('showShip'));
let massLogRow = tableElement.find('.' + config.connectionInfoTableRowMassLogClass);
let massShipRow = tableElement.find('.' + config.connectionInfoTableRowMassShipClass);
// icons
let massLogTooltipIcon = massLogRow.find('i.fa-question-circle');
let massLogStage2Icon = massLogRow.find('i.fa-adjust');
let massLogStage3Icon = massLogRow.find('i.fa-circle');
let massShipTooltipIcon = massShipRow.find('i.fa-question-circle');
let massShipWarningIcon = massShipRow.find('i.fa-exclamation-triangle');
// table cells
let connectionCell = tableElement.find('.' + config.connectionInfoTableCellConnectionClass);
let massTotalCell = tableElement.find('.' + config.connectionInfoTableCellMassTotalClass);
let massLogCell = tableElement.find('.' + config.connectionInfoTableCellMassLogClass);
let massShipCell = tableElement.find('.' + config.connectionInfoTableCellMassShipClass);
let massLeftCell = tableElement.find('.' + config.connectionInfoTableCellMassLeftClass);
let massTotal = null; // initial connection mass
let massReduction = 0; // default reduction (e.g. reduced, crit) in percent
let massLog = massLogCell.data('mass'); // recorded mass
let massLogTotal = massLog; // recorded mass + current ship
let massIndividual = null; // mass mass per jump
let massShip = 0; // current ship
let massIndividualError = false;
// get wormhole data from signature binding ---------------------------------------
if(wormholeData){
massTotal = parseInt(wormholeData.massTotal);
massIndividual = parseInt(wormholeData.massIndividual);
}
// get connection type (show fake connection div) ---------------------------------
connectionCell.find('div').removeClass().addClass(MapUtil.getConnectionFakeClassesByTypes(connectionData.type).join(' '));
// get wormhole status ------------------------------------------------------------
if(connectionData.type.indexOf('wh_critical') !== -1){
massReduction = 90;
massLogTooltipIcon.toggleClass('hidden', true);
massLogStage2Icon.toggleClass('hidden', true);
massLogStage3Icon.toggleClass('hidden', false);
massLogStage3Icon.parent().attr('title', 'stage 3 (critical)').tooltip('fixTitle');
}else if(connectionData.type.indexOf('wh_reduced') !== -1){
massReduction = 50;
massLogTooltipIcon.toggleClass('hidden', true);
massLogStage2Icon.toggleClass('hidden', false);
massLogStage3Icon.toggleClass('hidden', true);
massLogStage3Icon.parent().attr('title', 'stage 2 (reduced)').tooltip('fixTitle');
}else{
massLogTooltipIcon.toggleClass('hidden', false);
massLogStage2Icon.toggleClass('hidden', true);
massLogStage3Icon.toggleClass('hidden', true);
massLogStage3Icon.parent().attr('title', 'recorded total jump mass').tooltip('fixTitle');
}
if(massReduction){
let massLogReduction = massTotal / 100 * massReduction;
if(massLogReduction > massLog){
massLog = massLogTotal = massLogReduction;
}
}
// get current ship data ----------------------------------------------------------
massShipCell.parent().toggle(showShip);
if(showShip){
shipData = Util.getObjVal(Util.getCurrentCharacterLog(), 'ship');
if(shipData){
if(shipData.mass){
massShip = parseInt(shipData.mass);
// check individual mass jump
if(massIndividual){
massIndividualError = massShip > massIndividual;
}
}
if(shipData.typeId && shipData.typeName){
shipName = shipData.typeName;
}
}
}
// update ship mass and "individual mass" cells ----------------------------------
massShipTooltipIcon.toggleClass('hidden', massIndividualError);
massShipWarningIcon.toggleClass('hidden', !massIndividualError);
let shipMassTooltip = 'current ship mass ' + (shipName ? '"' + shipName + '"' : '');
if(massIndividualError){
shipMassTooltip = '"' + shipName + '" exceeds max jump mass for this connection: ' + Util.formatMassValue(massIndividual);
}else{
// current ship mass check is OK -> add to massLogTotal
massLogTotal += massShip;
}
massShipTooltipIcon.parent().attr('title', shipMassTooltip).tooltip('fixTitle');
// current ship mass --------------------------------------------------------------
massShipCell.html( function(){
let cell = $(this);
let value = ' ';
let error = false;
let textLineThrough = false;
if(massShip > 0){
value += Util.formatMassValue(massShip);
if(massIndividualError){
error = textLineThrough = true;
value = ' ' + value;
}else{
value = '-' + value;
}
}else{
error = true;
value = 'undefined';
}
// change cell style
cell.toggleClass('txt-color-red', error)
.toggleClass('txt-color-warning', !error)
.toggleClass('pf-font-line-through', textLineThrough);
return value;
});
// calculate mass left ------------------------------------------------------------
let massLeft = massTotal - massLogTotal;
massLeft = (massLeft < 0) ? 0 : massLeft;
let massPercentLog = (massTotal > 0) ? Math.floor((100 / massTotal) * massLogTotal) : 0;
// update easyPieChart and tooltip ------------------------------------------------
let massPercentLeft = (100 - massPercentLog <= 0) ? 0 : '< ' + (100 - massPercentLog);
massChartCell.data('easyPieChart').enableAnimation().update(massPercentLog * -1);
massChartCell.attr('title', massPercentLeft + '% mass left').tooltip('fixTitle');
// update mass cells --------------------------------------------------------------
massTotalCell.html(massTotal > 0 ? Util.formatMassValue(massTotal) : 'undefined')
.toggleClass('txt-color-red', massTotal <= 0);
massLogCell.html('- ' + Util.formatMassValue(massLog));
massLeftCell.html(
massLeft > 0 ?
'~ ' + Util.formatMassValue(massLeft) :
(massLeft === 0 && massTotal) ?
'will collapse' : 'undefined')
.toggleClass('txt-color-red', massLeft <= 0)
.toggleClass('txt-color-success', massLeft > 0);
})
);
element.find('[data-toggle="tooltip"]').tooltip({
container: 'body'
});
return element;
};
/**
* get HTML id by connectionId
* @param connectionId
* @returns {string}
*/
let getConnectionElementId = connectionId => config.connectionInfoPanelId + connectionId;
/**
* get all visible connection panel elements
* @param moduleElement
* @returns {*|T|{}}
*/
let getConnectionElements = moduleElement => moduleElement.find('.' + config.connectionInfoPanelClass).not('#' + getConnectionElementId(0));
/**
* enrich connectionData with "logs" data (if available) and other "missing" data
* @param connectionsData
* @param newConnectionsData
* @returns {*}
*/
let enrichConnectionsData = (connectionsData, newConnectionsData) => {
for(let i = 0; i < connectionsData.length; i++){
for(let newConnectionData of newConnectionsData){
if(connectionsData[i].id === newConnectionData.id){
// copy some missing data
connectionsData[i].character = newConnectionData.character;
connectionsData[i].created = newConnectionData.created;
connectionsData[i].type = newConnectionData.type;
// check for mass logs and copy data
if(newConnectionData.logs && newConnectionData.logs.length){
connectionsData[i].logs = newConnectionData.logs;
}
// check for signatures and copy data
if(newConnectionData.signatures && newConnectionData.signatures.length){
connectionsData[i].signatures = newConnectionData.signatures;
}
break;
}
}
}
return connectionsData;
};
/**
* request connection log data
* @param requestData
* @param context
* @param callback
*/
let requestConnectionLogData = (requestData, context, callback) => {
// show loading animation
for(let connectionId of requestData.connectionIds){
context.moduleElement.find('#' + getConnectionElementId(connectionId) + ' table').showLoadingAnimation();
}
$.ajax({
type: 'POST',
url: Init.path.getMapConnectionData,
data: requestData,
dataType: 'json',
context: context
}).done(function(connectionsData){
this.connectionsData = enrichConnectionsData(this.connectionsData, connectionsData);
callback(this.moduleElement, this.connectionsData);
}).always(function(){
// hide loading animation
for(let contextData of this.connectionsData){
context.moduleElement.find('#' + getConnectionElementId(contextData.id) + ' table').hideLoadingAnimation();
}
});
};
/**
* @see requestConnectionLogData
* @param moduleElement
* @param mapId
* @param connectionsData
*/
let getConnectionsLogData = (moduleElement, mapId, connectionsData) => {
let connectionIds = [];
for(let connectionData of connectionsData){
connectionIds.push(connectionData.id);
}
let requestData = {
mapId: mapId,
connectionIds: connectionIds,
addData : ['signatures', 'logs'],
// filterData : ['logs'] // do not exclude connections with NO "logs" -> sig data will be used as well
};
let contextData = {
moduleElement: moduleElement,
connectionsData: connectionsData
};
requestConnectionLogData(requestData, contextData, addConnectionsData);
};
/**
* replace/insert dataTables log data
* @param moduleElement
* @param connectionsData
*/
let addConnectionsData = (moduleElement, connectionsData) => {
let getRowIndexesByData = (tableApi, colName, value) => {
return tableApi.rows().eq(0).filter((rowIdx) => {
return (tableApi.cell(rowIdx, colName + ':name').data() === value);
});
};
for(let connectionData of connectionsData){
// find related dom element for current connection
let connectionElement = moduleElement.find('#' + getConnectionElementId(connectionData.id));
if(connectionElement.length){
// attach connectionData to connection information for later use ------------------
let connectionInfoElement = connectionElement.find('.' + config.moduleTableClass);
connectionInfoElement.data('connectionData', connectionData);
// update dataTable ---------------------------------------------------------------
let tableApi = connectionElement.find('.dataTable').dataTable().api();
if(connectionData.logs && connectionData.logs.length > 0){
for(let i = 0; i < connectionData.logs.length; i++){
let rowData = connectionData.logs[i];
let rowNew = null;
let animationStatus = null;
let indexes = getRowIndexesByData(tableApi, 'index', rowData.id);
if(indexes.length === 0){
// row not found -> add new row
rowNew = tableApi.row.add(rowData);
animationStatus = 'added';
}else{
// update row with FIRST index
let row = tableApi.row( parseInt(indexes[0]));
let rowDataCurrent = row.data();
// check if row data changed
if(rowDataCurrent.updated.updated !== rowData.updated.updated){
// ... row changed -> delete old and re-add
// -> cell actions might have changed
row.remove();
rowNew = tableApi.row.add(rowData);
animationStatus = 'changed';
}
}
if(
animationStatus !== null &&
rowNew.length > 0
){
rowNew.nodes().to$().data('animationStatus', animationStatus);
}
}
}else{
// clear table or leave empty
tableApi.clear();
}
// redraw dataTable
tableApi.draw(false);
}
}
};
/**
*
* @param moduleElement
* @param mapId
* @param connectionData
*/
let updateConnectionPanel = (moduleElement, mapId, connectionData) => {
let rowElement = moduleElement.find('.row');
let connectionElement = rowElement.find('#' + getConnectionElementId(connectionData.id));
if( !connectionElement.length ){
connectionElement = getConnectionElement(mapId, connectionData.id);
connectionElement.append(getInformationElement(connectionData));
let table = $(' | |
|---|