Strongest password policy
This commit is contained in:
committed by
Jose Alberto Hernandez
parent
9b17a6c4f8
commit
8fdf8fb10c
@@ -45,7 +45,7 @@ export class ChartOfAccountsComponent implements AfterViewInit, OnInit {
|
|||||||
/** Selected GL Account. */
|
/** Selected GL Account. */
|
||||||
glAccount: GLAccountNode;
|
glAccount: GLAccountNode;
|
||||||
/** Flag to check if tree is expanded or collapsed. */
|
/** Flag to check if tree is expanded or collapsed. */
|
||||||
isTreeExpanded: boolean = true;
|
isTreeExpanded = true;
|
||||||
|
|
||||||
/** Paginator for chart of accounts table. */
|
/** Paginator for chart of accounts table. */
|
||||||
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
||||||
@@ -182,9 +182,9 @@ export class ChartOfAccountsComponent implements AfterViewInit, OnInit {
|
|||||||
this.router.navigate(['/accounting']);
|
this.router.navigate(['/accounting']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expand and Collapse the tree
|
* Expand and Collapse the tree
|
||||||
*/
|
*/
|
||||||
toggleExpandCollapse() {
|
toggleExpandCollapse() {
|
||||||
this.isTreeExpanded = this.treeControlService.toggleExpandCollapse(this.nestedTreeControl, this.isTreeExpanded);
|
this.isTreeExpanded = this.treeControlService.toggleExpandCollapse(this.nestedTreeControl, this.isTreeExpanded);
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-15
@@ -12,7 +12,8 @@
|
|||||||
<mat-label> {{"labels.inputs.User Name" | translate}} </mat-label>
|
<mat-label> {{"labels.inputs.User Name" | translate}} </mat-label>
|
||||||
<input matInput required formControlName="username">
|
<input matInput required formControlName="username">
|
||||||
<mat-error *ngIf="createSelfServiceForm.controls.username.hasError('required')">
|
<mat-error *ngIf="createSelfServiceForm.controls.username.hasError('required')">
|
||||||
{{"labels.inputs.User Name" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
|
{{"labels.inputs.User Name" | translate}} {{"labels.commons.is" | translate}}
|
||||||
|
<strong>{{"labels.commons.required" | translate}}</strong>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
@@ -20,7 +21,8 @@
|
|||||||
<mat-label> {{"labels.inputs.First Name" | translate}} </mat-label>
|
<mat-label> {{"labels.inputs.First Name" | translate}} </mat-label>
|
||||||
<input matInput required formControlName="firstname">
|
<input matInput required formControlName="firstname">
|
||||||
<mat-error *ngIf="createSelfServiceForm.controls.firstname.hasError('required')">
|
<mat-error *ngIf="createSelfServiceForm.controls.firstname.hasError('required')">
|
||||||
{{"labels.inputs.First Name" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
|
{{"labels.inputs.First Name" | translate}} {{"labels.commons.is" | translate}}
|
||||||
|
<strong>{{"labels.commons.required" | translate}}</strong>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
@@ -28,7 +30,8 @@
|
|||||||
<mat-label> {{"labels.inputs.Last Name" | translate}} </mat-label>
|
<mat-label> {{"labels.inputs.Last Name" | translate}} </mat-label>
|
||||||
<input matInput required formControlName="lastname">
|
<input matInput required formControlName="lastname">
|
||||||
<mat-error *ngIf="createSelfServiceForm.controls.lastname.hasError('required')">
|
<mat-error *ngIf="createSelfServiceForm.controls.lastname.hasError('required')">
|
||||||
{{"labels.inputs.Last Name" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
|
{{"labels.inputs.Last Name" | translate}} {{"labels.commons.is" | translate}}
|
||||||
|
<strong>{{"labels.commons.required" | translate}}</strong>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
@@ -36,10 +39,12 @@
|
|||||||
<mat-label> {{"labels.inputs.Email" | translate}} </mat-label>
|
<mat-label> {{"labels.inputs.Email" | translate}} </mat-label>
|
||||||
<input matInput required formControlName="email">
|
<input matInput required formControlName="email">
|
||||||
<mat-error *ngIf="createSelfServiceForm.controls.email.hasError('required')">
|
<mat-error *ngIf="createSelfServiceForm.controls.email.hasError('required')">
|
||||||
{{"labels.inputs.Email" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
|
{{"labels.inputs.Email" | translate}} {{"labels.commons.is" | translate}}
|
||||||
|
<strong>{{"labels.commons.required" | translate}}</strong>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="createSelfServiceForm.controls.email.hasError('email')">
|
<mat-error *ngIf="createSelfServiceForm.controls.email.hasError('email')">
|
||||||
{{"labels.inputs.Email should be a" | translate}} <strong>{{"labels.inputs.valid" | translate}}</strong> {{"labels.inputs.email" | translate}}.
|
{{"labels.inputs.Email should be a" | translate}} <strong>{{"labels.inputs.valid" |
|
||||||
|
translate}}</strong> {{"labels.inputs.email" | translate}}.
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
@@ -53,15 +58,30 @@
|
|||||||
{{"labels.inputs.Override Password Expire Policy" | translate}} ?
|
{{"labels.inputs.Override Password Expire Policy" | translate}} ?
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
|
|
||||||
<i class="fa fa-question-circle fa fa-align-left" title="Determines if passwords do not expire for this user even if global configuration for password expiry is enabled"></i>
|
<i class="fa fa-question-circle fa fa-align-left"
|
||||||
|
title="Determines if passwords do not expire for this user even if global configuration for password expiry is enabled"></i>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-form-field fxFlex="48%" *ngIf="!hidePasswordField">
|
<mat-form-field fxFlex="48%" *ngIf="!hidePasswordField">
|
||||||
<mat-label> {{"labels.inputs.Password" | translate}} </mat-label>
|
<mat-label>{{ 'labels.inputs.Password' | translate }}</mat-label>
|
||||||
<input matInput required formControlName="password" type="password">
|
<input matInput formControlName="password" type="password">
|
||||||
<mat-error *ngIf="createSelfServiceForm.controls.password.hasError('required')">
|
<mat-error *ngIf="createSelfServiceForm.controls.password.hasError('required')">
|
||||||
{{"labels.inputs.Password" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
|
{{ 'labels.inputs.Password' | translate }} <strong>{{'labels.commons.is required' | translate }}</strong>
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="createSelfServiceForm.controls.password.hasError('minlength')">
|
||||||
|
{{'labels.commons.Password should be at least' | translate }} <strong>{{'labels.commons.8 characters long' | translate }}</strong>
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="createSelfServiceForm.controls.password.hasError('maxlength')">
|
||||||
|
{{'labels.commons.Password should not be more than' | translate }}
|
||||||
|
<strong>{{'labels.commons.50 characters long' | translate }}</strong>
|
||||||
|
</mat-error>
|
||||||
|
<mat-error
|
||||||
|
*ngIf="createSelfServiceForm.controls.password.hasError('pattern') && !(createSelfServiceForm.controls.password.hasError('minlength') || createSelfServiceForm.controls.password.hasError('maxlength'))">
|
||||||
|
{{'labels.commons.Password should include a' | translate }}
|
||||||
|
<strong>{{'labels.commons.numeral' | translate }}</strong> {{'labels.commons.and at' | translate }}
|
||||||
|
<strong>{{'labels.commons.least one uppercase' | translate }}</strong>
|
||||||
|
,<strong>{{'labels.commons.lowercase and special character' | translate }}</strong>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
@@ -69,10 +89,12 @@
|
|||||||
<mat-label> {{"labels.inputs.Repeat Password" | translate}} </mat-label>
|
<mat-label> {{"labels.inputs.Repeat Password" | translate}} </mat-label>
|
||||||
<input matInput required formControlName="repeatPassword" type="password">
|
<input matInput required formControlName="repeatPassword" type="password">
|
||||||
<mat-error *ngIf="createSelfServiceForm.controls.repeatPassword.hasError('required')">
|
<mat-error *ngIf="createSelfServiceForm.controls.repeatPassword.hasError('required')">
|
||||||
{{"labels.inputs.Repeat password" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
|
{{"labels.inputs.Repeat password" | translate}} {{"labels.commons.is" | translate}}
|
||||||
|
<strong>{{"labels.commons.required" | translate}}</strong>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="createSelfServiceForm.controls.repeatPassword.hasError('notequal')">
|
<mat-error *ngIf="createSelfServiceForm.controls.repeatPassword.hasError('notequal')">
|
||||||
{{"labels.inputs.Passwords should be" | translate}} <strong>{{"labels.inputs.matched" | translate}}</strong>
|
{{"labels.inputs.Passwords should be" | translate}} <strong>{{"labels.inputs.matched" |
|
||||||
|
translate}}</strong>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
@@ -84,9 +106,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-card-actions fxLayoutGap="5px" fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center">
|
<mat-card-actions fxLayoutGap="5px" fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center">
|
||||||
<button type="button" mat-raised-button [routerLink]="['../../']">{{"labels.buttons.Cancel" | translate}}</button>
|
<button type="button" mat-raised-button [routerLink]="['../../']">{{"labels.buttons.Cancel" |
|
||||||
<button mat-raised-button color="primary" [disabled]="!createSelfServiceForm.valid">{{"labels.buttons.Activate Self Service User" | translate}}</button>
|
translate}}</button>
|
||||||
<i class="fa fa-question-circle fa-2x" title="Activate Self Service User Help"></i>
|
<button mat-raised-button color="primary"
|
||||||
|
[disabled]="!createSelfServiceForm.valid">{{"labels.buttons.Activate Self Service User" |
|
||||||
|
translate}}</button>
|
||||||
|
<i class="fa fa-question-circle fa-2x" title="Activate Self Service User Help"></i>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
|
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
@@ -95,4 +120,4 @@
|
|||||||
|
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
+5
-23
@@ -6,6 +6,7 @@ import { Subscription } from 'rxjs';
|
|||||||
|
|
||||||
/** Client Services. */
|
/** Client Services. */
|
||||||
import { ClientsService } from 'app/clients/clients.service';
|
import { ClientsService } from 'app/clients/clients.service';
|
||||||
|
import { PasswordsUtility } from 'app/core/utils/passwords-utility';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'mifosx-create-self-service-user',
|
selector: 'mifosx-create-self-service-user',
|
||||||
@@ -21,7 +22,8 @@ export class CreateSelfServiceUserComponent implements OnInit {
|
|||||||
constructor(private formBuilder: UntypedFormBuilder,
|
constructor(private formBuilder: UntypedFormBuilder,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private clientService: ClientsService,
|
private clientService: ClientsService,
|
||||||
private router: Router) {
|
private router: Router,
|
||||||
|
private passwordsUtility: PasswordsUtility) {
|
||||||
this.route.data.subscribe((data: { clientActionData: any}) => {
|
this.route.data.subscribe((data: { clientActionData: any}) => {
|
||||||
this.clientData = data.clientActionData;
|
this.clientData = data.clientActionData;
|
||||||
});
|
});
|
||||||
@@ -43,8 +45,8 @@ export class CreateSelfServiceUserComponent implements OnInit {
|
|||||||
this.createSelfServiceForm.removeControl('repeatPassword');
|
this.createSelfServiceForm.removeControl('repeatPassword');
|
||||||
} else {
|
} else {
|
||||||
this.hidePasswordField = false;
|
this.hidePasswordField = false;
|
||||||
this.createSelfServiceForm.addControl('password', new UntypedFormControl('', [Validators.required]));
|
this.createSelfServiceForm.addControl('password', new UntypedFormControl('', this.passwordsUtility.getPasswordValidators()));
|
||||||
this.createSelfServiceForm.addControl('repeatPassword', new UntypedFormControl('', [Validators.required, this.confirmPassword('password')]));
|
this.createSelfServiceForm.addControl('repeatPassword', new UntypedFormControl('', [Validators.required, this.passwordsUtility.confirmPassword('password')]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -83,24 +85,4 @@ export class CreateSelfServiceUserComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirm Change Password of Users
|
|
||||||
* @param controlNameToCompare Form Control Name to be compared.
|
|
||||||
*/
|
|
||||||
confirmPassword(controlNameToCompare: string): ValidatorFn {
|
|
||||||
return (c: AbstractControl): ValidationErrors|null => {
|
|
||||||
if (c.value == null || c.value.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const controlToCompare = c.root.get(controlNameToCompare);
|
|
||||||
if (controlToCompare) {
|
|
||||||
const subscription: Subscription = controlToCompare.valueChanges.subscribe(() => {
|
|
||||||
c.updateValueAndValidity();
|
|
||||||
subscription.unsubscribe();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return controlToCompare && controlToCompare.value !== c.value ? {'notequal': true} : null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,9 @@
|
|||||||
|
|
||||||
<ng-container matColumnDef="Loan Account">
|
<ng-container matColumnDef="Loan Account">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Loan Product" | translate}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Loan Product" | translate}} </th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.productName}} </td>
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<mifosx-long-text textValue="{{element.productName}}" chars="35"></mifosx-long-text>
|
||||||
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="Original Loan">
|
<ng-container matColumnDef="Original Loan">
|
||||||
@@ -195,7 +197,9 @@
|
|||||||
|
|
||||||
<ng-container matColumnDef="Loan Account">
|
<ng-container matColumnDef="Loan Account">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Loan Product" | translate}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Loan Product" | translate}} </th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.productName}} </td>
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<mifosx-long-text textValue="{{element.productName}}" chars="35"></mifosx-long-text>
|
||||||
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="Original Loan">
|
<ng-container matColumnDef="Original Loan">
|
||||||
@@ -260,7 +264,9 @@
|
|||||||
|
|
||||||
<ng-container matColumnDef="Saving Account">
|
<ng-container matColumnDef="Saving Account">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Savings Product" | translate}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Savings Product" | translate}} </th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.productName}} </td>
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<mifosx-long-text textValue="{{element.productName}}" chars="35"></mifosx-long-text>
|
||||||
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="Last Active">
|
<ng-container matColumnDef="Last Active">
|
||||||
@@ -320,7 +326,9 @@
|
|||||||
|
|
||||||
<ng-container matColumnDef="Saving Account">
|
<ng-container matColumnDef="Saving Account">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Saving Product" | translate}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Saving Product" | translate}} </th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.productName}} </td>
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<mifosx-long-text textValue="{{element.productName}}" chars="35"></mifosx-long-text>
|
||||||
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="Closed Date">
|
<ng-container matColumnDef="Closed Date">
|
||||||
@@ -415,7 +423,9 @@
|
|||||||
|
|
||||||
<ng-container matColumnDef="Saving Account">
|
<ng-container matColumnDef="Saving Account">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Fixed Deposit Product" | translate}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Fixed Deposit Product" | translate}} </th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.productName}} </td>
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<mifosx-long-text textValue="{{element.productName}}" chars="35"></mifosx-long-text>
|
||||||
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="Closed Date">
|
<ng-container matColumnDef="Closed Date">
|
||||||
@@ -458,7 +468,9 @@
|
|||||||
|
|
||||||
<ng-container matColumnDef="Saving Account">
|
<ng-container matColumnDef="Saving Account">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Recurring Deposit Product" | translate}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Recurring Deposit Product" | translate}} </th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.productName}} </td>
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<mifosx-long-text textValue="{{element.productName}}" chars="35"></mifosx-long-text>
|
||||||
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="Last Active">
|
<ng-container matColumnDef="Last Active">
|
||||||
@@ -515,7 +527,9 @@
|
|||||||
|
|
||||||
<ng-container matColumnDef="Saving Account">
|
<ng-container matColumnDef="Saving Account">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Recurring Deposit Product" | translate}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Recurring Deposit Product" | translate}} </th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.productName}} </td>
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<mifosx-long-text textValue="{{element.productName}}" chars="35"></mifosx-long-text>
|
||||||
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="Closed Date">
|
<ng-container matColumnDef="Closed Date">
|
||||||
@@ -556,7 +570,9 @@
|
|||||||
|
|
||||||
<ng-container matColumnDef="Share Account">
|
<ng-container matColumnDef="Share Account">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Share Product" | translate}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Share Product" | translate}} </th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.productName}} </td>
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<mifosx-long-text textValue="{{element.productName}}" chars="35"></mifosx-long-text>
|
||||||
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="Approved Shares">
|
<ng-container matColumnDef="Approved Shares">
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { AbstractControl, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
|
||||||
|
export class PasswordsUtility {
|
||||||
|
// password regex pattern
|
||||||
|
public static PASSWORD_REGEX = '^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*[#$@$!%*?&])[A-Za-z\d#$@$!%*?&].{8,}$';
|
||||||
|
|
||||||
|
public getPasswordValidators(): ValidatorFn[] {
|
||||||
|
return [Validators.required, Validators.pattern(PasswordsUtility.PASSWORD_REGEX), Validators.maxLength(50), Validators.minLength(8)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm Change Password of Users
|
||||||
|
* @param controlNameToCompare Form Control Name to be compared.
|
||||||
|
*/
|
||||||
|
public confirmPassword(controlNameToCompare: string): ValidatorFn {
|
||||||
|
return (c: AbstractControl): ValidationErrors|null => {
|
||||||
|
if (c.value == null || c.value.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const controlToCompare = c.root.get(controlNameToCompare);
|
||||||
|
if (controlToCompare) {
|
||||||
|
const subscription: Subscription = controlToCompare.valueChanges.subscribe(() => {
|
||||||
|
c.updateValueAndValidity();
|
||||||
|
subscription.unsubscribe();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return controlToCompare && controlToCompare.value !== c.value ? {'notequal': true} : null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,8 +20,9 @@
|
|||||||
<h3>
|
<h3>
|
||||||
<i class="fa fa-stop" matTooltip="{{'labels.status.' + loanDetailsData.status.value | translate}}"
|
<i class="fa fa-stop" matTooltip="{{'labels.status.' + loanDetailsData.status.value | translate}}"
|
||||||
[ngClass]="loanDetailsData.inArrears?'status-active-overdue':( iconLoanStatusColor() | statusLookup)"></i>
|
[ngClass]="loanDetailsData.inArrears?'status-active-overdue':( iconLoanStatusColor() | statusLookup)"></i>
|
||||||
<span class="m-r-10">{{'labels.heading.Loan Product' | translate}}:</span> {{loanDetailsData.loanProductName}}
|
<span class="m-r-5">{{'labels.heading.Loan Product' | translate}} :</span>
|
||||||
<mifosx-account-number accountNo="{{loanDetailsData.accountNo}}"></mifosx-account-number>
|
<span class="m-r-5"><mifosx-long-text textValue="{{loanDetailsData.loanProductName}}"></mifosx-long-text></span>
|
||||||
|
<mifosx-account-number accountNo="{{loanDetailsData.accountNo}}" display="left"></mifosx-account-number>
|
||||||
</h3>
|
</h3>
|
||||||
<span class="loans-overview">
|
<span class="loans-overview">
|
||||||
<span class="m-r-10">{{'labels.text.' + entityType | translate}} {{"labels.inputs.name" | translate}} :</span> {{loanDetailsData.clientName ||
|
<span class="m-r-10">{{'labels.text.' + entityType | translate}} {{"labels.inputs.name" | translate}} :</span> {{loanDetailsData.clientName ||
|
||||||
|
|||||||
@@ -26,8 +26,17 @@
|
|||||||
</span>
|
</span>
|
||||||
<mat-label>{{'labels.inputs.Confirm Password' | translate}}</mat-label>
|
<mat-label>{{'labels.inputs.Confirm Password' | translate}}</mat-label>
|
||||||
<input type="password" matInput required formControlName="repeatPassword">
|
<input type="password" matInput required formControlName="repeatPassword">
|
||||||
<mat-error *ngIf="resetPasswordForm.controls.repeatPassword.hasError('required')">
|
<mat-error *ngIf="resetPasswordForm.controls.password.hasError('required')">
|
||||||
{{'labels.inputs.Confirm Password' | translate}} <strong>{{'labels.commons.is required' | translate}}</strong>
|
{{ 'labels.inputs.Password' | translate }} <strong>{{'labels.commons.is required' | translate }}</strong>
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="resetPasswordForm.controls.password.hasError('minlength')">
|
||||||
|
{{'labels.commons.Password should be at least' | translate }} <strong>{{'labels.commons.8 characters long' | translate }}</strong>
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="resetPasswordForm.controls.password.hasError('maxlength')">
|
||||||
|
{{'labels.commons.Password should not be more than' | translate }} <strong>{{'labels.commons.50 characters long' | translate }}</strong>
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="resetPasswordForm.controls.password.hasError('pattern') && !(resetPasswordForm.controls.password.hasError('minlength') || resetPasswordForm.controls.password.hasError('maxlength'))">
|
||||||
|
{{'labels.commons.Password should include a' | translate }} <strong>{{'labels.commons.numeral' | translate }}</strong> {{'labels.commons.and at' | translate }} <strong>{{'labels.commons.least one uppercase' | translate }}</strong> ,<strong>{{'labels.commons.lowercase and special character' | translate }}</strong>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { AuthenticationService } from '../../core/authentication/authentication.
|
|||||||
|
|
||||||
/** Custom Validators */
|
/** Custom Validators */
|
||||||
import { confirmPasswordValidator } from './confirm-password.validator';
|
import { confirmPasswordValidator } from './confirm-password.validator';
|
||||||
|
import { PasswordsUtility } from 'app/core/utils/passwords-utility';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset password component.
|
* Reset password component.
|
||||||
@@ -33,7 +34,8 @@ export class ResetPasswordComponent implements OnInit {
|
|||||||
* @param {AuthenticationService} authenticationService Authentication Service.
|
* @param {AuthenticationService} authenticationService Authentication Service.
|
||||||
*/
|
*/
|
||||||
constructor(private formBuilder: UntypedFormBuilder,
|
constructor(private formBuilder: UntypedFormBuilder,
|
||||||
private authenticationService: AuthenticationService) { }
|
private authenticationService: AuthenticationService,
|
||||||
|
private passwordsUtility: PasswordsUtility) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates reset password form.
|
* Creates reset password form.
|
||||||
@@ -66,7 +68,7 @@ export class ResetPasswordComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
private createResetPasswordForm() {
|
private createResetPasswordForm() {
|
||||||
this.resetPasswordForm = this.formBuilder.group({
|
this.resetPasswordForm = this.formBuilder.group({
|
||||||
'password': ['', Validators.required],
|
'password': ['', this.passwordsUtility.getPasswordValidators()],
|
||||||
'repeatPassword': ['', Validators.required]
|
'repeatPassword': ['', Validators.required]
|
||||||
}, { validator: confirmPasswordValidator });
|
}, { validator: confirmPasswordValidator });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export class OfficesComponent implements OnInit, AfterViewInit {
|
|||||||
/** Office data tables. */
|
/** Office data tables. */
|
||||||
dataTablesData: any;
|
dataTablesData: any;
|
||||||
/** Flag to check if tree is expanded or collapsed. */
|
/** Flag to check if tree is expanded or collapsed. */
|
||||||
isTreeExpanded: boolean = true;
|
isTreeExpanded = true;
|
||||||
|
|
||||||
/** Paginator for offices table. */
|
/** Paginator for offices table. */
|
||||||
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
||||||
@@ -190,9 +190,9 @@ export class OfficesComponent implements OnInit, AfterViewInit {
|
|||||||
this.router.navigate(['/organization']);
|
this.router.navigate(['/organization']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expand and Collapse the tree
|
* Expand and Collapse the tree
|
||||||
*/
|
*/
|
||||||
toggleExpandCollapse() {
|
toggleExpandCollapse() {
|
||||||
this.isTreeExpanded = this.treeControlService.toggleExpandCollapse(this.nestedTreeControl, this.isTreeExpanded);
|
this.isTreeExpanded = this.treeControlService.toggleExpandCollapse(this.nestedTreeControl, this.isTreeExpanded);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { FormatNumberPipe } from './format-number.pipe';
|
|||||||
import { YesnoPipe } from './yesno.pipe';
|
import { YesnoPipe } from './yesno.pipe';
|
||||||
import { PrettyPrintPipe } from './pretty-print.pipe';
|
import { PrettyPrintPipe } from './pretty-print.pipe';
|
||||||
import { TranslateCatalogPipe } from './translate-catalog.pipe';
|
import { TranslateCatalogPipe } from './translate-catalog.pipe';
|
||||||
|
import { TruncateTextPipe } from './truncate-text.pipe';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -30,7 +31,8 @@ import { TranslateCatalogPipe } from './translate-catalog.pipe';
|
|||||||
FormatNumberPipe,
|
FormatNumberPipe,
|
||||||
YesnoPipe,
|
YesnoPipe,
|
||||||
PrettyPrintPipe,
|
PrettyPrintPipe,
|
||||||
TranslateCatalogPipe],
|
TranslateCatalogPipe,
|
||||||
|
TruncateTextPipe],
|
||||||
providers: [StatusLookupPipe,
|
providers: [StatusLookupPipe,
|
||||||
AccountsFilterPipe,
|
AccountsFilterPipe,
|
||||||
ChargesFilterPipe,
|
ChargesFilterPipe,
|
||||||
@@ -43,7 +45,8 @@ import { TranslateCatalogPipe } from './translate-catalog.pipe';
|
|||||||
FormatNumberPipe,
|
FormatNumberPipe,
|
||||||
YesnoPipe,
|
YesnoPipe,
|
||||||
PrettyPrintPipe,
|
PrettyPrintPipe,
|
||||||
TranslateCatalogPipe],
|
TranslateCatalogPipe,
|
||||||
|
TruncateTextPipe],
|
||||||
exports: [StatusLookupPipe,
|
exports: [StatusLookupPipe,
|
||||||
AccountsFilterPipe,
|
AccountsFilterPipe,
|
||||||
ChargesFilterPipe,
|
ChargesFilterPipe,
|
||||||
@@ -56,6 +59,7 @@ import { TranslateCatalogPipe } from './translate-catalog.pipe';
|
|||||||
FormatNumberPipe,
|
FormatNumberPipe,
|
||||||
YesnoPipe,
|
YesnoPipe,
|
||||||
PrettyPrintPipe,
|
PrettyPrintPipe,
|
||||||
TranslateCatalogPipe]
|
TranslateCatalogPipe,
|
||||||
|
TruncateTextPipe]
|
||||||
})
|
})
|
||||||
export class PipesModule { }
|
export class PipesModule { }
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'truncateText'
|
||||||
|
})
|
||||||
|
export class TruncateTextPipe implements PipeTransform {
|
||||||
|
|
||||||
|
transform(value: string, chars: number): string {
|
||||||
|
if (value.length <= 40) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
let truncatedText = value.substring(0, 30);
|
||||||
|
if (chars) {
|
||||||
|
truncatedText = value.substring(0, chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
return truncatedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+2
-2
@@ -34,7 +34,7 @@
|
|||||||
<mat-label>{{'labels.inputs.Debit Account Type' | translate}}</mat-label>
|
<mat-label>{{'labels.inputs.Debit Account Type' | translate}}</mat-label>
|
||||||
<mat-select formControlName="debitAccountType">
|
<mat-select formControlName="debitAccountType">
|
||||||
<mat-option *ngFor="let debitAccountType of debitAccountTypeData" [value]="debitAccountType.id">
|
<mat-option *ngFor="let debitAccountType of debitAccountTypeData" [value]="debitAccountType.id">
|
||||||
{{ 'labels.inputs.accounting.' + debitAccountType.value | translate }}
|
{{ debitAccountType.value | translateCatalog }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
<mat-label>{{'labels.inputs.Credit Account Type' | translate}}</mat-label>
|
<mat-label>{{'labels.inputs.Credit Account Type' | translate}}</mat-label>
|
||||||
<mat-select formControlName="creditAccountType">
|
<mat-select formControlName="creditAccountType">
|
||||||
<mat-option *ngFor="let creditAccountType of creditAccountTypeData" [value]="creditAccountType.id">
|
<mat-option *ngFor="let creditAccountType of creditAccountTypeData" [value]="creditAccountType.id">
|
||||||
{{ 'labels.inputs.accounting.' + creditAccountType.value | translate }}
|
{{ creditAccountType.value | translateCatalog }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fxFlex="50%" *ngIf="taxComponentData.creditAccountType">
|
<div fxFlex="50%" *ngIf="taxComponentData.creditAccountType">
|
||||||
{{ 'labels.inputs.accounting.' + taxComponentData.creditAccountType.value | translate }}
|
{{ taxComponentData.creditAccountType.value | translateCatalog }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div fxFlex="50%" class="mat-body-strong" *ngIf="taxComponentData.creditAccount">
|
<div fxFlex="50%" class="mat-body-strong" *ngIf="taxComponentData.creditAccount">
|
||||||
|
|||||||
@@ -19,8 +19,9 @@
|
|||||||
[matTooltip]="savingsAccountData.status.value" *ngIf="!savingsAccountData.subStatus.block"></i>
|
[matTooltip]="savingsAccountData.status.value" *ngIf="!savingsAccountData.subStatus.block"></i>
|
||||||
<i class="fa fa-stop" [ngClass]="savingsAccountData.subStatus.value | statusLookup"
|
<i class="fa fa-stop" [ngClass]="savingsAccountData.subStatus.value | statusLookup"
|
||||||
[matTooltip]="savingsAccountData.subStatus.value" *ngIf="savingsAccountData.subStatus.block"></i>
|
[matTooltip]="savingsAccountData.subStatus.value" *ngIf="savingsAccountData.subStatus.block"></i>
|
||||||
{{'labels.inputs.Savings Product' | translate}} : {{savingsAccountData.savingsProductName}}<span class="m-l-10">
|
<span class="m-r-5">{{'labels.inputs.Savings Product' | translate}} :</span>
|
||||||
<mifosx-account-number accountNo="{{savingsAccountData.accountNo}}"></mifosx-account-number></span>
|
<span class="m-r-5"><mifosx-long-text textValue="{{savingsAccountData.savingsProductName}}"></mifosx-long-text></span>
|
||||||
|
<mifosx-account-number accountNo="{{savingsAccountData.accountNo}}" display="left"></mifosx-account-number>
|
||||||
</h3>
|
</h3>
|
||||||
<span class="account-overview">
|
<span class="account-overview">
|
||||||
{{'labels.text.' + entityType | translate}} {{"labels.inputs.name" | translate}}: {{savingsAccountData.clientName ||
|
{{'labels.text.' + entityType | translate}} {{"labels.inputs.name" | translate}}: {{savingsAccountData.clientName ||
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ export class SearchPageComponent {
|
|||||||
case 'CLIENT':
|
case 'CLIENT':
|
||||||
this.router.navigate(['clients', entity.entityId, 'general']);
|
this.router.navigate(['clients', entity.entityId, 'general']);
|
||||||
break;
|
break;
|
||||||
|
case 'CLIENTIDENTIFIER':
|
||||||
|
this.router.navigate(['clients', entity.parentId, 'general']);
|
||||||
|
break;
|
||||||
case 'CENTER':
|
case 'CENTER':
|
||||||
this.router.navigate(['centers', entity.entityId]);
|
this.router.navigate(['centers', entity.entityId]);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Component, OnInit, Inject } from '@angular/core';
|
|||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
import { UntypedFormBuilder, Validators, ValidatorFn, AbstractControl, ValidationErrors } from '@angular/forms';
|
import { UntypedFormBuilder, Validators, ValidatorFn, AbstractControl, ValidationErrors } from '@angular/forms';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
import { PasswordsUtility } from 'app/core/utils/passwords-utility';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change Password Dialog component.
|
* Change Password Dialog component.
|
||||||
@@ -23,7 +24,8 @@ export class ChangePasswordDialogComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
constructor(public dialogRef: MatDialogRef<ChangePasswordDialogComponent>,
|
constructor(public dialogRef: MatDialogRef<ChangePasswordDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||||
private formBuilder: UntypedFormBuilder) { }
|
private formBuilder: UntypedFormBuilder,
|
||||||
|
private passwordsUtility: PasswordsUtility) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.createChangePasswordForm();
|
this.createChangePasswordForm();
|
||||||
@@ -32,7 +34,7 @@ export class ChangePasswordDialogComponent implements OnInit {
|
|||||||
/** Change Password form */
|
/** Change Password form */
|
||||||
createChangePasswordForm() {
|
createChangePasswordForm() {
|
||||||
this.changePasswordForm = this.formBuilder.group({
|
this.changePasswordForm = this.formBuilder.group({
|
||||||
'password': ['', [Validators.required, Validators.pattern('^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*[#$@$!%*?&])[A-Za-z\d#$@$!%*?&].{8,}$'), Validators.maxLength(50), Validators.minLength(8)]],
|
'password': ['', this.passwordsUtility.getPasswordValidators()],
|
||||||
'repeatPassword': ['', [Validators.required, this.confirmPassword('password')]]
|
'repeatPassword': ['', [Validators.required, this.confirmPassword('password')]]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<span (mouseenter)="mouseEnter()" (mouseleave)="mouseLeave()" *ngIf="!emptyValue">
|
||||||
|
<span class="m-l-3" *ngIf="isLongValue()"><fa-icon icon="eye" size="sm" [title]="textValue"></fa-icon></span>
|
||||||
|
<span class="m-l-5" *ngIf="isLongValue()">{{ textValue | truncateText:chars }}...</span>
|
||||||
|
<span class="m-l-5" *ngIf="!isLongValue()">{{ textValue }}</span>
|
||||||
|
</span>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LongTextComponent } from './long-text.component';
|
||||||
|
|
||||||
|
describe('LongTextComponent', () => {
|
||||||
|
let component: LongTextComponent;
|
||||||
|
let fixture: ComponentFixture<LongTextComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ LongTextComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(LongTextComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-long-text',
|
||||||
|
templateUrl: './long-text.component.html',
|
||||||
|
styleUrls: ['./long-text.component.scss']
|
||||||
|
})
|
||||||
|
export class LongTextComponent implements OnInit {
|
||||||
|
@Input() textValue: string;
|
||||||
|
@Input() chars = 30;
|
||||||
|
|
||||||
|
iconVisible = false;
|
||||||
|
displayL = false;
|
||||||
|
displayR = true;
|
||||||
|
emptyValue = false;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.emptyValue = (!this.textValue || this.textValue === '');
|
||||||
|
}
|
||||||
|
|
||||||
|
isLongValue(): boolean {
|
||||||
|
if (this.textValue == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (this.textValue.length > 25);
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseEnter() {
|
||||||
|
this.iconVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseLeave() {
|
||||||
|
this.iconVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,6 +47,7 @@ import { GlAccountSelectorComponent } from './accounting/gl-account-selector/gl-
|
|||||||
import { GlAccountDisplayComponent } from './accounting/gl-account-display/gl-account-display.component';
|
import { GlAccountDisplayComponent } from './accounting/gl-account-display/gl-account-display.component';
|
||||||
import { ViewSavingsAccountingDetailsComponent } from './accounting/view-savings-accounting-details/view-savings-accounting-details.component';
|
import { ViewSavingsAccountingDetailsComponent } from './accounting/view-savings-accounting-details/view-savings-accounting-details.component';
|
||||||
import { ThemeToggleComponent } from './theme-toggle/theme-toggle.component';
|
import { ThemeToggleComponent } from './theme-toggle/theme-toggle.component';
|
||||||
|
import { LongTextComponent } from './long-text/long-text.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shared Module
|
* Shared Module
|
||||||
@@ -100,7 +101,8 @@ import { ThemeToggleComponent } from './theme-toggle/theme-toggle.component';
|
|||||||
GlAccountSelectorComponent,
|
GlAccountSelectorComponent,
|
||||||
GlAccountDisplayComponent,
|
GlAccountDisplayComponent,
|
||||||
ViewSavingsAccountingDetailsComponent,
|
ViewSavingsAccountingDetailsComponent,
|
||||||
ThemeToggleComponent
|
ThemeToggleComponent,
|
||||||
|
LongTextComponent
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
FileUploadComponent,
|
FileUploadComponent,
|
||||||
@@ -132,7 +134,8 @@ import { ThemeToggleComponent } from './theme-toggle/theme-toggle.component';
|
|||||||
GlAccountSelectorComponent,
|
GlAccountSelectorComponent,
|
||||||
GlAccountDisplayComponent,
|
GlAccountDisplayComponent,
|
||||||
ViewSavingsAccountingDetailsComponent,
|
ViewSavingsAccountingDetailsComponent,
|
||||||
ThemeToggleComponent
|
ThemeToggleComponent,
|
||||||
|
LongTextComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SharedModule { }
|
export class SharedModule { }
|
||||||
|
|||||||
@@ -67,6 +67,15 @@
|
|||||||
<mat-error *ngIf="userForm.controls.password.hasError('required')">
|
<mat-error *ngIf="userForm.controls.password.hasError('required')">
|
||||||
{{'labels.inputs.Password' | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
|
{{'labels.inputs.Password' | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
<mat-error *ngIf="userForm.controls.password.hasError('minlength')">
|
||||||
|
{{'labels.commons.Password should be at least' | translate }} <strong>{{'labels.commons.8 characters long' | translate }}</strong>
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="userForm.controls.password.hasError('maxlength')">
|
||||||
|
{{'labels.commons.Password should not be more than' | translate }} <strong>{{'labels.commons.50 characters long' | translate }}</strong>
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="userForm.controls.password.hasError('pattern') && !(userForm.controls.password.hasError('minlength') || userForm.controls.password.hasError('maxlength'))">
|
||||||
|
{{'labels.commons.Password should include a' | translate }} <strong>{{'labels.commons.numeral' | translate }}</strong> {{'labels.commons.and at' | translate }} <strong>{{'labels.commons.least one uppercase' | translate }}</strong> ,<strong>{{'labels.commons.lowercase and special character' | translate }}</strong>
|
||||||
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field fxFlex="48%" *ngIf="!userForm.controls.sendPasswordToEmail.value">
|
<mat-form-field fxFlex="48%" *ngIf="!userForm.controls.sendPasswordToEmail.value">
|
||||||
@@ -79,7 +88,7 @@
|
|||||||
|
|
||||||
<p fxFlex="98%" class="reset-password-error" *ngIf="userForm.errors?.passwordsDoNotMatch &&
|
<p fxFlex="98%" class="reset-password-error" *ngIf="userForm.errors?.passwordsDoNotMatch &&
|
||||||
(!userForm.controls.password.hasError('required') && !userForm.controls.repeatPassword.hasError('required'))">
|
(!userForm.controls.password.hasError('required') && !userForm.controls.repeatPassword.hasError('required'))">
|
||||||
{{'labels.inputs.Passwords' | translate}} <strong>{{"labels.commons.do not match' | translate}}</strong>
|
{{'labels.inputs.Passwords' | translate}} <strong>{{'labels.commons.do not match' | translate}}</strong>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<mat-form-field fxFlex="48%">
|
<mat-form-field fxFlex="48%">
|
||||||
|
|||||||
@@ -8,13 +8,12 @@ import { MatDialog } from '@angular/material/dialog';
|
|||||||
/** Custom Services */
|
/** Custom Services */
|
||||||
import { UsersService } from '../users.service';
|
import { UsersService } from '../users.service';
|
||||||
import { PopoverService } from '../../configuration-wizard/popover/popover.service';
|
import { PopoverService } from '../../configuration-wizard/popover/popover.service';
|
||||||
import { ConfigurationWizardService } from '../../configuration-wizard/configuration-wizard.service';
|
|
||||||
|
|
||||||
/** Custom Validators */
|
|
||||||
import { confirmPasswordValidator } from '../../login/reset-password/confirm-password.validator';
|
|
||||||
|
|
||||||
/** Custom Dialog Component */
|
/** Custom Dialog Component */
|
||||||
import { ContinueSetupDialogComponent } from '../../configuration-wizard/continue-setup-dialog/continue-setup-dialog.component';
|
import { PasswordsUtility } from 'app/core/utils/passwords-utility';
|
||||||
|
import { confirmPasswordValidator } from 'app/login/reset-password/confirm-password.validator';
|
||||||
|
import { ConfigurationWizardService } from 'app/configuration-wizard/configuration-wizard.service';
|
||||||
|
import { ContinueSetupDialogComponent } from 'app/configuration-wizard/continue-setup-dialog/continue-setup-dialog.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create user component.
|
* Create user component.
|
||||||
@@ -55,7 +54,8 @@ export class CreateUserComponent implements OnInit, AfterViewInit {
|
|||||||
private router: Router,
|
private router: Router,
|
||||||
private popoverService: PopoverService,
|
private popoverService: PopoverService,
|
||||||
private configurationWizardService: ConfigurationWizardService,
|
private configurationWizardService: ConfigurationWizardService,
|
||||||
public dialog: MatDialog) {
|
private dialog: MatDialog,
|
||||||
|
private passwordsUtility: PasswordsUtility) {
|
||||||
this.route.data.subscribe((data: {
|
this.route.data.subscribe((data: {
|
||||||
usersTemplate: any
|
usersTemplate: any
|
||||||
}) => {
|
}) => {
|
||||||
@@ -112,8 +112,8 @@ export class CreateUserComponent implements OnInit, AfterViewInit {
|
|||||||
this.userForm.removeControl('repeatPassword');
|
this.userForm.removeControl('repeatPassword');
|
||||||
this.userForm.get('email').setValidators([Validators.required, Validators.email]);
|
this.userForm.get('email').setValidators([Validators.required, Validators.email]);
|
||||||
} else {
|
} else {
|
||||||
this.userForm.addControl('password', new UntypedFormControl('', Validators.required));
|
this.userForm.addControl('password', new UntypedFormControl('', this.passwordsUtility.getPasswordValidators()));
|
||||||
this.userForm.addControl('repeatPassword', new UntypedFormControl('', Validators.required));
|
this.userForm.addControl('repeatPassword', new UntypedFormControl('', [Validators.required, this.passwordsUtility.confirmPassword('password')]));
|
||||||
this.userForm.get('email').setValidators([Validators.email]);
|
this.userForm.get('email').setValidators([Validators.email]);
|
||||||
}
|
}
|
||||||
this.userForm.get('email').updateValueAndValidity();
|
this.userForm.get('email').updateValueAndValidity();
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "ČTVRTEK",
|
"THURSDAY": "ČTVRTEK",
|
||||||
"FRIDAY": "PÁTEK",
|
"FRIDAY": "PÁTEK",
|
||||||
"SATURDAY": "SOBOTA",
|
"SATURDAY": "SOBOTA",
|
||||||
|
"Interest posting": "Zveřejnění zájmu",
|
||||||
|
"Amount on hold": "Částka na počkání",
|
||||||
"Invalid": "Neplatný"
|
"Invalid": "Neplatný"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "DONNERSTAG",
|
"THURSDAY": "DONNERSTAG",
|
||||||
"FRIDAY": "FREITAG",
|
"FRIDAY": "FREITAG",
|
||||||
"SATURDAY": "SAMSTAG",
|
"SATURDAY": "SAMSTAG",
|
||||||
|
"Interest posting": "Zinsbuchung",
|
||||||
|
"Amount on hold": "Zurückgestellter Betrag",
|
||||||
"Invalid": "Ungültig"
|
"Invalid": "Ungültig"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "THURSDAY",
|
"THURSDAY": "THURSDAY",
|
||||||
"FRIDAY": "FRIDAY",
|
"FRIDAY": "FRIDAY",
|
||||||
"SATURDAY": "SATURDAY",
|
"SATURDAY": "SATURDAY",
|
||||||
|
"Interest posting": "Interest posting",
|
||||||
|
"Amount on hold": "Amount on hold",
|
||||||
"Invalid": "Invalid"
|
"Invalid": "Invalid"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "JUEVES",
|
"THURSDAY": "JUEVES",
|
||||||
"FRIDAY": "VIERNES",
|
"FRIDAY": "VIERNES",
|
||||||
"SATURDAY": "SÁBADO",
|
"SATURDAY": "SÁBADO",
|
||||||
|
"Interest posting": "Intereses",
|
||||||
|
"Amount on hold": "Retención",
|
||||||
"Invalid": "Inválido"
|
"Invalid": "Inválido"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "JEUDI",
|
"THURSDAY": "JEUDI",
|
||||||
"FRIDAY": "VENDREDI",
|
"FRIDAY": "VENDREDI",
|
||||||
"SATURDAY": "SAMEDI",
|
"SATURDAY": "SAMEDI",
|
||||||
|
"Interest posting": "Publication d'intérêt",
|
||||||
|
"Amount on hold": "Montant retenu",
|
||||||
"Invalid": "Invalide"
|
"Invalid": "Invalide"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "GIOVEDÌ",
|
"THURSDAY": "GIOVEDÌ",
|
||||||
"FRIDAY": "VENERDÌ",
|
"FRIDAY": "VENERDÌ",
|
||||||
"SATURDAY": "SABATO",
|
"SATURDAY": "SABATO",
|
||||||
|
"Interest posting": "Pubblicazione di interessi",
|
||||||
|
"Amount on hold": "Importo sospeso",
|
||||||
"Invalid": "Non valido"
|
"Invalid": "Non valido"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "목요일",
|
"THURSDAY": "목요일",
|
||||||
"FRIDAY": "금요일",
|
"FRIDAY": "금요일",
|
||||||
"SATURDAY": "토요일",
|
"SATURDAY": "토요일",
|
||||||
|
"Interest posting": "관심 게시",
|
||||||
|
"Amount on hold": "보류 금액",
|
||||||
"Invalid": "유효하지 않은"
|
"Invalid": "유효하지 않은"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "KETVIRTADIENIS",
|
"THURSDAY": "KETVIRTADIENIS",
|
||||||
"FRIDAY": "PENKTADIENIS",
|
"FRIDAY": "PENKTADIENIS",
|
||||||
"SATURDAY": "ŠEŠTADIENIS",
|
"SATURDAY": "ŠEŠTADIENIS",
|
||||||
|
"Interest posting": "Interesų skelbimas",
|
||||||
|
"Amount on hold": "Sulaikyta suma",
|
||||||
"Invalid": "Neteisinga"
|
"Invalid": "Neteisinga"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "CETURTDIENA",
|
"THURSDAY": "CETURTDIENA",
|
||||||
"FRIDAY": "PIEKTDIENA",
|
"FRIDAY": "PIEKTDIENA",
|
||||||
"SATURDAY": "SESTDIENA",
|
"SATURDAY": "SESTDIENA",
|
||||||
|
"Interest posting": "Interešu publicēšana",
|
||||||
|
"Amount on hold": "Aizturētā summa",
|
||||||
"Invalid": "Nederīgs"
|
"Invalid": "Nederīgs"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "बिहीबार",
|
"THURSDAY": "बिहीबार",
|
||||||
"FRIDAY": "शुक्रबार",
|
"FRIDAY": "शुक्रबार",
|
||||||
"SATURDAY": "शनिबार",
|
"SATURDAY": "शनिबार",
|
||||||
|
"Interest posting": "चासो पोस्टिंग",
|
||||||
|
"Amount on hold": "होल्डमा रहेको रकम",
|
||||||
"Invalid": "अवैध"
|
"Invalid": "अवैध"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "QUINTA-FEIRA",
|
"THURSDAY": "QUINTA-FEIRA",
|
||||||
"FRIDAY": "SEXTA-FEIRA",
|
"FRIDAY": "SEXTA-FEIRA",
|
||||||
"SATURDAY": "SÁBADO",
|
"SATURDAY": "SÁBADO",
|
||||||
|
"Interest posting": "Postagem de interesse",
|
||||||
|
"Amount on hold": "Valor retido",
|
||||||
"Invalid": "Inválido"
|
"Invalid": "Inválido"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
@@ -644,6 +644,8 @@
|
|||||||
"THURSDAY": "ALHAMISI",
|
"THURSDAY": "ALHAMISI",
|
||||||
"FRIDAY": "IJUMAA",
|
"FRIDAY": "IJUMAA",
|
||||||
"SATURDAY": "JUMAMOSI",
|
"SATURDAY": "JUMAMOSI",
|
||||||
|
"Interest posting": "Nia ya kuchapisha",
|
||||||
|
"Amount on hold": "Kiasi kilichohifadhiwa",
|
||||||
"Invalid": "Batili"
|
"Invalid": "Batili"
|
||||||
},
|
},
|
||||||
"commons": {
|
"commons": {
|
||||||
|
|||||||
Reference in New Issue
Block a user