projects material geid

This commit is contained in:
Diamantis Tziotzios 2017-12-14 15:10:56 +02:00
parent fbc76556f7
commit c3ef5dfe63
28 changed files with 970 additions and 257 deletions

View File

@ -0,0 +1,3 @@
export class BaseCriteria {
public Like: string;
}

View File

@ -0,0 +1,3 @@
export class BaseCriteriaErrorModel {
public Like: String;
}

View File

@ -0,0 +1,6 @@
import { BaseCriteria } from "./BaseCriteria";
export class DataManagementPlanCriteria extends BaseCriteria {
public PeriodStart: Date;
public PeriodEnd: Date;
}

View File

@ -0,0 +1,6 @@
import { BaseCriteriaErrorModel } from "../BaseCriteriaErrorModel";
export class DataManagementPlanCriteriaErrorModel extends BaseCriteriaErrorModel{
public PeriodStart: String;
public PeriodEnd: String;
}

View File

@ -0,0 +1,6 @@
import { BaseCriteria } from "./BaseCriteria";
export class ProjectCriteria extends BaseCriteria {
public PeriodStart: Date;
public PeriodEnd: Date;
}

View File

@ -0,0 +1,6 @@
import { BaseCriteriaErrorModel } from "../BaseCriteriaErrorModel";
export class ProjectCriteriaErrorModel extends BaseCriteriaErrorModel{
public PeriodStart: String;
public PeriodEnd: String;
}

View File

@ -0,0 +1,27 @@
import { Serializable } from "../Serializable";
export class DmpListingModel implements Serializable<DmpListingModel> {
public id: String;
public label: String;
public abbreviation: String;
public reference: String;
public uri: String;
public status: String;
public startDate: Date;
public endDate: Date;
public description: String;
fromJSONObject(item: any): DmpListingModel {
this.id = item.id;
this.label = item.label;
this.abbreviation = item.abbreviation;
this.reference = item.reference;
this.uri = item.uri;
this.status = item.status;
this.startDate = item.startDate;
this.endDate = item.endDate;
this.description = item.description;
return this;
}
}

View File

@ -0,0 +1,27 @@
import { Serializable } from "../Serializable";
export class DmpModel implements Serializable<DmpModel> {
public id: String;
public label: String;
public abbreviation: String;
public reference: String;
public uri: String;
public status: String;
public startDate: Date;
public endDate: Date;
public description: String;
fromJSONObject(item: any): DmpModel {
this.id = item.id;
this.label = item.label;
this.abbreviation = item.abbreviation;
this.reference = item.reference;
this.uri = item.uri;
this.status = item.status;
this.startDate = item.startDate;
this.endDate = item.endDate;
this.description = item.description;
return this;
}
}

View File

@ -0,0 +1,4 @@
export class DataTableData<T> {
data = new Array<T>();
totalCount = 0;
}

View File

@ -0,0 +1,14 @@
import { ProjectCriteria } from "../criteria/ProjectCriteria";
import { DataManagementPlanCriteria } from "../criteria/DataManagementPlanCriteria";
export class DataTableRequest {
offset = 0;
length = 0;
projectCriteria: ProjectCriteria;
dmpCriteria: DataManagementPlanCriteria;
constructor(offset: number, length: number) {
this.length = length;
this.offset = offset;
}
}

View File

@ -0,0 +1,3 @@
export class BaseErrorModel {
}

View File

@ -0,0 +1,27 @@
import { Serializable } from "../Serializable";
export class ProjectListingModel implements Serializable<ProjectListingModel> {
public id: String;
public label: String;
public abbreviation: String;
public reference: String;
public uri: String;
public status: String;
public startDate: Date;
public endDate: Date;
public description: String;
fromJSONObject(item: any): ProjectListingModel {
this.id = item.id;
this.label = item.label;
this.abbreviation = item.abbreviation;
this.reference = item.reference;
this.uri = item.uri;
this.status = item.status;
this.startDate = item.startDate;
this.endDate = item.endDate;
this.description = item.description;
return this;
}
}

View File

@ -0,0 +1,27 @@
import { Serializable } from "../Serializable";
export class ProjectModel implements Serializable<ProjectModel> {
public id: String;
public label: String;
public abbreviation: String;
public reference: String;
public uri: String;
public status: String;
public startDate: Date;
public endDate: Date;
public description: String;
fromJSONObject(item: any): ProjectModel {
this.id = item.id;
this.label = item.label;
this.abbreviation = item.abbreviation;
this.reference = item.reference;
this.uri = item.uri;
this.status = item.status;
this.startDate = item.startDate;
this.endDate = item.endDate;
this.description = item.description;
return this;
}
}

