This commit is contained in:
Antonis Koulalis 2021-03-30 09:33:57 +00:00
parent 7b4fe01122
commit 10d3169a02
510 changed files with 166 additions and 19273 deletions

View File

@ -1,35 +0,0 @@
/* You can add fonts */
@font-face {
font-family: "CharterITCW05";
src: url("assets/fonts/CharterITCW05-Regular.woff") format("woff");
}
/*@font-face {
font-family: "HelveticaNeue";
src: url("assets/fonts/HelveticaNeue-Regular.ttf") format("truetype");
}
@font-face {
font-family: "PragmaticaMedium";
src: url("assets/fonts/PragmaticaMedium.otf") format("opentype");
}*/
:host ::ng-deep {
h1, h2, h3, h4, h5, h6 {
font-family: "CharterITCW05";
}
/*label, .p-button, th {
font-family: "PragmaticaMedium";
font-weight: 100;
}*/
/** {
:not(h1, h2, h3, h4, h5, h6, label, .p-button, th, .pi) {
font-family: "HelveticaNeue";
font-weight: 600;
}
}*/
}

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
/* You can add media styles */
@media (max-width: 991px) {
//header
.header {
padding: 10px;
}
//main-content
.main-content {
padding: 10px;
}
}
@media (max-width: 961px) {
.hidden-left-panel {
display: none !important;
}
}
@media (min-width: 961px) {
.hidden-horizontal-menu {
display: none !important;
}
}

View File

@ -1,65 +0,0 @@
/* You can add reusable colors */
// Primary
$dark-orange-1: #933401;
$dark-orange-2: #571F01;
$orange: #D04A02;
$light-orange-1: #FD6412;
$light-orange-2: #FEB791;
$dark-tangerine-1: #AE6800;
$dark-tangerine-2: #714300;
$tangerine: #EB8C00;
$light-tangerine-1: #FFA929;
$light-tangerine-2: #FFDCA9;
$dark-yellow-1: #C28A00;
$dark-yellow-2: #855F00;
$yellow: #FFB600;
$light-yellow-1: #FFC83D;
$light-yellow-2: #FFECBD;
$dark-rose-1: #A43E50;
$dark-rose-2: #6E2A35;
$rose: #DB536A;
$light-rose-1: #E27588;
$light-rose-2: #F1BAC3;
$dark-red-1: #AA2417;
$dark-red-2: #741910;
$red: #E0301E;
$light-red-1: #E86153;
$Light-red-2: #F7C8C4;
$white: white;
$black: black;
$dark-grey: #2D2D2D;
$medium-grey: #464646;
$grey: #7D7D7D;
$light-grey: #DEDEDE;
// Secondary
$dark-purple-1: #6A1CE2;
$dark-purple-2: #4B06B2;
$purple: #9013FE;
$light-purple-1: #B15AFE;
$light-purple-2: #DEB8FF;
$dark-blue-1: #0060D7;
$dark-blue-2: #003DAB;
$blue: #0089EB;
$light-blue-1: #4DACF1;
$light-blue-2: #B3DCF9;
$dark-green-1: #2C8646;
$dark-green-2: #175C2C;
$green: #4EB523;
$light-green-1: #86DB4F;
$light-green-2: #C4FC9F;
$rose-for-white-type: #D93954;
// Status Colors
$status-red: #E0301E;
$status-yellow: #FFB600;
$status-green: #175C2C;

View File

@ -1,10 +0,0 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

View File

@ -1,9 +0,0 @@
<p-toast preventOpenDuplicates="true"></p-toast>
<div class="container">
<div class="p-grid p-nogutter">
<div class="p-col-12">
<app-header></app-header>
<app-main-page></app-main-page>
</div>
</div>
</div>

View File

@ -1 +0,0 @@
@import 'src/styles';

View File

@ -1,35 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'RTA-Admin-UI'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('RTA-Admin-UI');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('RTA-Admin-UI app is running!');
});
});

View File

@ -1,19 +0,0 @@
import { AuthService } from './shared/services/auth.service';
import { Component, OnInit } from '@angular/core';
import { PrimeNGConfig } from 'primeng/api';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(private primengConfig: PrimeNGConfig, private authService: AuthService) { }
ngOnInit(): void {
this.primengConfig.ripple = true;
this.authService.initializeOAuth2Login();
}
}

View File

@ -1,61 +0,0 @@
import { ToastModule } from 'primeng/toast';
import { OAuthModule, OAuthStorage } from 'angular-oauth2-oidc';
import { environment } from './../environments/environment';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';
import { FeaturesModule } from './features/features.module';
import { SharedModule } from './shared/shared.module';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { ConfirmationService, MessageService } from 'primeng/api';
import { SearchListStateService } from './shared/back-button/search-list-state.service';
export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
return new TranslateHttpLoader(http);
}
// Settings localStorage as OAuth2 storage.
// We need a factory, since localStorage is not available during AOT build time.
export function storageFactory(): OAuthStorage {
return localStorage;
}
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
CoreModule,
FeaturesModule,
SharedModule,
HttpClientModule,
ToastModule,
OAuthModule.forRoot({
resourceServer: {
allowedUrls: [environment.baseApiUrl],
sendAccessToken: true
}
}),
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
},
defaultLanguage: environment.defaultLanguage,
}),
],
providers: [ConfirmationService, { provide: OAuthStorage, useFactory: storageFactory }, MessageService, SearchListStateService],
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@ -1,25 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { SharedModule } from 'primeng/api';
import { PrimengSharedModule } from './../shared/primeng-shared/primeng-shared.module';
import { ErrorHandlingModule } from './error-handling/error-handling.module';
import { HeaderComponent } from './header/header.component';
import { MainPageComponent } from './main-page/main-page.component';
@NgModule({
declarations: [HeaderComponent, MainPageComponent],
imports: [
CommonModule,
FormsModule,
PrimengSharedModule,
SharedModule,
ErrorHandlingModule
],
exports: [
HeaderComponent,
MainPageComponent
]
})
export class CoreModule { }

View File

@ -1,15 +0,0 @@
import { HttpErrorInterceptor } from './http-error.interceptor';
import { GlobalErrorHandler } from './global-error-handler';
import { NgModule, ErrorHandler } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
@NgModule({
declarations: [],
imports: [CommonModule],
providers: [
{ provide: ErrorHandler, useClass: GlobalErrorHandler },
{ provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true }
]
})
export class ErrorHandlingModule { }

View File

@ -1,21 +0,0 @@
import { environment } from 'src/environments/environment';
import { HttpErrorResponse } from '@angular/common/http';
import { ErrorHandlingService } from './../../shared/services/error-handling/error-handling.service';
import { ErrorHandler, Injectable, NgZone } from '@angular/core';
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
constructor(private errorHandlingService: ErrorHandlingService, private zone: NgZone) {}
handleError(error: Error): void {
this.zone.run(() => {
if (!(error instanceof HttpErrorResponse) && environment.enableGlobalErrorToast){
this.errorHandlingService.showErrorMessage(error.message);
}
});
console.error('Error from global error handler', error);
}
}

View File

@ -1,34 +0,0 @@
import { ErrorHandlingService } from './../../shared/services/error-handling/error-handling.service';
import {
HttpHandler,
HttpRequest,
HttpEvent,
HttpErrorResponse,
HttpInterceptor
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Injectable, Injector } from '@angular/core';
@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
constructor(
private injector: Injector,
) {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
catchError((error: HttpErrorResponse) => {
// We don't inject an HttpClient dependent service directly to an http interceptor's constructor,
// or we'll get cyclic dependency errors
const errorHandlingService = this.injector.get(ErrorHandlingService);
errorHandlingService.showHttpResponseError(error);
return throwError(error);
})
) as Observable<HttpEvent<any>>;
}
}

View File

@ -1,14 +0,0 @@
<div class="p-grid p-nogutter p-ai-center vertical-container header">
<div class="p-col-4">
<div class="p-grid p-nogutter p-jc-start">
<a routerLink=''>
<img src="assets/images/pwc-logo.svg" height="50">
</a>
</div>
</div>
<div class="p-col-8">
<div class="p-grid p-nogutter p-jc-end">
<p-selectButton class="p-ml-auto" [options]="languages" [(ngModel)]="selectedLang" (ngModelChange)="changeLanguage($event)" optionLabel="name" optionValue="code"></p-selectButton>
</div>
</div>
</div>

View File

@ -1 +0,0 @@
@import 'src/styles';

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HeaderComponent } from './header.component';
describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ HeaderComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,28 +0,0 @@
import { Language } from './../../shared/models/language.interface';
import { environment } from './../../../environments/environment';
import { AuthService } from './../../shared/services/auth.service';
import { Component, OnInit } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { TranslateService } from '@ngx-translate/core';
import {Router} from "@angular/router";
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
languages: Language[] = environment.languages;
selectedLang = environment.defaultLanguage;
constructor(private auth: AuthService, private translateService: TranslateService, private router: Router) {
}
ngOnInit(): void {
}
changeLanguage($event): void {
this.translateService.use($event);
}
}

View File

@ -1 +0,0 @@
<router-outlet></router-outlet>

View File

@ -1 +0,0 @@
@import 'src/styles';

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MainPageComponent } from './main-page.component';
describe('MainPageComponent', () => {
let component: MainPageComponent;
let fixture: ComponentFixture<MainPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MainPageComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MainPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,22 +0,0 @@
import { Router } from '@angular/router';
import { AuthService } from 'src/app/shared/services/auth.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-main-page',
templateUrl: './main-page.component.html',
styleUrls: ['./main-page.component.scss']
})
export class MainPageComponent implements OnInit {
constructor(private auth: AuthService, private router: Router) { }
ngOnInit(): void {
this.auth.authStatusChanged.subscribe((isAuthenticated) => {
if (!isAuthenticated) {
this.router.navigateByUrl('login');
}
});
}
}

View File

@ -1,26 +0,0 @@
<div class="p-grid p-nogutter">
<app-left-panel class="hidden-left-panel"></app-left-panel>
<div class="p-col main-content">
<h1>{{'ADMINISTRATION' | translate}}</h1>
<div class="p-mb-5 hidden-horizontal-menu">
<app-horizontal-menu></app-horizontal-menu>
</div>
<ng-template ngFor let-section [ngForOf]="adminSections">
<h3 class="sub-title" id="{{section.title}}">{{section.title}}</h3>
<div class="sub-content">
<div class="p-grid">
<ng-template ngFor let-subSection [ngForOf]="section.subSections">
<div class="p-col-12 p-sm-6 p-xl-3">
<app-card [data]="subSection"></app-card>
</div>
</ng-template>
</div>
</div>
</ng-template>
</div>
</div>

View File

