GUI -- Implemented Instance Panel.
- handling addInstance event. Change-Id: Ic98a3291bd37ecf1155dbe1696167d0635a31972
Showing
13 changed files
with
482 additions
and
59 deletions
| ... | @@ -75,7 +75,8 @@ | ... | @@ -75,7 +75,8 @@ |
| 75 | append: appendPanel, | 75 | append: appendPanel, |
| 76 | width: panelWidth, | 76 | width: panelWidth, |
| 77 | height: panelHeight, | 77 | height: panelHeight, |
| 78 | - isVisible: panelIsVisible | 78 | + isVisible: panelIsVisible, |
| 79 | + el: panelEl | ||
| 79 | }; | 80 | }; |
| 80 | 81 | ||
| 81 | p.el = panelLayer.append('div') | 82 | p.el = panelLayer.append('div') |
| ... | @@ -136,6 +137,10 @@ | ... | @@ -136,6 +137,10 @@ |
| 136 | return p.on; | 137 | return p.on; |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 140 | + function panelEl() { | ||
| 141 | + return p.el; | ||
| 142 | + } | ||
| 143 | + | ||
| 139 | return api; | 144 | return api; |
| 140 | } | 145 | } |
| 141 | 146 | ... | ... |
| ... | @@ -218,8 +218,7 @@ | ... | @@ -218,8 +218,7 @@ |
| 218 | if (xns) { | 218 | if (xns) { |
| 219 | atr.transform = sus.translate(trans); | 219 | atr.transform = sus.translate(trans); |
| 220 | } | 220 | } |
| 221 | - elem.append('use').attr(atr).classed('overlay', ovr); | 221 | + return elem.append('use').attr(atr).classed('overlay', ovr); |
| 222 | - | ||
| 223 | } | 222 | } |
| 224 | 223 | ||
| 225 | // ---------------------------------------------------------------------- | 224 | // ---------------------------------------------------------------------- | ... | ... |
| ... | @@ -143,11 +143,16 @@ | ... | @@ -143,11 +143,16 @@ |
| 143 | return 'translate(' + x + ',' + y + ')'; | 143 | return 'translate(' + x + ',' + y + ')'; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | + function stripPx(s) { | ||
| 147 | + return s.replace(/px$/,''); | ||
| 148 | + } | ||
| 149 | + | ||
| 146 | return { | 150 | return { |
| 147 | createDragBehavior: createDragBehavior, | 151 | createDragBehavior: createDragBehavior, |
| 148 | loadGlow: loadGlow, | 152 | loadGlow: loadGlow, |
| 149 | cat7: cat7, | 153 | cat7: cat7, |
| 150 | - translate: translate | 154 | + translate: translate, |
| 155 | + stripPx: stripPx | ||
| 151 | }; | 156 | }; |
| 152 | }]); | 157 | }]); |
| 153 | }()); | 158 | }()); | ... | ... |
| ... | @@ -78,6 +78,7 @@ | ... | @@ -78,6 +78,7 @@ |
| 78 | <script src="view/topo/topoEvent.js"></script> | 78 | <script src="view/topo/topoEvent.js"></script> |
| 79 | <script src="view/topo/topoForce.js"></script> | 79 | <script src="view/topo/topoForce.js"></script> |
| 80 | <script src="view/topo/topoPanel.js"></script> | 80 | <script src="view/topo/topoPanel.js"></script> |
| 81 | + <script src="view/topo/topoInst.js"></script> | ||
| 81 | <script src="view/device/device.js"></script> | 82 | <script src="view/device/device.js"></script> |
| 82 | <!-- TODO: inject javascript refs server-side --> | 83 | <!-- TODO: inject javascript refs server-side --> |
| 83 | 84 | ... | ... |
| ... | @@ -43,7 +43,7 @@ | ... | @@ -43,7 +43,7 @@ |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | 45 | ||
| 46 | -/* --- Topo Panels --- */ | 46 | +/* --- Topo Summary Panel --- */ |
| 47 | 47 | ||
| 48 | #topo-p-summary { | 48 | #topo-p-summary { |
| 49 | /* Base css from panel.css */ | 49 | /* Base css from panel.css */ |
| ... | @@ -107,3 +107,78 @@ | ... | @@ -107,3 +107,78 @@ |
| 107 | background-color: #888; | 107 | background-color: #888; |
| 108 | color: #888; | 108 | color: #888; |
| 109 | } | 109 | } |
| 110 | + | ||
| 111 | + | ||
| 112 | +/* --- Topo Detail Panel --- */ | ||
| 113 | + | ||
| 114 | +/* TODO: add CSS rules */ | ||
| 115 | + | ||
| 116 | + | ||
| 117 | +/* --- Topo Instance Panel --- */ | ||
| 118 | + | ||
| 119 | +#topo-p-instance { | ||
| 120 | + height: 100px; | ||
| 121 | +} | ||
| 122 | + | ||
| 123 | +#topo-p-instance div.onosInst { | ||
| 124 | + display: inline-block; | ||
| 125 | + width: 170px; | ||
| 126 | + height: 85px; | ||
| 127 | + cursor: pointer; | ||
| 128 | +} | ||
| 129 | + | ||
| 130 | +#topo-p-instance svg rect { | ||
| 131 | + fill: #ccc; | ||
| 132 | + stroke: #aaa; | ||
| 133 | + stroke-width: 3.5; | ||
| 134 | +} | ||
| 135 | +#topo-p-instance .online svg rect { | ||
| 136 | + opacity: 1; | ||
| 137 | + fill: #9cf; | ||
| 138 | + stroke: #555; | ||
| 139 | +} | ||
| 140 | + | ||
| 141 | +#topo-p-instance svg .glyph { | ||
| 142 | + fill: #888; | ||
| 143 | + fill-rule: evenodd; | ||
| 144 | +} | ||
| 145 | +#topo-p-instance .online svg .glyph { | ||
| 146 | + fill: #000; | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +#topo-p-instance svg .badgeIcon { | ||
| 150 | + fill: #777; | ||
| 151 | + fill-rule: evenodd; | ||
| 152 | +} | ||
| 153 | + | ||
| 154 | +#topo-p-instance .online svg .badgeIcon { | ||
| 155 | + fill: #fff; | ||
| 156 | +} | ||
| 157 | + | ||
| 158 | +#topo-p-instance svg text { | ||
| 159 | + text-anchor: middle; | ||
| 160 | + fill: #777; | ||
| 161 | +} | ||
| 162 | +#topo-p-instance .online svg text { | ||
| 163 | + fill: #eee; | ||
| 164 | +} | ||
| 165 | + | ||
| 166 | +#topo-p-instance svg text.instTitle { | ||
| 167 | + font-size: 11pt; | ||
| 168 | + font-weight: bold; | ||
| 169 | +} | ||
| 170 | +#topo-p-instance svg text.instLabel { | ||
| 171 | + font-size: 9pt; | ||
| 172 | + font-style: italic; | ||
| 173 | +} | ||
| 174 | + | ||
| 175 | +#topo-p-instance .onosInst.mastership { | ||
| 176 | + opacity: 0.3; | ||
| 177 | +} | ||
| 178 | +#topo-p-instance .onosInst.mastership.affinity { | ||
| 179 | + opacity: 1.0; | ||
| 180 | +} | ||
| 181 | +#topo-p-instance .onosInst.mastership.affinity svg rect { | ||
| 182 | + /* TODO: add blue glow */ | ||
| 183 | + /*filter: url(#blue-glow);*/ | ||
| 184 | +} | ... | ... |
| ... | @@ -143,12 +143,13 @@ | ... | @@ -143,12 +143,13 @@ |
| 143 | 143 | ||
| 144 | .controller('OvTopoCtrl', [ | 144 | .controller('OvTopoCtrl', [ |
| 145 | '$scope', '$log', '$location', '$timeout', | 145 | '$scope', '$log', '$location', '$timeout', |
| 146 | - 'FnService', 'MastService', | 146 | + 'FnService', 'MastService', 'KeyService', 'ZoomService', |
| 147 | - 'KeyService', 'ZoomService', 'GlyphService', 'MapService', | 147 | + 'GlyphService', 'MapService', |
| 148 | 'TopoEventService', 'TopoForceService', 'TopoPanelService', | 148 | 'TopoEventService', 'TopoForceService', 'TopoPanelService', |
| 149 | + 'TopoInstService', | ||
| 149 | 150 | ||
| 150 | function ($scope, _$log_, $loc, $timeout, _fs_, mast, | 151 | function ($scope, _$log_, $loc, $timeout, _fs_, mast, |
| 151 | - _ks_, _zs_, _gs_, _ms_, tes, _tfs_, tps) { | 152 | + _ks_, _zs_, _gs_, _ms_, tes, _tfs_, tps, tis) { |
| 152 | var self = this; | 153 | var self = this; |
| 153 | $log = _$log_; | 154 | $log = _$log_; |
| 154 | fs = _fs_; | 155 | fs = _fs_; |
| ... | @@ -167,6 +168,7 @@ | ... | @@ -167,6 +168,7 @@ |
| 167 | $log.log('OvTopoCtrl is saying Buh-Bye!'); | 168 | $log.log('OvTopoCtrl is saying Buh-Bye!'); |
| 168 | tes.closeSock(); | 169 | tes.closeSock(); |
| 169 | tps.destroyPanels(); | 170 | tps.destroyPanels(); |
| 171 | + tis.destroyInst(); | ||
| 170 | }); | 172 | }); |
| 171 | 173 | ||
| 172 | // svg layer and initialization of components | 174 | // svg layer and initialization of components |
| ... | @@ -181,6 +183,7 @@ | ... | @@ -181,6 +183,7 @@ |
| 181 | setUpMap(); | 183 | setUpMap(); |
| 182 | setUpForce(); | 184 | setUpForce(); |
| 183 | 185 | ||
| 186 | + tis.initInst(); | ||
| 184 | tps.initPanels(); | 187 | tps.initPanels(); |
| 185 | tes.openSock(); | 188 | tes.openSock(); |
| 186 | 189 | ... | ... |
| ... | @@ -23,7 +23,7 @@ | ... | @@ -23,7 +23,7 @@ |
| 23 | 'use strict'; | 23 | 'use strict'; |
| 24 | 24 | ||
| 25 | // injected refs | 25 | // injected refs |
| 26 | - var $log, wss, wes, tps; | 26 | + var $log, wss, wes, tps, tis; |
| 27 | 27 | ||
| 28 | // internal state | 28 | // internal state |
| 29 | var wsock; | 29 | var wsock; |
| ... | @@ -47,7 +47,8 @@ | ... | @@ -47,7 +47,8 @@ |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | function addInstance(ev) { | 49 | function addInstance(ev) { |
| 50 | - $log.debug(' *** We got an ADD INSTANCE event: ', ev); | 50 | + $log.debug(' **** Add Instance **** ', ev.payload); |
| 51 | + tis.addInstance(ev.payload); | ||
| 51 | } | 52 | } |
| 52 | 53 | ||
| 53 | // ========================== | 54 | // ========================== |
| ... | @@ -87,13 +88,14 @@ | ... | @@ -87,13 +88,14 @@ |
| 87 | angular.module('ovTopo') | 88 | angular.module('ovTopo') |
| 88 | .factory('TopoEventService', | 89 | .factory('TopoEventService', |
| 89 | ['$log', '$location', 'WebSocketService', 'WsEventService', | 90 | ['$log', '$location', 'WebSocketService', 'WsEventService', |
| 90 | - 'TopoPanelService', | 91 | + 'TopoPanelService', 'TopoInstService', |
| 91 | 92 | ||
| 92 | - function (_$log_, $loc, _wss_, _wes_, _tps_) { | 93 | + function (_$log_, $loc, _wss_, _wes_, _tps_, _tis_) { |
| 93 | $log = _$log_; | 94 | $log = _$log_; |
| 94 | wss = _wss_; | 95 | wss = _wss_; |
| 95 | wes = _wes_; | 96 | wes = _wes_; |
| 96 | tps = _tps_; | 97 | tps = _tps_; |
| 98 | + tis = _tis_; | ||
| 97 | 99 | ||
| 98 | function bindDispatcher(TopoDomElementsPassedHere) { | 100 | function bindDispatcher(TopoDomElementsPassedHere) { |
| 99 | // TODO: store refs to topo DOM elements... | 101 | // TODO: store refs to topo DOM elements... | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +/* | ||
| 18 | + ONOS GUI -- Topology Instances Module. | ||
| 19 | + Defines modeling of ONOS instances. | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | +(function () { | ||
| 23 | + 'use strict'; | ||
| 24 | + | ||
| 25 | + // injected refs | ||
| 26 | + var $log, ps, sus, gs; | ||
| 27 | + | ||
| 28 | + // configuration | ||
| 29 | + var instCfg = { | ||
| 30 | + rectPad: 8, | ||
| 31 | + nodeOx: 9, | ||
| 32 | + nodeOy: 9, | ||
| 33 | + nodeDim: 40, | ||
| 34 | + birdOx: 19, | ||
| 35 | + birdOy: 21, | ||
| 36 | + birdDim: 21, | ||
| 37 | + uiDy: 45, | ||
| 38 | + titleDy: 30, | ||
| 39 | + textYOff: 20, | ||
| 40 | + textYSpc: 15 | ||
| 41 | + }, | ||
| 42 | + showLogicErrors = true, | ||
| 43 | + idIns = 'topo-p-instance', | ||
| 44 | + instOpts = { | ||
| 45 | + edge: 'left', | ||
| 46 | + width: 20 | ||
| 47 | + }; | ||
| 48 | + | ||
| 49 | + // internal state | ||
| 50 | + var onosInstances, | ||
| 51 | + onosOrder, | ||
| 52 | + oiShowMaster, | ||
| 53 | + oiBox; | ||
| 54 | + | ||
| 55 | + | ||
| 56 | + // ========================== | ||
| 57 | + // *** ADD INSTANCE *** | ||
| 58 | + | ||
| 59 | + function addInstance(data) { | ||
| 60 | + var id = data.id; | ||
| 61 | + | ||
| 62 | + if (onosInstances[id]) { | ||
| 63 | + updateInstance(data); | ||
| 64 | + return; | ||
| 65 | + } | ||
| 66 | + onosInstances[id] = data; | ||
| 67 | + onosOrder.push(data); | ||
| 68 | + updateInstances(); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + function updateInstance(data) { | ||
| 72 | + var id = data.id, | ||
| 73 | + d = onosInstances[id]; | ||
| 74 | + if (d) { | ||
| 75 | + angular.extend(d, data); | ||
| 76 | + updateInstances(); | ||
| 77 | + } else { | ||
| 78 | + logicError('updateInstance: lookup fail: ID = "' + id + '"'); | ||
| 79 | + } | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + function computeDim(self) { | ||
| 83 | + var css = window.getComputedStyle(self); | ||
| 84 | + return { | ||
| 85 | + w: sus.stripPx(css.width), | ||
| 86 | + h: sus.stripPx(css.height) | ||
| 87 | + }; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + function clickInst(d) { | ||
| 91 | + var el = d3.select(this), | ||
| 92 | + aff = el.classed('affinity'); | ||
| 93 | + if (!aff) { | ||
| 94 | + setAffinity(el, d); | ||
| 95 | + } else { | ||
| 96 | + cancelAffinity(); | ||
| 97 | + } | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + function setAffinity(el, d) { | ||
| 101 | + d3.selectAll('.onosInst') | ||
| 102 | + .classed('mastership', true) | ||
| 103 | + .classed('affinity', false); | ||
| 104 | + el.classed('affinity', true); | ||
| 105 | + | ||
| 106 | + // TODO: suppress the layers and highlight only specific nodes... | ||
| 107 | + //suppressLayers(true); | ||
| 108 | + //node.each(function (n) { | ||
| 109 | + // if (n.master === d.id) { | ||
| 110 | + // n.el.classed('suppressed', false); | ||
| 111 | + // } | ||
| 112 | + //}); | ||
| 113 | + oiShowMaster = true; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + function cancelAffinity() { | ||
| 117 | + d3.selectAll('.onosInst') | ||
| 118 | + .classed('mastership affinity', false); | ||
| 119 | + | ||
| 120 | + // TODO: restore layer state | ||
| 121 | + //restoreLayerState(); | ||
| 122 | + oiShowMaster = false; | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + function instRectAttr(dim) { | ||
| 126 | + var pad = instCfg.rectPad; | ||
| 127 | + return { | ||
| 128 | + x: pad, | ||
| 129 | + y: pad, | ||
| 130 | + width: dim.w - pad*2, | ||
| 131 | + height: dim.h - pad*2, | ||
| 132 | + rx: 6 | ||
| 133 | + }; | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + function viewBox(dim) { | ||
| 137 | + return '0 0 ' + dim.w + ' ' + dim.h; | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + function attachUiBadge(svg) { | ||
| 141 | + gs.addGlyph(svg, 'uiAttached', 30, true, [12, instCfg.uiDy]) | ||
| 142 | + .classed('badgeIcon uiBadge', true); | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + function instColor(id, online) { | ||
| 146 | + // TODO: fix this.. | ||
| 147 | + //return cat7.get(id, !online, network.view.getTheme()); | ||
| 148 | + return 'blue'; | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + // ============================== | ||
| 152 | + | ||
| 153 | + function updateInstances() { | ||
| 154 | + var onoses = oiBox.el().selectAll('.onosInst') | ||
| 155 | + .data(onosOrder, function (d) { return d.id; }), | ||
| 156 | + instDim = {w:0,h:0}, | ||
| 157 | + c = instCfg; | ||
| 158 | + | ||
| 159 | + function nSw(n) { | ||
| 160 | + return '# Switches: ' + n; | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + // operate on existing onos instances if necessary | ||
| 164 | + onoses.each(function (d) { | ||
| 165 | + var el = d3.select(this), | ||
| 166 | + svg = el.select('svg'); | ||
| 167 | + instDim = computeDim(this); | ||
| 168 | + | ||
| 169 | + // update online state | ||
| 170 | + el.classed('online', d.online); | ||
| 171 | + | ||
| 172 | + // update ui-attached state | ||
| 173 | + svg.select('use.uiBadge').remove(); | ||
| 174 | + if (d.uiAttached) { | ||
| 175 | + attachUiBadge(svg); | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + function updAttr(id, value) { | ||
| 179 | + svg.select('text.instLabel.'+id).text(value); | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + updAttr('ip', d.ip); | ||
| 183 | + updAttr('ns', nSw(d.switches)); | ||
| 184 | + }); | ||
| 185 | + | ||
| 186 | + | ||
| 187 | + // operate on new onos instances | ||
| 188 | + var entering = onoses.enter() | ||
| 189 | + .append('div') | ||
| 190 | + .attr('class', 'onosInst') | ||
| 191 | + .classed('online', function (d) { return d.online; }) | ||
| 192 | + .on('click', clickInst); | ||
| 193 | + | ||
| 194 | + entering.each(function (d) { | ||
| 195 | + var el = d3.select(this), | ||
| 196 | + rectAttr, | ||
| 197 | + svg; | ||
| 198 | + instDim = computeDim(this); | ||
| 199 | + rectAttr = instRectAttr(instDim); | ||
| 200 | + | ||
| 201 | + svg = el.append('svg').attr({ | ||
| 202 | + width: instDim.w, | ||
| 203 | + height: instDim.h, | ||
| 204 | + viewBox: viewBox(instDim) | ||
| 205 | + }); | ||
| 206 | + | ||
| 207 | + svg.append('rect').attr(rectAttr); | ||
| 208 | + | ||
| 209 | + gs.addGlyph(svg, 'bird', 28, true, [14, 14]) | ||
| 210 | + .classed('badgeIcon', true); | ||
| 211 | + | ||
| 212 | + if (d.uiAttached) { | ||
| 213 | + attachUiBadge(svg); | ||
| 214 | + } | ||
| 215 | + | ||
| 216 | + var left = c.nodeOx + c.nodeDim, | ||
| 217 | + len = rectAttr.width - left, | ||
| 218 | + hlen = len / 2, | ||
| 219 | + midline = hlen + left; | ||
| 220 | + | ||
| 221 | + // title | ||
| 222 | + svg.append('text') | ||
| 223 | + .attr({ | ||
| 224 | + class: 'instTitle', | ||
| 225 | + x: midline, | ||
| 226 | + y: c.titleDy | ||
| 227 | + }) | ||
| 228 | + .text(d.id); | ||
| 229 | + | ||
| 230 | + // a couple of attributes | ||
| 231 | + var ty = c.titleDy + c.textYOff; | ||
| 232 | + | ||
| 233 | + function addAttr(id, label) { | ||
| 234 | + svg.append('text').attr({ | ||
| 235 | + class: 'instLabel ' + id, | ||
| 236 | + x: midline, | ||
| 237 | + y: ty | ||
| 238 | + }).text(label); | ||
| 239 | + ty += c.textYSpc; | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + addAttr('ip', d.ip); | ||
| 243 | + addAttr('ns', nSw(d.switches)); | ||
| 244 | + }); | ||
| 245 | + | ||
| 246 | + // operate on existing + new onoses here | ||
| 247 | + // set the affinity colors... | ||
| 248 | + onoses.each(function (d) { | ||
| 249 | + var el = d3.select(this), | ||
| 250 | + rect = el.select('svg').select('rect'), | ||
| 251 | + col = instColor(d.id, d.online); | ||
| 252 | + rect.style('fill', col); | ||
| 253 | + }); | ||
| 254 | + | ||
| 255 | + // adjust the panel size appropriately... | ||
| 256 | + oiBox.width(instDim.w * onosOrder.length); | ||
| 257 | + oiBox.height(instDim.h); | ||
| 258 | + | ||
| 259 | + // remove any outgoing instances | ||
| 260 | + onoses.exit().remove(); | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + | ||
| 264 | + // ========================== | ||
| 265 | + | ||
| 266 | + function logicError(msg) { | ||
| 267 | + if (showLogicErrors) { | ||
| 268 | + $log.warn('TopoInstService: ' + msg); | ||
| 269 | + } | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + function initInst() { | ||
| 273 | + oiBox = ps.createPanel(idIns, instOpts); | ||
| 274 | + oiBox.show(); | ||
| 275 | + | ||
| 276 | + onosInstances = {}; | ||
| 277 | + onosOrder = []; | ||
| 278 | + oiShowMaster = false; | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | + function destroyInst() { | ||
| 282 | + ps.destroyPanel(idIns); | ||
| 283 | + oiBox = null; | ||
| 284 | + } | ||
| 285 | + | ||
| 286 | + // ========================== | ||
| 287 | + | ||
| 288 | + angular.module('ovTopo') | ||
| 289 | + .factory('TopoInstService', | ||
| 290 | + ['$log', 'PanelService', 'SvgUtilService', 'GlyphService', | ||
| 291 | + | ||
| 292 | + function (_$log_, _ps_, _sus_, _gs_) { | ||
| 293 | + $log = _$log_; | ||
| 294 | + ps = _ps_; | ||
| 295 | + sus = _sus_; | ||
| 296 | + gs = _gs_; | ||
| 297 | + | ||
| 298 | + return { | ||
| 299 | + initInst: initInst, | ||
| 300 | + destroyInst: destroyInst, | ||
| 301 | + addInstance: addInstance | ||
| 302 | + }; | ||
| 303 | + }]); | ||
| 304 | +}()); |
| ... | @@ -28,43 +28,20 @@ | ... | @@ -28,43 +28,20 @@ |
| 28 | // constants | 28 | // constants |
| 29 | var idSum = 'topo-p-summary', | 29 | var idSum = 'topo-p-summary', |
| 30 | idDet = 'topo-p-detail', | 30 | idDet = 'topo-p-detail', |
| 31 | - idIns = 'topo-p-instance', | ||
| 32 | panelOpts = { | 31 | panelOpts = { |
| 33 | width: 260 | 32 | width: 260 |
| 34 | }; | 33 | }; |
| 35 | 34 | ||
| 36 | - // internal state | 35 | + // panels |
| 37 | - var settings; | ||
| 38 | - | ||
| 39 | - | ||
| 40 | - // SVG elements; | ||
| 41 | - var fooPane; | ||
| 42 | - | ||
| 43 | - // D3 selections; | ||
| 44 | var summaryPanel, | 36 | var summaryPanel, |
| 45 | - detailPanel, | 37 | + detailPanel; |
| 46 | - instancePanel; | ||
| 47 | - | ||
| 48 | - // default settings for force layout | ||
| 49 | - var defaultSettings = { | ||
| 50 | - foo: 2 | ||
| 51 | - }; | ||
| 52 | - | ||
| 53 | 38 | ||
| 54 | // ========================== | 39 | // ========================== |
| 40 | + // *** SHOW SUMMARY *** | ||
| 55 | 41 | ||
| 56 | - function addSep(tbody) { | 42 | + function showSummary(data) { |
| 57 | - tbody.append('tr').append('td').attr('colspan', 2).append('hr'); | 43 | + populateSummary(data); |
| 58 | - } | 44 | + showSummaryPanel(); |
| 59 | - | ||
| 60 | - function addProp(tbody, label, value) { | ||
| 61 | - var tr = tbody.append('tr'); | ||
| 62 | - | ||
| 63 | - function addCell(cls, txt) { | ||
| 64 | - tr.append('td').attr('class', cls).text(txt); | ||
| 65 | - } | ||
| 66 | - addCell('label', label + ' :'); | ||
| 67 | - addCell('value', value); | ||
| 68 | } | 45 | } |
| 69 | 46 | ||
| 70 | function populateSummary(data) { | 47 | function populateSummary(data) { |
| ... | @@ -89,9 +66,36 @@ | ... | @@ -89,9 +66,36 @@ |
| 89 | }); | 66 | }); |
| 90 | } | 67 | } |
| 91 | 68 | ||
| 69 | + function addSep(tbody) { | ||
| 70 | + tbody.append('tr').append('td').attr('colspan', 2).append('hr'); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + function addProp(tbody, label, value) { | ||
| 74 | + var tr = tbody.append('tr'); | ||
| 75 | + | ||
| 76 | + function addCell(cls, txt) { | ||
| 77 | + tr.append('td').attr('class', cls).text(txt); | ||
| 78 | + } | ||
| 79 | + addCell('label', label + ' :'); | ||
| 80 | + addCell('value', value); | ||
| 81 | + } | ||
| 82 | + | ||
| 92 | function showSummaryPanel() { | 83 | function showSummaryPanel() { |
| 93 | summaryPanel.show(); | 84 | summaryPanel.show(); |
| 85 | + // TODO: augment, once we have the details pane also | ||
| 86 | + } | ||
| 94 | 87 | ||
| 88 | + // ========================== | ||
| 89 | + | ||
| 90 | + function initPanels() { | ||
| 91 | + summaryPanel = ps.createPanel(idSum, panelOpts); | ||
| 92 | + detailPanel = ps.createPanel(idDet, panelOpts); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + function destroyPanels() { | ||
| 96 | + ps.destroyPanel(idSum); | ||
| 97 | + ps.destroyPanel(idDet); | ||
| 98 | + summaryPanel = detailPanel = null; | ||
| 95 | } | 99 | } |
| 96 | 100 | ||
| 97 | // ========================== | 101 | // ========================== |
| ... | @@ -105,22 +109,6 @@ | ... | @@ -105,22 +109,6 @@ |
| 105 | ps = _ps_; | 109 | ps = _ps_; |
| 106 | gs = _gs_; | 110 | gs = _gs_; |
| 107 | 111 | ||
| 108 | - function initPanels() { | ||
| 109 | - summaryPanel = ps.createPanel(idSum, panelOpts); | ||
| 110 | - // TODO: set up detail and instance panels.. | ||
| 111 | - } | ||
| 112 | - | ||
| 113 | - function destroyPanels() { | ||
| 114 | - ps.destroyPanel(idSum); | ||
| 115 | - summaryPanel = null; | ||
| 116 | - // TODO: destroy detail and instance panels.. | ||
| 117 | - } | ||
| 118 | - | ||
| 119 | - function showSummary(payload) { | ||
| 120 | - populateSummary(payload); | ||
| 121 | - showSummaryPanel(); | ||
| 122 | - } | ||
| 123 | - | ||
| 124 | return { | 112 | return { |
| 125 | initPanels: initPanels, | 113 | initPanels: initPanels, |
| 126 | destroyPanels: destroyPanels, | 114 | destroyPanels: destroyPanels, | ... | ... |
| ... | @@ -84,6 +84,13 @@ describe('factory: fw/layer/panel.js', function () { | ... | @@ -84,6 +84,13 @@ describe('factory: fw/layer/panel.js', function () { |
| 84 | expect(el.style('width')).toEqual('200px'); | 84 | expect(el.style('width')).toEqual('200px'); |
| 85 | }); | 85 | }); |
| 86 | 86 | ||
| 87 | + it('should provide an api of panel functions', function () { | ||
| 88 | + var p = ps.createPanel('foo'); | ||
| 89 | + expect(fs.areFunctions(p, [ | ||
| 90 | + 'show', 'hide', 'empty', 'append', 'width', 'height', 'isVisible', 'el' | ||
| 91 | + ])).toBeTruthy(); | ||
| 92 | + }); | ||
| 93 | + | ||
| 87 | it('should complain when a duplicate ID is used', function () { | 94 | it('should complain when a duplicate ID is used', function () { |
| 88 | spyOn($log, 'warn'); | 95 | spyOn($log, 'warn'); |
| 89 | var p = ps.createPanel('foo'); | 96 | var p = ps.createPanel('foo'); | ... | ... |
| ... | @@ -252,7 +252,7 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -252,7 +252,7 @@ describe('factory: fw/svg/glyph.js', function() { |
| 252 | 252 | ||
| 253 | it('should add a glyph with default size', function () { | 253 | it('should add a glyph with default size', function () { |
| 254 | gs.init(); | 254 | gs.init(); |
| 255 | - gs.addGlyph(svg, 'crown'); | 255 | + var retval = gs.addGlyph(svg, 'crown'); |
| 256 | var what = svg.selectAll('use'); | 256 | var what = svg.selectAll('use'); |
| 257 | expect(what.size()).toEqual(1); | 257 | expect(what.size()).toEqual(1); |
| 258 | expect(what.attr('width')).toEqual('40'); | 258 | expect(what.attr('width')).toEqual('40'); |
| ... | @@ -260,6 +260,10 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -260,6 +260,10 @@ describe('factory: fw/svg/glyph.js', function() { |
| 260 | expect(what.attr('xlink:href')).toEqual('#crown'); | 260 | expect(what.attr('xlink:href')).toEqual('#crown'); |
| 261 | expect(what.classed('glyph')).toBeTruthy(); | 261 | expect(what.classed('glyph')).toBeTruthy(); |
| 262 | expect(what.classed('overlay')).toBeFalsy(); | 262 | expect(what.classed('overlay')).toBeFalsy(); |
| 263 | + | ||
| 264 | + // check a couple on retval, which should be the same thing.. | ||
| 265 | + expect(retval.attr('xlink:href')).toEqual('#crown'); | ||
| 266 | + expect(retval.classed('glyph')).toBeTruthy(); | ||
| 263 | }); | 267 | }); |
| 264 | 268 | ||
| 265 | it('should add a glyph with given size', function () { | 269 | it('should add a glyph with given size', function () { | ... | ... |
| ... | @@ -43,7 +43,13 @@ describe('factory: fw/svg/svgUtil.js', function() { | ... | @@ -43,7 +43,13 @@ describe('factory: fw/svg/svgUtil.js', function() { |
| 43 | ])).toBeTruthy(); | 43 | ])).toBeTruthy(); |
| 44 | }); | 44 | }); |
| 45 | 45 | ||
| 46 | - // TODO: add unit tests for drag behavior etc. | 46 | + |
| 47 | + // TODO: add unit tests for drag behavior | ||
| 48 | + // TODO: add unit tests for loadGlow | ||
| 49 | + // TODO: add unit tests for cat7 | ||
| 50 | + | ||
| 51 | + | ||
| 52 | + // === translate() | ||
| 47 | 53 | ||
| 48 | it('should translate from two args', function () { | 54 | it('should translate from two args', function () { |
| 49 | expect(sus.translate(1,2)).toEqual('translate(1,2)'); | 55 | expect(sus.translate(1,2)).toEqual('translate(1,2)'); |
| ... | @@ -53,4 +59,14 @@ describe('factory: fw/svg/svgUtil.js', function() { | ... | @@ -53,4 +59,14 @@ describe('factory: fw/svg/svgUtil.js', function() { |
| 53 | expect(sus.translate([3,4])).toEqual('translate(3,4)'); | 59 | expect(sus.translate([3,4])).toEqual('translate(3,4)'); |
| 54 | }); | 60 | }); |
| 55 | 61 | ||
| 62 | + | ||
| 63 | + // === stripPx() | ||
| 64 | + | ||
| 65 | + it('should not affect a number', function () { | ||
| 66 | + expect(sus.stripPx('4')).toEqual('4'); | ||
| 67 | + }); | ||
| 68 | + | ||
| 69 | + it('should remove trailing px', function () { | ||
| 70 | + expect(sus.stripPx('4px')).toEqual('4'); | ||
| 71 | + }); | ||
| 56 | }); | 72 | }); | ... | ... |
-
Please register or login to post a comment