View File

@ -0,0 +1,20 @@
.mat-card {
overflow: auto;
padding: 0px;
}
.mat-table {
margin: 24px;
}
.mat-progress-bar {
position: absolute;
}
.mat-fab-bottom-right {
top: auto !important;
right: 20px !important;
bottom: 10px !important;
left: auto !important;
position: fixed !important;
}

View File

@ -1,4 +1,57 @@
<meta name="google-signin-client_id" content="524432312250-vhgidft856v8qftsc81kls4c74v87d8o.apps.googleusercontent.com">
<div class="container-fluid">
<h3>{{'PROJECT-LISTING.TITLE' | translate}}</h3>
<app-projects-criteria-component></app-projects-criteria-component>
<mat-card class="mat-card">
<mat-progress-bar *ngIf="dataSource?.isLoadingResults" mode="query"></mat-progress-bar>
<mat-table [dataSource]="dataSource" matSort>
<!-- Column Definition: Name -->
<ng-container cdkColumnDef="name">
<mat-header-cell *matHeaderCellDef>{{'PROJECT-LISTING.COLUMNS.NAME' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.name}}</mat-cell>
</ng-container>
<!-- Column Definition: Αbbreviation -->
<ng-container cdkColumnDef="abbreviation">
<mat-header-cell *matHeaderCellDef>{{'PROJECT-LISTING.COLUMNS.ABBREVIATION' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.abbreviation}} </mat-cell>
</ng-container>
<!-- Column Definition: Start -->
<ng-container cdkColumnDef="start">
<mat-header-cell *matHeaderCellDef>{{'PROJECT-LISTING.COLUMNS.START' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.start}} </mat-cell>
</ng-container>
<!-- Column Definition: End -->
<ng-container cdkColumnDef="end">
<mat-header-cell *matHeaderCellDef>{{'PROJECT-LISTING.COLUMNS.END' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.end}} </mat-cell>
</ng-container>
<!-- Column Definition: Submission Time -->
<ng-container cdkColumnDef="actions">
<mat-header-cell *matHeaderCellDef>{{'PROJECT-LISTING.COLUMNS.ACTIONS' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"></mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns" (click)="rowClick(row.id)"></mat-row>
</mat-table>
<mat-paginator #paginator
[length]="dataSource?.totalCount"
[pageSizeOptions]="[10, 25, 100]">
</mat-paginator>
</mat-card>
<button mat-fab class="mat-fab-bottom-right" color="primary" [routerLink]=" ['./new'] ">
<mat-icon class="mat-24">add</mat-icon>
</button>
</div>
<!-- <meta name="google-signin-client_id" content="524432312250-vhgidft856v8qftsc81kls4c74v87d8o.apps.googleusercontent.com">
<table class="table table-striped" [mfData]="tableData | projectTableFilter : filterQuery : whoami?.id : onlyMyProjects"
#mf="mfDataTable" [mfRowsOnPage]="rowsOnPage" [(mfSortBy)]="sortBy" [(mfSortOrder)]="sortOrder">
@ -63,11 +116,6 @@
<a [ngClass]="{'not-active': whoami?.id!=project?.creationUser?.id }" class="editGridColumn" (click)="editRow(project, $event)">
<i class="fa fa-pencil fa-fw" data-toggle="tooltip" title="edit properties" id="editDMP" ></i>
</a>
<!--
<a>
<i class="fa fa-eraser fa-fw" data-toggle="tooltip" title="delete project"></i>
</a>
-->
</td>
</tr>
@ -139,4 +187,4 @@
</div>
</div>
</div>
-->

View File

@ -0,0 +1,297 @@
import { Component, ViewChild, OnInit, AfterViewInit } from "@angular/core";
import { MatPaginator, MatSort, MatSnackBar } from "@angular/material";
import { Router } from "@angular/router";
import { TranslateService } from "@ngx-translate/core";
import { DataSource } from "@angular/cdk/table";
import { ProjectListingModel } from "../models/projects/ProjectListingModel";
import { ProjectService } from "../services/project/project.service";
import { ProjectCriteriaComponent } from "../shared/components/criteria/projects/projects-criteria.component";
import { ProjectCriteria } from "../models/criteria/project/ProjectCriteria";
import { Observable } from "rxjs/Observable";
import { DataTableRequest } from "../models/data-table/DataTableRequest";
import { SnackBarNotificationComponent } from "../shared/components/notificaiton/snack-bar-notification.component";
@Component({
selector: 'app-project-listing-component',
templateUrl: 'project-listing.component.html',
styleUrls: ['./project-listing.component.css'],
providers: [ProjectService]
})
export class FormsComponent implements OnInit, AfterViewInit {
@ViewChild(MatPaginator) _paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
@ViewChild(ProjectCriteriaComponent) criteria: ProjectCriteriaComponent;
dataSource: FormsDataSource | null;
displayedColumns: String[] = ['type', 'projectName', 'submissionTime', 'description', 'status'];
constructor(
private projectService: ProjectService,
private router: Router,
private languageService: TranslateService,
public snackBar: MatSnackBar,
) {
}
ngOnInit() {
}
ngAfterViewInit() {
setTimeout(() => {
this.criteria.setRefreshCallback(() => this.refresh());
this.criteria.setCriteria(this.getDefaultCriteria());
this.criteria.controlModified();
});
}
refresh() {
this.dataSource = new FormsDataSource(this.projectService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria, );
}
rowClick(rowId: String) {
this.router.navigate(['/forms/' + rowId]);
}
getDefaultCriteria(): ProjectCriteria {
const defaultCriteria = new ProjectCriteria();
return defaultCriteria;
}
// canShowOwner(): boolean {
// const principal: Principal = this.authentication.current();
// if (principal) {
// const principalRoles = principal.appRoles;
// for (let i = 0; i < principalRoles.length; i++) {
// if (principalRoles[i] === Principal.AppRole.Admin || principalRoles[i] === Principal.AppRole.BudgetManager) {
// return true;
// }
// }
// }
// return false;
// }
}
export class FormsDataSource extends DataSource<ProjectListingModel> {
totalCount = 0;
isLoadingResults = false;
constructor(
private _service: ProjectService,
private _paginator: MatPaginator,
private _sort: MatSort,
private _languageService: TranslateService,
private _snackBar: MatSnackBar,
private _criteria: ProjectCriteriaComponent
) {
super();
//this._paginator.page.subscribe((pageEvent: PageEvent) => {
// this.store.dispatch(new LoadPhotosRequestAction(pageEvent.pageIndex, pageEvent.pageSize))
//})
}
connect(): Observable<ProjectListingModel[]> {
const displayDataChanges = [
this._paginator.page
//this._sort.matSortChange
];
// If the user changes the sort order, reset back to the first page.
//this._sort.matSortChange.subscribe(() => {
// this._paginator.pageIndex = 0;
//})
return Observable.merge(...displayDataChanges)
.startWith(null)
.switchMap(() => {
setTimeout(() => {
this.isLoadingResults = true;
});
const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
const request = new DataTableRequest(startIndex, this._paginator.pageSize);
request.projectCriteria = this._criteria.getFormData();
return this._service.getPaged(request);
})
.catch((error: any) => {
this._snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService },
duration: 3000,
extraClasses: ['snackbar-warning']
});
this._criteria.onCallbackError(error);
return Observable.of(null);
})
.map(result => {
setTimeout(() => {
this.isLoadingResults = false;
});
return result;
})
.map(result => {
if (!result) { return []; }
if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; }
return result.data;
});
}
disconnect() {
// No-op
}
}
// export class ProjectListingComponent implements OnInit{
// // Start ALTERNATIVE
// //whole dmp data model
// tableData : any[] = new Array();
// //organisation editor data model
// editingOrganisation: any = {};
// organisationEditorForm : any;
// //required by the table
// public filterQuery = "";
// public rowsOnPage = 10;
// public sortBy = "label";
// public sortOrder = "asc";
// // for tableIds
// showIDs : boolean = false;
// statusDropDown: DropdownField;
// project: any;
// whoami: any;
// onlyMyProjects : boolean = false;
// options: DatepickerOptions = {
// minYear: 1900,
// maxYear: 2050,
// displayFormat: 'MMM D[,] YYYY',
// barTitleFormat: 'MMMM YYYY',
// firstCalendarDay: 0 // 0 - Sunday, 1 - Monday
// };
// //breadcrumbHome: MenuItem = {icon: 'fa fa-home'};
// breadcrumbData: MenuItem[] = new Array<MenuItem>();
// constructor(
// private serverService: ServerService,
// private route: ActivatedRoute,
// private router: Router) {
// this.statusDropDown = new DropdownField();
// this.statusDropDown.options= [{key:'0', value:"Active"},{key:'1', value:"Inactive"}]
// this.project = this.getEmptyProject();
// }
// ngAfterViewInit() {
// }
// getEmptyProject(){
// return {
// label: '',
// abbreviation:'',
// reference:'',
// uri:'',
// description:'',
// enddate:'',
// startdate:''
// }
// }
// ngOnInit() {
// this.getProjects();
// this.serverService.whoami().subscribe(
// response => {
// this.whoami = response;
// console.log(this.whoami)
// },
// err => {
// simple_notifier("danger",null,"Could not retrieve user config");
// }
// );
// }
// getProjects(muted? : boolean){
// //this.serverService.getProjectsOfUser().subscribe(
// this.serverService.getAllProjects().subscribe(
// response => {
// this.tableData = response;
// if(muted && muted!=true)
// simple_notifier("success",null,"Updated projects table");
// },
// err => {
// simple_notifier("danger",null,"Could not retrieve projects");
// }
// );
// }
// showDatasets(){ //dmpId, event
// //this.dataSetVisibe = true;
// }
// SaveProject(){
// let action : Observable<any>;
// if(this.project.id == null) //means it's a new one
// action = this.serverService.createProject(this.project);
// else
// action = this.serverService.updateProject(this.project);
// action.subscribe(
// response =>{
// this.getProjects();
// simple_notifier("success",null, (this.project.id == null) ? "Created" : "Updated" +" projects table");
// },
// error => {
// simple_notifier("danger",null, "Could not "+ (this.project.id == null) ? "create" : "update" + " projects table");
// }
// );
// $("#newEditProjectModal").modal("hide");
// }
// newProject(){
// this.project = this.getEmptyProject();
// $("#newEditProjectModal").modal("show");
// }
// editRow(item, event){
// this.project = Object.assign({}, item); //this will have id - that defines whether it's an update or not
// this.project.creationUser = {"id":this.project.creationUser.id};
// $("#newEditProjectModal").modal("show");
// return false;
// }
// /*
// markProjectForDelete(project){
// this.project = project;
// }
// deleteProject(confirmation){
// if(confirmation==true)
// this.deleteRow(this.project);
// }
// */
// }

