import {ChangeDetectorRef, Component, OnDestroy, OnInit, ViewRef} from '@angular/core'; import {ActivatedRoute, Params, Router} from '@angular/router'; import {DomSanitizer, Meta, Title} from '@angular/platform-browser'; import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties'; import {PiwikService} from '../openaireLibrary/utils/piwik/piwik.service'; import {Dates, StringUtils} from '../openaireLibrary/utils/string-utils.class'; import {ErrorCodes} from '../openaireLibrary/utils/properties/errorCodes'; import {ErrorMessagesComponent} from '../openaireLibrary/utils/errorMessages.component'; import {HelperService} from "../openaireLibrary/utils/helper/helper.service"; import {SEOService} from "../openaireLibrary/sharedComponents/SEO/SEO.service"; import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service"; import {Category, IndicatorPath, Stakeholder, SubCategory, Topic} from "../openaireLibrary/monitor/entities/stakeholder"; import {StatisticsService} from "../utils/services/statistics.service"; import {IndicatorUtils, StakeholderUtils} from "../utils/indicator-utils"; import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service"; import {FormBuilder, FormControl} from "@angular/forms"; import {Subscription} from "rxjs"; import {Session, User} from "../openaireLibrary/login/utils/helper.class"; import {UserManagementService} from "../openaireLibrary/services/user-management.service"; import {RangeFilter} from "../openaireLibrary/utils/rangeFilter/rangeFilterHelperClasses.class"; import {Filter, Value} from "../openaireLibrary/searchPages/searchUtils/searchHelperClasses.class"; import {Location} from "@angular/common"; import {RouterHelper} from "../openaireLibrary/utils/routerHelper.class"; @Component({ selector: 'monitor', templateUrl: 'monitor.component.html', styleUrls:['monitor.component.css'] }) export class MonitorComponent implements OnInit, OnDestroy { public user: User; public subscriptions: any[] = []; public piwiksub: any; public pageContents = null; public divContents = null; public status: number; public loading: boolean = true; public isViewPublic: boolean = false; public indicatorUtils: IndicatorUtils = new IndicatorUtils(); public stakeholderUtils: StakeholderUtils = new StakeholderUtils(); public activeTopic: Topic = null; public activeCategory: Category = null; public activeSubCategory: SubCategory = null; public errorCodes: ErrorCodes; public stakeholder: Stakeholder; public numberResults: Map = new Map(); public chartsActiveType: Map = new Map(); private errorMessages: ErrorMessagesComponent; properties: EnvProperties; filterToggle = false; public routerHelper: RouterHelper = new RouterHelper(); filters:Filter[] = []; queryParams = {}; periodFilter:RangeFilter = { title: "Time range", filterId: "year", originalFilterIdFrom: null, originalFilterIdTo: null, selectedFromValue: null, selectedToValue: null, selectedFromAndToValues: ""}; privateStakeholder = false; public keyword: FormControl; constructor( private route: ActivatedRoute, private _router: Router, private _meta: Meta, private _title: Title, private _piwikService: PiwikService, private helper: HelperService, private stakeholderService: StakeholderService, private userManagementService: UserManagementService, private statisticsService: StatisticsService, private layoutService: LayoutService, private seoService: SEOService, private cdr: ChangeDetectorRef, private sanitizer: DomSanitizer, private _fb: FormBuilder, private router: Router, private location: Location) { this.errorCodes = new ErrorCodes(); this.errorMessages = new ErrorMessagesComponent(); this.status = this.errorCodes.LOADING; } public ngOnInit() { this.keyword = this._fb.control(''); this.keyword.valueChanges.subscribe(value => { console.log("Keyword Changed!"); //TODO do a real action }); this.route.data .subscribe((data: { envSpecific: EnvProperties }) => { let subscription: Subscription; this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { this.user = user; this.route.params.subscribe(params => { this.loading = true; this.activeTopic = null; this.activeCategory = null; this.activeSubCategory = null; this.filterToggle = false; if (subscription) { subscription.unsubscribe(); } this.properties = data.envSpecific; var url = data.envSpecific.baseLink + this._router.url; this.route.queryParams.subscribe(params => { this.queryParams = Object.assign({}, params); this.isViewPublic = (params['view'] == 'public'); }); if (!this.stakeholder || this.stakeholder.alias !== params['stakeholder']) { this.status = this.errorCodes.LOADING; this.numberResults = new Map(); this.chartsActiveType = new Map(); subscription = this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => { if (stakeholder) { this.stakeholder = stakeholder; // add fl0 filter only for EC if(this.stakeholder.index_id == "ec__________::EC"){ this.filters.push({title: "Funding Stream",filterId: "relfundinglevel0_id",originalFilterId: "relfundinglevel0_id", countSelectedValues: 0, values:[{name: "EC|FP7", id: "ec__________::EC::FP7", selected: false, number: 0}, {name: "EC|H2020", id: "ec__________::EC::H2020", selected: false, number: 0}] ,filterOperator: "or", valueIsExact: true, filterType: "radio", radioValue:""}); } if(this.stakeholder.type == "funder"){ // this.filters.push({title: "Co-funded research outcomes",filterId: "co-funded",originalFilterId: "co-funded", countSelectedValues: 0, // values:[{name: "true", id: "co-funded", selected: false, number: 0}, {name: "false", id: "no-co-funded", selected: false, number: 0}] // ,filterOperator: "or", valueIsExact: true, filterType: "radio", radioValue:""}); this.filters.push({title: "Co-funded",filterId: "co-funded",originalFilterId: "co-funded", countSelectedValues: 0, values:[{name: "Co-funded research output", id: "co-funded-results", selected: false, number: 0}] ,filterOperator: "or", valueIsExact: true, filterType: "checkbox", radioValue:""}); } this.initializeFilters(); if(stakeholder.isActive && (stakeholder.isPublic || this.isPublicOrIsMember(stakeholder.isPublic))) { this.seoService.createLinkForCanonicalURL(url, false); this._meta.updateTag({content: url}, "property='og:url'"); var description = "Monitor Dashboard | " + this.stakeholder.name; var title = "Monitor Dashboard | " + this.stakeholder.name; this._meta.updateTag({content: description}, "name='description'"); this._meta.updateTag({content: description}, "property='og:description'"); this._meta.updateTag({content: title}, "property='og:title'"); this._title.setTitle(title); if (this.properties.enablePiwikTrack && (typeof document !== 'undefined')) { this.piwiksub = this._piwikService.trackView(this.properties, title, this.properties.piwikSiteId).subscribe(); } //this.getDivContents(); this.getPageContents(); this.status = this.errorCodes.DONE; this.setView(params); } else { this.privateStakeholder = true; // this.navigateToError(); if(subscription) { subscription.unsubscribe(); } } } }); this.subscriptions.push(subscription); } else { console.debug(" stakeholder is already available") this.initializeFilters(); this.setView(params); } }); })); }); } private initializeFilters(){ this.periodFilter.selectedFromValue = (this.queryParams['year'] && this.queryParams['year'].indexOf("range")==0)?this.queryParams['year'].split("range")[1].split(":")[0]:""; this.periodFilter.selectedToValue = (this.queryParams['year'] && this.queryParams['year'].indexOf("range")==0)?this.queryParams['year'].split("range")[1].split(":")[1]:""; this.validateYearRange(false); for(let filter of this.filters) { if (this.queryParams[filter.filterId]) { for (let value of filter.values) { if (value.id == this.queryParams[filter.filterId]) { value.selected = true; filter.countSelectedValues = 1; break; } } }else{ this.clearfFilter(filter); } } } private validateYearRange(navigateTo:boolean=false){ let validYears = true; if(this.periodFilter.selectedToValue && (this.periodFilter.selectedToValue.length == 0 || !Dates.isValidYear(this.periodFilter.selectedToValue, Dates.currentYear - 20, Dates.currentYear))){ this.periodFilter.selectedToValue = Dates.currentYear+""; validYears = false; } if( this.periodFilter.selectedFromValue && (this.periodFilter.selectedFromValue.length == 0 || !Dates.isValidYear(this.periodFilter.selectedFromValue, Dates.currentYear - 20, Dates.currentYear))){ this.periodFilter.selectedFromValue = Dates.currentYear - 20+""; validYears = false; } if(this.periodFilter.selectedFromValue && this.periodFilter.selectedFromValue.length && this.periodFilter.selectedToValue && this.periodFilter.selectedToValue.length > 0 && parseInt(this.periodFilter.selectedFromValue, 10) > parseInt(this.periodFilter.selectedToValue, 10)){ this.periodFilter.selectedFromValue = this.periodFilter.selectedToValue; validYears = false; } if(!validYears || navigateTo){ if(this.periodFilter.selectedFromValue || this.periodFilter.selectedToValue){ this.queryParams["year"]='range'+(this.periodFilter.selectedFromValue?this.periodFilter.selectedFromValue:'')+":"+(this.periodFilter.selectedToValue?this.periodFilter.selectedToValue:""); }else{ delete this.queryParams["year"]; } // this.location.go(location.pathname, this.routerHelper.createQueryParamsString( Object.keys(this.queryParams), Object.values(this.queryParams))); this.router.navigate([], {queryParams: this.queryParams }); this.setIndicators(); } } clearAll(){ for(let filter of this.filters) { this.clearfFilter(filter); } this.periodFilter.selectedFromValue = ""; this.periodFilter.selectedToValue = ""; this.validateYearRange(true) } clearfFilter(filter:Filter){ filter.countSelectedValues = 0; filter.radioValue = ""; for (let value of filter.values) { if (value.selected) { value.selected = false; } } if (this.queryParams[filter.filterId]) { delete this.queryParams[filter.filterId]; } } countSelectedFilters():number{ let count = 0; if(this.periodFilter.selectedFromAndToValues.length > 0){ count+=2; } for(let filter of this.filters) { count +=filter.countSelectedValues; } return count; } public get open() { return this.layoutService.open; } private getPageContents() { this.helper.getPageHelpContents(this.properties, 'monitor', this._router.url).subscribe(contents => { this.pageContents = contents; }) } private getDivContents() { this.helper.getDivHelpContents(this.properties, 'monitor', this._router.url).subscribe(contents => { this.divContents = contents; }) } private setView(params: Params) { this.loading = false; if (params['topic']) { this.activeTopic = this.stakeholder.topics.find(topic => topic.alias === decodeURIComponent(params['topic']) && this.isPublicOrIsMember(topic.isPublic) && topic.isActive); if (this.activeTopic) { if (params['category']) { this.activeCategory = this.activeTopic.categories.find(category => (category.alias === params['category']) && this.isPublicOrIsMember(category.isPublic) && category.isActive); if (!this.activeCategory) { this.navigateToError(); return; } } else { this.activeCategory = this.activeTopic.categories.find(category => this.isPublicOrIsMember(category.isPublic) && category.isActive); if (this.activeCategory) { this.activeSubCategory = this.activeCategory.subCategories.find(subCategory => this.isPublicOrIsMember(subCategory.isPublic) && subCategory.isActive); if (this.activeSubCategory) { this.setIndicators(); } } return; } if (this.activeCategory) { if (params['subCategory']) { this.activeSubCategory = this.activeCategory.subCategories.find(subCategory => (subCategory.alias === params['subCategory'] && this.isPublicOrIsMember(subCategory.isPublic) && subCategory.isActive)); if (!this.activeSubCategory) { this.navigateToError(); return; } } else { this.activeSubCategory = this.activeCategory.subCategories.find(subCategory => this.isPublicOrIsMember(subCategory.isPublic) && subCategory.isActive); } if (this.activeSubCategory) { this.setIndicators(); } else { this.navigateToError(); } return; } else { this.activeSubCategory = null; } } else { this.navigateToError(); return; } } else { this.activeTopic = this.stakeholder.topics.find(topic => this.isPublicOrIsMember(topic.isPublic) && topic.isActive); if (this.activeTopic) { this.activeCategory = this.activeTopic.categories.find(category => this.isPublicOrIsMember(category.isPublic) && category.isActive); if (this.activeCategory) { this.activeSubCategory = this.activeCategory.subCategories.find(subCategory => this.isPublicOrIsMember(subCategory.isPublic) && subCategory.isActive); if (this.activeSubCategory) { this.setIndicators(); } } } } } filter(){ this.validateYearRange(true); } filterChanged($event, navigate:boolean = true) { let selected = ""; for(let value of $event.value.values){ if(value.selected){ selected = value.id; break; } } if(selected){ this.queryParams[$event.value.filterId]=selected; }else{ delete this.queryParams[$event.value.filterId]; } if(navigate) { this.router.navigate([], {queryParams: this.queryParams }); this.setIndicators(); } } private getfl0(){ if (this.queryParams["relfundinglevel0_id"] && this.filters.length > 0){ return this.queryParams["relfundinglevel0_id"].split("::")[this.queryParams["relfundinglevel0_id"].split("::").length -1]; } return null; } private getCoFunded(){ if (this.queryParams["co-funded"] && this.filters.length > 0){ return this.queryParams["co-funded"] && this.queryParams["co-funded"]=="co-funded-results"; } return false; } clearPeriodFilter(){ if(this.periodFilter.selectedFromValue || this.periodFilter.selectedToValue){ this.periodFilter.selectedFromValue = ""; this.periodFilter.selectedToValue = ""; this.filter(); } } private setIndicators() { this.periodFilter.selectedFromAndToValues = (this.periodFilter.selectedFromValue || this.periodFilter.selectedToValue?((this.periodFilter.selectedFromValue && !this.periodFilter.selectedToValue?"From ":"")+(!this.periodFilter.selectedFromValue && this.periodFilter.selectedToValue?"Until ":"")+ (this.periodFilter.selectedFromValue?this.periodFilter.selectedFromValue:"") + (this.periodFilter.selectedFromValue && this.periodFilter.selectedToValue?" - ":"")+ (this.periodFilter.selectedToValue?this.periodFilter.selectedToValue:"")):""); //clear numbers when filters change this.numberResults.clear(); let urls: Map = new Map(); this.activeSubCategory.numbers.forEach((section, i) => { section.indicators.forEach((number, j) => { if (number.isActive && this.isPublicOrIsMember(number.isPublic)) { let url =this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, number.indicatorPaths[0], this.getfl0(), this.periodFilter.selectedFromValue, this.periodFilter.selectedToValue, this.getCoFunded()); const pair = JSON.stringify([number.indicatorPaths[0].source, url]); const indexes = urls.get(pair) ? urls.get(pair) : []; indexes.push([i, j]); urls.set(pair, indexes); } }); }); urls.forEach((indexes, pair) => { pair = JSON.parse(pair); this.statisticsService.getNumbers(this.statisticsService.getSourceType(pair[0]), pair[1]).subscribe(response => { indexes.forEach(([i, j]) => { let result = JSON.parse(JSON.stringify(response)); this.activeSubCategory.numbers[i].indicators[j].indicatorPaths[0].jsonPath.forEach(jsonPath => { if (result) { result = result[jsonPath]; } }); this.numberResults.set(i + '-' + j, result); }); }) }); this.activeSubCategory.charts.forEach((section, i) => { section.indicators.forEach((indicator, j) => { if (indicator.indicatorPaths.length > 0) { indicator.indicatorPaths[0].safeResourceUrl = this.getUrlByStakeHolder(indicator.indicatorPaths[0]); this.chartsActiveType.set(i + '-' + j, indicator.indicatorPaths[0]); } }); }); if (this.cdr && !(this.cdr as ViewRef).destroyed) { this.cdr.detectChanges(); } } public getUrlByStakeHolder(indicatorPath: IndicatorPath) { return this.sanitizer.bypassSecurityTrustResourceUrl( this.statisticsService.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, indicatorPath, this.getfl0(), this.periodFilter.selectedFromValue, this.periodFilter.selectedToValue, this.getCoFunded()))); } public setActiveChart(i: number, j: number, type: string) { let activeChart = this.activeSubCategory.charts[i].indicators[j].indicatorPaths.filter(indicatorPath => indicatorPath.type === type)[0]; activeChart.safeResourceUrl = this.getUrlByStakeHolder(activeChart); this.chartsActiveType.set(i + '-' + j, activeChart); } private navigateToError() { this._router.navigate(['/error'], {queryParams: {'page': this._router.url}}); } public navigateTo(stakeholder: string, topic: string, category: string = null, subcategory: string = null) { let url = stakeholder + '/' + topic + ((category) ? ('/' + category) : '') + ((subcategory) ? ('/' + subcategory) : ''); return this._router.navigate([url],{ queryParams: this.queryParams}); } public quote(param: string): string { return StringUtils.quote(param); } public ngOnDestroy() { if (this.piwiksub) { this.piwiksub.unsubscribe(); } } isAdmin(){ return this.user && (Session.isPortalAdministrator(this.user) || Session.isCommunityCurator(this.user) || Session.isMonitorCurator(this.user)); } public isPublicOrIsMember(isPublic: boolean): boolean { if (isPublic) { return true; } else { if (this.isViewPublic) { // preview for not members return false; } else if(this.isAdmin()) { // if user is member, return true return true; } return false; } } public countSubCategoriesToShow(category:Category): number { let counter = 0; for (let sub of category.subCategories) { if(sub.isActive) { if (sub.isPublic) { // return true; counter++; }else if (this.isAdmin()) { counter++; } } } return counter; } /* Feedback mail */ public get mailText() { return "mailto:"+this.properties.feedbackmail+"?subject=%5BOpenAIRE%20Monitor%5D%20"+(this.stakeholder?this.stakeholder.name:"")+"%20dashboard%20feedback" } mailMe(){ window.location.href = this.mailText; } }