From bd4663031940d94869e475d510807e87e850f3cb Mon Sep 17 00:00:00 2001 From: argirok Date: Thu, 9 Nov 2023 15:35:44 +0200 Subject: [PATCH] [develop WIP] upload dois: add filters, stats progress bar --- .../upload-dois/upload-dois.component.html | 202 ++++++++++--- .../upload-dois/upload-dois.component.less | 40 +++ src/app/upload-dois/upload-dois.component.ts | 272 +++++++++++++----- src/app/upload-dois/upload-dois.module.ts | 5 +- 4 files changed, 411 insertions(+), 108 deletions(-) create mode 100644 src/app/upload-dois/upload-dois.component.less diff --git a/src/app/upload-dois/upload-dois.component.html b/src/app/upload-dois/upload-dois.component.html index d7ee0e1..ac570e1 100644 --- a/src/app/upload-dois/upload-dois.component.html +++ b/src/app/upload-dois/upload-dois.component.html @@ -1,42 +1,170 @@ -
- - - Upload a DOI's CSV file +
+
+
+
Title
+
Lorem ipsum.......
+
+
+
+ + + + upload new file + - - -   -
-
-All valid DOIs: {{allIds.length}}
-invalid DOIs: {{noValidIds.length}}
-duplicate: {{duplicateIds.length}}
- found in Openaire: {{foundIds.length}}
- not found in Openaire: {{notFoundIds.length}}
-
+
+
+
+ +
+
+ {{filesToUpload[0].name}} + +
+
+
+
+
+
+
+
Drag and Drop your file here
+
File supported: CSV
+
or
+
+ + CHOOSE FILE +
+
Maximum size: 5 MB
+
+
+
+
+
+ +
+
+ {{filesToUpload[0].name}} + +
{{this.getercentage(this.foundIds.length + this.notFoundIds.length, false)}}% done +
+
+
+
+
+
-
Fetching {{foundIds.length + notFoundIds.length}}/{{allIds.length}}...
-{{results.length}} -
-
- - - - - - - - - - - - +
+ + +
+ +
+
+ Filter by + +
+
+ Sort by + +
+
+
+ Viewing {{(page-1)*size}}-{{resultsToShow.length>(page)*size? (page)*size : resultsToShow.length}} of {{resultsToShow.length}} +
+
+
    +
  • +
  • +
