diff --git a/app/main/model/pathfinder/connectionmodel.php b/app/main/model/pathfinder/connectionmodel.php
index 3f29cda3..df562fe6 100644
--- a/app/main/model/pathfinder/connectionmodel.php
+++ b/app/main/model/pathfinder/connectionmodel.php
@@ -88,6 +88,12 @@ class ConnectionModel extends AbstractMapTrackingModel {
]
];
+ /**
+ * allowed connection types
+ * @var array
+ */
+ protected static $connectionTypeWhitelist = ['wh_fresh', 'wh_reduced', 'wh_critical', 'frigate', 'preserve_mass'];
+
/**
* get connection data
* @param bool $addSignatureData
@@ -130,13 +136,15 @@ class ConnectionModel extends AbstractMapTrackingModel {
* @return int|number
*/
public function set_type($type){
- $newTypes = (array)$type;
+ // remove unwanted types -> they should not be send from client
+ // -> reset keys! otherwise JSON format results in object and not in array
+ $type = array_values(array_intersect((array)$type, self::$connectionTypeWhitelist));
// set EOL timestamp
- if( !in_array('wh_eol', $newTypes) ){
+ if( !in_array('wh_eol', $type) ){
$this->eolUpdated = null;
}elseif(
- in_array('wh_eol', $newTypes) &&
+ in_array('wh_eol', $type) &&
!in_array('wh_eol', (array)$this->type) // $this->type == null for new connection! (e.g. map import)
){
// connection EOL status change
diff --git a/js/app.js b/js/app.js
index e6ef6aad..f73fcc13 100644
--- a/js/app.js
+++ b/js/app.js
@@ -33,7 +33,7 @@ requirejs.config({
velocity: 'lib/velocity.min', // v1.5.1 animation engine - http://julian.com/research/velocity
velocityUI: 'lib/velocity.ui.min', // v5.2.0 plugin for velocity - http://julian.com/research/velocity/#uiPack
slidebars: 'lib/slidebars', // v2.0.2 Slidebars - side menu plugin https://www.adchsm.com/slidebars/
- jsPlumb: 'lib/dom.jsPlumb-1.7.6', // v1.7.6 jsPlumb (Vanilla)- main map draw plugin https://jsplumbtoolkit.com
+ jsPlumb: 'lib/jsplumb', // v2.9.3 jsPlumb main map draw plugin http://jsplumb.github.io/jsplumb/home.html
farahey: 'lib/farahey-0.5', // v0.5 jsPlumb "magnetizing" extension - https://github.com/jsplumb/farahey
customScrollbar: 'lib/jquery.mCustomScrollbar.min', // v3.1.5 Custom scroll bars - http://manos.malihu.gr
mousewheel: 'lib/jquery.mousewheel.min', // v3.1.13 Mousewheel - https://github.com/jquery/jquery-mousewheel
diff --git a/js/app/init.js b/js/app/init.js
index 3e3c008e..0208f097 100644
--- a/js/app/init.js
+++ b/js/app/init.js
@@ -343,51 +343,53 @@ define(['jquery'], ($) => {
}
},
wh_eol: {
- cssClass: 'pf-map-connection-wh-eol',
- paintStyle: {
- dashstyle: '0' // solid line
- }
+ cssClass: 'pf-map-connection-wh-eol'
},
wh_fresh: {
- cssClass: 'pf-map-connection-wh-fresh',
- paintStyle: {
- dashstyle: '0' // solid line
- }
+ cssClass: 'pf-map-connection-wh-fresh'
},
wh_reduced: {
- cssClass: 'pf-map-connection-wh-reduced',
- paintStyle: {
- dashstyle: '0' // solid line
- }
+ cssClass: 'pf-map-connection-wh-reduced'
},
wh_critical: {
- cssClass: 'pf-map-connection-wh-critical',
- paintStyle: {
- dashstyle: '0' // solid line
- }
+ cssClass: 'pf-map-connection-wh-critical'
},
frigate: {
cssClass: 'pf-map-connection-frig',
paintStyle: {
- dashstyle: '0.99'
+ dashstyle: '0.5 1'
},
- overlays:[
+ overlays: [
['Label',
{
label: 'frig',
cssClass: ['pf-map-component-overlay', 'frig'].join(' '),
- location: 0.6
+ location: 0.7
}]
]
},
preserve_mass: {
cssClass: 'pf-map-connection-preserve-mass',
- overlays:[
+ overlays: [
['Label',
{
label: ' save mass',
cssClass: ['pf-map-component-overlay', 'mass'].join(' '),
- location: 0.6
+ location: 0.3
+ }]
+ ]
+ },
+ info_signature: {
+ overlays: [
+ ['Arrow',
+ {
+ id: 'pf-map-connection-arrow-overlay',
+ cssClass: 'pf-map-connection-arrow-overlay',
+ width: 12,
+ length: 15,
+ foldback: 0.8,
+ direction: 1,
+ location: 0.5
}]
]
},
@@ -396,12 +398,12 @@ define(['jquery'], ($) => {
},
state_process: {
cssClass: 'pf-map-connection-process',
- overlays:[
+ overlays: [
['Label',
{
label: '',
cssClass: ['pf-map-connection-state-overlay'].join(' '),
- location: 0.6
+ location: 0.5
}]
]
}
diff --git a/js/app/key.js b/js/app/key.js
index bab7d1e8..be54743a 100644
--- a/js/app/key.js
+++ b/js/app/key.js
@@ -10,6 +10,12 @@ define([
label: 'Close open dialog',
keyNames: ['ESC']
},
+ // map ----------------------------------------------------------------------------------------------
+ mapMove: {
+ group: 'map',
+ label: 'Move map section',
+ keyNames: ['drag', 'move']
+ },
// signature ----------------------------------------------------------------------------------------
signatureSelect: {
group: 'signatures',
@@ -79,12 +85,6 @@ define([
*/
let debug = false;
- /**
- * check interval for "new" active keys
- * @type {number}
- */
- let keyWatchPeriod = 100;
-
/**
* DOM data key for an element that lists all active events (comma separated)
* @type {string}
@@ -133,6 +133,13 @@ define([
return Object.keys(map);
};
+ /**
+ * checks whether a key is currently active (keydown)
+ * @param key
+ * @returns {boolean}
+ */
+ let isActive = key => map.hasOwnProperty(key) && map[key] === true;
+
/**
* callback function that compares two arrays
* @param element
@@ -460,6 +467,7 @@ define([
};
return {
+ isActive: isActive,
getGroupedShortcuts: getGroupedShortcuts
};
});
\ No newline at end of file
diff --git a/js/app/map/map.js b/js/app/map/map.js
index 1b44cd40..56717688 100644
--- a/js/app/map/map.js
+++ b/js/app/map/map.js
@@ -6,17 +6,19 @@ define([
'jquery',
'app/init',
'app/util',
+ 'app/key',
'bootbox',
'app/map/util',
'app/map/contextmenu',
- 'app/map/overlay',
+ 'app/map/overlay/overlay',
+ 'app/map/overlay/util',
'app/map/system',
'app/map/layout',
'app/map/magnetizing',
'app/map/scrollbar',
'dragToSelect',
'app/map/local'
-], ($, Init, Util, bootbox, MapUtil, MapContextMenu, MapOverlay, System, Layout, MagnetizerWrapper) => {
+], ($, Init, Util, Key, bootbox, MapUtil, MapContextMenu, MapOverlay, MapOverlayUtil, System, Layout, MagnetizerWrapper, Scrollbar) => {
'use strict';
@@ -91,8 +93,7 @@ define([
},
connectionsDetachable: true, // dragOptions are set -> allow detaching them
maxConnections: 10, // due to isTarget is true, this is the max count of !out!-going connections
- // isSource:true,
- anchor: 'Continuous'
+ // isSource:true
},
target: {
filter: filterSystemHeadEvent,
@@ -104,9 +105,7 @@ define([
hoverClass: config.systemActiveClass,
activeClass: 'dragActive'
},
- // isTarget:true,
- // uniqueEndpoint: false,
- anchor: 'Continuous'
+ // uniqueEndpoint: false
},
endpointTypes: Init.endpointTypes,
connectionTypes: Init.connectionTypes
@@ -130,7 +129,7 @@ define([
// -> 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(MapOverlay.endpointOverlayId);
+ let overlay = endpoint.getOverlay(MapOverlayUtil.config.endpointOverlayId);
if(overlay instanceof jsPlumb.Overlays.Label){
let label = overlay.getParameter('label');
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, label));
@@ -588,7 +587,7 @@ define([
case 'change_status_empty':
case 'change_status_unscanned':
// change system status
- system.getMapOverlay('timer').startMapUpdateCounter();
+ MapOverlayUtil.getMapOverlay(system, 'timer').startMapUpdateCounter();
let statusString = action.split('_');
@@ -730,16 +729,15 @@ define([
case 'frigate': // set as frigate hole
case 'preserve_mass': // set "preserve mass
case 'wh_eol': // set "end of life"
- mapElement.getMapOverlay('timer').startMapUpdateCounter();
- connection.toggleType(action);
+ MapOverlayUtil.getMapOverlay(mapElement, 'timer').startMapUpdateCounter();
+ MapUtil.toggleConnectionType(connection, action);
MapUtil.markAsChanged(connection);
break;
case 'status_fresh':
case 'status_reduced':
case 'status_critical':
let newStatus = action.split('_')[1];
- mapElement.getMapOverlay('timer').startMapUpdateCounter();
-
+ MapOverlayUtil.getMapOverlay(mapElement, 'timer').startMapUpdateCounter();
MapUtil.setConnectionWHStatus(connection, 'wh_' + newStatus);
MapUtil.markAsChanged(connection);
break;
@@ -751,7 +749,7 @@ define([
bootbox.confirm('Change scope from ' + scopeName + ' to ' + newScopeName + '?', function(result){
if(result){
- mapElement.getMapOverlay('timer').startMapUpdateCounter();
+ MapOverlayUtil.getMapOverlay(mapElement, 'timer').startMapUpdateCounter();
setConnectionScope(connection, newScope);
@@ -775,7 +773,7 @@ define([
switch(action){
case 'bubble':
- mapElement.getMapOverlay('timer').startMapUpdateCounter();
+ MapOverlayUtil.getMapOverlay(mapElement, 'timer').startMapUpdateCounter();
endpoint.toggleType(action);
for(let connection of endpoint.connections){
@@ -860,7 +858,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,
@@ -878,6 +876,7 @@ define([
// check if connection is valid (e.g. source/target exist
if(connection instanceof jsPlumb.Connection){
+ connection.addType((connectionData.type || MapUtil.getDefaultConnectionTypeByScope(map.Defaults.Scope)).join(' '));
// set connection parameters
// they should persist even through connection type change (e.g. wh -> stargate,..)
@@ -1145,7 +1144,7 @@ define([
mapWrapper.setMapShortcuts();
// show static overlay actions
- let mapOverlay = mapContainer.getMapOverlay('info');
+ let mapOverlay = MapOverlayUtil.getMapOverlay(mapContainer, 'info');
mapOverlay.updateOverlayIcon('systemRegion', 'show');
mapOverlay.updateOverlayIcon('connection', 'show');
mapOverlay.updateOverlayIcon('connectionEol', 'show');
@@ -1316,7 +1315,7 @@ define([
deleteConnection.source &&
deleteConnection.target
){
- mapConfig.map.detach(deleteConnection, {fireEvent: false});
+ mapConfig.map.deleteConnection(deleteConnection, {fireEvent: false});
}
}
}
@@ -1626,12 +1625,12 @@ define([
Util.showNotify({title: title, text: 'Scope: ' + scope, type: 'success'});
}else{
// some save errors
- payload.context.map.detach(payload.context.connection, {fireEvent: false});
+ payload.context.map.deleteConnection(payload.context.connection, {fireEvent: false});
}
},
payload => {
// remove this connection from map
- payload.context.map.detach(payload.context.connection, {fireEvent: false});
+ payload.context.map.deleteConnection(payload.context.connection, {fireEvent: false});
Util.handleAjaxErrorResponse(payload);
}
);
@@ -1830,7 +1829,7 @@ define([
start: function(params){
let dragSystem = $(params.el);
- mapOverlayTimer = dragSystem.getMapOverlay('timer');
+ mapOverlayTimer = MapOverlayUtil.getMapOverlay(dragSystem, 'timer');
// start map update timer
mapOverlayTimer.startMapUpdateCounter();
@@ -2047,7 +2046,7 @@ define([
revalidate(map, system);
if(!hideCounter){
- $(system).getMapOverlay('timer').startMapUpdateCounter();
+ MapOverlayUtil.getMapOverlay(system, 'timer').startMapUpdateCounter();
}
};
@@ -2063,18 +2062,33 @@ define([
jsPlumb.Defaults.LogEnabled = true;
let newJsPlumbInstance = jsPlumb.getInstance({
- Anchor: 'Continuous', // anchors on each site
- Container: null, // will be set as soon as container is connected to DOM
+ Anchor: ['Continuous', {faces: ['top', 'right', 'bottom', 'left']}], // single anchor (used during drag action)
+ Anchors: [
+ ['Continuous', {faces: ['top', 'right', 'bottom', 'left']}],
+ ['Continuous', {faces: ['top', 'right', 'bottom', 'left']}],
+ ],
+ Container: null, // will be set as soon as container is connected to DOM
PaintStyle: {
- lineWidth: 4, // width of a Connector's line. An integer.
- strokeStyle: 'red', // color for a Connector
- outlineColor: 'red', // color of the outline for an Endpoint or Connector. see fillStyle examples.
- outlineWidth: 2 // width of the outline for an Endpoint or Connector. An integer.
+ strokeWidth: 4, // connection width (inner)
+ stroke: '#3c3f41', // connection color (inner)
+ outlineWidth: 2, // connection width (outer)
+ outlineStroke: '#63676a', // connection color (outer)
+ dashstyle: '0', // connection dashstyle (default) -> is used after connectionType got removed that has dashstyle specified
+ 'stroke-linecap': 'round' // connection shape
},
- Connector: [ 'Bezier', { curviness: 40 } ], // default connector style (this is not used!) all connections have their own style (by scope)
- Endpoint: [ 'Dot', { radius: 5 } ],
- ReattachConnections: false, // re-attach connection if dragged with mouse to "nowhere"
- Scope: Init.defaultMapScope, // default map scope for connections
+ Endpoint: ['Dot', {radius: 5}], // single endpoint (used during drag action)
+ Endpoints: [
+ ['Dot', {radius: 5, cssClass: config.endpointSourceClass}],
+ ['Dot', {radius: 5, cssClass: config.endpointTargetClass}]
+ ],
+ EndpointStyle: {fill: '#3c3f41', stroke: '#63676a', strokeWidth: 2}, // single endpoint style (used during drag action)
+ EndpointStyles: [
+ {fill: '#3c3f41', stroke: '#63676a', strokeWidth: 2},
+ {fill: '#3c3f41', stroke: '#63676a', strokeWidth: 2}
+ ],
+ Connector: ['Bezier', {curviness: 40}], // default connector style (this is not used!) all connections have their own style (by scope)
+ ReattachConnections: false, // re-attach connection if dragged with mouse to "nowhere"
+ Scope: Init.defaultMapScope, // default map scope for connections
LogEnabled: true
});
@@ -2181,6 +2195,13 @@ define([
});
+ // Notification an existing Connection is being dragged.
+ // Note that when this event fires for a brand new Connection, the target of the Connection is a transient element
+ // that jsPlumb is using for dragging, and will be removed from the DOM when the Connection is subsequently either established or aborted.
+ newJsPlumbInstance.bind('connectionDrag', function(info, e){
+
+ });
+
// Notification a Connection was detached.
// In the event that the Connection was new and had never been established between two Endpoints, it has a pending flag set on it.
newJsPlumbInstance.bind('connectionDetached', function(info, e){
@@ -2200,6 +2221,11 @@ define([
});
+ // Notification the current zoom was changed
+ newJsPlumbInstance.bind('zoom', function(zoom){
+ MapOverlay.updateZoomOverlay(this);
+ });
+
// ========================================================================================================
// Events for interactive CSS classes https://community.jsplumbtoolkit.com/doc/styling-via-css.html
//=========================================================================================================
@@ -2276,6 +2302,8 @@ define([
// get map container
let mapContainer = $(map.getContainer());
+ MapOverlay.initMapDebugOverlays(map);
+
// context menu for mapContainer
mapContainer.on('contextmenu', function(e){
e.preventDefault();
@@ -2472,14 +2500,14 @@ define([
// toggle "fullSize" Endpoint overlays for system (signature information) -------------------------------------
mapContainer.hoverIntent({
over: function(e){
- for(let overlayInfo of map.selectEndpoints({element: this}).getOverlay(MapOverlay.endpointOverlayId)){
+ for(let overlayInfo of map.selectEndpoints({element: this}).getOverlay(MapOverlayUtil.config.endpointOverlayId)){
if(overlayInfo[0] instanceof jsPlumb.Overlays.Label){
overlayInfo[0].fire('toggleSize', true);
}
}
},
out: function(e){
- for(let overlayInfo of map.selectEndpoints({element: this}).getOverlay(MapOverlay.endpointOverlayId)){
+ for(let overlayInfo of map.selectEndpoints({element: this}).getOverlay(MapOverlayUtil.config.endpointOverlayId)){
if(overlayInfo[0] instanceof jsPlumb.Overlays.Label){
overlayInfo[0].fire('toggleSize', false);
}
@@ -2526,7 +2554,7 @@ define([
}
// show map overlay info icon
- this.mapElement.getMapOverlay('info').updateOverlayIcon(this.mapOption.option, 'hide');
+ MapOverlayUtil.getMapOverlay(this.mapElement, 'info').updateOverlayIcon(this.mapOption.option, 'hide');
// delete map option
MapUtil.deleteLocalData('map', this.mapElement.data('id'), this.mapOption.option );
@@ -2545,7 +2573,7 @@ define([
}
// hide map overlay info icon
- this.mapElement.getMapOverlay('info').updateOverlayIcon(this.mapOption.option, 'show');
+ MapOverlayUtil.getMapOverlay(this.mapElement, 'info').updateOverlayIcon(this.mapOption.option, 'show');
// store map option
MapUtil.storeLocalData('map', this.mapElement.data('id'), this.mapOption.option, 1 );
@@ -2591,7 +2619,7 @@ define([
if(select){
let mapWrapper = mapElement.closest('.' + config.mapWrapperClass);
- mapWrapper.scrollToSystem(MapUtil.getSystemPosition(system));
+ Scrollbar.scrollToSystem(mapWrapper, MapUtil.getSystemPosition(system));
// select system
MapUtil.showSystemInfo(map, system);
}
@@ -2622,7 +2650,7 @@ define([
// update "local" overlay for this map
mapContainer.on('pf:updateLocal', function(e, userData){
let mapElement = $(this);
- let mapOverlay = mapElement.getMapOverlay('local');
+ let mapOverlay = MapOverlayUtil.getMapOverlay(mapElement, 'local');
if(userData && userData.config && userData.config.id){
let currentMapData = Util.getCurrentMapData(userData.config.id);
@@ -2826,7 +2854,7 @@ define([
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()){
+ if(!MapOverlayUtil.getMapOverlayInterval(mapContainer)){
mapData = mapContainer.getMapDataFromClient(filter, minimal);
}
return mapData;
@@ -3044,6 +3072,96 @@ define([
mapWrapperElement.initCustomScrollbar({
callbacks: {
+ onInit: function(){
+ // init 'space' key + 'mouse' down for map scroll -------------------------------------------------
+ let scrollStart = [0, 0];
+ let mouseStart = [0, 0];
+ let mouseOffset = [0, 0];
+
+ let animationFrameId = 0;
+
+ let toggleDragScroll = active => {
+ mapElement.toggleClass('disabled', active).toggleClass(' pf-map-move', active);
+ };
+
+ let stopDragScroll = () => {
+ cancelAnimationFrame(animationFrameId);
+ animationFrameId = 0;
+ scrollStart = [0, 0];
+ mouseStart = [0, 0];
+ mouseOffset = [0, 0];
+ };
+
+ let dragScroll = () => {
+ if(Key.isActive(' ')){
+ let scrollOffset = [
+ Math.max(0, scrollStart[0] - mouseOffset[0]),
+ Math.max(0, scrollStart[1] - mouseOffset[1])
+ ];
+
+ if(
+ scrollOffset[0] !== Math.abs(this.mcs.left) ||
+ scrollOffset[1] !== Math.abs(this.mcs.top)
+ ){
+ Scrollbar.scrollToPosition(this, [scrollOffset[1], scrollOffset[0]], {
+ scrollInertia: 0,
+ scrollEasing: 'linear',
+ timeout: 5
+ });
+ }
+
+ // recursive re-call on next render
+ animationFrameId = requestAnimationFrame(dragScroll);
+ }
+ };
+
+ let keyDownHandler = function(e){
+ if(e.keyCode === 32){
+ e.preventDefault();
+ toggleDragScroll(true);
+ }
+ };
+ let keyUpHandler = function(e){
+ if(e.keyCode === 32){
+ e.preventDefault();
+ toggleDragScroll(false);
+ }
+ };
+ let mouseMoveHandler = function(e){
+ if(animationFrameId){
+ mouseOffset[0] = e.clientX - mouseStart[0];
+ mouseOffset[1] = e.clientY - mouseStart[1];
+ }
+
+ // space activated on mouse move
+ toggleDragScroll(Key.isActive(' '));
+ };
+
+ let mouseDownHandler = function(e){
+ if(!animationFrameId && e.which === 1 && Key.isActive(' ')){
+ scrollStart[0] = Math.abs(this.mcs.left);
+ scrollStart[1] = Math.abs(this.mcs.top);
+ mouseStart[0] = e.clientX;
+ mouseStart[1] = e.clientY;
+
+ toggleDragScroll(true);
+
+ animationFrameId = requestAnimationFrame(dragScroll);
+ }
+ };
+
+ let mouseUpHandler = function(e){
+ if(e.which === 1){
+ stopDragScroll();
+ }
+ };
+
+ this.addEventListener('keydown', keyDownHandler, { capture: false });
+ this.addEventListener('keyup', keyUpHandler, { capture: false });
+ this.addEventListener('mousemove', mouseMoveHandler, { capture: false });
+ this.addEventListener('mousedown', mouseDownHandler, { capture: false });
+ this.addEventListener('mouseup', mouseUpHandler, { capture: false });
+ },
onScroll: function(){
// scroll complete
// update scroll position for drag-frame-selection
@@ -3070,7 +3188,6 @@ define([
// add map overlays after scrollbar is initialized
// because of its absolute position
mapWrapperElement.initMapOverlays();
-
mapWrapperElement.initLocalOverlay(mapId);
};
diff --git a/js/app/map/overlay.js b/js/app/map/overlay/overlay.js
similarity index 52%
rename from js/app/map/overlay.js
rename to js/app/map/overlay/overlay.js
index f720df19..524efbb1 100644
--- a/js/app/map/overlay.js
+++ b/js/app/map/overlay/overlay.js
@@ -6,36 +6,11 @@ define([
'jquery',
'app/init',
'app/util',
+ 'app/map/overlay/util',
'app/map/util'
-], ($, Init, Util, MapUtil) => {
+], ($, Init, Util, MapOverlayUtil, MapUtil) => {
'use strict';
- let config = {
- logTimerCount: 3, // map log timer in seconds
-
- // map overlay positions
- mapOverlayClass: 'pf-map-overlay', // class for all map overlays
- mapOverlayTimerClass: 'pf-map-overlay-timer', // class for map overlay timer e.g. map timer
- mapOverlayInfoClass: 'pf-map-overlay-info', // class for map overlay info e.g. map info
- overlayLocalClass: 'pf-map-overlay-local', // class for map overlay "local" table
-
- // system
- systemHeadClass: 'pf-system-head', // class for system head
-
- // overlay IDs
- connectionOverlayWhId: 'pf-map-connection-wh-overlay', // connection WH overlay ID (jsPlumb)
- connectionOverlayEolId: 'pf-map-connection-eol-overlay', // connection EOL overlay ID (jsPlumb)
- connectionOverlayArrowId: 'pf-map-connection-arrow-overlay', // connection Arrows overlay ID (jsPlumb)
-
- endpointOverlayId: 'pf-map-endpoint-overlay', // endpoint overlay ID (jsPlumb)
-
- // overlay classes
- componentOverlayClass: 'pf-map-component-overlay', // class for "normal size" overlay
-
- connectionArrowOverlayClass: 'pf-map-connection-arrow-overlay', // class for "connection arrow" overlay
- connectionDiamondOverlayClass: 'pf-map-connection-diamond-overlay' // class for "connection diamond" overlay
- };
-
/**
* get MapObject (jsPlumb) from mapElement
* @param mapElement
@@ -43,7 +18,7 @@ define([
*/
let getMapObjectFromMapElement = mapElement => {
let Map = require('app/map/map');
- return Map.getMapInstance( mapElement.data('id') );
+ return Map.getMapInstance(mapElement.data('id'));
};
/**
@@ -53,8 +28,7 @@ define([
*/
let getMapObjectFromOverlayIcon = overlayIcon => {
let mapElement = Util.getMapElementFromOverlay(overlayIcon);
-
- return getMapObjectFromMapElement( mapElement );
+ return getMapObjectFromMapElement(mapElement);
};
/**
@@ -65,127 +39,164 @@ define([
let addEndpointOverlaySignatureLabel = (endpoint, labelData) => {
let label = labelData.labels.join(', ');
let name = labelData.names.join(', ');
+ let overlay = endpoint.getOverlay(MapOverlayUtil.config.endpointOverlayId);
- endpoint.addOverlay([
- 'Label',
- {
- label: MapUtil.formatEndpointOverlaySignatureLabel(label),
- id: config.endpointOverlayId,
- cssClass: [config.componentOverlayClass, label.length ? 'small' : 'icon'].join(' '),
- location: MapUtil.getEndpointOverlaySignatureLocation(endpoint, label),
- events: {
- toggleSize: function(fullSize){
- let signatureName = this.getParameter('signatureName');
- if(fullSize && !this.getParameter('fullSize') && signatureName){
- this.setLabel(this.getLabel() + '
' + '' + signatureName + '');
- this.setParameter('fullSize', true);
- }else if(this.getParameter('fullSize')){
- this.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(this.getParameter('label')));
- this.setParameter('fullSize', false);
- }
- }
- },
- parameters: {
- fullSize: false,
- label: label,
- signatureName: name
- }
- }
- ]);
- };
-
- /**
- * add overlays to connections (signature based data)
- * @param connections
- * @param connectionsData
- */
- let addConnectionsOverlay = (connections, connectionsData) => {
- let SystemSignatures = require('app/ui/module/system_signature');
-
- // loop through all map connections (get from DOM)
- for(let connection of connections){
- let connectionId = connection.getParameter('connectionId');
- let sourceEndpoint = connection.endpoints[0];
- let targetEndpoint = connection.endpoints[1];
-
- let signatureTypeData = {
- source: {
- names: [],
- labels: []
- },
- target: {
- names: [],
- labels: []
- }
- };
-
- // ... find matching connectionData (from Ajax)
- for(let connectionData of connectionsData){
- if(connectionData.id === connectionId){
- signatureTypeData = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
- // ... connection matched -> continue with next one
- break;
- }
- }
-
- // add endpoint overlays ------------------------------------------------------
- addEndpointOverlaySignatureLabel(sourceEndpoint, signatureTypeData.source);
- addEndpointOverlaySignatureLabel(targetEndpoint, signatureTypeData.target);
-
- let sourceLabel = signatureTypeData.source.labels;
- let targetLabel = signatureTypeData.target.labels;
-
- // add arrow (connection) overlay that points from "XXX" => "K162" ------------
- let overlayType = 'Diamond'; // not specified
- let arrowDirection = 1;
-
+ if(overlay instanceof jsPlumb.Overlays.Label){
+ // update existing overlay
if(
- (sourceLabel.indexOf('K162') !== -1 && targetLabel.indexOf('K162') !== -1) ||
- (sourceLabel.length === 0 && targetLabel.length === 0) ||
- (
- sourceLabel.length > 0 && targetLabel.length > 0 &&
- sourceLabel.indexOf('K162') === -1 && targetLabel.indexOf('K162') === -1
- )
+ label !== overlay.getParameter('label') ||
+ name !== overlay.getParameter('signatureName')
){
- // unknown direction
- overlayType = 'Diamond'; // not specified
- arrowDirection = 1;
- }else if(
- (sourceLabel.indexOf('K162') !== -1) ||
- (sourceLabel.length === 0 && targetLabel.indexOf('K162') === -1)
- ){
- // convert default arrow direction
- overlayType = 'Arrow';
- arrowDirection = -1;
- }else{
- // default arrow direction is fine
- overlayType = 'Arrow';
- arrowDirection = 1;
+ // update label only on label changes
+ overlay.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(label));
+ overlay.setParameter('fullSize', false);
+ overlay.setParameter('label', label);
+ overlay.setParameter('signatureName', name);
+ overlay.updateClasses(label.length ? 'small' : 'icon', label.length ? 'icon' : 'small');
+ overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, label));
}
-
- connection.addOverlay([
- overlayType,
+ }else{
+ // add new overlay
+ endpoint.addOverlay([
+ 'Label',
{
- width: 12,
- length: 15,
- location: 0.5,
- foldback: 0.85,
- direction: arrowDirection,
- id: config.connectionOverlayArrowId,
- cssClass: (overlayType === 'Arrow') ? config.connectionArrowOverlayClass : config.connectionDiamondOverlayClass
+ label: MapUtil.formatEndpointOverlaySignatureLabel(label),
+ id: MapOverlayUtil.config.endpointOverlayId,
+ cssClass: [MapOverlayUtil.config.componentOverlayClass, label.length ? 'small' : 'icon'].join(' '),
+ location: MapUtil.getEndpointOverlaySignatureLocation(endpoint, label),
+ events: {
+ toggleSize: function(fullSize){
+ let signatureName = this.getParameter('signatureName');
+ if(fullSize && !this.getParameter('fullSize') && signatureName){
+ this.setLabel(this.getLabel() + '
' + '' + signatureName + '');
+ this.setParameter('fullSize', true);
+ }else if(this.getParameter('fullSize')){
+ this.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(this.getParameter('label')));
+ this.setParameter('fullSize', false);
+ }
+ }
+ },
+ parameters: {
+ fullSize: false,
+ label: label,
+ signatureName: name
+ }
}
]);
-
}
};
/**
- * remove overviews from a Tooltip
- * @param endpoint
- * @param i
+ * add overlays to connections (signature based data)
+ * @param map
+ * @param connectionsData
*/
- let removeEndpointOverlay = (endpoint, i) => {
- endpoint.removeOverlays(config.endpointOverlayId);
+ let updateInfoSignatureOverlays = (map, connectionsData) => {
+ let type = 'info_signature';
+ let SystemSignatures = require('app/ui/module/system_signature');
+
+ connectionsData = Util.arrayToObject(connectionsData);
+
+ map.batch(function(){
+ map.getAllConnections().forEach(function(connection){
+ let connectionId = connection.getParameter('connectionId');
+ let sourceEndpoint = connection.endpoints[0];
+ let targetEndpoint = connection.endpoints[1];
+
+ let signatureTypeData = {
+ source: {
+ names: [],
+ labels: []
+ },
+ target: {
+ names: [],
+ labels: []
+ }
+ };
+
+ if(connection.scope === 'wh'){
+ if(!connection.hasType(type)){
+ connection.addType(type);
+ }
+
+ let overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
+
+ // Arrow overlay needs to be cleared() (removed) if 'info_signature' gets removed!
+ // jsPlumb does not handle overlay updates for Arrow overlays... so we need to re-apply the the overlay manually
+ if(overlayArrow.path && !overlayArrow.path.isConnected){
+ connection.canvas.appendChild(overlayArrow.path);
+ }
+
+ let overlayType = 'Diamond'; // not specified
+ let arrowDirection = 1;
+ let arrowFoldback = 2;
+
+ if(connectionsData.hasOwnProperty(connectionId)){
+ // signature data found for current connection
+ signatureTypeData = MapUtil.getConnectionDataFromSignatures(connection, connectionsData[connectionId]);
+
+ let sourceLabel = signatureTypeData.source.labels;
+ let targetLabel = signatureTypeData.target.labels;
+
+ // add arrow (connection) overlay that points from "XXX" => "K162" ------------------------------------
+ if(
+ (sourceLabel.indexOf('K162') !== -1 && targetLabel.indexOf('K162') !== -1) ||
+ (sourceLabel.length === 0 && targetLabel.length === 0) ||
+ (
+ sourceLabel.length > 0 && targetLabel.length > 0 &&
+ sourceLabel.indexOf('K162') === -1 && targetLabel.indexOf('K162') === -1
+ )
+ ){
+ // unknown direction
+ overlayType = 'Diamond'; // not specified
+ arrowDirection = 1;
+ arrowFoldback = 2;
+ }else if(
+ (sourceLabel.indexOf('K162') !== -1) ||
+ (sourceLabel.length === 0 && targetLabel.indexOf('K162') === -1)
+ ){
+ // convert default arrow direction
+ overlayType = 'Arrow';
+ arrowDirection = -1;
+ arrowFoldback = 0.8;
+ }else{
+ // default arrow direction is fine
+ overlayType = 'Arrow';
+ arrowDirection = 1;
+ arrowFoldback = 0.8;
+ }
+ }
+
+ // class changes must be done on "connection" itself not on "overlayArrow"
+ // -> because Arrow might not be rendered to map at this point (if it does not exist already)
+ if(overlayType === 'Arrow'){
+ connection.updateClasses(
+ MapOverlayUtil.config.connectionArrowOverlaySuccessClass,
+ MapOverlayUtil.config.connectionArrowOverlayDangerClass
+ );
+ }else{
+ connection.updateClasses(
+ MapOverlayUtil.config.connectionArrowOverlayDangerClass,
+ MapOverlayUtil.config.connectionArrowOverlaySuccessClass
+ );
+ }
+
+ overlayArrow.updateFrom({
+ direction: arrowDirection,
+ foldback: arrowFoldback
+ });
+
+ // add endpoint overlays --------------------------------------------------------------------------
+ addEndpointOverlaySignatureLabel(sourceEndpoint, signatureTypeData.source);
+ addEndpointOverlaySignatureLabel(targetEndpoint, signatureTypeData.target);
+ }else{
+ // connection is not 'wh' scope
+ if(connection.hasType(type)){
+ connection.removeType(type);
+ }
+ }
+ });
+ });
};
/**
@@ -237,11 +248,10 @@ define([
/**
* git signature data that is linked to a connection for a mapId
* @param mapElement
- * @param connections
* @param callback
*/
- let getConnectionSignatureData = (mapElement, connections, callback) => {
- let mapOverlay = $(mapElement).getMapOverlay('info');
+ let getConnectionSignatureData = (mapElement, callback) => {
+ let mapOverlay = MapOverlayUtil.getMapOverlay(mapElement, 'info');
let overlayConnectionIcon = mapOverlay.find('.pf-map-overlay-endpoint');
showLoading(overlayConnectionIcon);
@@ -259,46 +269,48 @@ define([
dataType: 'json',
context: {
mapElement: mapElement,
- connections: connections,
overlayConnectionIcon: overlayConnectionIcon
}
}).done(function(connectionsData){
- // hide all connection before add them (refresh)
- this.mapElement.hideEndpointOverlays();
- // ... add overlays
- callback(this.connections, connectionsData);
+ let map = getMapObjectFromMapElement(this.mapElement);
+ callback(map, connectionsData);
}).always(function(){
hideLoading(this.overlayConnectionIcon);
});
};
/**
- * showEndpointOverlays
+ * showInfoSignatureOverlays
* -> used by "refresh" overlays (hover) AND/OR initial menu trigger
*/
- $.fn.showEndpointOverlays = function(){
+ $.fn.showInfoSignatureOverlays = function(){
let mapElement = $(this);
- let map = getMapObjectFromMapElement(mapElement);
- let MapUtil = require('app/map/util');
- let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', undefined, true);
-
- // get connection signature information ---------------------------------------
- getConnectionSignatureData(mapElement, connections, addConnectionsOverlay);
+ getConnectionSignatureData(mapElement, updateInfoSignatureOverlays);
};
/**
- * hideEndpointOverlays
- * -> see showEndpointOverlays()
+ * hideInfoSignatureOverlays
+ * -> see showInfoSignatureOverlays()
*/
- $.fn.hideEndpointOverlays = function(){
+ $.fn.hideInfoSignatureOverlays = function(){
let map = getMapObjectFromMapElement($(this));
- let MapUtil = require('app/map/util');
- let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
+ let type = 'info_signature';
- for(let connection of connections){
- connection.removeOverlays(config.connectionOverlayArrowId);
- connection.endpoints.forEach(removeEndpointOverlay);
- }
+ map.batch(function(){
+ map.getAllConnections().forEach(function(connection){
+ let overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
+
+ if(overlayArrow){
+ overlayArrow.cleanup();
+ }
+
+ if(connection.hasType(type)){
+ connection.removeType(type, {}, true);
+ }
+ });
+
+ map.selectEndpoints().removeOverlay(MapOverlayUtil.config.endpointOverlayId);
+ });
};
/**
@@ -343,7 +355,7 @@ define([
hoverIntent: {
over: function(e){
let mapElement = Util.getMapElementFromOverlay(this);
- mapElement.find('.' + config.systemHeadClass).each(function(){
+ mapElement.find('.' + MapOverlayUtil.config.systemHeadClass).each(function(){
let systemHead = $(this);
// init popover if not already exists
if(!systemHead.data('bs.popover')){
@@ -366,7 +378,7 @@ define([
},
out: function(e){
let mapElement = Util.getMapElementFromOverlay(this);
- mapElement.find('.' + config.systemHeadClass).popover('hide');
+ mapElement.find('.' + MapOverlayUtil.config.systemHeadClass).popover('hide');
}
}
},
@@ -378,7 +390,7 @@ define([
hoverIntent: {
over: function(e){
let mapElement = Util.getMapElementFromOverlay(this);
- mapElement.showEndpointOverlays();
+ mapElement.showInfoSignatureOverlays();
},
out: function(e){
// just "refresh" on hover
@@ -399,11 +411,10 @@ define([
hoverIntent: {
over: function(e){
let map = getMapObjectFromOverlayIcon(this);
- let MapUtil = require('app/map/util');
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
let serverDate = Util.getServerTime();
- // show connection overlays ---------------------------------------------------
+ // show connection overlays -----------------------------------------------------------------------
for(let connection of connections){
let createdTimestamp = connection.getParameter('created');
let updatedTimestamp = connection.getParameter('updated');
@@ -420,13 +431,13 @@ define([
' ' + formatTimeParts(updatedDiff)
];
- // add label overlay ------------------------------------------------------
+ // add label overlay --------------------------------------------------------------------------
connection.addOverlay([
'Label',
{
label: labels.join('
'),
- id: config.connectionOverlayWhId,
- cssClass: [config.componentOverlayClass, 'small'].join(' '),
+ id: MapOverlayUtil.config.connectionOverlayWhId,
+ cssClass: [MapOverlayUtil.config.componentOverlayClass, 'small'].join(' '),
location: 0.35
}
]);
@@ -434,11 +445,10 @@ define([
},
out: function(e){
let map = getMapObjectFromOverlayIcon(this);
- let MapUtil = require('app/map/util');
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
for(let connection of connections){
- connection.removeOverlays(config.connectionOverlayWhId);
+ connection.removeOverlay(MapOverlayUtil.config.connectionOverlayWhId);
}
}
}
@@ -451,7 +461,6 @@ define([
hoverIntent: {
over: function(e){
let map = getMapObjectFromOverlayIcon(this);
- let MapUtil = require('app/map/util');
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
let serverDate = Util.getServerTime();
@@ -464,8 +473,8 @@ define([
'Label',
{
label: ' ' + formatTimeParts(diff),
- id: config.connectionOverlayEolId,
- cssClass: [config.componentOverlayClass, 'eol'].join(' '),
+ id: MapOverlayUtil.config.connectionOverlayEolId,
+ cssClass: [MapOverlayUtil.config.componentOverlayClass, 'eol'].join(' '),
location: 0.25
}
]);
@@ -473,53 +482,26 @@ define([
},
out: function(e){
let map = getMapObjectFromOverlayIcon(this);
- let MapUtil = require('app/map/util');
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
for(let connection of connections){
- connection.removeOverlay(config.connectionOverlayEolId);
+ connection.removeOverlay(MapOverlayUtil.config.connectionOverlayEolId);
}
}
}
}
};
- /**
- * get map overlay element by type e.g. timer/counter, info - overlay
- * @param overlayType
- * @returns {*}
- */
- $.fn.getMapOverlay = function(overlayType){
- let mapWrapperElement = $(this).parents('.' + MapUtil.config.mapWrapperClass);
-
- let mapOverlay = null;
- switch(overlayType){
- case 'timer':
- mapOverlay = mapWrapperElement.find('.' + config.mapOverlayTimerClass);
- break;
- case 'info':
- mapOverlay = mapWrapperElement.find('.' + config.mapOverlayInfoClass);
- break;
- case 'local':
- mapOverlay = mapWrapperElement.find('.' + config.overlayLocalClass);
- break;
- }
-
- return mapOverlay;
- };
-
/**
* draws the map update counter to the map overlay timer
+ * @param mapOverlayTimer
* @param percent
* @param value
* @returns {*}
*/
- $.fn.setMapUpdateCounter = function(percent, value){
-
- let mapOverlayTimer = $(this);
-
+ let setMapUpdateCounter = (mapOverlayTimer, percent, value) => {
// check if counter already exists
- let counterChart = mapOverlayTimer.getMapCounter();
+ let counterChart = MapOverlayUtil.getMapCounter(mapOverlayTimer);
if(counterChart.length === 0){
// create new counter
@@ -546,27 +528,14 @@ define([
return counterChart;
};
- /**
- * get the map counter chart from overlay
- * @returns {JQuery|*|T|{}|jQuery}
- */
- $.fn.getMapCounter = function(){
- return $(this).find('.' + Init.classes.pieChart.pieChartMapCounterClass);
- };
-
- $.fn.getMapOverlayInterval = function(){
- return $(this).getMapOverlay('timer').getMapCounter().data('interval');
- };
-
/**
* start the map update counter or reset
*/
$.fn.startMapUpdateCounter = function(){
-
let mapOverlayTimer = $(this);
- let counterChart = mapOverlayTimer.getMapCounter();
+ let counterChart = MapOverlayUtil.getMapCounter(mapOverlayTimer);
- let maxSeconds = config.logTimerCount;
+ let maxSeconds = MapOverlayUtil.config.logTimerCount;
let counterChartLabel = counterChart.find('span');
@@ -709,6 +678,154 @@ define([
}
};
+ /**
+ * update map zoom overlay information
+ * @param map
+ */
+ let updateZoomOverlay = map => {
+ let zoom = map.getZoom();
+ let zoomPercent = Math.round(zoom * 1000) / 10;
+ let zoomOverlay = MapOverlayUtil.getMapOverlay(map.getContainer(), 'zoom');
+ let zoomValue = zoomOverlay.find('.' + MapOverlayUtil.config.zoomOverlayValueClass);
+ let zoomUp = zoomOverlay.find('.' + MapOverlayUtil.config.zoomOverlayUpClass);
+ let zoomDown = zoomOverlay.find('.' + MapOverlayUtil.config.zoomOverlayDownClass);
+ zoomValue.toggleClass('active', zoom !== 1).text(zoomPercent);
+ zoomUp.toggleClass('disabled', zoom >= MapUtil.config.zoomMax);
+ zoomDown.toggleClass('disabled', zoom <= MapUtil.config.zoomMin);
+ };
+
+ /**
+ * map debug overlays for connections/endpoints
+ * -> requires manual added "debug" GET param to URL
+ * @param map
+ */
+ let initMapDebugOverlays = map => {
+ let url = new URL(window.location.href);
+ if(url.searchParams.has('debug')){
+ let mapContainer = $(map.getContainer());
+
+ // debug map overlays for connection/endpoints
+ mapContainer.on('mouseover', '.jtk-connector', function(e){
+ e.stopPropagation();
+
+ if(e.target.classList.contains('jtk-connector-outline')){
+ let connection = e.currentTarget._jsPlumb;
+ // show debug overlay only if there is no active debug
+ if(!connection.getOverlay(MapOverlayUtil.config.debugOverlayId)){
+ // find nearby connections
+ let connections = [];
+ let endpoints = [];
+ let hasComponentId = id => {
+ return component => component.id === id;
+ };
+
+ for(let endpoint of connection.endpoints){
+ let connectionsInfo = map.anchorManager.getConnectionsFor(endpoint.elementId);
+ for(let connectionInfo of connectionsInfo){
+ if(!connections.some(hasComponentId(connectionInfo[0].id))){
+ connections.push(connectionInfo[0]);
+ for(let endpointTemp of connectionInfo[0].endpoints){
+ if(!endpoints.some(hasComponentId(endpointTemp.id))){
+ endpoints.push(endpointTemp);
+ }
+ }
+ }
+ }
+ }
+
+ let createConnectionOverlay = connection => {
+ let data = MapUtil.getDataByConnection(connection);
+
+ let html = '
| ' + connection.id + ' | ' + data.id + ' |
| Scope: | ' + data.scope + ' |
| Type: | ' + data.type.toString() + ' |
| ' + endpoint.id + ' | |
| Scope: | ' + endpoint.scope + ' |
| Type: | ' + types.toString() + ' |
| ' + connection.id + ' | ' + data.id + ' |
| Scope: | ' + data.scope + ' |
| Type: | ' + data.type.toString() + ' |
| ' + endpoint.id + ' | |
| Scope: | ' + endpoint.scope + ' |
| Type: | ' + types.toString() + ' |