GUI -- TopoView - Migrated more helper functions to topoModel.js.
Change-Id: I902c3561210c46fd23c6f6f01323d003dacefc19
Showing
5 changed files
with
217 additions
and
169 deletions
| ... | @@ -61,7 +61,7 @@ | ... | @@ -61,7 +61,7 @@ |
| 61 | eh = api[eid]; | 61 | eh = api[eid]; |
| 62 | 62 | ||
| 63 | if (eh) { | 63 | if (eh) { |
| 64 | - $log.debug(' *EVENT* ', ev.payload); | 64 | + $log.debug(' *EVENT* ', eid, ev.payload); |
| 65 | eh(ev.payload); | 65 | eh(ev.payload); |
| 66 | } else { | 66 | } else { |
| 67 | $log.warn('Unknown event (ignored):', ev); | 67 | $log.warn('Unknown event (ignored):', ev); | ... | ... |
| ... | @@ -70,6 +70,7 @@ | ... | @@ -70,6 +70,7 @@ |
| 70 | revLinkToKey: {} | 70 | revLinkToKey: {} |
| 71 | }, | 71 | }, |
| 72 | lu = network.lookup, // shorthand | 72 | lu = network.lookup, // shorthand |
| 73 | + rlk = network.revLinkToKey, | ||
| 73 | deviceLabelIndex = 0, // for device label cycling | 74 | deviceLabelIndex = 0, // for device label cycling |
| 74 | hostLabelIndex = 0, // for host label cycling | 75 | hostLabelIndex = 0, // for host label cycling |
| 75 | showHosts = true, // whether hosts are displayed | 76 | showHosts = true, // whether hosts are displayed |
| ... | @@ -134,9 +135,6 @@ | ... | @@ -134,9 +135,6 @@ |
| 134 | d = tms.createDeviceNode(data); | 135 | d = tms.createDeviceNode(data); |
| 135 | network.nodes.push(d); | 136 | network.nodes.push(d); |
| 136 | lu[id] = d; | 137 | lu[id] = d; |
| 137 | - | ||
| 138 | - $log.debug("Created new device.. ", d.id, d.x, d.y); | ||
| 139 | - | ||
| 140 | updateNodes(); | 138 | updateNodes(); |
| 141 | fStart(); | 139 | fStart(); |
| 142 | } | 140 | } |
| ... | @@ -154,7 +152,7 @@ | ... | @@ -154,7 +152,7 @@ |
| 154 | } | 152 | } |
| 155 | updateNodes(); | 153 | updateNodes(); |
| 156 | if (wasOnline !== d.online) { | 154 | if (wasOnline !== d.online) { |
| 157 | - findAttachedLinks(d.id).forEach(restyleLinkElement); | 155 | + tms.findAttachedLinks(d.id).forEach(restyleLinkElement); |
| 158 | updateOfflineVisibility(d); | 156 | updateOfflineVisibility(d); |
| 159 | } | 157 | } |
| 160 | } else { | 158 | } else { |
| ... | @@ -188,16 +186,10 @@ | ... | @@ -188,16 +186,10 @@ |
| 188 | d = tms.createHostNode(data); | 186 | d = tms.createHostNode(data); |
| 189 | network.nodes.push(d); | 187 | network.nodes.push(d); |
| 190 | lu[id] = d; | 188 | lu[id] = d; |
| 191 | - | ||
| 192 | - $log.debug("Created new host.. ", d.id, d.x, d.y); | ||
| 193 | - | ||
| 194 | updateNodes(); | 189 | updateNodes(); |
| 195 | 190 | ||
| 196 | lnk = tms.createHostLink(data); | 191 | lnk = tms.createHostLink(data); |
| 197 | if (lnk) { | 192 | if (lnk) { |
| 198 | - | ||
| 199 | - $log.debug("Created new host-link.. ", lnk.key); | ||
| 200 | - | ||
| 201 | d.linkData = lnk; // cache ref on its host | 193 | d.linkData = lnk; // cache ref on its host |
| 202 | network.links.push(lnk); | 194 | network.links.push(lnk); |
| 203 | lu[d.ingress] = lnk; | 195 | lu[d.ingress] = lnk; |
| ... | @@ -235,7 +227,7 @@ | ... | @@ -235,7 +227,7 @@ |
| 235 | } | 227 | } |
| 236 | 228 | ||
| 237 | function addLink(data) { | 229 | function addLink(data) { |
| 238 | - var result = findLink(data, 'add'), | 230 | + var result = tms.findLink(data, 'add'), |
| 239 | bad = result.badLogic, | 231 | bad = result.badLogic, |
| 240 | d = result.ldata; | 232 | d = result.ldata; |
| 241 | 233 | ||
| ... | @@ -261,7 +253,7 @@ | ... | @@ -261,7 +253,7 @@ |
| 261 | } | 253 | } |
| 262 | 254 | ||
| 263 | function updateLink(data) { | 255 | function updateLink(data) { |
| 264 | - var result = findLink(data, 'update'), | 256 | + var result = tms.findLink(data, 'update'), |
| 265 | bad = result.badLogic; | 257 | bad = result.badLogic; |
| 266 | if (bad) { | 258 | if (bad) { |
| 267 | //logicError(bad + ': ' + link.id); | 259 | //logicError(bad + ': ' + link.id); |
| ... | @@ -271,7 +263,7 @@ | ... | @@ -271,7 +263,7 @@ |
| 271 | } | 263 | } |
| 272 | 264 | ||
| 273 | function removeLink(data) { | 265 | function removeLink(data) { |
| 274 | - var result = findLink(data, 'remove'), | 266 | + var result = tms.findLink(data, 'remove'), |
| 275 | bad = result.badLogic; | 267 | bad = result.badLogic; |
| 276 | if (bad) { | 268 | if (bad) { |
| 277 | // may have already removed link, if attached to removed device | 269 | // may have already removed link, if attached to removed device |
| ... | @@ -286,20 +278,10 @@ | ... | @@ -286,20 +278,10 @@ |
| 286 | function addLinkUpdate(ldata, link) { | 278 | function addLinkUpdate(ldata, link) { |
| 287 | // add link event, but we already have the reverse link installed | 279 | // add link event, but we already have the reverse link installed |
| 288 | ldata.fromTarget = link; | 280 | ldata.fromTarget = link; |
| 289 | - network.revLinkToKey[link.id] = ldata.key; | 281 | + rlk[link.id] = ldata.key; |
| 290 | restyleLinkElement(ldata); | 282 | restyleLinkElement(ldata); |
| 291 | } | 283 | } |
| 292 | 284 | ||
| 293 | - function makeNodeKey(d, what) { | ||
| 294 | - var port = what + 'Port'; | ||
| 295 | - return d[what] + '/' + d[port]; | ||
| 296 | - } | ||
| 297 | - | ||
| 298 | - function makeLinkKey(d, flipped) { | ||
| 299 | - var one = flipped ? makeNodeKey(d, 'dst') : makeNodeKey(d, 'src'), | ||
| 300 | - two = flipped ? makeNodeKey(d, 'src') : makeNodeKey(d, 'dst'); | ||
| 301 | - return one + '-' + two; | ||
| 302 | - } | ||
| 303 | 285 | ||
| 304 | var widthRatio = 1.4, | 286 | var widthRatio = 1.4, |
| 305 | linkScale = d3.scale.linear() | 287 | linkScale = d3.scale.linear() |
| ... | @@ -329,113 +311,7 @@ | ... | @@ -329,113 +311,7 @@ |
| 329 | .attr('stroke', linkConfig[th].baseColor); | 311 | .attr('stroke', linkConfig[th].baseColor); |
| 330 | } | 312 | } |
| 331 | 313 | ||
| 332 | - function findLinkById(id) { | ||
| 333 | - // check to see if this is a reverse lookup, else default to given id | ||
| 334 | - var key = network.revLinkToKey[id] || id; | ||
| 335 | - return key && lu[key]; | ||
| 336 | - } | ||
| 337 | 314 | ||
| 338 | - function findLink(linkData, op) { | ||
| 339 | - var key = makeLinkKey(linkData), | ||
| 340 | - keyrev = makeLinkKey(linkData, 1), | ||
| 341 | - link = lu[key], | ||
| 342 | - linkRev = lu[keyrev], | ||
| 343 | - result = {}, | ||
| 344 | - ldata = link || linkRev, | ||
| 345 | - rawLink; | ||
| 346 | - | ||
| 347 | - if (op === 'add') { | ||
| 348 | - if (link) { | ||
| 349 | - // trying to add a link that we already know about | ||
| 350 | - result.ldata = link; | ||
| 351 | - result.badLogic = 'addLink: link already added'; | ||
| 352 | - | ||
| 353 | - } else if (linkRev) { | ||
| 354 | - // we found the reverse of the link to be added | ||
| 355 | - result.ldata = linkRev; | ||
| 356 | - if (linkRev.fromTarget) { | ||
| 357 | - result.badLogic = 'addLink: link already added'; | ||
| 358 | - } | ||
| 359 | - } | ||
| 360 | - } else if (op === 'update') { | ||
| 361 | - if (!ldata) { | ||
| 362 | - result.badLogic = 'updateLink: link not found'; | ||
| 363 | - } else { | ||
| 364 | - rawLink = link ? ldata.fromSource : ldata.fromTarget; | ||
| 365 | - result.updateWith = function (data) { | ||
| 366 | - angular.extend(rawLink, data); | ||
| 367 | - restyleLinkElement(ldata); | ||
| 368 | - } | ||
| 369 | - } | ||
| 370 | - } else if (op === 'remove') { | ||
| 371 | - if (!ldata) { | ||
| 372 | - result.badLogic = 'removeLink: link not found'; | ||
| 373 | - } else { | ||
| 374 | - rawLink = link ? ldata.fromSource : ldata.fromTarget; | ||
| 375 | - | ||
| 376 | - if (!rawLink) { | ||
| 377 | - result.badLogic = 'removeLink: link not found'; | ||
| 378 | - | ||
| 379 | - } else { | ||
| 380 | - result.removeRawLink = function () { | ||
| 381 | - if (link) { | ||
| 382 | - // remove fromSource | ||
| 383 | - ldata.fromSource = null; | ||
| 384 | - if (ldata.fromTarget) { | ||
| 385 | - // promote target into source position | ||
| 386 | - ldata.fromSource = ldata.fromTarget; | ||
| 387 | - ldata.fromTarget = null; | ||
| 388 | - ldata.key = keyrev; | ||
| 389 | - delete network.lookup[key]; | ||
| 390 | - network.lookup[keyrev] = ldata; | ||
| 391 | - delete network.revLinkToKey[keyrev]; | ||
| 392 | - } | ||
| 393 | - } else { | ||
| 394 | - // remove fromTarget | ||
| 395 | - ldata.fromTarget = null; | ||
| 396 | - delete network.revLinkToKey[keyrev]; | ||
| 397 | - } | ||
| 398 | - if (ldata.fromSource) { | ||
| 399 | - restyleLinkElement(ldata); | ||
| 400 | - } else { | ||
| 401 | - removeLinkElement(ldata); | ||
| 402 | - } | ||
| 403 | - } | ||
| 404 | - } | ||
| 405 | - } | ||
| 406 | - } | ||
| 407 | - return result; | ||
| 408 | - } | ||
| 409 | - | ||
| 410 | - function findDevices(offlineOnly) { | ||
| 411 | - var a = []; | ||
| 412 | - network.nodes.forEach(function (d) { | ||
| 413 | - if (d.class === 'device' && !(offlineOnly && d.online)) { | ||
| 414 | - a.push(d); | ||
| 415 | - } | ||
| 416 | - }); | ||
| 417 | - return a; | ||
| 418 | - } | ||
| 419 | - | ||
| 420 | - function findAttachedHosts(devId) { | ||
| 421 | - var hosts = []; | ||
| 422 | - network.nodes.forEach(function (d) { | ||
| 423 | - if (d.class === 'host' && d.cp.device === devId) { | ||
| 424 | - hosts.push(d); | ||
| 425 | - } | ||
| 426 | - }); | ||
| 427 | - return hosts; | ||
| 428 | - } | ||
| 429 | - | ||
| 430 | - function findAttachedLinks(devId) { | ||
| 431 | - var links = []; | ||
| 432 | - network.links.forEach(function (d) { | ||
| 433 | - if (d.source.id === devId || d.target.id === devId) { | ||
| 434 | - links.push(d); | ||
| 435 | - } | ||
| 436 | - }); | ||
| 437 | - return links; | ||
| 438 | - } | ||
| 439 | 315 | ||
| 440 | function removeLinkElement(d) { | 316 | function removeLinkElement(d) { |
| 441 | var idx = fs.find(d.key, network.links, 'key'), | 317 | var idx = fs.find(d.key, network.links, 'key'), |
| ... | @@ -475,8 +351,8 @@ | ... | @@ -475,8 +351,8 @@ |
| 475 | function removeDeviceElement(d) { | 351 | function removeDeviceElement(d) { |
| 476 | var id = d.id; | 352 | var id = d.id; |
| 477 | // first, remove associated hosts and links.. | 353 | // first, remove associated hosts and links.. |
| 478 | - findAttachedHosts(id).forEach(removeHostElement); | 354 | + tms.findAttachedHosts(id).forEach(removeHostElement); |
| 479 | - findAttachedLinks(id).forEach(removeLinkElement); | 355 | + tms.findAttachedLinks(id).forEach(removeLinkElement); |
| 480 | 356 | ||
| 481 | // remove from lookup cache | 357 | // remove from lookup cache |
| 482 | delete lu[id]; | 358 | delete lu[id]; |
| ... | @@ -485,7 +361,7 @@ | ... | @@ -485,7 +361,7 @@ |
| 485 | network.nodes.splice(idx, 1); | 361 | network.nodes.splice(idx, 1); |
| 486 | 362 | ||
| 487 | if (!network.nodes.length) { | 363 | if (!network.nodes.length) { |
| 488 | - xlink.showNoDevs(true); | 364 | + uplink.showNoDevs(true); |
| 489 | } | 365 | } |
| 490 | 366 | ||
| 491 | // remove from SVG | 367 | // remove from SVG |
| ... | @@ -502,11 +378,11 @@ | ... | @@ -502,11 +378,11 @@ |
| 502 | function updDev(d, show) { | 378 | function updDev(d, show) { |
| 503 | sus.makeVisible(d.el, show); | 379 | sus.makeVisible(d.el, show); |
| 504 | 380 | ||
| 505 | - findAttachedLinks(d.id).forEach(function (link) { | 381 | + tms.findAttachedLinks(d.id).forEach(function (link) { |
| 506 | b = show && ((link.type() !== 'hostLink') || showHosts); | 382 | b = show && ((link.type() !== 'hostLink') || showHosts); |
| 507 | sus.makeVisible(link.el, b); | 383 | sus.makeVisible(link.el, b); |
| 508 | }); | 384 | }); |
| 509 | - findAttachedHosts(d.id).forEach(function (host) { | 385 | + tms.findAttachedHosts(d.id).forEach(function (host) { |
| 510 | b = show && showHosts; | 386 | b = show && showHosts; |
| 511 | sus.makeVisible(host.el, b); | 387 | sus.makeVisible(host.el, b); |
| 512 | }); | 388 | }); |
| ... | @@ -517,7 +393,7 @@ | ... | @@ -517,7 +393,7 @@ |
| 517 | updDev(dev, dev.online || showOffline); | 393 | updDev(dev, dev.online || showOffline); |
| 518 | } else { | 394 | } else { |
| 519 | // updating all offline devices | 395 | // updating all offline devices |
| 520 | - findDevices(true).forEach(function (d) { | 396 | + tms.findDevices(true).forEach(function (d) { |
| 521 | updDev(d, showOffline); | 397 | updDev(d, showOffline); |
| 522 | }); | 398 | }); |
| 523 | } | 399 | } |
| ... | @@ -532,12 +408,7 @@ | ... | @@ -532,12 +408,7 @@ |
| 532 | // attach the x, y, longitude, latitude... | 408 | // attach the x, y, longitude, latitude... |
| 533 | if (!clearPos) { | 409 | if (!clearPos) { |
| 534 | ll = tms.lngLatFromCoord([d.x, d.y]); | 410 | ll = tms.lngLatFromCoord([d.x, d.y]); |
| 535 | - metaUi = { | 411 | + metaUi = {x: d.x, y: d.y, lng: ll[0], lat: ll[1]}; |
| 536 | - x: d.x, | ||
| 537 | - y: d.y, | ||
| 538 | - lng: ll[0], | ||
| 539 | - lat: ll[1] | ||
| 540 | - }; | ||
| 541 | } | 412 | } |
| 542 | d.metaUi = metaUi; | 413 | d.metaUi = metaUi; |
| 543 | uplink.sendEvent('updateMeta', { | 414 | uplink.sendEvent('updateMeta', { |
| ... | @@ -691,7 +562,7 @@ | ... | @@ -691,7 +562,7 @@ |
| 691 | 562 | ||
| 692 | function cycleDeviceLabels() { | 563 | function cycleDeviceLabels() { |
| 693 | deviceLabelIndex = (deviceLabelIndex+1) % 3; | 564 | deviceLabelIndex = (deviceLabelIndex+1) % 3; |
| 694 | - findDevices().forEach(function (d) { | 565 | + tms.findDevices().forEach(function (d) { |
| 695 | updateDeviceLabel(d); | 566 | updateDeviceLabel(d); |
| 696 | }); | 567 | }); |
| 697 | } | 568 | } |
| ... | @@ -1107,7 +978,7 @@ | ... | @@ -1107,7 +978,7 @@ |
| 1107 | }, | 978 | }, |
| 1108 | linkLabelAttr: { | 979 | linkLabelAttr: { |
| 1109 | transform: function (d) { | 980 | transform: function (d) { |
| 1110 | - var lnk = findLinkById(d.key); | 981 | + var lnk = tms.findLinkById(d.key); |
| 1111 | if (lnk) { | 982 | if (lnk) { |
| 1112 | return transformLabel({ | 983 | return transformLabel({ |
| 1113 | x1: lnk.source.x, | 984 | x1: lnk.source.x, |
| ... | @@ -1223,6 +1094,15 @@ | ... | @@ -1223,6 +1094,15 @@ |
| 1223 | // ========================== | 1094 | // ========================== |
| 1224 | // Module definition | 1095 | // Module definition |
| 1225 | 1096 | ||
| 1097 | + function mkModelApi(uplink) { | ||
| 1098 | + return { | ||
| 1099 | + projection: uplink.projection, | ||
| 1100 | + network: network, | ||
| 1101 | + restyleLinkElement: restyleLinkElement, | ||
| 1102 | + removeLinkElement: removeLinkElement | ||
| 1103 | + }; | ||
| 1104 | + } | ||
| 1105 | + | ||
| 1226 | angular.module('ovTopo') | 1106 | angular.module('ovTopo') |
| 1227 | .factory('TopoForceService', | 1107 | .factory('TopoForceService', |
| 1228 | ['$log', 'FnService', 'SvgUtilService', 'IconService', 'ThemeService', | 1108 | ['$log', 'FnService', 'SvgUtilService', 'IconService', 'ThemeService', |
| ... | @@ -1241,7 +1121,7 @@ | ... | @@ -1241,7 +1121,7 @@ |
| 1241 | icfg = is.iconConfig(); | 1121 | icfg = is.iconConfig(); |
| 1242 | 1122 | ||
| 1243 | // forceG is the SVG group to display the force layout in | 1123 | // forceG is the SVG group to display the force layout in |
| 1244 | - // xlink is the cross-link api from the main topo source file | 1124 | + // uplink is the api from the main topo source file |
| 1245 | // dim is the initial dimensions of the SVG as [w,h] | 1125 | // dim is the initial dimensions of the SVG as [w,h] |
| 1246 | // opts are, well, optional :) | 1126 | // opts are, well, optional :) |
| 1247 | function initForce(forceG, _uplink_, _dim_, opts) { | 1127 | function initForce(forceG, _uplink_, _dim_, opts) { |
| ... | @@ -1250,10 +1130,7 @@ | ... | @@ -1250,10 +1130,7 @@ |
| 1250 | 1130 | ||
| 1251 | $log.debug('initForce().. dim = ' + dim); | 1131 | $log.debug('initForce().. dim = ' + dim); |
| 1252 | 1132 | ||
| 1253 | - tms.initModel({ | 1133 | + tms.initModel(mkModelApi(uplink), dim); |
| 1254 | - projection: uplink.projection, | ||
| 1255 | - lookup: network.lookup | ||
| 1256 | - }, dim); | ||
| 1257 | 1134 | ||
| 1258 | settings = angular.extend({}, defaultSettings, opts); | 1135 | settings = angular.extend({}, defaultSettings, opts); |
| 1259 | 1136 | ... | ... |
| ... | @@ -26,6 +26,15 @@ | ... | @@ -26,6 +26,15 @@ |
| 26 | // injected refs | 26 | // injected refs |
| 27 | var $log, fs, rnd, api; | 27 | var $log, fs, rnd, api; |
| 28 | 28 | ||
| 29 | + // shorthand | ||
| 30 | + var lu, rlk, nodes, links; | ||
| 31 | + | ||
| 32 | + // api: | ||
| 33 | + // projection: func() | ||
| 34 | + // network {...} | ||
| 35 | + // restyleLinkElement: func(ldata) | ||
| 36 | + // removeLinkElement: func(ldata) | ||
| 37 | + | ||
| 29 | var dim; // dimensions of layout, as [w,h] | 38 | var dim; // dimensions of layout, as [w,h] |
| 30 | 39 | ||
| 31 | // configuration 'constants' | 40 | // configuration 'constants' |
| ... | @@ -95,7 +104,7 @@ | ... | @@ -95,7 +104,7 @@ |
| 95 | } | 104 | } |
| 96 | 105 | ||
| 97 | function getDevice(cp) { | 106 | function getDevice(cp) { |
| 98 | - var d = api.lookup[cp.device]; | 107 | + var d = lu[cp.device]; |
| 99 | return d || rand(); | 108 | return d || rand(); |
| 100 | } | 109 | } |
| 101 | 110 | ||
| ... | @@ -194,8 +203,8 @@ | ... | @@ -194,8 +203,8 @@ |
| 194 | 203 | ||
| 195 | 204 | ||
| 196 | function linkEndPoints(srcId, dstId) { | 205 | function linkEndPoints(srcId, dstId) { |
| 197 | - var srcNode = api.lookup[srcId], | 206 | + var srcNode = lu[srcId], |
| 198 | - dstNode = api.lookup[dstId], | 207 | + dstNode = lu[dstId], |
| 199 | sMiss = !srcNode ? missMsg('src', srcId) : '', | 208 | sMiss = !srcNode ? missMsg('src', srcId) : '', |
| 200 | dMiss = !dstNode ? missMsg('dst', dstId) : ''; | 209 | dMiss = !dstNode ? missMsg('dst', dstId) : ''; |
| 201 | 210 | ||
| ... | @@ -218,6 +227,127 @@ | ... | @@ -218,6 +227,127 @@ |
| 218 | return '\n[' + what + '] "' + id + '" missing'; | 227 | return '\n[' + what + '] "' + id + '" missing'; |
| 219 | } | 228 | } |
| 220 | 229 | ||
| 230 | + | ||
| 231 | + function makeNodeKey(d, what) { | ||
| 232 | + var port = what + 'Port'; | ||
| 233 | + return d[what] + '/' + d[port]; | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + function makeLinkKey(d, flipped) { | ||
| 237 | + var one = flipped ? makeNodeKey(d, 'dst') : makeNodeKey(d, 'src'), | ||
| 238 | + two = flipped ? makeNodeKey(d, 'src') : makeNodeKey(d, 'dst'); | ||
| 239 | + return one + '-' + two; | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + function findLinkById(id) { | ||
| 243 | + // check to see if this is a reverse lookup, else default to given id | ||
| 244 | + var key = rlk[id] || id; | ||
| 245 | + return key && lu[key]; | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | + function findLink(linkData, op) { | ||
| 249 | + var key = makeLinkKey(linkData), | ||
| 250 | + keyrev = makeLinkKey(linkData, 1), | ||
| 251 | + link = lu[key], | ||
| 252 | + linkRev = lu[keyrev], | ||
| 253 | + result = {}, | ||
| 254 | + ldata = link || linkRev, | ||
| 255 | + rawLink; | ||
| 256 | + | ||
| 257 | + if (op === 'add') { | ||
| 258 | + if (link) { | ||
| 259 | + // trying to add a link that we already know about | ||
| 260 | + result.ldata = link; | ||
| 261 | + result.badLogic = 'addLink: link already added'; | ||
| 262 | + | ||
| 263 | + } else if (linkRev) { | ||
| 264 | + // we found the reverse of the link to be added | ||
| 265 | + result.ldata = linkRev; | ||
| 266 | + if (linkRev.fromTarget) { | ||
| 267 | + result.badLogic = 'addLink: link already added'; | ||
| 268 | + } | ||
| 269 | + } | ||
| 270 | + } else if (op === 'update') { | ||
| 271 | + if (!ldata) { | ||
| 272 | + result.badLogic = 'updateLink: link not found'; | ||
| 273 | + } else { | ||
| 274 | + rawLink = link ? ldata.fromSource : ldata.fromTarget; | ||
| 275 | + result.updateWith = function (data) { | ||
| 276 | + angular.extend(rawLink, data); | ||
| 277 | + api.restyleLinkElement(ldata); | ||
| 278 | + } | ||
| 279 | + } | ||
| 280 | + } else if (op === 'remove') { | ||
| 281 | + if (!ldata) { | ||
| 282 | + result.badLogic = 'removeLink: link not found'; | ||
| 283 | + } else { | ||
| 284 | + rawLink = link ? ldata.fromSource : ldata.fromTarget; | ||
| 285 | + | ||
| 286 | + if (!rawLink) { | ||
| 287 | + result.badLogic = 'removeLink: link not found'; | ||
| 288 | + | ||
| 289 | + } else { | ||
| 290 | + result.removeRawLink = function () { | ||
| 291 | + if (link) { | ||
| 292 | + // remove fromSource | ||
| 293 | + ldata.fromSource = null; | ||
| 294 | + if (ldata.fromTarget) { | ||
| 295 | + // promote target into source position | ||
| 296 | + ldata.fromSource = ldata.fromTarget; | ||
| 297 | + ldata.fromTarget = null; | ||
| 298 | + ldata.key = keyrev; | ||
| 299 | + delete lu[key]; | ||
| 300 | + lu[keyrev] = ldata; | ||
| 301 | + delete rlk[keyrev]; | ||
| 302 | + } | ||
| 303 | + } else { | ||
| 304 | + // remove fromTarget | ||
| 305 | + ldata.fromTarget = null; | ||
| 306 | + delete rlk[keyrev]; | ||
| 307 | + } | ||
| 308 | + if (ldata.fromSource) { | ||
| 309 | + api.restyleLinkElement(ldata); | ||
| 310 | + } else { | ||
| 311 | + api.removeLinkElement(ldata); | ||
| 312 | + } | ||
| 313 | + } | ||
| 314 | + } | ||
| 315 | + } | ||
| 316 | + } | ||
| 317 | + return result; | ||
| 318 | + } | ||
| 319 | + | ||
| 320 | + function findDevices(offlineOnly) { | ||
| 321 | + var a = []; | ||
| 322 | + nodes.forEach(function (d) { | ||
| 323 | + if (d.class === 'device' && !(offlineOnly && d.online)) { | ||
| 324 | + a.push(d); | ||
| 325 | + } | ||
| 326 | + }); | ||
| 327 | + return a; | ||
| 328 | + } | ||
| 329 | + | ||
| 330 | + function findAttachedHosts(devId) { | ||
| 331 | + var hosts = []; | ||
| 332 | + nodes.forEach(function (d) { | ||
| 333 | + if (d.class === 'host' && d.cp.device === devId) { | ||
| 334 | + hosts.push(d); | ||
| 335 | + } | ||
| 336 | + }); | ||
| 337 | + return hosts; | ||
| 338 | + } | ||
| 339 | + | ||
| 340 | + function findAttachedLinks(devId) { | ||
| 341 | + var links = []; | ||
| 342 | + links.forEach(function (d) { | ||
| 343 | + if (d.source.id === devId || d.target.id === devId) { | ||
| 344 | + links.push(d); | ||
| 345 | + } | ||
| 346 | + }); | ||
| 347 | + return links; | ||
| 348 | + } | ||
| 349 | + | ||
| 350 | + | ||
| 221 | // ========================== | 351 | // ========================== |
| 222 | // Module definition | 352 | // Module definition |
| 223 | 353 | ||
| ... | @@ -233,6 +363,10 @@ | ... | @@ -233,6 +363,10 @@ |
| 233 | function initModel(_api_, _dim_) { | 363 | function initModel(_api_, _dim_) { |
| 234 | api = _api_; | 364 | api = _api_; |
| 235 | dim = _dim_; | 365 | dim = _dim_; |
| 366 | + lu = api.network.lookup; | ||
| 367 | + rlk = api.network.revLinkToKey; | ||
| 368 | + nodes = api.network.nodes; | ||
| 369 | + links = api.network.links; | ||
| 236 | } | 370 | } |
| 237 | 371 | ||
| 238 | function newDim(_dim_) { | 372 | function newDim(_dim_) { |
| ... | @@ -250,6 +384,11 @@ | ... | @@ -250,6 +384,11 @@ |
| 250 | createLink: createLink, | 384 | createLink: createLink, |
| 251 | coordFromLngLat: coordFromLngLat, | 385 | coordFromLngLat: coordFromLngLat, |
| 252 | lngLatFromCoord: lngLatFromCoord, | 386 | lngLatFromCoord: lngLatFromCoord, |
| 387 | + findLink: findLink, | ||
| 388 | + findLinkById: findLinkById, | ||
| 389 | + findDevices: findDevices, | ||
| 390 | + findAttachedHosts: findAttachedHosts, | ||
| 391 | + findAttachedLinks: findAttachedLinks | ||
| 253 | } | 392 | } |
| 254 | }]); | 393 | }]); |
| 255 | }()); | 394 | }()); | ... | ... |
| ... | @@ -45,23 +45,22 @@ describe('factory: view/topo/topoModel.js', function() { | ... | @@ -45,23 +45,22 @@ describe('factory: view/topo/topoModel.js', function() { |
| 45 | return [xy[0] + 2000, xy[1] + 3000]; | 45 | return [xy[0] + 2000, xy[1] + 3000]; |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | - // our test device lookup | 48 | + // our test devices and hosts: |
| 49 | - var lu = { | 49 | + var dev1 = { |
| 50 | - dev1: { | ||
| 51 | 'class': 'device', | 50 | 'class': 'device', |
| 52 | id: 'dev1', | 51 | id: 'dev1', |
| 53 | x: 17, | 52 | x: 17, |
| 54 | y: 27, | 53 | y: 27, |
| 55 | online: true | 54 | online: true |
| 56 | }, | 55 | }, |
| 57 | - dev2: { | 56 | + dev2 = { |
| 58 | 'class': 'device', | 57 | 'class': 'device', |
| 59 | id: 'dev2', | 58 | id: 'dev2', |
| 60 | x: 18, | 59 | x: 18, |
| 61 | y: 28, | 60 | y: 28, |
| 62 | online: true | 61 | online: true |
| 63 | }, | 62 | }, |
| 64 | - host1: { | 63 | + host1 = { |
| 65 | 'class': 'host', | 64 | 'class': 'host', |
| 66 | id: 'host1', | 65 | id: 'host1', |
| 67 | x: 23, | 66 | x: 23, |
| ... | @@ -72,7 +71,7 @@ describe('factory: view/topo/topoModel.js', function() { | ... | @@ -72,7 +71,7 @@ describe('factory: view/topo/topoModel.js', function() { |
| 72 | }, | 71 | }, |
| 73 | ingress: 'dev1/7-host1' | 72 | ingress: 'dev1/7-host1' |
| 74 | }, | 73 | }, |
| 75 | - host2: { | 74 | + host2 = { |
| 76 | 'class': 'host', | 75 | 'class': 'host', |
| 77 | id: 'host2', | 76 | id: 'host2', |
| 78 | x: 24, | 77 | x: 24, |
| ... | @@ -82,13 +81,20 @@ describe('factory: view/topo/topoModel.js', function() { | ... | @@ -82,13 +81,20 @@ describe('factory: view/topo/topoModel.js', function() { |
| 82 | port: 0 | 81 | port: 0 |
| 83 | }, | 82 | }, |
| 84 | ingress: 'dev0/0-host2' | 83 | ingress: 'dev0/0-host2' |
| 85 | - } | 84 | + }; |
| 86 | - }; | 85 | + |
| 87 | 86 | ||
| 88 | // our test api | 87 | // our test api |
| 89 | var api = { | 88 | var api = { |
| 90 | projection: function () { return mockProjection; }, | 89 | projection: function () { return mockProjection; }, |
| 91 | - lookup: lu | 90 | + network: { |
| 91 | + nodes: [dev1, dev2, host1, host2], | ||
| 92 | + links: [], | ||
| 93 | + lookup: {dev1: dev1, dev2: dev2, host1: host1, host2: host2}, | ||
| 94 | + revLinkToKey: {} | ||
| 95 | + }, | ||
| 96 | + restyleLinkElement: function () {}, | ||
| 97 | + removeLinkElement: function () {} | ||
| 92 | }; | 98 | }; |
| 93 | 99 | ||
| 94 | // our test dimensions and well known locations.. | 100 | // our test dimensions and well known locations.. |
| ... | @@ -204,7 +210,9 @@ describe('factory: view/topo/topoModel.js', function() { | ... | @@ -204,7 +210,9 @@ describe('factory: view/topo/topoModel.js', function() { |
| 204 | 'initModel', 'newDim', | 210 | 'initModel', 'newDim', |
| 205 | 'positionNode', 'createDeviceNode', 'createHostNode', | 211 | 'positionNode', 'createDeviceNode', 'createHostNode', |
| 206 | 'createHostLink', 'createLink', | 212 | 'createHostLink', 'createLink', |
| 207 | - 'coordFromLngLat', 'lngLatFromCoord' | 213 | + 'coordFromLngLat', 'lngLatFromCoord', |
| 214 | + 'findLink', 'findLinkById', 'findDevices', | ||
| 215 | + 'findAttachedHosts', 'findAttachedLinks' | ||
| 208 | ])).toBeTruthy(); | 216 | ])).toBeTruthy(); |
| 209 | }); | 217 | }); |
| 210 | 218 | ||
| ... | @@ -348,9 +356,9 @@ describe('factory: view/topo/topoModel.js', function() { | ... | @@ -348,9 +356,9 @@ describe('factory: view/topo/topoModel.js', function() { |
| 348 | // === unit tests for createHostLink() | 356 | // === unit tests for createHostLink() |
| 349 | 357 | ||
| 350 | it('should create a basic host link', function () { | 358 | it('should create a basic host link', function () { |
| 351 | - var link = tms.createHostLink(lu.host1); | 359 | + var link = tms.createHostLink(host1); |
| 352 | - expect(link.source).toEqual(lu.host1); | 360 | + expect(link.source).toEqual(host1); |
| 353 | - expect(link.target).toEqual(lu.dev1); | 361 | + expect(link.target).toEqual(dev1); |
| 354 | expect(link).toHaveEndPoints(host1Loc, dev1Loc); | 362 | expect(link).toHaveEndPoints(host1Loc, dev1Loc); |
| 355 | expect(link.key).toEqual('dev1/7-host1'); | 363 | expect(link.key).toEqual('dev1/7-host1'); |
| 356 | expect(link.class).toEqual('link'); | 364 | expect(link.class).toEqual('link'); |
| ... | @@ -361,7 +369,7 @@ describe('factory: view/topo/topoModel.js', function() { | ... | @@ -361,7 +369,7 @@ describe('factory: view/topo/topoModel.js', function() { |
| 361 | 369 | ||
| 362 | it('should return null for failed endpoint lookup', function () { | 370 | it('should return null for failed endpoint lookup', function () { |
| 363 | spyOn($log, 'error'); | 371 | spyOn($log, 'error'); |
| 364 | - var link = tms.createHostLink(lu.host2); | 372 | + var link = tms.createHostLink(host2); |
| 365 | expect(link).toBeNull(); | 373 | expect(link).toBeNull(); |
| 366 | expect($log.error).toHaveBeenCalledWith( | 374 | expect($log.error).toHaveBeenCalledWith( |
| 367 | 'Node(s) not on map for link:\n[dst] "dev0" missing' | 375 | 'Node(s) not on map for link:\n[dst] "dev0" missing' |
| ... | @@ -389,8 +397,8 @@ describe('factory: view/topo/topoModel.js', function() { | ... | @@ -389,8 +397,8 @@ describe('factory: view/topo/topoModel.js', function() { |
| 389 | linkWidth: 1.5 | 397 | linkWidth: 1.5 |
| 390 | }, | 398 | }, |
| 391 | link = tms.createLink(linkData); | 399 | link = tms.createLink(linkData); |
| 392 | - expect(link.source).toEqual(lu.dev1); | 400 | + expect(link.source).toEqual(dev1); |
| 393 | - expect(link.target).toEqual(lu.dev2); | 401 | + expect(link.target).toEqual(dev2); |
| 394 | expect(link).toHaveEndPoints(dev1Loc, dev2Loc); | 402 | expect(link).toHaveEndPoints(dev1Loc, dev2Loc); |
| 395 | expect(link.key).toEqual('baz'); | 403 | expect(link.key).toEqual('baz'); |
| 396 | expect(link.class).toEqual('link'); | 404 | expect(link.class).toEqual('link'); |
| ... | @@ -400,4 +408,5 @@ describe('factory: view/topo/topoModel.js', function() { | ... | @@ -400,4 +408,5 @@ describe('factory: view/topo/topoModel.js', function() { |
| 400 | expect(link.linkWidth()).toEqual(1.5); | 408 | expect(link.linkWidth()).toEqual(1.5); |
| 401 | }); | 409 | }); |
| 402 | 410 | ||
| 411 | + // TODO: more unit tests for additional functions.... | ||
| 403 | }); | 412 | }); | ... | ... |
| 1 | +{ | ||
| 2 | + "event": "removeDevice", | ||
| 3 | + "payload": { | ||
| 4 | + "id": "of:0000ffffffff0008", | ||
| 5 | + "type": "switch", | ||
| 6 | + "online": false, | ||
| 7 | + "master": "myInstA", | ||
| 8 | + "location": { | ||
| 9 | + "type": "latlng", | ||
| 10 | + "lat": 37.7833, | ||
| 11 | + "lng": -122.4167 | ||
| 12 | + }, | ||
| 13 | + "labels": [ | ||
| 14 | + "", | ||
| 15 | + "sw-8", | ||
| 16 | + "0000ffffffff0008" | ||
| 17 | + ], | ||
| 18 | + "metaUi": { | ||
| 19 | + "x": 520, | ||
| 20 | + "y": 350 | ||
| 21 | + } | ||
| 22 | + } | ||
| 23 | +} |
-
Please register or login to post a comment