Add form validation and toast messages to user mgmt
Adds form field validation with ng-messages and toast messages
with toast service to the User management page. Also adds check
that the number of users does not exceed 15 and that the username
does not already exist prior to sending call to the backend.
Resolves openbmc/phosphor-webui#73
Resolves openbmc/phosphor-webui#74
Tested: Able to add/delete/edit users as before. Page presents
appropriate message to user upon creating or updating a user
when:
1. A field is missing
2. Passwords don't match
3. Password is longer than max or shorter than min
4. Username already exists when creating new user
5. User tries to create the 16th user
Change-Id: I5ae1a7979f7a396b0fb2ea280b875afc805a7f9f
Signed-off-by: beccabroek <beccabroek@gmail.com>
diff --git a/app/users/controllers/user-accounts-controller.html b/app/users/controllers/user-accounts-controller.html
index b48626d..f5bdda0 100644
--- a/app/users/controllers/user-accounts-controller.html
+++ b/app/users/controllers/user-accounts-controller.html
@@ -19,18 +19,6 @@
<input type="number" id="lockoutThreshold" min="3" max="10" ng-model="properties.AccountLockoutThreshold"/>
</div>
</div>
- <div class= "col-sm-12">
- <label class="col-md-1 control-label"> Max Password Length </label>
- <div class="col-md-3 acnt-prop__span-wrapper">
- <span>{{properties.MaxPasswordLength}}</span>
- </div>
- </div>
- <div class="col-sm-12">
- <label class="col-md-1 control-label"> Min Password Length </label>
- <div class="col-md-3 acnt-prop__span-wrapper">
- <span>{{properties.MinPasswordLength}}</span>
- </div>
- </div>
<div class="acnt-prop__submit-wrapper">
<button type="button" class="btn-primary inline" ng-click="saveAllValues()">Save settings</button>
</div>
@@ -67,43 +55,59 @@
<span>No users exist in system</span>
</div>
- <form role="form" class="user-manage__form">
- <section class="row column" aria-label="user manage form">
+ <form role="form" name="user__form" class="user-manage__form">
+ <section class="row column" aria-label="user manage form" ng-class="{'submitted':submitted}">
<div class="column small-12 page-header">
<h2 class="inline">User account settings</h2>
</div>
<div class='col-sm-12'>
<label class="col-md-1 control-label" for="user-manage__username">UserName</label>
<div class="col-md-3">
- <input type="text" name="UserName" id="user-manage__username" ng-model="selectedUser.UserName" />
+ <input type="text" name="UserName" id="user-manage__username" ng-model="selectedUser.UserName" has-error="doesUserExist()" required />
+ <div ng-messages="user__form.UserName.$error" class="form-error" ng-class="{'visible' : user__form.UserName.$touched || submitted}">
+ <p ng-message="required">Field is required</p>
+ <p ng-message="hasError">Username exists</p>
+ </div>
</div>
</div>
<div class='col-sm-12 inline'>
<label class="col-md-1 control-label" for="user-manage__passwd">Password</label>
<div class="col-md-3 user-manage__input-wrapper inline">
- <input type="{{showpassword ? 'text' : 'password'}}" class="user-manage__new-password inline" name="Password" id="user-manage__passwd" ng-model="selectedUser.Password" autocomplete="off"/>
+ <input type="{{showpassword ? 'text' : 'password'}}" class="user-manage__new-password inline" name="Password" id="user-manage__passwd" ng-model="selectedUser.Password" ng-minlength="properties.MinPasswordLength" ng-maxlength="properties.MaxPasswordLength" required autocomplete="off"/>
<button ng-model="showpassword" ng-click="togglePassword = !togglePassword; showpassword = !showpassword;" class="password-toggle">
<span ng-hide="togglePassword">Show</span>
<span ng-show="togglePassword">Hide</span>
</button>
+ <div ng-messages="user__form.Password.$error" class="form-error" ng-class="{'visible' : user__form.Password.$touched || submitted}">
+ <p ng-message="required">Field is required</p>
+ <p ng-message="minlength">Must be at least {{properties.MinPasswordLength}} characters</p>
+ <p ng-message="maxlength">Must be {{properties.MaxPasswordLength}} characters or less</p>
+ </div>
</div>
</div>
<div class='col-sm-12'>
<label class="col-md-1 control-label" for="user-manage__verifypasswd">Retype Password</label>
<div class="col-md-3 user-manage__input-wrapper inline">
- <input type="{{showpasswordVerify ? 'text' : 'password'}}" class="user-manage__verify-password inline" name="VerifyPassword" id="user-manage__verifypasswd" ng-model="selectedUser.VerifyPassword" autocomplete="off">
+ <input type="{{showpasswordVerify ? 'text' : 'password'}}" class="user-manage__verify-password inline" name="VerifyPassword" id="user-manage__verifypasswd" ng-model="selectedUser.VerifyPassword" has-error="selectedUser.VerifyPassword != selectedUser.Password" required autocomplete="off">
<button ng-model="showpasswordVerify" ng-click="toggleVerify = !toggleVerify; showpasswordVerify = !showpasswordVerify;" class="password-toggle">
<span ng-hide="toggleVerify">Show</span>
<span ng-show="toggleVerify">Hide</span>
</button>
+ <div ng-messages="user__form.VerifyPassword.$error" class="form-error" ng-class="{'visible' : user__form.VerifyPassword.$touched || submitted}">
+ <p ng-message="required">Field is required</p>
+ <p ng-message="hasError">Passwords do not match</p>
+ </div>
</div>
</div>
<div class='col-sm-12'>
- <label class="col-md-1 control-label" for="user-manage__role">Role</label>
+ <label class="col-md-1 control-label" for="role">Role</label>
<div class="col-md-3 user-manage__input-wrapper inline">
- <select ng-model="selectedUser.RoleId" id="user-manage__role" class="inline">
+ <select ng-model="selectedUser.RoleId" id="role" name="role" class="inline" required>
<option ng-repeat="role in roles" class="inline">{{role}}</option>
</select>
+ <div ng-messages="user__form.role.$error" class="form-error" ng-class="{'visible' : user__form.role.$touched || submitted}">
+ <p ng-message="required">Field is required</p>
+ </div>
</div>
</div>
<div class='col-sm-12'>
@@ -116,17 +120,10 @@
</div>
</div>
<div class="user-manage__submit-wrapper">
- <button type="button" class="btn-primary inline" ng-if="!isUserSelected" ng-click="createNewUser()">Create User</button>
- <button type="button" class="btn-primary inline" ng-if="isUserSelected" ng-click="updateUserInfo()">Save</button>
+ <button type="button" ng-click="submitted=true; user__form.$valid && createNewUser(); user__form.$setUntouched()" ng-show="!isUserSelected" class="btn-primary inline">Create user</button>
+ <button type="button" class="btn-primary inline" ng-click="submitted=true; user__form.$valid && updateUserInfo(); user__form.$setUntouched()" ng-show="isUserSelected">Save</button>
<button type="button" class="btn-primary inline" ng-if="isUserSelected" ng-click="cancel()">Cancel</button>
</div>
</section>
- <section class="row column">
- <div class='col-sm-12'>
- <p ng-class="'user-manage__' + state" role="alert">
- {{outMsg}}
- </p>
- </div>
- </section>
</form>
</div>