From b2cddcbfb6207422b46ffd88594afe8bfea6eb54 Mon Sep 17 00:00:00 2001 From: "konstantina.galouni" Date: Tue, 3 Oct 2023 17:00:58 +0300 Subject: [PATCH] [Validator]: Updates & improvements. 1. JobResult.ts: Added "set:string" and "exceptionMessage: string" fields. 2. RulePerJob.ts: Removed "rule_description" field and added fields "requirement_level: string, description: string, fair_principles: string, fair_principles_tooltip: string, link: string;". 3. oaipmh-analysis.component.html: Added cards on the right for base url and set | Added requirement level to the rule name, updated field for description, added fair principles. 4. oaipmh-analysis.component.ts: Added "requirementLevelMapping" and initialize tooltip of fair principles. 5. oaipmh-history.component.html: Updated table to show multiple validations | Updated columns of table - removed actions and updated status (view results - gets us to the analysis, in progress, stoppes, error, errors - opens a modal with the exception message). 6. oaipmh-history.component.ts: Added method "getJobResults()" and methods for error modal | Added a limit of 120 requests (10 minutes) for repetable requests of getting jobResult to update status when status is in progress. 7. oaipmh-validator.component.ts: Updated label for guidelines | Updated validation checks | Added exception catch in getSets(). 8. oaipmh-validator.service.ts: Added method "getJobResults(limit: number = 200)". 9. topmenu.component.html: Removed jobId from history demo page. 10. package-lock.json: Updated uikit version. --- package-lock.json | 14 ++--- src/app/openaire-library | 2 +- src/app/pages/entities/JobResult.ts | 2 + src/app/pages/entities/RulePerJob.ts | 8 ++- .../oaipmh-analysis.component.html | 45 +++++++++++-- .../oaipmh-analysis.component.ts | 34 ++++++++++ .../oaipmh-history.component.html | 63 +++++++++++++------ .../oaipmh-history.component.ts | 49 ++++++++++++--- .../oaipmh-validator.component.ts | 22 +++++-- src/app/services/oaipmh-validator.service.ts | 5 ++ src/app/shared/topmenu/topmenu.component.html | 2 +- 11 files changed, 201 insertions(+), 45 deletions(-) diff --git a/package-lock.json b/package-lock.json index b98b093..1e0151c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@angular/router": "^16.1.8", "rxjs": "~7.5.0", "tslib": "^2.3.0", - "uikit": "3.13.10", + "uikit": "3.16.24", "zone.js": "~0.13.1" }, "devDependencies": { @@ -11575,9 +11575,9 @@ } }, "node_modules/uikit": { - "version": "3.13.10", - "resolved": "https://registry.npmjs.org/uikit/-/uikit-3.13.10.tgz", - "integrity": "sha512-kxSPDT7HiwiQW3e++V8LfIe7/E1L5viPXH4P2yxyDIaU6CP1gWh2Ggy6skc/ziZNlY3CqI2JJkOU2/5zd+NaVw==" + "version": "3.16.24", + "resolved": "https://registry.npmjs.org/uikit/-/uikit-3.16.24.tgz", + "integrity": "sha512-b33pxCinNlgrkQf+VUNk7AzN0wFWo41C5avYbXQTtt41xOAlJD2mBQHNwlTm8s8uo+CZa3djX1inJLuY2JwusQ==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -20994,9 +20994,9 @@ "dev": true }, "uikit": { - "version": "3.13.10", - "resolved": "https://registry.npmjs.org/uikit/-/uikit-3.13.10.tgz", - "integrity": "sha512-kxSPDT7HiwiQW3e++V8LfIe7/E1L5viPXH4P2yxyDIaU6CP1gWh2Ggy6skc/ziZNlY3CqI2JJkOU2/5zd+NaVw==" + "version": "3.16.24", + "resolved": "https://registry.npmjs.org/uikit/-/uikit-3.16.24.tgz", + "integrity": "sha512-b33pxCinNlgrkQf+VUNk7AzN0wFWo41C5avYbXQTtt41xOAlJD2mBQHNwlTm8s8uo+CZa3djX1inJLuY2JwusQ==" }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", diff --git a/src/app/openaire-library b/src/app/openaire-library index 11d0be4..6d7f6ec 160000 --- a/src/app/openaire-library +++ b/src/app/openaire-library @@ -1 +1 @@ -Subproject commit 11d0be4ffd6649189f87c91aed1c2d47c5d9b2c8 +Subproject commit 6d7f6eca720d18fe694f13e380c1ede1f46303a8 diff --git a/src/app/pages/entities/JobResult.ts b/src/app/pages/entities/JobResult.ts index ab81f91..b256cbe 100644 --- a/src/app/pages/entities/JobResult.ts +++ b/src/app/pages/entities/JobResult.ts @@ -1,6 +1,7 @@ export class JobResult { id: string; baseUrl: string; + set: string; numberOfRecords: number; guidelines: string; startDate: Date; @@ -9,6 +10,7 @@ export class JobResult { progress: Progress; status: Status; score: number; + exceptionMessage: string; } export enum Status { diff --git a/src/app/pages/entities/RulePerJob.ts b/src/app/pages/entities/RulePerJob.ts index 3ab9b1a..2fb4be8 100644 --- a/src/app/pages/entities/RulePerJob.ts +++ b/src/app/pages/entities/RulePerJob.ts @@ -1,9 +1,15 @@ export class RulePerJob { rule_name: string; - rule_description: string; rule_weight: number; guidelines: string; rule_status: Status; + + "requirement_level": string; + "description": string; + "fair_principles": string; + "fair_principles_tooltip": string; + "link": string; + passed_records: number; failed_records: number; // warnings: string[]; diff --git a/src/app/pages/oaipmh-validator/validation-analysis/oaipmh-analysis.component.html b/src/app/pages/oaipmh-validator/validation-analysis/oaipmh-analysis.component.html index 7a59d80..a1dba9a 100644 --- a/src/app/pages/oaipmh-validator/validation-analysis/oaipmh-analysis.component.html +++ b/src/app/pages/oaipmh-validator/validation-analysis/oaipmh-analysis.component.html @@ -15,8 +15,16 @@ -
{{ruleResult.rule_name ? ruleResult.rule_name : '-'}}
-
{{ruleResult.rule_description}}
+
+ {{ruleResult.rule_name ? ruleResult.rule_name : '-'}} + + ( + {{requirementLevelMapping.get(ruleResult.requirement_level)}} + {{ruleResult.requirement_level}} + ) + +
+
{{ruleResult.description}}
@@ -26,7 +34,8 @@ - - + {{ruleResult.fair_principles}} + - @@ -198,10 +207,34 @@
+
+
+ +
+
Base url
+
{{jobResult.baseUrl}}
+
+
+
+
+ +
+
+
+ +
+
Set
+
{{jobResult.set}}
+
+
+
+
+ +
-
+
Guidelines
{{jobResult.guidelines}}
@@ -212,7 +245,7 @@
-
+
Started
{{jobResult.startDate | date: 'yyyy-MM-dd, HH:mm:ss'}}
Not yet Ended
@@ -225,7 +258,7 @@
-
+
Duration
{{jobDuration.years}} years diff --git a/src/app/pages/oaipmh-validator/validation-analysis/oaipmh-analysis.component.ts b/src/app/pages/oaipmh-validator/validation-analysis/oaipmh-analysis.component.ts index 6bb5670..6cd8905 100644 --- a/src/app/pages/oaipmh-validator/validation-analysis/oaipmh-analysis.component.ts +++ b/src/app/pages/oaipmh-validator/validation-analysis/oaipmh-analysis.component.ts @@ -53,6 +53,14 @@ export class OaipmhAnalysisComponent implements OnInit { ['OpenAIRE FAIR Guidelines for Data Repositories Profile', 'oai_datacite'] ]); + public requirementLevelMapping: Map = new Map([ + ["MANDATORY", "M"], + ["MANDATORY_IF_APPLICABLE", "MA"], + ["RECOMMENDED", "R"], + ["OPTIONAL", "O"] + ]); + + constructor(private route: ActivatedRoute, private cdr: ChangeDetectorRef, private validator: OaipmhValidatorService) {} ngOnInit(): void { @@ -100,6 +108,32 @@ export class OaipmhAnalysisComponent implements OnInit { new Map; for(let rulePerJob of result) { + if(rulePerJob.fair_principles) { + if(rulePerJob.fair_principles.includes("F")) { + rulePerJob.fair_principles_tooltip = "Findable"; + } + if(rulePerJob.fair_principles.includes("F") && + (rulePerJob.fair_principles.includes("A") || rulePerJob.fair_principles.includes("I") || rulePerJob.fair_principles.includes("R"))) { + rulePerJob.fair_principles_tooltip += ", "; + } + if(rulePerJob.fair_principles.includes("A")) { + rulePerJob.fair_principles_tooltip += "Accessible"; + } + if(rulePerJob.fair_principles.includes("A") && + (rulePerJob.fair_principles.includes("I") || rulePerJob.fair_principles.includes("R"))) { + rulePerJob.fair_principles_tooltip += ", "; + } + if(rulePerJob.fair_principles.includes("I")) { + rulePerJob.fair_principles_tooltip += "Interoperable"; + } + if(rulePerJob.fair_principles.includes("I") && rulePerJob.fair_principles.includes("R")) { + rulePerJob.fair_principles_tooltip += ", "; + } + if(rulePerJob.fair_principles.includes("R")) { + rulePerJob.fair_principles_tooltip += "Reusable"; + } + } + if(!validationResult.has(rulePerJob.guidelines)) { validationResult.set(rulePerJob.guidelines, {analysisResult: [], successfulAnalysisResult: [], warningAnalysisResult: [], failedAnalysisResult: []}); } diff --git a/src/app/pages/oaipmh-validator/validation-history/oaipmh-history.component.html b/src/app/pages/oaipmh-validator/validation-history/oaipmh-history.component.html index 6129e9a..bc84c21 100644 --- a/src/app/pages/oaipmh-validator/validation-history/oaipmh-history.component.html +++ b/src/app/pages/oaipmh-validator/validation-history/oaipmh-history.component.html @@ -7,10 +7,12 @@

Validator's History

-
+ + +
No validated metadata record yet
-
+
@@ -21,11 +23,11 @@ - + - + @@ -34,27 +36,52 @@ - + + + + + + + +
Guidelines StatusActions
{{result.baseUrl}} - - {{result.status}} - - - {{result.progress}} - - - + + + + - - View Results - + View results + + + In progess + + + Stopped + + + Error + + + Errors +
+ +
Please reload the page to get the updated status.
+ + +
+
No errors available
+
+
{{error}}
+
+
+
+
diff --git a/src/app/pages/oaipmh-validator/validation-history/oaipmh-history.component.ts b/src/app/pages/oaipmh-validator/validation-history/oaipmh-history.component.ts index 7ff02f8..af4943d 100644 --- a/src/app/pages/oaipmh-validator/validation-history/oaipmh-history.component.ts +++ b/src/app/pages/oaipmh-validator/validation-history/oaipmh-history.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit} from '@angular/core'; +import {Component, OnInit, ViewChild} from '@angular/core'; import {OaipmhValidatorService} from "../../../services/oaipmh-validator.service"; import {JobResult, Progress, Status} from "../../entities/JobResult"; import {ActivatedRoute} from "@angular/router"; @@ -12,10 +12,16 @@ import {filter, repeat, take} from "rxjs/operators"; styleUrls: ['./oaipmh-history.component.less'] }) export class OaipmhHistoryComponent implements OnInit { - public result: JobResult; + public warning: boolean = false; + public results: JobResult[]; public jobId: string = ""; public breadcrumbs: Breadcrumb[] = [{name: 'home', route: '/'}, {name: 'Validator\'s History'}]; protected readonly Progress = Progress; + protected readonly Status = Status; + + @ViewChild('errorsModal') errorsModal; + public errorsModalOpen: boolean = false; + public error: string = null; subscriptions = []; @@ -24,11 +30,13 @@ export class OaipmhHistoryComponent implements OnInit { ngOnInit(): void { this.subscriptions.push(this.route.queryParams.subscribe(params => { this.jobId = params['jobId']; - this.result = null; + this.results = []; + this.warning = false; if(!this.jobId) { - this.jobId = "825"; + this.getJobResults(); + } else { + this.getJobResult(); } - this.getJobResult(); })); } @@ -41,11 +49,18 @@ export class OaipmhHistoryComponent implements OnInit { } public getJobResult() { + let count: number = 0; this.subscriptions.push(this.validator.getJobResult(this.jobId) .pipe( repeat({ delay: 5000 }), filter((result: JobResult) => { - this.result = result; + this.results = []; + this.results.push(result); + count++; + if(count == 120 && result.progress == Progress.IN_PROGRESS) { + this.warning = true; + return true; + } return result.progress !== Progress.IN_PROGRESS }), take(1) @@ -54,5 +69,25 @@ export class OaipmhHistoryComponent implements OnInit { ); } - protected readonly Status = Status; + public getJobResults() { + this.subscriptions.push(this.validator.getJobResults().subscribe( + (results: JobResult[]) => { + this.results = results; + }), + ); + } + + public viewErrors(error: string) { + this.error = error; + this.openErrorsModal(); + this.errorsModalOpen = true; + } + + public openErrorsModal() { + this.errorsModalOpen = true; + this.errorsModal.cancelButton = false; + this.errorsModal.okButton = false; + this.errorsModal.alertTitle = "Errors"; + this.errorsModal.open(); + } } diff --git a/src/app/pages/oaipmh-validator/validation-settings/oaipmh-validator.component.ts b/src/app/pages/oaipmh-validator/validation-settings/oaipmh-validator.component.ts index 315a8b4..6fbd1b2 100644 --- a/src/app/pages/oaipmh-validator/validation-settings/oaipmh-validator.component.ts +++ b/src/app/pages/oaipmh-validator/validation-settings/oaipmh-validator.component.ts @@ -7,6 +7,8 @@ import {JobResult} from "../../entities/JobResult"; import {Router} from "@angular/router"; import {Subscriber} from "rxjs"; +declare var UIkit: any; + @Component({ selector: 'app-oaipmh-validator', templateUrl: './oaipmh-validator.component.html', @@ -18,7 +20,7 @@ export class OaipmhValidatorComponent implements OnInit { @ViewChild("right_sidebar_footer") right_sidebar_footer; public options: Option[] = [ - {label: 'OpenAIRE Guidelines for Data Archives Profile v2', value: 'OpenAIRE Guidelines for Data Archives Profile v2'}, + {label: 'OpenAIRE Guidelines for Data Archives Profile v2 & OpenAIRE FAIR Guidelines for Data Repositories Profile', value: 'OpenAIRE Guidelines for Data Archives Profile v2'}, {label: 'OpenAIRE Guidelines for Literature Repositories Profile v3', value: 'OpenAIRE Guidelines for Literature Repositories Profile v3'}, {label: 'OpenAIRE Guidelines for Literature Repositories Profile v4', value: 'OpenAIRE Guidelines for Literature Repositories Profile v4'}, {label: 'OpenAIRE FAIR Guidelines for Data Repositories Profile', value: 'OpenAIRE FAIR Guidelines for Data Repositories Profile'} @@ -40,7 +42,7 @@ export class OaipmhValidatorComponent implements OnInit { private cdr: ChangeDetectorRef, private validator: OaipmhValidatorService) { this.form = this.fb.group({ - url: this.fb.control("", StringUtils.urlValidator()),//[Validators.required/*, Validators.email*/]), + url: this.fb.control("", [Validators.required, StringUtils.urlValidator()]),//[Validators.required/*, Validators.email*/]), guidelines: this.fb.control("", Validators.required), recordsNum: this.fb.control(null, Validators.required), set: this.fb.control('all', Validators.required) @@ -113,9 +115,21 @@ export class OaipmhValidatorComponent implements OnInit { this.router.navigate(['/oaipmh-history'], { queryParams: { 'jobId': result.id } }); + }, + error => { + // if(error.status == 400) { + UIkit.notification((error.error && error.error.message) ? error.error.message: error.message, { + status: 'danger', + timeout: 4000, + pos: 'bottom-right' + }); + // } + // if(error.status == 422) { + // this.router.navigate(['/oaipmh-history'], { + // queryParams: { 'jobId': error.error.id } + // }) + // } } )); } - - protected readonly innerHeight = innerHeight; } diff --git a/src/app/services/oaipmh-validator.service.ts b/src/app/services/oaipmh-validator.service.ts index 55cd26c..3a15be3 100644 --- a/src/app/services/oaipmh-validator.service.ts +++ b/src/app/services/oaipmh-validator.service.ts @@ -30,6 +30,11 @@ export class OaipmhValidatorService { return this.http.get(url); } + getJobResults(limit: number = 200) { + let url: string = environment.validatorAPI + "jobs/latest?limit="+limit; + return this.http.get(url); + } + getSets(baseUrl) { let url: string = environment.validatorAPI + "getSets?baseUrl="+baseUrl; return this.http.get(url).pipe(map(res => res['set'])); diff --git a/src/app/shared/topmenu/topmenu.component.html b/src/app/shared/topmenu/topmenu.component.html index 7eca178..93dcbb2 100644 --- a/src/app/shared/topmenu/topmenu.component.html +++ b/src/app/shared/topmenu/topmenu.component.html @@ -106,7 +106,7 @@ Validate [demo]
  • - History [demo] + History [demo]
  • Analysis [demo]