blob: d95c4f5d42ee52a205f26abf9eb168de9d441454 [file] [log] [blame]
Simon Huntb0ec1e52015-01-28 18:13:49 -08001/*
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 Panel Module.
19 Defines functions for manipulating the summary, detail, and instance panels.
20 */
21
22(function () {
23 'use strict';
24
25 // injected refs
Simon Hunt0c6b2d32015-03-26 17:46:29 -070026 var $log, fs, ps, gs, flash, wss;
Simon Huntb0ec1e52015-01-28 18:13:49 -080027
Simon Hunt626d2102015-01-29 11:54:50 -080028 // constants
Simon Hunt08f841d02015-02-10 14:39:20 -080029 var pCls = 'topo-p',
30 idSum = 'topo-p-summary',
Simon Hunt626d2102015-01-29 11:54:50 -080031 idDet = 'topo-p-detail',
Simon Hunt626d2102015-01-29 11:54:50 -080032 panelOpts = {
33 width: 260
34 };
35
Simon Hunt4b668592015-01-29 17:33:53 -080036 // panels
Simon Huntb0ec1e52015-01-28 18:13:49 -080037 var summaryPanel,
Simon Hunt4b668592015-01-29 17:33:53 -080038 detailPanel;
Simon Huntb0ec1e52015-01-28 18:13:49 -080039
Simon Hunt0c6b2d32015-03-26 17:46:29 -070040 // internal state
41 var useDetails = true, // should we show details if we have 'em?
42 haveDetails = false; // do we have details that we could show?
Simon Huntb0ec1e52015-01-28 18:13:49 -080043
Simon Hunt08f841d02015-02-10 14:39:20 -080044 // === -----------------------------------------------------
45 // Utility functions
Simon Hunt626d2102015-01-29 11:54:50 -080046
Simon Hunt4b668592015-01-29 17:33:53 -080047 function addSep(tbody) {
48 tbody.append('tr').append('td').attr('colspan', 2).append('hr');
49 }
50
51 function addProp(tbody, label, value) {
Simon Hunte25c5a22015-04-02 14:37:12 -070052 var tr = tbody.append('tr'),
53 lab = label.replace(/_/g, ' ');
Simon Hunt4b668592015-01-29 17:33:53 -080054
55 function addCell(cls, txt) {
Simon Hunta36f03b2015-04-01 15:22:49 -070056 tr.append('td').attr('class', cls).html(txt);
Simon Hunt4b668592015-01-29 17:33:53 -080057 }
Simon Hunte25c5a22015-04-02 14:37:12 -070058 addCell('label', lab + ' :');
Simon Hunt4b668592015-01-29 17:33:53 -080059 addCell('value', value);
60 }
61
Simon Hunt08f841d02015-02-10 14:39:20 -080062 function listProps(tbody, data) {
63 data.propOrder.forEach(function(p) {
64 if (p === '-') {
65 addSep(tbody);
66 } else {
67 addProp(tbody, p, data.props[p]);
68 }
69 });
70 }
71
72 function dpa(x) {
73 return detailPanel.append(x);
74 }
75
76 function spa(x) {
77 return summaryPanel.append(x);
78 }
79
80 // === -----------------------------------------------------
81 // Functions for populating the summary panel
82
83 function populateSummary(data) {
84 summaryPanel.empty();
85
86 var svg = spa('svg'),
87 title = spa('h2'),
88 table = spa('table'),
89 tbody = table.append('tbody');
90
91 gs.addGlyph(svg, 'node', 40);
92 gs.addGlyph(svg, 'bird', 24, true, [8,12]);
93
94 title.text(data.id);
95 listProps(tbody, data);
96 }
97
98 // === -----------------------------------------------------
99 // Functions for populating the detail panel
100
101 function displaySingle(data) {
102 detailPanel.empty();
103
104 var svg = dpa('svg'),
105 title = dpa('h2'),
106 table = dpa('table'),
107 tbody = table.append('tbody');
108
109 gs.addGlyph(svg, (data.type || 'unknown'), 40);
110 title.text(data.id);
111 listProps(tbody, data);
112 dpa('hr');
113 }
114
115 function displayMulti(ids) {
116 detailPanel.empty();
117
118 var title = dpa('h3'),
119 table = dpa('table'),
120 tbody = table.append('tbody');
121
122 title.text('Selected Nodes');
123 ids.forEach(function (d, i) {
124 addProp(tbody, i+1, d);
125 });
126 dpa('hr');
127 }
128
129 function addAction(text, cb) {
130 dpa('div')
131 .classed('actionBtn', true)
132 .text(text)
133 .on('click', cb);
134 }
135
Simon Hunta36f03b2015-04-01 15:22:49 -0700136 var friendlyIndex = {
137 device: 1,
138 host: 0
139 };
140
141 function friendly(d) {
142 var i = friendlyIndex[d.class] || 0;
143 return (d.labels && d.labels[i]) || '';
144 }
145
146 function linkSummary(d) {
147 var o = d && d.online ? 'online' : 'offline';
148 return d ? d.type + ' / ' + o : '-';
149 }
150
Simon Hunte25c5a22015-04-02 14:37:12 -0700151 // provided to change presentation of internal type name
152 var linkTypePres = {
153 hostLink: 'edge link'
154 };
155
156 function linkType(d) {
157 return linkTypePres[d.type()] || d.type();
158 }
159
160 var coreOrder = [
161 'Type', '-',
162 'A_type', 'A_id', 'A_label', 'A_port', '-',
163 'B_type', 'B_id', 'B_label', 'B_port', '-'
164 ],
165 edgeOrder = [
166 'Type', '-',
167 'A_type', 'A_id', 'A_label', '-',
168 'B_type', 'B_id', 'B_label', 'B_port'
169 ];
170
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700171 function displayLink(data) {
172 detailPanel.empty();
173
174 var svg = dpa('svg'),
175 title = dpa('h2'),
176 table = dpa('table'),
Simon Hunte25c5a22015-04-02 14:37:12 -0700177 tbody = table.append('tbody'),
178 edgeLink = data.type() === 'hostLink',
179 order = edgeLink ? edgeOrder : coreOrder;
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700180
181 gs.addGlyph(svg, 'ports', 40);
182 title.text('Link');
Simon Hunta36f03b2015-04-01 15:22:49 -0700183
Simon Hunta36f03b2015-04-01 15:22:49 -0700184
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700185 listProps(tbody, {
Simon Hunta36f03b2015-04-01 15:22:49 -0700186 propOrder: order,
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700187 props: {
Simon Hunte25c5a22015-04-02 14:37:12 -0700188 Type: linkType(data),
Simon Hunta36f03b2015-04-01 15:22:49 -0700189
190 A_type: data.source.class,
191 A_id: data.source.id,
192 A_label: friendly(data.source),
193 A_port: data.srcPort,
194
195 B_type: data.target.class,
196 B_id: data.target.id,
197 B_label: friendly(data.target),
198 B_port: data.tgtPort
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700199 }
200 });
Simon Hunta36f03b2015-04-01 15:22:49 -0700201
Simon Hunte25c5a22015-04-02 14:37:12 -0700202 if (!edgeLink) {
203 addProp(tbody, 'A → B', linkSummary(data.fromSource));
204 addProp(tbody, 'B → A', linkSummary(data.fromTarget));
205 }
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700206 }
207
208 function displayNothing() {
209 haveDetails = false;
210 hideDetailPanel();
211 }
212
213 function displaySomething() {
214 haveDetails = true;
215 if (useDetails) {
216 showDetailPanel();
217 }
218 }
219
Simon Hunt08f841d02015-02-10 14:39:20 -0800220 // === -----------------------------------------------------
221 // Event Handlers
222
223 function showSummary(data) {
224 populateSummary(data);
225 showSummaryPanel();
226 }
227
Simon Hunt36a58c62015-04-08 11:00:07 -0700228 function toggleSummary(x) {
229 var on = (x === 'keyev') ? !summaryPanel.isVisible() : !!x;
230
231 if (on) {
Simon Hunta0eb0a82015-02-11 12:30:06 -0800232 // ask server to start sending summary data.
Simon Hunt237676b52015-03-10 19:04:26 -0700233 wss.sendEvent('requestSummary');
Simon Hunta0eb0a82015-02-11 12:30:06 -0800234 // note: the summary panel will appear, once data arrives
Simon Hunt36a58c62015-04-08 11:00:07 -0700235 } else {
236 hideSummaryPanel();
Simon Hunt6036b192015-02-11 11:20:26 -0800237 }
238 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800239
240 // === -----------------------------------------------------
241 // === LOGIC For showing/hiding summary and detail panels...
242
Simon Hunt626d2102015-01-29 11:54:50 -0800243 function showSummaryPanel() {
Simon Hunt6036b192015-02-11 11:20:26 -0800244 if (detailPanel.isVisible()) {
245 detailPanel.down(summaryPanel.show);
246 } else {
247 summaryPanel.show();
248 }
Simon Huntc252aa62015-02-10 16:45:39 -0800249 }
250
251 function hideSummaryPanel() {
Simon Hunta0eb0a82015-02-11 12:30:06 -0800252 // instruct server to stop sending summary data
Simon Hunt237676b52015-03-10 19:04:26 -0700253 wss.sendEvent("cancelSummary");
Simon Hunta0eb0a82015-02-11 12:30:06 -0800254 summaryPanel.hide(detailPanel.up);
Simon Hunt4b668592015-01-29 17:33:53 -0800255 }
Simon Hunt626d2102015-01-29 11:54:50 -0800256
Simon Hunt08f841d02015-02-10 14:39:20 -0800257 function showDetailPanel() {
Simon Hunt6036b192015-02-11 11:20:26 -0800258 if (summaryPanel.isVisible()) {
259 detailPanel.down(detailPanel.show);
260 } else {
261 detailPanel.up(detailPanel.show);
262 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800263 }
264
265 function hideDetailPanel() {
266 detailPanel.hide();
267 }
268
Simon Hunt6036b192015-02-11 11:20:26 -0800269 // ==========================
Simon Hunt08f841d02015-02-10 14:39:20 -0800270
Simon Hunt6036b192015-02-11 11:20:26 -0800271 function noop () {}
272
273 function augmentDetailPanel() {
274 var dp = detailPanel;
275 dp.ypos = { up: 64, down: 320, current: 320};
276
277 dp._move = function (y, cb) {
278 var endCb = fs.isF(cb) || noop,
279 yp = dp.ypos;
280 if (yp.current !== y) {
281 yp.current = y;
282 dp.el().transition().duration(300)
283 .each('end', endCb)
284 .style('top', yp.current + 'px');
285 } else {
286 endCb();
287 }
288 };
289
290 dp.down = function (cb) { dp._move(dp.ypos.down, cb); };
291 dp.up = function (cb) { dp._move(dp.ypos.up, cb); };
292 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800293
Simon Hunt36a58c62015-04-08 11:00:07 -0700294 function toggleDetails(x) {
295 useDetails = (x === 'keyev') ? !useDetails : !!x;
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700296 if (useDetails) {
297 flash.flash('Enable details panel');
298 if (haveDetails) {
299 showDetailPanel();
300 }
301 } else {
302 flash.flash('Disable details panel');
303 hideDetailPanel();
304 }
305 }
306
Simon Hunt4b668592015-01-29 17:33:53 -0800307 // ==========================
308
Simon Hunt237676b52015-03-10 19:04:26 -0700309 function initPanels() {
Simon Hunt4b668592015-01-29 17:33:53 -0800310 summaryPanel = ps.createPanel(idSum, panelOpts);
311 detailPanel = ps.createPanel(idDet, panelOpts);
Simon Hunt08f841d02015-02-10 14:39:20 -0800312
313 summaryPanel.classed(pCls, true);
314 detailPanel.classed(pCls, true);
Simon Hunt6036b192015-02-11 11:20:26 -0800315
316 augmentDetailPanel();
Simon Hunt4b668592015-01-29 17:33:53 -0800317 }
318
319 function destroyPanels() {
320 ps.destroyPanel(idSum);
321 ps.destroyPanel(idDet);
322 summaryPanel = detailPanel = null;
Simon Hunt626d2102015-01-29 11:54:50 -0800323 }
324
325 // ==========================
326
Simon Huntb0ec1e52015-01-28 18:13:49 -0800327 angular.module('ovTopo')
328 .factory('TopoPanelService',
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700329 ['$log', 'FnService', 'PanelService', 'GlyphService',
330 'FlashService', 'WebSocketService',
Simon Huntb0ec1e52015-01-28 18:13:49 -0800331
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700332 function (_$log_, _fs_, _ps_, _gs_, _flash_, _wss_) {
Simon Huntb0ec1e52015-01-28 18:13:49 -0800333 $log = _$log_;
Simon Hunt6036b192015-02-11 11:20:26 -0800334 fs = _fs_;
Simon Huntb0ec1e52015-01-28 18:13:49 -0800335 ps = _ps_;
Simon Huntc9b73162015-01-29 14:02:15 -0800336 gs = _gs_;
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700337 flash = _flash_;
Simon Hunt237676b52015-03-10 19:04:26 -0700338 wss = _wss_;
Simon Huntb0ec1e52015-01-28 18:13:49 -0800339
Simon Huntb0ec1e52015-01-28 18:13:49 -0800340 return {
341 initPanels: initPanels,
Simon Hunt626d2102015-01-29 11:54:50 -0800342 destroyPanels: destroyPanels,
Simon Hunt08f841d02015-02-10 14:39:20 -0800343
344 showSummary: showSummary,
Simon Hunt6036b192015-02-11 11:20:26 -0800345 toggleSummary: toggleSummary,
Simon Hunt08f841d02015-02-10 14:39:20 -0800346
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700347 toggleDetails: toggleDetails,
Simon Hunt08f841d02015-02-10 14:39:20 -0800348 displaySingle: displaySingle,
349 displayMulti: displayMulti,
350 addAction: addAction,
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700351 displayLink: displayLink,
352 displayNothing: displayNothing,
353 displaySomething: displaySomething,
Simon Hunt08f841d02015-02-10 14:39:20 -0800354
Simon Huntc252aa62015-02-10 16:45:39 -0800355 hideSummaryPanel: hideSummaryPanel,
Simon Hunt08f841d02015-02-10 14:39:20 -0800356
357 detailVisible: function () { return detailPanel.isVisible(); },
358 summaryVisible: function () { return summaryPanel.isVisible(); }
Simon Huntb0ec1e52015-01-28 18:13:49 -0800359 };
360 }]);
361}());