Project

General

Profile

1
import {ChangeDetectorRef, Component, OnDestroy, OnInit, ViewRef} from '@angular/core';
2
import {ActivatedRoute, Params, Router} from '@angular/router';
3
import {DomSanitizer, Meta, Title} from '@angular/platform-browser';
4
import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties';
5

    
6
import {PiwikService} from '../openaireLibrary/utils/piwik/piwik.service';
7
import {Dates, StringUtils} from '../openaireLibrary/utils/string-utils.class';
8
import {ErrorCodes} from '../openaireLibrary/utils/properties/errorCodes';
9
import {ErrorMessagesComponent} from '../openaireLibrary/utils/errorMessages.component';
10
import {HelperService} from "../openaireLibrary/utils/helper/helper.service";
11
import {SEOService} from "../openaireLibrary/sharedComponents/SEO/SEO.service";
12
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
13
import {Category, IndicatorPath, Stakeholder, SubCategory, Topic} from "../openaireLibrary/monitor/entities/stakeholder";
14
import {StatisticsService} from "../utils/services/statistics.service";
15
import {IndicatorUtils, StakeholderUtils} from "../utils/indicator-utils";
16
import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service";
17
import {FormBuilder, FormControl} from "@angular/forms";
18
import {Subscription} from "rxjs";
19
import {Session, User} from "../openaireLibrary/login/utils/helper.class";
20
import {UserManagementService} from "../openaireLibrary/services/user-management.service";
21
import {RangeFilter} from "../openaireLibrary/utils/rangeFilter/rangeFilterHelperClasses.class";
22
import {Filter, Value} from "../openaireLibrary/searchPages/searchUtils/searchHelperClasses.class";
23
import {Location} from "@angular/common";
24
import {RouterHelper} from "../openaireLibrary/utils/routerHelper.class";
25

    
26
@Component({
27
  selector: 'monitor',
28
  templateUrl: 'monitor.component.html',
29
  styleUrls:['monitor.component.css']
30
})
31
export class MonitorComponent implements OnInit, OnDestroy {
32
  public user: User;
33
  public subscriptions: any[] = [];
34
  public piwiksub: any;
35
  public pageContents = null;
36
  public divContents = null;
37
  public status: number;
38
  public loading: boolean = true;
39
  public isViewPublic: boolean = false;
40
  public indicatorUtils: IndicatorUtils = new IndicatorUtils();
41
  public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
42
  public activeTopic: Topic = null;
43
  public activeCategory: Category = null;
44
  public activeSubCategory: SubCategory = null;
45
  public errorCodes: ErrorCodes;
46
  public stakeholder: Stakeholder;
47
  public numberResults: Map<string, number> = new Map<string, number>();
48
  public chartsActiveType: Map<string, IndicatorPath> = new Map<string, IndicatorPath>();
49
  private errorMessages: ErrorMessagesComponent;
50
  properties: EnvProperties;
51
  filterToggle = false;
52
  public routerHelper: RouterHelper = new RouterHelper();
53
  filters:Filter[] = [];
54
  queryParams = {};
55
  periodFilter:RangeFilter = { title: "Period",  filterId: "year", originalFilterIdFrom: null, originalFilterIdTo: null, selectedFromValue: null, selectedToValue: null, selectedFromAndToValues: ""};
56
  privateStakeholder = false;
57
  public keyword: FormControl;
58
  constructor(
59
    private route: ActivatedRoute,
60
    private _router: Router,
61
    private _meta: Meta,
62
    private _title: Title,
63
    private _piwikService: PiwikService,
64
    private helper: HelperService,
65
    private stakeholderService: StakeholderService,
66
    private userManagementService: UserManagementService,
67
    private statisticsService: StatisticsService,
68
    private layoutService: LayoutService,
69
    private seoService: SEOService,
70
    private cdr: ChangeDetectorRef,
71
    private sanitizer: DomSanitizer, private _fb: FormBuilder,  private router: Router,
72
    private location: Location) {
73
    this.errorCodes = new ErrorCodes();
74
    this.errorMessages = new ErrorMessagesComponent();
75
    this.status = this.errorCodes.LOADING;
76
  }
77

    
78
  public ngOnInit() {
79
    this.keyword = this._fb.control('');
80
    this.keyword.valueChanges.subscribe(value => {
81
      console.log("Keyword Changed!");
82
      //TODO do a real action
83
    });
84
    this.route.data
85
      .subscribe((data: { envSpecific: EnvProperties }) => {
86
        let subscription: Subscription;
87
        this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
88
          this.user = user;
89

    
90
          this.route.params.subscribe(params => {
91
            this.loading = true;
92
            this.activeTopic = null;
93
            this.activeCategory = null;
94
            this.activeSubCategory = null;
95
            this.filterToggle = false;
96
            if (subscription) {
97
              subscription.unsubscribe();
98
            }
99
            this.properties = data.envSpecific;
100
            var url = data.envSpecific.baseLink + this._router.url;
101
            this.route.queryParams.subscribe(params => {
102
              this.queryParams = Object.assign({}, params);
103
              this.isViewPublic = (params['view'] == 'public');
104
            });
105
            if (!this.stakeholder || this.stakeholder.alias !== params['stakeholder']) {
106
              this.status = this.errorCodes.LOADING;
107
              this.numberResults = new Map<string, number>();
108
              this.chartsActiveType = new Map<string, IndicatorPath>();
109
              subscription = this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
110
                if (stakeholder) {
111
                  this.stakeholder = stakeholder;
112
                  // add fl0 filter only for EC
113
                  if(this.stakeholder.index_id == "ec__________::EC"){
114
                    this.filters.push({title: "Funding Stream",filterId: "relfundinglevel0_id",originalFilterId: "relfundinglevel0_id", countSelectedValues: 0,
115
                      values:[{name: "EC|FP7", id: "ec__________::EC::FP7", selected:  false, number: 0}, {name: "EC|H2020", id: "ec__________::EC::H2020", selected:  false, number: 0}]
116
                      ,filterOperator: "or", valueIsExact: true, filterType: "radio", radioValue:""});
117
                  }
118
                  this.initializeFilters();
119
                  if(stakeholder.isActive && (stakeholder.isPublic || this.isPublicOrIsMember(stakeholder.isPublic))) {
120
                    this.seoService.createLinkForCanonicalURL(url, false);
121
                    this._meta.updateTag({content: url}, "property='og:url'");
122
                    var description = "Monitor Dashboard | " + this.stakeholder.name;
123
                    var title = "Monitor Dashboard | " + this.stakeholder.name;
124
                    this._meta.updateTag({content: description}, "name='description'");
125
                    this._meta.updateTag({content: description}, "property='og:description'");
126
                    this._meta.updateTag({content: title}, "property='og:title'");
127
                    this._title.setTitle(title);
128
                    if (this.properties.enablePiwikTrack && (typeof document !== 'undefined')) {
129
                      this.piwiksub = this._piwikService.trackView(this.properties, title, this.properties.piwikSiteId).subscribe();
130
                    }
131
                    //this.getDivContents();
132
                    this.getPageContents();
133
                    this.status = this.errorCodes.DONE;
134
                    this.setView(params);
135
                    this.layoutService.setOpen(true);
136
                  } else {
137
                    this.privateStakeholder = true;
138
                    // this.navigateToError();
139
                    if(subscription) {
140
                      subscription.unsubscribe();
141
                    }
142
                  }
143
                }
144
              });
145
              this.subscriptions.push(subscription);
146
            } else {
147
              console.debug(" stakeholder is already available")
148
              this.initializeFilters();
149
              this.setView(params);
150
            }
151
          });
152
        }));
