refactors out the usage of 'ui.showNavigation' and replaces with using appState. Adds unit tests for appState.

This commit is contained in:
Shannon
2013-11-13 15:51:59 +11:00
parent ac15e84324
commit ad7edf0d52
5 changed files with 165 additions and 63 deletions

View File

@@ -10,14 +10,11 @@ function appState($rootScope) {
//Define all variables here - we are never returning this objects so they cannot be publicly mutable
// changed, we only expose methods to interact with the values.
//var dialogState = {
// //The current dialog
// currentDialog: null,
// //The dialog title
// dialogTitle: null
//};
var globalState = {
showNavigation: null
};
var sectionState = {
//The currently active section
currentSection: null,
@@ -36,8 +33,57 @@ function appState($rootScope) {
showMenu: null
};
/** function to validate and set the state on a state object */
function setState(stateObj, key, value, stateObjName) {
if (!_.has(stateObj, key)) {
throw "The variable " + key + " does not exist in " + stateObjName;
}
var changed = stateObj[key] !== value;
stateObj[key] = value;
if (changed) {
$rootScope.$broadcast("appState." + stateObjName + ".changed", { key: key, value: value });
}
}
/** function to validate and set the state on a state object */
function getState(stateObj, key, stateObjName) {
if (!_.has(stateObj, key)) {
throw "The variable " + key + " does not exist in " + stateObjName;
}
return stateObj[key];
}
return {
/**
* @ngdoc function
* @name umbraco.services.angularHelper#getGlobalState
* @methodOf umbraco.services.appState
* @function
*
* @description
* Returns the current global state value by key - we do not return an object here - we do NOT want this
* to be publicly mutable and allow setting arbitrary values
*
*/
getGlobalState: function (key) {
return getState(globalState, key, "globalState");
},
/**
* @ngdoc function
* @name umbraco.services.angularHelper#setGlobalState
* @methodOf umbraco.services.appState
* @function
*
* @description
* Sets a global state value by key
*
*/
setGlobalState: function (key, value) {
setState(globalState, key, value, "globalState");
},
/**
* @ngdoc function
* @name umbraco.services.angularHelper#getSectionState
@@ -45,15 +91,12 @@ function appState($rootScope) {
* @function
*
* @description
* Returns the current section state value by key - we do not return a variable here - we do NOT want this
* Returns the current section state value by key - we do not return an object here - we do NOT want this
* to be publicly mutable and allow setting arbitrary values
*
*/
getSectionState: function (key) {
if (!_.has(sectionState, key)) {
throw "The variable " + key + " does not exist in section state";
}
return sectionState[key];
return getState(sectionState, key, "sectionState");
},
/**
@@ -67,14 +110,7 @@ function appState($rootScope) {
*
*/
setSectionState: function(key, value) {
if (!_.has(sectionState, key)) {
throw "The variable " + key + " does not exist in section state";
}
var changed = sectionState[key] !== value;
sectionState[key] = value;
if (changed) {
$rootScope.$broadcast("appState.sectionState.changed", { key: key, value: value });
}
setState(sectionState, key, value, "sectionState");
},
/**
@@ -84,15 +120,12 @@ function appState($rootScope) {
* @function
*
* @description
* Returns the current tree state value by key - we do not return a variable here - we do NOT want this
* Returns the current tree state value by key - we do not return an object here - we do NOT want this
* to be publicly mutable and allow setting arbitrary values
*
*/
getTreeState: function (key) {
if (!_.has(treeState, key)) {
throw "The variable " + key + " does not exist in tree state";
}
return treeState[key];
return getState(treeState, key, "treeState");
},
/**
@@ -106,14 +139,7 @@ function appState($rootScope) {
*
*/
setTreeState: function (key, value) {
if (!_.has(treeState, key)) {
throw "The variable " + key + " does not exist in tree state";
}
var changed = treeState[key] !== value;
treeState[key] = value;
if (changed) {
$rootScope.$broadcast("appState.treeState.changed", { key: key, value: value });
}
setState(treeState, key, value, "treeState");
},
/**
@@ -123,15 +149,12 @@ function appState($rootScope) {
* @function
*
* @description
* Returns the current menu state value by key - we do not return a variable here - we do NOT want this
* Returns the current menu state value by key - we do not return an object here - we do NOT want this
* to be publicly mutable and allow setting arbitrary values
*
*/
getMenuState: function (key) {
if (!_.has(menuState, key)) {
throw "The variable " + key + " does not exist in menu state";
}
return menuState[key];
return getState(menuState, key, "menuState");
},
/**
@@ -145,14 +168,7 @@ function appState($rootScope) {
*
*/
setMenuState: function (key, value) {
if (!_.has(menuState, key)) {
throw "The variable " + key + " does not exist in menu state";
}
var changed = treeState[key] !== value;
menuState[key] = value;
if (changed) {
$rootScope.$broadcast("appState.menuState.changed", { key: key, value: value });
}
setState(menuState, key, value, "menuState");
},
};

View File

@@ -22,7 +22,6 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
//Define all sub-properties for the UI object here
var ui = {
tablet: false,
showNavigation: false,
showContextMenu: false,
stickyNavigation: false,
showTray: false,
@@ -43,14 +42,15 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
function setTreeMode() {
ui.tablet = ($(window).width() <= minScreenSize);
ui.showNavigation = !ui.tablet;
appState.setGlobalState("showNavigation", !ui.tablet);
}
function setMode(mode) {
switch (mode) {
case 'tree':
ui.currentMode = "tree";
ui.showNavigation = true;
appState.setGlobalState("showNavigation", true);
ui.showContextMenu = false;
appState.setMenuState("showMenu", false);
ui.stickyNavigation = false;
@@ -60,7 +60,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
break;
case 'menu':
ui.currentMode = "menu";
ui.showNavigation = true;
appState.setGlobalState("showNavigation", true);
ui.showContextMenu = true;
appState.setMenuState("showMenu", false);
ui.stickyNavigation = true;
@@ -68,14 +68,14 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
case 'dialog':
ui.currentMode = "dialog";
ui.stickyNavigation = true;
ui.showNavigation = true;
appState.setGlobalState("showNavigation", true);
ui.showContextMenu = false;
appState.setMenuState("showMenu", true);
break;
case 'search':
ui.currentMode = "search";
ui.stickyNavigation = false;
ui.showNavigation = true;
appState.setGlobalState("showNavigation", true);
ui.showContextMenu = false;
appState.setSectionState("showSearchResults", true);
appState.setMenuState("showMenu", false);
@@ -94,7 +94,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
ui.showTray = false;
if (ui.tablet) {
ui.showNavigation = false;
appState.setGlobalState("showNavigation", false);
}
break;

View File

@@ -9,7 +9,14 @@
*
* @param {navigationService} navigationService A reference to the navigationService
*/
function NavigationController($scope,$rootScope, $location, $log, $routeParams, navigationService, keyboardService, dialogService, historyService, sectionResource, angularHelper) {
function NavigationController($scope, $rootScope, $location, $log, $routeParams, appState, navigationService, keyboardService, dialogService, historyService, sectionResource, angularHelper) {
//TODO: Put all of this nav service init in the main controller ! - or on the appStart not here!
//initialize nav service
navigationService.init();
//the tree event handler i used to subscribe to the main tree click events
$scope.treeEventHandler = $({});
navigationService.setupTreeEvents($scope.treeEventHandler, $scope);
//Put the navigation service on this scope so we can use it's methods/properties in the view.
// IMPORTANT: all properties assigned to this scope are generally available on the scope object on dialogs since
@@ -19,14 +26,8 @@ function NavigationController($scope,$rootScope, $location, $log, $routeParams,
//set up our scope vars
$scope.showContextMenuDialog = false;
$scope.showSearchResults = false;
$scope.currentSection = null;
//TODO: Put all of this in the main controller ! - or on the appStart not here!
//initialize nav service
navigationService.init();
//the tree event handler i used to subscribe to the main tree click events
$scope.treeEventHandler = $({});
navigationService.setupTreeEvents($scope.treeEventHandler, $scope);
$scope.currentSection = appState.getSectionState("currentSection");
$scope.showNavigation = appState.getGlobalState("showNavigation");
//trigger search with a hotkey:
keyboardService.bind("ctrl+shift+s", function(){
@@ -41,6 +42,13 @@ function NavigationController($scope,$rootScope, $location, $log, $routeParams,
$scope.selectedId = navigationService.currentId;
//Listen for global state changes
$scope.$on("appState.globalState.changed", function (e, args) {
if (args.key === "showNavigation") {
$scope.showNavigation = args.value;
}
});
//Listen for menu state changes
$scope.$on("appState.menuState.changed", function(e, args) {
if (args.key === "showMenu") {

View File

@@ -5,7 +5,7 @@
</umb-sections>
<!-- navigation container -->
<div id="navigation" ng-show="nav.ui.showNavigation" class="fill umb-modalcolumn" ng-animate="'slide'">
<div id="navigation" ng-show="showNavigation" class="fill umb-modalcolumn" ng-animate="'slide'">
<div ng-swipe-left="nav.hideNavigation()" class="navigation-inner-container span6" style="z-index: 100">

View File

@@ -0,0 +1,78 @@
describe('appState tests', function () {
var appState, $rootScope;
beforeEach(module('umbraco.services'));
beforeEach(inject(function ($injector) {
appState = $injector.get('appState');
$rootScope = $injector.get('$rootScope');
}));
describe('Global state', function () {
it('Can get/set state', function () {
appState.setGlobalState("showNavigation", true);
expect(appState.getGlobalState("showNavigation")).toBe(true);
});
it('Throws when invalid key', function () {
function setInvalidKey() {
appState.setGlobalState("blah", true);
}
function getInvalidKey() {
appState.getGlobalState("blah");
}
expect(setInvalidKey).toThrow();
expect(getInvalidKey).toThrow();
});
});
describe('Section state', function () {
it('Can get/set state', function () {
appState.setSectionState("currentSection", true);
expect(appState.getSectionState("currentSection")).toBe(true);
});
it('Throws when invalid key', function () {
function setInvalidKey() {
appState.getSectionState("blah", true);
}
function getInvalidKey() {
appState.setSectionState("blah");
}
expect(setInvalidKey).toThrow();
expect(getInvalidKey).toThrow();
});
});
describe('Tree state', function () {
it('Can get/set state', function () {
appState.setTreeState("currentEntity", true);
expect(appState.getTreeState("currentEntity")).toBe(true);
});
it('Throws when invalid key', function () {
function setInvalidKey() {
appState.getTreeState("blah", true);
}
function getInvalidKey() {
appState.setTreeState("blah");
}
expect(setInvalidKey).toThrow();
expect(getInvalidKey).toThrow();
});
});
describe('Menu state', function () {
it('Can get/set state', function () {
appState.setMenuState("showMenu", true);
expect(appState.getMenuState("showMenu")).toBe(true);
});
it('Throws when invalid key', function () {
function setInvalidKey() {
appState.getMenuState("blah", true);
}
function getInvalidKey() {
appState.setMenuState("blah");
}
expect(setInvalidKey).toThrow();
expect(getInvalidKey).toThrow();
});
});
});