View File

@ -1,62 +0,0 @@
:host /deep/ .index-column,
:host /deep/ .index-column-header {
text-align: right;
}
:host /deep/ .data-table .data-table-row.selected {
background-color: #E4EDF9;
}
a.editGridColumn{
color: #333;
}
.invisible {
display:none;
}
.visible {
display:block;
}
tr.hover:hover > * {
background-color: #eeeeee;
}
.editor-container{
padding-top: 10px;
padding-right: 10px;
padding-bottom: 10px;
padding-left: 10px;
}
.button-150px {
max-width: 150px;
}
.ng-template{
text-align: right;
}
.grayout-empty-table {
opacity: 0.6; /* Real browsers */
filter: alpha(opacity = 60); /* MSIE */
text-align: center;
vertical-align: middle;
}
.btncustom{
background-color:#337ab7;
color:white;
margin-top:15px;
}
a{
cursor: pointer;
}
.not-active {
pointer-events: none;
cursor:not-allowed;
opacity: 0.5;
filter: alpha(opacity=50); /* For IE8 and earlier */
}

View File

@ -1,188 +0,0 @@
import { Component, OnInit, Input, Output, EventEmitter, ViewChild } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {GoogleSignInSuccess} from 'angular-google-signin';
import { Router, ActivatedRoute } from '@angular/router';
import { ServerService } from '../../app/services/server.service';
import { Project } from '../entities/model/project';
import { Dmp } from '../entities/model/dmp';
import { Dataset } from '../entities/model/dataset';
//import { DataTable, DataTableTranslations, DataTableResource } from 'angular-4-data-table-bootstrap-4';
import {DataTable} from 'angular2-datatable';
import { DropdownField } from '../../app/form/fields/dropdown/field-dropdown';
import { Param } from '../entities/model/param';
import { ModalComponent } from '../modal/modal.component';
import { HttpErrorResponse } from '@angular/common/http';
import { FormGroup, FormControl } from '@angular/forms'; //na dw an xreiazontai
import { NgForm } from '@angular/forms';
import { DatepickerOptions } from 'ng2-datepicker';
import { StatusToString} from '../pipes/various/status-to-string';
import { ConfirmationComponent } from '../widgets/confirmation/confirmation.component';
import {MenuItem} from 'primeng/primeng';
import { ProjectTableFilterPipe } from '../pipes/project-table-filter.pipe';
declare var $ :any;
import '../../assets/custom.js';
declare function simple_notifier(type: string, title: string, message:string): any;
@Component({
selector: 'projects',
templateUrl: 'project.html',
styleUrls: ['./project.css'],
providers: [ServerService]
})
export class ProjectsComponent implements OnInit{
// Start ALTERNATIVE
//whole dmp data model
tableData : any[] = new Array();
//organisation editor data model
editingOrganisation: any = {};
organisationEditorForm : any;
//required by the table
public filterQuery = "";
public rowsOnPage = 10;
public sortBy = "label";
public sortOrder = "asc";
// for tableIds
showIDs : boolean = false;
statusDropDown: DropdownField;
project: any;
whoami: any;
onlyMyProjects : boolean = false;
options: DatepickerOptions = {
minYear: 1900,
maxYear: 2050,
displayFormat: 'MMM D[,] YYYY',
barTitleFormat: 'MMMM YYYY',
firstCalendarDay: 0 // 0 - Sunday, 1 - Monday
};
//breadcrumbHome: MenuItem = {icon: 'fa fa-home'};
breadcrumbData: MenuItem[] = new Array<MenuItem>();
constructor(
private serverService: ServerService,
private route: ActivatedRoute,
private router: Router) {
this.statusDropDown = new DropdownField();
this.statusDropDown.options= [{key:'0', value:"Active"},{key:'1', value:"Inactive"}]
this.project = this.getEmptyProject();
}
ngAfterViewInit() {
}
getEmptyProject(){
return {
label: '',
abbreviation:'',
reference:'',
uri:'',
description:'',
enddate:'',
startdate:''
}
}
ngOnInit() {
this.getProjects();
this.serverService.whoami().subscribe(
response => {
this.whoami = response;
console.log(this.whoami)
},
err => {
simple_notifier("danger",null,"Could not retrieve user config");
}
);
}
getProjects(muted? : boolean){
//this.serverService.getProjectsOfUser().subscribe(
this.serverService.getAllProjects().subscribe(
response => {
this.tableData = response;
if(muted && muted!=true)
simple_notifier("success",null,"Updated projects table");
},
err => {
simple_notifier("danger",null,"Could not retrieve projects");
}
);
}
showDatasets(){ //dmpId, event
//this.dataSetVisibe = true;
}
SaveProject(){
let action : Observable<any>;
if(this.project.id == null) //means it's a new one
action = this.serverService.createProject(this.project);
else
action = this.serverService.updateProject(this.project);
action.subscribe(
response =>{
this.getProjects();
simple_notifier("success",null, (this.project.id == null) ? "Created" : "Updated" +" projects table");
},
error => {
simple_notifier("danger",null, "Could not "+ (this.project.id == null) ? "create" : "update" + " projects table");
}
);
$("#newEditProjectModal").modal("hide");
}
newProject(){
this.project = this.getEmptyProject();
$("#newEditProjectModal").modal("show");
}
editRow(item, event){
this.project = Object.assign({}, item); //this will have id - that defines whether it's an update or not
this.project.creationUser = {"id":this.project.creationUser.id};
$("#newEditProjectModal").modal("show");
return false;
}
/*
markProjectForDelete(project){
this.project = project;
}
deleteProject(confirmation){
if(confirmation==true)
this.deleteRow(this.project);
}
*/
}