153
      });
154
  }
155
  private initializeFilters(){
156
    this.periodFilter.selectedFromValue = (this.queryParams['year'] && this.queryParams['year'].indexOf("range")==0)?this.queryParams['year'].split("range")[1].split(":")[0]:"";
157
    this.periodFilter.selectedToValue = (this.queryParams['year'] && this.queryParams['year'].indexOf("range")==0)?this.queryParams['year'].split("range")[1].split(":")[1]:"";
158
    this.validateYearRange(false);
159

    
160
    for(let filter of this.filters) {
161
      if (this.queryParams[filter.filterId]) {
162
        for (let value of filter.values) {
163
          if (value.id == this.queryParams[filter.filterId]) {
164
            value.selected = true;
165
            filter.countSelectedValues = 1;
166
            break;
167
          }
168
        }
169
      }else{
170
        this.clearfFilter(filter);
171
      }
172
    }
173

    
174
  }
175
  private validateYearRange(navigateTo:boolean=false){
176
    let validYears = true;
177

    
178
    if(this.periodFilter.selectedToValue && (this.periodFilter.selectedToValue.length == 0 ||  !Dates.isValidYear(this.periodFilter.selectedToValue, Dates.currentYear - 20, Dates.currentYear))){
179
      this.periodFilter.selectedToValue = Dates.currentYear+"";
180
      validYears = false;
181
    }
182
    if( this.periodFilter.selectedFromValue && (this.periodFilter.selectedFromValue.length == 0 || !Dates.isValidYear(this.periodFilter.selectedFromValue, Dates.currentYear - 20, Dates.currentYear))){
183
      this.periodFilter.selectedFromValue = Dates.currentYear - 20+"";
184
      validYears = false;
185
    }
186
    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)){
187
      this.periodFilter.selectedFromValue = this.periodFilter.selectedToValue;
188
      validYears = false;
189
    }
