GUI -- Completed ONOS Instance panel, and handling of updateInstance and removeInstance.
- minor refactorings and other cleanup. Change-Id: I4d0e467f71269f7fb91175e78d2c6af750bf9aad
Showing
8 changed files
with
218 additions
and
145 deletions
... | @@ -49,7 +49,7 @@ div.onosView.currentView { | ... | @@ -49,7 +49,7 @@ div.onosView.currentView { |
49 | #alerts { | 49 | #alerts { |
50 | display: none; | 50 | display: none; |
51 | position: absolute; | 51 | position: absolute; |
52 | - z-index: 2000; | 52 | + z-index: 1200; |
53 | opacity: 0.65; | 53 | opacity: 0.65; |
54 | background-color: #006; | 54 | background-color: #006; |
55 | color: white; | 55 | color: white; |
... | @@ -83,10 +83,12 @@ div.onosView.currentView { | ... | @@ -83,10 +83,12 @@ div.onosView.currentView { |
83 | color: #66d; | 83 | color: #66d; |
84 | } | 84 | } |
85 | 85 | ||
86 | +#floatPanels { | ||
87 | + z-index: 1100; | ||
88 | +} | ||
86 | 89 | ||
87 | #flyout { | 90 | #flyout { |
88 | position: absolute; | 91 | position: absolute; |
89 | - z-index: 100; | ||
90 | display: block; | 92 | display: block; |
91 | top: 10%; | 93 | top: 10%; |
92 | width: 280px; | 94 | width: 280px; | ... | ... |
... | @@ -785,8 +785,14 @@ | ... | @@ -785,8 +785,14 @@ |
785 | function pxHide() { | 785 | function pxHide() { |
786 | return (-20 - widthVal()) + 'px'; | 786 | return (-20 - widthVal()) + 'px'; |
787 | } | 787 | } |
788 | + function noPx(what) { | ||
789 | + return el.style(what).replace(/px$/, ''); | ||
790 | + } | ||
788 | function widthVal() { | 791 | function widthVal() { |
789 | - return el.style('width').replace(/px$/, ''); | 792 | + return noPx('width'); |
793 | + } | ||
794 | + function heightVal() { | ||
795 | + return noPx('height'); | ||
790 | } | 796 | } |
791 | 797 | ||
792 | fp = { | 798 | fp = { |
... | @@ -822,6 +828,12 @@ | ... | @@ -822,6 +828,12 @@ |
822 | return widthVal(); | 828 | return widthVal(); |
823 | } | 829 | } |
824 | el.style('width', w + 'px'); | 830 | el.style('width', w + 'px'); |
831 | + }, | ||
832 | + height: function (h) { | ||
833 | + if (h === undefined) { | ||
834 | + return heightVal(); | ||
835 | + } | ||
836 | + el.style('height', h + 'px'); | ||
825 | } | 837 | } |
826 | }; | 838 | }; |
827 | fpanels[id] = fp; | 839 | fpanels[id] = fp; | ... | ... |
... | @@ -318,8 +318,9 @@ svg .node.host circle { | ... | @@ -318,8 +318,9 @@ svg .node.host circle { |
318 | 318 | ||
319 | #topo-oibox div.onosInst { | 319 | #topo-oibox div.onosInst { |
320 | display: inline-block; | 320 | display: inline-block; |
321 | - width: 120px; | 321 | + width: 170px; |
322 | - height: 100px; | 322 | + height: 85px; |
323 | + cursor: pointer; | ||
323 | } | 324 | } |
324 | 325 | ||
325 | #topo-oibox svg rect { | 326 | #topo-oibox svg rect { |
... | @@ -350,75 +351,31 @@ svg .node.host circle { | ... | @@ -350,75 +351,31 @@ svg .node.host circle { |
350 | fill: #fff; | 351 | fill: #fff; |
351 | } | 352 | } |
352 | 353 | ||
353 | - | 354 | +#topo-oibox svg text { |
354 | -#topo-oibox .onosInst.mastership { | 355 | + text-anchor: middle; |
355 | - opacity: 0.3; | 356 | + fill: #888; |
356 | -} | ||
357 | -#topo-oibox .onosInst.mastership.affinity { | ||
358 | - opacity: 1.0; | ||
359 | -} | ||
360 | -#topo-oibox .onosInst.mastership.affinity svg rect { | ||
361 | - filter: url(#blue-glow); | ||
362 | } | 357 | } |
363 | - | 358 | +#topo-oibox .online svg text { |
364 | -/* ------------------------------------------------------ */ | 359 | + fill: #000; |
365 | -/* ------------------------------------------------------ */ | ||
366 | -/* ------------------------------------------------------ */ | ||
367 | - | ||
368 | -#topo-oibox .onosInst_OLD { | ||
369 | - position: relative; | ||
370 | - width: 88%; | ||
371 | - left: 4%; | ||
372 | - height: 80px; | ||
373 | - margin: 8px 0; | ||
374 | - cursor: pointer; | ||
375 | - | ||
376 | - -moz-border-radius: 12px; | ||
377 | - border-radius: 12px; | ||
378 | - | ||
379 | - /* theme-related */ | ||
380 | - color: #444; | ||
381 | - background-color: #ccc; | ||
382 | - border: 4px solid #aaa; | ||
383 | } | 360 | } |
384 | 361 | ||
385 | -#topo-oibox .onosInst_OLD .onosTitle { | 362 | +#topo-oibox svg text.instTitle { |
386 | - text-align: center; | 363 | + font-size: 11pt; |
387 | - font-size: 10pt; | 364 | + font-weight: bold; |
388 | - margin-top: 6px; | ||
389 | - color: #888; | ||
390 | } | 365 | } |
391 | - | 366 | +#topo-oibox svg text.instLabel { |
392 | -#topo-oibox .onosInst_OLD.online .onosTitle { | 367 | + font-size: 9pt; |
393 | - color: black; | 368 | + font-style: italic; |
394 | } | 369 | } |
395 | 370 | ||
396 | -#topo-oibox .onosInst_OLD svg .glyphIcon { | 371 | +#topo-oibox .onosInst.mastership { |
397 | - opacity: 0.5; | 372 | + opacity: 0.3; |
398 | - fill: black; | ||
399 | - stroke: none; | ||
400 | - fill-rule: evenodd; | ||
401 | -} | ||
402 | -#topo-oibox .onosInst_OLD.online svg .glyphIcon { | ||
403 | - opacity: 1; | ||
404 | - fill: black; | ||
405 | - stroke: none; | ||
406 | - fill-rule: evenodd; | ||
407 | } | 373 | } |
408 | - | 374 | +#topo-oibox .onosInst.mastership.affinity { |
409 | - | ||
410 | -#topo-oibox .onosInst_OLD.online img { | ||
411 | opacity: 1.0; | 375 | opacity: 1.0; |
412 | - padding: 3px; | ||
413 | } | 376 | } |
414 | - | 377 | +#topo-oibox .onosInst.mastership.affinity svg rect { |
415 | -#topo-oibox .onosInst_OLD img.ui { | 378 | + filter: url(#blue-glow); |
416 | - opacity: 1; | ||
417 | - position: absolute; | ||
418 | - top: 3px; | ||
419 | - right: 3px; | ||
420 | - width: 20px; | ||
421 | - height: 20px; | ||
422 | } | 379 | } |
423 | 380 | ||
424 | 381 | ... | ... |
... | @@ -580,7 +580,7 @@ | ... | @@ -580,7 +580,7 @@ |
580 | updateLink: updateLink, | 580 | updateLink: updateLink, |
581 | updateHost: updateHost, | 581 | updateHost: updateHost, |
582 | 582 | ||
583 | - removeInstance: stillToImplement, | 583 | + removeInstance: removeInstance, |
584 | removeDevice: stillToImplement, | 584 | removeDevice: stillToImplement, |
585 | removeLink: removeLink, | 585 | removeLink: removeLink, |
586 | removeHost: removeHost, | 586 | removeHost: removeHost, |
... | @@ -715,6 +715,23 @@ | ... | @@ -715,6 +715,23 @@ |
715 | } | 715 | } |
716 | 716 | ||
717 | // TODO: fold removeX(...) methods into base method - remove dup code | 717 | // TODO: fold removeX(...) methods into base method - remove dup code |
718 | + function removeInstance(data) { | ||
719 | + evTrace(data); | ||
720 | + var inst = data.payload, | ||
721 | + id = inst.id, | ||
722 | + instData = onosInstances[id]; | ||
723 | + if (instData) { | ||
724 | + var idx = find(id, onosOrder, 'id'); | ||
725 | + if (idx >= 0) { | ||
726 | + onosOrder.splice(idx, 1); | ||
727 | + } | ||
728 | + delete onosInstances[id]; | ||
729 | + updateInstances(); | ||
730 | + } else { | ||
731 | + logicError('updateInstance lookup fail. ID = "' + id + '"'); | ||
732 | + } | ||
733 | + } | ||
734 | + | ||
718 | function removeLink(data) { | 735 | function removeLink(data) { |
719 | evTrace(data); | 736 | evTrace(data); |
720 | var link = data.payload, | 737 | var link = data.payload, |
... | @@ -793,8 +810,10 @@ | ... | @@ -793,8 +810,10 @@ |
793 | function stillToImplement(data) { | 810 | function stillToImplement(data) { |
794 | var p = data.payload; | 811 | var p = data.payload; |
795 | note(data.event, p.id); | 812 | note(data.event, p.id); |
813 | + if (!config.useLiveData) { | ||
796 | network.view.alert('Not yet implemented: "' + data.event + '"'); | 814 | network.view.alert('Not yet implemented: "' + data.event + '"'); |
797 | } | 815 | } |
816 | + } | ||
798 | 817 | ||
799 | function unknownEvent(data) { | 818 | function unknownEvent(data) { |
800 | network.view.alert('Unknown event type: "' + data.event + '"'); | 819 | network.view.alert('Unknown event type: "' + data.event + '"'); |
... | @@ -966,56 +985,62 @@ | ... | @@ -966,56 +985,62 @@ |
966 | return true; | 985 | return true; |
967 | } | 986 | } |
968 | 987 | ||
969 | - // TODO: these should be moved out to utility module. | ||
970 | - function stripPx(s) { | ||
971 | - return s.replace(/px$/,''); | ||
972 | - } | ||
973 | 988 | ||
974 | - function appendUse(svg, ox, oy, dim, iid, cls) { | 989 | + // ============================== |
975 | - var use = svg.append('use').attr({ | 990 | + // onos instance panel functions |
976 | - transform: translate(ox,oy), | ||
977 | - 'xlink:href': iid, | ||
978 | - width: dim, | ||
979 | - height: dim | ||
980 | - }); | ||
981 | - if (cls) { | ||
982 | - use.classed(cls, true); | ||
983 | - } | ||
984 | - return use; | ||
985 | - } | ||
986 | 991 | ||
987 | - function appendGlyph(svg, ox, oy, dim, iid, cls) { | 992 | + var instCfg = { |
988 | - appendUse(svg, ox, oy, dim, iid, cls).classed('glyphIcon', true); | 993 | + rectPad: 8, |
989 | - } | 994 | + nodeOx: 9, |
995 | + nodeOy: 9, | ||
996 | + nodeDim: 40, | ||
997 | + birdOx: 19, | ||
998 | + birdOy: 21, | ||
999 | + birdDim: 21, | ||
1000 | + uiDy: 45, | ||
1001 | + titleDy: 30, | ||
1002 | + textYOff: 20, | ||
1003 | + textYSpc: 15 | ||
1004 | + }; | ||
990 | 1005 | ||
991 | - function appendBadge(svg, ox, oy, dim, iid, cls) { | 1006 | + function viewBox(dim) { |
992 | - appendUse(svg, ox, oy, dim, iid,cls ).classed('badgeIcon', true); | 1007 | + return '0 0 ' + dim.w + ' ' + dim.h; |
993 | } | 1008 | } |
994 | 1009 | ||
995 | - function attachUiBadge(svg) { | 1010 | + function instRectAttr(dim) { |
996 | - appendBadge(svg, 12, 50, 30, '#uiAttached', 'uiBadge'); | 1011 | + var pad = instCfg.rectPad; |
1012 | + return { | ||
1013 | + x: pad, | ||
1014 | + y: pad, | ||
1015 | + width: dim.w - pad*2, | ||
1016 | + height: dim.h - pad*2, | ||
1017 | + rx: 12 | ||
1018 | + }; | ||
997 | } | 1019 | } |
998 | 1020 | ||
999 | - // ============================== | 1021 | + function computeDim(self) { |
1000 | - // onos instance panel functions | 1022 | + var css = window.getComputedStyle(self); |
1001 | - var instW = 120; | 1023 | + return { |
1002 | - | 1024 | + w: stripPx(css.width), |
1003 | - function viewBox(w, h) { | 1025 | + h: stripPx(css.height) |
1004 | - return '0 0 ' + w + ' ' + h; | 1026 | + }; |
1005 | } | 1027 | } |
1006 | 1028 | ||
1007 | function updateInstances() { | 1029 | function updateInstances() { |
1008 | var onoses = oiBox.el.selectAll('.onosInst') | 1030 | var onoses = oiBox.el.selectAll('.onosInst') |
1009 | .data(onosOrder, function (d) { return d.id; }), | 1031 | .data(onosOrder, function (d) { return d.id; }), |
1010 | - boxW = instW * onosOrder.length; | 1032 | + instDim = {w:0,h:0}, |
1033 | + c = instCfg; | ||
1011 | 1034 | ||
1012 | - // adjust the width of the panel based on number of instances... | 1035 | + function nSw(n) { |
1013 | - oiBox.width(boxW); | 1036 | + return '# Switches: ' + n; |
1037 | + } | ||
1014 | 1038 | ||
1015 | // operate on existing onos instances if necessary | 1039 | // operate on existing onos instances if necessary |
1016 | onoses.each(function (d) { | 1040 | onoses.each(function (d) { |
1017 | var el = d3.select(this), | 1041 | var el = d3.select(this), |
1018 | svg = el.select('svg'); | 1042 | svg = el.select('svg'); |
1043 | + instDim = computeDim(this); | ||
1019 | 1044 | ||
1020 | // update online state | 1045 | // update online state |
1021 | el.classed('online', d.online); | 1046 | el.classed('online', d.online); |
... | @@ -1026,7 +1051,12 @@ | ... | @@ -1026,7 +1051,12 @@ |
1026 | attachUiBadge(svg); | 1051 | attachUiBadge(svg); |
1027 | } | 1052 | } |
1028 | 1053 | ||
1029 | - // TODO: update title and property values | 1054 | + function updAttr(id, value) { |
1055 | + svg.select('text.instLabel.'+id).text(value); | ||
1056 | + } | ||
1057 | + | ||
1058 | + updAttr('ip', d.ip); | ||
1059 | + updAttr('ns', nSw(d.switches)); | ||
1030 | }); | 1060 | }); |
1031 | 1061 | ||
1032 | 1062 | ||
... | @@ -1039,61 +1069,64 @@ | ... | @@ -1039,61 +1069,64 @@ |
1039 | 1069 | ||
1040 | entering.each(function (d) { | 1070 | entering.each(function (d) { |
1041 | var el = d3.select(this), | 1071 | var el = d3.select(this), |
1042 | - css = window.getComputedStyle(this), | 1072 | + rectAttr, |
1043 | - w = stripPx(css.width), | 1073 | + svg; |
1044 | - h = stripPx(css.height); | 1074 | + instDim = computeDim(this); |
1045 | - | 1075 | + rectAttr = instRectAttr(instDim); |
1046 | - var svg = el.append('svg').attr({ | 1076 | + |
1047 | - width: w, | 1077 | + svg = el.append('svg').attr({ |
1048 | - height: h, | 1078 | + width: instDim.w, |
1049 | - viewBox: viewBox(w, h) | 1079 | + height: instDim.h, |
1080 | + viewBox: viewBox(instDim) | ||
1050 | }); | 1081 | }); |
1051 | 1082 | ||
1052 | - svg.append('rect') | 1083 | + svg.append('rect').attr(rectAttr); |
1053 | - .attr({ | ||
1054 | - x: 8, | ||
1055 | - y: 8, | ||
1056 | - width: 104, | ||
1057 | - height: 84, | ||
1058 | - rx: 12 | ||
1059 | - }); | ||
1060 | 1084 | ||
1061 | - | 1085 | + appendGlyph(svg, c.nodeOx, c.nodeOy, c.nodeDim, '#node'); |
1062 | - appendGlyph(svg, 9, 9, 36, '#node'); | 1086 | + appendBadge(svg, c.birdOx, c.birdOy, c.birdDim, '#bird'); |
1063 | - appendBadge(svg, 17, 19, 21, '#bird'); | ||
1064 | 1087 | ||
1065 | if (d.uiAttached) { | 1088 | if (d.uiAttached) { |
1066 | attachUiBadge(svg); | 1089 | attachUiBadge(svg); |
1067 | } | 1090 | } |
1068 | 1091 | ||
1069 | - //svg.append('use') | 1092 | + var left = c.nodeOx + c.nodeDim, |
1070 | - // .attr({ | 1093 | + len = rectAttr.width - left, |
1071 | - // class: 'birdBadge', | 1094 | + hlen = len / 2, |
1072 | - // transform: translate(8,10), | 1095 | + midline = hlen + left; |
1073 | - // 'xlink:href': '#bird', | 1096 | + |
1074 | - // width: 18, | 1097 | + // title |
1075 | - // height: 18, | 1098 | + svg.append('text') |
1076 | - // fill: '#fff' | 1099 | + .attr({ |
1077 | - // }); | 1100 | + class: 'instTitle', |
1078 | - // | 1101 | + x: midline, |
1079 | - //$('<div>').attr('class', 'onosTitle').text(d.id).appendTo(el); | 1102 | + y: c.titleDy |
1080 | - | 1103 | + }) |
1081 | - // is the UI attached to this instance? | 1104 | + .text(d.id); |
1082 | - // TODO: need uiAttached boolean in instance data | 1105 | + |
1083 | - // TODO: use SVG glyph, not png.. | 1106 | + // a couple of attributes |
1084 | - //if (d.uiAttached) { | 1107 | + var ty = c.titleDy + c.textYOff; |
1085 | - //if (i === 0) { | 1108 | + |
1086 | - // $('<img src="img/ui.png">').attr('class','ui').appendTo(el); | 1109 | + function addAttr(id, label) { |
1087 | - //} | 1110 | + svg.append('text').attr({ |
1111 | + class: 'instLabel ' + id, | ||
1112 | + x: midline, | ||
1113 | + y: ty | ||
1114 | + }).text(label); | ||
1115 | + ty += c.textYSpc; | ||
1116 | + } | ||
1117 | + | ||
1118 | + addAttr('ip', d.ip); | ||
1119 | + addAttr('ns', nSw(d.switches)); | ||
1088 | }); | 1120 | }); |
1089 | 1121 | ||
1090 | // operate on existing + new onoses here | 1122 | // operate on existing + new onoses here |
1091 | 1123 | ||
1092 | - // the departed... | 1124 | + // adjust the panel size appropriately... |
1093 | - var exiting = onoses.exit() | 1125 | + oiBox.width(instDim.w * onosOrder.length); |
1094 | - .transition() | 1126 | + oiBox.height(instDim.h); |
1095 | - .style('opacity', 0) | 1127 | + |
1096 | - .remove(); | 1128 | + // remove any outgoing instances |
1129 | + onoses.exit().remove(); | ||
1097 | } | 1130 | } |
1098 | 1131 | ||
1099 | function clickInst(d) { | 1132 | function clickInst(d) { |
... | @@ -1128,6 +1161,36 @@ | ... | @@ -1128,6 +1161,36 @@ |
1128 | oiShowMaster = false; | 1161 | oiShowMaster = false; |
1129 | } | 1162 | } |
1130 | 1163 | ||
1164 | + // TODO: these should be moved out to utility module. | ||
1165 | + function stripPx(s) { | ||
1166 | + return s.replace(/px$/,''); | ||
1167 | + } | ||
1168 | + | ||
1169 | + function appendUse(svg, ox, oy, dim, iid, cls) { | ||
1170 | + var use = svg.append('use').attr({ | ||
1171 | + transform: translate(ox,oy), | ||
1172 | + 'xlink:href': iid, | ||
1173 | + width: dim, | ||
1174 | + height: dim | ||
1175 | + }); | ||
1176 | + if (cls) { | ||
1177 | + use.classed(cls, true); | ||
1178 | + } | ||
1179 | + return use; | ||
1180 | + } | ||
1181 | + | ||
1182 | + function appendGlyph(svg, ox, oy, dim, iid, cls) { | ||
1183 | + appendUse(svg, ox, oy, dim, iid, cls).classed('glyphIcon', true); | ||
1184 | + } | ||
1185 | + | ||
1186 | + function appendBadge(svg, ox, oy, dim, iid, cls) { | ||
1187 | + appendUse(svg, ox, oy, dim, iid,cls ).classed('badgeIcon', true); | ||
1188 | + } | ||
1189 | + | ||
1190 | + function attachUiBadge(svg) { | ||
1191 | + appendBadge(svg, 12, instCfg.uiDy, 30, '#uiAttached', 'uiBadge'); | ||
1192 | + } | ||
1193 | + | ||
1131 | // ============================== | 1194 | // ============================== |
1132 | // force layout modification functions | 1195 | // force layout modification functions |
1133 | 1196 | ||
... | @@ -1763,9 +1826,12 @@ | ... | @@ -1763,9 +1826,12 @@ |
1763 | 1826 | ||
1764 | } | 1827 | } |
1765 | 1828 | ||
1766 | - function find(key, array) { | 1829 | + function find(key, array, tag) { |
1767 | - for (var idx = 0, n = array.length; idx < n; idx++) { | 1830 | + var _tag = tag || 'key', |
1768 | - if (array[idx].key === key) { | 1831 | + idx, n, d; |
1832 | + for (idx = 0, n = array.length; idx < n; idx++) { | ||
1833 | + d = array[idx]; | ||
1834 | + if (d[_tag] === key) { | ||
1769 | return idx; | 1835 | return idx; |
1770 | } | 1836 | } |
1771 | } | 1837 | } | ... | ... |
-
Please register or login to post a comment