View File

@ -0,0 +1,35 @@
import 'rxjs/add/operator/map';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HostConfiguration } from './../../app.constants';
import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service';
import { Observable } from 'rxjs/Observable';
import { DataTableRequest } from '../../models/data-table/DataTableRequest';
import { DataTableData } from '../../models/data-table/DataTableData';
import { DmpListingModel } from '../../models/data-managemnt-plans/DmpListingModel';
import { DmpModel } from '../../models/data-managemnt-plans/DmpModel';
@Injectable()
export class DataManagementPlanService {
private actionUrl: string;
private headers: HttpHeaders;
constructor(private http: BaseHttpService) {
this.actionUrl = HostConfiguration.Server + 'api/dmp/';
this.headers = new HttpHeaders();
this.headers = this.headers.set('Content-Type', 'application/json');
this.headers = this.headers.set('Accept', 'application/json');
}
getPaged(dataTableRequest: DataTableRequest): Observable<DataTableData<DmpListingModel>> {
return this.http.post<DataTableData<DmpListingModel>>(this.actionUrl + 'getPaged', JSON.stringify(dataTableRequest), { headers: this.headers });
}
getSingle(id: string): Observable<DmpModel> {
return this.http.get<DmpModel>(this.actionUrl + id, { headers: this.headers });
}
}