190
    if(!validYears || navigateTo){
191
      if(this.periodFilter.selectedFromValue || this.periodFilter.selectedToValue){
192
        this.queryParams["year"]='range'+(this.periodFilter.selectedFromValue?this.periodFilter.selectedFromValue:'')+":"+(this.periodFilter.selectedToValue?this.periodFilter.selectedToValue:"");
193
      }else{
194
         delete this.queryParams["year"];
195
      }
196
      this.location.go(location.pathname, this.routerHelper.createQueryParamsString( Object.keys(this.queryParams), Object.values(this.queryParams)));
197
      this.setIndicators();
198
    }
199
  }
200
  clearAll(){
201
    for(let filter of this.filters) {
202
      this.clearfFilter(filter);
203
    }
204
    this.periodFilter.selectedFromValue = "";
205
    this.periodFilter.selectedToValue = "";
206
    this.validateYearRange(true)
207
  }
208
  clearfFilter(filter:Filter){
209
    filter.countSelectedValues = 0;
210
    filter.radioValue = "";
211
    for (let value of filter.values) {
212
      if (value.selected) {
213
        value.selected = false;
214
      }
215
    }
216
    if (this.queryParams[filter.filterId]) {
217
      delete this.queryParams[filter.filterId];
218
    }
219
  }
220
  countSelectedFilters():number{
221
    let count = 0;
222
    if(this.periodFilter.selectedFromAndToValues.length > 0){
223
      count++;
224
    }
225
    for(let filter of this.filters) {
226
      count +=filter.countSelectedValues;
227
    }
228
    return count;
229
  }
230
  public get open() {
231
    return this.layoutService.open;
232
  }
233

    
234
  private getPageContents() {
235
    this.helper.getPageHelpContents(this.properties, 'monitor', this._router.url).subscribe(contents => {
236
      this.pageContents = contents;
237
    })
238
  }
239

    
240
  private getDivContents() {
241
    this.helper.getDivHelpContents(this.properties, 'monitor', this._router.url).subscribe(contents => {
242
      this.divContents = contents;
243
    })
244
  }
