Fixing UI incompatibilities

This commit is contained in:
Thomas Georgios Giannos 2023-10-05 11:41:11 +03:00
parent 074e374d9a
commit 3f14528f16
13 changed files with 219 additions and 91 deletions

View File

@ -1,5 +1,6 @@
package eu.eudat.query;
import eu.eudat.commons.enums.DescriptionTemplateTypeStatus;
import eu.eudat.data.DescriptionTemplateTypeEntity;
import eu.eudat.query.lookup.DescriptionTemplateTypeLookup;
import eu.eudat.query.lookup.LookupAware;
@ -74,6 +75,8 @@ public class DescriptionTemplateTypeQuery extends QueryBase<DescriptionTemplateT
public DescriptionTemplateTypeQuery fromLookup(DescriptionTemplateTypeLookup lookup) {
if (lookup == null)
return this;
if (lookup.getStatus() == null)
statuses(DescriptionTemplateTypeStatus.SAVED.getValue(), DescriptionTemplateTypeStatus.FINALIZED.getValue());
if (lookup.getName() != null)
names(lookup.getName());
if (lookup.getStatus() != null)

View File

@ -18,6 +18,7 @@ import java.util.UUID;
import static eu.eudat.controllers.v2.BaseController.extractQueryResultWithCount;
@RestController
@CrossOrigin
@Transactional
@RequestMapping(path = "api/v2/descriptionTemplateType", produces = MediaType.APPLICATION_JSON_VALUE)
public class DescriptionTemplateTypeV2Controller {

View File

@ -41,6 +41,7 @@
"pako": "^1.0.11",
"rxjs": "^6.3.2",
"tinymce": "^5.9.2",
"ts-simple-nameof": "^1.3.1",
"tslib": "^2.0.0",
"web-animations-js": "^2.3.2",
"zone.js": "~0.11.4"

View File

@ -53,6 +53,7 @@ import { GlossaryService } from './services/glossary/glossary.service';
import { TermsOfServiceService } from './services/terms-of-service/terms-of-service.service';
import { UnlinkAccountEmailConfirmationService } from './services/unlink-account-email-confirmation/unlink-account-email-confirmation.service';
import { DescriptionTemplateTypeService } from './services/description-template-type/description-template-type.service';
import { BaseHttpV2Service } from './services/http/base-http-v2.service';
//
//
// This is shared module that provides all the services. Its imported only once on the AppModule.
@ -79,6 +80,7 @@ export class CoreServiceModule {
AuthService,
CookieService,
BaseHttpService,
BaseHttpV2Service,
AdminAuthGuard,
SpecialAuthGuard,
AuthGuard,

View File

@ -0,0 +1,10 @@
import { Lookup } from "@common/model/lookup";
export class DescriptionTemplateTypeLookup extends Lookup {
name: string;
status: number;
constructor() {
super();
}
}

View File

@ -1,38 +1,42 @@
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpService } from '../http/base-http.service';
import { Observable } from 'rxjs';
import { DataTableData } from '@app/core/model/data-table/data-table-data';
import { DescriptionTemplateType } from '@app/core/model/description-template-type/description-template-type';
import { QueryResult } from '@common/model/query-result';
import { DescriptionTemplateTypeLookup } from '@app/core/query/description-template/description-template-type.lookup';
import { BaseHttpV2Service } from '../http/base-http-v2.service';
@Injectable()
export class DescriptionTemplateTypeService {
private actionUrl: string;
private get apiBase(): string { return `${this.configurationService.server}v2/descriptionTemplateType`; }
private headers = new HttpHeaders();
constructor(private http: BaseHttpService, private httpClient: HttpClient, private configurationService: ConfigurationService) {
this.actionUrl = configurationService.server + 'descriptionTemplateType/';
}
constructor(private http: BaseHttpV2Service, private configurationService: ConfigurationService) {}
getTypes(): Observable<DataTableData<DescriptionTemplateType>> {
return this.http.get<DataTableData<DescriptionTemplateType>>(this.actionUrl + 'get', { headers: this.headers });
getAll(lookup: DescriptionTemplateTypeLookup): Observable<QueryResult<DescriptionTemplateType>> {
const url = `${this.apiBase}/all`;
return this.http.post<QueryResult<DescriptionTemplateType>>(url, lookup, { headers: this.headers });
}
getSingle(id: string): Observable<DescriptionTemplateType> {
return this.http.get<DescriptionTemplateType>(this.actionUrl + 'get/' + id, { headers: this.headers });
getSingle(id: string): Observable<QueryResult<DescriptionTemplateType>> {
const url = `${this.apiBase}/${id}`;
return this.http.get<QueryResult<DescriptionTemplateType>>(url , { headers: this.headers });
}
createType(type: DescriptionTemplateType): Observable<DescriptionTemplateType> {
return this.http.post<DescriptionTemplateType>(this.actionUrl + 'create', type, { headers: this.headers });
create(payload: DescriptionTemplateType): Observable<QueryResult<DescriptionTemplateType>> {
const url = `${this.apiBase}/create`;
return this.http.post<QueryResult<DescriptionTemplateType>>(url, payload, { headers: this.headers });
}
updateType(type: DescriptionTemplateType): Observable<DescriptionTemplateType> {
return this.http.post<DescriptionTemplateType>(this.actionUrl + 'update', type, { headers: this.headers });
update(payload: DescriptionTemplateType): Observable<QueryResult<DescriptionTemplateType>> {
const url = `${this.apiBase}/update`;
return this.http.post<QueryResult<DescriptionTemplateType>>(url, payload, { headers: this.headers });
}
deleteType(id: string): Observable<DescriptionTemplateType> {
return this.http.delete<DescriptionTemplateType>(this.actionUrl + 'delete/' + id, { headers: this.headers });
delete(id: string): Observable<void> {
const url = `${this.apiBase}/delete/${id}`;
return this.http.delete<void>(url, { headers: this.headers });
}
}

View File

@ -0,0 +1,40 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable()
export class BaseHttpV2Service {
constructor(
protected http: HttpClient
) {
}
get<T>(url: string, options?: Object): Observable<T> {
return this.http.get<T>(url, options);
}
post<T>(url: string, body: any, options?: Object): Observable<T> {
return this.http.post<T>(url, body, options);
}
put<T>(url: string, body: any, options?: Object): Observable<T> {
return this.http.put<T>(url, body, options);
}
delete<T>(url: string, options?: Object): Observable<T> {
return this.http.delete<T>(url, options);
}
patch<T>(url: string, body: any, options?: Object): Observable<T> {
return this.http.patch<T>(url, body, options);
}
head<T>(url: string, options?: Object): Observable<T> {
return this.http.head<T>(url, options);
}
options<T>(url: string, options?: Object): Observable<T> {
return this.http.options<T>(url, options);
}
}

View File

@ -48,6 +48,8 @@ import { CheckDeactivateBaseComponent } from '@app/library/deactivate/deactivate
import { DescriptionTemplateTypeService } from '@app/core/services/description-template-type/description-template-type.service';
import { DescriptionTemplateType } from '@app/core/model/description-template-type/description-template-type';
import { DescriptionTemplateTypeStatus } from '@app/core/common/enum/description-template-type-status';
import { DescriptionTemplateTypeLookup } from '@app/core/query/description-template/description-template-type.lookup';
import { nameof } from 'ts-simple-nameof';
const skipDisable: any[] = require('../../../../../assets/resources/skipDisable.json');
@ -607,9 +609,17 @@ export class DatasetProfileEditorComponent extends CheckDeactivateBaseComponent
}
getDescriptionTemplateTypes(): DescriptionTemplateType[] {
this.descriptionTemplateTypeService.getTypes().pipe(takeUntil(this._destroyed))
let lookup: DescriptionTemplateTypeLookup = new DescriptionTemplateTypeLookup();
lookup.project = {
fields: [
nameof<DescriptionTemplateType>(x => x.id),
nameof<DescriptionTemplateType>(x => x.name),
nameof<DescriptionTemplateType>(x => x.status)
]
};
this.descriptionTemplateTypeService.getAll(lookup).pipe(takeUntil(this._destroyed))
.subscribe(types => {
this.descriptionTemplateTypes = types.data.filter(type => type.status === DescriptionTemplateTypeStatus.Finalized);
this.descriptionTemplateTypes = types.items.filter(type => type.status === DescriptionTemplateTypeStatus.Finalized);
});
return this.descriptionTemplateTypes;
}

View File

@ -14,9 +14,9 @@ import { TranslateService } from '@ngx-translate/core';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-description-type-editor',
templateUrl: './description-type-editor.component.html',
styleUrls: ['./description-type-editor.component.scss']
selector: 'app-description-type-editor',
templateUrl: './description-type-editor.component.html',
styleUrls: ['./description-type-editor.component.scss']
})
export class DescriptionTypeEditorComponent extends BaseComponent implements OnInit {
@ -34,7 +34,7 @@ export class DescriptionTypeEditorComponent extends BaseComponent implements OnI
private language: TranslateService,
private route: ActivatedRoute,
private router: Router
) {
) {
super();
}
@ -47,12 +47,12 @@ export class DescriptionTypeEditorComponent extends BaseComponent implements OnI
this.descriptionTemplateTypeService.getSingle(this.descriptionTemplateTypeId)
.pipe(takeUntil(this._destroyed)).subscribe(
type => {
this.descriptionTypeModel = new DescriptionTypeEditorModel().fromModel(type);
if(this.descriptionTypeModel.status === DescriptionTemplateTypeStatus.Finalized){
this.descriptionTypeModel = new DescriptionTypeEditorModel().fromModel(type.items[0]);
if (this.descriptionTypeModel.status === DescriptionTemplateTypeStatus.Finalized) {
this.formGroup = this.descriptionTypeModel.buildForm(null, true);
this.viewOnly = true;
}
else{
else {
this.formGroup = this.descriptionTypeModel.buildForm();
}
},
@ -67,7 +67,7 @@ export class DescriptionTypeEditorComponent extends BaseComponent implements OnI
});
}
formSubmit(): void {
formSubmit(): void {
this.formService.touchAllFormFields(this.formGroup);
if (!this.isFormValid()) { return; }
this.onSubmit();
@ -82,17 +82,17 @@ export class DescriptionTypeEditorComponent extends BaseComponent implements OnI
this.onSubmit();
}
onSubmit(): void {
if(this.isNew){
this.descriptionTemplateTypeService.createType(this.formGroup.value)
onSubmit(): void {
if (this.isNew) {
this.descriptionTemplateTypeService.create(this.formGroup.value)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => this.onCallbackSuccess(true),
error => this.onCallbackError(error)
);
}
else{
this.descriptionTemplateTypeService.updateType(this.formGroup.value)
else {
this.descriptionTemplateTypeService.update(this.formGroup.value)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => this.onCallbackSuccess(false),
@ -102,10 +102,10 @@ export class DescriptionTypeEditorComponent extends BaseComponent implements OnI
}
onCallbackSuccess(creation: boolean): void {
if(creation){
if (creation) {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION'), SnackBarNotificationLevel.Success);
}
else{
else {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
}
this.router.navigate(['/description-types']);
@ -123,15 +123,15 @@ export class DescriptionTypeEditorComponent extends BaseComponent implements OnI
});
}
public cancel(): void {
public cancel(): void {
this.router.navigate(['/description-types']);
}
}
export class DescriptionTypeEditorModel {
public id: string;
public name: string;
public id: string;
public name: string;
public status: DescriptionTemplateTypeStatus;
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
@ -151,7 +151,7 @@ export class DescriptionTypeEditorModel {
});
return formGroup;
}
createValidationContext(): ValidationContext {
const baseContext: ValidationContext = new ValidationContext();
baseContext.validation.push({ key: 'name', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'name')] });

View File

@ -28,23 +28,26 @@
<ng-container cdkColumnDef="status">
<mat-header-cell *matHeaderCellDef mat-sort-header="status">{{'DESCRIPTION-TYPES-LISTING.COLUMNS.STATUS' |
translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> <div [ngClass]="['status-chip',getStatusClass(row.status)]">{{parseStatus(row.status) | translate}}</div></mat-cell>
</ng-container>
<ng-container cdkColumnDef="delete">
<mat-header-cell *matHeaderCellDef></mat-header-cell>
<mat-cell *matCellDef="let row" (click)="$event.stopPropagation()">
<button mat-icon-button (click)="deleteTemplate(row.id)">
<mat-icon [matTooltip]="('DESCRIPTION-TYPES-LISTING.ACTIONS.DELETE' | translate)" matTooltipPosition="right" class="dlt-btn">delete</mat-icon>
</button>
<mat-cell *matCellDef="let row">
<div [ngClass]="['status-chip',getStatusClass(row.status)]">{{parseStatus(row.status) | translate}}</div>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<ng-container cdkColumnDef="delete">
<mat-header-cell *matHeaderCellDef></mat-header-cell>
<mat-cell *matCellDef="let row" (click)="$event.stopPropagation()">
<button mat-icon-button (click)="deleteTemplate(row.id)">
<mat-icon [matTooltip]="('DESCRIPTION-TYPES-LISTING.ACTIONS.DELETE' | translate)"
matTooltipPosition="right" class="dlt-btn">delete</mat-icon>
</button>
</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 #paginator [pageSizeOptions]="[10, 25, 100]">
</mat-paginator>
</div>
</div>

View File

@ -1,28 +1,31 @@
import { DataSource } from '@angular/cdk/table';
import { HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, EventEmitter, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { Router } from '@angular/router';
import { DescriptionTemplateType } from '@app/core/model/description-template-type/description-template-type';
import { DescriptionTemplateTypeLookup } from '@app/core/query/description-template/description-template-type.lookup';
import { DescriptionTemplateTypeService } from '@app/core/services/description-template-type/description-template-type.service';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { BaseComponent } from '@common/base/base.component';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import { TranslateService } from '@ngx-translate/core';
import { merge as observableMerge, Observable, of } from 'rxjs';
import { Observable, merge, of } from 'rxjs';
import { map, startWith, switchMap, takeUntil } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof';
@Component({
selector: 'app-description-types',
templateUrl: './description-types.component.html',
styleUrls: ['./description-types.component.scss']
selector: 'app-description-types',
templateUrl: './description-types.component.html',
styleUrls: ['./description-types.component.scss']
})
export class DescriptionTypesComponent extends BaseComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) _paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) sort: MatSort;
@ViewChild(MatPaginator, { static: true }) _paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) _sort: MatSort;
dataSource: DescriptionTypesDataSource | null;
displayedColumns: String[] = ['label', 'status', 'delete'];
@ -38,7 +41,7 @@ export class DescriptionTypesComponent extends BaseComponent implements OnInit {
private language: TranslateService,
private uiNotificationService: UiNotificationService,
private router: Router
) {
) {
super();
}
@ -46,25 +49,25 @@ export class DescriptionTypesComponent extends BaseComponent implements OnInit {
this.refresh();
}
refresh() {
this.dataSource = new DescriptionTypesDataSource(this.descriptionTemplateTypeService, this._paginator, this.sort/*, this.criteria*/);
refresh() {
this.dataSource = new DescriptionTypesDataSource(this.descriptionTemplateTypeService, this._paginator, this._sort);
}
rowClick(rowId: String) {
this.router.navigate(['description-types/' + rowId]);
}
parseStatus(value: number): string{
parseStatus(value: number): string {
const stringVal = value.toString()
try{
try {
return this.statuses.find(status => status.value === stringVal).viewValue;
}catch{
} catch {
return stringVal;
}
}
deleteTemplate(id: string){
if(id){
deleteTemplate(id: string) {
if (id) {
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
restoreFocus: false,
data: {
@ -77,22 +80,22 @@ export class DescriptionTypesComponent extends BaseComponent implements OnInit {
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
this.descriptionTemplateTypeService.deleteType(id)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Success);
this.refresh();
},
error => {
this.onCallbackError(error);
if (error.error.statusCode == 674) {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Error);
} else {
this.uiNotificationService.snackBarNotification(this.language.instant(error.message), SnackBarNotificationLevel.Error);
this.descriptionTemplateTypeService.delete(id)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Success);
this.refresh();
},
error => {
this.onCallbackError(error);
if (error.error.statusCode == 674) {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Error);
} else {
this.uiNotificationService.snackBarNotification(this.language.instant(error.message), SnackBarNotificationLevel.Error);
}
}
}
);
);
}
});
@ -104,8 +107,8 @@ export class DescriptionTypesComponent extends BaseComponent implements OnInit {
}
getStatusClass(status: number): string {
if(status == 1){
if (status == 1) {
return 'status-chip-finalized'
}
@ -116,7 +119,8 @@ export class DescriptionTypesComponent extends BaseComponent implements OnInit {
export class DescriptionTypesDataSource extends DataSource<DescriptionTemplateType> {
totalCount = 0;
data: DescriptionTemplateType[] = [];
loadData: EventEmitter<boolean> = new EventEmitter<boolean>();
constructor(
private _service: DescriptionTemplateTypeService,
@ -124,27 +128,41 @@ export class DescriptionTypesDataSource extends DataSource<DescriptionTemplateTy
private _sort: MatSort
) {
super();
}
connect(): Observable<DescriptionTemplateType[]> {
const displayDataChanges = [
this._paginator.page
//this._sort.matSortChange
const dataChanges = [
this._paginator.page,
this._sort.sortChange
];
return observableMerge(...displayDataChanges).pipe(
startWith(null),
return merge(...dataChanges).pipe(
startWith(<string>null),
switchMap(() => {
return this._service.getTypes();
let lookup: DescriptionTemplateTypeLookup = new DescriptionTemplateTypeLookup();
lookup.page = {
offset: this._paginator.pageIndex * this._paginator.pageSize,
size: this._paginator.pageSize
},
lookup.project = {
fields: [
nameof<DescriptionTemplateType>(x => x.id),
nameof<DescriptionTemplateType>(x => x.name),
nameof<DescriptionTemplateType>(x => x.status)
]
};
return this._service.getAll(lookup)
}),
map(result => {
return result;
}),
map(result => {
if (!result) { return []; }
if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; }
return result.data;
this.data = result.items;
this._paginator.length = result.count;
return result.items;
}));
}

View File

@ -0,0 +1,31 @@
export class Lookup {
public page: Lookup.Paging;
public order: Lookup.Ordering;
public metadata: Lookup.Header;
public project: Lookup.FieldDirectives;
constructor() {
this.project = {
fields: []
};
}
}
export namespace Lookup {
export interface Header {
countAll: boolean;
}
export interface FieldDirectives {
fields: string[];
}
export interface Ordering {
items: string[];
}
export interface Paging {
offset: number;
size: number;
}
}

View File

@ -0,0 +1,5 @@
export interface QueryResult<T> {
count: number;
countOverride?: number;
items: T[];
}