View File

@ -0,0 +1,35 @@
import 'rxjs/add/operator/map';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HostConfiguration } from './../../app.constants';
import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service';
import { Observable } from 'rxjs/Observable';
import { DataTableRequest } from '../../models/data-table/DataTableRequest';
import { DataTableData } from '../../models/data-table/DataTableData';
import { ProjectListingModel } from '../../models/projects/ProjectListingModel';
import { ProjectModel } from '../../models/projects/ProjectModel';
@Injectable()
export class ProjectService {
private actionUrl: string;
private headers: HttpHeaders;
constructor(private http: BaseHttpService) {
this.actionUrl = HostConfiguration.Server + 'api/project/';
this.headers = new HttpHeaders();
this.headers = this.headers.set('Content-Type', 'application/json');
this.headers = this.headers.set('Accept', 'application/json');
}
getPaged(dataTableRequest: DataTableRequest): Observable<DataTableData<ProjectListingModel>> {
return this.http.post<DataTableData<ProjectListingModel>>(this.actionUrl + 'getPaged', JSON.stringify(dataTableRequest), { headers: this.headers });
}
getSingle(id: string): Observable<ProjectModel> {
return this.http.get<ProjectModel>(this.actionUrl + id, { headers: this.headers });
}
}

View File

@ -0,0 +1,102 @@
import { Component, OnInit, Input } from '@angular/core';
import { FormControl, FormGroup, NgForm, FormArray, AbstractControl } from '@angular/forms';
import { CriteriaErrorModel } from '../../../../models/criteria/criteriaErrorModel';
@Component({
selector: 'base-criteria-component',
template: '',
providers: [
]
})
export class BaseCriteriaComponent implements OnInit {
public refreshCallback: Function = null;
public formGroup: FormGroup = null;
constructor(
public baseErrorModel?: CriteriaErrorModel,
) {
}
ngOnInit() {
if (this.baseErrorModel == null) { this.baseErrorModel = new CriteriaErrorModel(); }
}
controlModified(): void {
this.clearErrorModel();
if (!this.isFormValid()) { return; }
if (this.refreshCallback != null) { this.refreshCallback(); }
}
public isFormValid(): boolean {
this.touchAllFormFields(this.formGroup);
this.validateAllFormFields(this.formGroup);
return this.formGroup.valid;
}
public getFormData(): any {
return this.formGroup.value;
}
public getFormControl(controlName: string): AbstractControl {
return this.formGroup.get(controlName);
}
public disableFormFields(formControl: AbstractControl) {
formControl.disable();
}
public validateAllFormFields(formControl: AbstractControl) {
if (formControl instanceof FormControl) {
formControl.updateValueAndValidity({ emitEvent: false })
} else if (formControl instanceof FormGroup) {
Object.keys(formControl.controls).forEach(item => {
const control = formControl.get(item);
this.validateAllFormFields(control);
})
} else if (formControl instanceof FormArray) {
formControl.controls.forEach(item => {
this.validateAllFormFields(item);
})
}
}
public touchAllFormFields(formControl: AbstractControl) {
if (formControl instanceof FormControl) {
formControl.markAsTouched();
} else if (formControl instanceof FormGroup) {
Object.keys(formControl.controls).forEach(item => {
const control = formControl.get(item);
this.touchAllFormFields(control);
})
} else if (formControl instanceof FormArray) {
formControl.controls.forEach(item => {
this.touchAllFormFields(item);
})
}
}
setRefreshCallback(callback: Function): void {
this.refreshCallback = callback;
}
onCallbackError(error: any) {
this.setErrorModel(error.error);
this.validateAllFormFields(this.formGroup);
}
public setErrorModel(errorModel: CriteriaErrorModel) {
Object.keys(errorModel).forEach(item => {
(<any>this.baseErrorModel)[item] = (<any>errorModel)[item];
})
}
public clearErrorModel() {
Object.keys(this.baseErrorModel).forEach(item => {
(<any>this.baseErrorModel)[item] = '';
})
}
}

