Added user preference handling
From comments on our paging review, it became clear that we need some kind of user preference support. This commit provides a client-side implementation with an abstraction layer that allows us to connect the API at a later time. Actions taken: - Added currentUser resolution for routes. - Added new profile module to handle user profile management. - Added navigation in menu. - Small fix to logout button in mobile, to make sure it doesn't show up. - New route and UI for /profile/preferences - Created preference provider factory that allows any module to register/inject their own preferences with defaults. See services/resource/preference.js as an example. Change-Id: I2d72a40a9e0c3a142da6c1d1e5f9dd4da7ca58a1
This commit is contained in:
parent
8b9f371065
commit
359297afab
@ -80,6 +80,15 @@ angular.module('sb.auth').constant('SessionResolver',
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* This resolver ensures that the currentUser has been resolved
|
||||
* before the route resolves.
|
||||
*/
|
||||
requireCurrentUser: function ($q, $log, CurrentUser) {
|
||||
$log.debug('Resolving current user...');
|
||||
return CurrentUser.resolve();
|
||||
}
|
||||
};
|
||||
})());
|
||||
|
31
src/app/profile/controller/profile_preferences_controller.js
Normal file
31
src/app/profile/controller/profile_preferences_controller.js
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Preferences controller for our user profile. Allows explicit editing of
|
||||
* individual preferences.
|
||||
*/
|
||||
angular.module('sb.profile').controller('ProfilePreferencesController',
|
||||
function ($scope, Preference) {
|
||||
'use strict';
|
||||
|
||||
$scope.pageSize = Preference.$get('page_size');
|
||||
|
||||
$scope.save = function () {
|
||||
Preference.$set('page_size', $scope.pageSize);
|
||||
$scope.message = 'Preferences Saved!';
|
||||
};
|
||||
});
|
50
src/app/profile/module.js
Normal file
50
src/app/profile/module.js
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Storyboard root application module.
|
||||
*
|
||||
* This module contains the entire, standalone application for the Storyboard
|
||||
* ticket tracking web client.
|
||||
*
|
||||
* @author Michael Krotscheck
|
||||
*/
|
||||
angular.module('sb.profile',
|
||||
['sb.services', 'sb.templates', 'sb.auth', 'ui.router', 'ui.bootstrap']
|
||||
)
|
||||
.config(function ($stateProvider, SessionResolver, $urlRouterProvider) {
|
||||
'use strict';
|
||||
|
||||
// URL Defaults.
|
||||
$urlRouterProvider.when('/profile', '/profile/preferences');
|
||||
|
||||
// Declare the states for this module.
|
||||
$stateProvider
|
||||
.state('profile', {
|
||||
abstract: true,
|
||||
template: '<div ui-view></div>',
|
||||
url: '/profile',
|
||||
resolve: {
|
||||
isLoggedIn: SessionResolver.requireLoggedIn,
|
||||
currentUser: SessionResolver.requireCurrentUser
|
||||
}
|
||||
})
|
||||
.state('profile.preferences', {
|
||||
url: '/preferences',
|
||||
templateUrl: 'app/templates/profile/preferences.html',
|
||||
controller: 'ProfilePreferencesController'
|
||||
});
|
||||
});
|
114
src/app/services/resource/preference.js
Normal file
114
src/app/services/resource/preference.js
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple preferences service, backed by localStorage.
|
||||
*/
|
||||
angular.module('sb.services').provider('Preference',
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Our preference defaults. We're using underscore naming here in
|
||||
* anticipation of these keys living on the python side of things.
|
||||
*/
|
||||
var defaults = { };
|
||||
|
||||
/**
|
||||
* Preference name key generator. Basically it's poor man's
|
||||
* namespacing.
|
||||
*/
|
||||
function preferenceName(key) {
|
||||
return 'pref_' + key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Each module can manually declare its own preferences that it would
|
||||
* like to keep track of, as well as set a default. During the config()
|
||||
* phase, inject the Preference Provider and call 'addPreference()' to
|
||||
* do so. An example is available at the bottom of this file.
|
||||
*/
|
||||
this.addPreference = function (preferenceName, preferenceDefault) {
|
||||
defaults[preferenceName] = preferenceDefault;
|
||||
};
|
||||
|
||||
/**
|
||||
* The actual preference implementation.
|
||||
*/
|
||||
function Preference($log, localStorageService) {
|
||||
/**
|
||||
* Get a preference.
|
||||
*/
|
||||
this.$get = function (key) {
|
||||
|
||||
// Is this a valid preference?
|
||||
if (!defaults.hasOwnProperty(key)) {
|
||||
$log.warn('Attempt to get unregistered preference: ' +
|
||||
key);
|
||||
return null;
|
||||
}
|
||||
|
||||
var value = localStorageService.get(preferenceName(key));
|
||||
|
||||
// If the value is unset, and we have a default, set and use
|
||||
// that.
|
||||
if (value === null && defaults.hasOwnProperty(key)) {
|
||||
var defaultValue = defaults[key];
|
||||
this.$set(key, defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a preference.
|
||||
*/
|
||||
this.$set = function (key, value) {
|
||||
|
||||
// Is this a valid preference?
|
||||
if (!defaults.hasOwnProperty(key)) {
|
||||
$log.warn('Attempt to set unregistered preference: ' +
|
||||
key);
|
||||
return null;
|
||||
}
|
||||
|
||||
return localStorageService.set(preferenceName(key), value);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory getter - returns a configured instance of preference
|
||||
* provider, as needed.
|
||||
*/
|
||||
this.$get = function ($log, localStorageService) {
|
||||
return new Preference($log, localStorageService);
|
||||
};
|
||||
})
|
||||
.config(function (PreferenceProvider) {
|
||||
'use strict';
|
||||
|
||||
// WARNING: In all modules OTHER than the services module, this config
|
||||
// block can appear anywhere as long as this module is listed as a
|
||||
// dependency. In the services module, the config() block must appear
|
||||
// AFTER the provider block. For more information,
|
||||
// @see https://github.com/angular/angular.js/issues/6723
|
||||
|
||||
// Let our preference provider know about page_size.
|
||||
PreferenceProvider.addPreference('page_size', 10);
|
||||
|
||||
})
|
||||
;
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
angular.module('storyboard',
|
||||
[ 'sb.services', 'sb.templates', 'sb.pages', 'sb.projects', 'sb.auth',
|
||||
'sb.story', 'ui.router', 'ui.bootstrap']
|
||||
'sb.story', 'sb.profile', 'ui.router', 'ui.bootstrap']
|
||||
)
|
||||
.config(function ($provide, $stateProvider, $urlRouterProvider,
|
||||
$locationProvider, $httpProvider) {
|
||||
|
@ -64,12 +64,17 @@
|
||||
<li class="visible-xs">
|
||||
<hr/>
|
||||
</li>
|
||||
|
||||
<li class="visible-xs">
|
||||
<a href="#!/profile/preferences" ng-show="isLoggedIn"
|
||||
active-path="^\/profile\/preferences*">Preferences</a>
|
||||
</li>
|
||||
<!-- Login/Logout button, XS only. -->
|
||||
<li class="visible-xs">
|
||||
<a href="#!/auth/authorize" ng-hide="isLoggedIn">
|
||||
Log in
|
||||
</a>
|
||||
<a href="" ng-click="logout()">
|
||||
<a href="" ng-click="logout()" ng-show="isLoggedIn">
|
||||
Log out
|
||||
</a>
|
||||
</li>
|
||||
@ -93,6 +98,9 @@
|
||||
<i class="fa fa-caret-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#!/profile/preferences">Preferences</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="logout()">Logout</a>
|
||||
</li>
|
||||
|
69
src/app/templates/profile/preferences.html
Normal file
69
src/app/templates/profile/preferences.html
Normal file
@ -0,0 +1,69 @@
|
||||
<!--
|
||||
~ Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
~ not use this file except in compliance with the License. You may obtain
|
||||
~ a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
~ License for the specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<div class="container" ng-hide="isLoading">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h1>Preferences</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<form name="preferencesForm">
|
||||
<div class="form-group">
|
||||
<label>Page size</label>
|
||||
|
||||
<p class="help-block">
|
||||
How many results would you like to see when viewing
|
||||
lists?
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<input type="radio" name="pageSize"
|
||||
id="pageSize10" value="10"
|
||||
ng-model="pageSize">
|
||||
10
|
||||
|
||||
<input type="radio" name="pageSize"
|
||||
id="pageSize25" value="25"
|
||||
ng-model="pageSize">
|
||||
25
|
||||
|
||||
<input type="radio" name="pageSize"
|
||||
id="pageSize50" value="50"
|
||||
ng-model="pageSize">
|
||||
50
|
||||
|
||||
<input type="radio" name="pageSize"
|
||||
id="pageSize100" value="100"
|
||||
ng-model="pageSize">
|
||||
100
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn btn-default"
|
||||
ng-click="save()">
|
||||
Save
|
||||
</button>
|
||||
<p class="help-block text-success">{{message}}</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
x
Reference in New Issue
Block a user