GUI -- First cut at persisting user settings (on topology view).
Change-Id: Id58a744bf3514852b31d9d8c053c6e167974e1ef
Showing
6 changed files
with
327 additions
and
19 deletions
... | @@ -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 |
-
Please register or login to post a comment