View File

@ -0,0 +1,54 @@
<form class="form-criteria" [formGroup]="formGroup">
<mat-card class="mat-card">
<div class="row">
<div class="col-sm-6 col-md-2">
<mat-form-field>
<input matInput
(focus)="periodFromPicker.open()"
(click)="periodFromPicker.open()"
placeholder=" {{'CRITERIA.FORMS.PERIOD-FROM'| translate}}"
[matDatepicker]="periodFromPicker"
formControlName="periodFrom"
[ngModel]="this.criteria.PeriodFrom" (ngModelChange)="controlModified()">
<mat-error *ngIf="getFormControl('periodFrom').errors?.backendError">{{baseErrorModel['Criteria.PeriodFrom']}}</mat-error>
<mat-datepicker-toggle matSuffix [for]="periodFromPicker"></mat-datepicker-toggle>
<mat-datepicker #periodFromPicker></mat-datepicker>
</mat-form-field>
</div>
<div class="col-sm-6 col-md-2">
<mat-form-field>
<input matInput
(focus)="periodToPicker.open()"
(click)="periodToPicker.open()"
placeholder=" {{'CRITERIA.FORMS.PERIOD-TO'| translate}}"
[matDatepicker]="periodToPicker"
formControlName="periodTo"
[ngModel]="this.criteria.PeriodTo" (ngModelChange)="controlModified()">
<mat-error *ngIf="getFormControl('periodTo').errors?.backendError">{{baseErrorModel['Criteria.PeriodTo']}}</mat-error>
<mat-datepicker-toggle matSuffix [for]="periodToPicker"></mat-datepicker-toggle>
<mat-datepicker #periodToPicker></mat-datepicker>
</mat-form-field>
</div>
<div class="col-sm-6 col-md-5">
<mat-form-field>
<mat-select placeholder="{{'CRITERIA.FORMS.TYPE' | translate}}"
formControlName="type"
(change)="controlModified()">
<mat-option>{{'TYPES.FORM-TYPE.ANY' | translate}}</mat-option>
<mat-option *ngFor="let type of getFormTypeValues()" [value]="type">{{getFormTypeWithLanguage(type)}}</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="col-sm-6 col-md-3">
<mat-form-field>
<mat-select placeholder="{{'CRITERIA.FORMS.STATUS' | translate}}"
formControlName="status"
(change)="controlModified()"
multiple>
<mat-option *ngFor="let status of getFormStatusValues()" [value]="status">{{getFormStatusWithLanguage(status)}}</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</mat-card>
</form>

