angular/projects/researchdatabox/manage-users/src/app/manage-users.component.ts
selector | manage-users |
templateUrl | ./manage-users.component.html |
constructor(loggerService: LoggerService, translationService: TranslationService, userService: UserService, _fb: FormBuilder)
|
|||||||||||||||
Parameters :
|
editUser | ||||||
editUser(username: string)
|
||||||
Parameters :
Returns :
void
|
genKey | ||||||
genKey(userid: string)
|
||||||
Parameters :
Returns :
void
|
getNewUserFormControls |
getNewUserFormControls()
|
Returns :
{}
|
getNewUserPasswordErrors |
getNewUserPasswordErrors()
|
Returns :
{}
|
getNewUserPasswordFormControls |
getNewUserPasswordFormControls()
|
Returns :
any
|
getUpdateUserFormControls |
getUpdateUserFormControls()
|
Returns :
{}
|
getUpdateUserPasswordErrors |
getUpdateUserPasswordErrors()
|
Returns :
{}
|
hideDetailsModal |
hideDetailsModal()
|
Returns :
void
|
hideNewUserModal |
hideNewUserModal()
|
Returns :
void
|
Protected Async initComponent |
initComponent()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:59
|
Returns :
Promise<void>
|
isUpdateUserFormConfirmPasswordTouched |
isUpdateUserFormConfirmPasswordTouched()
|
Returns :
boolean
|
mapRoles | ||||||
mapRoles(roles: any)
|
||||||
Parameters :
Returns :
any
|
newUser |
newUser()
|
Returns :
void
|
Async newUserSubmit |
newUserSubmit(user: UserForm, isValid: boolean)
|
Returns :
any
|
onDetailsModalHidden |
onDetailsModalHidden()
|
Returns :
void
|
onFilterChange |
onFilterChange()
|
Returns :
void
|
onNewUserHidden |
onNewUserHidden()
|
Returns :
void
|
Async refreshUsers |
refreshUsers()
|
Returns :
any
|
resetFilter |
resetFilter()
|
Returns :
void
|
revokeKey | ||||||
revokeKey(userid: string)
|
||||||
Parameters :
Returns :
void
|
setNewUserMessage |
setNewUserMessage(msg: any, type: string)
|
Returns :
void
|
setUpdateMessage |
setUpdateMessage(msg: any, type: string)
|
Returns :
void
|
setupForms | ||||||
setupForms(newUser: boolean)
|
||||||
Parameters :
Returns :
void
|
showDetailsModal |
showDetailsModal()
|
Returns :
void
|
showNewUserModal |
showNewUserModal()
|
Returns :
void
|
Async updateUserSubmit |
updateUserSubmit(user: UserForm, isValid: boolean)
|
Returns :
any
|
getInitSubject |
getInitSubject()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:71
|
For those interested in the init from RXJS-land. Note that it returns a BehaviorSubject instance, and will have an initial value of false, so process the return value as needed.
Returns :
Subject<any>
|
isInitializing |
isInitializing()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:95
|
Main flag to indicate the init status
Returns :
boolean
|
ngOnInit |
ngOnInit()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:50
|
Returns :
void
|
Async waitForDeps |
waitForDeps()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:78
|
Wait for dependencies to initialise
Returns :
Promise<any>
|
Async waitForInit |
waitForInit()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:89
|
For those interested in the init from the Promise-land
Returns :
Promise<any>
|
allRoles |
Type : Role[]
|
Default value : []
|
allUsers |
Type : User[]
|
Default value : []
|
currentUser |
Type : User
|
Default value : null as any
|
filteredUsers |
Type : any[]
|
Default value : []
|
hiddenUsers |
Type : any
|
Default value : ['']
|
isDetailsModalShown |
Type : boolean
|
Default value : false
|
isNewUserModalShown |
Type : boolean
|
Default value : false
|
newUserForm |
Type : FormGroup
|
Default value : null as any
|
newUserMsg |
Type : string
|
Default value : ''
|
newUserMsgType |
Type : string
|
Default value : 'info'
|
searchFilter |
Type : literal type
|
Default value : {
name: '',
prevName: '',
users: [ {value: null, label:'Any', checked:true}]
}
|
showToken |
Type : boolean
|
Default value : false
|
submitted |
Type : boolean
|
Default value : false
|
title |
Type : string
|
Default value : '@researchdatabox/manage-users'
|
updateDetailsMsg |
Type : string
|
Default value : ''
|
updateDetailsMsgType |
Type : string
|
Default value : 'info'
|
updateUserForm |
Type : FormGroup
|
Default value : null as any
|
Optional userDetailsModal |
Type : ModalDirective
|
Decorators :
@ViewChild('userDetailsModal', {static: false})
|
Optional userNewModal |
Type : ModalDirective
|
Decorators :
@ViewChild('userNewModal', {static: false})
|
Protected brandingAndPortalUrl |
Type : string
|
Default value : ''
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:42
|
Private filterFn |
Default value : function(initStat: boolean) { return initStat; }
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:40
|
Protected initDependencies |
Type : Initable[]
|
Default value : []
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:39
|
Protected initSubject |
Type : BehaviorSubject<any>
|
Default value : new BehaviorSubject(false)
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:38
|
Protected isReady |
Type : boolean
|
Default value : false
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:37
|
import { Component, Inject, ViewChild } from '@angular/core';
import { ModalDirective } from 'ngx-bootstrap/modal';
import { FormArray, FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { Role, User, UserLoginResult, SaveResult } from '@researchdatabox/portal-ng-common';
import { BaseComponent, LoggerService, TranslationService, UserService} from '@researchdatabox/portal-ng-common';
import { UserForm, matchingValuesValidator, optionalEmailValidator, passwordStrengthValidator } from './forms';
import * as _ from 'lodash';
@Component({
selector: 'manage-users',
templateUrl: './manage-users.component.html'
})
export class ManageUsersComponent extends BaseComponent {
title = '@researchdatabox/manage-users';
allUsers: User[] = [];
filteredUsers: any[] = [];
allRoles: Role[] = [];
searchFilter: { name: string,
prevName: string,
users: any[]
} = {
name: '',
prevName: '',
users: [ {value: null, label:'Any', checked:true}]
};
hiddenUsers: any = [''];
currentUser: User = null as any;
updateDetailsMsg: string = '';
updateDetailsMsgType: string = 'info';
newUserMsg: string = '';
newUserMsgType: string = 'info';
@ViewChild('userDetailsModal', { static: false }) userDetailsModal?: ModalDirective;
@ViewChild('userNewModal', { static: false }) userNewModal?: ModalDirective;
isDetailsModalShown: boolean = false;
isNewUserModalShown: boolean = false;
updateUserForm: FormGroup = null as any;;
newUserForm: FormGroup = null as any;;
submitted: boolean = false;
showToken: boolean = false;
constructor(
@Inject(LoggerService) private loggerService: LoggerService,
@Inject(TranslationService) private translationService: TranslationService,
@Inject(UserService) private userService: UserService,
@Inject(FormBuilder) private _fb: FormBuilder
) {
super();
this.loggerService.debug(`Manage Users waiting for deps to init...`);
this.initDependencies = [this.translationService, this.userService];
}
protected override async initComponent():Promise<void> {
let roles: any = await this.userService.getBrandRoles();
for(let role of roles) {
this.allRoles.push(role);
}
await this.refreshUsers();
}
setupForms(newUser: boolean) {
this.submitted = false;
if(newUser) {
let newRolesControlArray = new FormArray(this.allRoles.map((role) => {
return new FormGroup({
key: new FormControl(role.id),
value: new FormControl(role.name),
checked: new FormControl(false),
});
}));
const pwGroup_new = this._fb.group(
{
password: [''],
confirmPassword: ['']
}
);
pwGroup_new.setValidators([matchingValuesValidator('password', 'confirmPassword'), passwordStrengthValidator('confirmPassword')]);
this.newUserForm = this._fb.group({
username: ['', Validators.required],
name: ['', Validators.required],
email: ['', optionalEmailValidator],
passwords: pwGroup_new,
allRoles: newRolesControlArray,
roles: [this.mapRoles(newRolesControlArray.value), Validators.required]
});
newRolesControlArray.valueChanges.subscribe((v) => {
this.newUserForm.controls['roles'].setValue(this.mapRoles(v));
});
} else {
let updateRolesControlArray = new FormArray(this.allRoles.map((role) => {
return new FormGroup({
key: new FormControl(role.id),
value: new FormControl(role.name),
checked: new FormControl(_.includes(_.flatMap(this.currentUser.roles, role => { return role['name']; }), role.name)),
});
}));
const pwGroup_update = this._fb.group(
{
password: [''],
confirmPassword: ['']
}
);
pwGroup_update.setValidators([matchingValuesValidator('password', 'confirmPassword'), passwordStrengthValidator('confirmPassword')]);
this.updateUserForm = this._fb.group({
userid: this.currentUser.id,
username: this.currentUser.username,
name: [this.currentUser.name, Validators.required],
email: [this.currentUser.email, optionalEmailValidator],
passwords: pwGroup_update,
allRoles: updateRolesControlArray,
roles: [this.mapRoles(updateRolesControlArray.value), Validators.required]
});
updateRolesControlArray.valueChanges.subscribe((v) => {
this.updateUserForm.controls['roles'].setValue(this.mapRoles(v));
});
}
}
mapRoles(roles: any) {
let selectedRoles = roles.filter((role: any) => role.checked).map((r: any) => {
let ret: Role = {
id: '',
name: '',
users: [],
hasRole: true
};
ret.id = r.key;
ret.name = r.value;
return ret;
});
return selectedRoles.length ? selectedRoles : null;
}
async refreshUsers() {
let users: any = await this.userService.getUsers();
for(let user of users) {
this.allUsers.push(user);
}
_.forEach(this.searchFilter.users, (user:any) => {
this.searchFilter.users.pop();
});
this.filteredUsers = [];
_.forEach(users, (user:any) => {
this.searchFilter.users.push({value:user.name, label:user.name, checked:false});
if (!_.includes(this.hiddenUsers, user.username)) {
this.filteredUsers.push(user);
}
});
_.map(this.filteredUsers, (user:any)=> {user.roleStr = _.join(_.map(user.roles, 'name'), ', ')});
}
editUser(username: string) {
this.showToken = false;
this.setUpdateMessage();
let user = _.find(this.allUsers, (user:any)=>{return user.username == username});
if(!_.isUndefined(user)) {
this.currentUser = user;
}
this.setupForms(false);
this.showDetailsModal();
}
newUser() {
this.setNewUserMessage();
this.setupForms(true);
this.showNewUserModal();
}
showDetailsModal(): void {
this.isDetailsModalShown = true;
this.userDetailsModal?.show();
}
hideDetailsModal(): void {
if(!_.isUndefined(this.userDetailsModal)) {
this.userDetailsModal.hide();
}
}
onDetailsModalHidden(): void {
this.isDetailsModalShown = false;
}
showNewUserModal(): void {
this.isNewUserModalShown = true;
}
hideNewUserModal(): void {
if(!_.isUndefined(this.userNewModal)) {
this.userNewModal.hide();
}
}
onNewUserHidden(): void {
this.isNewUserModalShown = false;
}
genKey(userid: string) {
this.setUpdateMessage('Generating...', 'primary');
this.userService.genKey(userid).then((saveRes:any) => { //SaveResult
if (saveRes.status) {
this.showToken = true;
this.currentUser.token = saveRes.message;
this.refreshUsers();
this.setUpdateMessage('Token generated.', 'primary');
} else {
this.setUpdateMessage(saveRes.message, 'danger');
}
});
}
revokeKey(userid: string) {
this.setUpdateMessage('Revoking...', 'primary');
this.userService.revokeKey(userid).then((saveRes:any) => { //SaveResult
if (saveRes.status) {
this.currentUser.token = '';
this.refreshUsers();
this.setUpdateMessage('Token revoked.', 'primary');
} else {
this.setUpdateMessage(saveRes.message, 'danger');
}
});
}
async updateUserSubmit(user: UserForm, isValid: boolean) {
this.submitted = true;
if (!isValid){
this.setUpdateMessage(this.translationService.t('manage-users-validation-submit'), 'danger');
return;
}
let details: { name: string, email: string, password: string, roles: any[] } =
{ name: user.name, email: user.email, password: user.passwords.password, roles: [] };
_.forEach(user.roles, (role:any) => {
details.roles.push(role.name);
});
this.setUpdateMessage('Saving...', 'primary');
let saveRes:any = await this.userService.updateUserDetails(user.userid, details); //SaveResult
if (saveRes.status) {
this.hideDetailsModal();
this.refreshUsers();
this.setUpdateMessage();
} else {
this.setUpdateMessage(saveRes.message, 'danger');
}
}
async newUserSubmit(user: UserForm, isValid: boolean) {
this.submitted = true;
if (!isValid){
this.setNewUserMessage(this.translationService.t('manage-users-validation-submit'), 'danger');
return;
}
let details: { name: string, email: string, password: string, roles: any[] } =
{ name: user.name, email: user.email, password: user.passwords.password, roles: [] };
_.forEach(user.roles, (role:any) => {
details.roles.push(role.name);
});
this.setNewUserMessage('Saving...', 'primary');
let saveRes:any = await this.userService.addLocalUser(user.username, details); //SaveResult
if (saveRes.status) {
this.hideNewUserModal();
this.refreshUsers();
this.setNewUserMessage();
} else {
this.setNewUserMessage(saveRes.message, 'danger');
}
}
setUpdateMessage(msg:any=undefined, type:string='primary') {
this.updateDetailsMsg = msg;
this.updateDetailsMsgType = type;
}
setNewUserMessage(msg:any=undefined, type:string='primary') {
this.newUserMsg = msg;
this.newUserMsgType = type;
}
onFilterChange() {
if (this.searchFilter.name != this.searchFilter.prevName) {
this.searchFilter.prevName = this.searchFilter.name;
var nameFilter =_.isEmpty(this.searchFilter.name) ? '' : _.trim(this.searchFilter.name);
this.filteredUsers = _.filter(this.allUsers, (user:any) => {
var hasNameMatch = nameFilter == '' ? true : (_.toLower(user.name).indexOf(_.toLower(this.searchFilter.name)) >= 0);
return hasNameMatch;
});
}
}
resetFilter() {
this.searchFilter.name = '';
_.map(this.searchFilter.users, (user:any)=> user.checked = user.value == null);
this.onFilterChange();
}
isUpdateUserFormConfirmPasswordTouched() {
let passControls = (this.updateUserForm.controls['passwords'] as FormGroup).controls;
if(passControls['confirmPassword'] && passControls['confirmPassword'].touched) {
return true;
}
return false;
}
getUpdateUserPasswordErrors() {
let errors = this.updateUserForm.controls['passwords'].errors;
let errorMessages = [];
if(errors) {
for(let errorMsg of errors['passwordStrengthDetails'].errors) {
errorMessages.push(errorMsg);
}
}
return errorMessages;
}
getNewUserPasswordErrors() {
let errors = this.newUserForm.controls['passwords'].errors;
let errorMessages = [];
if(errors) {
for(let errorMsg of errors['passwordStrengthDetails'].errors) {
errorMessages.push(errorMsg);
}
}
return errorMessages;
}
getNewUserPasswordFormControls() {
return (this.newUserForm.controls['passwords'] as FormGroup).controls;
}
getUpdateUserFormControls() {
return (this.updateUserForm.get('allRoles') as FormArray).controls as FormGroup[];
}
getNewUserFormControls() {
return (this.newUserForm.get('allRoles') as FormArray).controls as FormGroup[];
}
}
<div class="col-md-offset-2 col-md-8" *ngIf="isReady">
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel-title">
{{ 'manage-users-title' | i18next }}
</span>
</div>
<div class="panel-body" style="overflow:scroll">
<div class="row">
<div class="col-sm-9">
<div class="input-group">
<span class="input-group-addon" id="name-addon">{{ 'manage-users-filter-name' | i18next }}</span>
<input type="text" (keyup)="onFilterChange()" [(ngModel)]="searchFilter.name" class="form-control" placeholder="{{ 'manage-users-filter-name-placeholder' | i18next }}" [attr.aria-label]="'manage-users-filter-name' | i18next">
<span (click)="resetFilter()" class="input-group-btn"><button class="btn btn-primary" type='button'>Reset</button></span>
</div>
</div>
<div class="col-sm-3">
<span (click)="newUser()"><button class="btn btn-primary" type='button'>{{ 'manage-users-add-local' | i18next }}</button></span>
</div>
</div>
<div>
<br/>
</div>
<div>
<br/>
</div>
<div class="table-responsive">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>{{ 'manage-users-name' | i18next }}</th>
<th>{{ 'manage-users-email' | i18next }}</th>
<th>{{ 'manage-users-role' | i18next }}</th>
<th>{{ 'manage-users-api' | i18next }}</th>
<th>{{ 'manage-users-action' | i18next }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of filteredUsers">
<td>{{user.name}}</td>
<td>{{user.email}}</td>
<td>{{user.roleStr}}</td>
<td align="center">
<i class="fa fa-check" aria-hidden="true" *ngIf="user.token"></i>
</td>
<td>
<a style="cursor:pointer" (click)="editUser(user.username)">Edit</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- User Details Modal -->
<div *ngIf="isDetailsModalShown" [config]="{backdrop: 'static', show: true}" (onHidden)="onDetailsModalHidden()" bsModal #userDetailsModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="detailsform" >
<div class="modal-dialog modal-md">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">{{ 'manage-users-edit' | i18next }}</h4>
</div>
<div class="modal-body">
<form id="detailsform" [formGroup]="updateUserForm" novalidate (ngSubmit)="updateUserSubmit(updateUserForm.value, updateUserForm.valid)">
<div class="table-responsive">
<table class="table">
<tbody>
<tr *ngIf="currentUser.type == 'local'">
<td>{{ 'manage-users-username' | i18next }}</td>
<td>{{ currentUser.username }}</td>
</tr>
<tr>
<td>{{ 'manage-users-name' | i18next }}</td>
<td *ngIf="currentUser.type == 'local'">
<input type="text" formControlName="name" class="form-control input-sm chat-input"/>
<div class='form-text error text-danger' *ngIf="updateUserForm.controls['name'].touched || submitted">
<div *ngIf="updateUserForm.controls['name'].hasError('required')">{{ 'manage-users-validation-name' | i18next }}</div>
</div>
</td>
<td *ngIf="currentUser.type != 'local'">{{currentUser.name}}</td>
</tr>
<tr>
<td>{{ 'manage-users-email' | i18next }}</td>
<td *ngIf="currentUser.type == 'local'">
<input type="email" formControlName="email" class="form-control input-sm chat-input"/>
<div class='form-text error text-danger' *ngIf="updateUserForm.controls['email'].touched || submitted">
<div *ngIf="updateUserForm.controls['email'].hasError('invalidEmail')">{{ 'manage-users-validation-email' | i18next }}</div>
</div>
</td>
<td *ngIf="currentUser.type != 'local'">{{currentUser.email}}</td>
</tr>
<tr>
<td>{{ 'manage-users-password' | i18next }}</td>
<td *ngIf="currentUser.type == 'local'">
<div formGroupName="passwords">
<input type="password" formControlName="password" class="form-control input-sm chat-input" placeholder="{{ 'manage-users-update-password' | i18next }}"/>
</div>
</td>
<td *ngIf="currentUser.type != 'local'">{{ 'manage-users-aaf-password' | i18next}}</td>
</tr>
<tr *ngIf="currentUser.type == 'local'">
<td>{{ 'manage-users-confirm-password' | i18next }}</td>
<td>
<div formGroupName="passwords">
<input type="password" formControlName="confirmPassword" class="form-control input-sm chat-input" placeholder="Confirm Password"/>
</div>
<div class='form-text error text-danger' *ngIf="isUpdateUserFormConfirmPasswordTouched() || submitted">
<div *ngIf="updateUserForm.controls['passwords'].hasError('mismatched')">{{ 'manage-users-validation-confirmpassword' | i18next }}</div>
<ng-container *ngIf="updateUserForm.controls['passwords'].hasError('passwordStrength')" >
<div *ngFor="let errorMsg of getUpdateUserPasswordErrors()" >
{{ errorMsg | i18next }}
</div>
</ng-container>
</div>
</td>
</tr>
<tr>
<td>{{ 'manage-users-api' | i18next }}</td>
<td *ngIf="!currentUser.token">
<button type="button" class="btn btn-primary" (click)="genKey(currentUser.id)">{{ 'manage-users-api-generate' | i18next }}</button>
</td>
<td *ngIf="currentUser.token">
<ng-container *ngIf="showToken">
<p>{{ 'manage-users-token-message' | i18next }}</p>
<p><strong>{{ currentUser.token }}</strong></p>
</ng-container>
<button type="button" class="btn btn-primary" (click)="revokeKey(currentUser.id)">{{ 'manage-users-api-revoke' | i18next }}</button>
</td>
</tr>
<tr>
<td class="col-md-2">{{ 'manage-roles-role' | i18next }}</td>
<td class="col-md-8">
<div [formArrayName]="'allRoles'">
<div *ngFor="let role of getUpdateUserFormControls(); let i = index;" [formGroup]="role">
<input type="checkbox" formControlName="checked" id="role_{{ role.controls['key'].value }}">
<label attr.for="role_{{ role.controls['key'].value }}">{{ role.controls['value'].value }}</label>
</div>
<div class='form-text error text-danger' *ngIf="!updateUserForm.controls['roles'].valid">
<div>{{ 'manage-users-validation-role' | i18next }}</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</form>
<div class="bg-{{updateDetailsMsgType}} center-block">{{updateDetailsMsg}}</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" form="detailsform" type="submit">{{ 'manage-users-save' | i18next }}</button>
<button type="button" class="btn btn-default" (click)="hideDetailsModal()">{{ 'manage-users-cancel' | i18next }}</button>
</div>
</div>
</div>
</div>
<!-- New User Modal -->
<div *ngIf="isNewUserModalShown" [config]="{ show: true }" (onHidden)="onNewUserHidden()" bsModal #userNewModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<span class="modal-title h4-header">{{ 'manage-users-new' | i18next }}</span>
</div>
<div class="modal-body">
<form id="newform" [formGroup]="newUserForm" novalidate (ngSubmit)="newUserSubmit(newUserForm.value, newUserForm.valid)">
<div class="table-responsive">
<table class="table">
<tbody>
<tr>
<td>{{ 'manage-users-username' | i18next }}</td>
<td>
<input type="text" formControlName="username" class="form-control input-sm chat-input" placeholder="{{ 'manage-users-username' | i18next }}" [attr.aria-label]="'manage-users-username' | i18next"/>
<div class='form-text error text-danger' *ngIf="newUserForm.controls['username'].touched || submitted">
<div *ngIf="newUserForm.controls['username'].hasError('required')">{{ 'manage-users-validation-username' | i18next }}</div>
</div>
</td>
</tr>
<tr>
<td>{{ 'manage-users-name' | i18next }}</td>
<td>
<input type="text" formControlName="name" class="form-control input-sm chat-input" placeholder="{{ 'manage-users-name' | i18next }}" [attr.aria-label]="'manage-users-name' | i18next "/>
<div class='form-text error text-danger' *ngIf="newUserForm.controls['name'].touched || submitted">
<div *ngIf="newUserForm.controls['name'].hasError('required')">{{ 'manage-users-validation-name' | i18next }}</div>
</div>
</td>
</tr>
<tr>
<td>{{ 'manage-users-email' | i18next }}</td>
<td>
<input type="email" formControlName="email" class="form-control input-sm chat-input" placeholder="{{ 'manage-users-email' | i18next }}" [attr.aria-label]="'manage-users-email' | i18next"/>
<div class='form-text error text-danger' *ngIf="newUserForm.controls['email'].touched || submitted">
<div *ngIf="newUserForm.controls['email'].hasError('invalidEmail')">{{ 'manage-users-validation-email' | i18next }}</div>
</div>
</td>
</tr>
<tr>
<td>{{ 'manage-users-password' | i18next }}</td>
<td>
<div formGroupName="passwords">
<input type="password" formControlName="password" class="form-control input-sm chat-input" placeholder="{{ 'manage-users-password' | i18next }}" [attr.aria-label]="'manage-users-password' | i18next "/>
</div>
<div class='form-text error text-danger' *ngIf="getNewUserPasswordFormControls()['password'].touched || submitted">
<div *ngIf="getNewUserPasswordFormControls()['password'].hasError('required')">{{ 'manage-users-validation-password' | i18next }}</div>
</div>
</td>
</tr>
<tr>
<td>{{ 'manage-users-confirm-password' | i18next }}</td>
<td>
<div formGroupName="passwords">
<input type="password" formControlName="confirmPassword" class="form-control input-sm chat-input" placeholder="{{ 'manage-users-confirm-password' | i18next }}" [attr.aria-label]="'manage-users-confirm-password' | i18next"/>
</div>
<div class='form-text error text-danger' *ngIf="getNewUserPasswordFormControls()['confirmPassword'].touched || submitted">
<div *ngIf="newUserForm.controls['passwords'].hasError('mismatched')">{{ 'manage-users-validation-confirmpassword' | i18next }}</div>
<ng-container *ngIf="newUserForm.controls['passwords'].hasError('passwordStrength')" >
<div *ngFor="let errorMsg of getNewUserPasswordErrors()" >
{{ errorMsg | i18next }}
</div>
</ng-container>
</div>
</td>
</tr>
<tr>
<td class="col-md-2">{{ 'manage-roles-role' | i18next }}</td>
<td class="col-md-8">
<div [formArrayName]="'allRoles'">
<div *ngFor="let role of getNewUserFormControls(); let i = index;" [formGroup]="role">
<input type="checkbox" formControlName="checked" id="role_{{ role.controls['key'].value }}">
<label attr.for="role_{{ role.controls['key'].value }}">{{ role.controls['value'].value }}</label>
</div>
<div class='form-text error text-danger' *ngIf="!newUserForm.controls['roles'].valid">
<div>{{ 'manage-users-validation-role' | i18next }}</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</form>
<div class="bg-{{newUserMsgType}} center-block">{{ newUserMsg }}</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" form="newform" type="submit">{{ 'manage-users-save' | i18next }}</button>
<button type="button" class="btn btn-default" (click)="hideNewUserModal()">{{ 'manage-users-cancel' | i18next }}</button>
</div>
</div>
</div>
</div>