245

    
246
  private setView(params: Params) {
247
    if (params['topic']) {
248
      this.activeTopic = this.stakeholder.topics.find(topic => topic.alias === decodeURIComponent(params['topic']) && this.isPublicOrIsMember(topic.isPublic) && topic.isActive);
249
      if (this.activeTopic) {
250
        if (params['category']) {
251
          this.activeCategory = this.activeTopic.categories.find(category =>
252
            (category.alias === params['category']) && this.isPublicOrIsMember(category.isPublic) && category.isActive);
253
          if (!this.activeCategory) {
254
            this.navigateToError();
255
            return;
256
          }
257
        } else {
258
          this.activeCategory = this.activeTopic.categories.find(category => this.isPublicOrIsMember(category.isPublic) && category.isActive);
259
          if (this.activeCategory) {
260
            this.activeSubCategory = this.activeCategory.subCategories.find(subCategory =>
261
              this.isPublicOrIsMember(subCategory.isPublic) && subCategory.isActive);
262
            if (this.activeSubCategory) {
263
              this.setIndicators();
264
            }
265
          }
266
          return;
267
        }
268
        if (this.activeCategory) {
269
          if (params['subCategory']) {
270
            this.activeSubCategory = this.activeCategory.subCategories.find(subCategory =>
271
              (subCategory.alias === params['subCategory'] && this.isPublicOrIsMember(subCategory.isPublic) && subCategory.isActive));
272
            if (!this.activeSubCategory) {
273
              this.navigateToError();
274
              return;
275
            }
276
          } else {
277
            this.activeSubCategory = this.activeCategory.subCategories.find(subCategory =>
278
              this.isPublicOrIsMember(subCategory.isPublic) && subCategory.isActive);
279
          }
280
          if (this.activeSubCategory) {
281
            this.setIndicators();
282
          } else {
283
            this.navigateToError();
284
          }
285
          return;
286
        } else {
287
          this.activeSubCategory = null;
288
        }
289
      } else {
290
        this.navigateToError();
291
        return;
292
      }
293
    } else {
294
      this.activeTopic = this.stakeholder.topics.find(topic => this.isPublicOrIsMember(topic.isPublic) && topic.isActive);
295
      if (this.activeTopic) {
296
        this.activeCategory = this.activeTopic.categories.find(category => this.isPublicOrIsMember(category.isPublic) && category.isActive);
297
        if (this.activeCategory) {
298
          this.activeSubCategory = this.activeCategory.subCategories.find(subCategory => this.isPublicOrIsMember(subCategory.isPublic) && subCategory.isActive);
299
          if (this.activeSubCategory) {
300
            this.setIndicators();
301
          }
302
        }
303
      }
304
    }
305
  }
306

    
307
  filter(){
308
    this.validateYearRange(true);
309
  }
310
  filterChanged($event, navigate:boolean = true) {
311
    let selected = "";
312
    for(let value of $event.value.values){
313
      if(value.selected){
314
        selected = value.id;
315
        break;
316
      }
317
    }
318
    if(selected){
319
      this.queryParams[$event.value.filterId]=selected;
320
    }else{
321
      delete this.queryParams[$event.value.filterId];
322
    }
323
    if(navigate) {
324
      this.location.go(location.pathname, this.routerHelper.createQueryParamsString( Object.keys(this.queryParams), Object.values(this.queryParams)));
325
      this.setIndicators();
326
    }
327

    
328
  }
329
  private getfl0(){
330
    if (this.queryParams["relfundinglevel0_id"] && this.filters.length > 0){
331
      return this.queryParams["relfundinglevel0_id"].split("::")[this.queryParams["relfundinglevel0_id"].split("::").length -1];
332
    }
333
    return null;
334
  }
335
    clearPeriodFilter(){
336
    if(this.periodFilter.selectedFromValue || this.periodFilter.selectedToValue){
337
      this.periodFilter.selectedFromValue = "";
338
      this.periodFilter.selectedToValue = "";
339
      this.filter();
340
    }
341

    
342
  }
343
  private setIndicators() {
344
    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:"") +
345
      (this.periodFilter.selectedFromValue && this.periodFilter.selectedToValue?" - ":"")+ (this.periodFilter.selectedToValue?this.periodFilter.selectedToValue:"")):"");
346
    //clear numbers when filters change
347
    this.numberResults.clear();
