diff --git a/app/main/lib/db/SQL.php b/app/main/lib/db/SQL.php index b1ea5711..dc56edba 100644 --- a/app/main/lib/db/SQL.php +++ b/app/main/lib/db/SQL.php @@ -19,6 +19,14 @@ class SQL extends \DB\SQL { parent::__construct($dsn, $user, $pw, $options); } + /** + * get DB DSN config string + * @return string + */ + public function getDSN() : string { + return $this->dsn; + } + /** * get all table names * @return array|bool @@ -27,6 +35,7 @@ class SQL extends \DB\SQL { $schema = new Schema($this); return $schema->getTables(); } + /** * checks whether a table exists or not * @param string $table diff --git a/app/main/model/abstractmodel.php b/app/main/model/abstractmodel.php index 382f355b..db5e8594 100644 --- a/app/main/model/abstractmodel.php +++ b/app/main/model/abstractmodel.php @@ -154,6 +154,22 @@ abstract class AbstractModel extends Cortex { }); } + /** + * clear existing table Schema cache + * @return bool + */ + public function clearSchemaCache() : bool { + $f3 = self::getF3(); + $cache=\Cache::instance(); + if( + $f3->CACHE && is_object($this->db) && + $cache->exists($hash = $f3->hash($this->db->getDSN() . $this->table) . '.schema') + ){ + return (bool)$cache->clear($hash); + } + return false; + } + /** * @param string $key * @param mixed $val diff --git a/js/app/map/magnetizing.js b/js/app/map/magnetizing.js index 40954184..f63f8ed2 100644 --- a/js/app/map/magnetizing.js +++ b/js/app/map/magnetizing.js @@ -74,7 +74,7 @@ define([ } if(markAsUpdated === true){ - $(system).markAsChanged(); + MapUtil.markAsChanged($(system)); } }; diff --git a/js/app/map/map.js b/js/app/map/map.js index a4b2c639..a79bf830 100644 --- a/js/app/map/map.js +++ b/js/app/map/map.js @@ -112,6 +112,34 @@ define([ connectionTypes: Init.connectionTypes }; + /** + * revalidate (repaint) all connections of el + * -> in addition this re-calculates the Location of potential Endpoint Overlays + * @param map + * @param element (can also be an array) + */ + let revalidate = (map, element) => { + map.revalidate(element); + + // get attached connections + let elements = (typeof element === 'object' && element.length) ? element : [element]; + for(let element of elements){ + let connectionsInfo = map.anchorManager.getConnectionsFor(element.id); + for(let connectionInfo of connectionsInfo){ + // index 0 -> Connection, 1 -> Endpoint + // -> we need BOTH endpoints of a connection -> index 0 + for(let endpoint of connectionInfo[0].endpoints){ + // check if there is a Label overlay + let overlay = endpoint.getOverlay('pf-map-endpoint-overlay'); + if(overlay instanceof jsPlumb.Overlays.Label){ + let label = overlay.getParameter('label'); + overlay.setLocation(MapUtil.getLabelEndpointOverlayLocation(endpoint, label)); + } + } + } + } + }; + /** * updates a system with current information * @param map @@ -282,7 +310,7 @@ define([ duration: 50, display: 'auto', progress: function(){ - //revalidate element size and repaint + //re-validate element size and repaint map.revalidate( systemDomId ); }, complete: function(){ @@ -371,7 +399,6 @@ define([ // get system info classes let effectBasicClass = MapUtil.getEffectInfoForSystem('effect', 'class'); - let effectName = MapUtil.getEffectInfoForSystem(data.effect, 'name'); let effectClass = MapUtil.getEffectInfoForSystem(data.effect, 'class'); let secClass = Util.getSecurityClassForSystem(data.security); @@ -449,14 +476,14 @@ define([ // move them to the "top" $(system).updateSystemZIndex(); }, - progress: function(){ - map.revalidate( systemId ); + progress: function(system){ + revalidate(map, system); }, complete: function(system){ // show tooltip $(system).toggleSystemTooltip('show', {show: true}); - map.revalidate( systemId ); + revalidate(map, system); } } ); @@ -494,7 +521,7 @@ define([ system.attr('data-mapid', parseInt(mapContainer.data('id'))); // locked system - if( Boolean( system.data('locked') ) !== data.locked ){ + if( Boolean(system.data('locked')) !== data.locked ){ system.toggleLockSystem(false, {hideNotification: true, hideCounter: true, map: map}); } @@ -530,16 +557,16 @@ define([ // repaint connections, -> system changed its size! map.repaint(system); - system.markAsChanged(); + MapUtil.markAsChanged(system); break; case 'set_rally': // toggle rally point - if( !system.data('rallyUpdated') ){ + if(!system.data('rallyUpdated')){ $.fn.showRallyPointDialog(system); }else{ // remove rally point system.setSystemRally(0); - system.markAsChanged(); + MapUtil.markAsChanged(system); } break; case 'find_route': @@ -567,7 +594,7 @@ define([ system.setSystemStatus(statusString[2]); - system.markAsChanged(); + MapUtil.markAsChanged(system); break; case 'delete_system': // delete this system AND delete selected systems as well @@ -705,7 +732,7 @@ define([ case 'wh_eol': // set "end of life" mapElement.getMapOverlay('timer').startMapUpdateCounter(); connection.toggleType(action); - $(connection).markAsChanged(); + MapUtil.markAsChanged(connection); break; case 'status_fresh': case 'status_reduced': @@ -714,7 +741,7 @@ define([ mapElement.getMapOverlay('timer').startMapUpdateCounter(); MapUtil.setConnectionWHStatus(connection, 'wh_' + newStatus); - $(connection).markAsChanged(); + MapUtil.markAsChanged(connection); break; case 'scope_wh': case 'scope_stargate': @@ -730,7 +757,7 @@ define([ Util.showNotify({title: 'Connection scope changed', text: 'New scope: ' + newScopeName, type: 'success'}); - $(connection).markAsChanged(); + MapUtil.markAsChanged(connection); } }); break; @@ -752,7 +779,7 @@ define([ endpoint.toggleType(action); for(let connection of endpoint.connections){ - $(connection).markAsChanged(); + MapUtil.markAsChanged(connection); } break; } @@ -802,7 +829,7 @@ define([ // set new new connection type // if scope changed -> connection type == scope - connection.setType( MapUtil.getDefaultConnectionTypeByScope(scope) ); + connection.setType(MapUtil.getDefaultConnectionTypeByScope(scope)); // change scope connection.scope = scope; @@ -816,12 +843,12 @@ define([ * @returns new connection */ let drawConnection = (map, connectionData) => { - let mapContainer = $( map.getContainer() ); + let mapContainer = $(map.getContainer()); let mapId = mapContainer.data('id'); let connectionId = connectionData.id || 0; let connection; - let sourceSystem = $('#' + MapUtil.getSystemId(mapId, connectionData.source) ); - let targetSystem = $('#' + MapUtil.getSystemId(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",...) @@ -833,7 +860,7 @@ define([ source: sourceSystem[0], target: targetSystem[0], scope: connectionData.scope || map.Defaults.Scope, - type: (connectionData.type || MapUtil.getDefaultConnectionTypeByScope(map.Defaults.Scope)).join(' '), + type: (connectionData.type || MapUtil.getDefaultConnectionTypeByScope(map.Defaults.Scope)).join(' ') /* experimental set "static" connection parameters in initial load parameters: { connectionId: connectionId, @@ -906,15 +933,21 @@ define([ let updateConnection = (connection, newConnectionData) => { let connectionData = MapUtil.getDataByConnection(connection); let map = connection._jsPlumb.instance; - let mapContainer = $( map.getContainer() ); + let mapContainer = $(map.getContainer()); let mapId = mapContainer.data('id'); - // check id, IDs should never change but must be set after initial save + // type "process" is not included in connectionData + // -> if "process" type exists, add it types for removal + if(connection.hasType('state_process')){ + connectionData.type.push('state_process'); + } + + // check id, IDs should never change but must be set after initial save --------------------------------------- if(connection.getParameter('connectionId') !== newConnectionData.id){ connection.setParameter('connectionId', newConnectionData.id); } - // check scope + // update scope ----------------------------------------------------------------------------------------------- if(connectionData.scope !== newConnectionData.scope){ setConnectionScope(connection, newConnectionData.scope); } @@ -922,17 +955,17 @@ define([ let addType = newConnectionData.type.diff(connectionData.type); let removeType = connectionData.type.diff(newConnectionData.type); - // check if source or target has changed - if(connectionData.source !== newConnectionData.source ){ - map.setSource(connection, MapUtil.getSystemId(mapId, newConnectionData.source) ); + // update source/target (after drag&drop) --------------------------------------------------------------------- + if(connectionData.source !== newConnectionData.source){ + map.setSource(connection, MapUtil.getSystemId(mapId, newConnectionData.source)); } - if(connectionData.target !== newConnectionData.target ){ - map.setTarget(connection, MapUtil.getSystemId(mapId, newConnectionData.target) ); + if(connectionData.target !== newConnectionData.target){ + map.setTarget(connection, MapUtil.getSystemId(mapId, newConnectionData.target)); } + // update connection types ------------------------------------------------------------------------------------ let checkAvailability = (arr, val) => arr.some(arrVal => arrVal === val); - // add types for(let type of addType){ if(checkAvailability(['fresh', 'reduced', 'critical'], type)){ MapUtil.setConnectionWHStatus(connection, type); @@ -942,17 +975,21 @@ define([ } } - // remove types for(let type of removeType){ - if(checkAvailability(['wh_eol', 'frigate', 'preserve_mass'], type)){ + if(checkAvailability(['wh_eol', 'frigate', 'preserve_mass', 'state_process'], type)){ connection.removeType(type); } } - // update endpoints + // update endpoints ------------------------------------------------------------------------------------------- + // important: In case source or target changed (drag&drop) (see above lines..) + // -> NEW endpoints are created (default Endpoint properties from makeSource()/makeTarget() call are used + // -> connectionData.endpoints might no longer be valid -> get fresh endpointData + let endpointData = MapUtil.getEndpointsDataByConnection(connection); + for(let endpoint of connection.endpoints){ let label = MapUtil.getEndpointLabel(connection, endpoint); - let endpointTypes = Util.getObjVal(connectionData, ['endpoints', label, 'types'].join('.')) || []; + let endpointTypes = Util.getObjVal(endpointData, [label, 'types'].join('.')) || []; let newEndpointTypes = Util.getObjVal(newConnectionData, ['endpoints', label, 'types'].join('.')) || []; let addEndpointTypes = newEndpointTypes.diff(endpointTypes); @@ -1156,7 +1193,8 @@ define([ } // get map data - let mapData = mapContainer.getMapDataFromClient({forceData: false}); + let mapData = getMapDataForSync(mapContainer, [], true); + if(mapData !== false){ // map data available -> map not locked by update counter :) @@ -1172,7 +1210,7 @@ define([ for(let k = 0; k < currentSystemData.length; k++){ if(currentSystemData[k].id === systemData.id){ - if( currentSystemData[k].updated.updated < systemData.updated.updated ){ + if(currentSystemData[k].updated.updated < systemData.updated.updated){ // system changed -> update mapContainer.getSystem(mapConfig.map, systemData); } @@ -1190,7 +1228,6 @@ define([ // check for systems that are gone -> delete system for(let a = 0; a < currentSystemData.length; a++){ - let deleteThisSystem = true; for(let b = 0; b < mapConfig.data.systems.length; b++){ @@ -1203,7 +1240,7 @@ define([ } if(deleteThisSystem === true){ - let deleteSystem = $('#' + MapUtil.getSystemId(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); @@ -1223,18 +1260,23 @@ define([ let addNewConnection= true; for(let c = 0; c < currentConnectionData.length; c++){ - if( - currentConnectionData[c].id === connectionData.id - ){ + if(currentConnectionData[c].id === connectionData.id){ // connection already exists -> check for updates - if( - currentConnectionData[c].updated < connectionData.updated - ){ + if(currentConnectionData[c].updated < connectionData.updated){ // connection changed -> update - let tempConnection = $().getConnectionById(mapData.config.id, connectionData.id); - updateConnection(tempConnection, connectionData); + updateConnection(currentConnectionData[c].connection, connectionData); } + addNewConnection = false; + break; + }else if( + currentConnectionData[c].id === 0 && + currentConnectionData[c].source === connectionData.source && + currentConnectionData[c].target === connectionData.target + ){ + // if ids don´t match -> check for unsaved connection + updateConnection(currentConnectionData[c].connection, connectionData); + addNewConnection = false; break; } @@ -1247,6 +1289,10 @@ define([ // check for connections that are gone -> delete connection for(let d = 0; d < currentConnectionData.length; d++){ + // skip connections with id = 0 -> they might get updated before + if(currentConnectionData[d].id === 0){ + continue; + } let deleteThisConnection = true; @@ -1260,8 +1306,8 @@ define([ } if(deleteThisConnection === true){ - // get connection from cache -> delete connection - let deleteConnection = $().getConnectionById(mapData.config.id, currentConnectionData[d].id); + // connection not found -> delete connection + let deleteConnection = currentConnectionData[d].connection; if(deleteConnection){ // check if "source" and "target" still exist before remove @@ -1326,13 +1372,12 @@ define([ */ let updateConnectionsCache = map => { let connections = map.getAllConnections(); - let mapContainer = $( map.getContainer() ); + let mapContainer = $(map.getContainer()); let mapId = mapContainer.data('id'); if(mapId > 0){ // clear cache connectionCache[mapId] = []; - for(let i = 0; i < connections.length; i++){ updateConnectionCache(mapId, connections[i]); } @@ -1351,8 +1396,7 @@ define([ mapId > 0 && connection ){ - let connectionId = parseInt( connection.getParameter('connectionId') ); - + let connectionId = parseInt(connection.getParameter('connectionId')); if(connectionId > 0){ connectionCache[mapId][connectionId] = connection; } @@ -1387,7 +1431,7 @@ define([ * @param system */ let makeSource = (map, system) => { - if( !map.isSource(system) ){ + if(!map.isSource(system)){ // get scope from map defaults let sourceConfig = globalMapConfig.source; sourceConfig.scope = map.Defaults.Scope; // set all allowed connections for this scopes @@ -1405,7 +1449,7 @@ define([ * @param system */ let makeTarget = (map, system) => { - if( !map.isTarget(system) ){ + if(!map.isTarget(system)){ // get scope from map defaults let targetConfig = globalMapConfig.target; targetConfig.scope = map.Defaults.Scope; // set all allowed connections for this scopes @@ -1503,7 +1547,7 @@ define([ headElement.on('save', function(e, params){ // system alias changed -> mark system as updated - system.markAsChanged(); + MapUtil.markAsChanged(system); }); headElement.on('shown', function(e, editable){ @@ -1525,7 +1569,7 @@ define([ // if system with changed (e.g. long alias) -> revalidate system let map = MapUtil.getMapInstance(system.attr('data-mapid')); - map.revalidate(system.attr('id')); + revalidate(map, system); }); }; @@ -1564,36 +1608,12 @@ define([ payload => { let newConnectionData = payload.data; - if( !$.isEmptyObject(newConnectionData) ){ - payload.context.connection.removeType('state_process'); + if(!$.isEmptyObject(newConnectionData)){ + // update connection data e.g. "scope" has auto detected + connection = updateConnection(payload.context.connection, newConnectionData); - let updateCon = false; - - if(payload.context.oldConnectionData.id > 0){ - // connection exists (e.g. drag&drop new target system... (ids should never changed) - let connection = $().getConnectionById(payload.context.mapId, payload.context.oldConnectionData.id); - updateCon = true; - }else{ - // new connection, check if connectionId was already updated (webSocket push is faster than ajax callback) - let connection = $().getConnectionById(payload.context.mapId, newConnectionData.id); - - if(connection){ - // connection already updated - payload.context.map.detach(payload.context.connection, {fireEvent: false}); - }else{ - // .. else update this connection - connection = payload.context.connection; - updateCon = true; - } - } - - if(updateCon){ - // update connection data e.g. "scope" has auto detected - connection = updateConnection(connection, newConnectionData); - - // new/updated connection should be cached immediately! - updateConnectionCache(payload.context.mapId, connection); - } + // new/updated connection should be cached immediately! + updateConnectionCache(payload.context.mapId, connection); // connection scope let scope = MapUtil.getScopeInfoForConnection(newConnectionData.scope, 'label'); @@ -1795,7 +1815,7 @@ define([ system = $(system); // get map container - let mapContainer = $( map.getContainer() ); + let mapContainer = $(map.getContainer()); let grid = [MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension]; // map overlay will be set on "drag" start let mapOverlayTimer = null; @@ -1816,7 +1836,7 @@ define([ mapOverlayTimer.startMapUpdateCounter(); // check if grid-snap is enable -> this enables napping for !CURRENT! Element - if( mapContainer.hasClass(MapUtil.config.mapGridClass) ){ + if(mapContainer.hasClass(MapUtil.config.mapGridClass)){ params.drag.params.grid = grid; }else{ delete( params.drag.params.grid ); @@ -1827,7 +1847,7 @@ define([ // drag system is not always selected let selectedSystems = mapContainer.getSelectedSystems().get(); - selectedSystems = selectedSystems.concat( dragSystem.get() ); + selectedSystems = selectedSystems.concat(dragSystem.get()); selectedSystems = $.unique( selectedSystems ); // hide tooltip @@ -1861,7 +1881,7 @@ define([ dragSystem.toggleSystemTooltip('show', {show: true}); // mark as "changed" - dragSystem.markAsChanged(); + MapUtil.markAsChanged(dragSystem); // set new position for popover edit field (system name) let newPosition = dragSystem.position(); @@ -1877,14 +1897,11 @@ define([ // drag system is not always selected let selectedSystems = mapContainer.getSelectedSystems().get(); - selectedSystems = selectedSystems.concat( dragSystem.get() ); + selectedSystems = selectedSystems.concat(dragSystem.get()); selectedSystems = $.unique( selectedSystems ); - for(let i = 0; i < selectedSystems.length; i++){ - let tempSystem = $(selectedSystems[i]); - // repaint connections -> just in case something fails... - map.revalidate( tempSystem.attr('id') ); - } + // repaint connections (and overlays) -> just in case something fails... + revalidate(map, selectedSystems); } }); @@ -1922,11 +1939,11 @@ define([ } // continue if click was *not* on a popover dialog of a system - if( !popoverClick ){ + if(!popoverClick){ let system = $(this); // check if system is locked for "click" events - if( !system.hasClass('no-click') ){ + if(!system.hasClass('no-click')){ // left mouse button if(e.which === 1){ if(e.ctrlKey === true){ @@ -1958,42 +1975,6 @@ define([ MagnetizerWrapper.setElements(map); }; - /** - * mark a dom element (map, system, connection) as changed - */ - $.fn.markAsChanged = function(){ - return this.each(function(){ - let element = $(this); - - if( element.hasClass(config.systemClass) ){ - // system element - element.data('changed', true); - }else{ - // connection element - this.setParameter('changed', true); - } - }); - }; - - /** - * check if an dom element (system, connection) has changed - * @returns {boolean} - */ - $.fn.hasChanged = function(){ - let element = $(this); - let changed = false; - - if( element.hasClass(config.systemClass) ){ - // system element - changed = element.data('changed') || false; - }else{ - // connection element - changed = this[0].getParameter('changed') || false; - } - - return changed; - }; - /** * select all (selectable) systems on a mapElement */ @@ -2025,9 +2006,7 @@ define([ * @param options */ $.fn.toggleLockSystem = function(poke, options){ - let system = $(this); - let map = options.map; let hideNotification = false; @@ -2065,13 +2044,11 @@ define([ } // repaint connections - map.revalidate( system.attr('id') ); + revalidate(map, system); - - if(! hideCounter){ + if(!hideCounter){ $(system).getMapOverlay('timer').startMapUpdateCounter(); } - }; /** @@ -2081,7 +2058,7 @@ define([ */ let getMapInstance = function(mapId){ - if( !MapUtil.existsMapInstance(mapId) ){ + if(!MapUtil.existsMapInstance(mapId)){ // create new instance jsPlumb.Defaults.LogEnabled = true; @@ -2150,7 +2127,7 @@ define([ // set "default" connection status only for NEW connections if(!connection.suspendedElement){ - MapUtil.setConnectionWHStatus(connection, MapUtil.getDefaultConnectionTypeByScope(connection.scope) ); + MapUtil.setConnectionWHStatus(connection, MapUtil.getDefaultConnectionTypeByScope(connection.scope)); } // prevent multiple connections between same systems @@ -2178,7 +2155,7 @@ define([ // This is called when the user has detached a Connection, which can happen for a number of reasons: // by default, jsPlumb allows users to drag Connections off of target Endpoints, but this can also result from a programmatic 'detach' call. - newJsPlumbInstance.bind('beforeDetach', function(info){ + newJsPlumbInstance.bind('beforeDetach', function(connection){ return true; }); @@ -2501,7 +2478,7 @@ define([ // get map menu config options let data = MapUtil.mapOptions[mapOption.option]; - let promiseStore = MapUtil.getLocaleData('map', mapElement.data('id') ); + let promiseStore = MapUtil.getLocaleData('map', mapElement.data('id')); promiseStore.then(function(dataStore){ let notificationText = 'disabled'; let button = $('#' + this.data.buttonId); @@ -2677,7 +2654,7 @@ define([ // get current system alias let systemHeadNameElement = $(this).find('.' + config.systemHeadNameClass); let alias = ''; - if( systemHeadNameElement.hasClass('editable') ){ + if(systemHeadNameElement.hasClass('editable')){ // xEditable is initiated alias = systemHeadNameElement.editable('getValue', true); } @@ -2820,150 +2797,147 @@ define([ return new Promise(updateUserDataExecutor); }; + /** + * collect all map data from client for server or client sync + * @param mapContainer + * @param filter + * @param minimal + * @returns {boolean} + */ + let getMapDataForSync = (mapContainer, filter = [], minimal = false) => { + let mapData = false; + // check if there is an active map counter that prevents collecting map data (locked map) + if(!mapContainer.getMapOverlayInterval()){ + mapData = mapContainer.getMapDataFromClient(filter, minimal); + } + return mapData; + }; + /** * collect all map data for export/save for a map * this function returns the "client" data NOT the "server" data for a map - * @param options - * @returns {*} + * @param filter + * @param minimal */ - $.fn.getMapDataFromClient = function(options){ - let mapElement = $(this); - let map = getMapInstance( mapElement.data('id') ); + $.fn.getMapDataFromClient = function(filter = [], minimal = false){ + let mapContainer = $(this); + let map = getMapInstance(mapContainer.data('id')); + + let filterHasId = filter.includes('hasId'); + let filterHasChanged = filter.includes('hasChanged'); + let mapData = {}; - // check if there is an active map counter that prevents collecting map data (locked map) - let interval = mapElement.getMapOverlayInterval(); + // map config ------------------------------------------------------------------------------------------------- + mapData.config = { + id: parseInt(mapContainer.data('id')), + name: mapContainer.data('name'), + scope: { + id: parseInt(mapContainer.data('scopeId')) + }, + icon: mapContainer.data('icon'), + type: { + id: parseInt(mapContainer.data('typeId')) + }, + created: parseInt(mapContainer.data('created')), + updated: parseInt(mapContainer.data('updated')) + }; - if( - !interval || - options.forceData === true - ){ + let data = {}; - // map config --------------------------------------------------------------------------------------------- - mapData.config = { - id: parseInt( mapElement.data('id') ), - name: mapElement.data('name'), - scope: { - id: parseInt( mapElement.data('scopeId') ) - }, - icon: mapElement.data('icon'), - type: { - id: parseInt( mapElement.data('typeId') ) - }, - created: parseInt( mapElement.data('created') ), - updated: parseInt( mapElement.data('updated') ), - }; + // systems data ----------------------------------------------------------------------------------------------- + let systemsData = []; + let systems = mapContainer.getSystems(); - // map data ----------------------------------------------------------------------------------------------- - let data = {}; + for(let i = 0; i < systems.length; i++){ + let system = $(systems[i]); - // systems data ------------------------------------------------------------------------------------------- - let systemsData = []; - let systems = mapElement.getSystems(); - - for(let i = 0; i < systems.length; i++){ - let tempSystem = $(systems[i]); - - // check if system data should be added - let addSystemData = true; - if( - options.getAll !== true && - options.checkForChange === true && - !tempSystem.hasChanged() - ){ - addSystemData = false; - } - - if(addSystemData){ - systemsData.push( tempSystem.getSystemData() ); - } + if(filterHasChanged && !MapUtil.hasChanged(system)){ + continue; } - data.systems = systemsData; - - // connections -------------------------------------------------------------------------------------------- - let connections = map.getAllConnections(); - let connectionsFormatted = []; - - // format connections - for(let j = 0; j < connections.length; j++){ - let tempConnection = connections[j]; - let connectionData = MapUtil.getDataByConnection(tempConnection); - - // only add valid connections (id is required, this is not the case if connection is new) - if(connectionData.id > 0){ - // check if connection data should be added - let addConnectionData = true; - if( - options.getAll !== true && - options.checkForChange === true && - !$(tempConnection).hasChanged() - ){ - addConnectionData = false; - } - - - if(addConnectionData){ - connectionsFormatted.push( connectionData ); - } - - // add to cache - updateConnectionCache(mapData.config.id, tempConnection); - } - } - - data.connections = connectionsFormatted; - - mapData.data = data; - }else{ - return false; + systemsData.push(system.getSystemData(minimal)); } + data.systems = systemsData; + + // connections ------------------------------------------------------------------------------------------------ + let connectionsData = []; + let connections = map.getAllConnections(); + + for(let j = 0; j < connections.length; j++) { + let connection = connections[j]; + + // add to cache + updateConnectionCache(mapData.config.id, connection); + + if(filterHasChanged && !MapUtil.hasChanged(connection)){ + continue; + } + + if(filterHasId && !connection.getParameter('connectionId')){ + continue; + } + + connectionsData.push(MapUtil.getDataByConnection(connection, minimal)); + } + + data.connections = connectionsData; + + mapData.data = data; + return mapData; }; /** * get all relevant data for a system object - * @returns {{}} + * @param minimal + * @returns {{id: number, updated: {updated: number}}} */ - $.fn.getSystemData = function(){ + $.fn.getSystemData = function(minimal = false){ let system = $(this); - let systemData = {}; - systemData.id = parseInt( system.data('id') ); - systemData.systemId = parseInt( system.data('systemId') ); - systemData.name = system.data('name'); - systemData.alias = system.getSystemInfo(['alias']); - systemData.effect = system.data('effect'); - systemData.type = { - id: system.data('typeId') + let systemData = { + id: parseInt(system.data('id')), + updated: { + updated: parseInt(system.data('updated')) + } }; - systemData.security = system.data('security'); - systemData.trueSec = system.data('trueSec'); - systemData.region = { - id: system.data('regionId'), - name: system.data('region') - }; - systemData.constellation = { - id: system.data('constellationId'), - name: system.data('constellation') - }; - systemData.status = { - id: system.data('statusId') - }; - systemData.locked = system.data('locked') ? 1 : 0; - systemData.rallyUpdated = system.data('rallyUpdated') || 0; - systemData.rallyPoke = system.data('rallyPoke') ? 1 : 0; - systemData.currentUser = system.data('currentUser'); // if user is currently in this system - systemData.faction = system.data('faction'); - systemData.planets = system.data('planets'); - systemData.shattered = system.data('shattered') ? 1 : 0; - systemData.statics = system.data('statics'); - systemData.updated = { - updated: parseInt( system.data('updated') ) - }; - systemData.userCount = (system.data('userCount') ? parseInt( system.data('userCount') ) : 0); - systemData.position = MapUtil.getSystemPosition(system); + + if(!minimal){ + systemData = Object.assign(systemData, { + systemId: parseInt(system.data('systemId')), + name: system.data('name'), + alias: system.getSystemInfo(['alias']), + effect: system.data('effect'), + type: { + id: system.data('typeId') + }, + security: system.data('security'), + trueSec: system.data('trueSec'), + region: { + id: system.data('regionId'), + name: system.data('region') + }, + constellation: { + id: system.data('constellationId'), + name: system.data('constellation') + }, + status: { + id: system.data('statusId') + }, + locked: system.data('locked') ? 1 : 0, + rallyUpdated: system.data('rallyUpdated') || 0, + rallyPoke: system.data('rallyPoke') ? 1 : 0, + currentUser: system.data('currentUser'), // if user is currently in this system + faction: system.data('faction'), + planets: system.data('planets'), + shattered: system.data('shattered') ? 1 : 0, + statics: system.data('statics'), + userCount: (system.data('userCount') ? parseInt(system.data('userCount')) : 0), + position: MapUtil.getSystemPosition(system) + }); + } return systemData; }; @@ -3085,6 +3059,7 @@ define([ getMapInstance: getMapInstance, loadMap: loadMap, updateUserData: updateUserData, + getMapDataForSync: getMapDataForSync, saveSystemCallback: saveSystemCallback }; diff --git a/js/app/map/overlay.js b/js/app/map/overlay.js index 0766cc8a..d7318c9d 100644 --- a/js/app/map/overlay.js +++ b/js/app/map/overlay.js @@ -74,13 +74,18 @@ define([ * @param label */ let addEndpointOverlay = (endpoint, label) => { + label = label.join(', '); + endpoint.addOverlay([ 'Label', { label: MapUtil.getEndpointOverlayContent(label), id: config.endpointOverlayId, cssClass: [config.componentOverlayClass, label.length ? 'small' : 'icon'].join(' '), - location: [ 0.9, 0.9 ] + location: MapUtil.getLabelEndpointOverlayLocation(endpoint, label), + parameters: { + label: label + } } ]); }; diff --git a/js/app/map/system.js b/js/app/map/system.js index c902327f..b6187040 100644 --- a/js/app/map/system.js +++ b/js/app/map/system.js @@ -145,7 +145,7 @@ define([ let statusData = [{id: 0, text: 'auto'}]; // get current map data --------------------------------------------------------------------------------------- - let mapData = mapContainer.getMapDataFromClient({forceData: true}); + let mapData = mapContainer.getMapDataFromClient(['hasId']); let mapSystems = mapData.data.systems; let mapSystemCount = mapSystems.length; let mapTypeName = mapContainer.data('typeName'); diff --git a/js/app/map/util.js b/js/app/map/util.js index 1893afd9..d6894311 100644 --- a/js/app/map/util.js +++ b/js/app/map/util.js @@ -5,9 +5,8 @@ define([ 'jquery', 'app/init', - 'app/util', - 'bootbox' -], ($, Init, Util, bootbox) => { + 'app/util' +], ($, Init, Util) => { 'use strict'; let config = { @@ -262,6 +261,33 @@ define([ return effectInfo; }; + /** + * flag map component (map, system, connection) as "changed" + * @param component + */ + let markAsChanged = component => { + if(component instanceof $ && component.hasClass(config.systemClass)){ + component.data('changed', true); + }else if(component instanceof jsPlumb.Connection){ + component.setParameter('changed', true); + } + }; + + /** + * check if map component (system, connection) is flagged as "changed" + * @param component + * @returns {boolean} + */ + let hasChanged = component => { + let changed = false; + if(component instanceof $ && component.hasClass(config.systemClass)){ + changed = component.data('changed') || false; + }else if(component instanceof jsPlumb.Connection){ + changed = component.getParameter('changed') || false; + } + return changed; + }; + /** * get system elements on a map * @returns {*|jQuery} @@ -317,55 +343,71 @@ define([ * filter connections by type * @param map * @param type + * @param exclude * @returns {Array} */ - let getConnectionsByType = (map, type) => { + let getConnectionsByType = (map, type, exclude = false) => { let connections = []; - // iterate through ALL connections and filter... - // -> there is no "filterByScope()" method in jsPlumb - for(let connection of map.getAllConnections()){ - if(connection.getType().indexOf(type) !== -1){ - connections.push(connection); + for(let data of map.select().hasType(type)){ + if(data[0] !== exclude){ + connections.push(data[1]); } } return connections; }; /** - * get all relevant data for a connection object + * get endpoints data from connection * @param connection - * @returns {{targetName: *, endpoints, scope: *, targetAlias: *, id: number, source: number, sourceName: *, type, updated: number, sourceAlias: *, target: number}} + * @returns {{source: {}, target: {}}} */ - let getDataByConnection = connection => { - let source = $(connection.source); - let target = $(connection.target); - - let id = connection.getParameter('connectionId'); - let updated = connection.getParameter('updated'); - - let endpoints = {source: {}, target: {}}; + let getEndpointsDataByConnection = connection => { + let endpointsData = {source: {}, target: {}}; for(let endpoint of connection.endpoints){ let endpointData = getDataByEndpoint(connection, endpoint); if(endpointData.label === 'source'){ - endpoints.source = endpointData; + endpointsData.source = endpointData; }else if(endpointData.label === 'target'){ - endpoints.target = endpointData; + endpointsData.target = endpointData; } } + return endpointsData; + }; - return { - id: id ? id : 0, + /** + * get connection data from connection + * @param connection + * @param minimal + * @returns {{id: (*|number), updated: (*|number)}} + */ + let getDataByConnection = (connection, minimal = false) => { + let source = $(connection.source); + let target = $(connection.target); + + let connectionData = { + id: connection.getParameter('connectionId') || 0, + updated: connection.getParameter('updated') || 0, source: parseInt(source.data('id')), - sourceName: source.data('name'), - sourceAlias: source.getSystemInfo(['alias']) || source.data('name'), - target: parseInt(target.data('id')), - targetName: target.data('name'), - targetAlias: target.getSystemInfo(['alias']) || target.data('name'), - scope: connection.scope, - type: filterDefaultTypes(connection.getType()), - endpoints: endpoints, - updated: updated ? updated : 0 + target: parseInt(target.data('id')) }; + + if(minimal){ + connectionData = Object.assign(connectionData, { + connection: connection + }); + }else{ + connectionData = Object.assign(connectionData, { + sourceName: source.data('name'), + sourceAlias: source.getSystemInfo(['alias']) || source.data('name'), + targetName: target.data('name'), + targetAlias: target.getSystemInfo(['alias']) || target.data('name'), + scope: connection.scope, + type: filterDefaultTypes(connection.getType()), + endpoints: getEndpointsDataByConnection(connection) + }); + } + + return connectionData; }; /** @@ -516,30 +558,53 @@ define([ return signatureTypeNames; }; + /** + * get Location [x,y] for Endpoint Overlays (e.g. wh type from Signature mapping) + * -> Coordinates are relative to the Endpoint (not the system!) + * -> jsPlumb specific format + * @param endpoint + * @param label + * @returns {number[]} + */ + let getLabelEndpointOverlayLocation = (endpoint, label) => { + let chars = label.length ? label.length : 2; + let xTop = chars === 2 ? +0.05 : chars <= 4 ? -0.75 : 3; + let xLeft = chars === 2 ? -1.10 : chars <= 4 ? -2.75 : 3; + let xRight = chars === 2 ? +1.25 : chars <= 4 ? +1.25 : 3; + let xBottom = chars === 2 ? +0.05 : chars <= 4 ? -0.75 : 3; + + let yTop = chars === 2 ? -1.10 : chars <= 4 ? -1.75 : 3; + + switch(endpoint._continuousAnchorEdge){ + case 'top': return [xTop, yTop]; + case 'left': return [xLeft, 0]; + case 'right': return [xRight, 0]; + case 'bottom': return [xBottom , 1.3]; + default: return [0.0, 0.0]; + } + }; + /** * get overlay HTML for connection endpoints by Label array * @param label * @returns {string} */ let getEndpointOverlayContent = label => { - let newLabel = ''; let colorClass = 'txt-color-grayLighter'; if(label.length > 0){ - newLabel = label.join(', '); - // check if multiple labels found => conflict - if( newLabel.includes(', ') ){ + if( label.includes(', ') ){ colorClass = 'txt-color-orangeLight'; - }else if( !newLabel.includes('K162') ){ + }else if( !label.includes('K162') ){ colorClass = 'txt-color-yellow'; } }else{ // endpoint not connected with a signature - newLabel = ''; + label = ''; colorClass = 'txt-color-red'; } - return '' + newLabel + ''; + return '' + label + ''; }; /** @@ -1737,6 +1802,8 @@ define([ getSystemData: getSystemData, getSystemTypeInfo: getSystemTypeInfo, getEffectInfoForSystem: getEffectInfoForSystem, + markAsChanged: markAsChanged, + hasChanged: hasChanged, toggleSystemsSelect: toggleSystemsSelect, toggleConnectionActive: toggleConnectionActive, setSystemActive: setSystemActive, @@ -1745,6 +1812,7 @@ define([ showFindRouteDialog: showFindRouteDialog, getEndpointLabel: getEndpointLabel, getConnectionsByType: getConnectionsByType, + getEndpointsDataByConnection: getEndpointsDataByConnection, getDataByConnection: getDataByConnection, searchConnectionsBySystems: searchConnectionsBySystems, searchConnectionsByScopeAndType: searchConnectionsByScopeAndType, @@ -1757,6 +1825,7 @@ define([ getDataByConnections: getDataByConnections, deleteConnections: deleteConnections, getConnectionDataFromSignatures: getConnectionDataFromSignatures, + getLabelEndpointOverlayLocation: getLabelEndpointOverlayLocation, getEndpointOverlayContent: getEndpointOverlayContent, getTabContentElementByMapElement: getTabContentElementByMapElement, hasActiveConnection: hasActiveConnection, diff --git a/js/app/module_map.js b/js/app/module_map.js index d08de79a..df3d1e3c 100644 --- a/js/app/module_map.js +++ b/js/app/module_map.js @@ -1350,7 +1350,7 @@ define([ let data = []; for(let i = 0; i < mapElements.length; i++){ // get all changed (system / connection) data from this map - let mapData = $(mapElements[i]).getMapDataFromClient({forceData: false, checkForChange: true}); + let mapData = Map.getMapDataForSync($(mapElements[i]), ['hasId', 'hasChanged']); if(mapData !== false){ if( mapData.data.systems.length > 0 || diff --git a/js/app/page.js b/js/app/page.js index 8e302476..bd21cf42 100644 --- a/js/app/page.js +++ b/js/app/page.js @@ -701,7 +701,7 @@ define([ let activeMap = Util.getMapModule().getActiveMap(); if(activeMap){ - mapData = activeMap.getMapDataFromClient({forceData: true}); + mapData = activeMap.getMapDataFromClient(['hasId']); } $.fn.showDeleteMapDialog(mapData); diff --git a/js/app/ui/dialog/map_info.js b/js/app/ui/dialog/map_info.js index 9dd383d6..8e5c717a 100644 --- a/js/app/ui/dialog/map_info.js +++ b/js/app/ui/dialog/map_info.js @@ -322,7 +322,8 @@ define([ },{ name: 'region', title: 'region', - data: 'region.name' + data: 'region.name', + className: 'min-screen-l', },{ name: 'planets', title: '', @@ -442,7 +443,7 @@ define([ title: 'updated', width: 80, searchable: false, - className: ['text-right', config.tableCellCounterClass, 'min-screen-l'].join(' '), + className: ['text-right', config.tableCellCounterClass].join(' '), data: 'updated.updated', defaultContent: '', },{ @@ -480,7 +481,7 @@ define([ // refresh connection table (connections might have changed) -------------- let connectionsElement = $('#' + config.mapInfoConnectionsId); - let mapDataNew = activeMap.getMapDataFromClient({forceData: true}); + let mapDataNew = activeMap.getMapDataFromClient(['hasId']); connectionsElement.initConnectionInfoTable(mapDataNew); }else{ @@ -522,6 +523,10 @@ define([ // table init complete connectionTable.on('init.dt', function(){ connectionsElement.hideLoadingAnimation(); + + // init table tooltips + let tooltipElements = connectionsElement.find('[data-toggle="tooltip"]'); + tooltipElements.tooltip(); }); // connections table ------------------------------------------------------------------------------------------ @@ -530,7 +535,7 @@ define([ paging: true, lengthMenu: [[5, 10, 20, 50, -1], [5, 10, 20, 50, 'All']], ordering: true, - order: [ 0, 'desc' ], + order: [ 6, 'desc' ], autoWidth: false, hover: false, data: mapData.data.connections, @@ -1264,7 +1269,7 @@ define([ */ $.fn.showMapInfoDialog = function(options){ let activeMap = Util.getMapModule().getActiveMap(); - let mapData = activeMap ? activeMap.getMapDataFromClient({forceData: true}) : false; + let mapData = activeMap ? activeMap.getMapDataFromClient(['hasId']) : false; if(mapData !== false){ // "log" tab -> get "Origin", not all config options are set in mapData @@ -1321,7 +1326,7 @@ define([ let menuAction = $(this).attr('data-action'); if(menuAction === 'refresh'){ // get new map data - let mapData = activeMap.getMapDataFromClient({forceData: true}); + let mapData = activeMap.getMapDataFromClient(['hasId']); // find active tab let activeTabLink = $(this).parents('.navbar').find('.navbar-header.pull-left li.active a'); if(activeTabLink.attr('href') === '#' + config.dialogMapInfoLogsId){ diff --git a/js/app/ui/dialog/map_settings.js b/js/app/ui/dialog/map_settings.js index b61e1434..bd02f526 100644 --- a/js/app/ui/dialog/map_settings.js +++ b/js/app/ui/dialog/map_settings.js @@ -496,10 +496,7 @@ define([ // IMPORTANT: Get map data from client (NOT from global mapData which is available in here) // -> This excludes some data (e.g. wh statics) // -> Bring export inline with main map toggle requests - let exportMapData = mapElement.getMapDataFromClient({ - forceData: true, - getAll: true - }); + let exportMapData = mapElement.getMapDataFromClient(['hasId']); let exportButton = $(this); // set map data right before download diff --git a/js/app/ui/module/connection_info.js b/js/app/ui/module/connection_info.js index 32c428a3..bcac90cb 100644 --- a/js/app/ui/module/connection_info.js +++ b/js/app/ui/module/connection_info.js @@ -308,8 +308,8 @@ define([ let sourceLabel = signatureTypeNames.sourceLabels; let targetLabel = signatureTypeNames.targetLabels; - sourceLabelElement.html(MapUtil.getEndpointOverlayContent(sourceLabel)); - targetLabelElement.html(MapUtil.getEndpointOverlayContent(targetLabel)); + sourceLabelElement.html(MapUtil.getEndpointOverlayContent(sourceLabel.join(', '))); + targetLabelElement.html(MapUtil.getEndpointOverlayContent(targetLabel.join(', '))); // remove K162 sourceLabel = sourceLabel.diff(['K162']); @@ -1153,7 +1153,7 @@ define([ */ let getConnectionsDataFromModule = (moduleElement, mapId) => { let activeMap = Util.getMapModule().getActiveMap(); - let mapData = activeMap.getMapDataFromClient({forceData: true}); + let mapData = activeMap.getMapDataFromClient(['hasId']); let connectionsData = { connectionsDataUpdate: [], connectionsDataRemove: [], diff --git a/js/lib/dom.jsPlumb-1.7.6.js b/js/lib/dom.jsPlumb-1.7.6.js index cadf836f..04237fb2 100644 --- a/js/lib/dom.jsPlumb-1.7.6.js +++ b/js/lib/dom.jsPlumb-1.7.6.js @@ -10390,9 +10390,10 @@ // be fixed. IE8 is not going to be supported for much longer. //var ts = "translate(calc(-50% + 3px), calc(-50% + 3px))"; //var ts = "translate3d(-50%, -50, 0)"; - //var ts = "translate3d(0, 0, 0)"; - var ts = "translate3d(50%, 50, 0)"; + var ts = "translate3d(0, 0, 0)"; + //var ts = "translate3d(50%, -50, 0)"; //var ts = "translate3d(-8px, 5px, 0)"; + //var ts = "translate(-50%, -50%)"; div.style.webkitTransform = ts; div.style.mozTransform = ts; div.style.msTransform = ts; diff --git a/public/js/v1.5.1/app/map/magnetizing.js b/public/js/v1.5.1/app/map/magnetizing.js index 40954184..f63f8ed2 100644 --- a/public/js/v1.5.1/app/map/magnetizing.js +++ b/public/js/v1.5.1/app/map/magnetizing.js @@ -74,7 +74,7 @@ define([ } if(markAsUpdated === true){ - $(system).markAsChanged(); + MapUtil.markAsChanged($(system)); } }; diff --git a/public/js/v1.5.1/app/map/map.js b/public/js/v1.5.1/app/map/map.js index a4b2c639..a79bf830 100644 --- a/public/js/v1.5.1/app/map/map.js +++ b/public/js/v1.5.1/app/map/map.js @@ -112,6 +112,34 @@ define([ connectionTypes: Init.connectionTypes }; + /** + * revalidate (repaint) all connections of el + * -> in addition this re-calculates the Location of potential Endpoint Overlays + * @param map + * @param element (can also be an array) + */ + let revalidate = (map, element) => { + map.revalidate(element); + + // get attached connections + let elements = (typeof element === 'object' && element.length) ? element : [element]; + for(let element of elements){ + let connectionsInfo = map.anchorManager.getConnectionsFor(element.id); + for(let connectionInfo of connectionsInfo){ + // index 0 -> Connection, 1 -> Endpoint + // -> we need BOTH endpoints of a connection -> index 0 + for(let endpoint of connectionInfo[0].endpoints){ + // check if there is a Label overlay + let overlay = endpoint.getOverlay('pf-map-endpoint-overlay'); + if(overlay instanceof jsPlumb.Overlays.Label){ + let label = overlay.getParameter('label'); + overlay.setLocation(MapUtil.getLabelEndpointOverlayLocation(endpoint, label)); + } + } + } + } + }; + /** * updates a system with current information * @param map @@ -282,7 +310,7 @@ define([ duration: 50, display: 'auto', progress: function(){ - //revalidate element size and repaint + //re-validate element size and repaint map.revalidate( systemDomId ); }, complete: function(){ @@ -371,7 +399,6 @@ define([ // get system info classes let effectBasicClass = MapUtil.getEffectInfoForSystem('effect', 'class'); - let effectName = MapUtil.getEffectInfoForSystem(data.effect, 'name'); let effectClass = MapUtil.getEffectInfoForSystem(data.effect, 'class'); let secClass = Util.getSecurityClassForSystem(data.security); @@ -449,14 +476,14 @@ define([ // move them to the "top" $(system).updateSystemZIndex(); }, - progress: function(){ - map.revalidate( systemId ); + progress: function(system){ + revalidate(map, system); }, complete: function(system){ // show tooltip $(system).toggleSystemTooltip('show', {show: true}); - map.revalidate( systemId ); + revalidate(map, system); } } ); @@ -494,7 +521,7 @@ define([ system.attr('data-mapid', parseInt(mapContainer.data('id'))); // locked system - if( Boolean( system.data('locked') ) !== data.locked ){ + if( Boolean(system.data('locked')) !== data.locked ){ system.toggleLockSystem(false, {hideNotification: true, hideCounter: true, map: map}); } @@ -530,16 +557,16 @@ define([ // repaint connections, -> system changed its size! map.repaint(system); - system.markAsChanged(); + MapUtil.markAsChanged(system); break; case 'set_rally': // toggle rally point - if( !system.data('rallyUpdated') ){ + if(!system.data('rallyUpdated')){ $.fn.showRallyPointDialog(system); }else{ // remove rally point system.setSystemRally(0); - system.markAsChanged(); + MapUtil.markAsChanged(system); } break; case 'find_route': @@ -567,7 +594,7 @@ define([ system.setSystemStatus(statusString[2]); - system.markAsChanged(); + MapUtil.markAsChanged(system); break; case 'delete_system': // delete this system AND delete selected systems as well @@ -705,7 +732,7 @@ define([ case 'wh_eol': // set "end of life" mapElement.getMapOverlay('timer').startMapUpdateCounter(); connection.toggleType(action); - $(connection).markAsChanged(); + MapUtil.markAsChanged(connection); break; case 'status_fresh': case 'status_reduced': @@ -714,7 +741,7 @@ define([ mapElement.getMapOverlay('timer').startMapUpdateCounter(); MapUtil.setConnectionWHStatus(connection, 'wh_' + newStatus); - $(connection).markAsChanged(); + MapUtil.markAsChanged(connection); break; case 'scope_wh': case 'scope_stargate': @@ -730,7 +757,7 @@ define([ Util.showNotify({title: 'Connection scope changed', text: 'New scope: ' + newScopeName, type: 'success'}); - $(connection).markAsChanged(); + MapUtil.markAsChanged(connection); } }); break; @@ -752,7 +779,7 @@ define([ endpoint.toggleType(action); for(let connection of endpoint.connections){ - $(connection).markAsChanged(); + MapUtil.markAsChanged(connection); } break; } @@ -802,7 +829,7 @@ define([ // set new new connection type // if scope changed -> connection type == scope - connection.setType( MapUtil.getDefaultConnectionTypeByScope(scope) ); + connection.setType(MapUtil.getDefaultConnectionTypeByScope(scope)); // change scope connection.scope = scope; @@ -816,12 +843,12 @@ define([ * @returns new connection */ let drawConnection = (map, connectionData) => { - let mapContainer = $( map.getContainer() ); + let mapContainer = $(map.getContainer()); let mapId = mapContainer.data('id'); let connectionId = connectionData.id || 0; let connection; - let sourceSystem = $('#' + MapUtil.getSystemId(mapId, connectionData.source) ); - let targetSystem = $('#' + MapUtil.getSystemId(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",...) @@ -833,7 +860,7 @@ define([ source: sourceSystem[0], target: targetSystem[0], scope: connectionData.scope || map.Defaults.Scope, - type: (connectionData.type || MapUtil.getDefaultConnectionTypeByScope(map.Defaults.Scope)).join(' '), + type: (connectionData.type || MapUtil.getDefaultConnectionTypeByScope(map.Defaults.Scope)).join(' ') /* experimental set "static" connection parameters in initial load parameters: { connectionId: connectionId, @@ -906,15 +933,21 @@ define([ let updateConnection = (connection, newConnectionData) => { let connectionData = MapUtil.getDataByConnection(connection); let map = connection._jsPlumb.instance; - let mapContainer = $( map.getContainer() ); + let mapContainer = $(map.getContainer()); let mapId = mapContainer.data('id'); - // check id, IDs should never change but must be set after initial save + // type "process" is not included in connectionData + // -> if "process" type exists, add it types for removal + if(connection.hasType('state_process')){ + connectionData.type.push('state_process'); + } + + // check id, IDs should never change but must be set after initial save --------------------------------------- if(connection.getParameter('connectionId') !== newConnectionData.id){ connection.setParameter('connectionId', newConnectionData.id); } - // check scope + // update scope ----------------------------------------------------------------------------------------------- if(connectionData.scope !== newConnectionData.scope){ setConnectionScope(connection, newConnectionData.scope); } @@ -922,17 +955,17 @@ define([ let addType = newConnectionData.type.diff(connectionData.type); let removeType = connectionData.type.diff(newConnectionData.type); - // check if source or target has changed - if(connectionData.source !== newConnectionData.source ){ - map.setSource(connection, MapUtil.getSystemId(mapId, newConnectionData.source) ); + // update source/target (after drag&drop) --------------------------------------------------------------------- + if(connectionData.source !== newConnectionData.source){ + map.setSource(connection, MapUtil.getSystemId(mapId, newConnectionData.source)); } - if(connectionData.target !== newConnectionData.target ){ - map.setTarget(connection, MapUtil.getSystemId(mapId, newConnectionData.target) ); + if(connectionData.target !== newConnectionData.target){ + map.setTarget(connection, MapUtil.getSystemId(mapId, newConnectionData.target)); } + // update connection types ------------------------------------------------------------------------------------ let checkAvailability = (arr, val) => arr.some(arrVal => arrVal === val); - // add types for(let type of addType){ if(checkAvailability(['fresh', 'reduced', 'critical'], type)){ MapUtil.setConnectionWHStatus(connection, type); @@ -942,17 +975,21 @@ define([ } } - // remove types for(let type of removeType){ - if(checkAvailability(['wh_eol', 'frigate', 'preserve_mass'], type)){ + if(checkAvailability(['wh_eol', 'frigate', 'preserve_mass', 'state_process'], type)){ connection.removeType(type); } } - // update endpoints + // update endpoints ------------------------------------------------------------------------------------------- + // important: In case source or target changed (drag&drop) (see above lines..) + // -> NEW endpoints are created (default Endpoint properties from makeSource()/makeTarget() call are used + // -> connectionData.endpoints might no longer be valid -> get fresh endpointData + let endpointData = MapUtil.getEndpointsDataByConnection(connection); + for(let endpoint of connection.endpoints){ let label = MapUtil.getEndpointLabel(connection, endpoint); - let endpointTypes = Util.getObjVal(connectionData, ['endpoints', label, 'types'].join('.')) || []; + let endpointTypes = Util.getObjVal(endpointData, [label, 'types'].join('.')) || []; let newEndpointTypes = Util.getObjVal(newConnectionData, ['endpoints', label, 'types'].join('.')) || []; let addEndpointTypes = newEndpointTypes.diff(endpointTypes); @@ -1156,7 +1193,8 @@ define([ } // get map data - let mapData = mapContainer.getMapDataFromClient({forceData: false}); + let mapData = getMapDataForSync(mapContainer, [], true); + if(mapData !== false){ // map data available -> map not locked by update counter :) @@ -1172,7 +1210,7 @@ define([ for(let k = 0; k < currentSystemData.length; k++){ if(currentSystemData[k].id === systemData.id){ - if( currentSystemData[k].updated.updated < systemData.updated.updated ){ + if(currentSystemData[k].updated.updated < systemData.updated.updated){ // system changed -> update mapContainer.getSystem(mapConfig.map, systemData); } @@ -1190,7 +1228,6 @@ define([ // check for systems that are gone -> delete system for(let a = 0; a < currentSystemData.length; a++){ - let deleteThisSystem = true; for(let b = 0; b < mapConfig.data.systems.length; b++){ @@ -1203,7 +1240,7 @@ define([ } if(deleteThisSystem === true){ - let deleteSystem = $('#' + MapUtil.getSystemId(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); @@ -1223,18 +1260,23 @@ define([ let addNewConnection= true; for(let c = 0; c < currentConnectionData.length; c++){ - if( - currentConnectionData[c].id === connectionData.id - ){ + if(currentConnectionData[c].id === connectionData.id){ // connection already exists -> check for updates - if( - currentConnectionData[c].updated < connectionData.updated - ){ + if(currentConnectionData[c].updated < connectionData.updated){ // connection changed -> update - let tempConnection = $().getConnectionById(mapData.config.id, connectionData.id); - updateConnection(tempConnection, connectionData); + updateConnection(currentConnectionData[c].connection, connectionData); } + addNewConnection = false; + break; + }else if( + currentConnectionData[c].id === 0 && + currentConnectionData[c].source === connectionData.source && + currentConnectionData[c].target === connectionData.target + ){ + // if ids don´t match -> check for unsaved connection + updateConnection(currentConnectionData[c].connection, connectionData); + addNewConnection = false; break; } @@ -1247,6 +1289,10 @@ define([ // check for connections that are gone -> delete connection for(let d = 0; d < currentConnectionData.length; d++){ + // skip connections with id = 0 -> they might get updated before + if(currentConnectionData[d].id === 0){ + continue; + } let deleteThisConnection = true; @@ -1260,8 +1306,8 @@ define([ } if(deleteThisConnection === true){ - // get connection from cache -> delete connection - let deleteConnection = $().getConnectionById(mapData.config.id, currentConnectionData[d].id); + // connection not found -> delete connection + let deleteConnection = currentConnectionData[d].connection; if(deleteConnection){ // check if "source" and "target" still exist before remove @@ -1326,13 +1372,12 @@ define([ */ let updateConnectionsCache = map => { let connections = map.getAllConnections(); - let mapContainer = $( map.getContainer() ); + let mapContainer = $(map.getContainer()); let mapId = mapContainer.data('id'); if(mapId > 0){ // clear cache connectionCache[mapId] = []; - for(let i = 0; i < connections.length; i++){ updateConnectionCache(mapId, connections[i]); } @@ -1351,8 +1396,7 @@ define([ mapId > 0 && connection ){ - let connectionId = parseInt( connection.getParameter('connectionId') ); - + let connectionId = parseInt(connection.getParameter('connectionId')); if(connectionId > 0){ connectionCache[mapId][connectionId] = connection; } @@ -1387,7 +1431,7 @@ define([ * @param system */ let makeSource = (map, system) => { - if( !map.isSource(system) ){ + if(!map.isSource(system)){ // get scope from map defaults let sourceConfig = globalMapConfig.source; sourceConfig.scope = map.Defaults.Scope; // set all allowed connections for this scopes @@ -1405,7 +1449,7 @@ define([ * @param system */ let makeTarget = (map, system) => { - if( !map.isTarget(system) ){ + if(!map.isTarget(system)){ // get scope from map defaults let targetConfig = globalMapConfig.target; targetConfig.scope = map.Defaults.Scope; // set all allowed connections for this scopes @@ -1503,7 +1547,7 @@ define([ headElement.on('save', function(e, params){ // system alias changed -> mark system as updated - system.markAsChanged(); + MapUtil.markAsChanged(system); }); headElement.on('shown', function(e, editable){ @@ -1525,7 +1569,7 @@ define([ // if system with changed (e.g. long alias) -> revalidate system let map = MapUtil.getMapInstance(system.attr('data-mapid')); - map.revalidate(system.attr('id')); + revalidate(map, system); }); }; @@ -1564,36 +1608,12 @@ define([ payload => { let newConnectionData = payload.data; - if( !$.isEmptyObject(newConnectionData) ){ - payload.context.connection.removeType('state_process'); + if(!$.isEmptyObject(newConnectionData)){ + // update connection data e.g. "scope" has auto detected + connection = updateConnection(payload.context.connection, newConnectionData); - let updateCon = false; - - if(payload.context.oldConnectionData.id > 0){ - // connection exists (e.g. drag&drop new target system... (ids should never changed) - let connection = $().getConnectionById(payload.context.mapId, payload.context.oldConnectionData.id); - updateCon = true; - }else{ - // new connection, check if connectionId was already updated (webSocket push is faster than ajax callback) - let connection = $().getConnectionById(payload.context.mapId, newConnectionData.id); - - if(connection){ - // connection already updated - payload.context.map.detach(payload.context.connection, {fireEvent: false}); - }else{ - // .. else update this connection - connection = payload.context.connection; - updateCon = true; - } - } - - if(updateCon){ - // update connection data e.g. "scope" has auto detected - connection = updateConnection(connection, newConnectionData); - - // new/updated connection should be cached immediately! - updateConnectionCache(payload.context.mapId, connection); - } + // new/updated connection should be cached immediately! + updateConnectionCache(payload.context.mapId, connection); // connection scope let scope = MapUtil.getScopeInfoForConnection(newConnectionData.scope, 'label'); @@ -1795,7 +1815,7 @@ define([ system = $(system); // get map container - let mapContainer = $( map.getContainer() ); + let mapContainer = $(map.getContainer()); let grid = [MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension]; // map overlay will be set on "drag" start let mapOverlayTimer = null; @@ -1816,7 +1836,7 @@ define([ mapOverlayTimer.startMapUpdateCounter(); // check if grid-snap is enable -> this enables napping for !CURRENT! Element - if( mapContainer.hasClass(MapUtil.config.mapGridClass) ){ + if(mapContainer.hasClass(MapUtil.config.mapGridClass)){ params.drag.params.grid = grid; }else{ delete( params.drag.params.grid ); @@ -1827,7 +1847,7 @@ define([ // drag system is not always selected let selectedSystems = mapContainer.getSelectedSystems().get(); - selectedSystems = selectedSystems.concat( dragSystem.get() ); + selectedSystems = selectedSystems.concat(dragSystem.get()); selectedSystems = $.unique( selectedSystems ); // hide tooltip @@ -1861,7 +1881,7 @@ define([ dragSystem.toggleSystemTooltip('show', {show: true}); // mark as "changed" - dragSystem.markAsChanged(); + MapUtil.markAsChanged(dragSystem); // set new position for popover edit field (system name) let newPosition = dragSystem.position(); @@ -1877,14 +1897,11 @@ define([ // drag system is not always selected let selectedSystems = mapContainer.getSelectedSystems().get(); - selectedSystems = selectedSystems.concat( dragSystem.get() ); + selectedSystems = selectedSystems.concat(dragSystem.get()); selectedSystems = $.unique( selectedSystems ); - for(let i = 0; i < selectedSystems.length; i++){ - let tempSystem = $(selectedSystems[i]); - // repaint connections -> just in case something fails... - map.revalidate( tempSystem.attr('id') ); - } + // repaint connections (and overlays) -> just in case something fails... + revalidate(map, selectedSystems); } }); @@ -1922,11 +1939,11 @@ define([ } // continue if click was *not* on a popover dialog of a system - if( !popoverClick ){ + if(!popoverClick){ let system = $(this); // check if system is locked for "click" events - if( !system.hasClass('no-click') ){ + if(!system.hasClass('no-click')){ // left mouse button if(e.which === 1){ if(e.ctrlKey === true){ @@ -1958,42 +1975,6 @@ define([ MagnetizerWrapper.setElements(map); }; - /** - * mark a dom element (map, system, connection) as changed - */ - $.fn.markAsChanged = function(){ - return this.each(function(){ - let element = $(this); - - if( element.hasClass(config.systemClass) ){ - // system element - element.data('changed', true); - }else{ - // connection element - this.setParameter('changed', true); - } - }); - }; - - /** - * check if an dom element (system, connection) has changed - * @returns {boolean} - */ - $.fn.hasChanged = function(){ - let element = $(this); - let changed = false; - - if( element.hasClass(config.systemClass) ){ - // system element - changed = element.data('changed') || false; - }else{ - // connection element - changed = this[0].getParameter('changed') || false; - } - - return changed; - }; - /** * select all (selectable) systems on a mapElement */ @@ -2025,9 +2006,7 @@ define([ * @param options */ $.fn.toggleLockSystem = function(poke, options){ - let system = $(this); - let map = options.map; let hideNotification = false; @@ -2065,13 +2044,11 @@ define([ } // repaint connections - map.revalidate( system.attr('id') ); + revalidate(map, system); - - if(! hideCounter){ + if(!hideCounter){ $(system).getMapOverlay('timer').startMapUpdateCounter(); } - }; /** @@ -2081,7 +2058,7 @@ define([ */ let getMapInstance = function(mapId){ - if( !MapUtil.existsMapInstance(mapId) ){ + if(!MapUtil.existsMapInstance(mapId)){ // create new instance jsPlumb.Defaults.LogEnabled = true; @@ -2150,7 +2127,7 @@ define([ // set "default" connection status only for NEW connections if(!connection.suspendedElement){ - MapUtil.setConnectionWHStatus(connection, MapUtil.getDefaultConnectionTypeByScope(connection.scope) ); + MapUtil.setConnectionWHStatus(connection, MapUtil.getDefaultConnectionTypeByScope(connection.scope)); } // prevent multiple connections between same systems @@ -2178,7 +2155,7 @@ define([ // This is called when the user has detached a Connection, which can happen for a number of reasons: // by default, jsPlumb allows users to drag Connections off of target Endpoints, but this can also result from a programmatic 'detach' call. - newJsPlumbInstance.bind('beforeDetach', function(info){ + newJsPlumbInstance.bind('beforeDetach', function(connection){ return true; }); @@ -2501,7 +2478,7 @@ define([ // get map menu config options let data = MapUtil.mapOptions[mapOption.option]; - let promiseStore = MapUtil.getLocaleData('map', mapElement.data('id') ); + let promiseStore = MapUtil.getLocaleData('map', mapElement.data('id')); promiseStore.then(function(dataStore){ let notificationText = 'disabled'; let button = $('#' + this.data.buttonId); @@ -2677,7 +2654,7 @@ define([ // get current system alias let systemHeadNameElement = $(this).find('.' + config.systemHeadNameClass); let alias = ''; - if( systemHeadNameElement.hasClass('editable') ){ + if(systemHeadNameElement.hasClass('editable')){ // xEditable is initiated alias = systemHeadNameElement.editable('getValue', true); } @@ -2820,150 +2797,147 @@ define([ return new Promise(updateUserDataExecutor); }; + /** + * collect all map data from client for server or client sync + * @param mapContainer + * @param filter + * @param minimal + * @returns {boolean} + */ + let getMapDataForSync = (mapContainer, filter = [], minimal = false) => { + let mapData = false; + // check if there is an active map counter that prevents collecting map data (locked map) + if(!mapContainer.getMapOverlayInterval()){ + mapData = mapContainer.getMapDataFromClient(filter, minimal); + } + return mapData; + }; + /** * collect all map data for export/save for a map * this function returns the "client" data NOT the "server" data for a map - * @param options - * @returns {*} + * @param filter + * @param minimal */ - $.fn.getMapDataFromClient = function(options){ - let mapElement = $(this); - let map = getMapInstance( mapElement.data('id') ); + $.fn.getMapDataFromClient = function(filter = [], minimal = false){ + let mapContainer = $(this); + let map = getMapInstance(mapContainer.data('id')); + + let filterHasId = filter.includes('hasId'); + let filterHasChanged = filter.includes('hasChanged'); + let mapData = {}; - // check if there is an active map counter that prevents collecting map data (locked map) - let interval = mapElement.getMapOverlayInterval(); + // map config ------------------------------------------------------------------------------------------------- + mapData.config = { + id: parseInt(mapContainer.data('id')), + name: mapContainer.data('name'), + scope: { + id: parseInt(mapContainer.data('scopeId')) + }, + icon: mapContainer.data('icon'), + type: { + id: parseInt(mapContainer.data('typeId')) + }, + created: parseInt(mapContainer.data('created')), + updated: parseInt(mapContainer.data('updated')) + }; - if( - !interval || - options.forceData === true - ){ + let data = {}; - // map config --------------------------------------------------------------------------------------------- - mapData.config = { - id: parseInt( mapElement.data('id') ), - name: mapElement.data('name'), - scope: { - id: parseInt( mapElement.data('scopeId') ) - }, - icon: mapElement.data('icon'), - type: { - id: parseInt( mapElement.data('typeId') ) - }, - created: parseInt( mapElement.data('created') ), - updated: parseInt( mapElement.data('updated') ), - }; + // systems data ----------------------------------------------------------------------------------------------- + let systemsData = []; + let systems = mapContainer.getSystems(); - // map data ----------------------------------------------------------------------------------------------- - let data = {}; + for(let i = 0; i < systems.length; i++){ + let system = $(systems[i]); - // systems data ------------------------------------------------------------------------------------------- - let systemsData = []; - let systems = mapElement.getSystems(); - - for(let i = 0; i < systems.length; i++){ - let tempSystem = $(systems[i]); - - // check if system data should be added - let addSystemData = true; - if( - options.getAll !== true && - options.checkForChange === true && - !tempSystem.hasChanged() - ){ - addSystemData = false; - } - - if(addSystemData){ - systemsData.push( tempSystem.getSystemData() ); - } + if(filterHasChanged && !MapUtil.hasChanged(system)){ + continue; } - data.systems = systemsData; - - // connections -------------------------------------------------------------------------------------------- - let connections = map.getAllConnections(); - let connectionsFormatted = []; - - // format connections - for(let j = 0; j < connections.length; j++){ - let tempConnection = connections[j]; - let connectionData = MapUtil.getDataByConnection(tempConnection); - - // only add valid connections (id is required, this is not the case if connection is new) - if(connectionData.id > 0){ - // check if connection data should be added - let addConnectionData = true; - if( - options.getAll !== true && - options.checkForChange === true && - !$(tempConnection).hasChanged() - ){ - addConnectionData = false; - } - - - if(addConnectionData){ - connectionsFormatted.push( connectionData ); - } - - // add to cache - updateConnectionCache(mapData.config.id, tempConnection); - } - } - - data.connections = connectionsFormatted; - - mapData.data = data; - }else{ - return false; + systemsData.push(system.getSystemData(minimal)); } + data.systems = systemsData; + + // connections ------------------------------------------------------------------------------------------------ + let connectionsData = []; + let connections = map.getAllConnections(); + + for(let j = 0; j < connections.length; j++) { + let connection = connections[j]; + + // add to cache + updateConnectionCache(mapData.config.id, connection); + + if(filterHasChanged && !MapUtil.hasChanged(connection)){ + continue; + } + + if(filterHasId && !connection.getParameter('connectionId')){ + continue; + } + + connectionsData.push(MapUtil.getDataByConnection(connection, minimal)); + } + + data.connections = connectionsData; + + mapData.data = data; + return mapData; }; /** * get all relevant data for a system object - * @returns {{}} + * @param minimal + * @returns {{id: number, updated: {updated: number}}} */ - $.fn.getSystemData = function(){ + $.fn.getSystemData = function(minimal = false){ let system = $(this); - let systemData = {}; - systemData.id = parseInt( system.data('id') ); - systemData.systemId = parseInt( system.data('systemId') ); - systemData.name = system.data('name'); - systemData.alias = system.getSystemInfo(['alias']); - systemData.effect = system.data('effect'); - systemData.type = { - id: system.data('typeId') + let systemData = { + id: parseInt(system.data('id')), + updated: { + updated: parseInt(system.data('updated')) + } }; - systemData.security = system.data('security'); - systemData.trueSec = system.data('trueSec'); - systemData.region = { - id: system.data('regionId'), - name: system.data('region') - }; - systemData.constellation = { - id: system.data('constellationId'), - name: system.data('constellation') - }; - systemData.status = { - id: system.data('statusId') - }; - systemData.locked = system.data('locked') ? 1 : 0; - systemData.rallyUpdated = system.data('rallyUpdated') || 0; - systemData.rallyPoke = system.data('rallyPoke') ? 1 : 0; - systemData.currentUser = system.data('currentUser'); // if user is currently in this system - systemData.faction = system.data('faction'); - systemData.planets = system.data('planets'); - systemData.shattered = system.data('shattered') ? 1 : 0; - systemData.statics = system.data('statics'); - systemData.updated = { - updated: parseInt( system.data('updated') ) - }; - systemData.userCount = (system.data('userCount') ? parseInt( system.data('userCount') ) : 0); - systemData.position = MapUtil.getSystemPosition(system); + + if(!minimal){ + systemData = Object.assign(systemData, { + systemId: parseInt(system.data('systemId')), + name: system.data('name'), + alias: system.getSystemInfo(['alias']), + effect: system.data('effect'), + type: { + id: system.data('typeId') + }, + security: system.data('security'), + trueSec: system.data('trueSec'), + region: { + id: system.data('regionId'), + name: system.data('region') + }, + constellation: { + id: system.data('constellationId'), + name: system.data('constellation') + }, + status: { + id: system.data('statusId') + }, + locked: system.data('locked') ? 1 : 0, + rallyUpdated: system.data('rallyUpdated') || 0, + rallyPoke: system.data('rallyPoke') ? 1 : 0, + currentUser: system.data('currentUser'), // if user is currently in this system + faction: system.data('faction'), + planets: system.data('planets'), + shattered: system.data('shattered') ? 1 : 0, + statics: system.data('statics'), + userCount: (system.data('userCount') ? parseInt(system.data('userCount')) : 0), + position: MapUtil.getSystemPosition(system) + }); + } return systemData; }; @@ -3085,6 +3059,7 @@ define([ getMapInstance: getMapInstance, loadMap: loadMap, updateUserData: updateUserData, + getMapDataForSync: getMapDataForSync, saveSystemCallback: saveSystemCallback }; diff --git a/public/js/v1.5.1/app/map/overlay.js b/public/js/v1.5.1/app/map/overlay.js index 0766cc8a..d7318c9d 100644 --- a/public/js/v1.5.1/app/map/overlay.js +++ b/public/js/v1.5.1/app/map/overlay.js @@ -74,13 +74,18 @@ define([ * @param label */ let addEndpointOverlay = (endpoint, label) => { + label = label.join(', '); + endpoint.addOverlay([ 'Label', { label: MapUtil.getEndpointOverlayContent(label), id: config.endpointOverlayId, cssClass: [config.componentOverlayClass, label.length ? 'small' : 'icon'].join(' '), - location: [ 0.9, 0.9 ] + location: MapUtil.getLabelEndpointOverlayLocation(endpoint, label), + parameters: { + label: label + } } ]); }; diff --git a/public/js/v1.5.1/app/map/system.js b/public/js/v1.5.1/app/map/system.js index c902327f..b6187040 100644 --- a/public/js/v1.5.1/app/map/system.js +++ b/public/js/v1.5.1/app/map/system.js @@ -145,7 +145,7 @@ define([ let statusData = [{id: 0, text: 'auto'}]; // get current map data --------------------------------------------------------------------------------------- - let mapData = mapContainer.getMapDataFromClient({forceData: true}); + let mapData = mapContainer.getMapDataFromClient(['hasId']); let mapSystems = mapData.data.systems; let mapSystemCount = mapSystems.length; let mapTypeName = mapContainer.data('typeName'); diff --git a/public/js/v1.5.1/app/map/util.js b/public/js/v1.5.1/app/map/util.js index 1893afd9..d6894311 100644 --- a/public/js/v1.5.1/app/map/util.js +++ b/public/js/v1.5.1/app/map/util.js @@ -5,9 +5,8 @@ define([ 'jquery', 'app/init', - 'app/util', - 'bootbox' -], ($, Init, Util, bootbox) => { + 'app/util' +], ($, Init, Util) => { 'use strict'; let config = { @@ -262,6 +261,33 @@ define([ return effectInfo; }; + /** + * flag map component (map, system, connection) as "changed" + * @param component + */ + let markAsChanged = component => { + if(component instanceof $ && component.hasClass(config.systemClass)){ + component.data('changed', true); + }else if(component instanceof jsPlumb.Connection){ + component.setParameter('changed', true); + } + }; + + /** + * check if map component (system, connection) is flagged as "changed" + * @param component + * @returns {boolean} + */ + let hasChanged = component => { + let changed = false; + if(component instanceof $ && component.hasClass(config.systemClass)){ + changed = component.data('changed') || false; + }else if(component instanceof jsPlumb.Connection){ + changed = component.getParameter('changed') || false; + } + return changed; + }; + /** * get system elements on a map * @returns {*|jQuery} @@ -317,55 +343,71 @@ define([ * filter connections by type * @param map * @param type + * @param exclude * @returns {Array} */ - let getConnectionsByType = (map, type) => { + let getConnectionsByType = (map, type, exclude = false) => { let connections = []; - // iterate through ALL connections and filter... - // -> there is no "filterByScope()" method in jsPlumb - for(let connection of map.getAllConnections()){ - if(connection.getType().indexOf(type) !== -1){ - connections.push(connection); + for(let data of map.select().hasType(type)){ + if(data[0] !== exclude){ + connections.push(data[1]); } } return connections; }; /** - * get all relevant data for a connection object + * get endpoints data from connection * @param connection - * @returns {{targetName: *, endpoints, scope: *, targetAlias: *, id: number, source: number, sourceName: *, type, updated: number, sourceAlias: *, target: number}} + * @returns {{source: {}, target: {}}} */ - let getDataByConnection = connection => { - let source = $(connection.source); - let target = $(connection.target); - - let id = connection.getParameter('connectionId'); - let updated = connection.getParameter('updated'); - - let endpoints = {source: {}, target: {}}; + let getEndpointsDataByConnection = connection => { + let endpointsData = {source: {}, target: {}}; for(let endpoint of connection.endpoints){ let endpointData = getDataByEndpoint(connection, endpoint); if(endpointData.label === 'source'){ - endpoints.source = endpointData; + endpointsData.source = endpointData; }else if(endpointData.label === 'target'){ - endpoints.target = endpointData; + endpointsData.target = endpointData; } } + return endpointsData; + }; - return { - id: id ? id : 0, + /** + * get connection data from connection + * @param connection + * @param minimal + * @returns {{id: (*|number), updated: (*|number)}} + */ + let getDataByConnection = (connection, minimal = false) => { + let source = $(connection.source); + let target = $(connection.target); + + let connectionData = { + id: connection.getParameter('connectionId') || 0, + updated: connection.getParameter('updated') || 0, source: parseInt(source.data('id')), - sourceName: source.data('name'), - sourceAlias: source.getSystemInfo(['alias']) || source.data('name'), - target: parseInt(target.data('id')), - targetName: target.data('name'), - targetAlias: target.getSystemInfo(['alias']) || target.data('name'), - scope: connection.scope, - type: filterDefaultTypes(connection.getType()), - endpoints: endpoints, - updated: updated ? updated : 0 + target: parseInt(target.data('id')) }; + + if(minimal){ + connectionData = Object.assign(connectionData, { + connection: connection + }); + }else{ + connectionData = Object.assign(connectionData, { + sourceName: source.data('name'), + sourceAlias: source.getSystemInfo(['alias']) || source.data('name'), + targetName: target.data('name'), + targetAlias: target.getSystemInfo(['alias']) || target.data('name'), + scope: connection.scope, + type: filterDefaultTypes(connection.getType()), + endpoints: getEndpointsDataByConnection(connection) + }); + } + + return connectionData; }; /** @@ -516,30 +558,53 @@ define([ return signatureTypeNames; }; + /** + * get Location [x,y] for Endpoint Overlays (e.g. wh type from Signature mapping) + * -> Coordinates are relative to the Endpoint (not the system!) + * -> jsPlumb specific format + * @param endpoint + * @param label + * @returns {number[]} + */ + let getLabelEndpointOverlayLocation = (endpoint, label) => { + let chars = label.length ? label.length : 2; + let xTop = chars === 2 ? +0.05 : chars <= 4 ? -0.75 : 3; + let xLeft = chars === 2 ? -1.10 : chars <= 4 ? -2.75 : 3; + let xRight = chars === 2 ? +1.25 : chars <= 4 ? +1.25 : 3; + let xBottom = chars === 2 ? +0.05 : chars <= 4 ? -0.75 : 3; + + let yTop = chars === 2 ? -1.10 : chars <= 4 ? -1.75 : 3; + + switch(endpoint._continuousAnchorEdge){ + case 'top': return [xTop, yTop]; + case 'left': return [xLeft, 0]; + case 'right': return [xRight, 0]; + case 'bottom': return [xBottom , 1.3]; + default: return [0.0, 0.0]; + } + }; + /** * get overlay HTML for connection endpoints by Label array * @param label * @returns {string} */ let getEndpointOverlayContent = label => { - let newLabel = ''; let colorClass = 'txt-color-grayLighter'; if(label.length > 0){ - newLabel = label.join(', '); - // check if multiple labels found => conflict - if( newLabel.includes(', ') ){ + if( label.includes(', ') ){ colorClass = 'txt-color-orangeLight'; - }else if( !newLabel.includes('K162') ){ + }else if( !label.includes('K162') ){ colorClass = 'txt-color-yellow'; } }else{ // endpoint not connected with a signature - newLabel = ''; + label = ''; colorClass = 'txt-color-red'; } - return '' + newLabel + ''; + return '' + label + ''; }; /** @@ -1737,6 +1802,8 @@ define([ getSystemData: getSystemData, getSystemTypeInfo: getSystemTypeInfo, getEffectInfoForSystem: getEffectInfoForSystem, + markAsChanged: markAsChanged, + hasChanged: hasChanged, toggleSystemsSelect: toggleSystemsSelect, toggleConnectionActive: toggleConnectionActive, setSystemActive: setSystemActive, @@ -1745,6 +1812,7 @@ define([ showFindRouteDialog: showFindRouteDialog, getEndpointLabel: getEndpointLabel, getConnectionsByType: getConnectionsByType, + getEndpointsDataByConnection: getEndpointsDataByConnection, getDataByConnection: getDataByConnection, searchConnectionsBySystems: searchConnectionsBySystems, searchConnectionsByScopeAndType: searchConnectionsByScopeAndType, @@ -1757,6 +1825,7 @@ define([ getDataByConnections: getDataByConnections, deleteConnections: deleteConnections, getConnectionDataFromSignatures: getConnectionDataFromSignatures, + getLabelEndpointOverlayLocation: getLabelEndpointOverlayLocation, getEndpointOverlayContent: getEndpointOverlayContent, getTabContentElementByMapElement: getTabContentElementByMapElement, hasActiveConnection: hasActiveConnection, diff --git a/public/js/v1.5.1/app/module_map.js b/public/js/v1.5.1/app/module_map.js index d08de79a..df3d1e3c 100644 --- a/public/js/v1.5.1/app/module_map.js +++ b/public/js/v1.5.1/app/module_map.js @@ -1350,7 +1350,7 @@ define([ let data = []; for(let i = 0; i < mapElements.length; i++){ // get all changed (system / connection) data from this map - let mapData = $(mapElements[i]).getMapDataFromClient({forceData: false, checkForChange: true}); + let mapData = Map.getMapDataForSync($(mapElements[i]), ['hasId', 'hasChanged']); if(mapData !== false){ if( mapData.data.systems.length > 0 || diff --git a/public/js/v1.5.1/app/page.js b/public/js/v1.5.1/app/page.js index 8e302476..bd21cf42 100644 --- a/public/js/v1.5.1/app/page.js +++ b/public/js/v1.5.1/app/page.js @@ -701,7 +701,7 @@ define([ let activeMap = Util.getMapModule().getActiveMap(); if(activeMap){ - mapData = activeMap.getMapDataFromClient({forceData: true}); + mapData = activeMap.getMapDataFromClient(['hasId']); } $.fn.showDeleteMapDialog(mapData); diff --git a/public/js/v1.5.1/app/ui/dialog/map_info.js b/public/js/v1.5.1/app/ui/dialog/map_info.js index 9dd383d6..8e5c717a 100644 --- a/public/js/v1.5.1/app/ui/dialog/map_info.js +++ b/public/js/v1.5.1/app/ui/dialog/map_info.js @@ -322,7 +322,8 @@ define([ },{ name: 'region', title: 'region', - data: 'region.name' + data: 'region.name', + className: 'min-screen-l', },{ name: 'planets', title: '', @@ -442,7 +443,7 @@ define([ title: 'updated', width: 80, searchable: false, - className: ['text-right', config.tableCellCounterClass, 'min-screen-l'].join(' '), + className: ['text-right', config.tableCellCounterClass].join(' '), data: 'updated.updated', defaultContent: '', },{ @@ -480,7 +481,7 @@ define([ // refresh connection table (connections might have changed) -------------- let connectionsElement = $('#' + config.mapInfoConnectionsId); - let mapDataNew = activeMap.getMapDataFromClient({forceData: true}); + let mapDataNew = activeMap.getMapDataFromClient(['hasId']); connectionsElement.initConnectionInfoTable(mapDataNew); }else{ @@ -522,6 +523,10 @@ define([ // table init complete connectionTable.on('init.dt', function(){ connectionsElement.hideLoadingAnimation(); + + // init table tooltips + let tooltipElements = connectionsElement.find('[data-toggle="tooltip"]'); + tooltipElements.tooltip(); }); // connections table ------------------------------------------------------------------------------------------ @@ -530,7 +535,7 @@ define([ paging: true, lengthMenu: [[5, 10, 20, 50, -1], [5, 10, 20, 50, 'All']], ordering: true, - order: [ 0, 'desc' ], + order: [ 6, 'desc' ], autoWidth: false, hover: false, data: mapData.data.connections, @@ -1264,7 +1269,7 @@ define([ */ $.fn.showMapInfoDialog = function(options){ let activeMap = Util.getMapModule().getActiveMap(); - let mapData = activeMap ? activeMap.getMapDataFromClient({forceData: true}) : false; + let mapData = activeMap ? activeMap.getMapDataFromClient(['hasId']) : false; if(mapData !== false){ // "log" tab -> get "Origin", not all config options are set in mapData @@ -1321,7 +1326,7 @@ define([ let menuAction = $(this).attr('data-action'); if(menuAction === 'refresh'){ // get new map data - let mapData = activeMap.getMapDataFromClient({forceData: true}); + let mapData = activeMap.getMapDataFromClient(['hasId']); // find active tab let activeTabLink = $(this).parents('.navbar').find('.navbar-header.pull-left li.active a'); if(activeTabLink.attr('href') === '#' + config.dialogMapInfoLogsId){ diff --git a/public/js/v1.5.1/app/ui/dialog/map_settings.js b/public/js/v1.5.1/app/ui/dialog/map_settings.js index b61e1434..bd02f526 100644 --- a/public/js/v1.5.1/app/ui/dialog/map_settings.js +++ b/public/js/v1.5.1/app/ui/dialog/map_settings.js @@ -496,10 +496,7 @@ define([ // IMPORTANT: Get map data from client (NOT from global mapData which is available in here) // -> This excludes some data (e.g. wh statics) // -> Bring export inline with main map toggle requests - let exportMapData = mapElement.getMapDataFromClient({ - forceData: true, - getAll: true - }); + let exportMapData = mapElement.getMapDataFromClient(['hasId']); let exportButton = $(this); // set map data right before download diff --git a/public/js/v1.5.1/app/ui/module/connection_info.js b/public/js/v1.5.1/app/ui/module/connection_info.js index 32c428a3..bcac90cb 100644 --- a/public/js/v1.5.1/app/ui/module/connection_info.js +++ b/public/js/v1.5.1/app/ui/module/connection_info.js @@ -308,8 +308,8 @@ define([ let sourceLabel = signatureTypeNames.sourceLabels; let targetLabel = signatureTypeNames.targetLabels; - sourceLabelElement.html(MapUtil.getEndpointOverlayContent(sourceLabel)); - targetLabelElement.html(MapUtil.getEndpointOverlayContent(targetLabel)); + sourceLabelElement.html(MapUtil.getEndpointOverlayContent(sourceLabel.join(', '))); + targetLabelElement.html(MapUtil.getEndpointOverlayContent(targetLabel.join(', '))); // remove K162 sourceLabel = sourceLabel.diff(['K162']); @@ -1153,7 +1153,7 @@ define([ */ let getConnectionsDataFromModule = (moduleElement, mapId) => { let activeMap = Util.getMapModule().getActiveMap(); - let mapData = activeMap.getMapDataFromClient({forceData: true}); + let mapData = activeMap.getMapDataFromClient(['hasId']); let connectionsData = { connectionsDataUpdate: [], connectionsDataRemove: [], diff --git a/public/js/v1.5.1/lib/dom.jsPlumb-1.7.6.js b/public/js/v1.5.1/lib/dom.jsPlumb-1.7.6.js index cadf836f..04237fb2 100644 --- a/public/js/v1.5.1/lib/dom.jsPlumb-1.7.6.js +++ b/public/js/v1.5.1/lib/dom.jsPlumb-1.7.6.js @@ -10390,9 +10390,10 @@ // be fixed. IE8 is not going to be supported for much longer. //var ts = "translate(calc(-50% + 3px), calc(-50% + 3px))"; //var ts = "translate3d(-50%, -50, 0)"; - //var ts = "translate3d(0, 0, 0)"; - var ts = "translate3d(50%, 50, 0)"; + var ts = "translate3d(0, 0, 0)"; + //var ts = "translate3d(50%, -50, 0)"; //var ts = "translate3d(-8px, 5px, 0)"; + //var ts = "translate(-50%, -50%)"; div.style.webkitTransform = ts; div.style.mozTransform = ts; div.style.msTransform = ts; diff --git a/public/templates/dialog/credit.html b/public/templates/dialog/credit.html index 090a4a41..81212dcc 100644 --- a/public/templates/dialog/credit.html +++ b/public/templates/dialog/credit.html @@ -28,8 +28,6 @@