Simon Hunt

GUI -- First cut at persisting user settings (on topology view).

Change-Id: Id58a744bf3514852b31d9d8c053c6e167974e1ef
...@@ -22,13 +22,14 @@ ...@@ -22,13 +22,14 @@
22 'use strict'; 22 'use strict';
23 23
24 var moduleDependencies = [ 24 var moduleDependencies = [
25 + 'ngCookies',
25 'onosUtil', 26 'onosUtil',
26 'onosSvg', 27 'onosSvg',
27 'onosRemote' 28 'onosRemote'
28 ]; 29 ];
29 30
30 // references to injected services etc. 31 // references to injected services etc.
31 - var $log, fs, ks, zs, gs, ms, sus, flash, wss, 32 + var $log, $cookies, fs, ks, zs, gs, ms, sus, flash, wss,
32 tes, tfs, tps, tis, tss, tls, tts, tos, fltr, ttbs; 33 tes, tfs, tps, tis, tss, tls, tts, tos, fltr, ttbs;
33 34
34 // DOM elements 35 // DOM elements
...@@ -43,9 +44,9 @@ ...@@ -43,9 +44,9 @@
43 // key bindings need to be made after the services have been injected 44 // key bindings need to be made after the services have been injected
44 // thus, deferred to here... 45 // thus, deferred to here...
45 actionMap = { 46 actionMap = {
46 - I: [toggleInstances, 'Toggle ONOS instances pane'], 47 + I: [toggleInstances, 'Toggle ONOS instances panel'],
47 - O: [tps.toggleSummary, 'Toggle ONOS summary pane'], 48 + O: [tps.toggleSummary, 'Toggle ONOS summary panel'],
48 - D: [tps.toggleDetails, 'Disable / enable details pane'], 49 + D: [tps.toggleDetails, 'Disable / enable details panel'],
49 50
50 H: [tfs.toggleHosts, 'Toggle host visibility'], 51 H: [tfs.toggleHosts, 'Toggle host visibility'],
51 M: [tfs.toggleOffline, 'Toggle offline visibility'], 52 M: [tfs.toggleOffline, 'Toggle offline visibility'],
...@@ -96,15 +97,26 @@ ...@@ -96,15 +97,26 @@
96 97
97 // NOTE: this really belongs in the TopoPanelService -- but how to 98 // NOTE: this really belongs in the TopoPanelService -- but how to
98 // cleanly link in the updateDeviceColors() call? To be fixed later. 99 // cleanly link in the updateDeviceColors() call? To be fixed later.
99 - function toggleInstances() { 100 + function toggleInstances(x) {
100 - tis.toggle(); 101 + if (x === 'keyev') {
102 + tis.toggle();
103 + updateCookieState('insts', tis.isVisible());
104 + } else if (x) {
105 + tis.show();
106 + } else {
107 + tis.hide();
108 + }
101 tfs.updateDeviceColors(); 109 tfs.updateDeviceColors();
102 } 110 }
103 111
104 - function toggleMap() { 112 + function toggleMap(x) {
105 - sus.visible(mapG, !sus.visible(mapG)); 113 + var on = (x === 'keyev') ? !sus.visible(mapG) : !!x;
114 + sus.visible(mapG, on);
115 + updateCookieState('bg', on);
106 } 116 }
107 117
118 + // TODO: need wrapper functions for state changes needed in cookies
119 +
108 function resetZoom() { 120 function resetZoom() {
109 zoomer.reset(); 121 zoomer.reset();
110 } 122 }
...@@ -236,11 +248,85 @@ ...@@ -236,11 +248,85 @@
236 .attr('opacity', b ? 1 : 0); 248 .attr('opacity', b ? 1 : 0);
237 } 249 }
238 250
251 + // --- Config from Cookies -------------------------------------------
252 +
253 + // TODO: write a general purpose cookie service, rather than custom here
254 +
255 + // NOTE: in Angular 1.3.5, $cookies is just a simple object, and
256 + // cookie values are just strings. From the 1.3.5 docs:
257 + //
258 + // "Only a simple Object is exposed and by adding or removing
259 + // properties to/from this object, new cookies are created/deleted
260 + // at the end of current $eval. The object's properties can only
261 + // be strings."
262 + //
263 + // We may want to upgrade the version of Angular sometime soon
264 + // since later version support objects as cookie values.
265 +
266 + var defaultCookieState = {
267 + bg: 1,
268 + insts: 1,
269 + summary: 1,
270 + detail: 1,
271 + hosts: 0
272 + };
273 +
274 + var cookieState = {};
275 +
276 + function writeCookieState() {
277 + var bits = [],
278 + str;
279 + angular.forEach(cookieState, function (value, key) {
280 + bits.push(key + ':' + value);
281 + });
282 + str = bits.join(',');
283 +
284 + // The angular way of doing this...
285 + // $cookies.topo_state = str;
286 + // ...but it appears that this gets delayed, and doesn't 'stick' ??
287 +
288 + // FORCE cookie to be set by writing directly to document.cookie...
289 + document.cookie = 'topo_state=' + encodeURIComponent(str);
290 + $log.debug('<<>> Wrote cookie:', str);
291 + }
292 +
293 + function readCookieState() {
294 + var cook = $cookies.topo_state || '',
295 + bits;
296 +
297 + if (!cook) {
298 + cookieState = angular.extend({}, defaultCookieState);
299 + writeCookieState(); // seed the pot
300 +
301 + } else {
302 + bits = cook.split(',');
303 + bits.forEach(function (value) {
304 + var x = value.split(':');
305 + cookieState[x[0]] = Number(x[1]);
306 + });
307 + }
308 + }
309 +
310 + function updateCookieState(what, b) {
311 + cookieState[what] = b ? 1 : 0;
312 + writeCookieState();
313 + }
314 +
315 + function restoreConfigFromCookies() {
316 + readCookieState();
317 + $log.debug('Cookie State:', cookieState);
318 +
319 + toggleInstances(cookieState.insts);
320 + tps.toggleSummary(cookieState.summary);
321 + tps.toggleDetails(cookieState.detail);
322 + }
323 +
324 +
239 // --- Controller Definition ----------------------------------------- 325 // --- Controller Definition -----------------------------------------
240 326
241 angular.module('ovTopo', moduleDependencies) 327 angular.module('ovTopo', moduleDependencies)
242 .controller('OvTopoCtrl', ['$scope', '$log', '$location', '$timeout', 328 .controller('OvTopoCtrl', ['$scope', '$log', '$location', '$timeout',
243 - 'FnService', 'MastService', 'KeyService', 'ZoomService', 329 + '$cookies', 'FnService', 'MastService', 'KeyService', 'ZoomService',
244 'GlyphService', 'MapService', 'SvgUtilService', 'FlashService', 330 'GlyphService', 'MapService', 'SvgUtilService', 'FlashService',
245 'WebSocketService', 331 'WebSocketService',
246 'TopoEventService', 'TopoForceService', 'TopoPanelService', 332 'TopoEventService', 'TopoForceService', 'TopoPanelService',
...@@ -248,8 +334,8 @@ ...@@ -248,8 +334,8 @@
248 'TopoTrafficService', 'TopoObliqueService', 'TopoFilterService', 334 'TopoTrafficService', 'TopoObliqueService', 'TopoFilterService',
249 'TopoToolbarService', 335 'TopoToolbarService',
250 336
251 - function ($scope, _$log_, $loc, $timeout, _fs_, mast, _ks_, _zs_, 337 + function ($scope, _$log_, $loc, $timeout, _$cookies_, _fs_, mast, _ks_,
252 - _gs_, _ms_, _sus_, _flash_, _wss_, _tes_, _tfs_, _tps_, 338 + _zs_, _gs_, _ms_, _sus_, _flash_, _wss_, _tes_, _tfs_, _tps_,
253 _tis_, _tss_, _tls_, _tts_, _tos_, _fltr_, _ttbs_) { 339 _tis_, _tss_, _tls_, _tts_, _tos_, _fltr_, _ttbs_) {
254 var self = this, 340 var self = this,
255 projection, 341 projection,
...@@ -264,6 +350,7 @@ ...@@ -264,6 +350,7 @@
264 }; 350 };
265 351
266 $log = _$log_; 352 $log = _$log_;
353 + $cookies = _$cookies_;
267 fs = _fs_; 354 fs = _fs_;
268 ks = _ks_; 355 ks = _ks_;
269 zs = _zs_; 356 zs = _zs_;
...@@ -316,6 +403,7 @@ ...@@ -316,6 +403,7 @@
316 function (proj) { 403 function (proj) {
317 projection = proj; 404 projection = proj;
318 $log.debug('** We installed the projection: ', proj); 405 $log.debug('** We installed the projection: ', proj);
406 + toggleMap(cookieState.bg);
319 } 407 }
320 ); 408 );
321 409
...@@ -325,6 +413,9 @@ ...@@ -325,6 +413,9 @@
325 tps.initPanels(); 413 tps.initPanels();
326 tes.start(); 414 tes.start();
327 415
416 + // temporary solution for persisting user settings
417 + restoreConfigFromCookies();
418 +
328 $log.log('OvTopoCtrl has been created'); 419 $log.log('OvTopoCtrl has been created');
329 }]); 420 }]);
330 }()); 421 }());
......
...@@ -225,13 +225,15 @@ ...@@ -225,13 +225,15 @@
225 showSummaryPanel(); 225 showSummaryPanel();
226 } 226 }
227 227
228 - function toggleSummary() { 228 + function toggleSummary(x) {
229 - if (summaryPanel.isVisible()) { 229 + var on = (x === 'keyev') ? !summaryPanel.isVisible() : !!x;
230 - hideSummaryPanel(); 230 +
231 - } else { 231 + if (on) {
232 // ask server to start sending summary data. 232 // ask server to start sending summary data.
233 wss.sendEvent('requestSummary'); 233 wss.sendEvent('requestSummary');
234 // note: the summary panel will appear, once data arrives 234 // note: the summary panel will appear, once data arrives
235 + } else {
236 + hideSummaryPanel();
235 } 237 }
236 } 238 }
237 239
...@@ -289,8 +291,8 @@ ...@@ -289,8 +291,8 @@
289 dp.up = function (cb) { dp._move(dp.ypos.up, cb); }; 291 dp.up = function (cb) { dp._move(dp.ypos.up, cb); };
290 } 292 }
291 293
292 - function toggleDetails() { 294 + function toggleDetails(x) {
293 - useDetails = !useDetails; 295 + useDetails = (x === 'keyev') ? !useDetails : !!x;
294 if (useDetails) { 296 if (useDetails) {
295 flash.flash('Enable details panel'); 297 flash.flash('Enable details panel');
296 if (haveDetails) { 298 if (haveDetails) {
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
61 61
62 function nodeMouseOver(m) { 62 function nodeMouseOver(m) {
63 if (!m.dragStarted) { 63 if (!m.dragStarted) {
64 - $log.debug("MouseOver()...", m); 64 + //$log.debug("MouseOver()...", m);
65 if (hovered != m) { 65 if (hovered != m) {
66 hovered = m; 66 hovered = m;
67 tts.requestTrafficForMode(); 67 tts.requestTrafficForMode();
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
75 hovered = null; 75 hovered = null;
76 tts.requestTrafficForMode(); 76 tts.requestTrafficForMode();
77 } 77 }
78 - $log.debug("MouseOut()...", m); 78 + //$log.debug("MouseOut()...", m);
79 } 79 }
80 } 80 }
81 81
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
30 <!--TODO: use minified versions, once debugging is complete --> 30 <!--TODO: use minified versions, once debugging is complete -->
31 <script src="tp/angular.js"></script> 31 <script src="tp/angular.js"></script>
32 <script src="tp/angular-route.js"></script> 32 <script src="tp/angular-route.js"></script>
33 + <script src="tp/angular-cookies.js"></script>
33 34
34 <script src="tp/d3.js"></script> 35 <script src="tp/d3.js"></script>
35 <script src="tp/topojson.v1.min.js"></script> 36 <script src="tp/topojson.v1.min.js"></script>
......
1 +/**
2 + * @license AngularJS v1.3.5
3 + * (c) 2010-2014 Google, Inc. http://angularjs.org
4 + * License: MIT
5 + */
6 +(function(window, angular, undefined) {'use strict';
7 +
8 +/**
9 + * @ngdoc module
10 + * @name ngCookies
11 + * @description
12 + *
13 + * # ngCookies
14 + *
15 + * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
16 + *
17 + *
18 + * <div doc-module-components="ngCookies"></div>
19 + *
20 + * See {@link ngCookies.$cookies `$cookies`} and
21 + * {@link ngCookies.$cookieStore `$cookieStore`} for usage.
22 + */
23 +
24 +
25 +angular.module('ngCookies', ['ng']).
26 + /**
27 + * @ngdoc service
28 + * @name $cookies
29 + *
30 + * @description
31 + * Provides read/write access to browser's cookies.
32 + *
33 + * Only a simple Object is exposed and by adding or removing properties to/from this object, new
34 + * cookies are created/deleted at the end of current $eval.
35 + * The object's properties can only be strings.
36 + *
37 + * Requires the {@link ngCookies `ngCookies`} module to be installed.
38 + *
39 + * @example
40 + *
41 + * ```js
42 + * angular.module('cookiesExample', ['ngCookies'])
43 + * .controller('ExampleController', ['$cookies', function($cookies) {
44 + * // Retrieving a cookie
45 + * var favoriteCookie = $cookies.myFavorite;
46 + * // Setting a cookie
47 + * $cookies.myFavorite = 'oatmeal';
48 + * }]);
49 + * ```
50 + */
51 + factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) {
52 + var cookies = {},
53 + lastCookies = {},
54 + lastBrowserCookies,
55 + runEval = false,
56 + copy = angular.copy,
57 + isUndefined = angular.isUndefined;
58 +
59 + //creates a poller fn that copies all cookies from the $browser to service & inits the service
60 + $browser.addPollFn(function() {
61 + var currentCookies = $browser.cookies();
62 + if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
63 + lastBrowserCookies = currentCookies;
64 + copy(currentCookies, lastCookies);
65 + copy(currentCookies, cookies);
66 + if (runEval) $rootScope.$apply();
67 + }
68 + })();
69 +
70 + runEval = true;
71 +
72 + //at the end of each eval, push cookies
73 + //TODO: this should happen before the "delayed" watches fire, because if some cookies are not
74 + // strings or browser refuses to store some cookies, we update the model in the push fn.
75 + $rootScope.$watch(push);
76 +
77 + return cookies;
78 +
79 +
80 + /**
81 + * Pushes all the cookies from the service to the browser and verifies if all cookies were
82 + * stored.
83 + */
84 + function push() {
85 + var name,
86 + value,
87 + browserCookies,
88 + updated;
89 +
90 + //delete any cookies deleted in $cookies
91 + for (name in lastCookies) {
92 + if (isUndefined(cookies[name])) {
93 + $browser.cookies(name, undefined);
94 + }
95 + }
96 +
97 + //update all cookies updated in $cookies
98 + for (name in cookies) {
99 + value = cookies[name];
100 + if (!angular.isString(value)) {
101 + value = '' + value;
102 + cookies[name] = value;
103 + }
104 + if (value !== lastCookies[name]) {
105 + $browser.cookies(name, value);
106 + updated = true;
107 + }
108 + }
109 +
110 + //verify what was actually stored
111 + if (updated) {
112 + updated = false;
113 + browserCookies = $browser.cookies();
114 +
115 + for (name in cookies) {
116 + if (cookies[name] !== browserCookies[name]) {
117 + //delete or reset all cookies that the browser dropped from $cookies
118 + if (isUndefined(browserCookies[name])) {
119 + delete cookies[name];
120 + } else {
121 + cookies[name] = browserCookies[name];
122 + }
123 + updated = true;
124 + }
125 + }
126 + }
127 + }
128 + }]).
129 +
130 +
131 + /**
132 + * @ngdoc service
133 + * @name $cookieStore
134 + * @requires $cookies
135 + *
136 + * @description
137 + * Provides a key-value (string-object) storage, that is backed by session cookies.
138 + * Objects put or retrieved from this storage are automatically serialized or
139 + * deserialized by angular's toJson/fromJson.
140 + *
141 + * Requires the {@link ngCookies `ngCookies`} module to be installed.
142 + *
143 + * @example
144 + *
145 + * ```js
146 + * angular.module('cookieStoreExample', ['ngCookies'])
147 + * .controller('ExampleController', ['$cookieStore', function($cookieStore) {
148 + * // Put cookie
149 + * $cookieStore.put('myFavorite','oatmeal');
150 + * // Get cookie
151 + * var favoriteCookie = $cookieStore.get('myFavorite');
152 + * // Removing a cookie
153 + * $cookieStore.remove('myFavorite');
154 + * }]);
155 + * ```
156 + */
157 + factory('$cookieStore', ['$cookies', function($cookies) {
158 +
159 + return {
160 + /**
161 + * @ngdoc method
162 + * @name $cookieStore#get
163 + *
164 + * @description
165 + * Returns the value of given cookie key
166 + *
167 + * @param {string} key Id to use for lookup.
168 + * @returns {Object} Deserialized cookie value.
169 + */
170 + get: function(key) {
171 + var value = $cookies[key];
172 + return value ? angular.fromJson(value) : value;
173 + },
174 +
175 + /**
176 + * @ngdoc method
177 + * @name $cookieStore#put
178 + *
179 + * @description
180 + * Sets a value for given cookie key
181 + *
182 + * @param {string} key Id for the `value`.
183 + * @param {Object} value Value to be stored.
184 + */
185 + put: function(key, value) {
186 + $cookies[key] = angular.toJson(value);
187 + },
188 +
189 + /**
190 + * @ngdoc method
191 + * @name $cookieStore#remove
192 + *
193 + * @description
194 + * Remove given cookie
195 + *
196 + * @param {string} key Id of the key-value pair to delete.
197 + */
198 + remove: function(key) {
199 + delete $cookies[key];
200 + }
201 + };
202 +
203 + }]);
204 +
205 +
206 +})(window, window.angular);
1 +/*
2 + AngularJS v1.3.5
3 + (c) 2010-2014 Google, Inc. http://angularjs.org
4 + License: MIT
5 +*/
6 +(function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(e,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&e.$apply())})();k=!0;e.$watch(function(){var a,d,e;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)d=c[a],f.isString(d)||(d=""+d,c[a]=d),d!==g[a]&&(b.cookies(a,d),e=!0);if(e)for(a in d=b.cookies(),c)c[a]!==d[a]&&(m(d[a])?delete c[a]:c[a]=d[a])});return c}]).factory("$cookieStore",
7 +["$cookies",function(e){return{get:function(b){return(b=e[b])?f.fromJson(b):b},put:function(b,c){e[b]=f.toJson(c)},remove:function(b){delete e[b]}}}])})(window,window.angular);
8 +//# sourceMappingURL=angular-cookies.min.js.map