348
    let urls: Map<string, [number, number][]> = new Map<string, [number, number][]>();
349
    this.activeSubCategory.numbers.forEach((section, i) => {
350
      section.indicators.forEach((number, j) => {
351
        if (number.isActive && this.isPublicOrIsMember(number.isPublic)) {
352
          let url =this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, number.indicatorPaths[0], this.getfl0(), this.periodFilter.selectedFromValue, this.periodFilter.selectedToValue);
353
          const pair = JSON.stringify([number.indicatorPaths[0].source, url]);
354
          const indexes = urls.get(pair) ? urls.get(pair) : [];
355
          indexes.push([i, j]);
356
          urls.set(pair, indexes);
357
        }
358
      });
359
    });
360
    urls.forEach((indexes, pair) => {
361
      pair = JSON.parse(pair);
362
      this.statisticsService.getNumbers(this.statisticsService.getSourceType(pair[0]),  pair[1]).subscribe(response => {
363
        indexes.forEach(([i, j]) => {
364
          let result = JSON.parse(JSON.stringify(response));
365
          this.activeSubCategory.numbers[i].indicators[j].indicatorPaths[0].jsonPath.forEach(jsonPath => {
366
            if (result) {
367
              result = result[jsonPath];
368
            }
369
          });
370
          this.numberResults.set(i + '-' + j, result);
371
        });
372
      })
373
    });
374
    this.activeSubCategory.charts.forEach((section, i) => {
375
      section.indicators.forEach((indicator, j) => {
376
        if (indicator.indicatorPaths.length > 0) {
377
          indicator.indicatorPaths[0].safeResourceUrl = this.getUrlByStakeHolder(indicator.indicatorPaths[0]);
378
          this.chartsActiveType.set(i + '-' + j, indicator.indicatorPaths[0]);
379
        }
380
      });
381
    });
382
    if (this.cdr && !(this.cdr as ViewRef).destroyed) {
383
      this.cdr.detectChanges();
384
    }
385
  }
386

    
387
  public getUrlByStakeHolder(indicatorPath: IndicatorPath) {
388
    return this.sanitizer.bypassSecurityTrustResourceUrl(
389
      this.statisticsService.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, indicatorPath,  this.getfl0(), this.periodFilter.selectedFromValue, this.periodFilter.selectedToValue)));
390
  }
391

    
392
  public setActiveChart(i: number, j: number, type: string) {
393
    let activeChart = this.activeSubCategory.charts[i].indicators[j].indicatorPaths.filter(indicatorPath => indicatorPath.type === type)[0];
394
    activeChart.safeResourceUrl = this.getUrlByStakeHolder(activeChart);
395
    this.chartsActiveType.set(i + '-' + j, activeChart);
396
  }
397

    
398
  private navigateToError() {
399
    this._router.navigate(['/error'], {queryParams: {'page': this._router.url}});
400
  }
401

    
402
  public navigateTo(stakeholder: string, topic: string, category: string = null, subcategory: string = null) {
403
    let url = stakeholder + '/' + topic + ((category) ? ('/'
404
      + category) : '') + ((subcategory) ? ('/' + subcategory) : '');
405
    return this._router.navigate([url]);
406
  }
407

    
408
  public quote(param: string): string {
409
    return StringUtils.quote(param);
410
  }
411

    
412
  public ngOnDestroy() {
413
    if (this.piwiksub) {
414
      this.piwiksub.unsubscribe();
415
    }
416
  }
417

    
418
  isAdmin(){
419
    return this.user && (Session.isPortalAdministrator(this.user) || Session.isCommunityCurator(this.user) || Session.isMonitorCurator(this.user));
420
  }
421

    
422
  public isPublicOrIsMember(isPublic: boolean): boolean {
423
    if (isPublic) {
424
      return true;
425
    } else {
426
      if (this.isViewPublic) { // preview for not members
427
        return false;
428
      } else if(this.isAdmin()) {
429
        // if user is member, return true
430
        return true;
431
      }
432
      return false;
433
    }
434
  }
435
}
(4-4/5)