From 4148f2eee6313068d3223871005160b2902abb18 Mon Sep 17 00:00:00 2001 From: Yoshie Muranaka Date: Wed, 29 Jan 2020 13:21:12 -0800 Subject: Create profile settings page Adding a profile settings page so readonly and operator roles are able to change their own password. Signed-off-by: Yoshie Muranaka Change-Id: Iee9536255ad47f4df4af8746c1e01da37c407f2b --- app/assets/icons/icon-avatar.svg | 1 + app/common/directives/app-header.html | 11 +++- app/common/directives/app-header.js | 2 + app/common/styles/base/forms.scss | 1 + app/common/styles/directives/dropdown.scss | 5 ++ app/common/styles/directives/index.scss | 3 +- app/common/styles/layout/header.scss | 51 ++++++++------- app/index.js | 5 +- .../controllers/profile-settings-controller.html | 76 ++++++++++++++++++++++ .../controllers/profile-settings-controller.js | 75 +++++++++++++++++++++ app/profile-settings/index.js | 25 +++++++ 11 files changed, 229 insertions(+), 26 deletions(-) create mode 100644 app/assets/icons/icon-avatar.svg create mode 100644 app/common/styles/directives/dropdown.scss create mode 100644 app/profile-settings/controllers/profile-settings-controller.html create mode 100644 app/profile-settings/controllers/profile-settings-controller.js create mode 100644 app/profile-settings/index.js diff --git a/app/assets/icons/icon-avatar.svg b/app/assets/icons/icon-avatar.svg new file mode 100644 index 0000000..665af99 --- /dev/null +++ b/app/assets/icons/icon-avatar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/common/directives/app-header.html b/app/common/directives/app-header.html index bf4fb8f..ec03874 100644 --- a/app/common/directives/app-header.html +++ b/app/common/directives/app-header.html @@ -2,7 +2,16 @@
OpenBMC - Log out +
+ + +
diff --git a/app/common/directives/app-header.js b/app/common/directives/app-header.js index 98d210f..df39772 100644 --- a/app/common/directives/app-header.js +++ b/app/common/directives/app-header.js @@ -14,6 +14,7 @@ window.angular && (function(angular) { function( $rootScope, $scope, dataService, userModel, $location, $route) { $scope.dataService = dataService; + $scope.username = ''; try { // Create a secure websocket with URL as /subscribe @@ -118,6 +119,7 @@ window.angular && (function(angular) { $scope.loadNetworkInfo(); $scope.loadServerHealth(); $scope.loadSystemName(); + $scope.username = dataService.getUser(); } loadData(); diff --git a/app/common/styles/base/forms.scss b/app/common/styles/base/forms.scss index c775c48..6699d44 100644 --- a/app/common/styles/base/forms.scss +++ b/app/common/styles/base/forms.scss @@ -1,3 +1,4 @@ +.label, label, legend { margin: 0; diff --git a/app/common/styles/directives/dropdown.scss b/app/common/styles/directives/dropdown.scss new file mode 100644 index 0000000..0c0add0 --- /dev/null +++ b/app/common/styles/directives/dropdown.scss @@ -0,0 +1,5 @@ +.dropdown.open { + .dropdown-menu { + display: block; + } +} \ No newline at end of file diff --git a/app/common/styles/directives/index.scss b/app/common/styles/directives/index.scss index 5d9de6f..1fcbb65 100644 --- a/app/common/styles/directives/index.scss +++ b/app/common/styles/directives/index.scss @@ -1 +1,2 @@ -@import "./app-navigation.scss"; \ No newline at end of file +@import "./app-navigation.scss"; +@import "./dropdown.scss"; \ No newline at end of file diff --git a/app/common/styles/layout/header.scss b/app/common/styles/layout/header.scss index c034c82..b1665ca 100644 --- a/app/common/styles/layout/header.scss +++ b/app/common/styles/layout/header.scss @@ -21,37 +21,42 @@ $logoMaxWidth: 125px; z-index: 300; } -.header__title { - margin-left: 1em; - display: none; - float: left; - @include mediaQuery(x-small) { - display: inline-block; - position: absolute; - top: 50%; - transform: translateY(-50%); - } -} - .header__info-section { position: relative; background: $primary-dark; color: $primary-light; - overflow: hidden; -} - -.header__logout { - float: right; - color: $primary-light; - font-size: 0.9em; - text-decoration: none; - padding: 1em; - font-weight: 400; - &:visited { + width: 100%; + height: 50px; + display: flex; + justify-content: space-between; + .dropdown-menu { + left: unset; + right: 0; + border-radius: 0; + font-size: 0.9rem; + .btn { + color: $primary-dark; + } + } + .dropdown-toggle { color: $primary-light; + fill: $primary-light; + text-decoration: none; + font-weight: 400; + margin-right: 0.5rem; + height: 50px; //to vertically align in 50px header + &::after { + display: none; //hiding dropdown caret inserted by bootstrap + } } } +.header__title { + margin-left: 1rem; + display: block; + line-height: 50px; //to vertically align in 50px header +} + .header__functions-section { color: $primary-light; padding: 0 1.1em; diff --git a/app/index.js b/app/index.js index 57d031b..156fab6 100644 --- a/app/index.js +++ b/app/index.js @@ -78,6 +78,9 @@ import file_upload from './common/components/file-upload.js'; import login_index from './login/index.js'; import login_controller from './login/controllers/login-controller.js'; +import profile_settings_index from './profile-settings/index.js'; +import profile_settings_controller from './profile-settings/controllers/profile-settings-controller.js'; + import overview_index from './overview/index.js'; import system_overview_controller from './overview/controllers/system-overview-controller.js'; @@ -133,7 +136,7 @@ window.angular && (function(angular) { // Model resources 'app.login', 'app.overview', 'app.serverControl', 'app.serverHealth', 'app.configuration', 'app.accessControl', - 'app.redfish' + 'app.redfish', 'app.profileSettings' ]) // Route configuration .config([ diff --git a/app/profile-settings/controllers/profile-settings-controller.html b/app/profile-settings/controllers/profile-settings-controller.html new file mode 100644 index 0000000..365cf7f --- /dev/null +++ b/app/profile-settings/controllers/profile-settings-controller.html @@ -0,0 +1,76 @@ + +
+ +
+
+
+
+
+

Profile information

+
+
+
Username
+
{{username}}
+
+
+
+
+
+
+
+
+

Change password

+
+
+ +
+ +

Password must between {{minPasswordLength}} – {{maxPasswordLength}} characters

+ +
+ + Field is required + + Length must be between {{minPasswordLength}} – {{maxPasswordLength}} characters +
+
+ +
+ + +
+ + Field is required + + Passwords do not match +
+
+ +
+ +
+
+
+
+
\ No newline at end of file diff --git a/app/profile-settings/controllers/profile-settings-controller.js b/app/profile-settings/controllers/profile-settings-controller.js new file mode 100644 index 0000000..404e055 --- /dev/null +++ b/app/profile-settings/controllers/profile-settings-controller.js @@ -0,0 +1,75 @@ +/** + * Controller for the profile settings page + * + * @module app/profile-settings/controllers/index + * @exports ProfileSettingsController + * @name ProfileSettingsController + */ + +window.angular && (function(angular) { + 'use strict'; + + angular.module('app.profileSettings') + .controller('profileSettingsController', [ + '$scope', 'APIUtils', 'dataService', 'toastService', + function($scope, APIUtils, dataService, toastService) { + $scope.username; + $scope.minPasswordLength; + $scope.maxPasswordLength; + $scope.password; + $scope.passwordConfirm; + + /** + * Make API call to update user password + * @param {string} password + */ + const updatePassword = function(password) { + $scope.loading = true; + APIUtils.updateUser($scope.username, null, password) + .then( + () => toastService.success( + 'Password has been updated successfully.')) + .catch((error) => { + console.log(JSON.stringify(error)); + toastService.error('Unable to update password.') + }) + .finally(() => { + $scope.password = ''; + $scope.passwordConfirm = ''; + $scope.form.$setPristine(); + $scope.form.$setUntouched(); + $scope.loading = false; + }) + }; + + /** + * API call to get account settings for min/max + * password length requirement + */ + const getAllUserAccountProperties = function() { + APIUtils.getAllUserAccountProperties().then((accountSettings) => { + $scope.minPasswordLength = accountSettings.MinPasswordLength; + $scope.maxPasswordLength = accountSettings.MaxPasswordLength; + }) + }; + + /** + * Callback after form submitted + */ + $scope.onSubmit = function(form) { + if (form.$valid) { + const password = form.password.$viewValue; + updatePassword(password); + } + }; + + /** + * Callback after view loaded + */ + $scope.$on('$viewContentLoaded', () => { + getAllUserAccountProperties(); + $scope.username = dataService.getUser(); + }); + } + ]); +})(angular); diff --git a/app/profile-settings/index.js b/app/profile-settings/index.js new file mode 100644 index 0000000..77947a7 --- /dev/null +++ b/app/profile-settings/index.js @@ -0,0 +1,25 @@ +/** + * A module for the Profile Settings page + * + * @module app/profile-settings/index + * @exports app/profile-settings/index + */ + +window.angular && (function(angular) { + 'use strict'; + + angular + .module('app.profileSettings', ['ngRoute', 'app.common.services']) + // Route configuration + .config([ + '$routeProvider', + function($routeProvider) { + $routeProvider.when('/profile-settings', { + 'template': + require('./controllers/profile-settings-controller.html'), + 'controller': 'profileSettingsController', + authenticated: true + }) + } + ]); +})(window.angular); -- cgit v1.2.1