import {ChangeDetectorRef, Component, OnInit} from '@angular/core'; import {Router} from '@angular/router'; import {Subscriber, Subscription, zip} from "rxjs"; import {Meta, Title} from "@angular/platform-browser"; import {EnvProperties} from "../openaireLibrary/utils/properties/env-properties"; import {PiwikService} from "../openaireLibrary/utils/piwik/piwik.service"; import {SEOService} from "../openaireLibrary/sharedComponents/SEO/SEO.service"; import {Breadcrumb} from "../openaireLibrary/utils/breadcrumbs/breadcrumbs.component"; import {properties} from "../../environments/environment"; import {RefineFieldResultsService} from '../openaireLibrary/services/refineFieldResults.service'; import {StakeholderService} from '../openaireLibrary/monitor/services/stakeholder.service'; import {Option} from '../openaireLibrary/sharedComponents/input/input.component'; import {StringUtils} from '../openaireLibrary/utils/string-utils.class'; import {HelperFunctions} from '../openaireLibrary/utils/HelperFunctions.class'; import {NumberUtils} from '../openaireLibrary/utils/number-utils.class'; import {LayoutService} from '../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service'; import {FormBuilder, FormControl} from '@angular/forms'; import {debounceTime, distinctUntilChanged} from 'rxjs/operators'; @Component({ selector: 'funders', templateUrl: './funders.component.html', styleUrls: ['funders.component.less'] }) export class FundersComponent implements OnInit { private subscriptions: Subscription[] = []; url: string = null; pageTitle: string = "OpenAIRE - Explore | Funders"; pageDescription: string = "Funders | Be an integral part of the open R&I ecosystem"; properties: EnvProperties = properties; breadcrumbs: Breadcrumb[] = [{name: 'home', route: '/'}, {name: 'funders'}]; showLoading: boolean = true; isMobile: boolean = false; funders: any[] = []; displayedFunders: any[] = []; showOptions: Option[]; sortOptions: Option[]; pageOptions: number[] = [10, 20, 30, 40]; show: string = 'all'; sortBy: string = 'alphAsc'; gridView: boolean = true; currentPage: number = 1; pageSize: number = 10; keywordControl: FormControl; keyword: string; fundersNumber: number = 0; researchProductsNumber: number = 0; projectsNumber: number = 0; fundersMap = new Map(); constructor(private router: Router, private meta: Meta, private title: Title, private seoService: SEOService, private piwikService: PiwikService, private refineFieldResultsService: RefineFieldResultsService, private stakeholderService: StakeholderService, private layoutService: LayoutService, private cdr: ChangeDetectorRef, private fb: FormBuilder,) { } ngOnInit() { this.title.setTitle('OpenAIRE - Explore | Funders'); this.properties = properties; this.subscriptions.push( this.piwikService.trackView(this.properties, this.pageTitle).subscribe()); this.url = this.properties.domain + this.router.url; this.seoService.createLinkForCanonicalURL(this.url); this.updateUrl(this.url); this.updateTitle(this.pageTitle); this.updateDescription(this.pageDescription); this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => { this.isMobile = isMobile; this.cdr.detectChanges(); })); this.showOptions = [ {value: 'all', label: 'All funders'}, {value: 'dashboard', label: 'Funders with dashboard'} ]; this.sortOptions = [ {value: 'alphAsc', label: 'Alphabetically Asc. (A-Z)'}, {value: 'alphDsc', label: 'Alphabetically Dsc. (Z-A)'}, {value: 'oaDsc', label: '"Open Access %" Dsc.'} ]; this.getFunders(); this.keywordControl = this.fb.control(''); this.subscriptions.push(this.keywordControl.valueChanges.pipe(debounceTime(500), distinctUntilChanged()).subscribe(value => { this.keyword = value; this.filtering(); })); } ngOnDestroy() { this.subscriptions.forEach(subscription => { if (subscription instanceof Subscriber) { subscription.unsubscribe(); } }); } private updateDescription(description: string) { this.meta.updateTag({content: description}, "name='description'"); this.meta.updateTag({content: description}, "property='og:description'"); } private updateTitle(title: string) { var title = ((title.length > 50) ? title.substring(0, 50) : title); this.title.setTitle(title); this.meta.updateTag({content: title}, "property='og:title'"); } private updateUrl(url: string) { this.meta.updateTag({content: url}, "property='og:url'"); } private getFunders() { let refineParams = '&fq=resultbestaccessright%20exact%20%22Open%20Access%22'; this.subscriptions.push( zip( this.refineFieldResultsService.getRefineFieldsResultsByEntityName(['relfunder'], 'result', this.properties), this.refineFieldResultsService.getRefineFieldsResultsByEntityName(['relfunder'], 'result', this.properties, refineParams), this.refineFieldResultsService.getRefineFieldsResultsByEntityName(['funder'], 'project', this.properties), this.stakeholderService.getStakeholders(this.properties.monitorServiceAPIURL, 'funder') ).subscribe((data: any[]) => { // storing all needed data to a map // 1st call let queriedFunders1 = data[0][1][0].values; queriedFunders1.forEach(queriedFunder => { this.fundersMap.set(queriedFunder.id, { "id": queriedFunder.id, "name": queriedFunder.name, "alias": '', "researchProducts": +queriedFunder.number, "openAccessResearchProducts": 0, "openAccessPercentage": 0, "projects": 0, "monitorDashboard": '', "monitorDashboardStatus": '', "logoUrl": '' }); }); // 2nd call let queriedFunders2 = data[1][1][0].values; queriedFunders2.forEach(queriedFunder => { if(this.fundersMap.has(queriedFunder.id)) { this.fundersMap.get(queriedFunder.id).openAccessResearchProducts = +queriedFunder.number; } }); // 3rd call let queriedFunders3 = data[2][1][0].values; queriedFunders3.forEach(queriedFunder => { if(+queriedFunder.number > 1) { if (this.fundersMap.has(queriedFunder.id)) { this.fundersMap.get(queriedFunder.id).projects = +queriedFunder.number; } else { this.fundersMap.set(queriedFunder.id, { "id": queriedFunder.id, "name": queriedFunder.name, "alias": '', "researchProducts": 0, "openAccessResearchProducts": 0, "openAccessPercentage": 0, "projects": +queriedFunder.number, "monitorDashboard": '', "monitorDashboardStatus": '', "logoUrl": '' }); } } }); // 4th call let queriedFunders4 = data[3]; queriedFunders4.forEach(queriedFunder => { let id = queriedFunder.index_id + '||' + queriedFunder.index_name + '||' + queriedFunder.index_shortName; if(this.fundersMap.has(id) && ( !this.fundersMap.get(id).monitorDashboardStatus || (this.fundersMap.get(id).monitorDashboardStatus == "RESTRICTED" && queriedFunder.visibility == "PUBLIC") || (this.fundersMap.get(id).monitorDashboardStatus == "PRIVATE" && (queriedFunder.visibility == "RESTRICTED" || queriedFunder.visibility == "PUBLIC")))) { this.fundersMap.get(id).alias = queriedFunder.alias; this.fundersMap.get(id).monitorDashboard = queriedFunder.alias; this.fundersMap.get(id).monitorDashboardStatus = queriedFunder.visibility; this.fundersMap.get(id).logoUrl = (queriedFunder.isUpload ? properties.utilsService + "/download/" : "")+ (queriedFunder.logoUrl); } }); this.fundersMap.forEach((value) => { if(value.openAccessResearchProducts > 0) { value.openAccessPercentage = Math.round((value.openAccessResearchProducts / value.researchProducts) * 100); } }); // convert funders map into an array this.funders = Array.from(this.fundersMap.values()); // calculate total numbers for intro content this.calculateNumbers(); // sort funders this.funders.sort((a, b) => a['name'].localeCompare(b['name'])); // initialize displayedFunders this.displayedFunders = this.funders; this.showLoading = false; }) ); } private calculateSum(array, property) { let sum = 0; array.forEach(element => { sum += element[property]; }); return sum; } private calculateNumbers() { this.fundersNumber = this.funders.length; this.researchProductsNumber = this.calculateSum(this.funders, 'researchProducts'); this.projectsNumber = this.calculateSum(this.funders, 'projects'); } get showContentWithNumbers() { return this.fundersNumber && this.researchProductsNumber && this.projectsNumber; } formatNumber(num: number | string) { let formatted = NumberUtils.roundNumber(+num); return formatted.number + formatted.size; } urlEncodeAndQuote(str: string): string { return StringUtils.quote(StringUtils.URIEncode(str)); } sortByChanged() { switch(this.sortBy) { case 'alphAsc': this.funders = this.funders.sort((a, b) => a['name'].localeCompare(b['name'])); break; case 'alphDsc': this.funders = this.funders.sort((a, b) => b['name'].localeCompare(a['name'])); break; case 'oaDsc': this.funders = this.funders.sort((a, b) => b['openAccessPercentage'] - a['openAccessPercentage']); break; } this.filtering(); } sizeChanged($event) { this.pageSize = $event; this.currentPage = 1; } filtering() { let displayedFunders = this.funders; if(!this.keyword){ this.keyword = ''; } if(this.funders.length) { displayedFunders = displayedFunders.filter(item => (item['name'] && item['name'].toLowerCase().includes(this.keyword.toLowerCase())) || (item['alias'] && item['alias'].toLowerCase().includes(this.keyword.toLowerCase()))); } if(this.show == 'dashboard') { displayedFunders = displayedFunders.filter(funder => funder.monitorDashboard && funder.monitorDashboard?.length > 0 && funder.monitorDashboardStatus != 'PRIVATE'); } this.displayedFunders = displayedFunders; this.currentPage = 1; } public updateCurrentPage($event) { this.currentPage = $event.value; HelperFunctions.scrollToId('target'); } }