/**
* System intel module
*/
define([
'jquery',
'app/init',
'app/util',
'module/base',
'bootbox',
'app/counter'
], ($, Init, Util, BaseModule, bootbox, Counter) => {
'use strict';
let SystemIntelModule = class SystemIntelModule extends BaseModule {
constructor(config = {}) {
super(Object.assign({}, new.target.defaultConfig, config));
}
/**
* get status icon for structure
* @param statusData
* @returns {string}
*/
getIconForStatusData(statusData){
return '';
}
/**
* get icon that marks a table cell as clickable
* @returns {string}
*/
getIconForInformationWindow(){
return '';
}
/**
* get a dataTableApi instance from global cache
* @param mapId
* @param systemId
* @param tableType
* @returns {*}
*/
getDataTableInstance(mapId, systemId, tableType){
return BaseModule.Util.getDataTableInstance(this._config.intelTableId, mapId, systemId, tableType);
}
/**
* get dataTable id
* @param {...string} parts e.g. 'tableType', 'mapId', 'systemId'
* @returns {string}
*/
getTableId(...parts){
return BaseModule.Util.getTableId(this._config.intelTableId, ...parts);
}
/**
* get dataTable row id
* @param tableType
* @param id
* @returns {string}
*/
getRowId(tableType, id){
return BaseModule.Util.getTableRowId(this._config.intelTableRowIdPrefix, tableType, id);
}
/**
* get
DOM id by id
* @param tableApi
* @param id
* @returns {*}
*/
getRowById(tableApi, id){
return tableApi.rows().ids().toArray().find(rowId => rowId === this.getRowId(BaseModule.Util.getObjVal(this.getTableMetaData(tableApi), 'type'), id));
}
/**
* get custom "metaData" from dataTables API
* @param tableApi
* @returns {*}
*/
getTableMetaData(tableApi){
return tableApi ? tableApi.init().pfMeta : null;
}
/**
* vormat roman numeric string to int
* -> e.g. 'VII' => 7
* @param str
* @returns {number}
*/
romanToInt(str){
let charToTnt = char => {
switch (char) {
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return -1;
}
};
if(str == null) return -1;
let num = charToTnt(str.charAt(0));
let pre, curr;
for(let i = 1; i < str.length; i++){
curr = charToTnt(str.charAt(i));
pre = charToTnt(str.charAt(i - 1));
if(curr <= pre){
num += curr;
}else{
num = num - pre * 2 + curr;
}
}
return num;
}
/**
* render module
* @param mapId
* @param systemData
* @returns {HTMLElement}
*/
render(mapId, systemData){
this._systemData = systemData;
let showStationTable = ['H', 'L', '0.0', 'T', 'C12'].includes(Util.getObjVal(this._systemData, 'security'));
this._bodyEl = Object.assign(document.createElement('div'), {
className: this._config.bodyClassName
});
this.moduleElement.append(this._bodyEl);
$(this.moduleElement).showLoadingAnimation();
this.initStructureTable();
if(showStationTable){
this.initStationTable();
}
this.setModuleObserver();
return this.moduleElement;
}
/**
* init 'Structure' table
*/
initStructureTable(){
let module = this;
let corporationId = Util.getCurrentUserInfo('corporationId');
let structureTableEl = document.createElement('table');
structureTableEl.id = module.getTableId('structure', module._systemData.mapId, module._systemData.id);
structureTableEl.classList.add('compact', 'stripe', 'order-column', 'row-border', 'pf-table-fixed', module._config.systemStructuresTableClass);
this._bodyEl.append(structureTableEl);
let structureDataTableOptions = {
pfMeta: {
type: 'structures'
},
order: [[10, 'desc' ], [0, 'asc' ]],
rowId: rowData => module.getRowId('structures', rowData.id),
select: {
style: 'os',
selector: 'td:not(.' + module._config.tableCellActionClass + ')'
},
language: {
emptyTable: 'No structures recorded',
info: '_START_ to _END_ of _MAX_',
infoEmpty: ''
},
columnDefs: [
{
targets: 0,
name: 'status',
title: '',
width: 2,
className: ['text-center', 'all'].join(' '),
data: 'status',
render: {
display: data => module.getIconForStatusData(data),
sort: data => data.id
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
$(cell).find('i').tooltip();
}
},{
targets: 1,
name: 'structureImage',
title: '',
width: 24,
orderable: false,
className: [module._config.tableCellImageClass, 'text-center', 'all'].join(' '),
data: 'structure.id',
defaultContent: '',
render: {
_: function(data, type, row, meta){
let value = data;
if(type === 'display' && value){
value = '
';
}
return value;
}
}
},{
targets: 2,
name: 'structureType',
title: 'type',
width: 30,
className: [module._config.tableCellEllipsisClass, 'all'].join(' '),
data: 'structure.name',
defaultContent: '',
},{
targets: 3,
name: 'name',
title: 'name',
width: 60,
className: [module._config.tableCellEllipsisClass, 'all'].join(' '),
data: 'name'
},{
targets: 4,
name: 'ownerImage',
title: '',
width: 24,
orderable: false,
className: [module._config.tableCellImageClass, 'text-center', 'all'].join(' '),
data: 'owner.id',
defaultContent: '',
render: {
_: function(data, type, row, meta){
let value = data;
if(type === 'display' && value){
value = '';
value += '
';
value += '';
}
return value;
}
}
},{
targets: 5,
name: 'ownerName',
title: 'owner',
width: 50,
className: [module._config.tableCellEllipsisClass, 'all'].join(' '),
data: 'owner.name',
defaultContent: '',
},{
targets: 6,
name: 'note',
title: 'note',
className: [module._config.tableCellEllipsisClass, 'all', Util.config.popoverTriggerClass, module._config.tableCellPopoverClass].join(' '),
data: 'description'
},{
targets: 7,
name: 'updated',
title: 'updated',
width: 60,
className: ['text-right', module._config.tableCellCounterClass, 'not-screen-l'].join(' '),
data: 'updated.updated'
},{
targets: 8,
name: 'edit',
title: '',
orderable: false,
width: 10,
className: ['text-center', module._config.tableCellActionClass, module._config.moduleHeadlineIconClass, 'all'].join(' '),
data: null,
render: {
display: data => {
let icon = '';
if(data.rowGroupData.id !== corporationId){
icon = '';
}
return icon;
}
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
let tableApi = this.api();
if($(cell).is(':empty')){
$(cell).removeClass(module._config.tableCellActionClass + ' ' + module._config.moduleHeadlineIconClass);
}else{
$(cell).on('click', function(e){
let rowData = null;
let bulkData = null;
// check if multiple rows are selected + current row is one of them -> bulk edit
let rowsSelected = tableApi.rows({selected: true});
if(rowsSelected.count() && tableApi.row(rowIndex, {selected: true}).count()){
bulkData = [...new Set(rowsSelected.data().toArray().map(rowData => ({id: rowData.id})))];
}else{
// get current row data (important!)
// -> "rowData" param is not current state, values are "on createCell()" state
rowData = tableApi.row( $(cell).parents('tr')).data();
}
module.showStructureDialog(tableApi, rowData, bulkData);
});
}
}
},{
targets: 9,
name: 'delete',
title: '',
orderable: false,
width: 10,
className: ['text-center', module._config.tableCellActionClass, 'all'].join(' '),
data: null,
render: {
display: data => {
let icon = '';
if(data.rowGroupData.id !== corporationId){
icon = '';
}
return icon;
}
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
let tableApi = this.api();
if($(cell).find('.fa-ban').length){
$(cell).removeClass(module._config.tableCellActionClass + ' ' + module._config.moduleHeadlineIconClass);
$(cell).find('i').tooltip();
}else{
let confirmationSettings = {
title: '---',
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
rowData = tableApi.row( $(cell).parents('tr')).data();
// let deleteRowElement = $(cell).parents('tr');
// tableApi.rows(deleteRowElement).remove().draw();
$(module.moduleElement).showLoadingAnimation();
Util.request('DELETE', 'Structure', rowData.id, {},
{
tableApi: tableApi
},
() => $(module.moduleElement).hideLoadingAnimation()
).then(
payload => module.callbackDeleteStructures(payload.context, payload.data),
Util.handleAjaxErrorResponse
);
}
};
// init confirmation dialog
$(cell).confirmation(confirmationSettings);
}
}
},{
targets: 10,
name: 'rowGroupData',
className: 'never', // never show this column. see: https://datatables.net/extensions/responsive/classes
data: 'rowGroupData',
visible: false,
render: {
sort: function(data){
return data.name;
}
}
}
],
initComplete: function(settings){
// table data is load in updateModule() method
// -> no need to trigger additional ajax call here for data
// -> in case table update failed -> each if this initComplete() function finished before table updated
// e.g. return now promise in getModule() function
Counter.initTableCounter(this, ['updated:name'], 'd');
}
};
this._tableApiStructure = $(structureTableEl).DataTable($.extend(true, {}, module.getDataTableDefaults(module), structureDataTableOptions));
// "Responsive" Datatables Plugin
new $.fn.dataTable.Responsive(this._tableApiStructure);
this._tableApiStructure.on('responsive-resize', function(e, tableApi, columns){
// rowGroup length changes as well -> trigger draw() updates rowGroup length (see drawCallback())
tableApi.draw();
});
// "Select" Datatables Plugin
this._tableApiStructure.select();
this._tableApiStructure.on('user-select', function(e, tableApi, type, cell, originalEvent){
let rowData = tableApi.row(cell.index().row).data();
if(Util.getObjVal(rowData, 'rowGroupData.id') !== corporationId){
e.preventDefault();
}
});
// "Buttons" Datatables Plugin
let buttons = new $.fn.dataTable.Buttons(this._tableApiStructure, {
dom: {
container: {
tag: 'h5',
className: 'pull-right'
},
button: {
tag: 'i',
className: ['fas', 'fa-fw', module._config.moduleHeadlineIconClass].join(' '),
},
buttonLiner: {
tag: null
}
},
name: 'tableTools',
buttons: [
{
name: 'add',
className: 'fa-plus',
titleAttr: 'add',
attr: {
'data-toggle': 'tooltip',
'data-html': true
},
action: function(e, tableApi, node, config){
module.showStructureDialog(tableApi);
}
},
{
name: 'selectToggle',
className: ['fa-check-double'].join(' '),
titleAttr: 'select all',
attr: {
'data-toggle': 'tooltip',
'data-html': true
},
action: function(e, tableApi, node, config){
let indexes = tableApi.rows().eq(0).filter(rowIdx => {
return Util.getObjVal(tableApi.cell(rowIdx, 'rowGroupData:name').data(), 'id') === corporationId;
});
let rowCountAll = tableApi.rows(indexes).count();
let rowCountSelected = tableApi.rows({selected: true}).count();
if(rowCountSelected && (rowCountSelected >= rowCountAll)){
tableApi.rows().deselect();
node.removeClass('active');
}else{
tableApi.rows(indexes).select();
node.addClass('active');
}
}
},
{
name: 'dScan',
className: 'fa-paste',
titleAttr: 'D-Scan reader',
attr: {
'data-toggle': 'tooltip',
'data-html': true
},
action: function(e, tableApi, node, config){
module.showDscanReaderDialog(tableApi);
}
},
{
name: 'refresh',
className: 'fa-sync',
titleAttr: 'refresh',
attr: {
'data-toggle': 'tooltip',
'data-html': true
},
action: function(e, tableApi, node, config){
$(module.moduleElement).showLoadingAnimation();
Util.request('GET', 'System', module._systemData.id, {mapId: module._systemData.mapId},
{
tableApi: tableApi,
removeMissing: true
},
context => $(module.moduleElement).hideLoadingAnimation()
).then(payload => module.callbackUpdateTableRows(payload.context, Util.getObjVal(payload.data, 'structures')));
}
}
]
});
this._tableApiStructure.buttons().container().appendTo(module.moduleElement.querySelector('.' + module._config.headClassName));
}
/**
* init 'Station' table
*/
initStationTable(){
let module = this;
this._bodyEl.append(module.newHeaderElement(module._config.headlineSub));
let stationTableEl = document.createElement('table');
stationTableEl.id = module.getTableId('station', module._systemData.mapId, module._systemData.id);
stationTableEl.classList.add('compact', 'stripe', 'order-column', 'row-border', 'pf-table-fixed', module._config.systemStationsTableClass);
this._bodyEl.append(stationTableEl);
let stationDataTableOptions = {
pfMeta: {
type: 'stations'
},
order: [[1, 'asc' ], [8, 'asc' ]],
rowId: rowData => module.getRowId('stations', rowData.id),
language: {
emptyTable: 'No stations found',
info: '_START_ to _END_ of _MAX_',
infoEmpty: ''
},
columnDefs: [
{
targets: 0,
name: 'stationImage',
title: '',
width: 24,
orderable: false,
className: [module._config.tableCellImageClass, 'text-center', 'all'].join(' '),
data: 'type.id',
defaultContent: '',
render: {
_: function(data, type, row, meta){
let value = data;
if(type === 'display' && value){
value = '
';
}
return value;
}
}
},{
targets: 1,
name: 'count',
title: '',
width: 5,
className: ['text-center', 'all'].join(' '),
data: 'name',
render: {
_: function(cellData, type, rowData, meta){
let value = '';
if(cellData){
// "grouped" regex not supported by FF
// let matches = /^(?[a-z0-9\s\-]+) (?[MDCLXVI]+) .*$/i.exec(cellData);
// let count = Util.getObjVal(matches, 'groups.count');
let matches = /^([a-z0-9\s\-]+) ([MDCLXVI]+) .*$/i.exec(cellData);
let count = Util.getObjVal(matches, '2');
if(type === 'display'){
value = count || 0;
}else{
value = module.romanToInt(count) || '';
}
}
return value;
}
}
},{
targets: 2,
name: 'name',
title: 'station',
className: [module._config.tableCellEllipsisClass, 'all'].join(' '),
data: 'name',
render: {
_: function(cellData, type, rowData, meta){
let value = cellData;
if(cellData){
// "grouped" regex not supported by FF
// let matches = /^(?[a-z0-9\s\-]+) (?[MDCLXVI]+) (?