http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6502523b/console/test/js/qdrTopology.js ---------------------------------------------------------------------- diff --git a/console/test/js/qdrTopology.js b/console/test/js/qdrTopology.js deleted file mode 100644 index 89ea7b3..0000000 --- a/console/test/js/qdrTopology.js +++ /dev/null @@ -1,2140 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ -/** - * @module QDR - */ -var QDR = (function(QDR) { - - QDR.module.controller('QDR.TopologyFormController', function($scope, QDRService) { - - $scope.attributes = [] - var nameTemplate = '<div title="{{row.entity.description}}" class="ngCellText"><span>{{row.entity.attributeName}}</span></div>'; - var valueTemplate = '<div title="{{row.entity.attributeValue}}" class="ngCellText"><span>{{row.entity.attributeValue}}</span></div>'; - $scope.topoGridOptions = { - data: 'attributes', - enableColumnResize: false, - multiSelect: false, - columnDefs: [{ - field: 'attributeName', - displayName: 'Attribute', - cellTemplate: nameTemplate - }, { - field: 'attributeValue', - displayName: 'Value', - cellTemplate: valueTemplate - }] - }; - $scope.form = '' - $scope.$on('showEntityForm', function(event, args) { - var attributes = args.attributes; - var entityTypes = QDRService.schema.entityTypes[args.entity].attributes; - attributes.forEach(function(attr) { - if (entityTypes[attr.attributeName] && entityTypes[attr.attributeName].description) - attr.description = entityTypes[attr.attributeName].description - }) - $scope.attributes = attributes; - $scope.form = args.entity; - }) - $scope.$on('showAddForm', function(event) { - //$scope.form = 'add'; - }) - }) - - /** - * @method TopologyController - * - * Controller that handles the QDR topology page - */ - QDR.module.controller("QDR.TopologyController", ['$scope', '$rootScope', 'QDRService', '$location', '$timeout', '$dialog', - function($scope, $rootScope, QDRService, $location, $timeout, $dialog) { - - $scope.baseName = "R" - $scope.clientAddress = "addr1" - $scope.panelVisible = true // show/hide the panel on the left - $scope.multiData = [] - $scope.selectedClient = []; - $scope.quiesceState = {} - var dontHide = false; - - $( document ).ready(function() { - - d3.select(".qdr-topology.pane.left") - .style("left" , "-480px") - d3.select(".panel-adjacent") - .style("margin-left", "10px") - return; - var isPaneHidden = localStorage["topoPanel"]; - if (isPaneHidden) { - $scope.panelVisible = false - d3.select(".qdr-topology.pane.left") - .style("left" , "-380px") - d3.select(".panel-adjacent") - .style("margin-left", "30px") - } - }); - $scope.hideLeftPane = function (duration) { - localStorage["topoPanel"] = "hide" - d3.select(".qdr-topology.pane.left") - .transition().duration(300).ease("sin-in") - .style("left" , "-380px") - - d3.select(".panel-adjacent") - .transition().duration(300).ease("sin-in") - .style("margin-left", "30px") - .each("end", function () { - resize() - $timeout(function () {QDR.log.debug("done with transition. setting scope ");$scope.panelVisible = false}) - }) - } - $scope.showLeftPane = function () { - localStorage.removeItem("topoPanel"); - d3.select(".qdr-topology.pane.left") - .transition().duration(300).ease("sin-out") - .style("left" , "0px") - - d3.select(".panel-adjacent") - .transition().duration(300).ease("sin-out") - .style("margin-left", "430px") - .each("end", function () { - resize() - $timeout(function () {QDR.log.debug("done with transition. setting scope ");$scope.panelVisible = true}) - }) - } - - $scope.Publish = function () { - var props = {nodes: nodes, links: links, topology: $scope.mockTopologyDir} - QDRService.sendMethod("amqp:///publish/", "", [], "PUBLISH", props, function (nodeName, entity, response, context) { - QDR.log.debug("method response " + response) - Core.notification('info', props.topology + " published"); - }) - } - - function sourceTarget(skey, tkey, stype, ttype) { - stype = stype || "inter-router" - ttype = ttype || "inter-router" - var source = nodes.findIndex( function (n) { - return (n.key === skey && n.nodeType === stype) - }) - var target = nodes.findIndex ( function (n) { - return (n.key === tkey && n.nodeType === ttype) - }) - return {source: source, target: target} - } - - $scope.Duplicate = function () { - var nodeBase = maxNodeIndex() - var maxx = 0 - var minx = width - radiusNormal - nodes.forEach (function (n1) { - if (n1.x > maxx) - maxx = n1.x - if (n1.x < minx) - minx = n1.x - }) - var curNodesLen = nodes.length - var baseName - var name - for (var i=0; i<curNodesLen; ++i) { - var x = maxx + radius*3 + nodes[i].x - minx - var y = nodes[i].y - - if (nodes[i].nodeType !== "inter-router") { - // this is a client - // find the parent router node - var ni = nodes.findIndex( function (n) { - return n.nodeType === 'inter-router' && n.key === nodes[i].key - }) - - var parentOffset = i - ni - baseName = nodes[i+curNodesLen-parentOffset].name - var nameParts = nodes[i].name.split('.') - name = baseName + "." + nameParts[nameParts.length-1] - } else { - baseName = genNewName() - name = baseName - } - - var id = "amqp:/_topo/0/" + baseName + "/$management"; - var node = aNode(id, name, nodes[i].nodeType, undefined, nodes.length, x, y, undefined, false) - if (node.nodeType !== 'inter-router') { - node.user = nodes[i].user - node.isEncrypted = nodes[i].isEncrypted - node.host = nodes[i].host - node.connectionId = node.id - node.cdir = nodes[i].cdir - node.normals = [] - for (var n=0; n<nodes[i].normals.length; ++n) { - var nameParts = nodes[i].normals[n].name.split('.') - var normalName = baseName + "." + nameParts[nameParts.length-1] - node.normals.push({name: normalName, addr: nodes[i].normals[n].addr}) - } - } - nodes.push(node); - } - var curLinksLen = links.length - for (var i=0; i<curLinksLen; ++i) { - var source = links[i].source.id + curNodesLen - var target = links[i].target.id + curNodesLen - var left = links[i].left - var right = links[i].right - var dir = "out" - if (left && right) - dir = "both" - else if (left) - dir = "in" - var cls = links[i].cls - var uid = source + "." + target - getLink(source, target, dir, cls, uid) - } - force.nodes(nodes).links(links).start(); - restart(); - } - - $scope.Clear = function () { - nodes = [] - links = [] - force.nodes(nodes).links(links).start(); - restart(); - } - - var fixIds = function (list) { - list.forEach( function (l, i) { - l.id = i - }) - } - var fixUids = function (list) { - list.forEach( function (l, i) { - l.uid = l.source.id + "." + l.target.id - }) - } - - $scope.delNode = function () { - var i = nodes.length - while (i--) { - if (nodes[i].name === $scope.contextNode.name) { - if (selected_node && selected_node.name === nodes[i].name) - selected_node = null - nodes.splice(i, 1) - } - } - fixIds(nodes) - - var i = links.length - while (i--) { - if (links[i].source.name === $scope.contextNode.name || links[i].target.name === $scope.contextNode.name) { - links.splice(i, 1) - } - } - fixUids(links) - - initGraph() - initForce() - restart(); - } - $scope.$watch('mockTopologyDir', function(newVal, oldVal) { - if (oldVal != newVal) { - switchTopology(newVal) - } - }) - - var switchTopology = function (topology) { - var props = {topology: topology} - QDRService.sendMethod("amqp:///switch/", "", [], "SWITCH", props, function (nodeName, entity, response, context) { - QDRService.addUpdatedAction("afterSwitch", function () { - QDRService.delUpdatedAction("afterSwitch") - $timeout(setupInitialUpdate) - }) - QDRService.topology.get() - -/* - $scope.mockTopologyDir = response.topology - nodes = response.nodes - links = response.links - initGraph() - initForce() - initLegend() - restart() -*/ - QDR.log.debug("method response " + response) - Core.notification('info', "switched to " + props.topology); - }) - } - - var port = 20000 - var connectionId = 1 - $scope.addToNode = function (type) { - var id = $scope.contextNode.key - var clients = nodes.filter ( function (node) { - return node.nodeType !== 'inter-router' && node.routerId === $scope.contextNode.name - }) - var clientLen = 0 - clients.forEach (function (client) { - clientLen += client.normals.length - }) - var dir = "out" - if (type === 'sender') - dir = "in" - else if (type === 'console' || type === 'both') - dir = "both" - var siblings = nodes.filter( function (n) { - var pass = n.nodeType !== "inter-router" && n.key === id && n.cdir === dir - if (pass) { - if ((type === 'console' && !n.properties.console_identifier) || - (type !== 'console' && n.properties.console_identifier)) - pass = false - } - return pass - }) - var name = $scope.contextNode.name + "." + (clientLen + 1) - if (!siblings.length) { - var properties = type === 'console' ? {console_identifier: "Dispatch console"} : {} - var node = aNode(id, name, "normal", undefined, nodes.length, $scope.contextNode.x, $scope.contextNode.y - radius - radiusNormal, - $scope.contextNode.id, false, properties) - node.user = "anonymous" - node.isEncrypted = false - node.host = "0.0.0.0:" + port - node.connectionId = node.id - node.cdir = dir - node.normals = [{name: node.name, addr: $scope.clientAddress}] - nodes.push(node) - - var uid = "connection/" + node.host + ":" + node.connectionId - getLink($scope.contextNode.id, nodes.length-1, dir, "small", uid); - ++port - ++connectionId - } else { - siblings[0].normals.push({name: name, addr: $scope.clientAddress}) - //siblings[0].name = siblings[0].routerId + "." + siblings[0].id + "." + siblings[0].normals.length - } - force.nodes(nodes).links(links).start(); - initLegend() - restart(); - } - - if (!QDRService.connected) { - // we are not connected. we probably got here from a bookmark or manual page reload - QDRService.redirectWhenConnected("topology"); - return; - } - // we are currently connected. setup a handler to get notified if we are ever disconnected - QDRService.addDisconnectAction(function() { - QDRService.redirectWhenConnected("topology"); - $scope.$apply(); - }) - - var urlPrefix = $location.absUrl(); - urlPrefix = urlPrefix.split("#")[0] - QDR.log.debug("started QDR.TopologyController with urlPrefix: " + urlPrefix); - - $scope.addingNode = { - step: 0, - hasLink: false, - trigger: '' - }; - - $scope.cancel = function() { - $scope.addingNode.step = 0; - } - - var NewRouterName = "__NEW__"; - // mouse event vars - var selected_node = null, - selected_link = null, - mousedown_link = null, - mousedown_node = null, - mouseover_node = null, - mouseup_node = null, - initial_mouse_down_position = null; - - $scope.schema = "Not connected"; - - $scope.modes = [{ - title: 'Topology view', - name: 'Diagram', - right: false - }, - /* {title: 'Add a new router node', name: 'Add Router', right: true} */ - ]; - $scope.mode = "Diagram"; - $scope.contextNode = null; // node that is associated with the current context menu - - $scope.isModeActive = function(name) { - if ((name == 'Add Router' || name == 'Diagram') && $scope.addingNode.step > 0) - return true; - return ($scope.mode == name); - } - $scope.selectMode = function(name) { - if (name == "Add Router") { - name = 'Diagram'; - if ($scope.addingNode.step > 0) { - $scope.addingNode.step = 0; - } else { - // start adding node mode - $scope.addingNode.step = 1; - } - } else { - $scope.addingNode.step = 0; - } - - $scope.mode = name; - } - $scope.addAnotherNode = function () { - // we are starting the add mode - $scope.$broadcast('showAddForm') - - resetMouseVars(); - //selected_node = null; - //selected_link = null; - // add a new node - var x = radiusNormal * 4; - var y = x;; - var offset = jQuery('#topology').offset(); - x = mouseX - offset.left + $(document).scrollLeft(); - y = mouseY - offset.top + $(document).scrollTop();; - var name = genNewName() - var nextId = nodes.length //maxNodeIndex() + 1 - //NewRouterName = genNewName(); - var id = "amqp:/_topo/0/" + name + "/$management"; - var node = aNode(id, name, "inter-router", undefined, nextId, x, y, undefined, false) - node.host = "0.0.0.0:" + port - ++port - nodes.push(node); - - force.nodes(nodes).links(links).start(); - restart(false); - } - - $scope.$watch(function() { return $scope.addingNode.step }, function(newValue, oldValue) { - if (newValue == 0 && oldValue != 0) { - // we are cancelling the add - - // find the New node - nodes.every(function(n, i) { - // for the placeholder node, the key will be __internal__ - if (QDRService.nameFromId(n.key) == '__internal__') { - var newLinks = links.filter(function(e, i) { - return e.source.id == n.id || e.target.id == n.id; - }) - // newLinks is an array of links to remove - newLinks.map(function(e) { - links.splice(links.indexOf(e), 1); - }) - // i is the index of the node to remove - nodes.splice(i, 1); - force.nodes(nodes).links(links).start(); - restart(false); - return false; // stop looping - } - return true; - }) - updateForm(Object.keys(QDRService.topology.nodeInfo())[0], 'router', 0); - - } else if (newValue > 0) { - // we are starting the add mode - $scope.$broadcast('showAddForm') - - resetMouseVars(); - selected_node = null; - selected_link = null; - // add a new node - var id = "amqp:/_topo/0/__internal__/$management"; - var x = radiusNormal * 4; - var y = x;; - if (newValue > 1) { // add at current mouse position - var offset = jQuery('#topology').offset(); - x = mouseX - offset.left + $(document).scrollLeft(); - y = mouseY - offset.top + $(document).scrollTop();; - } - QDRService.ensureAllEntities({entity: ".router"}, function () { - QDR.log.debug("got response for all .routers") - NewRouterName = genNewName(); - nodes.push(aNode(id, NewRouterName, "inter-router", undefined, nodes.length, x, y, undefined, true)); - force.nodes(nodes).links(links).start(); - restart(false); - }) - } - }) - $scope.isRight = function(mode) { - return mode.right; - } - - var maxNodeIndex = function () { - var maxIndex = -1 - nodes.forEach( function (node) { - if (node.nodeType === "inter-router") { - if (node.id > maxIndex) - maxIndex = node.id - } - }) - return maxIndex; - } - - // for ng-grid that shows details for multiple consoles/clients - // generate unique name for router and containerName - var genNewName = function() { - var newName = $scope.baseName + "." - for (var i=0; i<nodes.length; ++i) { - var found = nodes.some( function (n) { - return n.name === newName + i - }) - if (!found) - return newName + i - } - return newName + nodes.length - } - - $scope.settings = function () { - doAddDialog($scope.baseName); - }; - $scope.reverseLink = function() { - if (!mousedown_link) - return; - var d = mousedown_link; - var tmp = d.left; - d.left = d.right;; - d.right = tmp; - restart(false); - tick(); - } - $scope.removeLink = function() { - if (!mousedown_link) - return; - var d = mousedown_link; - links.every(function(l, i) { - if (l.source.id == d.source.id && l.target.id == d.target.id) { - links.splice(i, 1); - force.links(links).start(); - return false; // exit the 'every' loop - } - return true; - }); - restart(false); - tick(); - } - var setNodesFixed = function (name, b) { - nodes.some(function (n) { - if (n.name === name) { - n.fixed = b; - return true; - } - }) - } - $scope.setFixed = function(b) { - if ($scope.contextNode) { - $scope.contextNode.fixed = b; - setNodesFixed($scope.contextNode.name, b) - savePositions() - } - restart(); - } - $scope.isFixed = function() { - if (!$scope.contextNode) - return false; - return ($scope.contextNode.fixed & 0b1); - } - - var mouseX, mouseY; - // event handlers for popup context menu - $(document).mousemove(function(e) { - mouseX = e.clientX; - mouseY = e.clientY; - }); - $(document).mousemove(); - $(document).click(function(e) { - $scope.contextNode = null; - $(".contextMenu").fadeOut(200); - }); - - var radii = { - 'inter-router': 25, - 'normal': 15, - 'on-demand': 15 - }; - var radius = 25; - var radiusNormal = 15; - var svg, lsvg; - var force; - var animate = false; // should the force graph organize itself when it is displayed - var path, circle; - var savedKeys = {}; - var dblckickPos = [0, 0]; - var width = 0; - var height = 0; - - var getSizes = function() { - var legendWidth = 143; - var gap = 5; - var width = $('#topology').width() - gap - legendWidth; - var top = $('#topology').offset().top - var tpformHeight = $('#topologyForm').height() - var height = Math.max(window.innerHeight, tpformHeight + top) - top - gap; - if (width < 10) { - QDR.log.info("page width and height are abnormal w:" + width + " height:" + height) - return [0, 0]; - } - return [width, height] - } - var resize = function() { - if (!svg) - return; - var sizes = getSizes(); - width = sizes[0] - height = sizes[1] - if (width > 0) { - // set attrs and 'resume' force - svg.attr('width', width); - svg.attr('height', height); - force.size(sizes).resume(); - } - } - window.addEventListener('resize', resize); - var sizes = getSizes() - width = sizes[0] - height = sizes[1] - if (width <= 0 || height <= 0) - return - - // set up initial nodes and links - // - nodes are known by 'id', not by index in array. - // - selected edges are indicated on the node (as a bold red circle). - // - links are always source < target; edge directions are set by 'left' and 'right'. - var nodes = []; - var links = []; - - var aNode = function(id, name, nodeType, nodeInfo, nodeIndex, x, y, resultIndex, fixed, properties) { - for (var i=0; i<nodes.length; ++i) { - if (nodes[i].name === name) - return nodes[i] - } - properties = properties || {}; - var routerId = QDRService.nameFromId(id) - return { - key: id, - name: name, - nodeType: nodeType, - properties: properties, - routerId: routerId, - x: x, - y: y, - id: nodeIndex, - resultIndex: resultIndex, - fixed: !!+fixed, - cls: name == NewRouterName ? 'temp' : '' - }; - }; - - - var initForm = function(attributes, results, entityType, formFields) { - - while (formFields.length > 0) { - // remove all existing attributes - formFields.pop(); - } - - for (var i = 0; i < attributes.length; ++i) { - var name = attributes[i]; - var val = results[i]; - var desc = ""; - if (entityType.attributes[name]) - if (entityType.attributes[name].description) - desc = entityType.attributes[name].description; - - formFields.push({ - 'attributeName': name, - 'attributeValue': val, - 'description': desc - }); - } - } - - var getLinkAddr = function (id, connection, onode) { - var links = onode[".router.link"] - if (!links) { - return $scope.clientAddress - } - links.results.forEach( function (linkResult) { - var link = QDRService.flatten(links.attributeNames, linkResult) - if (link.linkType === "endpoint" && link.connectionId === connection.identity) - return link.owningAddr - }) - return $scope.clientAddress - } - - var getLinkDir = function (id, connection, onode) { - var links = onode[".router.link"] - if (!links) { - return "unknown" - } - var inCount = 0, outCount = 0 - links.results.forEach( function (linkResult) { - var link = QDRService.flatten(links.attributeNames, linkResult) - if (link.linkType === "endpoint" && link.connectionId === connection.identity) - if (link.linkDir === "in") - ++inCount - else - ++outCount - }) - if (inCount > 0 && outCount > 0) - return "both" - if (inCount > 0) - return "in" - if (outCount > 0) - return "out" - return "unknown" - } - - var savePositions = function () { - nodes.forEach( function (d) { - localStorage[d.name] = angular.toJson({ - x: Math.round(d.x), - y: Math.round(d.y), - fixed: d.fixed ? 1 : 0, - }); - }) - } - - var initializeNodes = function (nodeInfo) { - var nodeCount = Object.keys(nodeInfo).length - var yInit = 50; - nodes = [] - for (var id in nodeInfo) { - var name = QDRService.nameFromId(id); - // if we have any new nodes, animate the force graph to position them - var position = angular.fromJson(localStorage[name]); - if (!angular.isDefined(position)) { - animate = true; - position = { - x: Math.round(width / 4 + ((width / 2) / nodeCount) * nodes.length), - y: Math.round(height / 2 + Math.sin(nodes.length / (Math.PI*2.0)) * height / 4), - fixed: false, - }; - //QDR.log.debug("new node pos (" + position.x + ", " + position.y + ")") - } - if (position.y > height) { - position.y = 200 - yInit; - yInit *= -1 - } - nodes.push(aNode(id, name, "inter-router", nodeInfo, nodes.length, position.x, position.y, undefined, position.fixed)); - //QDR.log.debug("adding node " + nodes.length-1); - } - } - - var initializeLinks = function (nodeInfo, unknowns) { - links = []; - var source = 0; - var client = 1.0; - for (var id in nodeInfo) { - var onode = nodeInfo[id]; - var conns = onode['.connection'].results; - var attrs = onode['.connection'].attributeNames; - //QDR.log.debug("external client parent is " + parent); - var normalsParent = {}; // 1st normal node for this parent - - for (var j = 0; j < conns.length; j++) { - var connection = QDRService.flatten(attrs, conns[j]) - var role = connection.role - var properties = connection.properties || {}; - var dir = connection.dir - if (role == "inter-router") { - var connId = connection.container - var target = getContainerIndex(connId, nodeInfo); - if (target >= 0) { - getLink(source, target, dir, "", connection.name); - } - } else if (role == "normal" || role == "on-demand") { - // not a router, but an external client - var name = QDRService.nameFromId(id) + "." + connection.identity; - - // if we have any new clients, animate the force graph to position them - var position = angular.fromJson(localStorage[name]); - if (!angular.isDefined(position)) { - animate = true; - position = { - x: Math.round(nodes[source].x + 40 * Math.sin(client / (Math.PI * 2.0))), - y: Math.round(nodes[source].y + 40 * Math.cos(client / (Math.PI * 2.0))), - fixed: false - }; - //QDR.log.debug("new client pos (" + position.x + ", " + position.y + ")") - }// else QDR.log.debug("using previous location") - if (position.y > height) { - position.y = Math.round(nodes[source].y + 40 + Math.cos(client / (Math.PI * 2.0))) - } - var node = aNode(id, name, role, nodeInfo, nodes.length, position.x, position.y, j, position.fixed, properties) - var nodeType = QDRService.isAConsole(properties, connection.identity, role, node.key) ? "console" : "client" - if (role === 'normal') { - var cdir = getLinkDir(id, connection, onode) - if (cdir !== 'unknown') { - var addr = getLinkAddr(id, connection , onode) - node.user = connection.user - node.isEncrypted = connection.isEncrypted - node.host = connection.host - node.connectionId = connection.identity - node.cdir = cdir - // determine arrow direction by using the link directions - if (!normalsParent[nodeType+cdir]) { - normalsParent[nodeType+cdir] = node; - nodes.push(node); - node.normals = [{name: node.name, addr: addr}]; - // now add a link - getLink(source, nodes.length - 1, cdir, "small", connection.name); - client++; - } else { - normalsParent[nodeType+cdir].normals.push({name: node.name, addr: addr}) - } - } else { - unknowns.push(node) - } - } else { - nodes.push(node) - // now add a link - getLink(source, nodes.length - 1, dir, "small", connection.name); - client++; - } - } - } - source++; - } - } - - // vary the following force graph attributes based on nodeCount - // <= 6 routers returns min, >= 80 routers returns max, interpolate linearly - var forceScale = function(nodeCount, min, max) { - var count = nodeCount - if (nodeCount < 6) count = 6 - if (nodeCount > 200) count = 200 - var x = d3.scale.linear() - .domain([6,200]) - .range([min, max]); -//QDR.log.debug("forceScale(" + nodeCount + ", " + min + ", " + max + " returns " + x(count) + " " + x(nodeCount)) - return x(count) - } - var linkDistance = function (d, nodeCount) { - if (d.target.nodeType === 'inter-router') - return forceScale(nodeCount, 150, 20) - return forceScale(nodeCount, 75, 10) - } - var charge = function (d, nodeCount) { - if (d.nodeType === 'inter-router') - return forceScale(nodeCount, -1800, -200) - return -900 - } - var gravity = function (d, nodeCount) { - return forceScale(nodeCount, 0.0001, 0.1) - } - - var initGraph = function () { - d3.select("#SVG_ID").remove(); - svg = d3.select('#topology') - .append('svg') - .attr("id", "SVG_ID") - .attr('width', width) - .attr('height', height) - .on("contextmenu", function(d) { - if (d3.event.defaultPrevented) - return; - d3.event.preventDefault(); - - //if ($scope.addingNode.step != 0) - // return; - if (d3.select('#svg_context_menu').style('display') !== 'block') - $(document).click(); - d3.select('#svg_context_menu') - .style('left', (mouseX + $(document).scrollLeft()) + "px") - .style('top', (mouseY + $(document).scrollTop()) + "px") - .style('display', 'block'); - }) - .on('click', function(d) { - removeCrosssection() - }); - - svg.append("svg:defs").selectAll('marker') - .data(["end-arrow", "end-arrow-selected", "end-arrow-small", "end-arrow-highlighted"]) // Different link/path types can be defined here - .enter().append("svg:marker") // This section adds in the arrows - .attr("id", String) - .attr("viewBox", "0 -5 10 10") - .attr("markerWidth", 4) - .attr("markerHeight", 4) - .attr("orient", "auto") - .classed("small", function (d) {return d.indexOf('small') > -1}) - .append("svg:path") - .attr('d', 'M 0 -5 L 10 0 L 0 5 z') - - svg.append("svg:defs").selectAll('marker') - .data(["start-arrow", "start-arrow-selected", "start-arrow-small", "start-arrow-highlighted"]) // Different link/path types can be defined here - .enter().append("svg:marker") // This section adds in the arrows - .attr("id", String) - .attr("viewBox", "0 -5 10 10") - .attr("refX", 5) - .attr("markerWidth", 4) - .attr("markerHeight", 4) - .attr("orient", "auto") - .append("svg:path") - .attr('d', 'M 10 -5 L 0 0 L 10 5 z'); - - var grad = svg.append("svg:defs").append("linearGradient") - .attr("id", "half-circle") - .attr("x1", "0%") - .attr("x2", "0%") - .attr("y1", "100%") - .attr("y2", "0%"); - grad.append("stop").attr("offset", "50%").style("stop-color", "#C0F0C0"); - grad.append("stop").attr("offset", "50%").style("stop-color", "#F0F000"); - - // handles to link and node element groups - path = svg.append('svg:g').selectAll('path') - circle = svg.append('svg:g').selectAll('g') - - } - - var initLegend = function () { - // the legend - d3.select("#svg_legend svg").remove(); - lsvg = d3.select("#svg_legend") - .append('svg') - .attr('id', 'svglegend') - lsvg = lsvg.append('svg:g') - .attr('transform', 'translate(' + (radii['inter-router'] + 2) + ',' + (radii['inter-router'] + 2) + ')') - .selectAll('g'); - } - - var initForce = function () { - // convert link source/target into node index numbers - links.forEach( function (link, i) { - if (link.source.id) { - link.source = link.source.id - link.target = link.target.id - } - }) - var routerCount = nodes.filter(function (n) { - return n.nodeType === 'inter-router' - }).length - - force = d3.layout.force() - .nodes(nodes) - .links(links) - .size([width, height]) - .linkDistance(function(d) { return linkDistance(d, routerCount) }) - .charge(function(d) { return charge(d, routerCount) }) - .friction(.10) - .gravity(function(d) { return gravity(d, routerCount) }) - .on('tick', tick) - .on('end', function () {savePositions()}) - .start() - } - // initialize the nodes and links array from the QDRService.topology._nodeInfo object - var initForceGraph = function() { - nodes = []; - links = []; - var nodeInfo = QDRService.topology.nodeInfo(); - var nodeCount = Object.keys(nodeInfo).length - - var oldSelectedNode = selected_node - var oldMouseoverNode = mouseover_node - mouseover_node = null; - selected_node = null; - selected_link = null; - - savePositions(); - initGraph() - - $(document).keyup(function(e) { - if (e.keyCode === 27) { - removeCrosssection() - } - }); - - initLegend() - - // mouse event vars - mousedown_link = null; - mousedown_node = null; - mouseup_node = null; - - // initialize the list of nodes - initializeNodes(nodeInfo) - savePositions() - - // initialize the list of links - var unknowns = [] - initializeLinks(nodeInfo, unknowns) - $scope.schema = QDRService.schema; - // init D3 force layout - initForce() - - // app starts here - restart(false); - force.start(); - if (oldSelectedNode) { - d3.selectAll('circle.inter-router').classed("selected", function (d) { - if (d.key === oldSelectedNode.key) { - selected_node = d; - return true - } - return false - }) - } - if (oldMouseoverNode && selected_node) { - d3.selectAll('circle.inter-router').each(function (d) { - if (d.key === oldMouseoverNode.key) { - mouseover_node = d - QDRService.ensureAllEntities([{entity: ".router.node", attrs: ["id","nextHop"]}], function () { - nextHop(selected_node, d); - restart(); - }) - } - }) - } - setTimeout(function () { - updateForm(Object.keys(QDRService.topology.nodeInfo())[0], 'router', 0); - }) - - // if any clients don't yet have link directions, get the links for those nodes and restart the graph - if (unknowns.length > 0) - setTimeout(resolveUnknowns, 10, nodeInfo, unknowns) - - var continueForce = function (extra) { - if (extra > 0) { - --extra - force.start() - setTimeout(continueForce, 100, extra) - } - } - continueForce(forceScale(nodeCount, 20, 200)) // give graph time to settle down - } - - var resolveUnknowns = function (nodeInfo, unknowns) { - var unknownNodes = {} - // collapse the unknown node.keys using an object - for (var i=0; i<unknowns.length; ++i) { - unknownNodes[unknowns[i].key] = 1 - } - unknownNodes = Object.keys(unknownNodes) - //QDR.log.debug("there were " + unknownNodes.length + " connections with normal links") - //console.dump(unknownNodes) - - QDRService.ensureEntities(unknownNodes, {entity: ".router.link", attrs: ["linkType","connectionId","linkDir"], force: true}, function () { - initializeLinks(nodeInfo, []) - animate = true; - force.nodes(nodes).links(links).start(); - restart(false); - }) - } - - function updateForm(key, entity, resultIndex) { - var nodeInfo = QDRService.topology.nodeInfo(); - if (key in nodeInfo) { - QDRService.ensureEntities(key, [ - {entity: '.'+entity}, - {entity: '.listener', attrs: ["role", "port"]}], function () { - var onode = nodeInfo[key] - if (resultIndex >= onode['.' + entity].results.length) - return; - var nodeResults = onode['.' + entity].results[resultIndex] - var nodeAttributes = onode['.' + entity].attributeNames - var attributes = nodeResults.map(function(row, i) { - return { - attributeName: nodeAttributes[i], - attributeValue: row - } - }) - // sort by attributeName - attributes.sort(function(a, b) { - return a.attributeName.localeCompare(b.attributeName) - }) - - // move the Name first - var nameIndex = attributes.findIndex(function(attr) { - return attr.attributeName === 'name' - }) - if (nameIndex >= 0) - attributes.splice(0, 0, attributes.splice(nameIndex, 1)[0]); - - // get the list of ports this router is listening on - if (entity === 'router') { - var listeners = onode['.listener'].results; - var listenerAttributes = onode['.listener'].attributeNames; - var normals = listeners.filter(function(listener) { - return QDRService.valFor(listenerAttributes, listener, 'role') === 'normal'; - }) - var ports = [] - normals.forEach(function(normalListener) { - ports.push(QDRService.valFor(listenerAttributes, normalListener, 'port')) - }) - // add as 2nd row - if (ports.length) { - attributes.splice(1, 0, { - attributeName: 'Listening on', - attributeValue: ports, - description: 'The port on which this router is listening for connections' - }); - } - } - $scope.$broadcast('showEntityForm', { - entity: entity, - attributes: attributes - }) - if (!$scope.$$phase) $scope.$apply() - }) - } - } - - function getContainerIndex(_id, nodeInfo) { - var nodeIndex = 0; - for (var id in nodeInfo) { - if (QDRService.nameFromId(id) === _id) - return nodeIndex; - ++nodeIndex; - } - return -1; - } - - function getLink(_source, _target, dir, cls, uid) { - for (var i = 0; i < links.length; i++) { - var s = links[i].source, - t = links[i].target; - if (typeof links[i].source == "object") { - s = s.id; - t = t.id; - } - if (s == _source && t == _target) { - return i; - } - // same link, just reversed - if (s == _target && t == _source) { - return -i; - } - } - - //QDR.log.debug("creating new link (" + (links.length) + ") between " + nodes[_source].name + " and " + nodes[_target].name); - var link = { - source: _source, - target: _target, - left: dir != "out", - right: (dir == "out" || dir == "both"), - cls: cls, - uid: uid, - }; - return links.push(link) - 1; - } - - - function resetMouseVars() { - mousedown_node = null; - mouseover_node = null; - mouseup_node = null; - mousedown_link = null; - } - - // update force layout (called automatically each iteration) - function tick() { - circle.attr('transform', function(d) { - var cradius; - if (d.nodeType == "inter-router") { - cradius = d.left ? radius + 8 : radius; - } else { - cradius = d.left ? radiusNormal + 18 : radiusNormal; - } - d.x = Math.max(d.x, radiusNormal * 2); - d.y = Math.max(d.y, radiusNormal * 2); - d.x = Math.max(0, Math.min(width - cradius, d.x)) - d.y = Math.max(0, Math.min(height - cradius, d.y)) - return 'translate(' + d.x + ',' + d.y + ')'; - }); - - // draw directed edges with proper padding from node centers - path.attr('d', function(d) { - //QDR.log.debug("in tick for d"); - //console.dump(d); - var sourcePadding, targetPadding, r; - - if (d.target.nodeType == "inter-router") { - r = radius; - // right arrow left line start - sourcePadding = d.left ? radius + 8 : radius; - // left arrow right line start - targetPadding = d.right ? radius + 16 : radius; - } else { - r = radiusNormal - 18; - sourcePadding = d.left ? radiusNormal + 18 : radiusNormal; - targetPadding = d.right ? radiusNormal + 16 : radiusNormal; - } - var dtx = Math.max(targetPadding, Math.min(width - r, d.target.x)), - dty = Math.max(targetPadding, Math.min(height - r, d.target.y)), - dsx = Math.max(sourcePadding, Math.min(width - r, d.source.x)), - dsy = Math.max(sourcePadding, Math.min(height - r, d.source.y)); - - var deltaX = dtx - dsx, - deltaY = dty - dsy, - dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY), - normX = deltaX / dist, - normY = deltaY / dist; - var sourceX = dsx + (sourcePadding * normX), - sourceY = dsy + (sourcePadding * normY), - targetX = dtx - (targetPadding * normX), - targetY = dty - (targetPadding * normY); - sourceX = Math.max(0, Math.min(width, sourceX)) - sourceY = Math.max(0, Math.min(width, sourceY)) - targetX = Math.max(0, Math.min(width, targetX)) - targetY = Math.max(0, Math.min(width, targetY)) - - return 'M' + sourceX + ',' + sourceY + 'L' + targetX + ',' + targetY; - }); - - if (!animate) { - animate = true; - force.stop(); - } - } - - // highlight the paths between the selected node and the hovered node - function findNextHopNode(from, d) { - // d is the node that the mouse is over - // from is the selected_node .... - if (!from) - return null; - - if (from == d) - return selected_node; - - //QDR.log.debug("finding nextHop from: " + from.name + " to " + d.name); - var sInfo = QDRService.topology.nodeInfo()[from.key]; - - if (!sInfo) { - //QDR.log.warn("unable to find topology node info for " + from.key); - return null; - } - - // find the hovered name in the selected name's .router.node results - if (!sInfo['.router.node']) - return null; - var aAr = sInfo['.router.node'].attributeNames; - var vAr = sInfo['.router.node'].results; - var nhIndex = aAr.indexOf("nextHop") - for (var hIdx = 0; hIdx < vAr.length; ++hIdx) { - var addrT = QDRService.valFor(aAr, vAr[hIdx], "id"); - if (addrT == d.name) { - //QDR.log.debug("found " + d.name + " at " + hIdx); - var nextHop = vAr[hIdx][nhIndex] - //QDR.log.debug("nextHop was " + nextHop); - return (nextHop == null) ? nodeFor(addrT) : nodeFor(nextHop); - } - } - return null; - } - - function nodeFor(name) { - for (var i = 0; i < nodes.length; ++i) { - if (nodes[i].name == name) - return nodes[i]; - } - return null; - } - - function genLinkName(d1, d2) { - return d1.id + "." + d2.id - } - function linkFor(source, target) { - for (var i = 0; i < links.length; ++i) { - if ((links[i].source == source) && (links[i].target == target)) - return links[i]; - if ((links[i].source == target) && (links[i].target == source)) - return links[i]; - } - // the selected node was a client/broker - //QDR.log.debug("failed to find a link between "); - //console.dump(source); - //QDR.log.debug(" and "); - //console.dump(target); - return null; - } - - function clearPopups() { - d3.select("#crosssection").style("display", "none"); - $('.hastip').empty(); - d3.select("#multiple_details").style("display", "none") - d3.select("#link_details").style("display", "none") - d3.select('#node_context_menu').style('display', 'none'); - - } - - function removeCrosssection() { - setTimeout(function() { - d3.select("[id^=tooltipsy]").remove() - $('.hastip').empty(); - }, 1010); - d3.select("#crosssection svg g").transition() - .duration(1000) - .attr("transform", "scale(0)") - .style("opacity", 0) - .each("end", function (d) { - d3.select("#crosssection svg").remove(); - d3.select("#crosssection").style("display","none"); - }); - d3.select("#multiple_details").transition() - .duration(500) - .style("opacity", 0) - .each("end", function(d) { - d3.select("#multiple_details").style("display", "none") - }) - hideLinkDetails(); - } - - function hideLinkDetails() { - d3.select("#link_details").transition() - .duration(500) - .style("opacity", 0) - .each("end", function(d) { - d3.select("#link_details").style("display", "none") - }) - } - - function clerAllHighlights() { - for (var i = 0; i < links.length; ++i) { - links[i]['highlighted'] = false; - } - for (var i=0; i<nodes.length; ++i) { - nodes[i]['highlighted'] = false; - } - } - - // takes the nodes and links array of objects and adds svg elements for everything that hasn't already - // been added - function restart(start) { - circle.call(force.drag); - - // path (link) group - path = path.data(links, function(d) {return d.uid}); - - // update existing links - path.classed('selected', function(d) { - return d === selected_link; - }) - .classed('highlighted', function(d) { - return d.highlighted; - }) - .classed('temp', function(d) { - return d.cls == 'temp'; - }) - .attr('marker-start', function(d) { - var sel = d === selected_link ? '-selected' : (d.cls === 'small' ? '-small' : ''); - if (d.highlighted) - sel = "-highlighted" - return d.left ? 'url(' + urlPrefix + '#start-arrow' + sel + ')' : ''; - }) - .attr('marker-end', function(d) { - var sel = d === selected_link ? '-selected' : (d.cls === 'small' ? '-small' : ''); - if (d.highlighted) - sel = "-highlighted" - return d.right ? 'url(' + urlPrefix + '#end-arrow' + sel + ')' : ''; - }) - - - // add new links. if links[] is longer than the existing paths, add a new path for each new element - path.enter().append('svg:path') - .attr('class', 'link') - .attr('marker-start', function(d) { - var sel = d === selected_link ? '-selected' : (d.cls === 'small' ? '-small' : ''); - return d.left ? 'url(' + urlPrefix + '#start-arrow' + sel + ')' : ''; - }) - .attr('marker-end', function(d) { - var sel = d === selected_link ? '-selected' : (d.cls === 'small' ? '-small' : ''); - return d.right ? 'url(' + urlPrefix + '#end-arrow' + sel + ')' : ''; - }) - .classed('temp', function(d) { - return d.cls == 'temp'; - }) - .classed('small', function(d) { - return d.cls == 'small'; - }) - .on('mouseover', function(d) { // mouse over a path - if ($scope.addingNode.step > 0) { - if (d.cls == 'temp') { - d3.select(this).classed('over', true); - } - return; - } - //QDR.log.debug("showing connections form"); - var resultIndex = 0; // the connection to use - var left = d.left ? d.target : d.source; - // right is the node that the arrow points to, left is the other node - var right = d.left ? d.source : d.target; - var onode = QDRService.topology.nodeInfo()[left.key]; - // loop through all the connections for left, and find the one for right - if (!onode || !onode['.connection']) - return; - // update the info dialog for the link the mouse is over - if (!selected_node && !selected_link) { - for (resultIndex = 0; resultIndex < onode['.connection'].results.length; ++resultIndex) { - var conn = onode['.connection'].results[resultIndex]; - /// find the connection whose container is the right's name - var name = QDRService.valFor(onode['.connection'].attributeNames, conn, "container"); - if (name == right.routerId) { - break; - } - } - // did not find connection. this is a connection to a non-interrouter node - if (resultIndex === onode['.connection'].results.length) { - // use the non-interrouter node's connection info - left = d.target; - resultIndex = left.resultIndex; - } - if (resultIndex) - updateForm(left.key, 'connection', resultIndex); - } - - mousedown_link = d; - selected_link = mousedown_link; - restart(); - }) - .on('mouseout', function(d) { // mouse out of a path - if ($scope.addingNode.step > 0) { - if (d.cls == 'temp') { - d3.select(this).classed('over', false); - } - return; - } - //QDR.log.debug("showing connections form"); - selected_link = null; - restart(); - }) - .on("contextmenu", function(d) { // right click a path - $(document).click(); - d3.event.preventDefault(); - - mousedown_link = d; - d3.select('#link_context_menu') - .style('left', (mouseX + $(document).scrollLeft()) + "px") - .style('top', (mouseY + $(document).scrollTop()) + "px") - .style('display', 'block'); - }) - // left click a path - .on("click", function (d) { - var clickPos = d3.mouse(this); - d3.event.stopPropagation(); - clearPopups(); - var showCrossSection = function() { - var diameter = 400; - var format = d3.format(",d"); - var pack = d3.layout.pack() - .size([diameter - 4, diameter - 4]) - .padding(-10) - .value(function(d) { return d.size; }); - - d3.select("#crosssection svg").remove(); - var svg = d3.select("#crosssection").append("svg") - .attr("width", diameter) - .attr("height", diameter) - var svgg = svg.append("g") - .attr("transform", "translate(2,2)"); - - var root = { - name: " Links between " + d.source.name + " and " + d.target.name, - children: [] - } - var nodeInfo = QDRService.topology.nodeInfo(); - var connections = nodeInfo[d.source.key]['.connection']; - var containerIndex = connections.attributeNames.indexOf('container'); - connections.results.some ( function (connection) { - if (connection[containerIndex] == d.target.routerId) { - root.attributeNames = connections.attributeNames; - root.obj = connection; - root.desc = "Connection"; - return true; // stop looping after 1 match - } - return false; - }) - - // find router.links where link.remoteContainer is d.source.name - var links = nodeInfo[d.source.key]['.router.link']; - var identityIndex = connections.attributeNames.indexOf('identity') - var roleIndex = connections.attributeNames.indexOf('role') - var connectionIdIndex = links.attributeNames.indexOf('connectionId'); - var linkTypeIndex = links.attributeNames.indexOf('linkType'); - var nameIndex = links.attributeNames.indexOf('name'); - var linkDirIndex = links.attributeNames.indexOf('linkDir'); - - if (roleIndex < 0 || identityIndex < 0 || connectionIdIndex < 0 - || linkTypeIndex < 0 || nameIndex < 0 || linkDirIndex < 0) - return; - links.results.forEach ( function (link) { - if (root.obj && link[connectionIdIndex] == root.obj[identityIndex] && link[linkTypeIndex] == root.obj[roleIndex]) - root.children.push ( - { name: " " + link[linkDirIndex] + " ", - size: 100, - obj: link, - desc: "Link", - attributeNames: links.attributeNames - }) - }) - if (root.children.length == 0) - return; - var node = svgg.datum(root).selectAll(".node") - .data(pack.nodes) - .enter().append("g") - .attr("class", function(d) { return d.children ? "parent node hastip" : "leaf node hastip"; }) - .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")" + (!d.children ? "scale(0.9)" : ""); }) - .attr("title", function (d) { - var title = "<h4>" + d.desc + "</h4><table class='tiptable'><tbody>"; - if (d.attributeNames) - d.attributeNames.forEach( function (n, i) { - title += "<tr><td>" + n + "</td><td>"; - title += d.obj[i] != null ? d.obj[i] : ''; - title += '</td></tr>'; - }) - title += "</tbody></table>" - return title - }) - node.append("circle") - .attr("r", function(d) { return d.r; }); - - // node.filter(function(d) { return !d.children; }).append("text") - node.append("text") - .attr("dy", function (d) { return d.children ? "-10em" : ".5em"}) - .style("text-anchor", "middle") - .text(function(d) { - return d.name.substring(0, d.r / 3); - }); - $('.hastip').tooltipsy({ alignTo: 'cursor'}); - svgg.attr("transform", "translate(2,2) scale(0.01)") - - var bounds = $("#topology").position() - d3.select("#crosssection") - .style("display", "block") - .style("left", (clickPos[0] + bounds.left) + "px") - .style("top", (clickPos[1] + bounds.top) + "px") - - svgg.transition() - .attr("transform", "translate(2,2) scale(1)") - .each("end", function () { - d3.selectAll("#crosssection g.leaf text").attr("dy", ".3em") - }) - } - QDRService.ensureEntities(d.source.key, {entity: '.router.link', force: true}, showCrossSection) - }) - // remove old links - path.exit().remove(); - - - // circle (node) group - // nodes are known by id - circle = circle.data(nodes, function(d) { return d.name }); - - var appendTitle = function(g) { - g.append("svg:title").text(function(d) { - var x = ''; - if (d.normals && d.normals.length > 1) - x = " x " + d.normals.length; - if (QDRService.isConsole(d)) { - return 'Dispatch console' + x - } - if (d.properties.product == 'qpid-cpp') { - return 'Broker - qpid-cpp' + x - } - if (QDRService.isArtemis(d)) { - return 'Broker - Artemis' + x - } - if (d.cdir === 'in') - return 'Sender' + x - if (d.cdir === 'out') - return 'Receiver' + x - if (d.cdir === 'both') - return 'Sender/Receiver' + x - return d.nodeType == 'normal' ? 'client' + x : (d.nodeType == 'on-demand' ? 'broker' : 'Router ' + d.name) - }) - } - - // update existing nodes visual states - circle.selectAll('circle') - .classed('highlighted', function(d) { - return d.highlighted; - }) - .classed('selected', function(d) { - return (d === selected_node) - }) - .classed('fixed', function(d) { - return d.fixed - }) - // add 'multiple' class to existing <g> elements as needed - .each(function (d) { - if (d.normals && d.normals.length > 1) { - // add the "multiple" class to the parent <g> - var d3g = d3.select(this.parentElement) - d3g.attr('class', 'multiple') - d3g.select('title').remove() - appendTitle(d3g) - } - }) - - // add new circle nodes. if nodes[] is longer than the existing paths, add a new path for each new element - var g = circle.enter().append('svg:g') - .classed('multiple', function(d) { - return (d.normals && d.normals.length > 1) - }) - - var appendCircle = function(g) { - // add new circles and set their attr/class/behavior - return g.append('svg:circle') - .attr('class', 'node') - .attr('r', function(d) { - return radii[d.nodeType] - }) - .attr('fill', function (d) { - if (d.cdir === 'both' && !QDRService.isConsole(d)) { - return 'url(' + urlPrefix + '#half-circle)' - } - return null; - }) - .classed('fixed', function(d) { - return d.fixed - }) - .classed('temp', function(d) { - return QDRService.nameFromId(d.key) == '__internal__'; - }) - .classed('normal', function(d) { - return d.nodeType == 'normal' - }) - .classed('in', function(d) { - return d.cdir == 'in' - }) - .classed('out', function(d) { - return d.cdir == 'out' - }) - .classed('inout', function(d) { - return d.cdir == 'both' - }) - .classed('inter-router', function(d) { - return d.nodeType == 'inter-router' - }) - .classed('on-demand', function(d) { - return d.nodeType == 'on-demand' - }) - .classed('console', function(d) { - return QDRService.isConsole(d) - }) - .classed('artemis', function(d) { - return QDRService.isArtemis(d) - }) - .classed('qpid-cpp', function(d) { - return QDRService.isQpid(d) - }) - .classed('client', function(d) { - return d.nodeType === 'normal' && !d.properties.console_identifier - }) - } - appendCircle(g) - .on('mouseover', function(d) { // mouseover a circle - if ($scope.addingNode.step > 0) { - d3.select(this).attr('transform', 'scale(1.1)'); - return; - } - if (!selected_node) { - if (d.nodeType === 'inter-router') { - //QDR.log.debug("showing general form"); - updateForm(d.key, 'router', 0); - } else if (d.nodeType === 'normal' || d.nodeType === 'on-demand') { - //QDR.log.debug("showing connections form"); - updateForm(d.key, 'connection', d.resultIndex); - } - } - - if (d === mousedown_node) - return; - //if (d === selected_node) - // return; - // enlarge target node - d3.select(this).attr('transform', 'scale(1.1)'); - // highlight the next-hop route from the selected node to this node - mousedown_node = null; - - if (!selected_node) { - return; - } - clerAllHighlights() - // we need .router.node info to highlight hops - QDRService.ensureAllEntities([{entity: ".router.node", attrs: ["id","nextHop"]}], function () { - mouseover_node = d // save this node in case the topology changes so we can restore the highlights - nextHop(selected_node, d); - restart(); - }) - }) - .on('mouseout', function(d) { // mouse out for a circle - // unenlarge target node - d3.select(this).attr('transform', ''); - clerAllHighlights() - mouseover_node = null; - restart(); - }) - .on('mousedown', function(d) { // mouse down for circle - if (d3.event.button !== 0) { // ignore all but left button - return; - } - mousedown_node = d; - // mouse position relative to svg - initial_mouse_down_position = d3.mouse(this.parentElement.parentElement.parentElement).slice(); - }) - .on('mouseup', function(d) { // mouse up for circle - if (!mousedown_node) - return; - - selected_link = null; - // unenlarge target node - d3.select(this).attr('transform', ''); - - // check for drag - mouseup_node = d; - var mySvg = this.parentElement.parentElement.parentElement; - // if we dragged the node, make it fixed - var cur_mouse = d3.mouse(mySvg); - if (cur_mouse[0] != initial_mouse_down_position[0] || - cur_mouse[1] != initial_mouse_down_position[1]) { - return -/* - console.log("mouse pos changed. making this node fixed") - d.fixed = true; - setNodesFixed(d.name, true) - resetMouseVars(); - restart(); - return; -*/ - } - // we want a link between the selected_node and this node - if (selected_node && d !== selected_node) { - if (d.nodeType !== 'inter-router') - return; - - // add a link from the clicked node to the selected node - var source = nodes.findIndex( function (n) { - return (n.key === d.key && n.nodeType === 'inter-router') - }) - var target = nodes.findIndex( function (n) { - return (n.key === selected_node.key && n.nodeType === 'inter-router') - }) - var curLinkCount = links.length - var newIndex = getLink(source, target, "in", "", genLinkName(d, selected_node)); - // there was already a link from selected to clicked node - if (newIndex != curLinkCount) { - selected_node = d - restart(); - return; - } - // add new elements to the svg - force.links(links).start(); - restart(); - return; - - } - - // if this node was selected, unselect it - if (mousedown_node === selected_node) { - selected_node = null; - } else { - if (d.nodeType !== 'normal' && d.nodeType !== 'on-demand') - selected_node = mousedown_node; - } - clerAllHighlights() - mousedown_node = null; - if (!$scope.$$phase) $scope.$apply() - restart(false); - - }) - .on("dblclick", function(d) { // circle - if (d.fixed) { - d.fixed = false - setNodesFixed(d.name, false) - restart() // redraw the node without a dashed line - force.start(); // let the nodes move to a new position - } - if (QDRService.nameFromId(d.key) == '__internal__') { - editNode(); - if (!$scope.$$phase) $scope.$apply() - } - }) - .on("contextmenu", function(d) { // circle - $(document).click(); - d3.event.preventDefault(); - $scope.contextNode = d; - if (!$scope.$$phase) $scope.$apply() // we just changed a scope valiable during an async event - d3.select('#node_context_menu') - .style('left', (mouseX + $(document).scrollLeft()) + "px") - .style('top', (mouseY + $(document).scrollTop()) + "px") - .style('display', 'block'); - - }) - .on("click", function(d) { // circle - if (!mouseup_node) - return; - // clicked on a circle - clearPopups(); - if (!d.normals) { - // circle was a router or a broker - if (QDRService.isArtemis(d) && Core.ConnectionName === 'Artemis') { - $location.path('/jmx/attributes?tab=artemis&con=Artemis') - } - return; - } - clickPos = d3.mouse(this); - d3.event.stopPropagation(); - }) - //.attr("transform", function (d) {return "scale(" + (d.nodeType === 'normal' ? .5 : 1) + ")"}) - //.transition().duration(function (d) {return d.nodeType === 'normal' ? 3000 : 0}).ease("elastic").attr("transform", "scale(1)") - - var appendContent = function(g) { - // show node IDs - g.append('svg:text') - .attr('x', 0) - .attr('y', function(d) { - var y = 7; - if (QDRService.isArtemis(d)) - y = 8; - else if (QDRService.isQpid(d)) - y = 9; - else if (d.nodeType === 'inter-router') - y = 4; - return y; - }) - .attr('class', 'id') - .classed('console', function(d) { - return QDRService.isConsole(d) - }) - .classed('normal', function(d) { - return d.nodeType === 'normal' - }) - .classed('on-demand', function(d) { - return d.nodeType === 'on-demand' - }) - .classed('artemis', function(d) { - return QDRService.isArtemis(d) - }) - .classed('qpid-cpp', function(d) { - return QDRService.isQpid(d) - }) - .text(function(d) { - if (QDRService.isConsole(d)) { - return '\uf108'; // icon-desktop for this console - } - if (QDRService.isArtemis(d)) { - return '\ue900' - } - if (QDRService.isQpid(d)) { - return '\ue901'; - } - if (d.nodeType === 'normal') - return '\uf109'; // icon-laptop for clients - return d.name.length > 7 ? d.name.substr(0, 6) + '...' : d.name; - }); - } - - appendContent(g) - appendTitle(g); - - // remove old nodes - circle.exit().remove(); - - // add subcircles - svg.selectAll('.more').remove(); - svg.selectAll('.multiple') - .append('svg:path') - .attr('d', "M1.5,-1 V4 M-1,1.5 H4") - .attr('class', 'more') - .attr('transform', "translate(18, -3) scale(2)") - - // dynamically create the legend based on which node types are present - // the legend - d3.select("#svg_legend svg").remove(); - lsvg = d3.select("#svg_legend") - .append('svg') - .attr('id', 'svglegend') - lsvg = lsvg.append('svg:g') - .attr('transform', 'translate(' + (radii['inter-router'] + 2) + ',' + (radii['inter-router'] + 2) + ')') - .selectAll('g'); - var legendNodes = []; - legendNodes.push(aNode("Router", "", "inter-router", undefined, 0, 0, 0, 0, false, {})) - - if (!svg.selectAll('circle.console').empty()) { - legendNodes.push(aNode("Console", "", "normal", undefined, 1, 0, 0, 0, false, { - console_identifier: 'Dispatch console' - })) - } - if (!svg.selectAll('circle.client.in').empty()) { - var node = aNode("Sender", "", "normal", undefined, 2, 0, 0, 0, false, {}) - node.cdir = "in" - legendNodes.push(node) - } - if (!svg.selectAll('circle.client.out').empty()) { - var node = aNode("Receiver", "", "normal", undefined, 3, 0, 0, 0, false, {}) - node.cdir = "out" - legendNodes.push(node) - } - if (!svg.selectAll('circle.client.inout').empty()) { - var node = aNode("Sender/Receiver", "", "normal", undefined, 4, 0, 0, 0, false, {}) - node.cdir = "both" - legendNodes.push(node) - } - if (!svg.selectAll('circle.qpid-cpp').empty()) { - legendNodes.push(aNode("Qpid broker", "", "on-demand", undefined, 5, 0, 0, 0, false, { - product: 'qpid-cpp' - })) - } - if (!svg.selectAll('circle.artemis').empty()) { - legendNodes.push(aNode("Artemis broker", "", "on-demand", undefined, 6, 0, 0, 0, false, {})) - } - lsvg = lsvg.data(legendNodes, function(d) { - return d.key; - }); - var lg = lsvg.enter().append('svg:g') - .attr('transform', function(d, i) { - // 45px between lines and add 10px space after 1st line - return "translate(0, " + (45 * i + (i > 0 ? 10 : 0)) + ")" - }) - - appendCircle(lg) - appendContent(lg) - appendTitle(lg) - lg.append('svg:text') - .attr('x', 35) - .attr('y', 6) - .attr('class', "label") - .text(function(d) { - return d.key - }) - lsvg.exit().remove(); - var svgEl = document.getElementById('svglegend') - if (svgEl) { - var bb; - // firefox can throw an exception on getBBox on an svg element - try { - bb = svgEl.getBBox(); - } catch (e) { - bb = { - y: 0, - height: 200, - x: 0, - width: 200 - } - } - svgEl.style.height = (bb.y + bb.height) + 'px'; - svgEl.style.width = (bb.x + bb.width) + 'px'; - } - - if (!mousedown_node || !selected_node) - return; - - if (!start) - return; - // set the graph in motion - //QDR.log.debug("mousedown_node is " + mousedown_node); - force.start(); - - } - - function nextHop(thisNode, d) { - if ((thisNode) && (thisNode != d)) { - var target = findNextHopNode(thisNode, d); - //QDR.log.debug("highlight link from node "); - //console.dump(nodeFor(selected_node.name)); - //console.dump(target); - if (target) { - var hnode = nodeFor(thisNode.name) - var hlLink = linkFor(hnode, target); - //QDR.log.debug("need to highlight"); - //console.dump(hlLink); - if (hlLink) { - hlLink['highlighted'] = true; - hnode['highlighted'] = true - } - else - target = null; - } - nextHop(target, d); - } - if (thisNode == d) { - var hnode = nodeFor(thisNode.name) - hnode['highlighted'] = true - } - } - - - function mousedown() { - // prevent I-bar on drag - //d3.event.preventDefault(); - - // because :active only works in WebKit? - svg.classed('active', true); - } - - function hasChanged() { - // Don't update the underlying topology diagram if we are adding a new node. - // Once adding is completed, the topology will update automatically if it has changed - if ($scope.addingNode.step > 0) - return -2; - var nodeInfo = QDRService.topology.nodeInfo(); - if (Object.keys(nodeInfo).length != Object.keys(savedKeys).length) - return Object.keys(nodeInfo).length > Object.keys(savedKeys).length ? 1 : -1; - // we may have dropped a node and added a different node in the same update cycle - for (var key in nodeInfo) { - // if this node isn't in the saved node list - if (!savedKeys.hasOwnProperty(key)) - return 1; - // if the number of connections for this node chaanged - if (nodeInfo[key]['.connection'].results.length != savedKeys[key]) { - return -1; - } - } - return 0; - }; - - function saveChanged() { - savedKeys = {}; - var nodeInfo = QDRService.topology.nodeInfo(); - // save the number of connections per node - for (var key in nodeInfo) { - if (nodeInfo[key]['.connection']) - savedKeys[key] = nodeInfo[key]['.connection'].results.length; - } - //QDR.log.debug("saving current keys"); - //console.dump(savedKeys); - }; - // we are about to leave the page, save the node positions - $rootScope.$on('$locationChangeStart', function(event, newUrl, oldUrl) { - //QDR.log.debug("locationChangeStart"); - savePositions() - $scope.addingNode.step = 0; - }); - // When the DOM element is removed from the page, - // AngularJS will trigger the $destroy event on - // the scope - $scope.$on("$destroy", function(event) { - //QDR.log.debug("scope on destroy"); - savePositions(); - QDRService.setUpdateEntities([]) - QDRService.stopUpdating(); - QDRService.delUpdatedAction("normalsStats"); - QDRService.delUpdatedAction("topology"); - d3.select("#SVG_ID").remove(); - window.removeEventListener('resize', resize); - }); - - function handleInitialUpdate() { - // we only need to update connections during steady-state - saveChanged(); - animate = true; - initForceGraph(); - // after the graph is displayed fetch all .router.node info. This is done so highlighting between nodes - // doesn't incur a delay - QDRService.ensureAllEntities([{entity: ".router.node", attrs: ["id","nextHop"]}], function () {QDR.log.debug("got .router.node response")}) - - // call this function every time a background update is done -/* - QDRService.addUpdatedAction("topology", function() { - var changed = hasChanged() - // there is a new node, we need to get all of it's entities before drawing the graph - if (changed > 0) { - //QDRService.delUpdatedAction("topology") - QDR.log.debug("a new node was detected") - setupInitialUpdate() // gets the new node's .connection info - } else if (changed === -1) { - // we lost a node (or a client), we can draw the new svg immediately - saveChanged(); - QDR.log.debug("a node was dropped or a client was added/dropped") - handleInitialUpdate() - } - }) -*/ - } - - function setupInitialUpdate() { - // make sure all router nodes have .connection info. if not then fetch any missing info - QDRService.ensureAllEntities([{entity: ".connection"}], handleInitialUpdate) - } - - $scope.mockTopologies = [] - $scope.mockTopologyDir = "" - QDRService.sendMethod("amqp:///get-topology/", "", [], "GET-TOPOLOGY-LIST", {}, function (nodeName, entity, response, context) { - $scope.mockTopologies = response - QDRService.sendMethod("amqp:///get-topology/", "", [], "GET-TOPOLOGY", {}, function (nodeName, entity, response, context) { - // this will trigger the watch on this variable which will get the topology - $timeout(function () { - $scope.mockTopologyDir = response - }) - QDRService.setUpdateEntities([".connection"]) - //QDRService.addUpdatedAction("gotTopology", function () { - // QDRService.delUpdatedAction("gotTopology") - // $timeout(setupInitialUpdate) - //}) - //QDRService.topology.get() - }) - }) - //QDRService.startUpdating(); - //initForceGraph(); - //switchTopology("config-4") - - function doAddDialog(NewRouterName) { - var d = $dialog.dialog({ - dialogClass: "modal dlg-large", - backdrop: true, - keyboard: true, - backdropClick: true, - controller: 'QDR.NodeDialogController', - templateUrl: 'node-config-template.html', - resolve: { - newname: function() { - return $scope.baseName; - }, - address: function () { - return $scope.clientAddress - } - } - }); - $timeout(function () { - d.open().then(function(result) { - if (result) - $scope.baseName = result.baseName - $scope.clientAddress = result.address - }); - }) - }; - - } - ]); - - QDR.module.controller("QDR.NodeDialogController", function($scope, QDRService, dialog, newname, address) { - $scope.entity = {description: "Settings", attributes: []} - var attribute = {name: "prefix", humanName: "New router prefix", input: "input", type: "text", - value: newname, required: true} - $scope.entity.attributes.push(attribute) - attribute = {name: "address", humanName: "New client address", input: "input", type: "text", - value: address, required: true} - $scope.entity.attributes.push(attribute) - - $scope.setSettings = function () { - dialog.close({ - baseName: $scope.entity.attributes[0].value, - address: $scope.entity.attributes[1].value - }); - } - - $scope.cancel = function () { - dialog.close() - } - - }) - - - return QDR; -}(QDR || {}));
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6502523b/console/test/mock/__init__.py ---------------------------------------------------------------------- diff --git a/console/test/mock/__init__.py b/console/test/mock/__init__.py deleted file mode 100644 index 44f288e..0000000 --- a/console/test/mock/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License -# - -from entities import * -from nexthop import * - --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org