')
.children()
.css({
'willChange': 'height'
}).velocity('slideUp', {
duration: duration,
easing: 'linear',
complete: function(animationElements){
// remove wrapper
$(animationElements).children().unwrap();
resolve({
action: 'rowHidden',
row: rowElement
});
}
});
}else{
// show row
// remove padding on "hidden" cells for smother animation
cellElements.css({
'padding-top': 0,
'padding-bottom': 0,
'willChange': 'padding-top, padding-top, height'
});
// add hidden wrapper for ea
cellElements.wrapInner($('
').hide());
// show row for padding animation
rowElement.show();
cellElements.velocity({
paddingTop: ['4px', 0],
paddingBottom: ['4px', 0]
},{
duration: duration,
queue: false,
complete: function(){
// animate
wrapper
cellElements.children()
.css({
'willChange': 'height'
}).velocity('slideDown', {
duration: duration,
complete: function(animationElements){
// remove wrapper
for(let i = 0; i < animationElements.length; i++){
let currentWrapper = $(animationElements[i]);
if(currentWrapper.children().length > 0){
currentWrapper.children().unwrap();
}else{
currentWrapper.parent().html( currentWrapper.html() );
}
}
resolve({
action: 'rowShown',
row: rowElement
});
}
});
}
});
}
};
return new Promise(toggleTableRowExecutor);
}
/**
* update scanned signatures progress bar
* @param tableApi
* @param options
*/
updateScannedSignaturesBar(tableApi, options){
let tableElement = tableApi.table().node();
let parentElement = $(tableElement).parents('.' + this._config.className + ', .' + this._config.sigReaderDialogClass);
let progressBar = parentElement.find('.progress-bar');
let progressBarLabel = parentElement.find('.progress-label-right');
let percent = 0;
let progressBarType = '';
let columnGroupData = tableApi.column('group:name').data();
let sigCount = columnGroupData.length;
let sigIncompleteCount = columnGroupData.filter((value, index) => !value).length;
if(sigCount){
percent = 100 - Math.round( 100 / sigCount * sigIncompleteCount );
}
if(percent < 30){
progressBarType = 'progress-bar-danger';
}else if(percent < 100){
progressBarType = 'progress-bar-warning';
}else{
progressBarType = 'progress-bar-success';
}
progressBarLabel.text(percent + '%');
progressBar.removeClass().addClass('progress-bar').addClass(progressBarType);
progressBar.attr('aria-valuenow', percent);
progressBar.css({width: percent + '%'});
// show notifications
if(options.showNotice !== false){
let notification = (sigCount - sigIncompleteCount) + ' / ' + sigCount + ' (' + percent + '%) signatures scanned';
if(percent < 100){
this.showNotify({title: 'Unscanned signatures', text: notification, type: 'info'});
}else{
this.showNotify({title: 'System is scanned', text: notification, type: 'success'});
}
}
}
/**
* load existing (current) signature data into info table (preview)
* @param infoTableApi
* @param draw
*/
initTableDataWithCurrentSignatureData(infoTableApi, draw = false){
// reset/clear infoTable
infoTableApi.clear();
let primaryTableApi = this.getDataTableInstance(this._systemData.mapId, this._systemData.id, 'primary');
if(primaryTableApi){
infoTableApi.rows.add(primaryTableApi.data().toArray());
if(draw){
infoTableApi.draw();
}
}else{
console.warn('Signature table not found. mapId: %d; systemId: %d',this._systemData.mapId, this._systemData.id);
}
}
/**
* set "signature reader" dialog observer
* @param dialogElement
*/
setSignatureReaderDialogObserver(dialogElement){
dialogElement = $(dialogElement);
let form = dialogElement.find('form').first();
let textarea = form.find('#' + this._config.sigInfoTextareaId);
let deleteOutdatedCheckbox = form.find('#' + this._config.sigReaderLazyUpdateId);
let deleteConnectionsCheckbox = form.find('#' + this._config.sigReaderConnectionDeleteId);
let errorClipboardValidation = 'No signatures found in scan result';
let tableStatusElement = dialogElement.find('.' + this._config.tableToolbarStatusClass);
form.initFormValidation({
delay: 0,
feedback: {
success: 'fa-check',
error: 'fa-times'
},
custom: {
clipboard: textarea => {
let signatureData = this.parseSignatureString(textarea.val());
tableStatusElement.text(signatureData.length + ' signatures parsed');
if(signatureData.length === 0){
return errorClipboardValidation;
}
}
}
});
let updatePreviewSection = (formData) => {
let infoTableApi = this.getDataTableInstance(this._systemData.mapId, this._systemData.id, 'info');
if(infoTableApi){
// init 'infoTable' with existing signature rows
// infoTableApi.draw() not necessary at this point!
this.initTableDataWithCurrentSignatureData(infoTableApi);
let signatureData = this.parseSignatureString(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 = this.enrichParsedSignatureData(signatureData);
this.updateSignatureInfoTable(infoTableApi, signatureData, Boolean(formData.deleteOld), Boolean(formData.deleteConnection));
}else{
// no signatures pasted -> draw current signature rows
infoTableApi.draw();
// reset counter elements
this.updateSignatureReaderCounters(SystemSignatureModule.emptySignatureReaderCounterData);
this.updateScannedSignaturesBar(infoTableApi, {showNotice: false});
console.info(errorClipboardValidation);
}
}else{
console.warn('Signature "preview" table not found. mapId: %d; systemId: %d', this._systemData.mapId, this._systemData.id);
}
};
// changes in 'scan result' textarea -> update preview table --------------------------------------------------
let oldValue = '';
textarea.on('change keyup paste', () => {
let formData = form.getFormValues();
let currentValue = formData.clipboard;
if(currentValue === oldValue){
return; //check to prevent multiple simultaneous triggers
}
oldValue = currentValue;
updatePreviewSection(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', () => {
let formData = form.getFormValues();
if(formData.clipboard.length){
updatePreviewSection(form.getFormValues());
}
});
// listen 'primary' sig table updates -> update 'preview' sig table in the dialog -----------------------------
dialogElement.on('pf:updateSignatureReaderDialog', () => {
updatePreviewSection(form.getFormValues());
});
}
/**
* open "signature reader" dialog for signature table
* @param tableApi
*/
showSignatureReaderDialog(tableApi){
requirejs([
'text!templates/dialog/signature_reader.html',
'mustache'
], (TplDialog, Mustache) => {
let data = {
sigInfoId: this._config.sigInfoId,
sigReaderLazyUpdateId: this._config.sigReaderLazyUpdateId,
sigReaderConnectionDeleteId: this._config.sigReaderConnectionDeleteId,
sigInfoTextareaId: this._config.sigInfoTextareaId,
sigInfoLazyUpdateStatus: this.getLazyUpdateToggleStatus(),
sigInfoCountSigNewId: this._config.sigInfoCountSigNewId,
sigInfoCountSigChangeId: this._config.sigInfoCountSigChangeId,
sigInfoCountSigDeleteId: this._config.sigInfoCountSigDeleteId,
sigInfoCountConDeleteId: this._config.sigInfoCountConDeleteId,
sigInfoProgressElement: this.newProgressElement().outerHTML
};
let signatureReaderDialog = bootbox.dialog({
className: this._config.sigReaderDialogClass,
title: 'Signature reader',
size: 'large',
message: Mustache.render(TplDialog, data),
show: false,
buttons: {
close: {
label: 'cancel',
className: 'btn-default'
},
success: {
label: ' update signatures',
className: 'btn-success',
callback: e => {
let form = $(e.delegateTarget).find('form');
// validate form
form.validator('validate');
// 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
};
this.updateSignatureTableByClipboard(tableApi, formData.clipboard, signatureOptions);
}else{
return false;
}
}
}
}
});
signatureReaderDialog.on('show.bs.modal', e => {
let infoTableApi = this.drawSignatureTableInfo(e.target);
// init 'infoTable' with existing signature rows
this.initTableDataWithCurrentSignatureData(infoTableApi, true);
this.updateScannedSignaturesBar(infoTableApi, {showNotice: false});
this.setSignatureReaderDialogObserver(e.target);
});
// dialog shown event
signatureReaderDialog.on('shown.bs.modal', e => {
signatureReaderDialog.initTooltips();
// set focus on sig-input textarea
signatureReaderDialog.find('textarea').focus();
});
// show dialog
signatureReaderDialog.modal('show');
});
}
/**
* get "lazy delete" toggle element
* @returns {*}
*/
getLazyUpdateToggleElement(){
return this.moduleElement.querySelector('.' + this._config.moduleHeadlineIconLazyClass);
}
/**
* get status for "lazy delete" toggle
* @returns {number}
*/
getLazyUpdateToggleStatus(){
return this.getLazyUpdateToggleElement().classList.contains('active') ? 1 : 0;
}
/**
* update 'counter' UI elements in 'signature reader' dialog
* @param data
*/
updateSignatureReaderCounters(data){
let counterElement = $('#' + this._config.sigInfoCountSigNewId).text(data.added || 0);
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.added));
counterElement = $('#' + this._config.sigInfoCountSigChangeId).text(data.changed || 0);
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.changed));
counterElement = $('#' + this._config.sigInfoCountSigDeleteId).text(data.deleted || 0);
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.deleted));
counterElement = $('#' + this._config.sigInfoCountConDeleteId).text(data.deleteCon || 0);
counterElement.toggleClass(counterElement.attr('data-class'), Boolean(data.deleteCon));
}
/**
* add new row to signature table
* @param tableApi
* @param signatureData
* @returns {*}
*/
addSignatureRow(tableApi, signatureData){
return tableApi ? tableApi.row.add(signatureData) : null;
}
/**
* @param action
* @param rowId
* @returns {Promise}
*/
getPromiseForRow(action, rowId){
return new Promise(resolve => {
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)!
*/
rowUpdate(rowIndex, colIndex, tableLoopCount, cellLoopCount, options){
let cell = Util.getObjVal(options, 'cell');
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
this.editableSelectCheck(node);
break;
case 'connectionId':
// disables if no wormhole group set
let groupId = cell.cell(rowIndex, 'group:name').data();
if(groupId === 5){
// wormhole
this.editableEnable(node);
}else{
this.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(this._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
*/
updateSignatureInfoTable(tableApi, signaturesDataOrig, deleteOutdatedSignatures = false, deleteConnections = false){
let module = this;
// 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(){
module.rowUpdate(...arguments, {cell: this, 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(module.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(module.getPromiseForRow('deleted', rowId));
// check if there is a connectionId.
if(deleteConnections && Util.getObjVal(rowData, 'connection.id')){
promisesChanged.push(module.getPromiseForRow('deleteCon', rowId));
}
});
}
// add rows ---------------------------------------------------------------------------------------------------
for(let signatureData of signaturesData){
let row = module.addSignatureRow(tableApi, signatureData);
let rowElement = row.nodes().to$();
rowElement.pulseBackgroundColor('added', true);
promisesAdded.push(module.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({}, SystemSignatureModule.emptySignatureReaderCounterData));
module.updateSignatureReaderCounters(notificationCounter);
module.updateScannedSignaturesBar(tableApi, {showNotice: false});
}
});
}
/**
* update signature table with new signatures
* -> add/update/delete rows
* @param tableApi
* @param signaturesDataOrig
* @param deleteOutdatedSignatures
*/
updateSignatureTable(tableApi, signaturesDataOrig, deleteOutdatedSignatures = false){
let module = this;
if(tableApi.hasProcesses('lock')){
console.info('Signature table locked. Skip table update');
return;
}
// disable tableApi until update finished;
let processLockPromise = tableApi.newProcess('lock');
// clone signature array because of further manipulation
let signaturesData = $.extend([], signaturesDataOrig);
let rowIdsExist = [];
let promisesAdded = [];
let promisesChanged = [];
let promisesDeleted = [];
let allRows = tableApi.rows();
let updateEmptyTable = !allRows.any();
let rowUpdateCallback = function(){
module.rowUpdate(...arguments, {cell: this});
};
// update signatures ------------------------------------------------------------------------------------------
allRows.every(function(rowIdx, tableLoop, rowLoop){
let row = this;
let rowData = row.data();
for(let i = 0; i < signaturesData.length; i++){
if(signaturesData[i].id === rowData.id){
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
row.data(signaturesData[i]);
// 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(module.getPromiseForRow('changed', rowId));
}
rowIdsExist.push(rowId);
// remove signature data -> all left signatures will be added
signaturesData.splice(i, 1);
i--;
}
}
});
// delete signatures ------------------------------------------------------------------------------------------
if(deleteOutdatedSignatures){
let rows = tableApi.rows((rowIdx, rowData, node) => !rowIdsExist.includes('#' + module._config.sigTableRowIdPrefix + rowData.id));
rows.every(function(rowIdx, tableLoop, rowLoop){
let row = this;
let rowId = row.id(true);
let rowElement = row.nodes().to$();
// hide open editable fields on the row before removing them
rowElement.find('.editable').editable('destroy');
// destroy possible open popovers (e.g. wormhole types, update popover)
rowElement.destroyPopover(true);
rowElement.pulseBackgroundColor('deleted');
promisesDeleted.push(new Promise((resolve, reject) => {
module.toggleTableRow(rowElement).then(payload => resolve({action: 'deleted', rowIdx: rowId}));
}));
}).remove();
}
// add new signatures -----------------------------------------------------------------------------------------
for(let signatureData of signaturesData){
let row = module.addSignatureRow(tableApi, signatureData);
let rowId = row.id(true);
let rowElement = row.nodes().to$();
rowElement.pulseBackgroundColor('added');
promisesAdded.push(module.getPromiseForRow('added', rowId));
}
// done -------------------------------------------------------------------------------------------------------
Promise.all(promisesAdded.concat(promisesChanged, promisesDeleted)).then(payloads => {
if(payloads.length){
// table data changed -> draw() table changes
tableApi.draw();
// check for "leads to" conflicts -> important if there are just "update" (no add/delete) changes
module.checkConnectionConflicts();
if(!updateEmptyTable){
// no notifications if table was empty just progressbar notification is needed
// sum payloads by "action"
let notificationCounter = payloads.reduce((acc, payload) => {
if(!acc[payload.action]){
acc[payload.action] = 0;
}
acc[payload.action]++;
return acc;
}, Object.assign({}, SystemSignatureModule.emptySignatureReaderCounterData));
let notification = Object.keys(notificationCounter).reduce((acc, key) => {
return `${acc}${notificationCounter[key] ? `${notificationCounter[key]} ${key} ` : ''}`;
}, '');
if(notification.length){
Util.showNotify({title: 'Signatures updated', text: notification, type: 'success', textTrusted: true});
}
}
module.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)
$('.' + module._config.sigReaderDialogClass + '.in').trigger('pf:updateSignatureReaderDialog');
}
// unlock table
tableApi.endProcess(processLockPromise);
});
}
/**
* update signature "history" popover
* @param tableApi
* @param historyData
*/
updateSignatureHistory(tableApi, historyData){
let tableElement = tableApi.table().node();
$(tableElement).data('history', historyData);
}
/**
* update module
* compare data and update module
* @param systemData
* @returns {Promise}
*/
update(systemData){
return super.update(systemData).then(systemData => new Promise(resolve => {
if(
Util.getObjVal(systemData, 'id') === this._systemData.id &&
Util.getObjVal(systemData, 'mapId') === this._systemData.mapId &&
Util.getObjVal(systemData, 'signatures') &&
Util.getObjVal(systemData, 'sigHistory')
){
let tableApi = this.getDataTableInstance(systemData.mapId, systemData.id, 'primary');
this.updateSignatureTable(tableApi, systemData.signatures, true);
this.updateSignatureHistory(tableApi, systemData.sigHistory);
}
$(this.moduleElement).hideLoadingAnimation();
resolve({
action: 'update',
data: {
module: this
}
});
}));
}
/**
* init module
*/
init(){
super.init();
let tableApi = this.getDataTableInstance(this._systemData.mapId, this._systemData.id, 'primary');
tableApi.endProcess($(this.moduleElement).data('lockPromise'));
}
/**
* before module hide callback
*/
beforeHide(){
super.beforeHide();
// disable update
this.getDataTableInstance(this._systemData.mapId, this._systemData.id, 'primary').newProcess('lock');
}
/**
* get all signature types that can exist for a system (jQuery obj)
* @param systemElement
* @param groupId
* @returns {*[]|*}
*/
static getSignatureTypeOptionsBySystem(systemElement, groupId){
let systemTypeId = systemElement.data('typeId');
let areaId = Util.getAreaIdBySecurity(systemElement.data('security'));
let systemData = {statics: systemElement.data('statics')};
return SystemSignatureModule.getSignatureTypeOptions(systemTypeId, areaId, groupId, systemData);
}
/**
* get all connection select options
* @param mapId
* @param systemData
* @returns {[]}
*/
static getSignatureConnectionOptions(mapId, systemData){
let map = Map.getMapInstance(mapId);
let systemId = MapUtil.getSystemId(mapId, systemData.id);
let systemConnections = MapUtil.searchConnectionsBySystems(map, [systemId], 'wh');
let newSelectOptions = [];
let connectionOptions = [];
/**
* get option data for a single connection
* @param type
* @param connectionData
* @param systemData
* @returns {{value: *, text: string, metaData: {type: *}}}
*/
let getOption = (type, connectionData, systemData) => {
let text = 'UNKNOWN';
if(type === 'source'){
text = connectionData.sourceAlias + ' - ' + systemData.security;
}else if(type === 'target'){
text = connectionData.targetAlias + ' - ' + systemData.security;
}
return {
value: connectionData.id,
text: text,
metaData: {
type: connectionData.type
}
};
};
for(let systemConnection of systemConnections){
let connectionData = MapUtil.getDataByConnection(systemConnection);
// connectionId is required (must be stored)
if(connectionData.id){
// check whether "source" or "target" system is relevant for this connection
// -> hint "source" === 'target' --> loop
if(systemData.id !== connectionData.target){
let targetSystemData = MapUtil.getSystemData(mapId, connectionData.target);
if(targetSystemData){
// take target...
connectionOptions.push(getOption('target', connectionData, targetSystemData));
}
}else if(systemData.id !== connectionData.source){
let sourceSystemData = MapUtil.getSystemData(mapId, connectionData.source);
if(sourceSystemData){
// take source...
connectionOptions.push(getOption('source', connectionData, sourceSystemData));
}
}
}
}
if(connectionOptions.length > 0){
newSelectOptions.push({text: 'System', children: connectionOptions});
}
return newSelectOptions;
}
/**
* get all signature types that can exist for a given system
* -> result is partially cached
* @param systemTypeId
* @param areaId
* @param groupId
* @param statics
* @param shattered
* @returns {[]|*}
*/
static getSignatureTypeOptions(systemTypeId, areaId, groupId, {statics = null, shattered = false} = {}){
systemTypeId = parseInt(systemTypeId || 0);
areaId = parseInt(areaId || 0);
groupId = parseInt(groupId || 0);
let newSelectOptionsCount = 0;
if(!systemTypeId || !areaId || !groupId){
return [];
}
// check if sig types require more than one 'areaId' to be checked
let areaIds = SystemSignatureModule.getAreaIdsForSignatureTypeOptions(systemTypeId, areaId, groupId, shattered);
let cacheKey = [systemTypeId, ...areaIds, groupId].join('_');
let newSelectOptions = SystemSignatureModule.getCache('sigTypeOptions').get(cacheKey);
// check for cached signature names
if(Array.isArray(newSelectOptions)){
// hint: Cached signatures do not include static WHs!
// -> ".slice(0)" creates copy
newSelectOptions = newSelectOptions.slice(0);
newSelectOptionsCount = SystemSignatureModule.getOptionsCount('children', newSelectOptions);
}else{
newSelectOptions = [];
// get new Options ----------
// get all possible "static" signature names by the selected groupId
// -> for groupId == 5 (wormholes) this give you "wandering" whs
let tempSelectOptions = Util.getSignatureTypeNames(systemTypeId, areaIds, groupId);
// format options into array with objects advantages: keep order, add more options (whs), use optgroup
if(tempSelectOptions){
let fixSelectOptions = [];
for(let key in tempSelectOptions){
if(
key > 0 &&
tempSelectOptions.hasOwnProperty(key)
){
newSelectOptionsCount++;
fixSelectOptions.push({value: newSelectOptionsCount, text: tempSelectOptions[key]});
}
}
if(newSelectOptionsCount > 0){
if(groupId === 5){
// "wormhole" selected => multiple |