diff --git a/bower.json b/bower.json index bd7c6d9..0c21f18 100755 --- a/bower.json +++ b/bower.json @@ -24,19 +24,20 @@ "angular-jwt": "~0.0.9", "angular-footable": "~1.0.3", "appirio-tech-ng-auth": "3.x.x", - "appirio-tech-ng-api-services": "0.x.x" + "appirio-tech-ng-api-services": "0.x.x", + "angular-clipboard": "~1.2.1" }, "overrides": { "bootstrap": { "main": [ "less/bootstrap.less", + "dist/css/bootstrap.css", "dist/js/bootstrap.js", "dist/fonts/glyphicons-halflings-regular.eot", "dist/fonts/glyphicons-halflings-regular.svg", "dist/fonts/glyphicons-halflings-regular.ttf", "dist/fonts/glyphicons-halflings-regular.woff", - "dist/fonts/glyphicons-halflings-regular.woff2", - "css/bootstrap.css" + "dist/fonts/glyphicons-halflings-regular.woff2" ] }, "footable": { diff --git a/src/app/app.js b/src/app/app.js index ea2e68a..4629d0d 100755 --- a/src/app/app.js +++ b/src/app/app.js @@ -14,7 +14,8 @@ angular.module('supportAdminApp', [ 'app.constants', 'appirio-tech-ng-api-services', 'appirio-tech-ng-auth', - 'ui.footable']) + 'ui.footable', + 'angular-clipboard']) // In the run phase of your Angular application .run(function($rootScope, $location, AuthService, $state, UserV3Service) { // Listen to '$locationChangeSuccess', not '$stateChangeStart' diff --git a/src/app/login/login.controller.js b/src/app/login/login.controller.js index a84e502..274dfc8 100644 --- a/src/app/login/login.controller.js +++ b/src/app/login/login.controller.js @@ -32,12 +32,12 @@ angular.module('supportAdminApp') $userService.findById(token.userId).then( function(currentUser) { $rootScope.currentUser = currentUser; - $state.go('index.main'); + $state.go('index.users'); }, function(err) { $log.error('Failed to get user data.'); $log.error(err); - $state.go('index.main'); + $state.go('index.users'); } ); }; diff --git a/src/app/users/constants.js b/src/app/users/constants.js new file mode 100644 index 0000000..50aec4a --- /dev/null +++ b/src/app/users/constants.js @@ -0,0 +1,18 @@ +'use strict'; + +var module = angular.module('supportAdminApp'); + +module.constant('users.Constants', { + + MSG_CLIPBORD_TOOLTIP: "Copy to clipboard", + + MSG_CLIPBOARD_COPIED: "Copied", + + DICT_USER_STATUS: { + 'A': 'Active', + 'U': 'Unverified', + '4': 'Deactivated(User request)', + '5': 'Deactivated(Duplicate account)', + '6': 'Deactivated(Cheating account)' + } +}); diff --git a/src/app/users/user.js b/src/app/users/user.js new file mode 100644 index 0000000..63b0e7b --- /dev/null +++ b/src/app/users/user.js @@ -0,0 +1,40 @@ +'use strict'; + +var module = angular.module('supportAdminApp'); + +module.factory('User', ['$log', 'users.Constants', 'API_URL', + function($log, $const, API_URL) { + + var User = function() {}; + + + User.prototype.statusDesc = function() { + return $const.DICT_USER_STATUS[this.status]; + }; + + User.prototype.createdAtLabel = function() { + return this.formatDate(this.createdAt); + }; + + User.prototype.modifiedAtLabel = function() { + return this.formatDate(this.modifiedAt); + }; + + User.prototype.formatDate = function(isoDateText) { + return isoDateText && isoDateText.replace("T"," ").replace(".000Z",""); + }; + + /** + * create an activation link from an activation code. + */ + User.prototype.getActivationLink = function() { + if(!this.credential || !this.credential.activationCode) + return ''; + return API_URL + '/pub/activation.html?code=' + this.credential.activationCode + '&retUrl=https%3A%2F%2Fwww.topcoder.com%2Fskill-picker%2F'; + }; + + return User; + } +]); + + diff --git a/src/app/users/users.controller.js b/src/app/users/users.controller.js index b4a7da8..1aa3901 100644 --- a/src/app/users/users.controller.js +++ b/src/app/users/users.controller.js @@ -3,8 +3,8 @@ var module = angular.module('supportAdminApp'); module.controller('users.UserSearchController', [ - '$log', '$scope', '$rootScope', '$timeout', '$state', '$modal', 'AuthService','UserService', 'Alert', - function ($log, $scope, $rootScope, $timeout, $state, $modal, $authService, $userService, $alert) { + '$log', '$scope', '$rootScope', '$timeout', '$state', '$modal', 'AuthService', 'UserService', 'Alert', 'users.Constants', 'API_URL', + function ($log, $scope, $rootScope, $timeout, $state, $modal, $authService, $userService, $alert, $const, API_URL) { // footable angular.element(document).ready(function () { @@ -72,7 +72,7 @@ module.controller('users.UserSearchController', [ $scope.formSearch.setLoading(false); $timeout(function(){ $('.footable').trigger('footable_redraw'); - }, 100); + }, 100); }, function(error) { $alert.error(error.error, $scope); @@ -80,23 +80,23 @@ module.controller('users.UserSearchController', [ } ); }; - + // list $scope.users = []; - $scope.format = function(isoDateText) { - return isoDateText && isoDateText.replace("T"," ").replace(".000Z",""); - }; + // tooltip for activation link copy + $scope.tooltip = { + message : $const.MSG_CLIPBORD_TOOLTIP, - var statusLabels = { - 'A': 'Active', - 'U': 'Unverified', - '4': 'Deactivated(User request)', - '5': 'Deactivated(Duplicate account)', - '6': 'Deactivated(Cheating account)' - }; - $scope.statusLabel = function(status) { - return statusLabels[status] || 'Unknown'; + success : function() { + this.message = $const.MSG_CLIPBOARD_COPIED; + }, + fail : function(err) { + $log.debug(err); + }, + reset : function() { + $timeout(function(){ $scope.tooltip.message = $const.MSG_CLIPBORD_TOOLTIP; }, 250); + } }; $scope.activate = function(index) { @@ -123,9 +123,6 @@ module.controller('users.UserSearchController', [ }; $scope.openDeactivateDialog = function(index) { - var user = $scope.users[index]; - - //if(window.confirm('Are you sure you want to deactivate user \'' + user.handle + '\'?')) { var modalInstance = $modal.open({ size: 'sm', templateUrl: 'app/users/status-update-dialog.html', @@ -234,8 +231,8 @@ module.controller('users.UserEditDialogController', [ ]); module.controller('users.StatusUpdateDialogController', [ - '$scope', '$rootScope', '$timeout', '$state', '$modalInstance', 'AuthService', 'UserService', 'Alert', 'user', - function ($scope, $rootScope, $timeout, $state, $modalInstance, $authService, $userService, $alert, user) { + '$scope', '$rootScope', '$timeout', '$state', '$modalInstance', 'AuthService', 'UserService', 'users.Constants', 'Alert', 'user', + function ($scope, $rootScope, $timeout, $state, $modalInstance, $authService, $userService, $const, $alert, user) { $scope.form = { status : user.status, diff --git a/src/app/users/users.html b/src/app/users/users.html index 090f8d7..fed7b9b 100644 --- a/src/app/users/users.html +++ b/src/app/users/users.html @@ -9,7 +9,7 @@ --> - +

