blob: 2d54328fc301a67c22d81f308c4b0d5fae566304 [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 Hunt6036b192015-02-11 11:20:26 -0800228 function toggleSummary() {
229 if (summaryPanel.isVisible()) {
Simon Hunt6036b192015-02-11 11:20:26 -0800230 hideSummaryPanel();
231 } else {
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 Hunt6036b192015-02-11 11:20:26 -0800235 }
236 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800237
238 // === -----------------------------------------------------
239 // === LOGIC For showing/hiding summary and detail panels...
240
Simon Hunt626d2102015-01-29 11:54:50 -0800241 function showSummaryPanel() {
Simon Hunt6036b192015-02-11 11:20:26 -0800242 if (detailPanel.isVisible()) {
243 detailPanel.down(summaryPanel.show);
244 } else {
245 summaryPanel.show();
246 }
Simon Huntc252aa62015-02-10 16:45:39 -0800247 }
248
249 function hideSummaryPanel() {
Simon Hunta0eb0a82015-02-11 12:30:06 -0800250 // instruct server to stop sending summary data
Simon Hunt237676b52015-03-10 19:04:26 -0700251 wss.sendEvent("cancelSummary");
Simon Hunta0eb0a82015-02-11 12:30:06 -0800252 summaryPanel.hide(detailPanel.up);
Simon Hunt4b668592015-01-29 17:33:53 -0800253 }
Simon Hunt626d2102015-01-29 11:54:50 -0800254
Simon Hunt08f841d02015-02-10 14:39:20 -0800255 function showDetailPanel() {
Simon Hunt6036b192015-02-11 11:20:26 -0800256 if (summaryPanel.isVisible()) {
257 detailPanel.down(detailPanel.show);
258 } else {
259 detailPanel.up(detailPanel.show);
260 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800261 }
262
263 function hideDetailPanel() {
264 detailPanel.hide();
265 }
266
Simon Hunt6036b192015-02-11 11:20:26 -0800267 // ==========================
Simon Hunt08f841d02015-02-10 14:39:20 -0800268
Simon Hunt6036b192015-02-11 11:20:26 -0800269 function noop () {}
270
271 function augmentDetailPanel() {
272 var dp = detailPanel;
273 dp.ypos = { up: 64, down: 320, current: 320};
274
275 dp._move = function (y, cb) {
276 var endCb = fs.isF(cb) || noop,
277 yp = dp.ypos;
278 if (yp.current !== y) {
279 yp.current = y;
280 dp.el().transition().duration(300)
281 .each('end', endCb)
282 .style('top', yp.current + 'px');
283 } else {
284 endCb();
285 }
286 };
287
288 dp.down = function (cb) { dp._move(dp.ypos.down, cb); };
289 dp.up = function (cb) { dp._move(dp.ypos.up, cb); };
290 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800291
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700292 function toggleDetails() {
293 useDetails = !useDetails;
294 if (useDetails) {
295 flash.flash('Enable details panel');
296 if (haveDetails) {
297 showDetailPanel();
298 }
299 } else {
300 flash.flash('Disable details panel');
301 hideDetailPanel();
302 }
303 }
304
Simon Hunt4b668592015-01-29 17:33:53 -0800305 // ==========================
306
Simon Hunt237676b52015-03-10 19:04:26 -0700307 function initPanels() {
Simon Hunt4b668592015-01-29 17:33:53 -0800308 summaryPanel = ps.createPanel(idSum, panelOpts);
309 detailPanel = ps.createPanel(idDet, panelOpts);
Simon Hunt08f841d02015-02-10 14:39:20 -0800310
311 summaryPanel.classed(pCls, true);
312 detailPanel.classed(pCls, true);
Simon Hunt6036b192015-02-11 11:20:26 -0800313
314 augmentDetailPanel();
Simon Hunt4b668592015-01-29 17:33:53 -0800315 }
316
317 function destroyPanels() {
318 ps.destroyPanel(idSum);
319 ps.destroyPanel(idDet);
320 summaryPanel = detailPanel = null;
Simon Hunt626d2102015-01-29 11:54:50 -0800321 }
322
323 // ==========================
324
Simon Huntb0ec1e52015-01-28 18:13:49 -0800325 angular.module('ovTopo')
326 .factory('TopoPanelService',
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700327 ['$log', 'FnService', 'PanelService', 'GlyphService',
328 'FlashService', 'WebSocketService',
Simon Huntb0ec1e52015-01-28 18:13:49 -0800329
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700330 function (_$log_, _fs_, _ps_, _gs_, _flash_, _wss_) {
Simon Huntb0ec1e52015-01-28 18:13:49 -0800331 $log = _$log_;
Simon Hunt6036b192015-02-11 11:20:26 -0800332 fs = _fs_;
Simon Huntb0ec1e52015-01-28 18:13:49 -0800333 ps = _ps_;
Simon Huntc9b73162015-01-29 14:02:15 -0800334 gs = _gs_;
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700335 flash = _flash_;
Simon Hunt237676b52015-03-10 19:04:26 -0700336 wss = _wss_;
Simon Huntb0ec1e52015-01-28 18:13:49 -0800337
Simon Huntb0ec1e52015-01-28 18:13:49 -0800338 return {
339 initPanels: initPanels,
Simon Hunt626d2102015-01-29 11:54:50 -0800340 destroyPanels: destroyPanels,
Simon Hunt08f841d02015-02-10 14:39:20 -0800341
342 showSummary: showSummary,
Simon Hunt6036b192015-02-11 11:20:26 -0800343 toggleSummary: toggleSummary,
Simon Hunt08f841d02015-02-10 14:39:20 -0800344
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700345 toggleDetails: toggleDetails,
Simon Hunt08f841d02015-02-10 14:39:20 -0800346 displaySingle: displaySingle,
347 displayMulti: displayMulti,
348 addAction: addAction,
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700349 displayLink: displayLink,
350 displayNothing: displayNothing,
351 displaySomething: displaySomething,
Simon Hunt08f841d02015-02-10 14:39:20 -0800352
Simon Huntc252aa62015-02-10 16:45:39 -0800353 hideSummaryPanel: hideSummaryPanel,
Simon Hunt08f841d02015-02-10 14:39:20 -0800354
355 detailVisible: function () { return detailPanel.isVisible(); },
356 summaryVisible: function () { return summaryPanel.isVisible(); }
Simon Huntb0ec1e52015-01-28 18:13:49 -0800357 };
358 }]);
359}());