Simon Hunt

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

Change-Id: Id58a744bf3514852b31d9d8c053c6e167974e1ef
......@@ -22,13 +22,14 @@
'use strict';
var moduleDependencies = [
'ngCookies',
'onosUtil',
'onosSvg',
'onosRemote'
];
// references to injected services etc.
var $log, fs, ks, zs, gs, ms, sus, flash, wss,
var $log, $cookies, fs, ks, zs, gs, ms, sus, flash, wss,
tes, tfs, tps, tis, tss, tls, tts, tos, fltr, ttbs;
// DOM elements
......@@ -43,9 +44,9 @@
// key bindings need to be made after the services have been injected
// thus, deferred to here...
actionMap = {
I: [toggleInstances, 'Toggle ONOS instances pane'],
O: [tps.toggleSummary, 'Toggle ONOS summary pane'],
D: [tps.toggleDetails, 'Disable / enable details pane'],
I: [toggleInstances, 'Toggle ONOS instances panel'],
O: [tps.toggleSummary, 'Toggle ONOS summary panel'],
D: [tps.toggleDetails, 'Disable / enable details panel'],
H: [tfs.toggleHosts, 'Toggle host visibility'],
M: [tfs.toggleOffline, 'Toggle offline visibility'],
......@@ -96,15 +97,26 @@
// NOTE: this really belongs in the TopoPanelService -- but how to
// cleanly link in the updateDeviceColors() call? To be fixed later.
function toggleInstances() {
tis.toggle();
function toggleInstances(x) {
if (x === 'keyev') {
tis.toggle();
updateCookieState('insts', tis.isVisible());
} else if (x) {
tis.show();
} else {
tis.hide();
}
tfs.updateDeviceColors();
}
function toggleMap() {
sus.visible(mapG, !sus.visible(mapG));
function toggleMap(x) {
var on = (x === 'keyev') ? !sus.visible(mapG) : !!x;
sus.visible(mapG, on);
updateCookieState('bg', on);
}
// TODO: need wrapper functions for state changes needed in cookies
function resetZoom() {
zoomer.reset();
}
......@@ -236,11 +248,85 @@
.attr('opacity', b ? 1 : 0);
}
// --- Config from Cookies -------------------------------------------
// TODO: write a general purpose cookie service, rather than custom here
// NOTE: in Angular 1.3.5, $cookies is just a simple object, and
// cookie values are just strings. From the 1.3.5 docs:
//
// "Only a simple Object is exposed and by adding or removing
// properties to/from this object, new cookies are created/deleted
// at the end of current $eval. The object's properties can only
// be strings."
//
// We may want to upgrade the version of Angular sometime soon
// since later version support objects as cookie values.
var defaultCookieState = {
bg: 1,
insts: 1,
summary: 1,
detail: 1,
hosts: 0
};
var cookieState = {};
function writeCookieState() {
var bits = [],
str;
angular.forEach(cookieState, function (value, key) {
bits.push(key + ':' + value);
});
str = bits.join(',');
// The angular way of doing this...
// $cookies.topo_state = str;
// ...but it appears that this gets delayed, and doesn't 'stick' ??
// FORCE cookie to be set by writing directly to document.cookie...
document.cookie = 'topo_state=' + encodeURIComponent(str);
$log.debug('<<>> Wrote cookie:', str);
}
function readCookieState() {
var cook = $cookies.topo_state || '',
bits;
if (!cook) {
cookieState = angular.extend({}, defaultCookieState);
writeCookieState(); // seed the pot
} else {
bits = cook.split(',');
bits.forEach(function (value) {
var x = value.split(':');
cookieState[x[0]] = Number(x[1]);
});
}
}
function updateCookieState(what, b) {
cookieState[what] = b ? 1 : 0;
writeCookieState();
}
function restoreConfigFromCookies() {
readCookieState();
$log.debug('Cookie State:', cookieState);
toggleInstances(cookieState.insts);
tps.toggleSummary(cookieState.summary);
tps.toggleDetails(cookieState.detail);
}
// --- Controller Definition -----------------------------------------
angular.module('ovTopo', moduleDependencies)
.controller('OvTopoCtrl', ['$scope', '$log', '$location', '$timeout',
'FnService', 'MastService', 'KeyService', 'ZoomService',
'$cookies', 'FnService', 'MastService', 'KeyService', 'ZoomService',
'GlyphService', 'MapService', 'SvgUtilService', 'FlashService',
'WebSocketService',
'TopoEventService', 'TopoForceService', 'TopoPanelService',
......@@ -248,8 +334,8 @@
'TopoTrafficService', 'TopoObliqueService', 'TopoFilterService',
'TopoToolbarService',
function ($scope, _$log_, $loc, $timeout, _fs_, mast, _ks_, _zs_,
_gs_, _ms_, _sus_, _flash_, _wss_, _tes_, _tfs_, _tps_,
function ($scope, _$log_, $loc, $timeout, _$cookies_, _fs_, mast, _ks_,
_zs_, _gs_, _ms_, _sus_, _flash_, _wss_, _tes_, _tfs_, _tps_,
_tis_, _tss_, _tls_, _tts_, _tos_, _fltr_, _ttbs_) {
var self = this,
projection,
......@@ -264,6 +350,7 @@
};
$log = _$log_;
$cookies = _$cookies_;
fs = _fs_;
ks = _ks_;
zs = _zs_;
......@@ -316,6 +403,7 @@
function (proj) {
projection = proj;
$log.debug('** We installed the projection: ', proj);
toggleMap(cookieState.bg);
}
);
......@@ -325,6 +413,9 @@
tps.initPanels();
tes.start();
// temporary solution for persisting user settings
restoreConfigFromCookies();
$log.log('OvTopoCtrl has been created');
}]);
}());
......
......@@ -225,13 +225,15 @@
showSummaryPanel();
}
function toggleSummary() {
if (summaryPanel.isVisible()) {
hideSummaryPanel();
} else {
function toggleSummary(x) {
var on = (x === 'keyev') ? !summaryPanel.isVisible() : !!x;
if (on) {
// ask server to start sending summary data.
wss.sendEvent('requestSummary');
// note: the summary panel will appear, once data arrives
} else {
hideSummaryPanel();
}
}
......@@ -289,8 +291,8 @@
dp.up = function (cb) { dp._move(dp.ypos.up, cb); };
}
function toggleDetails() {
useDetails = !useDetails;
function toggleDetails(x) {
useDetails = (x === 'keyev') ? !useDetails : !!x;
if (useDetails) {
flash.flash('Enable details panel');
if (haveDetails) {
......
......@@ -61,7 +61,7 @@
function nodeMouseOver(m) {
if (!m.dragStarted) {
$log.debug("MouseOver()...", m);
//$log.debug("MouseOver()...", m);
if (hovered != m) {
hovered = m;
tts.requestTrafficForMode();
......@@ -75,7 +75,7 @@
hovered = null;
tts.requestTrafficForMode();
}
$log.debug("MouseOut()...", m);
//$log.debug("MouseOut()...", m);
}
}
......
......@@ -30,6 +30,7 @@
<!--TODO: use minified versions, once debugging is complete -->
<script src="tp/angular.js"></script>
<script src="tp/angular-route.js"></script>
<script src="tp/angular-cookies.js"></script>
<script src="tp/d3.js"></script>
<script src="tp/topojson.v1.min.js"></script>
......
/**
* @license AngularJS v1.3.5
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {'use strict';
/**
* @ngdoc module
* @name ngCookies
* @description
*
* # ngCookies
*
* The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
*
*
* <div doc-module-components="ngCookies"></div>
*
* See {@link ngCookies.$cookies `$cookies`} and
* {@link ngCookies.$cookieStore `$cookieStore`} for usage.
*/
angular.module('ngCookies', ['ng']).
/**
* @ngdoc service
* @name $cookies
*
* @description
* Provides read/write access to browser's cookies.
*
* Only a simple Object is exposed and by adding or removing properties to/from this object, new
* cookies are created/deleted at the end of current $eval.
* The object's properties can only be strings.
*
* Requires the {@link ngCookies `ngCookies`} module to be installed.
*
* @example
*
* ```js
* angular.module('cookiesExample', ['ngCookies'])
* .controller('ExampleController', ['$cookies', function($cookies) {
* // Retrieving a cookie
* var favoriteCookie = $cookies.myFavorite;
* // Setting a cookie
* $cookies.myFavorite = 'oatmeal';
* }]);
* ```
*/
factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) {
var cookies = {},
lastCookies = {},
lastBrowserCookies,
runEval = false,
copy = angular.copy,
isUndefined = angular.isUndefined;
//creates a poller fn that copies all cookies from the $browser to service & inits the service
$browser.addPollFn(function() {
var currentCookies = $browser.cookies();
if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
lastBrowserCookies = currentCookies;
copy(currentCookies, lastCookies);
copy(currentCookies, cookies);
if (runEval) $rootScope.$apply();
}
})();
runEval = true;
//at the end of each eval, push cookies
//TODO: this should happen before the "delayed" watches fire, because if some cookies are not
// strings or browser refuses to store some cookies, we update the model in the push fn.
$rootScope.$watch(push);
return cookies;
/**
* Pushes all the cookies from the service to the browser and verifies if all cookies were
* stored.
*/
function push() {
var name,
value,
browserCookies,
updated;
//delete any cookies deleted in $cookies
for (name in lastCookies) {
if (isUndefined(cookies[name])) {
$browser.cookies(name, undefined);
}
}
//update all cookies updated in $cookies
for (name in cookies) {
value = cookies[name];
if (!angular.isString(value)) {
value = '' + value;
cookies[name] = value;
}
if (value !== lastCookies[name]) {
$browser.cookies(name, value);
updated = true;
}
}
//verify what was actually stored
if (updated) {
updated = false;
browserCookies = $browser.cookies();
for (name in cookies) {
if (cookies[name] !== browserCookies[name]) {
//delete or reset all cookies that the browser dropped from $cookies
if (isUndefined(browserCookies[name])) {
delete cookies[name];
} else {
cookies[name] = browserCookies[name];
}
updated = true;
}
}
}
}
}]).
/**
* @ngdoc service
* @name $cookieStore
* @requires $cookies
*
* @description
* Provides a key-value (string-object) storage, that is backed by session cookies.
* Objects put or retrieved from this storage are automatically serialized or
* deserialized by angular's toJson/fromJson.
*
* Requires the {@link ngCookies `ngCookies`} module to be installed.
*
* @example
*
* ```js
* angular.module('cookieStoreExample', ['ngCookies'])
* .controller('ExampleController', ['$cookieStore', function($cookieStore) {
* // Put cookie
* $cookieStore.put('myFavorite','oatmeal');
* // Get cookie
* var favoriteCookie = $cookieStore.get('myFavorite');
* // Removing a cookie
* $cookieStore.remove('myFavorite');
* }]);
* ```
*/
factory('$cookieStore', ['$cookies', function($cookies) {
return {
/**
* @ngdoc method
* @name $cookieStore#get
*
* @description
* Returns the value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {Object} Deserialized cookie value.
*/
get: function(key) {
var value = $cookies[key];
return value ? angular.fromJson(value) : value;
},
/**
* @ngdoc method
* @name $cookieStore#put
*
* @description
* Sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {Object} value Value to be stored.
*/
put: function(key, value) {
$cookies[key] = angular.toJson(value);
},
/**
* @ngdoc method
* @name $cookieStore#remove
*
* @description
* Remove given cookie
*
* @param {string} key Id of the key-value pair to delete.
*/
remove: function(key) {
delete $cookies[key];
}
};
}]);
})(window, window.angular);
/*
AngularJS v1.3.5
(c) 2010-2014 Google, Inc. http://angularjs.org
License: MIT
*/
(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",
["$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);
//# sourceMappingURL=angular-cookies.min.js.map