Members

@@ -88,10 +88,23 @@

Members

{{user.handle}} {{user.email}} {{user.firstName}} {{user.lastName}} - {{statusLabel(user.status)}} - {{format(user.createdAt)}} - {{format(user.modifiedAt)}} - {{user.credential.activationCode}} + {{user.statusDesc()}} + {{user.createdAtLabel()}} + {{user.modifiedAtLabel()}} + + {{user.credential.activationCode}} +
+ + + + + + +
+ diff --git a/src/app/users/users.service.js b/src/app/users/users.service.js index 98b3838..dc2916b 100644 --- a/src/app/users/users.service.js +++ b/src/app/users/users.service.js @@ -1,243 +1,269 @@ 'use strict'; angular.module('supportAdminApp') - .factory('UserService', ['$log', '$q','$http', 'API_URL', - function ($log, $q, $http, API_URL) { + .factory('UserService', ['$log', '$q','$http', 'User', 'API_URL', + function ($log, $q, $http, User, API_URL) { // local dev //var API_URL = 'http://local.topcoder-dev.com:8080'; - return ({ + + var UserService = {}; - /** find user by ID */ - findById: function(userId) { - if(!userId) { - return $q.reject({error : 'userId must be specified.'}); + /** find user by ID */ + UserService.findById = function(userId) { + if(!userId) { + return $q.reject({error : 'userId must be specified.'}); + } + + var request = $http({ + method: 'GET', + url: API_URL + '/v3/users/' + userId, + headers: { + "Content-Type":"application/json" } + }); - var request = $http({ - method: 'GET', - url: API_URL + '/v3/users/' + userId, - headers: { - "Content-Type":"application/json" + return request.then( + function(response) { + $log.debug(response); + return UserService.createUser(response.data.result.content); + }, + function(error) { + $log.error(error); + var err; + if(error && error.data && error.data.result) { + err = { + status: error.status, + error : error.data.result.content + }; } - }); - - return request.then( - function(response) { - $log.debug(response); - return response.data.result.content; - }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); + if(!err) { + err = { + status: error.status, + error : error.statusText + }; } - ); - }, // findById() - - - /** find users */ - find: function(options) { - var opts = options || {}; - var query = ""; - angular.forEach({ - "fields": opts.fields || "id,handle,email,active,status,credential,firstName,lastName,createdAt,modifiedAt", - "filter": opts.filter - //"limit" : null, - //"offset": null, - //"orderBy": null, - }, function(value, key) { - query += ('&' + key + '=' + encodeURIComponent(value)); - }); + return $q.reject(err); + } + ); + }; // findById() - var request = $http({ - method: 'GET', - url: API_URL + '/v3/users?' + query, - headers: { - "Content-Type":"application/json" - } - }); - return request.then( - function(response) { - $log.debug(response); - return response.data.result.content; - }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); + /** find users */ + UserService.find = function(options) { + var opts = options || {}; + var query = ""; + angular.forEach({ + "fields": opts.fields || "id,handle,email,active,status,credential,firstName,lastName,createdAt,modifiedAt", + "filter": opts.filter + //"limit" : null, + //"offset": null, + //"orderBy": null, + }, function(value, key) { + query += ('&' + key + '=' + encodeURIComponent(value)); + }); + + var request = $http({ + method: 'GET', + url: API_URL + '/v3/users?' + query, + headers: { + "Content-Type":"application/json" + } + }); + + return request.then( + function(response) { + $log.debug(response); + return UserService.createUser(response.data.result.content); + }, + function(error) { + $log.error(error); + var err; + if(error && error.data && error.data.result) { + err = { + status: error.status, + error : error.data.result.content + }; } - ); - }, // find() - - activate: function(activationCode) { - - var request = $http({ - method: 'PUT', - url: API_URL + '/v3/users/activate?code=' + activationCode, - headers: { - "Content-Type":"application/json" - }, - data: {} - }); + if(!err) { + err = { + status: error.status, + error : error.statusText + }; + } + return $q.reject(err); + } + ); + }; // find() + + /** + * activates user + */ + UserService.activate = function(activationCode) { + + var request = $http({ + method: 'PUT', + url: API_URL + '/v3/users/activate?code=' + activationCode, + headers: { + "Content-Type":"application/json" + }, + data: {} + }); - return request.then( - function(response) { - $log.debug(response); - return response.data.result.content; - }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); + return request.then( + function(response) { + $log.debug(response); + return UserService.createUser(response.data.result.content); + }, + function(error) { + $log.error(error); + var err; + if(error && error.data && error.data.result) { + err = { + status: error.status, + error : error.data.result.content + }; } - ); - }, // activate() - - updateHandle: function(userId, handle) { - var payload = JSON.stringify({ param: { handle: handle } }); - var request = $http({ - method: 'PATCH', - url: API_URL + '/v3/users/'+userId+'/handle', - headers: { - "Content-Type":"application/json" - }, - data: payload - }); + if(!err) { + err = { + status: error.status, + error : error.statusText + }; + } + return $q.reject(err); + } + ); + }; // activate() + + /** + * updates a user handle + */ + UserService.updateHandle = function(userId, handle) { + var payload = JSON.stringify({ param: { handle: handle } }); + var request = $http({ + method: 'PATCH', + url: API_URL + '/v3/users/'+userId+'/handle', + headers: { + "Content-Type":"application/json" + }, + data: payload + }); - return request.then( - function(response) { - $log.debug(response); - return response.data.result.content; - }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); + return request.then( + function(response) { + $log.debug(response); + return UserService.createUser(response.data.result.content); + }, + function(error) { + $log.error(error); + var err; + if(error && error.data && error.data.result) { + err = { + status: error.status, + error : error.data.result.content + }; } - ); - }, // updateHandle() - - updateEmail: function(userId, email) { - var payload = JSON.stringify({ param: { email: email } }); - var request = $http({ - method: 'PATCH', - url: API_URL + '/v3/users/'+userId+'/email', - headers: { - "Content-Type":"application/json" - }, - data: payload - }); + if(!err) { + err = { + status: error.status, + error : error.statusText + }; + } + return $q.reject(err); + } + ); + }; // updateHandle() + + UserService.updateEmail = function(userId, email) { + var payload = JSON.stringify({ param: { email: email } }); + var request = $http({ + method: 'PATCH', + url: API_URL + '/v3/users/'+userId+'/email', + headers: { + "Content-Type":"application/json" + }, + data: payload + }); - return request.then( - function(response) { - $log.debug(response); - return response.data.result.content; - }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); + return request.then( + function(response) { + $log.debug(response); + return UserService.createUser(response.data.result.content); + }, + function(error) { + $log.error(error); + var err; + if(error && error.data && error.data.result) { + err = { + status: error.status, + error : error.data.result.content + }; } - ); - }, // updateEmail() - - updateStatus: function(userId, status, comment) { - - var payload = JSON.stringify({ param: { status: status } }), - param = comment ? '?comment=' + encodeURIComponent(comment) : '', - request = $http({ - method: 'PATCH', - url: API_URL + '/v3/users/'+userId+'/status'+param, - headers: { - "Content-Type":"application/json" - }, - data: payload - }); + if(!err) { + err = { + status: error.status, + error : error.statusText + }; + } + return $q.reject(err); + } + ); + }, // updateEmail() + + /** + * updates a user status + */ + UserService.updateStatus = function(userId, status, comment) { + + var payload = JSON.stringify({ param: { status: status } }), + param = comment ? '?comment=' + encodeURIComponent(comment) : '', + request = $http({ + method: 'PATCH', + url: API_URL + '/v3/users/'+userId+'/status'+param, + headers: { + "Content-Type":"application/json" + }, + data: payload + }); - return request.then( - function(response) { - $log.debug(response); - return response.data.result.content; - }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); + return request.then( + function(response) { + $log.debug(response); + return UserService.createUser(response.data.result.content); + }, + function(error) { + $log.error(error); + var err; + if(error && error.data && error.data.result) { + err = { + status: error.status, + error : error.data.result.content + }; } - ); - } // updateStatus() - }); + if(!err) { + err = { + status: error.status, + error : error.statusText + }; + } + return $q.reject(err); + } + ); + }; // updateStatus() + + /** + * Instantiate a user object(s) + */ + UserService.createUser = function(data) { + if(angular.isArray(data)) { + var result = []; + angular.forEach(data, function(elem){ + result.push(angular.extend(new User(), elem)); + }); + return result; + } else { + return angular.extend(new User(), data); + } + }; + + return UserService; }]);