View File

@ -0,0 +1,10 @@
.form-criteria {
mat-form-field {
padding-bottom: 5px;
width: 100%;
}
mat-card {
padding-bottom: 0px;
}
}

View File

@ -0,0 +1,69 @@
import { TranslateService } from '@ngx-translate/core';
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
import { BaseCriteriaComponent } from '../base/base-criteria.component';
import { ValidationContext, Validation } from '../../../../utilities/validators/ValidationContext';
import { BackendErrorValidator } from '../../../../utilities/validators/BackendErrorValidator';
import { ProjectCriteria } from '../../../../models/criteria/project/ProjectCriteria';
import { ProjectCriteriaErrorModel } from '../../../../models/criteria/project/ProjectCriteriaErrorModel';
@Component({
selector: 'app-projects-criteria-component',
templateUrl: './projects-criteria.component.html',
styleUrls: ['./projects-criteria.component.scss'],
providers: [
]
})
export class ProjectCriteriaComponent extends BaseCriteriaComponent implements OnInit {
// public form: ProjectType;
// public formStatus: ProjectStatus;
public criteria: ProjectCriteria = new ProjectCriteria();
constructor(
public language: TranslateService,
public errorModel: ProjectCriteriaErrorModel,
public formBuilder: FormBuilder
) {
super(errorModel);
}
ngOnInit() {
super.ngOnInit();
if (this.criteria == null) { this.criteria = new ProjectCriteria(); }
if (this.formGroup == null) { this.formGroup = this.buildForm(); }
}
setCriteria(criteria: ProjectCriteria): void {
this.criteria = criteria;
this.formGroup = this.buildForm();
}
public fromJSONObject(item: any): ProjectCriteria {
this.criteria = new ProjectCriteria();
this.criteria.PeriodStart = new Date(item.PeriodStart);
this.criteria.PeriodEnd = new Date(item.PeriodEnd);
return this.criteria;
}
buildForm(): FormGroup {
const context: ValidationContext = this.createValidationContext();
return this.formBuilder.group({
periodStart: [this.criteria.PeriodStart, context.getValidation('periodStart').validators],
periodEnd: [this.criteria.PeriodEnd, context.getValidation('periodEnd').validators],
});
}
createValidationContext(): ValidationContext {
const validationContext: ValidationContext = new ValidationContext();
const validationArray: Validation[] = new Array<Validation>();
validationArray.push({ key: 'periodStart', validators: [BackendErrorValidator(this.errorModel, 'Criteria.PeriodStart')] }); //must add 'Criteria.' because the criteria validator is inside the request validator
validationArray.push({ key: 'periodEnd', validators: [BackendErrorValidator(this.errorModel, 'Criteria.PeriodEnd')] });
validationContext.validation = validationArray;
return validationContext;
}
}

