diff --git a/app/main/controller/api/signature.php b/app/main/controller/api/signature.php index 3d2c8cb4..fe6e8545 100644 --- a/app/main/controller/api/signature.php +++ b/app/main/controller/api/signature.php @@ -68,7 +68,6 @@ class Signature extends Controller\AccessController { // delete all signatures that are not available in this request $deleteOldSignatures = (bool)$requestData['deleteOld']; - $return = (object) []; $return->error = []; $return->signatures = []; @@ -135,9 +134,17 @@ class Signature extends Controller\AccessController { $data['name'] => $data['value'] ]; - // if groupID changed -> typeID set to 0 + // if groupId changed if($data['name'] == 'groupId'){ + // -> typeId set to 0 $newData['typeId'] = 0; + // -> connectionId set to 0 + $newData['connectionId'] = 0; + } + + // if connectionId changed + if($data['name'] == 'connectionId'){ + $newData['connectionId'] = (int)$newData['connectionId']; } }else{ diff --git a/app/main/model/connectionmodel.php b/app/main/model/connectionmodel.php index 0b50281c..0b674f2f 100644 --- a/app/main/model/connectionmodel.php +++ b/app/main/model/connectionmodel.php @@ -79,9 +79,7 @@ class ConnectionModel extends BasicModel{ * @param $systemData */ public function setData($systemData){ - foreach((array)$systemData as $key => $value){ - if( !is_array($value) ){ if( $this->exists($key) ){ $this->$key = $value; @@ -98,7 +96,6 @@ class ConnectionModel extends BasicModel{ * @return array */ public function getData(){ - $connectionData = [ 'id' => $this->id, 'source' => $this->source->id, @@ -140,7 +137,11 @@ class ConnectionModel extends BasicModel{ * @return mixed */ public function hasAccess(CharacterModel $characterModel){ - return $this->mapId->hasAccess($characterModel); + $access = false; + if( !$this->dry() ){ + $access = $this->mapId->hasAccess($characterModel); + } + return $access; } /** diff --git a/app/main/model/systemsignaturemodel.php b/app/main/model/systemsignaturemodel.php index 44385146..30db870e 100644 --- a/app/main/model/systemsignaturemodel.php +++ b/app/main/model/systemsignaturemodel.php @@ -46,6 +46,18 @@ class SystemSignatureModel extends BasicModel { 'index' => true, 'activity-log' => true ], + 'connectionId' => [ + 'type' => Schema::DT_INT, + 'index' => true, + 'belongs-to-one' => 'Model\ConnectionModel', + 'constraint' => [ + [ + 'table' => 'connection', + 'on-delete' => 'CASCADE' + ] + ], + 'activity-log' => true + ], 'name' => [ 'type' => Schema::DT_VARCHAR128, 'nullable' => false, @@ -117,6 +129,11 @@ class SystemSignatureModel extends BasicModel { $signatureData->name = $this->name; $signatureData->description = $this->description; + if($connection = $this->getConnection()){ + $signatureData->connection = (object) []; + $signatureData->connection->id = $connection->_id; + } + $signatureData->created = (object) []; $signatureData->created->created = strtotime($this->created); if( is_object($this->createdCharacterId) ){ @@ -132,6 +149,48 @@ class SystemSignatureModel extends BasicModel { return $signatureData; } + /** + * setter for connectionId + * @param $connectionId + * @return int|null + */ + public function set_connectionId($connectionId){ + $connectionId = (int)$connectionId; + $validConnectionId = null; + + if($connectionId > 0){ + // check if connectionId is valid + $systemId = (int) $this->get('systemId', true); + + /** + * @var $connection ConnectionModel + */ + $connection = $this->rel('connectionId'); + $connection->getById($connectionId); + + if( + !$connection->dry() && + ( + $connection->get('source', true) === $systemId|| + $connection->get('target', true) === $systemId + ) + ){ + // connectionId belongs to same system as $this signature -> is valid + $validConnectionId = $connectionId; + } + } + + return $validConnectionId; + } + + /** + * get the connection (if attached) + * @return \Model\ConnectionModel|null + */ + public function getConnection(){ + return $this->connectionId; + } + /** * compares a new data set (array) with the current values * and checks if something has changed diff --git a/js/app/map/map.js b/js/app/map/map.js index 4e6cc5af..478c5cdb 100644 --- a/js/app/map/map.js +++ b/js/app/map/map.js @@ -32,7 +32,6 @@ define([ mapClass: 'pf-map', // class for all maps mapIdPrefix: 'pf-map-', // id prefix for all maps - systemIdPrefix: 'pf-system-', // id prefix for a system systemClass: 'pf-system', // class for all systems systemActiveClass: 'pf-system-active', // class for an active system in a map systemSelectedClass: 'pf-system-selected', // class for selected systems in a map @@ -453,7 +452,7 @@ define([ $.fn.getSystem = function(map, data){ // get map container for mapId information let mapContainer = $(this); - let systemId = config.systemIdPrefix + mapContainer.data('id') + '-' + data.id; + let systemId = MapUtil.getSystemId(mapContainer.data('id'), data.id); // check if system already exists let system = document.getElementById( systemId ); @@ -753,8 +752,8 @@ define([ let mapId = mapContainer.data('id'); let connectionId = connectionData.id || 0; let connection; - let sourceSystem = $('#' + config.systemIdPrefix + mapId + '-' + connectionData.source); - let targetSystem = $('#' + config.systemIdPrefix + mapId + '-' + connectionData.target); + let sourceSystem = $('#' + MapUtil.getSystemId(mapId, connectionData.source) ); + let targetSystem = $('#' + MapUtil.getSystemId(mapId, connectionData.target) ); // check if both systems exists // (If not -> something went wrong e.g. DB-Foreign keys for "ON DELETE",...) @@ -851,10 +850,10 @@ define([ // check if source or target has changed if(connectionData.source !== newConnectionData.source ){ - map.setSource(connection, config.systemIdPrefix + mapId + '-' + newConnectionData.source); + map.setSource(connection, MapUtil.getSystemId(mapId, newConnectionData.source) ); } if(connectionData.target !== newConnectionData.target ){ - map.setTarget(connection, config.systemIdPrefix + mapId + '-' + newConnectionData.target); + map.setTarget(connection, MapUtil.getSystemId(mapId, newConnectionData.target) ); } // connection.targetId @@ -998,7 +997,7 @@ define([ } if(deleteThisSystem === true){ - let deleteSystem = $('#' + config.systemIdPrefix + mapContainer.data('id') + '-' + currentSystemData[a].id); + let deleteSystem = $('#' + MapUtil.getSystemId(mapContainer.data('id'), currentSystemData[a].id) ); // system not found -> delete system System.removeSystems(mapConfig.map, deleteSystem); @@ -1423,7 +1422,6 @@ define([ * @returns {{id: Number, source: Number, sourceName: (*|T|JQuery|{}), target: Number, targetName: (*|T|JQuery), scope: *, type: *, updated: Number}} */ let getDataByConnection = function(connection){ - let source = $(connection.source); let target = $(connection.target); @@ -2786,7 +2784,7 @@ define([ $(mapContainer).on('pf:menuSelectSystem', function(e, data){ let tempMapContainer = $(this); - let systemId = config.systemIdPrefix + tempMapContainer.data('id') + '-' + data.systemId; + let systemId = MapUtil.getSystemId(tempMapContainer.data('id'), data.systemId); let system = $(this).find('#' + systemId); if(system.length === 1){ @@ -3309,7 +3307,6 @@ define([ return { getMapInstance: getMapInstance, clearMapInstance: clearMapInstance, - getDataByConnection: getDataByConnection }; diff --git a/js/app/map/util.js b/js/app/map/util.js index c9c4a1f1..fdc36bdc 100644 --- a/js/app/map/util.js +++ b/js/app/map/util.js @@ -17,6 +17,7 @@ define([ mapLocalStoragePrefix: 'map_', // prefix for map data local storage key mapTabContentClass: 'pf-map-tab-content', // Tab-Content element (parent element) + systemIdPrefix: 'pf-system-', // id prefix for a system systemClass: 'pf-system', // class for all systems mapGridClass: 'pf-grid-small' // class for map grid snapping }; @@ -191,7 +192,6 @@ define([ return this.find('.' + config.systemClass); }; - /** * search connections by systems * @param {Object} map - jsPlumb @@ -200,7 +200,7 @@ define([ */ let searchConnectionsBySystems = function(map, systems){ let connections = []; - let withBackConnection = false; + let withBackConnection = true; $.each(systems, function(i, system){ // get connections where system is source @@ -571,6 +571,16 @@ define([ }); }; + /** + * get systemId string (selector + * @param mapId + * @param systemId + * @returns {string} + */ + let getSystemId = (mapId, systemId) => { + return config.systemIdPrefix + mapId + '-' + systemId; + }; + return { config: config, mapOptions: mapOptions, @@ -593,6 +603,7 @@ define([ storeDefaultMapId: storeDefaultMapId, getLocaleData: getLocaleData, storeLocalData: storeLocalData, - deleteLocalData: deleteLocalData + deleteLocalData: deleteLocalData, + getSystemId: getSystemId }; }); \ No newline at end of file diff --git a/js/app/ui/dialog/map_info.js b/js/app/ui/dialog/map_info.js index 0d747d74..10140f7b 100644 --- a/js/app/ui/dialog/map_info.js +++ b/js/app/ui/dialog/map_info.js @@ -36,8 +36,6 @@ define([ tableActionCellClass: 'pf-table-action-cell', // class for table "action" cells tableCounterCellClass: 'pf-table-counter-cell', // class for table "counter" cells - systemIdPrefix: 'pf-system-', // id prefix for a system - loadingOptions: { // config for loading overlay icon: { size: 'fa-2x' @@ -430,7 +428,7 @@ define([ let deleteRowElement = $(target).parents('tr'); let activeMap = Util.getMapModule().getActiveMap(); - let systemElement = $('#' + config.systemIdPrefix + mapData.config.id + '-' + rowData.id); + let systemElement = MapUtil.getSystemId(mapData.config.id, rowData.id); if(systemElement){ // trigger system delete event diff --git a/js/app/ui/system_signature.js b/js/app/ui/system_signature.js index ba8ae690..e45baae7 100644 --- a/js/app/ui/system_signature.js +++ b/js/app/ui/system_signature.js @@ -7,8 +7,10 @@ define([ 'app/init', 'app/util', 'app/render', - 'bootbox' -], function($, Init, Util, Render, bootbox) { + 'bootbox', + 'app/map/map', + 'app/map/util' +], function($, Init, Util, Render, bootbox, Map, MapUtil) { 'use strict'; let config = { @@ -40,10 +42,12 @@ define([ sigTableEditSigNameInput: 'pf-sig-table-edit-name-input', // class for editable fields (input) sigTableEditSigGroupSelect: 'pf-sig-table-edit-group-select', // class for editable fields (sig group) sigTableEditSigTypeSelect: 'pf-sig-table-edit-type-select', // class for editable fields (sig type) + sigTableEditSigConnectionSelect: 'pf-sig-table-edit-connection-select', // class for editable fields (sig connection) sigTableEditSigDescriptionTextarea: 'pf-sig-table-edit-desc-text', // class for editable fields (sig description) sigTableCreatedCellClass: 'pf-sig-table-created', // class for "created" cells sigTableUpdatedCellClass: 'pf-sig-table-updated', // class for "updated" cells + sigTableConnectionClass: 'pf-table-connection-cell', // class for "connection" cells sigTableCounterClass: 'pf-table-counter-cell', // class for "counter" cells sigTableActionCellClass: 'pf-table-action-cell', // class for "action" cells @@ -159,7 +163,7 @@ define([ let updateCell = signatureTableApi.cell( rowIndex, cellIndex ); let updateCellElement = updateCell.nodes().to$(); - if(cellIndex === 6){ + if(cellIndex === 7){ // clear existing counter interval clearInterval( updateCellElement.data('interval') ); } @@ -167,7 +171,7 @@ define([ // set new value updateCell.data( data ).draw(); - if(cellIndex === 6){ + if(cellIndex === 7){ updateCellElement.initTimestampCounter(); } }; @@ -694,6 +698,27 @@ define([ tempData.type = sigType; + // set connection (to target system) ------------------------------------------------------------------ + let sigConnection = ' 0){ + sigConnection += 'data-pk="' + data.id + '" '; + } + + // set disabled if group is not wromhole + if(data.groupId !== 5){ + sigConnection += 'data-disabled="1" '; + } + + if(data.connection){ + sigConnection += 'data-value="' + data.connection.id + '" '; + } + sigConnection += '>'; + + tempData.connection = { + render: sigConnection, + connection: data.connection + }; + // set description ------------------------------------------------------------------------------------ let sigDescription = ' 0){ @@ -1014,6 +1039,7 @@ define([ let sigGroupFields = tableElement.find('.' + config.sigTableEditSigGroupSelect); let sigTypeFields = tableElement.find('.' + config.sigTableEditSigTypeSelect); let sigDescriptionFields = tableElement.find('.' + config.sigTableEditSigDescriptionTextarea); + let sigConnectionFields = tableElement.find('.' + config.sigTableEditSigConnectionSelect); // jump to "next" editable field on save let openNextEditDialogOnSave = function(fields){ @@ -1038,8 +1064,16 @@ define([ }; // helper function - get the next editable field in next table column - let getNextEditableField = function(field){ - let nextEditableField = $(field).closest('td').next().find('.editable'); + let getNextEditableField = function(field, selector){ + let nextEditableField = null; + if(selector){ + // search specific sibling + nextEditableField = $(field).closest('td').nextAll(selector).find('.editable'); + }else{ + // get next sibling + nextEditableField = $(field).closest('td').next().find('.editable'); + } + return $(nextEditableField); }; @@ -1108,7 +1142,7 @@ define([ updateTooltip(columnElement, newValue); // update "updated" cell - updateSignatureCell(rowElement, 6, newRowData.updated); + updateSignatureCell(rowElement, 7, newRowData.updated); } } }); @@ -1145,7 +1179,7 @@ define([ let newRowData = response.signatures[0]; // update "updated" cell - updateSignatureCell(rowElement, 6, newRowData.updated); + updateSignatureCell(rowElement, 7, newRowData.updated); } // find related "type" select (same row) and change options @@ -1166,6 +1200,18 @@ define([ }else{ typeSelect.editable('disable'); } + + // find "connection" select (same row) and change "enabled" flag + let connectionSelect = getNextEditableField(signatureTypeField, '.' + config.sigTableConnectionClass); + connectionSelect.editable('setValue', null); + + if(newValue === 5){ + // wormhole + connectionSelect.editable('enable'); + }else{ + checkConnectionConflicts(); + connectionSelect.editable('disable'); + } } }); @@ -1204,7 +1250,7 @@ define([ let newRowData = response.signatures[0]; // update "updated" cell - updateSignatureCell(rowElement, 6, newRowData.updated); + updateSignatureCell(rowElement, 7, newRowData.updated); } } }); @@ -1227,7 +1273,61 @@ define([ let newRowData = response.signatures[0]; // update "updated" cell - updateSignatureCell(rowElement, 6, newRowData.updated); + updateSignatureCell(rowElement, 7, newRowData.updated); + } + } + }); + + // Select connection (target system) -------------------------------------------------------------------------- + let initCount = 0; + sigConnectionFields.on('init', function(e, editable) { + if(++initCount >= sigConnectionFields.length){ + checkConnectionConflicts(); + } + }); + + sigConnectionFields.editable({ + type: 'select', + title: 'system', + name: 'connectionId', + emptytext: 'unknown', + onblur: 'submit', + showbuttons: false, + params: modifyFieldParamsOnSend, + display: function(value, sourceData) { + let editableElement = $(this); + let newValue = ''; + + if(value !== null){ + let selected = $.fn.editableutils.itemsByValue(value, sourceData); + if( + selected.length && + selected[0].text !== '' + ){ + newValue += ''; + newValue += ' ' + selected[0].text; + }else{ + newValue = 'unknown'; + } + } + + editableElement.html(newValue); + }, + source: function(a,b){ + let activeMap = Util.getMapModule().getActiveMap(); + let mapId = activeMap.data('id'); + let availableConnections = getSignatureConnectionOptions(mapId, systemData); + + return availableConnections; + }, + success: function(response, newValue){ + if(response){ + let signatureConnectionField = $(this); + let rowElement = signatureConnectionField.parents('tr'); + let newRowData = response.signatures[0]; + + // update "updated" cell + updateSignatureCell(rowElement, 7, newRowData.updated); } } }); @@ -1244,11 +1344,106 @@ define([ tableElement.parents('.' + config.tableToolsActionClass).css( 'height', '-=35px' ); }); + // save events + sigConnectionFields.on('save', function(e, editable){ + checkConnectionConflicts(); + }); + // open next field dialog ------------------------------------------------------------------------------------- openNextEditDialogOnSave(sigNameFields); openNextEditDialogOnSave(sigGroupFields); }; + /** + * get all connection select options + * @param mapId + * @param systemData + * @returns {Array} + */ + let getSignatureConnectionOptions = (mapId, systemData) => { + let map = Map.getMapInstance( mapId ); + let systemId = MapUtil.getSystemId(mapId, systemData.id); + let systemConnections = MapUtil.searchConnectionsBySystems(map, [systemId]); + let connectionOptions = []; + + for(let i = 0; i < systemConnections.length; i++){ + let connectionData = Map.getDataByConnection(systemConnections[i]); + + // 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){ + // take target... + connectionOptions.push({ + value: connectionData.id, + text: connectionData.targetName + }); + }else if(systemData.id !== connectionData.source){ + // take source... + connectionOptions.push({ + value: connectionData.id, + text: connectionData.sourceName + }); + } + } + } + + // add empty entry + connectionOptions.unshift({ value: null, text: ''}); + + return connectionOptions; + }; + + /** + * check connectionIds for conflicts (multiple signatures -> same connection) + * -> show "conflict" icon next to select + */ + let checkConnectionConflicts = () => { + setTimeout(function() { + let connectionSelects = $('.' + config.sigTableConnectionClass + ' .editable'); + let connectionIds = []; + let duplicateConnectionIds = []; + let groupedSelects = []; + + connectionSelects.each(function(){ + let select = $(this); + let value = parseInt(select.editable('getValue', true) )|| 0; + + if( + connectionIds.indexOf(value) > -1 && + duplicateConnectionIds.indexOf(value) === -1 + ){ + // duplicate found + duplicateConnectionIds.push(value); + } + + if(groupedSelects[value] !== undefined){ + groupedSelects[value].push(select[0]); + }else{ + groupedSelects[value] = [select[0]]; + } + + connectionIds.push(value); + }); + + // update "conflict" icon next to select label for connectionIds + connectionSelects.each(function(){ + let select = $(this); + let value = parseInt(select.editable('getValue', true) )|| 0; + let conflictIcon = select.find('.fa-exclamation-triangle'); + if( + duplicateConnectionIds.indexOf(value) > -1 && + groupedSelects[value].indexOf(select[0]) > -1 + ){ + conflictIcon.removeClass('hide'); + }else{ + conflictIcon.addClass('hide'); + } + }); + }, 200); + }; + /** * get all signatures that can exist for a given system * @param systemData @@ -1451,6 +1646,9 @@ define([ // update signature bar moduleElement.updateScannedSignaturesBar({showNotice: false}); + // update connection conflicts + checkConnectionConflicts(); + Util.showNotify({title: 'Signature deleted', text: signatureCount + ' signatures deleted', type: 'success'}); } }; @@ -1789,6 +1987,18 @@ define([ data: 'description' },{ targets: 5, + orderable: false, + searchable: false, + className: [config.sigTableConnectionClass].join(' '), + title: 'leads to', + type: 'html', + width: '70px', + data: 'connection', + render: { + _: 'render' + } + },{ + targets: 6, title: 'created', width: '90px', searchable: false, @@ -1802,7 +2012,7 @@ define([ $(cell).initTimestampCounter(); } },{ - targets: 6, + targets: 7, title: 'updated', width: '90px', searchable: false, @@ -1824,7 +2034,7 @@ define([ } } },{ - targets: 7, + targets: 8, title: '', orderable: false, searchable: false, @@ -1845,7 +2055,7 @@ define([ } } },{ - targets: 8, + targets: 9, title: '', orderable: false, searchable: false, diff --git a/public/js/v1.2.1/app/map/map.js b/public/js/v1.2.1/app/map/map.js index 4e6cc5af..478c5cdb 100644 --- a/public/js/v1.2.1/app/map/map.js +++ b/public/js/v1.2.1/app/map/map.js @@ -32,7 +32,6 @@ define([ mapClass: 'pf-map', // class for all maps mapIdPrefix: 'pf-map-', // id prefix for all maps - systemIdPrefix: 'pf-system-', // id prefix for a system systemClass: 'pf-system', // class for all systems systemActiveClass: 'pf-system-active', // class for an active system in a map systemSelectedClass: 'pf-system-selected', // class for selected systems in a map @@ -453,7 +452,7 @@ define([ $.fn.getSystem = function(map, data){ // get map container for mapId information let mapContainer = $(this); - let systemId = config.systemIdPrefix + mapContainer.data('id') + '-' + data.id; + let systemId = MapUtil.getSystemId(mapContainer.data('id'), data.id); // check if system already exists let system = document.getElementById( systemId ); @@ -753,8 +752,8 @@ define([ let mapId = mapContainer.data('id'); let connectionId = connectionData.id || 0; let connection; - let sourceSystem = $('#' + config.systemIdPrefix + mapId + '-' + connectionData.source); - let targetSystem = $('#' + config.systemIdPrefix + mapId + '-' + connectionData.target); + let sourceSystem = $('#' + MapUtil.getSystemId(mapId, connectionData.source) ); + let targetSystem = $('#' + MapUtil.getSystemId(mapId, connectionData.target) ); // check if both systems exists // (If not -> something went wrong e.g. DB-Foreign keys for "ON DELETE",...) @@ -851,10 +850,10 @@ define([ // check if source or target has changed if(connectionData.source !== newConnectionData.source ){ - map.setSource(connection, config.systemIdPrefix + mapId + '-' + newConnectionData.source); + map.setSource(connection, MapUtil.getSystemId(mapId, newConnectionData.source) ); } if(connectionData.target !== newConnectionData.target ){ - map.setTarget(connection, config.systemIdPrefix + mapId + '-' + newConnectionData.target); + map.setTarget(connection, MapUtil.getSystemId(mapId, newConnectionData.target) ); } // connection.targetId @@ -998,7 +997,7 @@ define([ } if(deleteThisSystem === true){ - let deleteSystem = $('#' + config.systemIdPrefix + mapContainer.data('id') + '-' + currentSystemData[a].id); + let deleteSystem = $('#' + MapUtil.getSystemId(mapContainer.data('id'), currentSystemData[a].id) ); // system not found -> delete system System.removeSystems(mapConfig.map, deleteSystem); @@ -1423,7 +1422,6 @@ define([ * @returns {{id: Number, source: Number, sourceName: (*|T|JQuery|{}), target: Number, targetName: (*|T|JQuery), scope: *, type: *, updated: Number}} */ let getDataByConnection = function(connection){ - let source = $(connection.source); let target = $(connection.target); @@ -2786,7 +2784,7 @@ define([ $(mapContainer).on('pf:menuSelectSystem', function(e, data){ let tempMapContainer = $(this); - let systemId = config.systemIdPrefix + tempMapContainer.data('id') + '-' + data.systemId; + let systemId = MapUtil.getSystemId(tempMapContainer.data('id'), data.systemId); let system = $(this).find('#' + systemId); if(system.length === 1){ @@ -3309,7 +3307,6 @@ define([ return { getMapInstance: getMapInstance, clearMapInstance: clearMapInstance, - getDataByConnection: getDataByConnection }; diff --git a/public/js/v1.2.1/app/map/util.js b/public/js/v1.2.1/app/map/util.js index c9c4a1f1..fdc36bdc 100644 --- a/public/js/v1.2.1/app/map/util.js +++ b/public/js/v1.2.1/app/map/util.js @@ -17,6 +17,7 @@ define([ mapLocalStoragePrefix: 'map_', // prefix for map data local storage key mapTabContentClass: 'pf-map-tab-content', // Tab-Content element (parent element) + systemIdPrefix: 'pf-system-', // id prefix for a system systemClass: 'pf-system', // class for all systems mapGridClass: 'pf-grid-small' // class for map grid snapping }; @@ -191,7 +192,6 @@ define([ return this.find('.' + config.systemClass); }; - /** * search connections by systems * @param {Object} map - jsPlumb @@ -200,7 +200,7 @@ define([ */ let searchConnectionsBySystems = function(map, systems){ let connections = []; - let withBackConnection = false; + let withBackConnection = true; $.each(systems, function(i, system){ // get connections where system is source @@ -571,6 +571,16 @@ define([ }); }; + /** + * get systemId string (selector + * @param mapId + * @param systemId + * @returns {string} + */ + let getSystemId = (mapId, systemId) => { + return config.systemIdPrefix + mapId + '-' + systemId; + }; + return { config: config, mapOptions: mapOptions, @@ -593,6 +603,7 @@ define([ storeDefaultMapId: storeDefaultMapId, getLocaleData: getLocaleData, storeLocalData: storeLocalData, - deleteLocalData: deleteLocalData + deleteLocalData: deleteLocalData, + getSystemId: getSystemId }; }); \ No newline at end of file diff --git a/public/js/v1.2.1/app/ui/dialog/map_info.js b/public/js/v1.2.1/app/ui/dialog/map_info.js index 0d747d74..10140f7b 100644 --- a/public/js/v1.2.1/app/ui/dialog/map_info.js +++ b/public/js/v1.2.1/app/ui/dialog/map_info.js @@ -36,8 +36,6 @@ define([ tableActionCellClass: 'pf-table-action-cell', // class for table "action" cells tableCounterCellClass: 'pf-table-counter-cell', // class for table "counter" cells - systemIdPrefix: 'pf-system-', // id prefix for a system - loadingOptions: { // config for loading overlay icon: { size: 'fa-2x' @@ -430,7 +428,7 @@ define([ let deleteRowElement = $(target).parents('tr'); let activeMap = Util.getMapModule().getActiveMap(); - let systemElement = $('#' + config.systemIdPrefix + mapData.config.id + '-' + rowData.id); + let systemElement = MapUtil.getSystemId(mapData.config.id, rowData.id); if(systemElement){ // trigger system delete event diff --git a/public/js/v1.2.1/app/ui/system_signature.js b/public/js/v1.2.1/app/ui/system_signature.js index ba8ae690..e45baae7 100644 --- a/public/js/v1.2.1/app/ui/system_signature.js +++ b/public/js/v1.2.1/app/ui/system_signature.js @@ -7,8 +7,10 @@ define([ 'app/init', 'app/util', 'app/render', - 'bootbox' -], function($, Init, Util, Render, bootbox) { + 'bootbox', + 'app/map/map', + 'app/map/util' +], function($, Init, Util, Render, bootbox, Map, MapUtil) { 'use strict'; let config = { @@ -40,10 +42,12 @@ define([ sigTableEditSigNameInput: 'pf-sig-table-edit-name-input', // class for editable fields (input) sigTableEditSigGroupSelect: 'pf-sig-table-edit-group-select', // class for editable fields (sig group) sigTableEditSigTypeSelect: 'pf-sig-table-edit-type-select', // class for editable fields (sig type) + sigTableEditSigConnectionSelect: 'pf-sig-table-edit-connection-select', // class for editable fields (sig connection) sigTableEditSigDescriptionTextarea: 'pf-sig-table-edit-desc-text', // class for editable fields (sig description) sigTableCreatedCellClass: 'pf-sig-table-created', // class for "created" cells sigTableUpdatedCellClass: 'pf-sig-table-updated', // class for "updated" cells + sigTableConnectionClass: 'pf-table-connection-cell', // class for "connection" cells sigTableCounterClass: 'pf-table-counter-cell', // class for "counter" cells sigTableActionCellClass: 'pf-table-action-cell', // class for "action" cells @@ -159,7 +163,7 @@ define([ let updateCell = signatureTableApi.cell( rowIndex, cellIndex ); let updateCellElement = updateCell.nodes().to$(); - if(cellIndex === 6){ + if(cellIndex === 7){ // clear existing counter interval clearInterval( updateCellElement.data('interval') ); } @@ -167,7 +171,7 @@ define([ // set new value updateCell.data( data ).draw(); - if(cellIndex === 6){ + if(cellIndex === 7){ updateCellElement.initTimestampCounter(); } }; @@ -694,6 +698,27 @@ define([ tempData.type = sigType; + // set connection (to target system) ------------------------------------------------------------------ + let sigConnection = ' 0){ + sigConnection += 'data-pk="' + data.id + '" '; + } + + // set disabled if group is not wromhole + if(data.groupId !== 5){ + sigConnection += 'data-disabled="1" '; + } + + if(data.connection){ + sigConnection += 'data-value="' + data.connection.id + '" '; + } + sigConnection += '>'; + + tempData.connection = { + render: sigConnection, + connection: data.connection + }; + // set description ------------------------------------------------------------------------------------ let sigDescription = ' 0){ @@ -1014,6 +1039,7 @@ define([ let sigGroupFields = tableElement.find('.' + config.sigTableEditSigGroupSelect); let sigTypeFields = tableElement.find('.' + config.sigTableEditSigTypeSelect); let sigDescriptionFields = tableElement.find('.' + config.sigTableEditSigDescriptionTextarea); + let sigConnectionFields = tableElement.find('.' + config.sigTableEditSigConnectionSelect); // jump to "next" editable field on save let openNextEditDialogOnSave = function(fields){ @@ -1038,8 +1064,16 @@ define([ }; // helper function - get the next editable field in next table column - let getNextEditableField = function(field){ - let nextEditableField = $(field).closest('td').next().find('.editable'); + let getNextEditableField = function(field, selector){ + let nextEditableField = null; + if(selector){ + // search specific sibling + nextEditableField = $(field).closest('td').nextAll(selector).find('.editable'); + }else{ + // get next sibling + nextEditableField = $(field).closest('td').next().find('.editable'); + } + return $(nextEditableField); }; @@ -1108,7 +1142,7 @@ define([ updateTooltip(columnElement, newValue); // update "updated" cell - updateSignatureCell(rowElement, 6, newRowData.updated); + updateSignatureCell(rowElement, 7, newRowData.updated); } } }); @@ -1145,7 +1179,7 @@ define([ let newRowData = response.signatures[0]; // update "updated" cell - updateSignatureCell(rowElement, 6, newRowData.updated); + updateSignatureCell(rowElement, 7, newRowData.updated); } // find related "type" select (same row) and change options @@ -1166,6 +1200,18 @@ define([ }else{ typeSelect.editable('disable'); } + + // find "connection" select (same row) and change "enabled" flag + let connectionSelect = getNextEditableField(signatureTypeField, '.' + config.sigTableConnectionClass); + connectionSelect.editable('setValue', null); + + if(newValue === 5){ + // wormhole + connectionSelect.editable('enable'); + }else{ + checkConnectionConflicts(); + connectionSelect.editable('disable'); + } } }); @@ -1204,7 +1250,7 @@ define([ let newRowData = response.signatures[0]; // update "updated" cell - updateSignatureCell(rowElement, 6, newRowData.updated); + updateSignatureCell(rowElement, 7, newRowData.updated); } } }); @@ -1227,7 +1273,61 @@ define([ let newRowData = response.signatures[0]; // update "updated" cell - updateSignatureCell(rowElement, 6, newRowData.updated); + updateSignatureCell(rowElement, 7, newRowData.updated); + } + } + }); + + // Select connection (target system) -------------------------------------------------------------------------- + let initCount = 0; + sigConnectionFields.on('init', function(e, editable) { + if(++initCount >= sigConnectionFields.length){ + checkConnectionConflicts(); + } + }); + + sigConnectionFields.editable({ + type: 'select', + title: 'system', + name: 'connectionId', + emptytext: 'unknown', + onblur: 'submit', + showbuttons: false, + params: modifyFieldParamsOnSend, + display: function(value, sourceData) { + let editableElement = $(this); + let newValue = ''; + + if(value !== null){ + let selected = $.fn.editableutils.itemsByValue(value, sourceData); + if( + selected.length && + selected[0].text !== '' + ){ + newValue += ''; + newValue += ' ' + selected[0].text; + }else{ + newValue = 'unknown'; + } + } + + editableElement.html(newValue); + }, + source: function(a,b){ + let activeMap = Util.getMapModule().getActiveMap(); + let mapId = activeMap.data('id'); + let availableConnections = getSignatureConnectionOptions(mapId, systemData); + + return availableConnections; + }, + success: function(response, newValue){ + if(response){ + let signatureConnectionField = $(this); + let rowElement = signatureConnectionField.parents('tr'); + let newRowData = response.signatures[0]; + + // update "updated" cell + updateSignatureCell(rowElement, 7, newRowData.updated); } } }); @@ -1244,11 +1344,106 @@ define([ tableElement.parents('.' + config.tableToolsActionClass).css( 'height', '-=35px' ); }); + // save events + sigConnectionFields.on('save', function(e, editable){ + checkConnectionConflicts(); + }); + // open next field dialog ------------------------------------------------------------------------------------- openNextEditDialogOnSave(sigNameFields); openNextEditDialogOnSave(sigGroupFields); }; + /** + * get all connection select options + * @param mapId + * @param systemData + * @returns {Array} + */ + let getSignatureConnectionOptions = (mapId, systemData) => { + let map = Map.getMapInstance( mapId ); + let systemId = MapUtil.getSystemId(mapId, systemData.id); + let systemConnections = MapUtil.searchConnectionsBySystems(map, [systemId]); + let connectionOptions = []; + + for(let i = 0; i < systemConnections.length; i++){ + let connectionData = Map.getDataByConnection(systemConnections[i]); + + // 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){ + // take target... + connectionOptions.push({ + value: connectionData.id, + text: connectionData.targetName + }); + }else if(systemData.id !== connectionData.source){ + // take source... + connectionOptions.push({ + value: connectionData.id, + text: connectionData.sourceName + }); + } + } + } + + // add empty entry + connectionOptions.unshift({ value: null, text: ''}); + + return connectionOptions; + }; + + /** + * check connectionIds for conflicts (multiple signatures -> same connection) + * -> show "conflict" icon next to select + */ + let checkConnectionConflicts = () => { + setTimeout(function() { + let connectionSelects = $('.' + config.sigTableConnectionClass + ' .editable'); + let connectionIds = []; + let duplicateConnectionIds = []; + let groupedSelects = []; + + connectionSelects.each(function(){ + let select = $(this); + let value = parseInt(select.editable('getValue', true) )|| 0; + + if( + connectionIds.indexOf(value) > -1 && + duplicateConnectionIds.indexOf(value) === -1 + ){ + // duplicate found + duplicateConnectionIds.push(value); + } + + if(groupedSelects[value] !== undefined){ + groupedSelects[value].push(select[0]); + }else{ + groupedSelects[value] = [select[0]]; + } + + connectionIds.push(value); + }); + + // update "conflict" icon next to select label for connectionIds + connectionSelects.each(function(){ + let select = $(this); + let value = parseInt(select.editable('getValue', true) )|| 0; + let conflictIcon = select.find('.fa-exclamation-triangle'); + if( + duplicateConnectionIds.indexOf(value) > -1 && + groupedSelects[value].indexOf(select[0]) > -1 + ){ + conflictIcon.removeClass('hide'); + }else{ + conflictIcon.addClass('hide'); + } + }); + }, 200); + }; + /** * get all signatures that can exist for a given system * @param systemData @@ -1451,6 +1646,9 @@ define([ // update signature bar moduleElement.updateScannedSignaturesBar({showNotice: false}); + // update connection conflicts + checkConnectionConflicts(); + Util.showNotify({title: 'Signature deleted', text: signatureCount + ' signatures deleted', type: 'success'}); } }; @@ -1789,6 +1987,18 @@ define([ data: 'description' },{ targets: 5, + orderable: false, + searchable: false, + className: [config.sigTableConnectionClass].join(' '), + title: 'leads to', + type: 'html', + width: '70px', + data: 'connection', + render: { + _: 'render' + } + },{ + targets: 6, title: 'created', width: '90px', searchable: false, @@ -1802,7 +2012,7 @@ define([ $(cell).initTimestampCounter(); } },{ - targets: 6, + targets: 7, title: 'updated', width: '90px', searchable: false, @@ -1824,7 +2034,7 @@ define([ } } },{ - targets: 7, + targets: 8, title: '', orderable: false, searchable: false, @@ -1845,7 +2055,7 @@ define([ } } },{ - targets: 8, + targets: 9, title: '', orderable: false, searchable: false, diff --git a/public/templates/dialog/credit.html b/public/templates/dialog/credit.html index 4e036800..31f05a65 100644 --- a/public/templates/dialog/credit.html +++ b/public/templates/dialog/credit.html @@ -28,7 +28,7 @@
pathfinder
Repository
GitHub
-
Community
+
Social
Google+