+
+ + +
+
{{result.doi}}{{result.title}}{{result.accessMode}}{{result.accessRoute}} not found
+ + + + + + + + + + + + + + + + + + + +
TitleAccess ModeAccess Route in OpenAIRE
{{result.title}}{{result.accessMode}}{{result.accessRoute}} {{result.doi}}
+
+
+
+
+ {{foundIds.length}} results found in Irish Monitor +
+
+
Access Rights
+
Open Access
{{stats['open']}} ({{getercentage(stats['open'])}}%)
+
Restricted
{{stats['restricted']}} ({{getercentage(stats['restricted'])}}%)
+
Embargo
{{stats['embargo']}} ({{getercentage(stats['embargo'])}}%)
+
Closed
{{stats['closed']}} ({{getercentage(stats['closed'])}}%)
+
+
Green
{{stats['green']}} ({{getercentage(stats['green'])}}%)
+
Gold
{{stats['gold']}} ({{getercentage(stats['gold'])}}%)
+
Hybrid
{{stats['hybrid']}} ({{getercentage(stats['hybrid'])}}%)
+
Bronze
{{stats['bronze']}} ({{getercentage(stats['bronze'])}}%)
+
Diamond
{{stats['diamond']}} ({{getercentage(stats['diamond'])}}%)
+
+
+
+
+
+
valid
+
{{allIds.length}}
+
+ +
+
+
+
not found
+
{{notFoundIds.length}}
+
+ +
+
+
+
duplicates
+
{{duplicateIds.length}}
+
+ +
+ +
+
+
+
- -
- diff --git a/src/app/upload-dois/upload-dois.component.less b/src/app/upload-dois/upload-dois.component.less new file mode 100644 index 0000000..7d8f18a --- /dev/null +++ b/src/app/upload-dois/upload-dois.component.less @@ -0,0 +1,40 @@ +.dot { + height: 8px; + width: 8px; + background-color: #bbb; + border-radius: 50%; + display: inline-block; + margin-right: 4px; +} +.dot.open{ + background-color: orange; +} + +.dot.restricted{ + background-color: #920192; +} + +.dot.embargo{ + background-color: #003E92; +} +.dot.closed{ + background-color: #E34950; +} + +.dot.green{ + background-color: #24B050; +} + +.dot.gold{ + background-color: #EAB201; +} + +.dot.hybrid{ + background-color: #ED7D31; +} +.dot.bronze{ + background-color: #806001; +} +.dot.diamond{ + background-color: #595959; +} diff --git a/src/app/upload-dois/upload-dois.component.ts b/src/app/upload-dois/upload-dois.component.ts index 1e6b2dc..3ec0775 100644 --- a/src/app/upload-dois/upload-dois.component.ts +++ b/src/app/upload-dois/upload-dois.component.ts @@ -1,22 +1,20 @@ -import {Component, Input, OnInit, ViewChild} from '@angular/core'; -import {Dates, DOI, Identifier, StringUtils} from "../openaireLibrary/utils/string-utils.class"; +import {Component, OnInit} from '@angular/core'; +import {DOI, Identifier} from "../openaireLibrary/utils/string-utils.class"; import {EnvProperties} from "../openaireLibrary/utils/properties/env-properties"; import {ErrorCodes} from "../openaireLibrary/utils/properties/errorCodes"; import {Subscriber, timer} from "rxjs"; import {properties} from "../../environments/environment"; -import {ClaimEntity} from "../openaireLibrary/claims/claim-utils/claimHelper.class"; -import {ModalLoading} from "../openaireLibrary/utils/modal/loading.component"; import {SearchResearchResultsService} from "../openaireLibrary/services/searchResearchResults.service"; import {map} from "rxjs/operators"; @Component({ selector: 'upload-dois', templateUrl: './upload-dois.component.html', + styleUrls:['./upload-dois.component.less'] }) export class UploadDoisComponent implements OnInit { page: number = 1; - size: number = 20; - public keyword: string = "";//"paolo manghi";//'0000-0001-7291-3210'; + size: number = 2; properties: EnvProperties = properties; public errorCodes: ErrorCodes = new ErrorCodes(); public warningMessage = ""; @@ -26,7 +24,8 @@ export class UploadDoisComponent implements OnInit { filesToUpload: Array; public select: boolean = true; - public results =[]; + public results = []; + public resultsToShow = []; allIds: string[] = []; foundIds: string[] = []; @@ -38,11 +37,41 @@ export class UploadDoisComponent implements OnInit { noValidIds: string[] = []; noValidIdsRow: number[] = []; showReport: boolean = false; - @ViewChild(ModalLoading) loading: ModalLoading; errorMessage = ""; enableUpload: boolean = true; exceedsLimit = false; fileLimit = 5; + stats = { + open: 0, + closed: 0, + embargo: 0, + restricted: 0, + green:0, + gold:0, + hybrid:0, + bronze:0, + diamond:0 + } + filterBy = null; + filterByOptions = [{label: "In Openaire", value: "openaire"}, + {label: "Not found", value: "notFound"}, + {label: "Open Access", value: "access-open"}, + {label: "Embargo", value: "access-embargo"}, + {label: "Restricted", value: "access-restricted"}, + {label: "Closed", value: "access-closed"}, + {label: "Green", value: "route-green"}, + {label: "Gold", value: "route-gold"}, + {label: "Hybrid", value: "route-hybrid"}, + {label: "Bronze", value: "route-bronze"}, + {label: "Diamond", value: "route-diamond"}, + ] + sortBy = null; + sortByOptions = [{label: "Title", value: "title"}, + {label: "Access mode", value: "accessMode"}, + ] + + keyword = ""; + loading = false; constructor(private _searchResearchResultsService: SearchResearchResultsService) { } @@ -58,11 +87,17 @@ export class UploadDoisComponent implements OnInit { } }); } + upload() { + this.loading = true; this.enableUpload = false; this.showReport = false; this.errorMessage = ""; - console.log(this.filesToUpload); + this.results = []; + this.resultsToShow = []; + this.sortBy = null; + this.filterBy = null; + this.keyword = ""; if (this.filesToUpload.length == 0) { this.errorMessage = "There is no selected file to upload."; return; @@ -73,8 +108,6 @@ export class UploadDoisComponent implements OnInit { return; } } - // this.loading.open(); - console.log("here!"); this.makeFileRequest(this.properties.utilsService + '/upload', [], this.filesToUpload).then((result) => { const rows = (result as any).split('\n'); // I have used space, you can use any thing. @@ -87,18 +120,18 @@ export class UploadDoisComponent implements OnInit { this.noValidIds = []; // this.results.slice(0, this.results.length); this.notFoundIds = []; - if(rows.length > this.fileLimit){ + if (rows.length > this.fileLimit) { this.exceedsLimit = true; } - for (let i = 0; i < ( rows.length); i++) {23 - if (rows[i] && rows[i] != null && rows[i]!="") { + for (let i = 0; i < (rows.length); i++) { + if (rows[i] && rows[i] != null && rows[i] != "") { const values = rows[i].split(','); let id = this.removeDoubleQuotes(values[0]); if (DOI.isValidDOI(id)) { id = Identifier.getRawDOIValue(id); console.log(id, id.split("\r")[0]); - id=id.split("\r")[0] + id = id.split("\r")[0] if (this.allIds.indexOf(id) > -1) { this.duplicateIds.push(id); this.duplicateIdsRow.push(i + 1); @@ -114,16 +147,16 @@ export class UploadDoisComponent implements OnInit { } } + this.enableUpload = true; this.fetchAllResults(); }, (error) => { this.enableUpload = true; - this.loading.close(); this.errorMessage = "An error occured."; this.handleError("Error uploading file", error); }); } - private removeDoubleQuotes(value) { + private removeDoubleQuotes(value) { if (value.indexOf('"') == 0) { value = value.substring(1, value.length); } @@ -134,7 +167,7 @@ export class UploadDoisComponent implements OnInit { return value; } - private validateAccessMode(value) { + private validateAccessMode(value) { const accessModes = ["OPEN", "CLOSED", "EMBARGO"]; return accessModes.indexOf(value) > -1; } @@ -167,51 +200,63 @@ export class UploadDoisComponent implements OnInit { fetchAllResults() { let page = 1; - let timerSubscription = timer(0, 1000).pipe( + let timerSubscription = timer(0, 1000).pipe( map(() => { - if((page-1)*this.size <= this.allIds.length) { + if ((page - 1) * this.size <= this.allIds.length) { this.fetchResultsByPage(page); // load data contains the http request page += 1; - }else{ + } else { this.stopFetching(timerSubscription); } }) ).subscribe(); this.subscriptions.push(timerSubscription); } - stopFetching(timerSubscription){ + + stopFetching(timerSubscription) { timerSubscription.unsubscribe(); - } - fetchResultsByPage(page) { - let dois = this.allIds.slice((page-1)*this.size,page*this.size); - if(dois.length == 0){ - return; - } - let query = "" - for (let i = 0; i < dois.length; i++) { - query += (query.length > 0 ? " or " : "") + '(pidclassid exact "doi" and pid="' + StringUtils.URIEncode(dois[i]) + '")'; - } - // this.subscriptions.push(this._searchResearchResultsService.advancedSearchResults("publications",query ,1,this.size,null,properties,"&type=results").subscribe(data=>{ - this.subscriptions.push(this._searchResearchResultsService.fetchByDOIs(dois).subscribe( data => { - for(let result of data[1]){ - let matchingDOI =this.findMatchingDoi(result.DOIs,dois) - this.foundIds.push(matchingDOI); - this.results.push({ doi:matchingDOI, title: result.title.name, accessMode:result.title.accessMode, accessRoute:null, found: true}) - } - if(data[0] { + for (let result of data[1]) { + let matchingDOI = this.findMatchingDoi(result.DOIs, dois); + this.foundIds.push(matchingDOI); + let showRes = { + doi: matchingDOI, + title: result.title.name, + accessMode: result.title.accessMode, + accessRoute: null, + green: false, + openAccessColor:null, + diamond: false, + found: true + }; + this.results.push(showRes) + this.addStatsPerResult(result) + } + if (data[0] < dois.length) { + for (let doi of dois) { + if (this.foundIds.indexOf(doi) == -1) { + this.notFoundIds.push(doi); + this.results.push({doi: doi, title: null, accessMode: null, green: false, openAccessColor:null, diamond: false, accessRoute: null, found: false}) + } + } + } + this.resultsToShow = [...this.results]; + + })); + } + + findMatchingDoi(resultDois, requestedDois) { + for (let doi of resultDois) { + if (requestedDois.indexOf(doi) != -1) { return doi; } @@ -219,27 +264,118 @@ export class UploadDoisComponent implements OnInit { return null; } - private handleError(message: string, error) { - console.error("Bulk Claim (component): " + message, error); + private handleError(message: string, error) { + console.error("Upload error: " + message, error); } - private isSelected(result: ClaimEntity) { - - let found: boolean = false; - const id = result.id; - for (let _i = 0; _i < this.results.length; _i++) { - let item = this.results[_i]; - if (item.id && item.id == id) { - found = true; - break; - } + addStatsPerResult(result) { + if (result.title.accessMode == "Open Access") { + this.stats.open++; } - return found; - // indexOf doesn't work when results came from - // return this.selectedResults.indexOf(entity)!=-1; + if (result.title.accessMode == "Closed Access") { + this.stats.closed++; + } + if (result.title.accessMode == "Embargo") { + this.stats.embargo++; + } + if (result.title.accessMode == "Restricted") { + this.stats.restricted++; + } + //TDO add access routes stats } - updatePage($event) { - this.page = $event.value; + updatePage(page) { + this.page = page; + } + + updateSortBy(sortBy) { + this.sortBy = sortBy; + this.updateView(); + } + + updateFilterBy(filterBy) { + this.filterBy = filterBy; + this.updateView(); + } + updateKeyword(keyword){ + this.keyword = keyword; + this.updateView(); + } + + updateView() { + this.resultsToShow = [...this.results]; + if (this.filterBy) { + this.resultsToShow = this.filterResults(); + } + if(this.keyword.length > 0){ + this.resultsToShow = this.filterResultsByKeyword(); + } + if(this.sortBy){ + this.resultsToShow= this.sortResults(); + } + + + } + + filterResults() { + return this.results.filter(res =>{ + if(this.filterBy == "openaire"){ + return res.found + }else if(this.filterBy == "notFound"){ + return !res.found + }else if(this.filterBy == "access-closed"){ + return res.accessMode == "Closed Access"; + }else if(this.filterBy == "access-restricted"){ + return res.accessMode == "Restricted"; + }else if(this.filterBy == "access-open"){ + return res.accessMode == "Open Access"; + }else if(this.filterBy == "access-embargo") { + return res.accessMode == "Embargo"; + }else if(this.filterBy == "route-green") { + return res.green; + }else if(this.filterBy == "route-diamond") { + return res.diamond; + }else if(this.filterBy == "route-gold") { + return res.openAccessColor == "gold"; + }else if(this.filterBy == "route-hybrid") { + return res.openAccessColor == "hybrid"; + }else if(this.filterBy == "route-bronze") { + return res.openAccessColor == "bronze"; + }else{ + return true; + } + }) + } + filterResultsByKeyword() { + return this.resultsToShow.filter(res =>{ + + return (res.found && (res.title && res.title.toLowerCase().indexOf(this.keyword.toLowerCase()) !=-1)) + || (res.doi && res.doi.indexOf(this.keyword.toLowerCase()) != -1); + + }) + } + sortResults(){ + + return this.resultsToShow.sort((n1, n2) => { + if (n1[this.sortBy] && n2[this.sortBy] && n1[this.sortBy] > n2[this.sortBy]) { + return 1; + } + + if (n1[this.sortBy] && n2[this.sortBy] && n1[this.sortBy] < n2[this.sortBy]) { + return -1; + } + + return 0; + }) + + } + + getercentage(number, foundIds = true){ + if(!number){ + return ""; + } + let from = foundIds?this.foundIds.length:this.allIds.length + var num = new Number((number/from)*100); + return num == 100?100:num.toPrecision(2); } } diff --git a/src/app/upload-dois/upload-dois.module.ts b/src/app/upload-dois/upload-dois.module.ts index 324f6cb..0e4349a 100644 --- a/src/app/upload-dois/upload-dois.module.ts +++ b/src/app/upload-dois/upload-dois.module.ts @@ -2,17 +2,16 @@ import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {UploadDoisComponent} from "./upload-dois.component"; import {UploadDoisRoutingModule} from "./upload-dois-routing.module"; -import {LoadingModalModule} from "../openaireLibrary/utils/modal/loadingModal.module"; import {SearchResearchResultsServiceModule} from "../openaireLibrary/services/searchResearchResultsService.module"; import {PagingModule} from "../openaireLibrary/utils/paging.module"; +import {SearchInputModule} from "../openaireLibrary/sharedComponents/search-input/search-input.module"; @NgModule({ declarations: [UploadDoisComponent], imports: [ - CommonModule, UploadDoisRoutingModule, LoadingModalModule, SearchResearchResultsServiceModule, PagingModule + CommonModule, UploadDoisRoutingModule, SearchResearchResultsServiceModule, PagingModule, SearchInputModule ], - // exports: [UploadDoisComponent] }) export class UploadDoisModule { }