diff --git a/web/gui/src/main/webapp/app/fw/layer/quickhelp.js b/web/gui/src/main/webapp/app/fw/layer/quickhelp.js index 4e8ac05a68..d5e8c0d9ab 100644 --- a/web/gui/src/main/webapp/app/fw/layer/quickhelp.js +++ b/web/gui/src/main/webapp/app/fw/layer/quickhelp.js @@ -50,7 +50,6 @@ // key-logical-name to key-display lookup.. var keyDisp = { equals: '=', - dash: '-', slash: '/', backSlash: '\\', backQuote: '`', diff --git a/web/gui/src/main/webapp/app/view/topo/topo.js b/web/gui/src/main/webapp/app/view/topo/topo.js index 4ce83485b3..0579a989c9 100644 --- a/web/gui/src/main/webapp/app/view/topo/topo.js +++ b/web/gui/src/main/webapp/app/view/topo/topo.js @@ -49,8 +49,9 @@ H: [tfs.toggleHosts, 'Toggle host visibility'], M: [tfs.toggleOffline, 'Toggle offline visibility'], - B: [toggleMap, 'Toggle background map'], P: [tfs.togglePorts, 'Toggle Port Highlighting'], + dash: [tfs.showBadLinks, 'Show bad links'], + B: [toggleMap, 'Toggle background map'], //X: [toggleNodeLock, 'Lock / unlock node positions'], Z: [tos.toggleOblique, 'Toggle oblique view (Experimental)'], @@ -73,7 +74,7 @@ _keyListener: ttbs.keyListener, _helpFormat: [ - ['I', 'O', 'D', '-', 'H', 'M', 'P', 'B' ], + ['I', 'O', 'D', '-', 'H', 'M', 'P', 'dash', 'B' ], ['X', 'Z', 'L', 'U', 'R', '-', 'dot'], ['V', 'rightArrow', 'leftArrow', 'W', 'A', 'F', '-', 'E' ] ] diff --git a/web/gui/src/main/webapp/app/view/topo/topoForce.js b/web/gui/src/main/webapp/app/view/topo/topoForce.js index 11f4934429..bbc697daae 100644 --- a/web/gui/src/main/webapp/app/view/topo/topoForce.js +++ b/web/gui/src/main/webapp/app/view/topo/topoForce.js @@ -23,7 +23,7 @@ 'use strict'; // injected refs - var $log, fs, sus, is, ts, flash, wss, + var $log, $timeout, fs, sus, is, ts, flash, wss, tis, tms, td3, tss, tts, tos, fltr, tls, icfg, uplink, svg; @@ -263,6 +263,7 @@ online = ldata.online(), delay = immediate ? 0 : 1000; + // TODO: understand why el is sometimes undefined on addLink events... el.classed('link', true); el.classed('inactive', !online); el.classed(allLinkTypes, false); @@ -450,6 +451,21 @@ // d3.selectAll('svg .portText').classed('inactive', b); } + function showBadLinks() { + var badLinks = tms.findBadLinks(); + flash.flash('Bad Links: ' + badLinks.length); + $log.debug('Bad Link List (' + badLinks.length + '):'); + badLinks.forEach(function (d) { + $log.debug('bad link: (' + d.bad + ') ' + d.key, d); + if (d.el) { + d.el.attr('stroke-width', linkScale(2.8)) + .attr('stroke', 'red'); + } + }); + // back to normal after 2 seconds... + $timeout(updateLinks, 2000); + } + // ========================================== function updateNodes() { @@ -749,15 +765,16 @@ angular.module('ovTopo') .factory('TopoForceService', - ['$log', 'FnService', 'SvgUtilService', 'IconService', 'ThemeService', - 'FlashService', 'WebSocketService', + ['$log', '$timeout', 'FnService', 'SvgUtilService', 'IconService', + 'ThemeService', 'FlashService', 'WebSocketService', 'TopoInstService', 'TopoModelService', 'TopoD3Service', 'TopoSelectService', 'TopoTrafficService', 'TopoObliqueService', 'TopoFilterService', 'TopoLinkService', - function (_$log_, _fs_, _sus_, _is_, _ts_, _flash_, _wss_, + function (_$log_, _$timeout_, _fs_, _sus_, _is_, _ts_, _flash_, _wss_, _tis_, _tms_, _td3_, _tss_, _tts_, _tos_, _fltr_, _tls_) { $log = _$log_; + $timeout = _$timeout_; fs = _fs_; sus = _sus_; is = _is_; @@ -874,6 +891,7 @@ cycleDeviceLabels: cycleDeviceLabels, unpin: unpin, showMastership: showMastership, + showBadLinks: showBadLinks, addDevice: addDevice, updateDevice: updateDevice, diff --git a/web/gui/src/main/webapp/app/view/topo/topoModel.js b/web/gui/src/main/webapp/app/view/topo/topoModel.js index 0a75652e00..6bec7e8b18 100644 --- a/web/gui/src/main/webapp/app/view/topo/topoModel.js +++ b/web/gui/src/main/webapp/app/view/topo/topoModel.js @@ -341,15 +341,37 @@ } function findAttachedLinks(devId) { - var links = []; + var lnks = []; links.forEach(function (d) { if (d.source.id === devId || d.target.id === devId) { - links.push(d); + lnks.push(d); } }); - return links; + return lnks; } + // returns one-way links or where the internal link types differ + function findBadLinks() { + var lnks = [], + src, tgt; + links.forEach(function (d) { + // NOTE: skip edge links, which are synthesized + if (d.type() !== 'hostLink') { + delete d.bad; + src = d.fromSource; + tgt = d.fromTarget; + if (src && !tgt) { + d.bad = 'missing link'; + } else if (src.type !== tgt.type) { + d.bad = 'type mismatch'; + } + if (d.bad) { + lnks.push(d); + } + } + }); + return lnks; + } // ========================== // Module definition @@ -394,7 +416,8 @@ findLinkById: findLinkById, findDevices: findDevices, findAttachedHosts: findAttachedHosts, - findAttachedLinks: findAttachedLinks + findAttachedLinks: findAttachedLinks, + findBadLinks: findBadLinks } }]); }());