View File

@ -0,0 +1,84 @@
import { Injectable } from '@angular/core';
import { Http, RequestOptions, Response, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Router, ActivatedRoute, RouterStateSnapshot } from '@angular/router';
import { MatSnackBar } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
import { HttpClient } from '@angular/common/http';
import { AuthService } from '../../services/auth/auth.service';
import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component';
@Injectable()
export class BaseHttpService {
constructor(
protected http: HttpClient,
private router: Router,
private authService: AuthService,
public language: TranslateService,
public snackBar: MatSnackBar,
) {
}
get<T>(url: string, options?: any): Observable<T> {
return this.interceptRepsonse<T>(this.http.get(url, this.buildRequestOptions(options)));
}
post<T>(url: string, body: any, options?: any): Observable<T> {
return this.interceptRepsonse<T>(this.http.post(url, body, this.buildRequestOptions(options)));
}
put<T>(url: string, body: any, options?: any): Observable<T> {
return this.interceptRepsonse<T>(this.http.put(url, body, this.buildRequestOptions(options)));
}
delete<T>(url: string, options?: any): Observable<T> {
return this.interceptRepsonse<T>(this.http.delete(url, this.buildRequestOptions(options)));
}
patch<T>(url: string, body: any, options?: any): Observable<T> {
return this.interceptRepsonse(this.http.patch(url, body, this.buildRequestOptions(options)));
}
head<T>(url: string, options?: any): Observable<T> {
return this.interceptRepsonse<T>(this.http.head(url, this.buildRequestOptions(options)));
}
options<T>(url: string, options?: any): Observable<T> {
return this.interceptRepsonse<T>(this.http.options(url, this.buildRequestOptions(options)));
}
protected buildRequestOptions(options?: any): Object {
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
if (!options.headers.has('Content-Type')) {
options.headers = options.headers.set('Content-Type', 'application/json');
}
if (!options.headers.has('Content-Type')) {
options.headers = options.headers.set('Content-Type', 'application/json');
}
if (!options.headers.has('AuthToken')) {
const principal = this.authService.current();
if (principal) {
options.headers = options.headers.set('AuthToken', principal.token);
}
}
return options;
}
private interceptRepsonse<T>(observable: Observable<Object>): Observable<T> {
return observable
.catch((error) => {
if (error.status === 401) {
this.snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-LOGOUT', language: this.language },
duration: 3000,
extraClasses: ['snackbar-success']
})
this.router.navigate(['/unauthorized']);
//this.notification.httpError(error);
return Observable.of<T>();
} else {
return Observable.throw(error);
}
});
}
}

View File

@ -0,0 +1,21 @@
import { CommonModule } from '@angular/common';
import { NgModule, ModuleWithProviders } from '@angular/core';
import { AuthService } from '../../services/auth/auth.service';
import { BaseHttpService } from './base-http.service';
@NgModule({
imports: [
CommonModule
]
})
export class BaseHttpModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: BaseHttpModule,
providers: [
AuthService,
BaseHttpService
]
};
}
}

View File

@ -0,0 +1,9 @@
import { ValidatorFn, AbstractControl } from '@angular/forms';
import { BaseErrorModel } from '../../models/error/BaseErrorModel';
export function BackendErrorValidator(errorModel: BaseErrorModel, propertyName: string): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
const error: string = (<any>errorModel)[propertyName];
return error ? { 'backendError': { value: error } } : null;
};
}

View File

@ -0,0 +1,20 @@
import { ValidatorFn } from '@angular/forms';
export class ValidationContext {
validation: Validation[];
getValidation(key: string): Validation {
for (let i = 0; i < this.validation.length; i++) {
if (this.validation[i].key === key) {
return this.validation[i];
}
}
throw new Error('Key Was Not Found In The Validation Context');
}
}
export class Validation {
key: string;
validators?: ValidatorFn[] = new Array<ValidatorFn>();
descendantValidations?: ValidationContext;
}