build: Use prettier for typescript
Stop ignoring .ts files in prettier and fix existing issues.
This commit is contained in:
@@ -11,7 +11,6 @@ import { Alert } from './alert.model';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AlertService {
|
||||
|
||||
/** Alert event. */
|
||||
public alertEvent: EventEmitter<Alert>;
|
||||
|
||||
@@ -29,5 +28,4 @@ export class AlertService {
|
||||
alert(alertEvent: Alert) {
|
||||
this.alertEvent.emit(alertEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,13 +14,14 @@ const log = new Logger('AuthenticationGuard');
|
||||
*/
|
||||
@Injectable()
|
||||
export class AuthenticationGuard implements CanActivate {
|
||||
|
||||
/**
|
||||
* @param {Router} router Router for navigation.
|
||||
* @param {AuthenticationService} authenticationService Authentication Service.
|
||||
*/
|
||||
constructor(private router: Router,
|
||||
private authenticationService: AuthenticationService) { }
|
||||
constructor(
|
||||
private router: Router,
|
||||
private authenticationService: AuthenticationService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Ensures route access is authorized only when user is authenticated, otherwise redirects to login.
|
||||
@@ -37,5 +38,4 @@ export class AuthenticationGuard implements CanActivate {
|
||||
this.router.navigate(['/login'], { replaceUrl: true });
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ const twoFactorAccessTokenHeader = 'Fineract-Platform-TFA-Token';
|
||||
*/
|
||||
@Injectable()
|
||||
export class AuthenticationInterceptor implements HttpInterceptor {
|
||||
|
||||
constructor(private settingsService: SettingsService) {}
|
||||
|
||||
/**
|
||||
@@ -82,5 +81,4 @@ export class AuthenticationInterceptor implements HttpInterceptor {
|
||||
removeTwoFactorAuthorization() {
|
||||
delete httpOptions.headers[twoFactorAccessTokenHeader];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,9 +56,11 @@ export class AuthenticationService {
|
||||
* @param {AlertService} alertService Alert Service.
|
||||
* @param {AuthenticationInterceptor} authenticationInterceptor Authentication Interceptor.
|
||||
*/
|
||||
constructor(private http: HttpClient,
|
||||
private alertService: AlertService,
|
||||
private authenticationInterceptor: AuthenticationInterceptor) {
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
private alertService: AlertService,
|
||||
private authenticationInterceptor: AuthenticationInterceptor
|
||||
) {
|
||||
this.userLoggedIn = false;
|
||||
this.rememberMe = false;
|
||||
this.storage = sessionStorage;
|
||||
@@ -96,19 +98,22 @@ export class AuthenticationService {
|
||||
let httpParams = new HttpParams();
|
||||
httpParams = httpParams.set('username', loginContext.username);
|
||||
httpParams = httpParams.set('password', loginContext.password);
|
||||
httpParams = httpParams.set('client_id', `${environment.oauth.appId}`);
|
||||
httpParams = httpParams.set('client_id', `${environment.oauth.appId}`);
|
||||
httpParams = httpParams.set('grant_type', 'password');
|
||||
let headers = new HttpHeaders();
|
||||
headers = headers.set('Content-Type', 'application/x-www-form-urlencoded')
|
||||
return this.http.disableApiPrefix().post(`${environment.oauth.serverUrl}/token`, httpParams.toString(), {headers: headers})
|
||||
headers = headers.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
return this.http
|
||||
.disableApiPrefix()
|
||||
.post(`${environment.oauth.serverUrl}/token`, httpParams.toString(), { headers: headers })
|
||||
.pipe(
|
||||
map((tokenResponse: OAuth2Token) => {
|
||||
map((tokenResponse: OAuth2Token) => {
|
||||
this.getUserDetails(tokenResponse);
|
||||
return of(true);
|
||||
})
|
||||
);
|
||||
} else {
|
||||
return this.http.post('/authentication', { username: loginContext.username, password: loginContext.password })
|
||||
return this.http
|
||||
.post('/authentication', { username: loginContext.username, password: loginContext.password })
|
||||
.pipe(
|
||||
map((credentials: Credentials) => {
|
||||
this.onLoginSuccess(credentials);
|
||||
@@ -124,11 +129,13 @@ export class AuthenticationService {
|
||||
* Sets the oauth2 token refresh time.
|
||||
* @param {OAuth2Token} tokenResponse OAuth2 Token details.
|
||||
*/
|
||||
private getUserDetails(tokenResponse: OAuth2Token) {
|
||||
private getUserDetails(tokenResponse: OAuth2Token) {
|
||||
this.refreshTokenOnExpiry(tokenResponse.expires_in);
|
||||
let headers = new HttpHeaders();
|
||||
headers = headers.set('Authorization', 'bearer '+tokenResponse.access_token)
|
||||
this.http.disableApiPrefix().get(`${environment.serverUrl}/userdetails`,{ headers: headers })
|
||||
let headers = new HttpHeaders();
|
||||
headers = headers.set('Authorization', 'bearer ' + tokenResponse.access_token);
|
||||
this.http
|
||||
.disableApiPrefix()
|
||||
.get(`${environment.serverUrl}/userdetails`, { headers: headers })
|
||||
.subscribe((credentials: Credentials) => {
|
||||
this.onLoginSuccess(credentials);
|
||||
if (!credentials.shouldRenewPassword) {
|
||||
@@ -141,7 +148,7 @@ export class AuthenticationService {
|
||||
* Sets the oauth2 token to refresh on expiry.
|
||||
* @param {number} expiresInTime OAuth2 token expiry time in seconds.
|
||||
*/
|
||||
private refreshTokenOnExpiry(expiresInTime: number) {
|
||||
private refreshTokenOnExpiry(expiresInTime: number) {
|
||||
setTimeout(() => this.refreshOAuthAccessToken(), expiresInTime * 1000);
|
||||
}
|
||||
|
||||
@@ -153,17 +160,19 @@ export class AuthenticationService {
|
||||
if (oAuthRefreshToken == null) {
|
||||
return;
|
||||
}
|
||||
oAuthRefreshToken = JSON.parse(this.storage.getItem(this.oAuthTokenDetailsStorageKey)).refresh_token;
|
||||
this.authenticationInterceptor.removeAuthorization();
|
||||
const credentials = JSON.parse(this.storage.getItem(this.credentialsStorageKey));
|
||||
let httpParams = new HttpParams();
|
||||
oAuthRefreshToken = JSON.parse(this.storage.getItem(this.oAuthTokenDetailsStorageKey)).refresh_token;
|
||||
this.authenticationInterceptor.removeAuthorization();
|
||||
const credentials = JSON.parse(this.storage.getItem(this.credentialsStorageKey));
|
||||
let httpParams = new HttpParams();
|
||||
httpParams = httpParams.set('username', credentials.username);
|
||||
httpParams = httpParams.set('client_id', `${environment.oauth.appId}`);
|
||||
httpParams = httpParams.set('refresh_token', oAuthRefreshToken);
|
||||
httpParams = httpParams.set('grant_type', 'refresh_token');
|
||||
let headers = new HttpHeaders();
|
||||
headers = headers.set('Content-Type', 'application/x-www-form-urlencoded')
|
||||
return this.http.disableApiPrefix().post(`${environment.oauth.serverUrl}/token`, httpParams.toString(), {headers: headers})
|
||||
headers = headers.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
return this.http
|
||||
.disableApiPrefix()
|
||||
.post(`${environment.oauth.serverUrl}/token`, httpParams.toString(), { headers: headers })
|
||||
.subscribe((tokenResponse: OAuth2Token) => {
|
||||
this.storage.setItem(this.oAuthTokenDetailsStorageKey, JSON.stringify(tokenResponse));
|
||||
this.authenticationInterceptor.setAuthorizationToken(tokenResponse.access_token);
|
||||
@@ -173,7 +182,7 @@ export class AuthenticationService {
|
||||
this.storage.setItem(this.credentialsStorageKey, JSON.stringify(credentials));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the authorization token followed by one of the following:
|
||||
*
|
||||
@@ -193,14 +202,23 @@ export class AuthenticationService {
|
||||
}
|
||||
if (credentials.isTwoFactorAuthenticationRequired) {
|
||||
this.credentials = credentials;
|
||||
this.alertService.alert({ type: 'Two Factor Authentication Required', message: 'Two Factor Authentication Required' });
|
||||
this.alertService.alert({
|
||||
type: 'Two Factor Authentication Required',
|
||||
message: 'Two Factor Authentication Required'
|
||||
});
|
||||
} else {
|
||||
if (credentials.shouldRenewPassword) {
|
||||
this.credentials = credentials;
|
||||
this.alertService.alert({ type: 'Password Expired', message: 'Your password has expired, please reset your password!' });
|
||||
this.alertService.alert({
|
||||
type: 'Password Expired',
|
||||
message: 'Your password has expired, please reset your password!'
|
||||
});
|
||||
} else {
|
||||
this.setCredentials(credentials);
|
||||
this.alertService.alert({ type: 'Authentication Success', message: `${credentials.username} successfully logged in!` });
|
||||
this.alertService.alert({
|
||||
type: 'Authentication Success',
|
||||
message: `${credentials.username} successfully logged in!`
|
||||
});
|
||||
delete this.credentials;
|
||||
}
|
||||
}
|
||||
@@ -211,15 +229,18 @@ export class AuthenticationService {
|
||||
*/
|
||||
private logoutAuthSession() {
|
||||
const oAuthRefreshToken = JSON.parse(this.storage.getItem(this.oAuthTokenDetailsStorageKey)).refresh_token;
|
||||
const credentials = JSON.parse(this.storage.getItem(this.credentialsStorageKey));
|
||||
this.authenticationInterceptor.removeAuthorizationTenant();
|
||||
let httpParams = new HttpParams();
|
||||
const credentials = JSON.parse(this.storage.getItem(this.credentialsStorageKey));
|
||||
this.authenticationInterceptor.removeAuthorizationTenant();
|
||||
let httpParams = new HttpParams();
|
||||
httpParams = httpParams.set('username', credentials.username);
|
||||
httpParams = httpParams.set('client_id', `${environment.oauth.appId}`);
|
||||
httpParams = httpParams.set('refresh_token', oAuthRefreshToken);
|
||||
let headers = new HttpHeaders();
|
||||
headers = headers.set('Content-Type', 'application/x-www-form-urlencoded')
|
||||
return this.http.disableApiPrefix().post(`${environment.oauth.serverUrl}/logout`, httpParams.toString(), {headers: headers}).subscribe();
|
||||
headers = headers.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
return this.http
|
||||
.disableApiPrefix()
|
||||
.post(`${environment.oauth.serverUrl}/logout`, httpParams.toString(), { headers: headers })
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,7 +271,7 @@ export class AuthenticationService {
|
||||
twoFactorAccessTokenIsValid(): boolean {
|
||||
const twoFactorAccessToken = JSON.parse(this.storage.getItem(this.twoFactorAuthenticationTokenStorageKey));
|
||||
if (twoFactorAccessToken) {
|
||||
return ((new Date()).getTime() < twoFactorAccessToken.validTo);
|
||||
return new Date().getTime() < twoFactorAccessToken.validTo;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -260,9 +281,11 @@ export class AuthenticationService {
|
||||
* @returns {boolean} True if the user is authenticated.
|
||||
*/
|
||||
isAuthenticated(): boolean {
|
||||
return !!(JSON.parse(
|
||||
return !!(
|
||||
JSON.parse(
|
||||
sessionStorage.getItem(this.credentialsStorageKey) || localStorage.getItem(this.credentialsStorageKey)
|
||||
) && this.twoFactorAccessTokenIsValid());
|
||||
) && this.twoFactorAccessTokenIsValid()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -333,12 +356,11 @@ export class AuthenticationService {
|
||||
*/
|
||||
validateOTP(otp: string) {
|
||||
const httpParams = new HttpParams().set('token', otp);
|
||||
return this.http.post(`/twofactor/validate`, {}, { params: httpParams })
|
||||
.pipe(
|
||||
map(response => {
|
||||
this.onOTPValidateSuccess(response);
|
||||
})
|
||||
);
|
||||
return this.http.post(`/twofactor/validate`, {}, { params: httpParams }).pipe(
|
||||
map((response) => {
|
||||
this.onOTPValidateSuccess(response);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,10 +374,16 @@ export class AuthenticationService {
|
||||
private onOTPValidateSuccess(response: any) {
|
||||
this.authenticationInterceptor.setTwoFactorAccessToken(response.token);
|
||||
if (this.credentials.shouldRenewPassword) {
|
||||
this.alertService.alert({ type: 'Password Expired', message: 'Your password has expired, please reset your password!' });
|
||||
this.alertService.alert({
|
||||
type: 'Password Expired',
|
||||
message: 'Your password has expired, please reset your password!'
|
||||
});
|
||||
} else {
|
||||
this.setCredentials(this.credentials);
|
||||
this.alertService.alert({ type: 'Authentication Success', message: `${this.credentials.username} successfully logged in!` });
|
||||
this.alertService.alert({
|
||||
type: 'Authentication Success',
|
||||
message: `${this.credentials.username} successfully logged in!`
|
||||
});
|
||||
delete this.credentials;
|
||||
this.storage.setItem(this.twoFactorAuthenticationTokenStorageKey, JSON.stringify(response));
|
||||
}
|
||||
@@ -366,8 +394,7 @@ export class AuthenticationService {
|
||||
* @param {any} passwordDetails New password.
|
||||
*/
|
||||
resetPassword(passwordDetails: any) {
|
||||
return this.http.put(`/users/${this.credentials.userId}`, passwordDetails).
|
||||
pipe(
|
||||
return this.http.put(`/users/${this.credentials.userId}`, passwordDetails).pipe(
|
||||
map(() => {
|
||||
this.alertService.alert({ type: 'Password Reset Success', message: `Your password was sucessfully reset!` });
|
||||
this.authenticationInterceptor.removeAuthorization();
|
||||
@@ -388,5 +415,4 @@ export class AuthenticationService {
|
||||
getUserLoggedIn(): boolean {
|
||||
return this.userLoggedIn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import { ToolbarComponent } from './shell/toolbar/toolbar.component';
|
||||
import { BreadcrumbComponent } from './shell/breadcrumb/breadcrumb.component';
|
||||
import { ContentComponent } from './shell/content/content.component';
|
||||
|
||||
|
||||
/**
|
||||
* Core Module
|
||||
*
|
||||
@@ -57,6 +56,7 @@ import { ContentComponent } from './shell/content/content.component';
|
||||
],
|
||||
exports: [
|
||||
SharedModule // TO BE REMOVED: Once all components have replaced the core module import by shared module.
|
||||
|
||||
],
|
||||
providers: [
|
||||
AuthenticationService,
|
||||
@@ -88,12 +88,10 @@ import { ContentComponent } from './shell/content/content.component';
|
||||
]
|
||||
})
|
||||
export class CoreModule {
|
||||
|
||||
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
|
||||
// Import guard
|
||||
if (parentModule) {
|
||||
throw new Error(`${parentModule} has already been loaded. Import Core module in the AppModule only.`);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Injectable } from '@angular/core';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class Dialogs {
|
||||
constructor() { }
|
||||
constructor() {}
|
||||
|
||||
public setColor(dataType: string): string {
|
||||
let color = 'primary';
|
||||
@@ -23,5 +23,4 @@ export class Dialogs {
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export class ApiPrefixInterceptor implements HttpInterceptor {
|
||||
/**
|
||||
* @param {SettingsService} settingsService Settings Service
|
||||
*/
|
||||
constructor(private settingsService: SettingsService) { }
|
||||
constructor(private settingsService: SettingsService) {}
|
||||
|
||||
/**
|
||||
* Intercepts a Http request and prefixes it with `serverUrl`.
|
||||
@@ -40,5 +40,4 @@ export class ApiPrefixInterceptor implements HttpInterceptor {
|
||||
}
|
||||
return next.handle(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,10 +14,9 @@ import { HttpCacheService } from './http-cache.service';
|
||||
*/
|
||||
@Injectable()
|
||||
export class CacheInterceptor implements HttpInterceptor {
|
||||
|
||||
private forceUpdate = false;
|
||||
|
||||
constructor(private httpCacheService: HttpCacheService) { }
|
||||
constructor(private httpCacheService: HttpCacheService) {}
|
||||
|
||||
/**
|
||||
* Configures interceptor options
|
||||
@@ -44,19 +43,17 @@ export class CacheInterceptor implements HttpInterceptor {
|
||||
subscriber.next(new HttpResponse(cachedData as Object));
|
||||
subscriber.complete();
|
||||
} else {
|
||||
next.handle(request)
|
||||
.subscribe(
|
||||
event => {
|
||||
if (event instanceof HttpResponse) {
|
||||
this.httpCacheService.setCacheData(request.urlWithParams, event);
|
||||
}
|
||||
subscriber.next(event);
|
||||
},
|
||||
error => subscriber.error(error),
|
||||
() => subscriber.complete()
|
||||
);
|
||||
next.handle(request).subscribe(
|
||||
(event) => {
|
||||
if (event instanceof HttpResponse) {
|
||||
this.httpCacheService.setCacheData(request.urlWithParams, event);
|
||||
}
|
||||
subscriber.next(event);
|
||||
},
|
||||
(error) => subscriber.error(error),
|
||||
() => subscriber.complete()
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,17 +21,16 @@ const log = new Logger('ErrorHandlerInterceptor');
|
||||
*/
|
||||
@Injectable()
|
||||
export class ErrorHandlerInterceptor implements HttpInterceptor {
|
||||
|
||||
/**
|
||||
* @param {AlertService} alertService Alert Service.
|
||||
*/
|
||||
constructor(private alertService: AlertService) { }
|
||||
constructor(private alertService: AlertService) {}
|
||||
|
||||
/**
|
||||
* Intercepts a Http request and adds a default error handler.
|
||||
*/
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
return next.handle(request).pipe(catchError(error => this.handleError(error)));
|
||||
return next.handle(request).pipe(catchError((error) => this.handleError(error)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,7 +38,7 @@ export class ErrorHandlerInterceptor implements HttpInterceptor {
|
||||
*/
|
||||
private handleError(response: HttpErrorResponse): Observable<HttpEvent<any>> {
|
||||
const status = response.status;
|
||||
let errorMessage = (response.error.developerMessage || response.message);
|
||||
let errorMessage = response.error.developerMessage || response.message;
|
||||
if (response.error.errors) {
|
||||
if (response.error.errors[0]) {
|
||||
errorMessage = response.error.errors[0].defaultUserMessage || response.error.errors[0].developerMessage;
|
||||
@@ -55,18 +54,26 @@ export class ErrorHandlerInterceptor implements HttpInterceptor {
|
||||
} else if (status === 403 && errorMessage === 'The provided one time token is invalid') {
|
||||
this.alertService.alert({ type: 'Invalid Token', message: 'Invalid Token. Please try again!' });
|
||||
} else if (status === 400) {
|
||||
this.alertService.alert({ type: 'Bad Request', message: errorMessage || 'Invalid parameters were passed in the request!' });
|
||||
this.alertService.alert({
|
||||
type: 'Bad Request',
|
||||
message: errorMessage || 'Invalid parameters were passed in the request!'
|
||||
});
|
||||
} else if (status === 403) {
|
||||
this.alertService.alert({ type: 'Unauthorized Request', message: errorMessage || 'You are not authorized for this request!' });
|
||||
this.alertService.alert({
|
||||
type: 'Unauthorized Request',
|
||||
message: errorMessage || 'You are not authorized for this request!'
|
||||
});
|
||||
} else if (status === 404) {
|
||||
this.alertService.alert({ type: 'Resource does not exist', message: errorMessage || 'Resource does not exist!' });
|
||||
} else if (status === 500) {
|
||||
this.alertService.alert({ type: 'Internal Server Error', message: 'Internal Server Error. Please try again later.' });
|
||||
} else if (status === 500) {
|
||||
this.alertService.alert({
|
||||
type: 'Internal Server Error',
|
||||
message: 'Internal Server Error. Please try again later.'
|
||||
});
|
||||
} else {
|
||||
this.alertService.alert({ type: 'Unknown Error', message: 'Unknown Error. Please try again later.' });
|
||||
}
|
||||
|
||||
throw response;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,11 +22,10 @@ export interface HttpCacheEntry {
|
||||
*/
|
||||
@Injectable()
|
||||
export class HttpCacheService {
|
||||
|
||||
/** Key to cache Http Requests in storage. */
|
||||
private cachePersistenceStorageKey = 'mifosXHttpCache';
|
||||
|
||||
private cachedData: { [key: string]: HttpCacheEntry; } = {};
|
||||
private cachedData: { [key: string]: HttpCacheEntry } = {};
|
||||
private storage: Storage | null = null;
|
||||
|
||||
constructor() {
|
||||
@@ -122,5 +121,4 @@ export class HttpCacheService {
|
||||
const data = this.storage ? this.storage[this.cachePersistenceStorageKey] : null;
|
||||
this.cachedData = data ? JSON.parse(data) : {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,13 +15,11 @@ import { ApiPrefixInterceptor } from './api-prefix.interceptor';
|
||||
* (see https://github.com/Microsoft/TypeScript/issues/13897)
|
||||
*/
|
||||
declare module '@angular/common/http' {
|
||||
|
||||
/**
|
||||
* Augment HttpClient with the added configuration methods from HttpService, to allow in-place replacement of
|
||||
* HttpClient with HttpService using dependency injection.
|
||||
*/
|
||||
export interface HttpClient {
|
||||
|
||||
/**
|
||||
* Enables caching for this request.
|
||||
* @param {boolean} forceUpdate Forces request to be made and updates cache entry.
|
||||
@@ -40,22 +38,21 @@ declare module '@angular/common/http' {
|
||||
* @returns {HttpClient} The new instance.
|
||||
*/
|
||||
disableApiPrefix(): HttpClient;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* From @angular/common/http/src/interceptor: allows to chain interceptors
|
||||
*/
|
||||
class HttpInterceptorHandler implements HttpHandler {
|
||||
|
||||
constructor(private next: HttpHandler, private interceptor: HttpInterceptor) { }
|
||||
constructor(
|
||||
private next: HttpHandler,
|
||||
private interceptor: HttpInterceptor
|
||||
) {}
|
||||
|
||||
handle(request: HttpRequest<any>): Observable<HttpEvent<any>> {
|
||||
return this.interceptor.intercept(request, this.next);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,18 +70,18 @@ export const HTTP_DYNAMIC_INTERCEPTORS = new InjectionToken<HttpInterceptor>('HT
|
||||
*/
|
||||
@Injectable()
|
||||
export class HttpService extends HttpClient {
|
||||
|
||||
constructor(private httpHandler: HttpHandler,
|
||||
private injector: Injector,
|
||||
@Optional() @Inject(HTTP_DYNAMIC_INTERCEPTORS) private interceptors: HttpInterceptor[] = []) {
|
||||
constructor(
|
||||
private httpHandler: HttpHandler,
|
||||
private injector: Injector,
|
||||
@Optional() @Inject(HTTP_DYNAMIC_INTERCEPTORS) private interceptors: HttpInterceptor[] = []
|
||||
) {
|
||||
super(httpHandler);
|
||||
|
||||
if (!this.interceptors) {
|
||||
// Configure default interceptors that can be disabled here
|
||||
this.interceptors = [
|
||||
this.injector.get(ApiPrefixInterceptor),
|
||||
this.injector.get(ErrorHandlerInterceptor)
|
||||
];
|
||||
this.injector.get(ErrorHandlerInterceptor)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,16 +113,11 @@ export class HttpService extends HttpClient {
|
||||
return new HttpService(
|
||||
this.httpHandler,
|
||||
this.injector,
|
||||
this.interceptors.filter(i => !(i instanceof interceptorType))
|
||||
this.interceptors.filter((i) => !(i instanceof interceptorType))
|
||||
);
|
||||
}
|
||||
|
||||
private addInterceptor(interceptor: HttpInterceptor): HttpService {
|
||||
return new HttpService(
|
||||
this.httpHandler,
|
||||
this.injector,
|
||||
this.interceptors.concat([interceptor])
|
||||
);
|
||||
return new HttpService(this.httpHandler, this.injector, this.interceptors.concat([interceptor]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,11 +7,9 @@ import { Observable } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class I18nService {
|
||||
|
||||
constructor(private translateService: TranslateService) { }
|
||||
constructor(private translateService: TranslateService) {}
|
||||
|
||||
public translate(key: string): Observable<string> {
|
||||
return this.translateService.get(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ export enum LogLevel {
|
||||
export type LogOutput = (source: string, level: LogLevel, ...objects: any[]) => void;
|
||||
|
||||
export class Logger {
|
||||
|
||||
/**
|
||||
* Current logging level.
|
||||
* Set it to LogLevel.Off to disable logs completely.
|
||||
@@ -68,7 +67,7 @@ export class Logger {
|
||||
Logger.level = LogLevel.Warning;
|
||||
}
|
||||
|
||||
constructor(private source?: string) { }
|
||||
constructor(private source?: string) {}
|
||||
|
||||
/**
|
||||
* Logs messages or objects with the debug level.
|
||||
@@ -106,8 +105,15 @@ export class Logger {
|
||||
if (level <= Logger.level) {
|
||||
const log = this.source ? ['[' + this.source + ']'].concat(objects) : objects;
|
||||
func.apply(console, log);
|
||||
Logger.outputs.forEach((output) => output.apply(output, [this.source, level].concat(objects)));
|
||||
Logger.outputs.forEach((output) =>
|
||||
output.apply(
|
||||
output,
|
||||
[
|
||||
this.source,
|
||||
level
|
||||
].concat(objects)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { Injectable, EventEmitter } from '@angular/core';
|
||||
*/
|
||||
@Injectable()
|
||||
export class ProgressBarService {
|
||||
|
||||
/** Progress bar update event. */
|
||||
public updateProgressBar: EventEmitter<any>;
|
||||
/** Denotes the number of requests currently running. */
|
||||
@@ -50,5 +49,4 @@ export class ProgressBarService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** Angular Imports */
|
||||
import { Injectable } from '@angular/core';
|
||||
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
|
||||
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
|
||||
|
||||
/** rxjs Imports */
|
||||
import { Observable } from 'rxjs';
|
||||
@@ -14,11 +14,10 @@ import { ProgressBarService } from './progress-bar.service';
|
||||
*/
|
||||
@Injectable()
|
||||
export class ProgressInterceptor implements HttpInterceptor {
|
||||
|
||||
/**
|
||||
* @param {ProgressBarService} progressBarService Progress Bar Service.
|
||||
*/
|
||||
constructor(private progressBarService: ProgressBarService) { }
|
||||
constructor(private progressBarService: ProgressBarService) {}
|
||||
|
||||
/**
|
||||
* Intercepts a Http request to start loading the progress bar for a pending request
|
||||
@@ -26,12 +25,10 @@ export class ProgressInterceptor implements HttpInterceptor {
|
||||
*/
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
this.progressBarService.increase();
|
||||
return next.handle(request)
|
||||
.pipe(
|
||||
finalize(
|
||||
() => { this.progressBarService.decrease(); }
|
||||
)
|
||||
);
|
||||
return next.handle(request).pipe(
|
||||
finalize(() => {
|
||||
this.progressBarService.decrease();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,12 +9,11 @@ import { Injectable } from '@angular/core';
|
||||
*/
|
||||
@Injectable()
|
||||
export class RouteReusableStrategy extends RouteReuseStrategy {
|
||||
|
||||
public shouldDetach(route: ActivatedRouteSnapshot): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
public store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle | null): void { }
|
||||
public store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle | null): void {}
|
||||
|
||||
public shouldAttach(route: ActivatedRouteSnapshot): boolean {
|
||||
return false;
|
||||
@@ -25,7 +24,6 @@ export class RouteReusableStrategy extends RouteReuseStrategy {
|
||||
}
|
||||
|
||||
public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
|
||||
return (future.routeConfig === curr.routeConfig) || future.data.reuse;
|
||||
return future.routeConfig === curr.routeConfig || future.data.reuse;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import { AuthenticationGuard } from '../authentication/authentication.guard';
|
||||
* Provides helper methods to create routes.
|
||||
*/
|
||||
export class Route {
|
||||
|
||||
/**
|
||||
* Creates routes using the shell component and authentication.
|
||||
* @param routes The routes to add.
|
||||
@@ -22,10 +21,9 @@ export class Route {
|
||||
path: '',
|
||||
component: ShellComponent,
|
||||
children: routes,
|
||||
canActivate: [AuthenticationGuard],
|
||||
canActivate: [AuthenticationGuard]
|
||||
// Reuse ShellComponent instance when navigating between child views
|
||||
// data: { reuse: true }
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,9 +8,8 @@ describe('BreadcrumbComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BreadcrumbComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
declarations: [BreadcrumbComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/** Angular Imports */
|
||||
import { Component, TemplateRef, ElementRef , ViewChild, AfterViewInit} from '@angular/core';
|
||||
import { Component, TemplateRef, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router, NavigationEnd, Data } from '@angular/router';
|
||||
|
||||
/** rxjs Imports */
|
||||
@@ -51,7 +51,6 @@ const routeAddBreadcrumbLink = 'addBreadcrumbLink';
|
||||
styleUrls: ['./breadcrumb.component.scss']
|
||||
})
|
||||
export class BreadcrumbComponent implements AfterViewInit {
|
||||
|
||||
/** Array of breadcrumbs. */
|
||||
breadcrumbs: Breadcrumb[];
|
||||
/* Reference of breadcrumb */
|
||||
@@ -66,11 +65,13 @@ export class BreadcrumbComponent implements AfterViewInit {
|
||||
* @param {ConfigurationWizardService} configurationWizardService ConfigurationWizard Service.
|
||||
* @param {PopoverService} popoverService PopoverService.
|
||||
*/
|
||||
constructor(private activatedRoute: ActivatedRoute,
|
||||
private router: Router,
|
||||
private configurationWizardService: ConfigurationWizardService,
|
||||
private popoverService: PopoverService,
|
||||
private translateService: TranslateService) {
|
||||
constructor(
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private router: Router,
|
||||
private configurationWizardService: ConfigurationWizardService,
|
||||
private popoverService: PopoverService,
|
||||
private translateService: TranslateService
|
||||
) {
|
||||
this.generateBreadcrumbs();
|
||||
}
|
||||
|
||||
@@ -78,7 +79,7 @@ export class BreadcrumbComponent implements AfterViewInit {
|
||||
* Generates the array of breadcrumbs for the visited route.
|
||||
*/
|
||||
generateBreadcrumbs() {
|
||||
const onNavigationEnd = this.router.events.pipe(filter(event => event instanceof NavigationEnd));
|
||||
const onNavigationEnd = this.router.events.pipe(filter((event) => event instanceof NavigationEnd));
|
||||
|
||||
onNavigationEnd.subscribe(() => {
|
||||
this.breadcrumbs = [];
|
||||
@@ -90,7 +91,7 @@ export class BreadcrumbComponent implements AfterViewInit {
|
||||
let breadcrumbLabel: any;
|
||||
let url: any;
|
||||
|
||||
childrenRoutes.forEach(route => {
|
||||
childrenRoutes.forEach((route) => {
|
||||
currentRoute = route;
|
||||
breadcrumbLabel = false;
|
||||
|
||||
@@ -98,22 +99,28 @@ export class BreadcrumbComponent implements AfterViewInit {
|
||||
return;
|
||||
}
|
||||
|
||||
const routeURL = route.snapshot.url.map(segment => segment.path).join('/');
|
||||
const routeURL = route.snapshot.url.map((segment) => segment.path).join('/');
|
||||
currentUrl += `/${routeURL}`;
|
||||
|
||||
if (currentUrl === '/') {
|
||||
breadcrumbLabel = 'Home';
|
||||
}
|
||||
|
||||
const hasData = (route.routeConfig && route.routeConfig.data);
|
||||
const hasData = route.routeConfig && route.routeConfig.data;
|
||||
|
||||
if (hasData) {
|
||||
if (route.snapshot.data.hasOwnProperty(routeResolveBreadcrumb) && route.snapshot.data[routeResolveBreadcrumb]) {
|
||||
if (
|
||||
route.snapshot.data.hasOwnProperty(routeResolveBreadcrumb) &&
|
||||
route.snapshot.data[routeResolveBreadcrumb]
|
||||
) {
|
||||
breadcrumbLabel = route.snapshot.data;
|
||||
route.snapshot.data[routeResolveBreadcrumb].forEach((property: any) => {
|
||||
breadcrumbLabel = breadcrumbLabel[property];
|
||||
});
|
||||
} else if (route.snapshot.data.hasOwnProperty(routeParamBreadcrumb) && route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb])) {
|
||||
} else if (
|
||||
route.snapshot.data.hasOwnProperty(routeParamBreadcrumb) &&
|
||||
route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb])
|
||||
) {
|
||||
breadcrumbLabel = route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb]);
|
||||
const routeData: Data = route.snapshot.data;
|
||||
if (routeData.breadcrumb === 'Clients') {
|
||||
@@ -124,11 +131,23 @@ export class BreadcrumbComponent implements AfterViewInit {
|
||||
} else if (routeData.breadcrumb === 'Centers') {
|
||||
breadcrumbLabel = routeData.centerViewData.name;
|
||||
} else if (routeData.breadcrumb === 'Loans') {
|
||||
breadcrumbLabel = this.printableValue(routeData.loanDetailsData.loanProductName) + ' (' + routeData.loanDetailsData.accountNo + ')';
|
||||
breadcrumbLabel =
|
||||
this.printableValue(routeData.loanDetailsData.loanProductName) +
|
||||
' (' +
|
||||
routeData.loanDetailsData.accountNo +
|
||||
')';
|
||||
} else if (routeData.breadcrumb === 'Savings') {
|
||||
breadcrumbLabel = this.printableValue(routeData.savingsAccountData.savingsProductName) + ' (' + routeData.savingsAccountData.accountNo + ')';
|
||||
breadcrumbLabel =
|
||||
this.printableValue(routeData.savingsAccountData.savingsProductName) +
|
||||
' (' +
|
||||
routeData.savingsAccountData.accountNo +
|
||||
')';
|
||||
} else if (routeData.breadcrumb === 'Fixed Deposits') {
|
||||
breadcrumbLabel = this.printableValue(routeData.fixedDepositsAccountData.depositProductName) + ' (' + routeData.fixedDepositsAccountData.accountNo + ')';
|
||||
breadcrumbLabel =
|
||||
this.printableValue(routeData.fixedDepositsAccountData.depositProductName) +
|
||||
' (' +
|
||||
routeData.fixedDepositsAccountData.accountNo +
|
||||
')';
|
||||
} else if (routeData.breadcrumb === 'Loan Products') {
|
||||
breadcrumbLabel = this.printableValue(routeData.loanProduct.name);
|
||||
} else if (routeData.breadcrumb === 'Charges') {
|
||||
@@ -159,7 +178,7 @@ export class BreadcrumbComponent implements AfterViewInit {
|
||||
}
|
||||
}
|
||||
if (url !== undefined) {
|
||||
if (url.length > 8 && url.search(`/clients/`) > 0 ) {
|
||||
if (url.length > 8 && url.search(`/clients/`) > 0) {
|
||||
const replaceGeneral = `/general/`;
|
||||
let currentUrlTemp = url.replace(replaceGeneral, `/`);
|
||||
currentUrlTemp = currentUrlTemp.replace(`//`, `/`);
|
||||
@@ -197,7 +216,12 @@ export class BreadcrumbComponent implements AfterViewInit {
|
||||
* @param position String.
|
||||
* @param backdrop Boolean.
|
||||
*/
|
||||
showPopover(template: TemplateRef<any>, target: HTMLElement | ElementRef<any>, position: string, backdrop: boolean): void {
|
||||
showPopover(
|
||||
template: TemplateRef<any>,
|
||||
target: HTMLElement | ElementRef<any>,
|
||||
position: string,
|
||||
backdrop: boolean
|
||||
): void {
|
||||
setTimeout(() => this.popoverService.open(template, target, position, backdrop, {}), 200);
|
||||
}
|
||||
|
||||
@@ -206,7 +230,7 @@ export class BreadcrumbComponent implements AfterViewInit {
|
||||
*/
|
||||
ngAfterViewInit() {
|
||||
if (this.configurationWizardService.showBreadcrumbs === true) {
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
this.showPopover(this.templateBreadcrumb, this.breadcrumb.nativeElement, 'bottom', true);
|
||||
});
|
||||
}
|
||||
@@ -237,8 +261,7 @@ export class BreadcrumbComponent implements AfterViewInit {
|
||||
getTranslate(text: string): any {
|
||||
const key: string = 'labels.text.' + text;
|
||||
const translation = this.translateService.instant(key);
|
||||
const result = (translation !== key) ? translation : text;
|
||||
const result = translation !== key ? translation : text;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,9 +8,8 @@ describe('ContentComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ContentComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
declarations: [ContentComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -10,7 +10,5 @@ import { Component } from '@angular/core';
|
||||
styleUrls: ['./content.component.scss']
|
||||
})
|
||||
export class ContentComponent {
|
||||
|
||||
constructor() { }
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,8 @@ describe('ShellComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ShellComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
declarations: [ShellComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -18,12 +18,10 @@ import { ProgressBarService } from '../progress-bar/progress-bar.service';
|
||||
styleUrls: ['./shell.component.scss']
|
||||
})
|
||||
export class ShellComponent implements OnInit, OnDestroy {
|
||||
|
||||
/** Subscription to breakpoint observer for handset. */
|
||||
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
|
||||
.pipe(
|
||||
map(result => result.matches)
|
||||
);
|
||||
isHandset$: Observable<boolean> = this.breakpointObserver
|
||||
.observe(Breakpoints.Handset)
|
||||
.pipe(map((result) => result.matches));
|
||||
/** Sets the initial state of sidenav as collapsed. Not collapsed if false. */
|
||||
sidenavCollapsed = true;
|
||||
/** Progress bar mode. */
|
||||
@@ -36,9 +34,11 @@ export class ShellComponent implements OnInit, OnDestroy {
|
||||
* @param {ProgressBarService} progressBarService Progress Bar Service.
|
||||
* @param {ChangeDetectorRef} cdr Change Detector Ref.
|
||||
*/
|
||||
constructor(private breakpointObserver: BreakpointObserver,
|
||||
private progressBarService: ProgressBarService,
|
||||
private cdr: ChangeDetectorRef) { }
|
||||
constructor(
|
||||
private breakpointObserver: BreakpointObserver,
|
||||
private progressBarService: ProgressBarService,
|
||||
private cdr: ChangeDetectorRef
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Subscribes to progress bar to update its mode.
|
||||
@@ -67,5 +67,4 @@ export class ShellComponent implements OnInit, OnDestroy {
|
||||
this.progressBar$.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,5 +53,5 @@ export const frequentActivities: any[] = [
|
||||
path: '/self-service',
|
||||
icon: 'laptop',
|
||||
toolTip: 'Self Service'
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
@@ -8,9 +8,8 @@ describe('SidenavComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SidenavComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
declarations: [SidenavComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/** Angular Imports */
|
||||
import { Component, OnInit, Input, TemplateRef, ElementRef , ViewChild,
|
||||
AfterViewInit } from '@angular/core';
|
||||
import { Component, OnInit, Input, TemplateRef, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@@ -25,7 +24,6 @@ import { SettingsService } from 'app/settings/settings.service';
|
||||
styleUrls: ['./sidenav.component.scss']
|
||||
})
|
||||
export class SidenavComponent implements OnInit, AfterViewInit {
|
||||
|
||||
/** True if sidenav is in collapsed state. */
|
||||
@Input() sidenavCollapsed: boolean;
|
||||
/** Tooltip position */
|
||||
@@ -48,7 +46,6 @@ export class SidenavComponent implements OnInit, AfterViewInit {
|
||||
/* Template for popover on chart of accounts */
|
||||
@ViewChild('templateChartOfAccounts') templateChartOfAccounts: TemplateRef<any>;
|
||||
|
||||
|
||||
/**
|
||||
* @param {Router} router Router for navigation.
|
||||
* @param {MatDialog} dialog Mat Dialog
|
||||
@@ -57,12 +54,14 @@ export class SidenavComponent implements OnInit, AfterViewInit {
|
||||
* @param {ConfigurationWizardService} configurationWizardService ConfigurationWizard Service.
|
||||
* @param {PopoverService} popoverService PopoverService.
|
||||
*/
|
||||
constructor(private router: Router,
|
||||
public dialog: MatDialog,
|
||||
private authenticationService: AuthenticationService,
|
||||
private settingsService: SettingsService,
|
||||
private configurationWizardService: ConfigurationWizardService,
|
||||
private popoverService: PopoverService) {
|
||||
constructor(
|
||||
private router: Router,
|
||||
public dialog: MatDialog,
|
||||
private authenticationService: AuthenticationService,
|
||||
private settingsService: SettingsService,
|
||||
private configurationWizardService: ConfigurationWizardService,
|
||||
private popoverService: PopoverService
|
||||
) {
|
||||
this.userActivity = JSON.parse(localStorage.getItem('mifosXLocation'));
|
||||
}
|
||||
|
||||
@@ -79,8 +78,7 @@ export class SidenavComponent implements OnInit, AfterViewInit {
|
||||
* Logs out the authenticated user and redirects to login page.
|
||||
*/
|
||||
logout() {
|
||||
this.authenticationService.logout()
|
||||
.subscribe(() => this.router.navigate(['/login'], { replaceUrl: true }));
|
||||
this.authenticationService.logout().subscribe(() => this.router.navigate(['/login'], { replaceUrl: true }));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,18 +100,24 @@ export class SidenavComponent implements OnInit, AfterViewInit {
|
||||
* Returns top three frequent activities.
|
||||
*/
|
||||
getFrequentActivities() {
|
||||
const frequencyCounts: any = {};
|
||||
let index = this.userActivity.length;
|
||||
const frequencyCounts: any = {};
|
||||
let index = this.userActivity.length;
|
||||
while (index) {
|
||||
frequencyCounts[this.userActivity[--index]] = (frequencyCounts[this.userActivity[index]] || 0) + 1;
|
||||
}
|
||||
const frequencyCountsArray = Object.entries(frequencyCounts);
|
||||
const topThreeFrequentActivities =
|
||||
frequencyCountsArray
|
||||
.sort((a: any, b: any) => b[1] - a[1])
|
||||
.map((entry: any[]) => entry[0])
|
||||
.filter((activity: string) => !['/', '/login', '/home', '/dashboard'].includes(activity))
|
||||
.slice(0, 3);
|
||||
const topThreeFrequentActivities = frequencyCountsArray
|
||||
.sort((a: any, b: any) => b[1] - a[1])
|
||||
.map((entry: any[]) => entry[0])
|
||||
.filter(
|
||||
(activity: string) => ![
|
||||
'/',
|
||||
'/login',
|
||||
'/home',
|
||||
'/dashboard'
|
||||
].includes(activity)
|
||||
)
|
||||
.slice(0, 3);
|
||||
return topThreeFrequentActivities;
|
||||
}
|
||||
|
||||
@@ -168,7 +172,12 @@ export class SidenavComponent implements OnInit, AfterViewInit {
|
||||
* @param position String.
|
||||
* @param backdrop Boolean.
|
||||
*/
|
||||
showPopover(template: TemplateRef<any>, target: HTMLElement | ElementRef<any>, position: string, backdrop: boolean): void {
|
||||
showPopover(
|
||||
template: TemplateRef<any>,
|
||||
target: HTMLElement | ElementRef<any>,
|
||||
position: string,
|
||||
backdrop: boolean
|
||||
): void {
|
||||
setTimeout(() => this.popoverService.open(template, target, position, backdrop, {}), 200);
|
||||
}
|
||||
|
||||
@@ -178,12 +187,12 @@ export class SidenavComponent implements OnInit, AfterViewInit {
|
||||
ngAfterViewInit() {
|
||||
if (this.configurationWizardService.showSideNav === true) {
|
||||
setTimeout(() => {
|
||||
this.showPopover(this.templateLogo, this.logo.nativeElement, 'bottom', true);
|
||||
this.showPopover(this.templateLogo, this.logo.nativeElement, 'bottom', true);
|
||||
});
|
||||
}
|
||||
if (this.configurationWizardService.showSideNavChartofAccounts === true) {
|
||||
setTimeout(() => {
|
||||
this.showPopover(this.templateChartOfAccounts, this.chartOfAccounts.nativeElement, 'top', true);
|
||||
this.showPopover(this.templateChartOfAccounts, this.chartOfAccounts.nativeElement, 'top', true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -218,5 +227,4 @@ export class SidenavComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
return this.settingsService.tenantIdentifier;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,9 +8,8 @@ describe('ToolbarComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ToolbarComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
declarations: [ToolbarComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
/** Angular Imports */
|
||||
import { Component, OnInit, Input, EventEmitter, Output, ViewChild, AfterViewInit, ElementRef, TemplateRef, AfterContentChecked, ChangeDetectorRef } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
EventEmitter,
|
||||
Output,
|
||||
ViewChild,
|
||||
AfterViewInit,
|
||||
ElementRef,
|
||||
TemplateRef,
|
||||
AfterContentChecked,
|
||||
ChangeDetectorRef
|
||||
} from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatSidenav } from '@angular/material/sidenav';
|
||||
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
|
||||
@@ -26,7 +38,6 @@ import { ConfigurationWizardComponent } from '../../../configuration-wizard/conf
|
||||
styleUrls: ['./toolbar.component.scss']
|
||||
})
|
||||
export class ToolbarComponent implements OnInit, AfterViewInit, AfterContentChecked {
|
||||
|
||||
/* Reference of institution */
|
||||
@ViewChild('institution') institution: ElementRef<any>;
|
||||
/* Template for popover on institution */
|
||||
@@ -36,12 +47,10 @@ export class ToolbarComponent implements OnInit, AfterViewInit, AfterContentChec
|
||||
/* Template for popover on appMenu */
|
||||
@ViewChild('templateAppMenu') templateAppMenu: TemplateRef<any>;
|
||||
|
||||
|
||||
/** Subscription to breakpoint observer for handset. */
|
||||
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
|
||||
.pipe(
|
||||
map(result => result.matches)
|
||||
);
|
||||
isHandset$: Observable<boolean> = this.breakpointObserver
|
||||
.observe(Breakpoints.Handset)
|
||||
.pipe(map((result) => result.matches));
|
||||
|
||||
/** Sets the initial state of sidenav as collapsed. Not collapsed if false. */
|
||||
sidenavCollapsed = true;
|
||||
@@ -59,19 +68,21 @@ export class ToolbarComponent implements OnInit, AfterViewInit, AfterContentChec
|
||||
* @param {ConfigurationWizardService} configurationWizardService ConfigurationWizard Service.
|
||||
* @param {PopoverService} popoverService PopoverService.
|
||||
*/
|
||||
constructor(private breakpointObserver: BreakpointObserver,
|
||||
private router: Router,
|
||||
private authenticationService: AuthenticationService,
|
||||
private popoverService: PopoverService,
|
||||
private configurationWizardService: ConfigurationWizardService,
|
||||
private dialog: MatDialog,
|
||||
private changeDetector: ChangeDetectorRef) { }
|
||||
constructor(
|
||||
private breakpointObserver: BreakpointObserver,
|
||||
private router: Router,
|
||||
private authenticationService: AuthenticationService,
|
||||
private popoverService: PopoverService,
|
||||
private configurationWizardService: ConfigurationWizardService,
|
||||
private dialog: MatDialog,
|
||||
private changeDetector: ChangeDetectorRef
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Subscribes to breakpoint for handset.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.isHandset$.subscribe(isHandset => {
|
||||
this.isHandset$.subscribe((isHandset) => {
|
||||
if (isHandset && this.sidenavCollapsed) {
|
||||
this.toggleSidenavCollapse(false);
|
||||
}
|
||||
@@ -101,8 +112,7 @@ export class ToolbarComponent implements OnInit, AfterViewInit, AfterContentChec
|
||||
* Logs out the authenticated user and redirects to login page.
|
||||
*/
|
||||
logout() {
|
||||
this.authenticationService.logout()
|
||||
.subscribe(() => this.router.navigate(['/login'], { replaceUrl: true }));
|
||||
this.authenticationService.logout().subscribe(() => this.router.navigate(['/login'], { replaceUrl: true }));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,7 +177,6 @@ export class ToolbarComponent implements OnInit, AfterViewInit, AfterContentChec
|
||||
this.router.navigate(['/organization']);
|
||||
}
|
||||
if (response.show === 0) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -182,8 +191,11 @@ export class ToolbarComponent implements OnInit, AfterViewInit, AfterContentChec
|
||||
});
|
||||
}
|
||||
|
||||
if (this.configurationWizardService.showSideNav === true || this.configurationWizardService.showSideNavChartofAccounts === true) {
|
||||
this.toggleSidenavCollapse();
|
||||
if (
|
||||
this.configurationWizardService.showSideNav === true ||
|
||||
this.configurationWizardService.showSideNavChartofAccounts === true
|
||||
) {
|
||||
this.toggleSidenavCollapse();
|
||||
}
|
||||
|
||||
if (this.configurationWizardService.showToolbarAdmin === true) {
|
||||
@@ -196,5 +208,4 @@ export class ToolbarComponent implements OnInit, AfterViewInit, AfterContentChec
|
||||
navigateMenu(routePath: string): void {
|
||||
this.router.navigate([routePath]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,84 +2,99 @@ import { Injectable } from '@angular/core';
|
||||
import { AccountingMapping, GLAccount } from 'app/shared/models/general.model';
|
||||
import { OptionData } from 'app/shared/models/option-data.model';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class Accounting {
|
||||
public getAccountingRulesForShares(): string[] {
|
||||
return [
|
||||
'NONE',
|
||||
'Cash'
|
||||
];
|
||||
}
|
||||
|
||||
public getAccountingRulesForShares(): string[] {
|
||||
return ['NONE', 'Cash'];
|
||||
public getAccountingRulesForSavings(): string[] {
|
||||
return [
|
||||
'NONE',
|
||||
'Cash',
|
||||
'Accrual (periodic)'
|
||||
];
|
||||
}
|
||||
|
||||
public getAccountingRulesForLoans(): string[] {
|
||||
return [
|
||||
'NONE',
|
||||
'Cash',
|
||||
'Accrual (periodic)',
|
||||
'Accrual (upfront)'
|
||||
];
|
||||
}
|
||||
|
||||
public getAccountRuleName(value: string): string {
|
||||
if ([
|
||||
'ACCRUAL PERIODIC',
|
||||
'ACCRUAL (PERIODIC)'
|
||||
].includes(value)) {
|
||||
return 'Accrual (periodic)';
|
||||
} else if ([
|
||||
'ACCRUAL UPFRONT',
|
||||
'ACCRUAL (UPFRONT)'
|
||||
].includes(value)) {
|
||||
return 'Accrual (upfront)';
|
||||
} else if (value === 'CASH BASED') {
|
||||
return 'Cash';
|
||||
} else if (value === 'NONE') {
|
||||
return 'NONE';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public getAccountingRulesForSavings(): string[] {
|
||||
return ['NONE', 'Cash', 'Accrual (periodic)'];
|
||||
public isNoneAccounting(accountingRule: OptionData): boolean {
|
||||
return accountingRule.id === 1;
|
||||
}
|
||||
|
||||
public isNoneAccountingRuleId(accountingRuleId: number): boolean {
|
||||
return accountingRuleId === 1;
|
||||
}
|
||||
|
||||
public isCashOrAccrualAccounting(accountingRule: OptionData): boolean {
|
||||
return accountingRule.id === 2 || accountingRule.id === 3;
|
||||
}
|
||||
|
||||
public isCashOrAccrualAccountingRuleId(accountingRuleId: number): boolean {
|
||||
return accountingRuleId === 2 || accountingRuleId === 3;
|
||||
}
|
||||
|
||||
public isAccrualAccounting(accountingRule: OptionData): boolean {
|
||||
return accountingRule.id === 3;
|
||||
}
|
||||
|
||||
public isAccrualAccountingRuleId(accountingRuleId: number): boolean {
|
||||
return accountingRuleId === 3;
|
||||
}
|
||||
|
||||
public getAccountingRuleFrom(accountingRuleId: number): OptionData {
|
||||
if (accountingRuleId === 1) {
|
||||
return { code: 'NONE', id: accountingRuleId, value: 'None' };
|
||||
} else if (accountingRuleId === 2) {
|
||||
return { code: 'CASH', id: accountingRuleId, value: 'Cash' };
|
||||
} else if (accountingRuleId === 3) {
|
||||
return { code: 'ACCRUAL_PERIODIC', id: accountingRuleId, value: 'Accural (periodic)' };
|
||||
} else if (accountingRuleId === 4) {
|
||||
return { code: 'ACCRUAL_UPFRONT', id: accountingRuleId, value: 'Accural (upfront)' };
|
||||
}
|
||||
return { code: 'INVALID', id: accountingRuleId, value: 'Invalid' };
|
||||
}
|
||||
|
||||
public getAccountingRulesForLoans(): string[] {
|
||||
return ['NONE', 'Cash', 'Accrual (periodic)', 'Accrual (upfront)'];
|
||||
}
|
||||
|
||||
public getAccountRuleName(value: string): string {
|
||||
if (['ACCRUAL PERIODIC', 'ACCRUAL (PERIODIC)'].includes(value)) {
|
||||
return 'Accrual (periodic)';
|
||||
} else if (['ACCRUAL UPFRONT', 'ACCRUAL (UPFRONT)'].includes(value)) {
|
||||
return 'Accrual (upfront)';
|
||||
} else if (value === 'CASH BASED') {
|
||||
return 'Cash';
|
||||
} else if (value === 'NONE') {
|
||||
return 'NONE';
|
||||
public glAccountLookUp(glAccountId: number, glAccounts: GLAccount[]): AccountingMapping {
|
||||
let accountMapping: AccountingMapping | null = null;
|
||||
if (glAccountId) {
|
||||
glAccounts.some((glAccount: GLAccount) => {
|
||||
if (glAccount.id === glAccountId) {
|
||||
accountMapping = { id: glAccount.id, name: glAccount.name, glCode: glAccount.glCode };
|
||||
}
|
||||
return '';
|
||||
});
|
||||
}
|
||||
|
||||
public isNoneAccounting(accountingRule: OptionData): boolean {
|
||||
return (accountingRule.id === 1);
|
||||
}
|
||||
|
||||
public isNoneAccountingRuleId(accountingRuleId: number): boolean {
|
||||
return (accountingRuleId === 1);
|
||||
}
|
||||
|
||||
public isCashOrAccrualAccounting(accountingRule: OptionData): boolean {
|
||||
return ((accountingRule.id === 2) || (accountingRule.id === 3));
|
||||
}
|
||||
|
||||
public isCashOrAccrualAccountingRuleId(accountingRuleId: number): boolean {
|
||||
return ((accountingRuleId === 2) || (accountingRuleId === 3));
|
||||
}
|
||||
|
||||
public isAccrualAccounting(accountingRule: OptionData): boolean {
|
||||
return (accountingRule.id === 3);
|
||||
}
|
||||
|
||||
public isAccrualAccountingRuleId(accountingRuleId: number): boolean {
|
||||
return (accountingRuleId === 3);
|
||||
}
|
||||
|
||||
public getAccountingRuleFrom(accountingRuleId: number): OptionData {
|
||||
if (accountingRuleId === 1) {
|
||||
return {code: 'NONE', id: accountingRuleId, value: 'None'};
|
||||
} else if (accountingRuleId === 2) {
|
||||
return {code: 'CASH', id: accountingRuleId, value: 'Cash'};
|
||||
} else if (accountingRuleId === 3) {
|
||||
return {code: 'ACCRUAL_PERIODIC', id: accountingRuleId, value: 'Accural (periodic)'};
|
||||
} else if (accountingRuleId === 4) {
|
||||
return {code: 'ACCRUAL_UPFRONT', id: accountingRuleId, value: 'Accural (upfront)'};
|
||||
}
|
||||
return {code: 'INVALID', id: accountingRuleId, value: 'Invalid'};
|
||||
}
|
||||
|
||||
public glAccountLookUp(glAccountId: number, glAccounts: GLAccount[]): AccountingMapping {
|
||||
let accountMapping: AccountingMapping | null = null;
|
||||
if (glAccountId) {
|
||||
glAccounts.some((glAccount: GLAccount) => {
|
||||
if (glAccount.id === glAccountId) {
|
||||
accountMapping = { id: glAccount.id, name: glAccount.name, glCode: glAccount.glCode };
|
||||
}
|
||||
});
|
||||
}
|
||||
return accountMapping;
|
||||
}
|
||||
|
||||
return accountMapping;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { OptionData } from 'app/shared/models/option-data.model';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class Charges {
|
||||
|
||||
public getChargeAppliesToOptions(): OptionData[] {
|
||||
return [
|
||||
{ 'id': 1, 'code': 'chargeAppliesTo.loan', 'value': 'Loan' },
|
||||
{ 'id': 2, 'code': 'chargeAppliesTo.savings', 'value': 'Savings' },
|
||||
{ 'id': 3, 'code': 'chargeAppliesTo.client', 'value': 'Client' },
|
||||
{ 'id': 4, 'code': 'chargeAppliesTo.shares', 'value': 'Shares' }
|
||||
];
|
||||
}
|
||||
|
||||
public getChargeAppliesToOptions(): OptionData[] {
|
||||
return [
|
||||
{ id: 1, code: 'chargeAppliesTo.loan', value: 'Loan' },
|
||||
{ id: 2, code: 'chargeAppliesTo.savings', value: 'Savings' },
|
||||
{ id: 3, code: 'chargeAppliesTo.client', value: 'Client' },
|
||||
{ id: 4, code: 'chargeAppliesTo.shares', value: 'Shares' }
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,17 @@ import { Injectable } from '@angular/core';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class Commons {
|
||||
|
||||
constructor() {}
|
||||
|
||||
public dynamicSort(property: string) {
|
||||
let sortOrder = 1;
|
||||
if (property[0] === '-') {
|
||||
sortOrder = -1;
|
||||
property = property.substr(1);
|
||||
sortOrder = -1;
|
||||
property = property.substr(1);
|
||||
}
|
||||
return (a: any, b: any) => {
|
||||
const result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
|
||||
return result * sortOrder;
|
||||
const result = a[property] < b[property] ? -1 : a[property] > b[property] ? 1 : 0;
|
||||
return result * sortOrder;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,14 +11,29 @@ import { Dates } from './dates';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class Datatables {
|
||||
systemFields: string[] = [
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
systemFields: string[] = ['id', 'created_at', 'updated_at'];
|
||||
entitiesIdFields: string[] = [
|
||||
'client_id',
|
||||
'savings_account_id',
|
||||
'savings_transaction_id',
|
||||
'loan_id',
|
||||
'group_id',
|
||||
'center_id',
|
||||
'office_id',
|
||||
'product_loan_id',
|
||||
'savings_product_id',
|
||||
'share_product_id'
|
||||
];
|
||||
|
||||
entitiesIdFields: string[] = ['client_id', 'savings_account_id', 'savings_transaction_id',
|
||||
'loan_id', 'group_id', 'center_id', 'office_id', 'product_loan_id', 'savings_product_id', 'share_product_id'];
|
||||
|
||||
constructor(private dateUtils: Dates,
|
||||
private settingsService: SettingsService) { }
|
||||
constructor(
|
||||
private dateUtils: Dates,
|
||||
private settingsService: SettingsService
|
||||
) {}
|
||||
|
||||
public getFormfields(columns: any, dateTransformColumns: string[], dataTableEntryObject: any) {
|
||||
return columns.map((column: any) => {
|
||||
@@ -26,27 +41,30 @@ export class Datatables {
|
||||
case 'INTEGER':
|
||||
case 'STRING':
|
||||
case 'DECIMAL':
|
||||
case 'TEXT': return new InputBase({
|
||||
controlName: column.columnName,
|
||||
label: column.columnName,
|
||||
value: '',
|
||||
type: (column.columnDisplayType === 'INTEGER' || column.columnDisplayType === 'DECIMAL') ? 'number' : 'text',
|
||||
required: (column.isColumnNullable) ? false : true
|
||||
});
|
||||
case 'BOOLEAN': return new CheckboxBase({
|
||||
controlName: column.columnName,
|
||||
label: column.columnName,
|
||||
value: '',
|
||||
type: 'checkbox',
|
||||
required: (column.isColumnNullable) ? false : true
|
||||
});
|
||||
case 'CODELOOKUP': return new SelectBase({
|
||||
controlName: column.columnName,
|
||||
label: column.columnName,
|
||||
value: '',
|
||||
options: { label: 'value', value: 'id', data: column.columnValues },
|
||||
required: (column.isColumnNullable) ? false : true
|
||||
});
|
||||
case 'TEXT':
|
||||
return new InputBase({
|
||||
controlName: column.columnName,
|
||||
label: column.columnName,
|
||||
value: '',
|
||||
type: column.columnDisplayType === 'INTEGER' || column.columnDisplayType === 'DECIMAL' ? 'number' : 'text',
|
||||
required: column.isColumnNullable ? false : true
|
||||
});
|
||||
case 'BOOLEAN':
|
||||
return new CheckboxBase({
|
||||
controlName: column.columnName,
|
||||
label: column.columnName,
|
||||
value: '',
|
||||
type: 'checkbox',
|
||||
required: column.isColumnNullable ? false : true
|
||||
});
|
||||
case 'CODELOOKUP':
|
||||
return new SelectBase({
|
||||
controlName: column.columnName,
|
||||
label: column.columnName,
|
||||
value: '',
|
||||
options: { label: 'value', value: 'id', data: column.columnValues },
|
||||
required: column.isColumnNullable ? false : true
|
||||
});
|
||||
case 'DATE': {
|
||||
dateTransformColumns.push(column.columnName);
|
||||
if (!dataTableEntryObject.dateFormat) {
|
||||
@@ -57,7 +75,7 @@ export class Datatables {
|
||||
label: column.columnName,
|
||||
value: '',
|
||||
maxDate: this.settingsService.maxAllowedDate,
|
||||
required: (column.isColumnNullable) ? false : true
|
||||
required: column.isColumnNullable ? false : true
|
||||
});
|
||||
}
|
||||
case 'DATETIME': {
|
||||
@@ -68,7 +86,7 @@ export class Datatables {
|
||||
label: column.columnName,
|
||||
value: '',
|
||||
maxDate: this.settingsService.maxAllowedDate,
|
||||
required: (column.isColumnNullable) ? false : true
|
||||
required: column.isColumnNullable ? false : true
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -76,11 +94,11 @@ export class Datatables {
|
||||
}
|
||||
|
||||
public isEntityId(columnName: string): boolean {
|
||||
return (this.entitiesIdFields.includes(columnName));
|
||||
return this.entitiesIdFields.includes(columnName);
|
||||
}
|
||||
|
||||
public isSystemColumn(columnName: string): boolean {
|
||||
return (this.systemFields.includes(columnName) || this.entitiesIdFields.includes(columnName));
|
||||
return this.systemFields.includes(columnName) || this.entitiesIdFields.includes(columnName);
|
||||
}
|
||||
|
||||
public filterSystemColumns(columnHeaders: any): any {
|
||||
@@ -124,7 +142,7 @@ export class Datatables {
|
||||
}
|
||||
|
||||
public isColumnType(columnType: string, expectedType: string): boolean {
|
||||
return (columnType === expectedType);
|
||||
return columnType === expectedType;
|
||||
}
|
||||
|
||||
public buildPayload(datatableInputs: any, datatableDataValues: any, dateFormat: string, output: any): any {
|
||||
@@ -159,12 +177,11 @@ export class Datatables {
|
||||
}
|
||||
|
||||
public isValidUrl(urlString: string): boolean {
|
||||
try {
|
||||
const url = new URL(urlString);
|
||||
return url.protocol.startsWith('http') || url.protocol.startsWith('https');
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const url = new URL(urlString);
|
||||
return url.protocol.startsWith('http') || url.protocol.startsWith('https');
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import * as moment from 'moment';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class Dates {
|
||||
|
||||
public static DEFAULT_DATEFORMAT = 'yyyy-MM-dd';
|
||||
public static DEFAULT_DATETIMEFORMAT = 'yyyy-MM-dd HH:mm';
|
||||
|
||||
@@ -48,8 +47,11 @@ export class Dates {
|
||||
return JSON.parse(localStorage.getItem('mifosXLanguage'));
|
||||
}
|
||||
|
||||
calculateDiff(date1: Date, date2: Date){
|
||||
return Math.floor((Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate()) - Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate()) ) /(1000 * 60 * 60 * 24));
|
||||
calculateDiff(date1: Date, date2: Date) {
|
||||
return Math.floor(
|
||||
(Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate()) -
|
||||
Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate())) /
|
||||
(1000 * 60 * 60 * 24)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,27 +2,26 @@ import { Injectable } from '@angular/core';
|
||||
import { OptionData } from 'app/shared/models/option-data.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DropdownOptions {
|
||||
|
||||
public retrievePeriodFrequencyTypeOptions(includeAll: boolean): OptionData[] {
|
||||
if (includeAll) {
|
||||
return [
|
||||
{ id: 0, code: 'DAYS', value: 'Days' },
|
||||
{ id: 1, code: 'WEEKS', value: 'Weeks' },
|
||||
{ id: 2, code: 'MONTHS', value: 'Months' },
|
||||
{ id: 3, code: 'YEARS', value: 'Years' },
|
||||
{ id: 4, code: 'WHOLE_TERM', value: 'Whole Term' },
|
||||
{ id: 5, code: 'INVALID', value: 'Invalid' },
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
{ id: 0, code: 'DAYS', value: 'Days' },
|
||||
{ id: 1, code: 'WEEKS', value: 'Weeks' },
|
||||
{ id: 2, code: 'MONTHS', value: 'Months' },
|
||||
{ id: 3, code: 'YEARS', value: 'Years' }
|
||||
];
|
||||
}
|
||||
public retrievePeriodFrequencyTypeOptions(includeAll: boolean): OptionData[] {
|
||||
if (includeAll) {
|
||||
return [
|
||||
{ id: 0, code: 'DAYS', value: 'Days' },
|
||||
{ id: 1, code: 'WEEKS', value: 'Weeks' },
|
||||
{ id: 2, code: 'MONTHS', value: 'Months' },
|
||||
{ id: 3, code: 'YEARS', value: 'Years' },
|
||||
{ id: 4, code: 'WHOLE_TERM', value: 'Whole Term' },
|
||||
{ id: 5, code: 'INVALID', value: 'Invalid' }
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
{ id: 0, code: 'DAYS', value: 'Days' },
|
||||
{ id: 1, code: 'WEEKS', value: 'Weeks' },
|
||||
{ id: 2, code: 'MONTHS', value: 'Months' },
|
||||
{ id: 3, code: 'YEARS', value: 'Years' }
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,36 +2,38 @@ import { Injectable } from '@angular/core';
|
||||
import { AbstractControl, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
||||
export class PasswordsUtility {
|
||||
// password regex pattern
|
||||
public static PASSWORD_REGEX = '^(?!.*(.)\\1)(?!.*\\s)(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^\\w\\s]).{12,50}$';
|
||||
// password regex pattern
|
||||
public static PASSWORD_REGEX = '^(?!.*(.)\\1)(?!.*\\s)(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^\\w\\s]).{12,50}$';
|
||||
|
||||
public getPasswordValidators(): ValidatorFn[] {
|
||||
return [Validators.required, Validators.pattern(PasswordsUtility.PASSWORD_REGEX), Validators.maxLength(50), Validators.minLength(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;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user