build: Use prettier for typescript

Stop ignoring .ts files in prettier and fix existing issues.
This commit is contained in:
Ralph Hopman
2025-01-15 11:59:30 +00:00
committed by Adam Saghy
parent 9d6cf1514a
commit cac1d11ad7
1812 changed files with 22516 additions and 16862 deletions
-2
View File
@@ -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;
}
}
+1 -3
View File
@@ -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.`);
}
}
}
+1 -2
View File
@@ -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;
}
}
+1 -2
View File
@@ -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);
}
}
+11 -14
View File
@@ -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()
);
}
});
}
}
+16 -9
View File
@@ -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;
}
}
+1 -3
View File
@@ -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) : {};
}
}
+12 -20
View File
@@ -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]));
}
}
+1 -3
View File
@@ -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);
}
}
+10 -4
View File
@@ -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;
}
}
+1 -3
View File
@@ -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() {}
}
+2 -3
View File
@@ -8,9 +8,8 @@ describe('ShellComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ShellComponent ]
})
.compileComponents();
declarations: [ShellComponent]
}).compileComponents();
}));
beforeEach(() => {
+8 -9
View File
@@ -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(() => {
+32 -24
View File
@@ -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(() => {
+32 -21
View File
@@ -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]);
}
}
+85 -70
View File
@@ -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;
}
}
+9 -12
View File
@@ -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' }
];
}
}
+5 -6
View File
@@ -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;
};
}
}
}
+56 -39
View File
@@ -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 -4
View File
@@ -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)
);
}
}
+19 -20
View File
@@ -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' }
];
}
}
}
+29 -27
View File
@@ -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;
};
}
}