@ -1 +0,0 @@
@import 'src/styles';

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AdministrationComponent } from './administration.component';
describe('WelcomeComponent', () => {
let component: AdministrationComponent;
let fixture: ComponentFixture<AdministrationComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AdministrationComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AdministrationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,103 +0,0 @@
import { AuthService } from './../../shared/services/auth.service';
import { Component, OnInit } from '@angular/core';
import { CardItem } from './../../shared/models/card-item.interface';
import { AdministrationSection } from './../../shared/models/administration-section.interface';
@Component({
selector: 'app-administration',
templateUrl: './administration.component.html',
styleUrls: ['./administration.component.scss']
})
export class AdministrationComponent implements OnInit {
data: CardItem;
adminSections: AdministrationSection[];
constructor(public authService: AuthService) { }
ngOnInit(): void {
this.initializeData();
}
initializeData() {
this.adminSections = [
{
title: 'Monitoring',
subSections: [
{
title: 'Downloads Monitoring',
subtitle: 'View File\'s Downloading Process and Manage...',
headerImage: 'pi-image',
footerImage: 'pi-desktop',
path: '/pages/administration/downloads-monitoring'
}
]
},
{
title: 'Configurations',
subSections: [
{
title: 'Categories Managenent',
subtitle: 'View File\'s Downloading Process and Manage...',
headerImage: 'pi-image',
footerImage: 'pi-cog',
path: '/pages/administration/categories-management'
},
{
title: 'Templates Managenent',
subtitle: 'View File\'s Downloading Process and Manage...',
headerImage: 'pi-image',
footerImage: 'pi-cog',
path: '/pages/administration/templates-management'
},
{
title: 'Verification Managenent',
subtitle: 'View File\'s Downloading Process and Manage...',
headerImage: 'pi-image',
footerImage: 'pi-cog',
path: '/pages/administration/verification-management'
},
{
title: 'Configurator',
subtitle: 'View File\'s Downloading Process and Manage...',
headerImage: 'pi-image',
footerImage: 'pi-cog',
path: '/pages/administration/configurator'
}
]
},
{
title: 'Access',
subSections: [
{
title: 'Users Managenent',
subtitle: 'View File\'s Downloading Process and Manage...',
headerImage: 'pi-image',
footerImage: 'pi-key',
path: '/pages/administration/users-management'
},
{
title: 'Roles Managenent',
subtitle: 'View File\'s Downloading Process and Manage...',
headerImage: 'pi-image',
footerImage: 'pi-key',
path: '/pages/administration/roles-management'
}
]
},
{
title: 'Exception Handling',
subSections: [
{
title: 'Application Level Exceptions',
subtitle: 'View Application Level exceptions thrown by the Platform',
headerImage: 'pi-image',
footerImage: 'pi-exclamation-triangle',
path: '/pages/administration/application-level-exceptions'
}
]
}
];
}
}

View File

@ -1,18 +0,0 @@
<p-dialog [header]="header"
[(visible)]="displayDialog "
[closable]="false"
[draggable]="false"
[modal]="true"
appendTo="body">
<ng-template pTemplate="content">
<pre>
{{this.trace}}
</pre>
</ng-template>
<ng-template pTemplate="footer">
<p-button (onClick)="cancel()"
label="Close"
styleClass="p-mt-3 p-button-warning">
</p-button>
</ng-template>
</p-dialog>

View File

@ -1,13 +0,0 @@
@import 'src/styles';
pre {
width: 900px !important;
}
@media (max-width: 991px) {
pre {
width: 420px !important;
}
}

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ApplicationLevelDialogComponent } from './application-level-dialog.component';
describe('ApplicationLevelDialogComponent', () => {
let component: ApplicationLevelDialogComponent;
let fixture: ComponentFixture<ApplicationLevelDialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ApplicationLevelDialogComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ApplicationLevelDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,24 +0,0 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ApplicationLevelExceptionService } from 'src/app/shared/services/administration/application-level-exception.service';
@Component({
selector: 'app-application-level-dialog',
templateUrl: './application-level-dialog.component.html',
styleUrls: ['./application-level-dialog.component.scss']
})
export class ApplicationLevelDialogComponent implements OnInit {
@Input() displayDialog: boolean;
@Input() header: string;
@Input() trace: string;
@Output() cancelled = new EventEmitter<boolean>();
constructor() { }
ngOnInit(): void {
}
cancel() {
this.cancelled.emit(true);
}
}

View File

@ -1,29 +0,0 @@
<div class="p-grid p-nogutter">
<div class="p-col main-content">
<h1>{{'APPLICATION-LEVEL-EXCEPTIONS' | translate}}</h1>
<app-horizontal-menu></app-horizontal-menu>
<app-breadcrumb></app-breadcrumb>
<div class="p-grid p-nogutter p-pt-5 p-pb-5">
<div class="p-col p-nogutter p-col-12 p-mt-5">
<app-application-level-search-form [paginationEventRequest]="paginationEventRequest"
(searchResults)="searchMade($event)"
(loading)="passloading($event)">
</app-application-level-search-form>
</div>
<div class="p-col p-nogutter p-col-12 p-mt-5">
<app-application-level-table [searchResultsPage]="searchResults"
(paginationEvent)="paginationEvent($event)"
[loading]="loading">
</app-application-level-table>
</div>
</div>
</div>
</div>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ApplicationLevelExceptionsComponent } from './application-level-exceptions.component';
describe('ApplicationLevelExceptionsComponent', () => {
let component: ApplicationLevelExceptionsComponent;
let fixture: ComponentFixture<ApplicationLevelExceptionsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ApplicationLevelExceptionsComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ApplicationLevelExceptionsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,33 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { Page } from 'src/app/shared/models/paging/page.interface';
import { SystemException } from 'src/app/shared/models/system-exception.interface';
@Component({
selector: 'app-application-level-exceptions',
templateUrl: './application-level-exceptions.component.html',
styleUrls: ['./application-level-exceptions.component.scss']
})
export class ApplicationLevelExceptionsComponent implements OnInit {
searchResults: Page<SystemException> = null;
paginationEventRequest: { page: number, offset: number } ;
loading: boolean;
constructor() { }
ngOnInit(): void {
}
searchMade(results) {
this.searchResults = results;
}
passloading(loading) {
this.loading = loading;
}
paginationEvent(paginationEvent) {
this.paginationEventRequest = paginationEvent;
}
}

View File

@ -1,14 +0,0 @@
<p-fieldset legend="Search Filters"
[toggleable]="true">
<app-application-level-form></app-application-level-form>
<div class="p-formgroup-inline p-jc-center p-mt-3">
<p-button (onClick)="clear()" label="Clear" styleClass="p-mr-2 p-button-warning"
[disabled]="!canPreviewLevelExceptions()">
</p-button>
<p-button (onClick)="search()"
label="Search"
styleClass="p-button-primary"
[disabled]="!canPreviewLevelExceptions()">
</p-button>
</div>
</p-fieldset>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ApplicationLevelSearchFormComponent } from './application-level-search-form.component';
describe('ApplicationLevelSearchFormComponent', () => {
let component: ApplicationLevelSearchFormComponent;
let fixture: ComponentFixture<ApplicationLevelSearchFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ApplicationLevelSearchFormComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ApplicationLevelSearchFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,59 +0,0 @@
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
import { Page } from 'src/app/shared/models/paging/page.interface';
import { SystemException } from 'src/app/shared/models/system-exception.interface';
import { AuthService } from 'src/app/shared/services/auth.service';
import { ApplicationLevelExceptionService } from 'src/app/shared/services/administration/application-level-exception.service';
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
import { environment } from 'src/environments/environment';
import { ApplicationLevelFormComponent } from '../../forms/application-level-form/application-level-form.component';
@Component({
selector: 'app-application-level-search-form',
templateUrl: './application-level-search-form.component.html',
styleUrls: ['./application-level-search-form.component.scss']
})
export class ApplicationLevelSearchFormComponent implements OnInit {
@Input() set paginationEventRequest(value: { page: number, offset: number }) {
// This setter may be called on page setup without arguments.
if (!value) {
return;
}
// this._value = Object.assign(value);
this.search(value.page, value.offset);
}
@Output() searchResults = new EventEmitter<Page<SystemException>>();
@Output() loading = new EventEmitter<boolean>();
@ViewChild(ApplicationLevelFormComponent)
private searchCriteriaForm: ApplicationLevelFormComponent;
_value : {page: number , offset: number};
constructor(private applicationLevelService: ApplicationLevelExceptionService,private errorHandlingService: ErrorHandlingService, private auth: AuthService) { }
ngOnInit(): void {
}
search(pageNumber = 0, pageSize = 10) {
this.loading.emit(true);
this.applicationLevelService.searchByCriteriaPaged(pageNumber, pageSize, this.searchCriteriaForm?.formValue(), 'search').subscribe((results: Page<SystemException>) => {
this.searchResults.emit(results);
this.loading.emit(false);
},
err => {
this.errorHandlingService.showHttpResponseError(err)
this.loading.emit(false);
});
}
canPreviewLevelExceptions(): boolean {
return this.auth.userHasRightForClient(USER_RIGHTS.K01, environment.globalRightsClientID);
}
clear() {
this.searchCriteriaForm.resetForm();
}
}

View File

@ -1,54 +0,0 @@
<p-fieldset legend="List of Exceptions"
[toggleable]="_searchResultsPage?.data !== null"
[collapsed]="_searchResultsPage?.data === null">
<p-table [value]="_searchResultsPage?.data"
[lazy]="true"
(onLazyLoad)="onLazyLoad($event)"
[paginator]="true"
[rows]="rows"
[totalRecords]="totalRecords"
styleClass="p-datatable-gridlines"
[rowHover]="true"
[loading]="loading"
[autoLayout]="true"
[lazyLoadOnInit]="false">
<ng-template pTemplate="header">
<tr>
<th>Date-Time</th>
<th>Process Id</th>
<th>Job Name</th>
<th>File Code</th>
<th>iPower Client Code</th>
<th>Message</th>
<th>Cause</th>
<th class="one-button">Trace</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-systemException>
<tr>
<td>{{systemException.creationDatetime|date: "dd/MM/yyyy HH:mm"}}</td>
<td>{{systemException.processId}}</td>
<td>{{systemException.jobName}}</td>
<td>{{systemException.dmsFileCode}}</td>
<td>{{systemException.clientId}}</td>
<td>{{systemException.message}}</td>
<td>{{systemException.cause}}</td>
<!-- Edit & Delete icons -->
<td>
<button pButton
(click)="edit(systemException.id)"
icon="pi pi-align-justify"
pTooltip="{{'TRACE' | translate}}"
class="p-button-secondary p-button-rounded p-button-outlined">
</button>
</td>
</tr>
</ng-template>
</p-table>
</p-fieldset>
<app-application-level-dialog [displayDialog]="displayTraceDialog"
[header]="header"
(cancelled)="cancelEditLevelException()"
[trace]="trace">
</app-application-level-dialog>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ApplicationLevelTableComponent } from './application-level-table.component';
describe('ApplicationLevelTableComponent', () => {
let component: ApplicationLevelTableComponent;
let fixture: ComponentFixture<ApplicationLevelTableComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ApplicationLevelTableComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ApplicationLevelTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,64 +0,0 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { LazyLoadEvent } from 'primeng/api';
import { Page } from 'src/app/shared/models/paging/page.interface';
import { SystemException } from 'src/app/shared/models/system-exception.interface';
import { ApplicationLevelExceptionService } from 'src/app/shared/services/administration/application-level-exception.service';
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
@Component({
selector: 'app-application-level-table',
templateUrl: './application-level-table.component.html',
styleUrls: ['./application-level-table.component.scss']
})
export class ApplicationLevelTableComponent implements OnInit {
@Output() paginationEvent = new EventEmitter<{ page: number, offset: number }>(); // TODO: Use interface.
@Input() loading: boolean;
@Input() set searchResultsPage(results: Page<SystemException>) {
// This setter may be called on page setup without arguments.
if (!results) {
return;
}
this._searchResultsPage = results;
this.totalRecords = results.totalElements;
// this.loading = false;
}
_searchResultsPage: Page<SystemException>;
totalRecords: number;
rows: number = 10;
header: string;
trace: string;
displayTraceDialog: boolean;
constructor(private errorHandlingService: ErrorHandlingService, private applicationLevelService: ApplicationLevelExceptionService) { }
ngOnInit(): void {
}
onLazyLoad(event: LazyLoadEvent) {
let pageToRequest = Math.floor(event.first / event.rows);
let pageSize = event.rows;
this.paginationEvent.emit({ page: pageToRequest, offset: pageSize });
}
edit(id: number) {
this.header = "Trace";
if(id){
this.applicationLevelService.getById(id).subscribe(result => {
this.trace = result.trace;
this.displayTraceDialog = true;
},
err => {
this.errorHandlingService.showHttpResponseError(err)
});
}
}
cancelEditLevelException() {
this.displayTraceDialog = false;
this.trace = null;
}
}

View File

@ -1,53 +0,0 @@
<div class="p-grid p-nogutter">
<div class="p-col main-content">
<h1>{{'CATEGORIES-MANAGEMENT' | translate}}</h1>
<app-horizontal-menu></app-horizontal-menu>
<app-breadcrumb></app-breadcrumb>
<div class="p-grid p-nogutter p-pt-5 p-pb-5">
<div class="p-col p-nogutter p-col-12">
<div class="p-grid p-nogutter p-jc-end">
<button pButton
pRipple
type="button"
label="{{'ADD-NEW-CATEGORY' | translate}}"
icon="pi pi-plus-circle"
class="p-button-primary"
[disabled]="!canAddNewCategory()"
(click)="addCategory()">
</button>
<app-create-category-dialog [displayDialog]="displayCategoryCreationDialog"
[header]="header"
(cancelled)="displayCategoryCreationDialog = false"
(valueChange)="passEvent($event)">
</app-create-category-dialog>
</div>
</div>
<div class="p-col p-nogutter p-col-12 p-mt-5">
<app-categories-search [paginationEventRequest]="paginationEventRequest"
(searchResults)="searchMade($event)"
(loading)="passLoadingForTable($event)"
[passChange]="passChange"
(loading)="passloading($event)"
[valueTableChange]="valueOfTableChanged">
</app-categories-search>
</div>
<div class="p-col p-nogutter p-col-12 p-mt-5">
<app-categories-search-results [searchResultsPage]="searchResults"
[loading]="loading"
(paginationEvent)="paginationEvent($event)"
(valueChange)="passEvent($event)"
[loading]="loading">
</app-categories-search-results>
</div>
</div>
</div>
</div>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CategoriesManagementComponent } from './categories-management.component';
describe('CategoriesManagementComponent', () => {
let component: CategoriesManagementComponent;
let fixture: ComponentFixture<CategoriesManagementComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ CategoriesManagementComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(CategoriesManagementComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,59 +0,0 @@
import { environment } from './../../../../environments/environment.prod';
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
import { AuthService } from './../../../shared/services/auth.service';
import { Category } from 'src/app/shared/models/category.interface';
import { Component, OnInit } from '@angular/core';
import { Page } from '../../../shared/models/paging/page.interface';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-categories-management',
templateUrl: './categories-management.component.html',
styleUrls: ['./categories-management.component.scss']
})
export class CategoriesManagementComponent implements OnInit {
displayCategoryCreationDialog: boolean = false;
searchResults: Page<Category> = null;
paginationEventRequest: { page: number, offset: number } = { page: 10, offset: 0 };
header: string;
passChange: boolean;
valueOfTableChanged: any;
loading: boolean;
constructor(private authService: AuthService, private translate: TranslateService) { }
ngOnInit(): void {
}
searchMade(results) {
this.searchResults = results;
}
passLoadingForTable(loading) {
this.loading = loading;
}
paginationEvent(paginationEvent) {
this.paginationEventRequest = paginationEvent;
}
canAddNewCategory(): boolean {
return this.authService.userHasRightForClient(USER_RIGHTS.H02, environment.globalRightsClientID);
}
addCategory(): void {
this.header = this.translate.instant('ADD-NEW-CATEGORY');
this.displayCategoryCreationDialog = true;
}
passEvent(passEvent: any) {
if (passEvent) {
this.valueOfTableChanged = passEvent;
}
}
passloading(loading) {
this.loading = loading;
}
}

View File

@ -1,64 +0,0 @@
<p-fieldset legend="Results"
[toggleable]="_searchResultsPage?.data !== null"
[collapsed]="_searchResultsPage?.data === null">
<p-confirmDialog message="{{'DELETE-MESSAGE-CATEGORY' | translate}}"
header="{{'DELETE-CONFIRMATION' | translate}}"
acceptLabel="{{'ACCEPT_LABEL' | translate}}"
rejectLabel="{{'REJECT_LABEL' | translate}}"
acceptButtonStyleClass="p-button-primary"
rejectButtonStyleClass="p-button-warning"
acceptIcon="null"
rejectIcon="null">
</p-confirmDialog>
<p-table [value]="_searchResultsPage?.data"
[lazy]="true"
(onLazyLoad)="onLazyLoad($event)"
[paginator]="true"
[rows]="rows"
[totalRecords]="totalRecords"
styleClass="p-datatable-gridlines"
[rowHover]="true"
[loading]="loading"
[autoLayout]="true">
<ng-template pTemplate="header">
<tr>
<th>Document Classification</th>
<th>Category Name</th>
<th>Category Code</th>
<!-- TODO: Fix hacky way of locking the icon-columns in place -->
<th class="two-buttons">Actions</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-category>
<tr>
<td>{{category.documentClassification.classificationName}}</td>
<td>{{category.categoryName}}</td>
<td>{{category.categoryCode}}</td>
<!-- Edit & Delete icons -->
<td>
<button pButton
[disabled]="!canEditCategories()"
(click)="edit(category)"
icon="pi pi-pencil"
pTooltip="{{'EDIT-CATEGORY' | translate}}"
class="p-button-secondary p-button-rounded p-button-outlined">
</button>
<button pButton
[disabled]="!canDeleteCategories()"
(click)="delete(category)"
icon="pi pi pi-trash"
pTooltip="{{'DELETE-CATEGORY' | translate}}"
class="p-button-danger p-button-rounded p-button-outlined p-ml-2">
</button>
</td>
</tr>
</ng-template>
</p-table>
</p-fieldset>
<app-create-category-dialog [displayDialog]="displayEditCategoryDialog"
[header]="header"
(cancelled)="cancelEditCategory()"
[categoryToEdit]="categoryToEdit"
(valueChange)="passEvent($event)">
</app-create-category-dialog>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CategoriesSearchResultsComponent } from './categories-search-results.component';
describe('CategoriesSearchResultsComponent', () => {
let component: CategoriesSearchResultsComponent;
let fixture: ComponentFixture<CategoriesSearchResultsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ CategoriesSearchResultsComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(CategoriesSearchResultsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,103 +0,0 @@
import { AuthService } from './../../../../shared/services/auth.service';
import { environment } from './../../../../../environments/environment.prod';
import { ErrorHandlingService } from './../../../../shared/services/error-handling/error-handling.service';
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
import { Category } from './../../../../shared/models/category.interface';
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
import { ConfirmationService, LazyLoadEvent } from 'primeng/api';
import { Page } from '../../../../shared/models/paging/page.interface';
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
import { TranslateService } from '@ngx-translate/core';
import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service';
@Component({
selector: 'app-categories-search-results',
templateUrl: './categories-search-results.component.html',
styleUrls: ['./categories-search-results.component.scss']
})
export class CategoriesSearchResultsComponent implements OnInit {
@Output() paginationEvent = new EventEmitter<{ page: number, offset: number }>(); // TODO: Use interface.
@Output() valueChange = new EventEmitter<any>();
@Input() loading: boolean;
@Input() set searchResultsPage(results: Page<Category>) {
// This setter may be called on page setup without arguments.
if (!results) {
return;
}
this._searchResultsPage = results;
this.totalRecords = results.totalElements;
}
_searchResultsPage: Page<Category>;
totalRecords: number;
rows: number = 10;
header: string;
displayEditCategoryDialog: boolean;
categoryToEdit: Category;
constructor(
private categoriesService: CategoriesService,
private errorHandlingService: ErrorHandlingService,
private authService: AuthService,
private translate: TranslateService,
private confirmationService: ConfirmationService,
private notifications: NotificationsHandlingService
) { }
ngOnInit(): void {
}
onLazyLoad(event: LazyLoadEvent) {
let pageToRequest = Math.floor(event.first / event.rows);
let pageSize = event.rows;
this.paginationEvent.emit({ page: pageToRequest, offset: pageSize });
}
edit(category: Category) {
this.header = this.translate.instant('EDIT-CATEGORY');
this.categoryToEdit = category;
this.displayEditCategoryDialog = true;
}
cancelEditCategory() {
this.displayEditCategoryDialog = false;
this.categoryToEdit = null;
}
delete(category: Category): void {
this.confirmationService.confirm({
accept: () => {
this.categoriesService.delete(category.id).subscribe((success) => {
this.valueChange.emit(success);
this.notifications.showDeleteCategorySuccess();
},
err => this.errorHandlingService.showHttpResponseError(err)
);
// Actual logic to perform a confirmation
}, reject: () => {
}
});
}
/*
* UserRights-check Methods
*/
canEditCategories(): boolean {
return this.authService.userHasRightForClient(USER_RIGHTS.H03, environment.globalRightsClientID);
}
canDeleteCategories(): boolean {
return this.authService.userHasRightForClient(USER_RIGHTS.H04, environment.globalRightsClientID);
}
passEvent(passEvent : any) {
if(passEvent){
this.valueChange.emit(passEvent);
}
}
}

View File

@ -1,15 +0,0 @@
<p-fieldset legend="Search Filters"
[toggleable]="true">
<app-category-form [autosuggestInputs]="true"></app-category-form>
<div class="p-formgroup-inline p-jc-center p-mt-3">
<p-button (onClick)="clear()"
label="Clear"
styleClass="p-mr-2 p-button-warning">
</p-button>
<p-button (onClick)="searchButtonClicked()"
label="Search"
styleClass="p-ml-2 p-button-primary"
[disabled]="!canPreviewAllCategories()">
</p-button>
</div>
</p-fieldset>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CategoriesSearchComponent } from './categories-search.component';
describe('CategoriesSearchComponent', () => {
let component: CategoriesSearchComponent;
let fixture: ComponentFixture<CategoriesSearchComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ CategoriesSearchComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(CategoriesSearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,101 +0,0 @@
import { environment } from './../../../../../environments/environment.prod';
import { ErrorHandlingService } from './../../../../shared/services/error-handling/error-handling.service';
import { AuthService } from 'src/app/shared/services/auth.service';
import { CategoryFormComponent } from './../../forms/category-form/category-form.component';
import { Category } from './../../../../shared/models/category.interface';
import { DocumentClassificationsService } from './../../../../shared/services/administration/document-classifications.service';
import { Component, OnInit, Output, EventEmitter, Input, ViewChild } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
import { DocumentClassification } from 'src/app/shared/models/document-classification.interface';
import { Page } from '../../../../shared/models/paging/page.interface';
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
@Component({
selector: 'app-categories-search',
templateUrl: './categories-search.component.html',
styleUrls: ['./categories-search.component.scss']
})
export class CategoriesSearchComponent implements OnInit {
@Input() set paginationEventRequest(value: { page: number, offset: number }) {
// This setter may be called on page setup without arguments.
if (!value) {
return;
}
this._value = Object.assign(value);
this.search(value.page, value.offset);
}
@Input() set valueTableChange(results: any) {
if (results) {
this.search(this._value.page, this._value.offset);
}
}
@Output() searchResults = new EventEmitter<Page<Category>>();
@Output() loading = new EventEmitter<boolean>();
@Output() searchInitiated = new EventEmitter<boolean>();
@Input() passChange: any;
@ViewChild(CategoryFormComponent)
private categoryForm: CategoryFormComponent;
_value: { page: number, offset: number };
lastSearchCriteria: { docClassificationId: number | string, categoryName: string, categoryCode: string };
constructor(
private categoriesService: CategoriesService,
private authService: AuthService,
private errorHandlingService: ErrorHandlingService
) { }
ngOnInit(): void {
}
clear() {
this.categoryForm.resetForm();
}
searchButtonClicked() {
// Inform anyone interested there is a new search underway.
this.searchInitiated.emit(true);
// Remember the search for future pagination/whatever requests.
let categoryFormValue = this.categoryForm.formValue();
let docClassId = categoryFormValue.documentClassification ? categoryFormValue.documentClassification.classificationId : null;
let catName = categoryFormValue.categoryName;
let catCode = categoryFormValue.categoryCode;
this.lastSearchCriteria = {
docClassificationId: docClassId ? docClassId : '',
categoryName: catName ? catName : '',
categoryCode: catCode ? catCode : ''
};
// Then actually search.
this.search();
}
search(pageNumber = 0, pageSize = 10) {
this.loading.emit(true);
// A search may be issued by the paginationEventRequest setter upon setting up the page.
if (!this.lastSearchCriteria) {
return;
}
this.categoriesService.searchByCriteriaPaged(pageNumber, pageSize, this.lastSearchCriteria, 'search').subscribe((results: Page<Category>) => {
this.searchResults.emit(results);
this.loading.emit(false);
},err => {
this.loading.emit(false);
this.errorHandlingService.showHttpResponseError(err);
});
}
canPreviewAllCategories(): boolean {
return this.authService.userHasRightForClient(USER_RIGHTS.H01, environment.globalRightsClientID);
}
}

View File

@ -1,33 +0,0 @@
<p-dialog [header]="header"
[(visible)]="displayDialog"
[closable]="false"
[draggable]="false"
[modal]="true"
(onHide)="reset()"
(onShow)="onShow()"
appendTo="body">
<div class="p-grid p-nogutter">
<app-category-form [dialogLayout]="true"
[requiredFields]="true"
[displayValidationMessagesEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-category-form>
</div>
<div class="p-grid p-nogutter p-jc-center">
<div class="p-formgroup-inline p-mt-3">
<p-button (onClick)="cancel()"
label="Cancel"
styleClass="p-mr-2 p-button-warning">
</p-button>
<p-button *ngIf="!categoryToEdit"
(onClick)="addCategory()"
label="Add"
styleClass="p-ml-2 p-mr-2 p-button-primary">
</p-button>
<p-button *ngIf="categoryToEdit && categoryToEdit.id"
(onClick)="editCategory()"
label="Update"
styleClass="p-ml-2 p-button-primary">
</p-button>
</div>
</div>
</p-dialog>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CreateCategoryDialogComponent } from './create-category-dialog.component';
describe('CreateCategoryComponent', () => {
let component: CreateCategoryDialogComponent;
let fixture: ComponentFixture<CreateCategoryDialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ CreateCategoryDialogComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(CreateCategoryDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,86 +0,0 @@
import { CategoryFormComponent } from './../../forms/category-form/category-form.component';
import { Category } from './../../../../shared/models/category.interface';
import { CategoriesService } from '../../../../shared/services/administration/categories.service';
import { Component, Input, OnInit, Output, EventEmitter, ViewChild } from '@angular/core';
import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service';
@Component({
selector: 'app-create-category-dialog',
templateUrl: './create-category-dialog.component.html',
styleUrls: ['./create-category-dialog.component.scss']
})
export class CreateCategoryDialogComponent implements OnInit {
@ViewChild(CategoryFormComponent) private categoryForm: CategoryFormComponent;
@Input() displayDialog: boolean;
@Input() header: string;
@Input() categoryToEdit: Category;
@Output() cancelled = new EventEmitter<boolean>();
@Output() valueChange = new EventEmitter<any>();
displayValidationMessagesEvenIfPristine: boolean;
constructor(private categoriesService: CategoriesService,
private notificationHandling: NotificationsHandlingService) { }
ngOnInit(): void {
this.reset(); // Make sure everything is cleanly initialised.
}
reset() {
this.displayValidationMessagesEvenIfPristine = false;
this.categoryForm?.resetForm();
}
onShow() {
// If a categoryToEdit was provided.
if (this.categoryToEdit) {
this.categoryForm.setValue(this.categoryToEdit);
}
}
cancel() {
this.cancelled.emit(true);
}
addCategory() {
// If the form is not valid, make sure validator messages are displayed and then return without doing anything.
if (!this.categoryForm.isValid()) {
this.displayValidationMessagesEvenIfPristine = true;
return;
}
// TODO: What is returned from backend on create()??
this.categoriesService.createNewCategory(this.categoryForm.formValue()).subscribe(result => {
this.valueChange.emit(result);
this.notificationHandling.showCreateCategorySuccess();
this.cancel();
this.notificationHandling.showCreateNewCategorySuccess();
},
error => {
});
}
editCategory() {
// If the form is not valid, make sure validator messages are displayed and then return without doing anything.
if (!this.categoryForm.isValid()) {
this.displayValidationMessagesEvenIfPristine = true;
return;
}
// TODO: What is returned from backend on create()??
// TODO: It's to ugly having to provide the categoryId separately.
this.categoriesService.updateCategory(this.categoryForm.formValue()).subscribe(result => {
this.valueChange.emit(result);
this.cancel();
this.notificationHandling.showUpdateCategorySuccess();
},
error => {
});
}
}

View File

@ -1,3 +0,0 @@
<p-fieldset legend="Edit Value" [toggleable]="true">
<app-configurator-form [editableParameter]="editParameterRequestInput" (valueChange)="passValueChange($event)"></app-configurator-form>
</p-fieldset>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ConfiguratorEditValueComponent } from './configurator-edit-value.component';
describe('ConfiguratorEditValueComponent', () => {
let component: ConfiguratorEditValueComponent;
let fixture: ComponentFixture<ConfiguratorEditValueComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ConfiguratorEditValueComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ConfiguratorEditValueComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,28 +0,0 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {ConfiguratorParameter} from "../../../../shared/models/configurator-parameter.interface";
@Component({
selector: 'app-configurator-edit-value',
templateUrl: './configurator-edit-value.component.html',
styleUrls: ['./configurator-edit-value.component.scss']
})
export class ConfiguratorEditValueComponent implements OnInit {
@Input() editParameterRequestInput: ConfiguratorParameter;
@Output() newConfiguratorParameter = new EventEmitter<ConfiguratorParameter>();
selectedParameter: ConfiguratorParameter = null;
constructor() { }
ngOnInit(): void {
console.log('editParameterRequestInput in edit: ' + JSON.stringify(this.editParameterRequestInput));
}
passValueChange(newConfigurator: ConfiguratorParameter) {
this.newConfiguratorParameter.emit(newConfigurator);
}
}

View File

@ -1,38 +0,0 @@
<p-fieldset legend="List of Parameters" [toggleable]="true">
<p-table [value]="parametersListInput"
[lazy]="true"
[loading]="loadingInput"
[autoLayout]="true"
[rowHover]="true"
styleClass="p-datatable-gridlines"
[(selection)]="selectedParameterRequest"
(click)="passSelectedConfigurator(selectedParameterRequest)">
<ng-template pTemplate="header">
<tr>
<th style="width: 3rem"></th>
<th>Parameter Name</th>
<th>Parameter Type</th>
<th>Parameter Value </th>
</tr>
</ng-template>
<ng-template pTemplate="body"
let-parameter>
<tr>
<td>
<p-tableRadioButton *ngIf="parameter.configurationVariable != 'CRON_EXPRESSION'" [value]="parameter"></p-tableRadioButton>
</td>
<td>{{parameter.configurationVariable}}</td>
<td>{{parameter.variableType}}</td>
<td>
<span *ngIf="parameter.variableType === 'Integer'" >{{parameter.integerValue}}<br></span>
<span *ngIf="parameter.variableType === 'String'" >{{parameter.stringValue}}<br></span>
</td>
<!-- <td *ngIf="parameter.variableType === 'Integer'">{{parameter.integerValue}}</td>
<td *ngIf="parameter.variableType === 'String'">{{parameter.stringValue}}</td> -->
<!-- Edit & Delete icons -->
</tr>
</ng-template>
</p-table>
</p-fieldset>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ConfiguratorListOfParametersComponent } from './configurator-list-of-parameters.component';
describe('ConfiguratorListOfParametersComponent', () => {
let component: ConfiguratorListOfParametersComponent;
let fixture: ComponentFixture<ConfiguratorListOfParametersComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ConfiguratorListOfParametersComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ConfiguratorListOfParametersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,40 +0,0 @@
import {AfterViewChecked, AfterViewInit, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {ConfiguratorParameter} from '../../../../shared/models/configurator-parameter.interface';
import {Page} from '../../../../shared/models/paging/page.interface';
import {LazyLoadEvent} from 'primeng/api';
@Component({
selector: 'app-configurator-list-of-parameters',
templateUrl: './configurator-list-of-parameters.component.html',
styleUrls: ['./configurator-list-of-parameters.component.scss']
})
export class ConfiguratorListOfParametersComponent implements OnInit {
@Input() parametersListInput: ConfiguratorParameter[];
@Input() loadingInput: boolean;
@Output() editEventRequest = new EventEmitter<ConfiguratorParameter>();
editParameterRequest: ConfiguratorParameter;
parametersList: ConfiguratorParameter[];
selectedParameterRequest: ConfiguratorParameter;
totalRecords: number;
rows = 10;
constructor() { }
ngOnInit(): void {
const initParameter: ConfiguratorParameter = {
configurationId: null,
configurationVariable: null,
variableType: null,
integerValue: null,
stringValue: null
};
this.editEventRequest.emit(initParameter);
}
passSelectedConfigurator(parameter: ConfiguratorParameter) {
this.editEventRequest.emit(parameter);
}
}

View File

@ -1,27 +0,0 @@
<div class="p-grid p-nogutter">
<div class="p-col main-content">
<h1>{{'CONFIGURATOR' | translate}}</h1>
<app-horizontal-menu></app-horizontal-menu>
<app-breadcrumb></app-breadcrumb>
<div class="p-grid p-nogutter p-pt-5 p-pb-5">
<div class="p-col p-nogutter p-col-12">
<app-configurator-list-of-parameters [parametersListInput]="parametersList"
[loadingInput] = "loading"
(editEventRequest)="editEvent($event)">
</app-configurator-list-of-parameters>
</div>
<div class="p-col p-nogutter p-col-12 p-mt-5">
<app-configurator-edit-value [editParameterRequestInput]="editEventRequest" (newConfiguratorParameter)="passNewConfigurator($event)">
</app-configurator-edit-value>
</div>
</div>
</div>
</div>

View File

@ -1 +0,0 @@
@import 'src/styles';

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ConfiguratorComponent } from './configurator.component';
describe('ConfiguratorComponent', () => {
let component: ConfiguratorComponent;
let fixture: ComponentFixture<ConfiguratorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ConfiguratorComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ConfiguratorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,51 +0,0 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
import {ConfiguratorParameter} from '../../../shared/models/configurator-parameter.interface';
import {ConfiguratorService} from "../../../shared/services/administration/configurator.service";
@Component({
selector: 'app-configurator',
templateUrl: './configurator.component.html',
styleUrls: ['./configurator.component.scss']
})
export class ConfiguratorComponent implements OnInit {
// @Input() parametersListInput: [ConfiguratorParameter];
// @Input() editParameterRequestInput: ConfiguratorParameter;
// @Output() editEventRequest = new EventEmitter<ConfiguratorParameter>();
parametersList: ConfiguratorParameter[];
editEventRequest: ConfiguratorParameter;
loading = true;
constructor(private configuratorService: ConfiguratorService, private errorHandlingService: ErrorHandlingService) { }
ngOnInit(): void {
this.initData();
console.log('this.parametersList: ' + JSON.stringify(this.parametersList));
}
initData() {
this.loading = true;
this.configuratorService.getConfiguratorParameters().subscribe(values => {
this.parametersList = values;
this.loading = false;
console.log('IN this.parametersList: ' + JSON.stringify(this.parametersList));
},
err => {
this.errorHandlingService.showHttpResponseError(err);
this.loading = false;
});
}
editEvent(request) {
this.editEventRequest = request;
}
passNewConfigurator(newConfigurator: ConfiguratorParameter){
this.initData();
}
}

View File

@ -1,101 +0,0 @@
<div [formGroup]="searchCriteriaForm">
<div class="p-fluid p-grid">
<div class="p-col-12">
<div class="p-grid p-formgrid">
<div class="p-field p-col-12 p-sm-6 p-lg-3">
<label for="dateFrom">
Date From
</label>
<p-calendar id="dateFrom"
formControlName="dateFrom"
[maxDate]="searchCriteriaForm.get('dateFrom').value"
[readonlyInput]="false"
showButtonBar="true"
todayButtonStyleClass="p-button-set-today"
clearButtonStyleClass="p-button-clear-date"
[showIcon]="true"
dateFormat="dd/mm/yy">
</p-calendar>
</div>
<div class="p-field p-col-12 p-sm-6 p-lg-3">
<label for="dateTo">
Date To
</label>
<p-calendar id="dateTo"
formControlName="dateTo"
showButtonBar="true"
[minDate]="searchCriteriaForm.get('dateTo').value"
[readonlyInput]="false"
todayButtonStyleClass="p-button-set-today"
clearButtonStyleClass="p-button-clear-date"
[showIcon]="true"
dateFormat="dd/mm/yy">
</p-calendar>
</div>
<div class="p-field p-col-12 p-sm-6 p-lg-3">
<label for="clientName">
iPower Client Name
</label>
<p-autoComplete id="clientName"
formControlName="clientName"
[suggestions]="iPowerClientNameSuggestions"
[forceSelection]="true"
(completeMethod)="autosuggestIPowerClientName($event)"
(onSelect)="iPowerClientNameSelected($event)">
</p-autoComplete>
</div>
<div class="p-field p-col-12 p-sm-6 p-lg-3">
<label for="clientId">
iPower Client Code
</label>
<p-autoComplete id="clientId"
formControlName="clientId"
[suggestions]="iPowerClientCodeSuggestions"
[forceSelection]="true"
(completeMethod)="autosuggestIPowerClientCode($event)"
(onSelect)="iPowerClientCodeSelected($event)">
</p-autoComplete>
</div>
</div>
</div>
<div class="p-col-12">
<div class="p-grid p-formgrid">
<div class="p-field p-col-12 p-sm-6 p-lg-3">
<label for="processId">
Process Id
</label>
<input id="processId"
type="text"
pInputText
formControlName="processId">
</div>
<div class="p-field p-col-12 p-sm-6 p-lg-3">
<label for="jobName">
Job Name
</label>
<input id="jobName"
type="text"
pInputText
formControlName="jobName">
</div>
<div class="p-field p-col-12 p-sm-6 p-lg-3">
<label for="dmsFileCode">
File Code
</label>
<input id="dmsFileCode"
type="text"
pInputText
formControlName="dmsFileCode">
</div>
</div>
</div>
</div>
</div>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ApplicationLevelFormComponent } from './application-level-form.component';
describe('ApplicationLevelFormComponent', () => {
let component: ApplicationLevelFormComponent;
let fixture: ComponentFixture<ApplicationLevelFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ApplicationLevelFormComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ApplicationLevelFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,111 +0,0 @@
import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { IPowerClient } from 'src/app/shared/models/ipower-client.interface';
import { SearchSystemException} from 'src/app/shared/models/request/search-system-exceptions.interface';
import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service';
@Component({
selector: 'app-application-level-form',
templateUrl: './application-level-form.component.html',
styleUrls: ['./application-level-form.component.scss']
})
export class ApplicationLevelFormComponent implements OnInit {
iPowerClientNameSuggestions: any;
iPowerClientCodeSuggestions: any;
private iPowerClientSuggestions: IPowerClient[];
private selectedIPowerClient: IPowerClient;
searchCriteriaForm = this.fb.group({
processId: [null],
clientId: [null],
clientName: [null],
jobName: [null],
dmsFileCode: [null],
dateFrom: [null],
dateTo: [null],
});
constructor(private fb: FormBuilder, private iPowerClientsService: IpowerClientsService) { }
ngOnInit(): void {
}
public formValue(): SearchSystemException {
let formValue: SearchSystemException = {
processId: this.searchCriteriaForm.get('processId').value,
clientId: this.searchCriteriaForm.get('clientId').value,
jobName: this.searchCriteriaForm.get('jobName').value,
dmsFileCode: this.searchCriteriaForm.get('dmsFileCode').value,
dateFrom: this.searchCriteriaForm.get('dateFrom').value,
dateTo: this.searchCriteriaForm.get('dateTo').value
};
formValue.dateFrom = new Date(Date.UTC(formValue.dateFrom?.getFullYear(), formValue.dateFrom?.getMonth(), formValue.dateFrom?.getDate()));
formValue.dateTo = new Date(Date.UTC(formValue.dateTo?.getFullYear(), formValue.dateTo?.getMonth(),formValue.dateTo?.getDate() + 1));
formValue.dateTo?.setMilliseconds(formValue.dateTo?.getMilliseconds() -1);
return formValue;
}
/*
* Auto-suggest & Auto-complete IPower Client
*/
autosuggestIPowerClientName(event): void {
if (!event.query || event.query.length < 3) {
this.iPowerClientNameSuggestions = [];
return;
}
this.iPowerClientsService.getClientsByNameOnly(event.query).subscribe(
(values: IPowerClient[]) => {
this.iPowerClientSuggestions = values;
const temp: string[] = [];
values.map(val => temp.push(val.name));
this.iPowerClientNameSuggestions = temp;
},
err => console.error(err) // TODO: Handle this via a Messaging Service
);
}
autosuggestIPowerClientCode(event): void {
if (event.query.length < 3) {
this.iPowerClientCodeSuggestions = [];
return;
}
this.iPowerClientsService.getClientsByCodeOnly(event.query).subscribe(
(values: IPowerClient[]) => {
this.iPowerClientSuggestions = values;
const temp: string[] = [];
values.map(val => temp.push(val.clientCode));
this.iPowerClientCodeSuggestions = temp;
},
err => console.error(err)
);
}
iPowerClientNameSelected(name: string): void {
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.name === name);
this.searchCriteriaForm.get('clientId').patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.clientCode : '');
this.searchCriteriaForm.updateValueAndValidity();
}
iPowerClientCodeSelected(code: string): void {
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.clientCode === code);
this.searchCriteriaForm.get('clientName').patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.name : '');
this.searchCriteriaForm.updateValueAndValidity();
}
resetForm() {
this.searchCriteriaForm.reset();
}
}

View File

@ -1,72 +0,0 @@
<div [formGroup]="categoryForm">
<div class="p-fluid p-formgrid"
[ngClass]="{'p-grid': !dialogLayout}">
<div class="p-field"
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="document-classification">
Document Classification
</label>
<p-dropdown inputId="document-classification"
[options]="documentClassificationsList"
optionLabel="classificationName"
placeholder="Select"
formControlName="documentClassification"
[showClear]="true">
</p-dropdown>
<app-validation-message [control]="categoryForm.get('documentClassification')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field"
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="categoryName">
Category Name
</label>
<p-autoComplete id="categoryName"
formControlName="categoryName"
*ngIf="autosuggestInputs"
[suggestions]="categoryNameSuggestions"
(completeMethod)="autosuggestCategoryName($event)"
(onSelect)="categoryNameSelected($event)"
[forceSelection]="true">
</p-autoComplete>
<input id="categoryName"
type="text"
pInputText
formControlName="categoryName"
*ngIf="!autosuggestInputs">
<app-validation-message [control]="categoryForm.get('categoryName')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field"
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="categoryCode">
Category Code
</label>
<p-autoComplete id="categoryCode"
formControlName="categoryCode"
*ngIf="autosuggestInputs"
[suggestions]="categoryCodeSuggestions"
(completeMethod)="autosuggestCategoryCode($event)"
(onSelect)="categoryCodeSelected($event)"
[forceSelection]="true">
</p-autoComplete>
<input id="categoryCode"
type="text"
pInputText
formControlName="categoryCode"
*ngIf="!autosuggestInputs">
<app-validation-message [control]="categoryForm.get('categoryCode')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
</div>
</div>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CategoryFormComponent } from './category-form.component';
describe('CategoryFormComponent', () => {
let component: CategoryFormComponent;
let fixture: ComponentFixture<CategoryFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ CategoryFormComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(CategoryFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,183 +0,0 @@
import { Category } from './../../../../shared/models/category.interface';
import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, Validators, FormGroup } from '@angular/forms';
import { DocumentClassification } from 'src/app/shared/models/document-classification.interface';
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service';
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
@Component({
selector: 'app-category-form',
templateUrl: './category-form.component.html',
styleUrls: ['./category-form.component.scss']
})
export class CategoryFormComponent implements OnInit {
/*
* Inputs
*/
@Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog.
@Input() requiredFields: string[] | boolean = false; // True/False indicates that all/none are required. String[] specifies the form controls required.
@Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty.
@Input() autosuggestInputs: boolean = false;
/*
* Reactive Form
*/
categoryForm = this.fb.group({
documentClassification: [null],
categoryName: [null],
categoryCode: [null]
});
setFormValue: Category = null;
selectedCategory: Category;
/*
* Other Variables
*/
documentClassificationsList: DocumentClassification[];
categoryNameSuggestions: string[];
categoryCodeSuggestions: string[];
categorySuggestions: Category[];
/*
* Constructor & Initialisers
*/
constructor(
private fb: FormBuilder,
private categoriesService: CategoriesService,
private documentClassificationsService: DocumentClassificationsService,
private errorHandlingService: ErrorHandlingService
) { }
ngOnInit(): void {
this.initData();
this.initValidators()
}
initData() {
this.documentClassificationsService.getAll().subscribe(
value => this.documentClassificationsList = value,
err => this.errorHandlingService.showHttpResponseError(err)
);
}
// TODO: Have this mechanism offer the use of custom validators too.
initValidators() {
if (!this.requiredFields) { return; }
// In a true/false case.
if (typeof this.requiredFields == 'boolean') {
// If true, enable the required validator for all controls and sub-controls.
if (this.requiredFields) {
this.setRequiredValidatorRecursively(this.categoryForm);
}
// If false, do nothing.
return;
}
// If it was a string array, enable the validators for all provided field-names. TODO: This ONLY supports 1st level controls and not nested ones.
(<string[]>this.requiredFields).forEach(field => this.categoryForm.controls[field].setValidators(Validators.required))
}
setRequiredValidatorRecursively(group: FormGroup) {
Object.keys(group.controls).forEach(key => {
group.controls[key].setValidators(Validators.required);
if (group.controls[key]['controls']) {
this.setRequiredValidatorRecursively(<FormGroup>group.controls[key])
}
});
}
/*
* Auto-suggest & Auto-complete Category
*/
autosuggestCategoryName(event) {
if (!event.query || event.query.length < 3) {
this.categoryNameSuggestions = [];
return;
}
let classId = this.categoryForm.get('documentClassification').value ? this.categoryForm.get('documentClassification').value.classificationId : null;
this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe(
(values: Category[]) => {
let temp: string[] = [];
this.categorySuggestions = values;
values.map(val => temp.push(val.categoryName));
this.categoryNameSuggestions = temp
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
autosuggestCategoryCode(event) {
if (event.query.length < 3) {
this.categoryCodeSuggestions = [];
return;
}
let classId = this.categoryForm.get('documentClassification').value ? this.categoryForm.get('documentClassification').value.classificationId : null;
this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe(
(values: Category[]) => {
let temp: string[] = [];
this.categorySuggestions = values;
values.map(val => temp.push(val.categoryCode));
this.categoryCodeSuggestions = temp
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
categoryNameSelected(name: string) {
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name);
this.categoryForm.get('categoryCode').patchValue(this.selectedCategory.categoryCode);
this.categoryForm.updateValueAndValidity();
}
categoryCodeSelected(code: string) {
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code);
this.categoryForm.get('categoryName').patchValue(this.selectedCategory.categoryName);
this.categoryForm.updateValueAndValidity();
}
/*
* API methods
*/
public resetForm(): void {
this.categoryForm.reset();
}
public formValue(): Category {
let formValue: Category = {
id: this.setFormValue ? this.setFormValue.id : null,
documentClassification: this.categoryForm.get('documentClassification').value,
categoryName: this.categoryForm.get('categoryName').value,
categoryCode: this.categoryForm.get('categoryCode').value
};
return formValue;
}
public setValue(value: Category): void {
if (!value) {
return;
}
this.setFormValue = value;
this.categoryForm.get('documentClassification').setValue(value.documentClassification);
this.categoryForm.get('categoryName').setValue(value.categoryName);
this.categoryForm.get('categoryCode').setValue(value.categoryCode);
this.categoryForm.updateValueAndValidity();
}
public isValid(): boolean {
return this.categoryForm.valid;
}
}

View File

@ -1,60 +0,0 @@
<div [formGroup]="configuratorForm">
<div class="p-fluid p-formgrid"
[ngClass]="{'p-grid': !dialogLayout}">
<!-- Configurator Form - Start -->
<div class="p-field p-col-12"
[ngClass]="{'p-lg-4': !dialogLayout}">
<label for="parameterName">Parameter Name</label>
<input id="parameterName"
type="text"
pInputText
disabled
formControlName="parameterName"
value="{{editableParameter?.configurationVariable}}">
<app-validation-message [control]="configuratorForm.get('parameterName')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field p-col-12 "
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="parameterType">Parameter Type</label>
<input id="parameterType"
type="text"
pInputText
disabled
formControlName="parameterType"
value="{{editableParameter?.variableType}}">
<app-validation-message [control]="configuratorForm.get('parameterType')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field p-col-12 "
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="parameterValue">Parameter Value</label>
<input id="parameterValue"
type="text"
pInputText
formControlName="parameterValue"
value="{{editableParameter?.variableType == 'Integer' ? editableParameter?.integerValue : editableParameter?.stringValue}}">
<app-validation-message [control]="configuratorForm.get('parameterValue')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
</div>
<div class="p-formgroup-inline p-jc-center p-mt-3">
<p-button (onClick)="updateButtonClicked()"
label="Update"
styleClass="p-button-primary"
[disabled]="!canEditParameterValue()">
</p-button>
</div>
</div>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ConfiguratorFormComponent } from './configurator-form.component';
describe('ConfiguratorFormComponent', () => {
let component: ConfiguratorFormComponent;
let fixture: ComponentFixture<ConfiguratorFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ConfiguratorFormComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ConfiguratorFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,69 +0,0 @@
import { AfterViewChecked, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { ConfiguratorParameter } from '../../../../shared/models/configurator-parameter.interface';
import { ConfiguratorService } from "../../../../shared/services/administration/configurator.service";
import { Category } from "../../../../shared/models/category.interface";
import { Router } from "@angular/router";
import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service';
import { AuthService } from 'src/app/shared/services/auth.service';
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-configurator-form',
templateUrl: './configurator-form.component.html',
styleUrls: ['./configurator-form.component.scss']
})
export class ConfiguratorFormComponent implements OnInit {
@Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog.
@Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty.
@Input() editableParameter: ConfiguratorParameter;
@Output() valueChange = new EventEmitter<ConfiguratorParameter>();
/*
* Reactive Form
*/
configuratorForm = this.fb.group({
parameterName: null,
parameterType: null,
parameterValue: null
});
constructor(private fb: FormBuilder, private configuratorService: ConfiguratorService, private router: Router, private notificationService: NotificationsHandlingService,
private authService: AuthService) { }
ngOnInit(): void {
}
ngOnChanges(): void {
}
public formValue(): ConfiguratorParameter {
let formValue: ConfiguratorParameter = {
configurationId: this.editableParameter.configurationId,
configurationVariable: this.editableParameter.configurationVariable,
variableType: this.editableParameter.variableType,
integerValue: this.editableParameter.variableType === 'Integer' ? Number(this.configuratorForm.get('parameterValue').value) : null,
stringValue: this.editableParameter.variableType === 'String' ? String(this.configuratorForm.get('parameterValue').value) : null
};
return formValue;
}
updateButtonClicked(): void {
if (this.editableParameter.configurationId !== null) {
this.configuratorService.updateConfiguratorParameter(this.formValue()).subscribe(result => {
this.valueChange.emit(this.formValue());
this.notificationService.showUpdateConfiguratorParameterSuccess();
},
error => {
});
}
}
canEditParameterValue(): boolean {
return this.authService.userHasRightForClient(USER_RIGHTS.J01, environment.globalRightsClientID) && this.editableParameter.configurationVariable != null;
}
}

View File

@ -1,138 +0,0 @@
<div [formGroup]="templateForm">
<div class="p-fluid p-formgrid"
[ngClass]="{'p-grid': !dialogLayout}">
<div class="p-field"
*ngIf="!excludedFormControls?.includes('documentClassification')"
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="documentClassification">
Document Classification
</label>
<p-dropdown inputId="documentClassification"
[options]="documentClassificationsList"
optionLabel="classificationName"
placeholder="Select"
formControlName="documentClassification"
(onChange)="documentClassificationSelected($event.value)"
[showClear]="true">
</p-dropdown>
<app-validation-message [control]="templateForm.get('documentClassification')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field"
*ngIf="!excludedFormControls?.includes('categoryName')"
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="categoryName">
Category Name
</label>
<p-autoComplete id="categoryName"
formControlName="categoryName"
[suggestions]="categoryNameSuggestions"
[forceSelection]="true"
(completeMethod)="autosuggestCategoryName($event)"
(onSelect)="categoryNameSelected($event)">
</p-autoComplete>
<app-validation-message [control]="templateForm.get('categoryName')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field"
*ngIf="!excludedFormControls?.includes('categoryName')"
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="categoryCode">
Category Code
</label>
<p-autoComplete id="categoryCode"
formControlName="categoryCode"
[suggestions]="categoryCodeSuggestions"
[forceSelection]="true"
(completeMethod)="autosuggestCategoryCode($event)"
(onSelect)="categoryCodeSelected($event)">
</p-autoComplete>
<app-validation-message [control]="templateForm.get('categoryCode')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field"
*ngIf="!excludedFormControls?.includes('iPowerClient')"
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="iPowerClientName">
iPower Client Name
</label>
<p-autoComplete id="iPowerClientName"
formControlName="iPowerClientName"
[suggestions]="iPowerClientNameSuggestions"
[forceSelection]="true"
(completeMethod)="autosuggestIPowerClientName($event)"
(onSelect)="iPowerClientNameSelected($event)">
</p-autoComplete>
<app-validation-message [control]="templateForm.get('iPowerClientName')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field"
*ngIf="!excludedFormControls?.includes('iPowerClient')"
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="iPowerClientCode">
iPower Client Code
</label>
<p-autoComplete id="iPowerClientCode"
formControlName="iPowerClientCode"
[suggestions]="iPowerClientCodeSuggestions"
[forceSelection]="true"
(completeMethod)="autosuggestIPowerClientCode($event)"
(onSelect)="iPowerClientCodeSelected($event)">
</p-autoComplete>
<app-validation-message [control]="templateForm.get('iPowerClientCode')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field"
*ngIf="!excludedFormControls?.includes('documentSubclassification')"
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="documentSubclassification">
Sub-Category Name
</label>
<p-dropdown inputId="documentSubclassification"
[options]="availableDocumentSubclassifications"
[disabled]="subCategoryCodeDisabled"
optionLabel="subclassificationName"
placeholder="Select a Document Classification first"
formControlName="documentSubclassification">
</p-dropdown>
<app-validation-message [control]="templateForm.get('documentSubclassification')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field"
*ngIf="!excludedFormControls?.includes('abbyyTemplateCode')"
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
<label for="abbyyTemplateCode"
>
ABBYY Template Code
</label>
<input id="abbyyTemplateCode"
type="text"
pInputText
formControlName="abbyyTemplateCode">
<app-validation-message [control]="templateForm.get('abbyyTemplateCode')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
</div>
</div>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TemplateFormComponent } from './template-form.component';
describe('TemplateFormComponent', () => {
let component: TemplateFormComponent;
let fixture: ComponentFixture<TemplateFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TemplateFormComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TemplateFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,369 +0,0 @@
import { DocumentClassification } from './../../../../shared/models/document-classification.interface';
import { Category } from './../../../../shared/models/category.interface';
import { DocumentSubclassificationsService } from './../../../../shared/services/administration/document-subclassifications.service';
import { DocumentSubclassification } from './../../../../shared/models/document-subclassification.interface';
import { IPowerClient } from './../../../../shared/models/ipower-client.interface';
import { Template } from './../../../../shared/models/template.interface';
import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service';
import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service';
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
@Component({
selector: 'app-template-form',
templateUrl: './template-form.component.html',
styleUrls: ['./template-form.component.scss']
})
export class TemplateFormComponent implements OnInit {
/*
* Inputs
*/
@Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog.
@Input() requiredFields: string[] | boolean = false; // True/False indicates that all/none are required. String[] specifies the form controls required.
@Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty.
@Input() excludedFormControls: string[]; // Specifies the form controls to be removed and NOT displayed.
/*
* Reactive Form
*/
templateForm = this.fb.group({
documentClassification: [null],
categoryName: [null],
categoryCode: [null],
iPowerClientName: [null],
iPowerClientCode: [null],
documentSubclassification: [null],
abbyyTemplateCode: [null]
});
initiallySetFormValue: Template;
/*
* Other Variables
*/
documentClassificationsList: DocumentClassification[];
categoryNameSuggestions: string[];
categoryCodeSuggestions: string[];
categorySuggestions: Category[];
selectedCategory: Category;
iPowerClientNameSuggestions: string[];
iPowerClientCodeSuggestions: string[];
iPowerClientSuggestions: IPowerClient[];
selectedIPowerClient: IPowerClient;
documentSubclassificationsList: DocumentSubclassification[];
availableDocumentSubclassifications: DocumentSubclassification[];
subCategoryCodeDisabled: boolean = true;
/*
* Constructor & Initialisers
*/
constructor(
private fb: FormBuilder,
private documentClassificationsService: DocumentClassificationsService,
private categoriesService: CategoriesService,
private iPowerClientsService: IpowerClientsService,
private documentSubclassificationsService: DocumentSubclassificationsService,
private errorHandlingService: ErrorHandlingService
) { }
ngOnInit(): void {
this.initData();
this.initValidators()
this.excludeFields();
}
initData() {
this.documentClassificationsService.getAll().subscribe(
value => this.documentClassificationsList = value,
err => this.errorHandlingService.showHttpResponseError(err)
);
// This is NOT the list of Subclassifications used for the dropdown.
this.documentSubclassificationsService.getAll().subscribe(
value => this.documentSubclassificationsList = value,
err => this.errorHandlingService.showHttpResponseError(err)
);
}
// TODO: Have this mechanism offer the use of custom validators too.
initValidators() {
if (!this.requiredFields) { return; }
// In a true/false case.
if (typeof this.requiredFields == 'boolean') {
// If true, enable the required validator for all controls.
if (this.requiredFields) {
Object.keys(this.templateForm.controls).forEach(key => this.templateForm.controls[key].setValidators(Validators.required));
}
// If false, do nothing.
return;
}
// If it was a string array, enable the validators for all provided field-names.
(<string[]>this.requiredFields).forEach(field => this.templateForm.controls[field].setValidators(Validators.required))
}
excludeFields() {
if (!this.excludedFormControls) { return; }
this.excludedFormControls.forEach(field => this.templateForm.removeControl(field));
}
/*
* Auto-suggest & Auto-complete Category
*/
autosuggestCategoryName(event) {
if (!event.query || event.query.length < 3) {
this.categoryNameSuggestions = [];
return;
}
let classId = this.templateForm.get('documentClassification').value ? this.templateForm.get('documentClassification').value.classificationId : null;
this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe(
(values: Category[]) => {
let temp: string[] = [];
this.categorySuggestions = values;
values.map(val => temp.push(val.categoryName));
this.categoryNameSuggestions = temp
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
autosuggestCategoryCode(event) {
if (event.query.length < 3) {
this.categoryCodeSuggestions = [];
return;
}
let classId = this.templateForm.get('documentClassification').value ? this.templateForm.get('documentClassification').value.classificationId : null;
this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe(
(values: Category[]) => {
let temp: string[] = [];
this.categorySuggestions = values;
values.map(val => temp.push(val.categoryCode));
this.categoryCodeSuggestions = temp
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
categoryNameSelected(name: string) {
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name);
this.templateForm.get('categoryCode')?.patchValue(this.selectedCategory.categoryCode);
this.templateForm.updateValueAndValidity();
}
categoryCodeSelected(code: string) {
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code);
this.templateForm.get('categoryName')?.patchValue(this.selectedCategory?.categoryName);
this.templateForm.updateValueAndValidity();
}
/*
* Auto-suggest & Auto-complete IPower Client
*/
autosuggestIPowerClientName(event): void {
if (!event.query || event.query.length < 3) {
this.iPowerClientNameSuggestions = [];
return;
}
this.iPowerClientsService.getClientsByNameOnly(event.query).subscribe(
(values: IPowerClient[]) => {
this.iPowerClientSuggestions = values;
const temp: string[] = [];
values.map(val => temp.push(val.name));
this.iPowerClientNameSuggestions = temp;
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
autosuggestIPowerClientCode(event): void {
if (event.query.length < 3) {
this.iPowerClientCodeSuggestions = [];
return;
}
this.iPowerClientsService.getClientsByCodeOnly(event.query).subscribe(
(values: IPowerClient[]) => {
this.iPowerClientSuggestions = values;
const temp: string[] = [];
values.map(val => temp.push(val.clientCode));
this.iPowerClientCodeSuggestions = temp;
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
iPowerClientNameSelected(name: string) {
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.name == name);
this.templateForm.get('iPowerClientCode')?.patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.clientCode : '');
this.templateForm.updateValueAndValidity();
}
iPowerClientCodeSelected(code: string) {
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.clientCode == code);
this.templateForm.get('iPowerClientName')?.patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.name : '');
this.templateForm.updateValueAndValidity();
}
/*
* Other Methods
*/
documentClassificationSelected(selection: DocumentClassification) {
this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => element.documentClassification.classificationId == selection.classificationId);
this.templateForm.get('documentSubclassification')?.setValue(this.availableDocumentSubclassifications[0]); //TODO CHECK
this.subCategoryCodeDisabled = false;
}
/*
* Utility Methods
*/
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedCategory, otherwise truncate it.
syncSelectedCategory() {
// Ιf our form has no value, truncate the selectedCategory either way.
if (!this.templateForm.get('categoryName')?.value && !this.templateForm.get('categoryCode').value) {
this.selectedCategory = null;
return;
}
// If both or either of our form's values match the selectedCategory's and the other one doesn't have a value, all is good.
// Just sync the values in case one is missing. Otherwise truncate the selectedCategory.
if (
this.templateForm.get('categoryName')?.value == this.selectedCategory.categoryName
|| this.templateForm.get('categoryCode')?.value == this.selectedCategory.categoryCode
) {
this.selectedCategory.categoryName = this.templateForm.get('categoryName')?.value;
this.selectedCategory.categoryCode = this.templateForm.get('categoryCode')?.value;
}
// If both our values were different from the selectedCategory's, truncate it. This is an extremely abnormal scenario.
else {
console.error('WARNING - syncSelectedCategory()', 'Both of our form\'s values were different from the selectedCategory\'s.');
this.selectedCategory = null;
this.templateForm.get('categoryName')?.setValue('');
this.templateForm.get('categoryCode')?.setValue('');
this.templateForm.updateValueAndValidity();
}
}
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedIPowerClient, otherwise truncate it.
syncSelectedIPowerClient() {
// Ιf our form has no value, truncate the selectedIPowerClient either way.
if (!this.templateForm.get('iPowerClientName')?.value && !this.templateForm.get('iPowerClientCode')?.value) {
this.selectedIPowerClient = null;
return;
}
// If both or either of our form's values match the selectedIPowerClient's and the other one doesn't have a value, all is good.
// Just sync the values in case one is missing. Otherwise truncate the selectedIPowerClient.
if (
this.templateForm.get('iPowerClientName')?.value == this.selectedIPowerClient.name
|| this.templateForm.get('iPowerClientCode')?.value == this.selectedIPowerClient.clientCode
) {
this.selectedIPowerClient.name = this.templateForm.get('iPowerClientName')?.value;
this.selectedIPowerClient.clientCode = this.templateForm.get('iPowerClientCode')?.value;
}
// If both our values were different from the selectedIPowerClient's, truncate it. This is an extremely abnormal scenario.
else {
console.error('WARNING - syncSelectedIPowerClient()', 'Both of our form\'s values were different from the selectedIPowerClient\'s.');
this.selectedIPowerClient = null;
this.templateForm.get('iPowerClientName')?.setValue('');
this.templateForm.get('iPowerClientCode')?.setValue('');
this.templateForm.updateValueAndValidity();
}
}
/*
* API methods
*/
public resetForm(): void {
this.templateForm.reset();
this.selectedCategory = null;
this.selectedIPowerClient = null;
}
public formValue(): Template {
// A field ('documentSubclassification') may be excluded, so we have to check for that too.
let subCatCode = this.templateForm.get('documentSubclassification') ? this.templateForm.get('documentSubclassification').value : null;
let abbyy = this.templateForm.get('abbyyTemplateCode') ? this.templateForm.get('abbyyTemplateCode').value : null;
let docClass = this.templateForm.get('documentClassification') ? this.templateForm.get('documentClassification').value : null;
// We keep track of those two using object-variables separate from our ReactiveForm.
// Thus, we now have to make sure the ReactiveForm really has values that match those objects, before we forward them.
// Also, keep in mind that our auto-suggest inputs limit the user in choosing one of their values.
this.syncSelectedCategory();
this.syncSelectedIPowerClient();
let formValue: Template = {
id: this.initiallySetFormValue ? this.initiallySetFormValue.id : null,
category: this.selectedCategory,
subCategoryCode: subCatCode ? subCatCode.subclassificationName : '',
abbyyTemplate: abbyy,
client: this.selectedIPowerClient,
documentClassification: docClass
};
return formValue;
}
public setValue(value: Template): void {
if (!value) {
return;
}
this.initiallySetFormValue = value;
// If a documentClassification is already selected, enable the subclassification dropdown.
this.subCategoryCodeDisabled = !value.documentClassification;
this.templateForm.get('documentClassification')?.setValue(value.documentClassification);
// Having set the documentClassification -and provided there was one- we must also set the availableDocumentSubclassifications.
this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element =>
element.documentClassification.classificationId == value.documentClassification.classificationId
);
this.selectedCategory = value.category;
this.templateForm.get('categoryName')?.setValue(value.category.categoryName);
this.templateForm.get('categoryCode')?.setValue(value.category.categoryCode);
this.selectedIPowerClient = value.client;
this.templateForm.get('iPowerClientName')?.setValue(value.client.name);
this.templateForm.get('iPowerClientCode')?.setValue(value.client.clientCode);
this.templateForm.get('abbyyTemplateCode')?.setValue(value.abbyyTemplate);
// To set the subcategory/subclassification we also have to make sure the documentClassification is the same.
// WARNING: Since we have enabled the [forceSelection] option of the <p-autoComplete>,
// if the availableDocumentSubclassifications are not set, documentSubclassification won't be displayed.
this.templateForm.get('documentSubclassification').setValue(
this.documentSubclassificationsList.find(subClass => (
subClass.subclassificationName == value.subCategoryCode && subClass.documentClassification.classificationId == value.documentClassification.classificationId
))
);
this.templateForm.updateValueAndValidity();
}
public isValid(): boolean {
return this.templateForm.valid;
}
}

View File

@ -1,16 +0,0 @@
import { JournalVerification } from './../../../../shared/models/journal-verification.interface';
import { CapturingVerification } from './../../../../shared/models/capturing-verification.interface';
import { Template } from 'src/app/shared/models/template.interface';
export interface CreateVerificationRuleFormValue {
id: number;
confidenceLevelMinThreshold: number;
clientId: string
categoryId: number;
subCategoryCode: string;
verificationRuleStatus: string;
capturingVerification: CapturingVerification;
journalVerification: JournalVerification;
alteryxRoutineId: string;
template: Template;
}

View File

@ -1,200 +0,0 @@
<div [formGroup]="verificationRuleForm">
<div class="p-fluid"
[ngClass]="{'p-formgrid': !dialogLayout}">
<div class="p-grid">
<div class="p-field p-col-12 p-lg-6">
<label for="document-classification">
Document Classification
</label>
<p-dropdown inputId="document-classification"
[options]="documentClassificationsList"
optionLabel="classificationName"
placeholder="Select"
formControlName="documentClassification"
[disabled]="editMode"
(onChange)="documentClassificationSelected($event)">
</p-dropdown>
<app-validation-message [control]="verificationRuleForm.get('documentClassification')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
</div>
<div class="p-grid">
<div class="p-field p-col-12 p-lg-6">
<label for="ipower-name">
iPower Client Name
</label>
<p-autoComplete id="ipower-name"
formControlName="ipowerName"
[suggestions]="iPowerClientNameSuggestions"
[forceSelection]="true"
(completeMethod)="autosuggestIPowerClientName($event)"
[disabled]="editMode"
(onSelect)="iPowerClientNameSelected($event)">
</p-autoComplete>
<app-validation-message [control]="verificationRuleForm.get('ipowerName')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field p-col-12 p-lg-6">
<label for="ipower-code">
iPower Client Code
</label>
<p-autoComplete id="ipower-code"
formControlName="ipowerCode"
[suggestions]="iPowerClientCodeSuggestions"
[forceSelection]="true"
(completeMethod)="autosuggestIPowerClientCode($event)"
[disabled]="editMode"
(onSelect)="iPowerClientCodeSelected($event)">
</p-autoComplete>
<app-validation-message [control]="verificationRuleForm.get('ipowerCode')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
</div>
<div class="p-grid">
<div class="p-field p-col-12 p-lg-6">
<label for="category-name">
Category Name
</label>
<p-autoComplete id="category-name"
formControlName="categoryName"
[suggestions]="categoryNameSuggestions"
[forceSelection]="true"
(completeMethod)="autosuggestCategoryName($event)"
[disabled]="editMode"
(onSelect)="categoryNameSelected($event)">
</p-autoComplete>
<app-validation-message [control]="verificationRuleForm.get('categoryName')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field p-col-12 p-lg-6">
<label for="category-code">
Category Code
</label>
<p-autoComplete id="category-code"
formControlName="categoryCode"
[suggestions]="categoryCodeSuggestions"
[forceSelection]="true"
(completeMethod)="autosuggestCategoryCode($event)"
[disabled]="editMode"
(onSelect)="categoryCodeSelected($event)">
</p-autoComplete>
<app-validation-message [control]="verificationRuleForm.get('categoryCode')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
</div>
<div class="p-grid">
<div class="p-field p-col-12 p-lg-6">
<label for="document-subclassification">
Sub-Category Name
</label>
<p-dropdown inputId="document-subclassification"
[options]="availableDocumentSubclassifications"
[disabled]="subCategoryCodeDisabled || editMode"
optionLabel="subclassificationName"
placeholder="Select a Document Classification first"
formControlName="subCategoryCode">
</p-dropdown>
<app-validation-message [control]="verificationRuleForm.get('subCategoryCode')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
</div>
<div class="p-grid"
[ngClass]="{'p-pt-4': (initiallySetFormValue && initiallySetFormValue.id)}">
<div class="p-field p-col-12 p-lg-6">
<label for="capturing-verification">
Capturing Verification
</label>
<p-dropdown inputId="capturing-verification"
formControlName="capturingVerification"
[options]="capturingVerificationsList"
optionLabel="capturingVerificationName"
placeholder="Select">
</p-dropdown>
<app-validation-message [control]="verificationRuleForm.get('capturingVerification')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field p-col-12 p-lg-6">
<label for="journal-verification">
Journal Verification
</label>
<p-dropdown inputId="journal-verification"
formControlName="journalVerification"
[options]="journalVerificationsList"
optionLabel="journalVerificationName"
placeholder="Select">
</p-dropdown>
<app-validation-message [control]="verificationRuleForm.get('journalVerification')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
</div>
<div class="p-grid">
<div class="p-field p-col-12 p-lg-6">
<label for="confidence-level">
Confidence Level
</label>
<input id="confidence-level"
type="number"
pInputText
formControlName="confidenceLevelMinThreshold">
<app-validation-message [control]="verificationRuleForm.get('confidenceLevelMinThreshold')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
<div class="p-field p-col-12 p-lg-6">
<label for="alteryx-routine-id">
Alteryx Routine Name
</label>
<input id="alteryx-routine-id"
type="text"
pInputText
formControlName="alteryxRoutineId">
<app-validation-message [control]="verificationRuleForm.get('alteryxRoutineId')"
[validationMessage]="'This field is required.'"
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
</app-validation-message>
</div>
</div>
<div class="p-grid p-jc-center" *ngIf="editMode">
<div class="p-field p-col-5 p-m-2">
</div>
<div class="p-field p-col-5 p-m-2">
<p-checkbox id="verification-rule-status" name="verification-rule-status"
[formControl]="verificationRuleForm.get('verificationRuleStatus')" binary="true" label="Rule Status"
[disabled]="!canEditRuleStatus()">
</p-checkbox>
</div>
</div>
</div>
</div>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { VerificationRuleFormComponent } from './verification-rule-form.component';
describe('VerificationRuleFormComponent', () => {
let component: VerificationRuleFormComponent;
let fixture: ComponentFixture<VerificationRuleFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ VerificationRuleFormComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(VerificationRuleFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,527 +0,0 @@
import { Right } from './../../../../shared/models/right.interface';
import { environment } from './../../../../../environments/environment';
import { USER_RIGHTS } from './../../../../shared/enums/USER_RIGHTS.enum';
import { AuthService } from 'src/app/shared/services/auth.service';
import { CreateVerificationRuleFormValue } from './create-verification-rule-form-value.interface';
import { JournalVerificationsService } from './../../../../shared/services/administration/journal-verifications.service';
import { CapturingVerificationsService } from './../../../../shared/services/administration/capturing-verifications.service';
import { DocumentSubclassificationsService } from 'src/app/shared/services/administration/document-subclassifications.service';
import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service';
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service';
import { FormBuilder, Validators } from '@angular/forms';
import { DocumentSubclassification } from 'src/app/shared/models/document-subclassification.interface';
import { Component, Input, OnInit } from '@angular/core';
import { CapturingVerification } from '../../../../shared/models/capturing-verification.interface';
import { Category } from '../../../../shared/models/category.interface';
import { IPowerClient } from '../../../../shared/models/ipower-client.interface';
import { JournalVerification } from '../../../../shared/models/journal-verification.interface';
import { VerificationRule } from './../../../../shared/models/verification-rule.interface';
import { DocumentClassification } from '../../../../shared/models/document-classification.interface';
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
import { Observable } from 'rxjs';
@Component({
selector: 'app-verification-rule-form',
templateUrl: './verification-rule-form.component.html',
styleUrls: ['./verification-rule-form.component.scss']
})
export class VerificationRuleFormComponent implements OnInit {
/*
* Inputs
*/
@Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog.
@Input() requiredFields: string[] | boolean = false; // True/False indicates that all/none are required. String[] specifies the form controls required.
@Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty.
@Input() excludedFormControls: string[]; // Specifies the form controls to be removed and NOT displayed.
/*
* Reactive Form
*/
verificationRuleForm = this.fb.group({
documentClassification: [null],
ipowerName: [null],
ipowerCode: [null],
categoryName: [null],
categoryCode: [null],
subCategoryCode: [null], // This actually represents the complete DocumentSubclassification object.
confidenceLevelMinThreshold: [null],
capturingVerification: [null],
journalVerification: [null],
alteryxRoutineId: [null],
verificationRuleStatus: [true],
template: [null]
});
initiallySetFormValue: VerificationRule;
editMode: boolean = false;
/*
* Other Variables
*/
documentClassificationsList: DocumentClassification[];
categoryNameSuggestions: string[];
categoryCodeSuggestions: string[];
categorySuggestions: Category[];
selectedCategory: Category;
iPowerClientNameSuggestions: string[];
iPowerClientCodeSuggestions: string[];
iPowerClientSuggestions: IPowerClient[];
selectedIPowerClient: IPowerClient;
capturingVerificationsList: CapturingVerification[];
journalVerificationsList: JournalVerification[];
documentSubclassificationsList: DocumentSubclassification[];
availableDocumentSubclassifications: DocumentSubclassification[];
subCategoryCodeDisabled: boolean = true;
/*
* Constructor & Initialisers
*/
constructor(
private fb: FormBuilder,
private documentClassificationsService: DocumentClassificationsService,
private categoriesService: CategoriesService,
private iPowerClientsService: IpowerClientsService,
private documentSubclassificationsService: DocumentSubclassificationsService,
private capturingVerificationsService: CapturingVerificationsService,
private journalVerificationsService: JournalVerificationsService,
private authService: AuthService,
private errorHandlingService: ErrorHandlingService
) { }
ngOnInit(): void {
this.initData();
this.initValidators()
this.excludeFields();
}
initData() {
this.documentClassificationsService.getAll().subscribe(
value => this.documentClassificationsList = value,
err => this.errorHandlingService.showHttpResponseError(err)
);
// This is NOT the list of Subclassifications used for the dropdown.
this.documentSubclassificationsService.getAll().subscribe(
value => this.documentSubclassificationsList = value,
err => this.errorHandlingService.showHttpResponseError(err)
);
this.journalVerificationsService.getJournalVerifications().subscribe(
values => this.journalVerificationsList = values,
err => this.errorHandlingService.showHttpResponseError(err)
);
this.capturingVerificationsService.getCapturingVerifications().subscribe(
values => this.capturingVerificationsList = values,
err => this.errorHandlingService.showHttpResponseError(err)
);
}
// TODO: Have this mechanism offer the use of custom validators too.
initValidators() {
if (!this.requiredFields) { return; }
// In a true/false case.
if (typeof this.requiredFields == 'boolean') {
// If true, enable the required validator for all controls.
if (this.requiredFields) {
Object.keys(this.verificationRuleForm.controls).forEach(key => this.verificationRuleForm.controls[key].setValidators(Validators.required));
}
// If false, do nothing.
return;
}
// If it was a string array, enable the validators for all provided field-names.
(<string[]>this.requiredFields).forEach(field => this.verificationRuleForm.controls[field].setValidators(Validators.required))
}
excludeFields() {
if (!this.excludedFormControls) { return; }
this.excludedFormControls.forEach(field => this.verificationRuleForm.removeControl(field));
}
/*
* Auto-suggest & Auto-complete Category
*/
autosuggestCategoryName(event) {
if (!event.query || event.query.length < 3) {
this.categoryNameSuggestions = [];
return;
}
let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null;
this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe(
(values: Category[]) => {
let temp: string[] = [];
this.categorySuggestions = values;
values.map(val => temp.push(val.categoryName));
this.categoryNameSuggestions = temp
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
autosuggestCategoryCode(event) {
if (event.query.length < 3) {
this.categoryCodeSuggestions = [];
return;
}
let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null;
this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe(
(values: Category[]) => {
let temp: string[] = [];
this.categorySuggestions = values;
values.map(val => temp.push(val.categoryCode));
this.categoryCodeSuggestions = temp
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
categoryNameSelected(name: string) {
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name);
this.verificationRuleForm.get('categoryCode').patchValue(this.selectedCategory.categoryCode);
this.verificationRuleForm.updateValueAndValidity();
}
categoryCodeSelected(code: string) {
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code);
this.verificationRuleForm.get('categoryName').patchValue(this.selectedCategory.categoryName);
this.verificationRuleForm.updateValueAndValidity();
}
// /*
// * Auto-suggest & Auto-complete IPower Client
// */
// /*
// * Rights-check Warning:
// * If we are NOT in editMode (and are thus on "addMode"), we should only suggest clients for which we actually CAN add a new rule.
// * Note:
// * I know that if on editMode the client-input is disabled and thus this check is redundant,
// * but I think it is better to work with as an abstract perspective as possible, not entailing business logic that may either be unrelated or prone to changes.
// */
// autosuggestIPowerClientName(event) {
// if (!event.query || event.query.length < 3) {
// this.iPowerClientNameSuggestions = [];
// return;
// }
// // If the user has the right to preview all rules (B01), we use the endpoint that returns all iPowerClients,
// // otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button.
// let endpointToSubscribeTo: Observable<IPowerClient[]> = USER_RIGHTS.B01.isGrantedToUser(
// this.authService.userRights.find(rbc => rbc.client.id == environment.globalRightsClientID)?.rights
// )
// ? this.iPowerClientsService.getClientsByNameOnly(event.query)
// : this.iPowerClientsService.getClientsByNameDistinct(event.query);
// endpointToSubscribeTo.subscribe(
// (values: IPowerClient[]) => {
// // ***See comment at method level***
// if (!this.editMode) {
// values = values.filter(client => USER_RIGHTS.B03.isGrantedToUser(
// this.authService.userRights.find(rdc => rdc.client.id == client.id)?.rights
// ));
// }
// let temp: string[] = [];
// this.iPowerClientSuggestions = values;
// values.map(val => temp.push(val.name));
// this.iPowerClientNameSuggestions = temp
// },
// err => this.errorHandlingService.showHttpResponseError(err)
// );
// }
// /*
// * Rights-check Warning:
// * If we are NOT in editMode (and are thus on "addMode"), we should only suggest clients for which we actually CAN add a new rule.
// * Note:
// * I know that if on editMode the client-input is disabled and thus this check is redundant,
// * but I think it is better to work with as an abstract perspective as possible, not entailing business logic that may either be unrelated or prone to changes.
// */
// autosuggestIPowerClientCode(event) {
// if (event.query.length < 3) {
// this.iPowerClientCodeSuggestions = [];
// return;
// }
// // If the user has the right to preview all rules (B01), we use the endpoint that returns all iPowerClients,
// // otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button.
// let endpointToSubscribeTo: Observable<IPowerClient[]> = USER_RIGHTS.B01.isGrantedToUser(
// this.authService.userRights.find(rbc => rbc.client.id == environment.globalRightsClientID)?.rights
// )
// ? this.iPowerClientsService.getClientsByCodeOnly(event.query): null;
// endpointToSubscribeTo.subscribe(
// (values: IPowerClient[]) => {
// // ***See comment at method level***
// if (!this.editMode) {
// values = values;
// }
// let temp: string[] = [];
// this.iPowerClientSuggestions = values;
// values.map(val => temp.push(val.clientCode));
// this.iPowerClientCodeSuggestions = temp
// },
// err => this.errorHandlingService.showHttpResponseError(err)
// );
// }
/*
* Auto-suggest & Auto-complete IPower Client
*/
autosuggestIPowerClientName(event): void {
if (!event.query || event.query.length < 3) {
this.iPowerClientNameSuggestions = [];
return;
}
this.iPowerClientsService.getClientsByNameOnly(event.query).subscribe(
(values: IPowerClient[]) => {
this.iPowerClientSuggestions = values;
const temp: string[] = [];
values.map(val => temp.push(val.name));
this.iPowerClientNameSuggestions = temp;
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
autosuggestIPowerClientCode(event): void {
if (event.query.length < 3) {
this.iPowerClientCodeSuggestions = [];
return;
}
this.iPowerClientsService.getClientsByCodeOnly(event.query).subscribe(
(values: IPowerClient[]) => {
this.iPowerClientSuggestions = values;
const temp: string[] = [];
values.map(val => temp.push(val.clientCode));
this.iPowerClientCodeSuggestions = temp;
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
iPowerClientNameSelected(name: string) {
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.name == name);
this.verificationRuleForm.get('ipowerCode').patchValue(this.selectedIPowerClient.clientCode);
this.verificationRuleForm.updateValueAndValidity();
}
iPowerClientCodeSelected(code: string) {
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.clientCode == code);
this.verificationRuleForm.get('ipowerName').patchValue(this.selectedIPowerClient.name);
this.verificationRuleForm.updateValueAndValidity();
}
/*
* Other Methods
*/
documentClassificationSelected(selection) {
this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => element.documentClassification.classificationId == selection.value.classificationId);
this.verificationRuleForm.get('subCategoryCode').setValue(this.availableDocumentSubclassifications[0]);
this.subCategoryCodeDisabled = false;
}
/*
* Utility Methods
*/
initiateEditMode() {
// let controlsToDisableInEditMode = ['documentClassification', 'ipowerName', 'ipowerCode', 'categoryName', 'categoryCode', 'subCategoryCode']
// controlsToDisableInEditMode.forEach(ctrl => this.verificationRuleForm.get(ctrl).disable());
}
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedCategory, otherwise truncate it.
syncSelectedCategory() {
// Ιf our form has no value, truncate the selectedCategory either way.
if (!this.verificationRuleForm.get('categoryName').value && !this.verificationRuleForm.get('categoryCode').value) {
this.selectedCategory = null;
return;
}
// If both or either of our form's values match the selectedCategory's and the other one doesn't have a value, all is good.
// Just sync the values in case one is missing. Otherwise truncate the selectedCategory.
if (
this.verificationRuleForm.get('categoryName').value == this.selectedCategory.categoryName
|| this.verificationRuleForm.get('categoryCode').value == this.selectedCategory.categoryCode
) {
this.selectedCategory.categoryName = this.verificationRuleForm.get('categoryName').value;
this.selectedCategory.categoryCode = this.verificationRuleForm.get('categoryCode').value;
}
// If both our values were different from the selectedCategory's, truncate it. This is an extremely abnormal scenario.
else {
console.error('WARNING - syncSelectedCategory()', 'Both of our form\'s values were different from the selectedCategory\'s.');
this.selectedCategory = null;
this.verificationRuleForm.get('categoryName').setValue('');
this.verificationRuleForm.get('categoryCode').setValue('');
this.verificationRuleForm.updateValueAndValidity();
}
}
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedIPowerClient, otherwise truncate it.
syncSelectedIPowerClient() {
// Ιf our form has no value, truncate the selectedIPowerClient either way.
if (!this.verificationRuleForm.get('ipowerName').value && !this.verificationRuleForm.get('ipowerCode').value) {
this.selectedIPowerClient = null;
return;
}
// If both or either of our form's values match the selectedIPowerClient's and the other one doesn't have a value, all is good.
// Just sync the values in case one is missing. Otherwise truncate the selectedIPowerClient.
if (
this.verificationRuleForm.get('ipowerName').value == this.selectedIPowerClient.name
|| this.verificationRuleForm.get('ipowerCode').value == this.selectedIPowerClient.clientCode
) {
this.selectedIPowerClient.name = this.verificationRuleForm.get('ipowerName').value;
this.selectedIPowerClient.clientCode = this.verificationRuleForm.get('ipowerCode').value;
}
// If both our values were different from the selectedIPowerClient's, truncate it. This is an extremely abnormal scenario.
else {
console.error('WARNING - syncSelectedIPowerClient()', 'Both of our form\'s values were different from the selectedIPowerClient\'s.');
this.selectedIPowerClient = null;
this.verificationRuleForm.get('ipowerName').setValue('');
this.verificationRuleForm.get('ipowerCode').setValue('');
this.verificationRuleForm.updateValueAndValidity();
}
}
/*
* Rights-check Methods
*/
canEditRuleStatus(): boolean {
if (this.initiallySetFormValue) {
return this.authService.userHasRightForClient(USER_RIGHTS.B06, environment.globalRightsClientID);
}
return false;
}
// canEditConfidenceLevel(): boolean {
// if (this.initiallySetFormValue) {
// return this.authService.userHasRightForClient(USER_RIGHTS.B07, this.initiallySetFormValue.client.id);
// }
// return false;
// }
/*
* API methods
*/
public resetForm(): void {
this.verificationRuleForm.reset();
this.selectedCategory = null;
this.selectedIPowerClient = null;
this.editMode = null;
}
public formValue(): CreateVerificationRuleFormValue {
// We keep track of those two using object-variables separate from our ReactiveForm.
// Thus, we now have to make sure the ReactiveForm really has values that match those objects, before we forward them.
// Also, keep in mind that our auto-suggest inputs limit the user in choosing one of their values.
this.syncSelectedCategory();
this.syncSelectedIPowerClient();
let formValue: CreateVerificationRuleFormValue = {
id: this.initiallySetFormValue ? this.initiallySetFormValue.id : null,
confidenceLevelMinThreshold: this.verificationRuleForm.get('confidenceLevelMinThreshold').value,
clientId: this.selectedIPowerClient ? this.selectedIPowerClient.id : null,
categoryId: this.selectedCategory ? this.selectedCategory.id : null,
// The backend only requires the subcategory's name, and not the whole object. Don't ask me.
subCategoryCode: this.verificationRuleForm.get('subCategoryCode').value ? this.verificationRuleForm.get('subCategoryCode').value['subclassificationName'] : '',
capturingVerification: this.verificationRuleForm.get('capturingVerification').value,
journalVerification: this.verificationRuleForm.get('journalVerification').value,
alteryxRoutineId: this.verificationRuleForm.get('alteryxRoutineId').value,
template: this.verificationRuleForm.get('template').value,
// Convert 'verificationRuleStatus' from boolean to string.
verificationRuleStatus: this.verificationRuleForm.get('verificationRuleStatus').value ? 'Enabled' : 'Disabled'
};
return formValue;
}
public setValue(value: VerificationRule): void {
if (!value) {
return;
}
this.editMode = true;
this.initiateEditMode();
this.initiallySetFormValue = value
// If a documentClassification is already selected, enable the subclassification dropdown.
this.subCategoryCodeDisabled = !value.docClassificationCategory;
this.verificationRuleForm.get('documentClassification').setValue(value.docClassificationCategory);
// Having set the documentClassification -and provided there was one- we must also set the availableDocumentSubclassifications.
this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element =>
element.documentClassification.classificationId == value.docClassificationCategory.classificationId
);
this.verificationRuleForm.get('ipowerName').setValue(value.client.name);
this.verificationRuleForm.get('ipowerCode').setValue(value.client.clientCode);
this.selectedIPowerClient = value.client;
this.verificationRuleForm.get('categoryName').setValue(value.template.category.categoryName);
this.verificationRuleForm.get('categoryCode').setValue(value.template.category.categoryCode);
this.selectedCategory = value.template.category;
this.verificationRuleForm.get('confidenceLevelMinThreshold').setValue(value.confidenceLevelMinThreshold);
this.verificationRuleForm.get('capturingVerification').setValue(value.capturingVerification);
this.verificationRuleForm.get('journalVerification').setValue(value.journalVerification);
this.verificationRuleForm.get('alteryxRoutineId').setValue(value.alteryxRoutineId);
this.verificationRuleForm.get('template').setValue(value.template);
// Convert 'verificationRuleStatus' from string to boolean.
this.verificationRuleForm.get('verificationRuleStatus').setValue(value.verificationRuleStatus.trim().toLowerCase() == 'enabled');
// To set the subcategory/subclassification we also have to make sure the documentClassification is the same.
// WARNING: Since we have enabled the [forceSelection] option of the <p-autoComplete>,
// if the availableDocumentSubclassifications are not set, documentSubclassification won't be displayed.
this.verificationRuleForm.get('subCategoryCode').setValue(
this.documentSubclassificationsList.find(subClass =>
subClass.subclassificationName == value.template.subCategoryCode && subClass.documentClassification.classificationId == value.docClassificationCategory.classificationId
)
);
this.verificationRuleForm.updateValueAndValidity();
}
public isValid(): boolean {
return this.verificationRuleForm.valid;
}
public initForCreation() {
this.editMode = false;
this.verificationRuleForm.get('verificationRuleStatus').setValue(true); // The default value in creation mode.
this.verificationRuleForm.get('template').setValidators(null); // 'template' is not required during the creation.
}
}

View File

@ -1,6 +0,0 @@
export interface VerificationRuleSearchFormValue {
clientId: string;
categoryId: number;
docClassificationId: number;
docSubcategory: string;
}

View File

@ -1,93 +0,0 @@
<div [formGroup]="verificationRuleForm">
<div class="p-fluid p-grid">
<div class="p-col-12 p-lg-8">
<div class="p-grid p-formgrid">
<div class="p-field p-col-12 p-lg-6">
<label for="ipower-name">
iPower Client Name
</label>
<p-autoComplete id="ipower-name"
formControlName="ipowerName"
[suggestions]="ipowerClientNameSuggestions"
(completeMethod)="autosuggestIPowerClientName($event)"
(onSelect)="ipowerClientNameSelected($event)"
[forceSelection]="true">
</p-autoComplete>
</div>
<div class="p-field p-col-12 p-lg-6">
<label for="ipower-code">
iPower Client Code
</label>
<p-autoComplete id="ipower-code"
formControlName="ipowerCode"
[suggestions]="ipowerClientCodeSuggestions"
(completeMethod)="autosuggestIPowerClientCode($event)"
(onSelect)="ipowerClientCodeSelected($event)"
[forceSelection]="true">
</p-autoComplete>
</div>
<div class="p-field p-col-12 p-lg-6">
<label for="category-name">
Category Name
</label>
<p-autoComplete id="category-name"
formControlName="categoryName"
[suggestions]="categoryNameSuggestions"
(completeMethod)="autosuggestCategoryName($event)"
(onSelect)="categoryNameSelected($event)"
[forceSelection]="true">
</p-autoComplete>
</div>
<div class="p-field p-col-12 p-lg-6">
<label for="category-code">
Category Code
</label>
<p-autoComplete id="category-code"
formControlName="categoryCode"
[suggestions]="categoryCodeSuggestions"
(completeMethod)="autosuggestCategoryCode($event)"
(onSelect)="categoryCodeSelected($event)"
[forceSelection]="true">
</p-autoComplete>
</div>
</div>
</div>
<div class="p-col-12 p-lg-4">
<div class="p-grid p-formgrid">
<div class="p-field p-col-12">
<label for="document-classification">
Document Classification
</label>
<p-dropdown inputId="document-classification"
[options]="documentClassificationsList"
optionLabel="classificationName"
placeholder="Select"
formControlName="documentClassification"
(onChange)="documentClassificationSelected($event.value)"
[showClear]="true">
</p-dropdown>
</div>
<div class="p-field p-col-12">
<label for="subCategoryCode">
Document Subclassification
</label>
<p-dropdown inputId="subCategoryCode"
[options]="availableDocumentSubclassifications"
optionLabel="subclassificationName"
placeholder="Select"
formControlName="subCategoryCode"
(onChange)="documentSubclassificationSelected($event.value)"
[showClear]="true">
</p-dropdown>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { VerificationRuleSearchFormComponent } from './verification-rule-search-form.component';
describe('VerificationRuleSearchFormComponent', () => {
let component: VerificationRuleSearchFormComponent;
let fixture: ComponentFixture<VerificationRuleSearchFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ VerificationRuleSearchFormComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(VerificationRuleSearchFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,358 +0,0 @@
import { VerificationRulesService } from './../../../../shared/services/administration/verification-rules.service';
import { VerificationRule } from './../../../../shared/models/verification-rule.interface';
import { Component, Input, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder } from '@angular/forms';
import { Category } from 'src/app/shared/models/category.interface';
import { DocumentClassification } from 'src/app/shared/models/document-classification.interface';
import { DocumentSubclassification } from 'src/app/shared/models/document-subclassification.interface';
import { IPowerClient } from 'src/app/shared/models/ipower-client.interface';
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service';
import { DocumentSubclassificationsService } from 'src/app/shared/services/administration/document-subclassifications.service';
import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service';
import { VerificationRuleSearchFormValue } from './verification-rule-search-form-value.interface';
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
import { AuthService } from 'src/app/shared/services/auth.service';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-verification-rule-search-form',
templateUrl: './verification-rule-search-form.component.html',
styleUrls: ['./verification-rule-search-form.component.scss']
})
export class VerificationRuleSearchFormComponent implements OnInit {
@Input() disabled: boolean = false;
documentClassificationsList: DocumentClassification[];
documentSubclassificationsList: DocumentSubclassification[];
availableDocumentSubclassifications: DocumentSubclassification[];
previouslySelectedClassificationId: number;
categoryNameSuggestions: string[];
categoryCodeSuggestions: string[];
categorySuggestions: Category[];
selectedCategory: Category = null;
ipowerClientNameSuggestions: string[];
ipowerClientCodeSuggestions: string[];
ipowerClientSuggestions: IPowerClient[];
selectedIPowerClient: IPowerClient = null;
displayValidationMessagesEvenIfPristine: boolean;
verificationRuleForm = this.fb.group({
ipowerName: [null],
ipowerCode: [null],
categoryName: [null],
categoryCode: [null],
documentClassification: [null],
subCategoryCode: [null] // This actually represents the complete DocumentSubclassification object.
});
constructor(
private fb: FormBuilder,
private documentClassificationsService: DocumentClassificationsService,
private documentSubclassificationsService: DocumentSubclassificationsService,
private verificationRulesService: VerificationRulesService,
private categoriesService: CategoriesService,
private ipowerClientsService: IpowerClientsService,
private errorHandlingService: ErrorHandlingService,
private authService: AuthService
) { }
ngOnInit(): void {
if (this.disabled) {
Object.keys(this.verificationRuleForm.controls).forEach(ctrl => this.verificationRuleForm.get(ctrl).disable());
return; // Don't even bother initialising or requesting anything.
}
this.initData();
}
initData() {
this.documentClassificationsService.getAll().subscribe(
value => this.documentClassificationsList = value,
err => this.errorHandlingService.showHttpResponseError(err)
);
// This is NOT the list of Subclassifications used for the dropdown.
this.documentSubclassificationsService.getAll().subscribe(
value => {
this.documentSubclassificationsList = value;
this.availableDocumentSubclassifications = value;
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
clear() {
this.verificationRuleForm.reset();
this.selectedCategory = null;
this.selectedIPowerClient = null;
}
documentClassificationSelected(selection: DocumentClassification) {
// If a different Classification has been selected, reset the Subclassification's value.
if (this.previouslySelectedClassificationId && selection.classificationId != this.previouslySelectedClassificationId) {
this.verificationRuleForm.get('subCategoryCode').reset();
}
this.previouslySelectedClassificationId = this.verificationRuleForm.get('documentClassification').value.classificationId;
this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => element.documentClassification.classificationId == selection.classificationId);
}
documentSubclassificationSelected(selection: DocumentSubclassification) {
this.verificationRuleForm.get('documentClassification').setValue(selection.documentClassification);
}
/*
* Auto-suggest/complete Categories
*/
autosuggestCategoryName(event) {
if (!event.query || event.query.length < 3) {
this.categoryNameSuggestions = [];
return;
}
let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null;
this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe(
(values: Category[]) => {
let temp: string[] = [];
this.categorySuggestions = values;
values.map(val => temp.push(val.categoryName));
this.categoryNameSuggestions = temp
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
autosuggestCategoryCode(event) {
if (event.query.length < 3) {
this.categoryCodeSuggestions = [];
return;
}
let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null;
this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe(
(values: Category[]) => {
let temp: string[] = [];
this.categorySuggestions = values;
values.map(val => temp.push(val.categoryCode));
this.categoryCodeSuggestions = temp
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
categoryNameSelected(name: string) {
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name);
this.verificationRuleForm.get('categoryCode').patchValue(this.selectedCategory.categoryCode);
this.verificationRuleForm.updateValueAndValidity();
}
categoryCodeSelected(code: string) {
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code);
this.verificationRuleForm.get('categoryName').patchValue(this.selectedCategory.categoryName);
this.verificationRuleForm.updateValueAndValidity();
}
// /*
// * Auto-suggest/complete iPower Clients
// */
// autosuggestIPowerClientName(event) {
// if (!event.query || event.query.length < 3) {
// this.ipowerClientNameSuggestions = [];
// return;
// }
// this.ipowerClientsService.getClientsByNameDistinct(event.query).subscribe(
// (values: IPowerClient[]) => {
// let temp: string[] = [];
// this.ipowerClientSuggestions = values;
// values.map(val => temp.push(val.name));
// this.ipowerClientNameSuggestions = temp
// },
// err => this.errorHandlingService.showHttpResponseError(err)
// );
// }
// autosuggestIPowerClientCode(event) {
// if (!event.query || event.query.length < 3) {
// this.ipowerClientCodeSuggestions = [];
// return;
// }
// this.ipowerClientsService.getClientsByCodeDistinct(event.query).subscribe(
// (values: IPowerClient[]) => {
// let temp: string[] = [];
// this.ipowerClientSuggestions = values;
// values.map(val => temp.push(val.clientCode));
// this.ipowerClientCodeSuggestions = temp
// },
// err => this.errorHandlingService.showHttpResponseError(err)
// );
// }
autosuggestIPowerClientCode(event) {
if (event.query.length < 3) {
this.ipowerClientCodeSuggestions = [];
return;
}
// If the user has the right to Preview of Scheduling Procedure (A02), we use the endpoint that returns all iPowerClients,
// otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button.
let endpointToSubscribeTo: Observable<IPowerClient[]> = this.authService.userHasRightForClient(USER_RIGHTS.B01, environment.globalRightsClientID)
? this.ipowerClientsService.getClientsByCodeOnly(event.query)
: this.authService.userRights.find(rdc => USER_RIGHTS.B02.isGrantedToUser(rdc.rights)) != null ? this.ipowerClientsService.getClientsByCodeDistinct(event.query) : null;
endpointToSubscribeTo.subscribe(
(values: IPowerClient[]) => {
let temp: string[] = [];
this.ipowerClientSuggestions = values;
values.map(val => temp.push(val.clientCode));
this.ipowerClientCodeSuggestions = temp
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
/*
* Auto-suggest & Auto-complete IPower Client
*/
autosuggestIPowerClientName(event): void {
if (!event.query || event.query.length < 3) {
this.ipowerClientNameSuggestions = [];
return;
}
// If the user has the right to Preview of Scheduling Procedure (A02), we use the endpoint that returns all iPowerClients,
// otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button.
let endpointToSubscribeTo: Observable<IPowerClient[]> = this.authService.userHasRightForClient(USER_RIGHTS.B01, environment.globalRightsClientID)
? this.ipowerClientsService.getClientsByNameOnly(event.query)
: this.authService.userRights.find(rdc => USER_RIGHTS.B02.isGrantedToUser(rdc.rights)) != null ? this.ipowerClientsService.getClientsByNameDistinct(event.query) : null;
endpointToSubscribeTo.subscribe(
(values: IPowerClient[]) => {
this.ipowerClientSuggestions = values;
const temp: string[] = [];
values.map(val => temp.push(val.name));
this.ipowerClientNameSuggestions = temp;
},
err => this.errorHandlingService.showHttpResponseError(err)
);
}
ipowerClientNameSelected(name: string) {
this.selectedIPowerClient = this.ipowerClientSuggestions.find(client => client.name == name);
this.verificationRuleForm.get('ipowerCode').patchValue(this.selectedIPowerClient.clientCode);
this.verificationRuleForm.updateValueAndValidity();
}
ipowerClientCodeSelected(code: string) {
this.selectedIPowerClient = this.ipowerClientSuggestions.find(client => client.clientCode == code);
this.verificationRuleForm.get('ipowerName').patchValue(this.selectedIPowerClient.name);
this.verificationRuleForm.updateValueAndValidity();
}
/*
* Utility Methods
*/
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedCategory, otherwise truncate it.
syncSelectedCategory() {
// Ιf our form has no value, truncate the selectedCategory either way.
if (!this.verificationRuleForm.get('categoryName').value && !this.verificationRuleForm.get('categoryCode').value) {
this.selectedCategory = null;
return;
}
// If both or either of our form's values match the selectedCategory's and the other one doesn't have a value, all is good.
// Just sync the values in case one is missing. Otherwise truncate the selectedCategory.
if (
this.verificationRuleForm.get('categoryName').value == this.selectedCategory.categoryName
|| this.verificationRuleForm.get('categoryCode').value == this.selectedCategory.categoryCode
) {
this.selectedCategory.categoryName = this.verificationRuleForm.get('categoryName').value;
this.selectedCategory.categoryCode = this.verificationRuleForm.get('categoryCode').value;
}
// If both our values were different from the selectedCategory's, truncate it. This is an extremely abnormal scenario.
else {
console.error('WARNING - syncSelectedCategory()', 'Both of our form\'s values were different from the selectedCategory\'s.');
this.selectedCategory = null;
this.verificationRuleForm.get('categoryName').setValue('');
this.verificationRuleForm.get('categoryCode').setValue('');
this.verificationRuleForm.updateValueAndValidity();
}
}
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedIPowerClient, otherwise truncate it.
syncSelectedIPowerClient() {
// Ιf our form has no value, truncate the selectedIPowerClient either way.
if (!this.verificationRuleForm.get('ipowerName').value && !this.verificationRuleForm.get('ipowerCode').value) {
this.selectedIPowerClient = null;
return;
}
// If both or either of our form's values match the selectedIPowerClient's and the other one doesn't have a value, all is good.
// Just sync the values in case one is missing. Otherwise truncate the selectedIPowerClient.
if (
this.verificationRuleForm.get('ipowerName').value == this.selectedIPowerClient.name
|| this.verificationRuleForm.get('ipowerCode').value == this.selectedIPowerClient.clientCode
) {
this.selectedIPowerClient.name = this.verificationRuleForm.get('ipowerName').value;
this.selectedIPowerClient.clientCode = this.verificationRuleForm.get('ipowerCode').value;
}
// If both our values were different from the selectedIPowerClient's, truncate it. This is an extremely abnormal scenario.
else {
console.error('WARNING - syncSelectedIPowerClient()', 'Both of our form\'s values were different from the selectedIPowerClient\'s.');
this.selectedIPowerClient = null;
this.verificationRuleForm.get('ipowerName').setValue('');
this.verificationRuleForm.get('ipowerCode').setValue('');
this.verificationRuleForm.updateValueAndValidity();
}
}
/*
* API methods
*/
public resetForm(): void {
this.verificationRuleForm.reset();
}
// TODO: Set type
public formValue(): VerificationRuleSearchFormValue {
this.syncSelectedCategory();
this.syncSelectedIPowerClient();
let formValue: VerificationRuleSearchFormValue = {
clientId: this.selectedIPowerClient ? this.selectedIPowerClient.id : '',
categoryId: this.selectedCategory ? this.selectedCategory.id : null,
docClassificationId: this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : '',
// The backend only requires the subcategory's name, and not the whole object. Don't ask me.
docSubcategory: this.verificationRuleForm.get('subCategoryCode').value ? this.verificationRuleForm.get('subCategoryCode').value['subclassificationName'] : ''
}
return formValue;
}
public isValid(): boolean {
return this.verificationRuleForm.valid;
}
}

View File

@ -1,30 +0,0 @@
<p-dialog [header]= "header"
[(visible)]="displayDialog"
[closable]="false"
[draggable]="false"
[modal]="true"
(onHide)="reset()"
(onShow)="onShow()"
appendTo="body">
<div class="p-grid p-nogutter">
<app-template-form [dialogLayout]="true"></app-template-form>
</div>
<div class="p-grid p-nogutter p-jc-center">
<div class="p-formgroup-inline p-mt-3">
<p-button (onClick)="cancel()"
label="Cancel"
styleClass="p-mr-2 p-button-warning">
</p-button>
<p-button *ngIf="!templateToEdit"
(onClick)="addTemplate()"
label="Add"
styleClass="p-ml-2 p-mr-2 p-button-primary">
</p-button>
<p-button *ngIf="templateToEdit && templateToEdit.id"
(onClick)="editTemplate()"
label="Update"
styleClass="p-ml-2 p-button-primary">
</p-button>
</div>
</div>
</p-dialog>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CreateTemplateDialogComponent } from './create-template-dialog.component';
describe('CreateTemplateDialogComponent', () => {
let component: CreateTemplateDialogComponent;
let fixture: ComponentFixture<CreateTemplateDialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ CreateTemplateDialogComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(CreateTemplateDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,92 +0,0 @@
import { TemplateFormComponent } from './../../forms/template-form/template-form.component';
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
import { IpowerClientsService } from './../../../../shared/services/administration/ipower-clients.service';
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { Category } from 'src/app/shared/models/category.interface';
import { DocumentClassification } from 'src/app/shared/models/document-classification.interface';
import { DocumentSubclassification } from 'src/app/shared/models/document-subclassification.interface';
import { IPowerClient } from 'src/app/shared/models/ipower-client.interface';
import { Template } from 'src/app/shared/models/template.interface';
import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service';
import { DocumentSubclassificationsService } from 'src/app/shared/services/administration/document-subclassifications.service';
import { TemplatesService } from 'src/app/shared/services/administration/templates.service';
import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service';
@Component({
selector: 'app-create-template-dialog',
templateUrl: './create-template-dialog.component.html',
styleUrls: ['./create-template-dialog.component.scss']
})
export class CreateTemplateDialogComponent implements OnInit {
@ViewChild(TemplateFormComponent) templateForm: TemplateFormComponent;
@Input() displayDialog: boolean;
@Input() header: string;
@Input() templateToEdit: Template;
@Output() cancelled = new EventEmitter<boolean>();
@Output() valueChange = new EventEmitter<any>();
displayValidationMessagesEvenIfPristine: boolean;
constructor(private templatesService: TemplatesService, private notificationService: NotificationsHandlingService) { }
ngOnInit(): void {
this.reset(); // Make sure everything is cleanly initialised.
}
reset() {
this.displayValidationMessagesEvenIfPristine = false;
if (this.templateForm) {
this.templateForm.resetForm();
}
}
onShow() {
// If a categoryToEdit was provided.
if (this.templateToEdit) {
this.templateForm.setValue(this.templateToEdit);
}
}
cancel() {
this.cancelled.emit(true);
}
addTemplate() {
// If the form is not valid, make sure validator messages are displayed and then return without doing anything.
if (!this.templateForm.isValid()) {
this.displayValidationMessagesEvenIfPristine = true;
return;
}
// TODO: What is returned from backend on create()??
this.templatesService.createNewTemplate(this.templateForm.formValue()).subscribe(result => {
this.valueChange.emit(result);
this.cancel();
this.notificationService.showCreateNewTemplateSuccess();
},
error => {
});
}
editTemplate() {
// If the form is not valid, make sure validator messages are displayed and then return without doing anything.
if (!this.templateForm.isValid()) {
this.displayValidationMessagesEvenIfPristine = true;
return;
}
// TODO: What is returned from backend on create()??
this.templatesService.updateTemplate(this.templateForm.formValue()).subscribe(result => {
this.valueChange.emit(result);
this.cancel();
this.notificationService.showUpdateTemplateSuccess();
},
error => {
});
}
}

Some files were not shown because too many files have changed in this diff Show More