Project

General

Profile

1
import {ChangeDetectorRef, Component, Input, ViewChild} from '@angular/core';
2
import {ActivatedRoute, Router} from '@angular/router';
3
import {Meta, Title} from '@angular/platform-browser';
4

    
5
import {EnvProperties} from '../../utils/properties/env-properties';
6
import {Id, ResultLandingInfo} from '../../utils/entities/resultLandingInfo';
7
import {RouterHelper} from '../../utils/routerHelper.class';
8

    
9
import {PiwikService} from '../../utils/piwik/piwik.service';
10
import {ResultLandingService} from './resultLanding.service';
11
import {SEOService} from '../../sharedComponents/SEO/SEO.service';
12
import {HelperFunctions} from '../../utils/HelperFunctions.class';
13
import {HelperService} from '../../utils/helper/helper.service';
14
import {Location} from "@angular/common";
15
import {MetricsService} from "../../services/metrics.service";
16
import {Organization, RelationResult, ResultPreview} from "../../utils/result-preview/result-preview";
17
import {IndexInfoService} from "../../utils/indexInfo.service";
18

    
19

    
20
@Component({
21
  selector: 'result-landing',
22
  templateUrl: 'resultLanding.component.html',
23
})
24
export class ResultLandingComponent {
25
  @Input() type: string = "publication";
26
  @Input() piwikSiteId = null;
27
  @Input() communityId = null;
28
  
29
  // Active tab variable for responsiveness
30
  @Input() activeTab: string = "References";
31
  @ViewChild('linkModal') linkModal;
32
  @ViewChild('citeModal') citeModal;
33
  @ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference;
34
  @ViewChild('relationModal') relationModal;
35
  @ViewChild('organizationModal') organizationModal;
36
  public deleteByInferenceOpened: boolean = false;
37
  
38
  public resultLandingInfo: ResultLandingInfo;
39
  public relationResults: RelationResult[];
40
  public relation: string = 'trust';
41
  public id: string;
42
  public title: string;
43
  
44
  // Links for SEO
45
  public linkToLandingPage: string = null;
46
  public linkToSearchPage: string = null;
47
  
48
  public thresholdDescription: number = 670;
49
  public showNumDescription: number = 670;
50
  
51
  // Metrics tab variables
52
  public metricsClicked: boolean;
53
  public hasAltMetrics: boolean = false;
54
  public viewsFrameUrl: string;
55
  public downloadsFrameUrl: string;
56
  public totalViews: number;
57
  public totalDownloads: number;
58
  public pageViews: number;
59
  
60
  // Custom tab paging variables
61
  public referencesPage: number = 1;
62
  public bioentitiesPage: number = 1;
63
  public relationPage: number = 1;
64
  public organizationsPage: number = 1;
65
  public softwarePage: number = 1;
66
  public openCitationsPage: number = 1;
67
  public pageSize: number = 10;
68
  
69
  // Map counting variables
70
  public bioentitiesNum: number = 0;
71
  
72
  // Message variables
73
  public warningMessage = "";
74
  public errorMessage = "";
75
  public showLoading: boolean = true;
76
  
77
  public routerHelper: RouterHelper = new RouterHelper();
78
  
79
  private doi: string;
80
  public doiURL: string;
81
  sub: any;
82
  piwiksub: any;
83
  infoSub: any;
84
  properties: EnvProperties;
85
  public indexUpdateDate: Date;
86
  public pageContents = null;
87
  public divContents = null;
88
  public showFeedback: boolean = false;
89
  public feedbackFields: string [] = [
90
    'Title', 'Authors', 'Access rights',
91
    'Publisher information', 'Funding Information',
92
    'Persistent identifiers', 'Other'];
93
  
94
  constructor(private _resultLaningService: ResultLandingService,
95
              private _piwikService: PiwikService,
96
              private route: ActivatedRoute,
97
              private router: Router,
98
              private _meta: Meta,
99
              private _title: Title,
100
              private _router: Router,
101
              private helper: HelperService,
102
              private seoService: SEOService,
103
              private metricsService: MetricsService,
104
              private cdr: ChangeDetectorRef,
105
              private _location: Location,
106
              private indexInfoService: IndexInfoService) {
107
  }
108
  
109
  ngOnInit() {
110
    this.route.data
111
      .subscribe((data: { envSpecific: EnvProperties }) => {
112
        this.properties = data.envSpecific;
113
        this.indexInfoService.getLastIndexDate(this.properties).subscribe(lastIndexUpdate => {
114
          if (lastIndexUpdate) {
115
            this.indexUpdateDate = new Date(lastIndexUpdate);
116
          } else if (this.properties.lastIndexUpdate) {
117
            this.indexUpdateDate = new Date(this.properties.lastIndexUpdate);
118
          }
119
        });
120
        //this.getDivContents();
121
        this.getPageContents();
122
        this.doiURL = this.properties.doiURL;
123
        this.updateUrl(data.envSpecific.baseLink + this._router.url);
124
        this.sub = this.route.queryParams.subscribe(data => {
125
          this.resultLandingInfo = null;
126
          if (this.type == "publication") {
127
            this.updateTitle("Publication");
128
            this.linkToLandingPage = this.properties.searchLinkToPublication;
129
            this.linkToSearchPage = this.properties.searchLinkToPublications;
130
            this.id = data['articleId'];
131
            this.title = "Publication";
132
          } else if (this.type == "dataset") {
133
            this.updateTitle("Dataset");
134
            this.linkToLandingPage = this.properties.searchLinkToDataset;
135
            this.linkToSearchPage = this.properties.searchLinkToDatasets;
136
            this.id = data['datasetId'];
137
            this.title = "Research Data";
138
          } else if (this.type == "software") {
139
            this.updateTitle("Software");
140
            this.linkToLandingPage = this.properties.searchLinkToSoftware;
141
            this.linkToSearchPage = this.properties.searchLinkToSoftwareLanding;
142
            this.id = data['softwareId'];
143
            this.title = "Software";
144
          } else if (this.type == "orp") {
145
            this.updateTitle("Other Research Product");
146
            this.linkToLandingPage = this.properties.searchLinkToOrp;
147
            this.linkToSearchPage = this.properties.searchLinkToOrps;
148
            this.id = data['orpId'];
149
            this.title = "Other Research Product";
150
          } else if (this.type == "result") {
151
            this.id = data["id"];
152
            this.updateTitle("Research Result");
153
            this.linkToLandingPage = this.properties.searchLinkToOrp;
154
            this.linkToSearchPage = this.properties.searchLinkToResults;
155
            this.title = "Research Result";
156
          }
157
          this.updateDescription("");
158
          
159
          this.metricsClicked = false;
160
          
161
          if (this.id) {
162
            this.getProvenanceVocabularyAndResultLandingInfo();
163
          } else {
164
            this.showLoading = false;
165
            
166
            this._router.navigate(['/error'], {
167
              queryParams: {
168
                "page": this._location.path(true),
169
                "page_type": this.type
170
              }
171
            });
172
            /*
173
            this.warningMessage = "No valid ";
174
            if(this.type == "publication" || this.type == "software") {
175
              this.warningMessage += this.type + " ";
176
            } else if(this.type == "dataset") {
177
              this.warningMessage += "research data ";
178
            } else if(this.type == "orp") {
179
              this.warningMessage += "other research product ";
180
            }
181
            this.warningMessage += "id";
182
            */
183
          }
184
          
185
          this.viewsFrameUrl = this.properties.framesAPIURL + 'merge.php?com=query&data=[{"query":"resRepoViews", "resTitle":"' + this.id + '", "table":"","fields":[{"fld":"sum","agg":"sum","type":"column","yaxis":1,"c":false}],"xaxis":{"name":"month","agg":"sum"},"group":" ","color":"","type":"chart","size":80,"sort":"xaxis","xStyle":{"r":-30,"s":"6","l":"-","ft":"-","wt":"-"},"title":"","subtitle":"","xaxistitle":"Repository","yaxisheaders":["Monthly views"],"generalxaxis":"","theme":0,"in":[],"filters":[{"name":"","values":[""],"to":"-1"}]}]&info_types=["column"]&stacking=normal&steps=false&fontFamily=Courier&spacing=[5,0,0,0]&style=[{"color":"rgba(0, 0, 0, 1)","size":"18"},{"color":"rgba(0, 0, 0, 1)","size":"18"},{"color":"000000","size":""},{"color":"000000","size":""}]&backgroundColor=rgba(255,255,255,1)&colors[]=rgba(67, 67, 72, 1)&colors[]=rgba(144, 237, 125, 1)&colors[]=rgba(247, 163, 92, 1)&colors[]=rgba(128, 133, 233, 1)&colors[]=rgba(241, 92, 128, 1)&colors[]=rgba(228, 211, 84, 1)&colors[]=rgba(43, 144, 143, 1)&colors[]=rgba(244, 91, 91, 1)&colors[]=rgba(145, 232, 225, 1)&xlinew=0&ylinew=1&legends=true&tooltips=true&persistent=false';
186
          this.downloadsFrameUrl = this.properties.framesAPIURL + 'merge.php?com=query&data=[{"query":"resRepoDownloads", "resTitle":"' + this.id + '", "table":"","fields":[{"fld":"sum","agg":"sum","type":"column","yaxis":1,"c":false}],"xaxis":{"name":"month","agg":"sum"},"group":" ","color":"","type":"chart","size":80,"sort":"xaxis","xStyle":{"r":-30,"s":"6","l":"-","ft":"-","wt":"-"},"title":"","subtitle":"","xaxistitle":"Repository","yaxisheaders":["Monthly downloads"],"generalxaxis":"","theme":0,"in":[],"filters":[{"name":"","values":[""],"to":"-1"}]}]&info_types=["column"]&stacking=normal&steps=false&fontFamily=Courier&spacing=[5,0,0,0]&style=[{"color":"rgba(0, 0, 0, 1)","size":"18"},{"color":"rgba(0, 0, 0, 1)","size":"18"},{"color":"000000","size":""},{"color":"000000","size":""}]&backgroundColor=rgba(255,255,255,1)&colors[]=rgba(67, 67, 72, 1)&colors[]=rgba(144, 237, 125, 1)&colors[]=rgba(247, 163, 92, 1)&colors[]=rgba(128, 133, 233, 1)&colors[]=rgba(241, 92, 128, 1)&colors[]=rgba(228, 211, 84, 1)&colors[]=rgba(43, 144, 143, 1)&colors[]=rgba(244, 91, 91, 1)&colors[]=rgba(145, 232, 225, 1)&xlinew=0&ylinew=1&legends=true&tooltips=true&persistent=false';
187
          
188
          this.scroll();
189
        });
190
      });
191
  }
192
  
193
  private getPageContents() {
194
    this.helper.getPageHelpContents(this.properties, this.communityId, this._router.url).subscribe(contents => {
195
      this.pageContents = contents;
196
    });
197
  }
198
  
199
  private getDivContents() {
200
    this.helper.getDivHelpContents(this.properties, this.communityId, this._router.url).subscribe(contents => {
201
      this.divContents = contents;
202
    });
203
  }
204
  
205
  ngOnDestroy() {
206
    if (this.sub) {
207
      this.sub.unsubscribe();
208
    }
209
    if (this.piwiksub) {
210
      this.piwiksub.unsubscribe();
211
    }
212
    if (this.infoSub) {
213
      this.infoSub.unsubscribe();
214
    }
215
  }
216
  
217
  public getTypeName(): string {
218
    if (this.type === "dataset") {
219
      return "research data";
220
    } else if (this.type === "orp" || this.type === "other") {
221
      return "other research product";
222
    } else {
223
      return this.type;
224
    }
225
  }
226
  
227
  public removeUnknown(array: string[], type: boolean = false): string[] {
228
    if (type) {
229
      return this.removeDuplicates(array).filter(value => value.toLowerCase() !== 'unknown');
230
    } else {
231
      return array.filter(value => value.toLowerCase() !== 'unknown');
232
    }
233
  }
234
  
235
  public removeDuplicates(array: string[]): string[] {
236
    let type = this.getTypeName();
237
    return array.filter(value => value.toLowerCase() !== type);
238
  }
239
  
240
  private getOpenCitations() {
241
    this._resultLaningService.getOpenCitations(this.id, this.properties).subscribe(
242
      data => {
243
        this.resultLandingInfo.openCitations = data[1];
244
      },
245
      err => {
246
        this.handleError("Error getting open citation for " + this.type + " with id: " + this.id, err);
247
      }
248
    );
249
  }
250
  
251
  private getProvenanceVocabularyAndResultLandingInfo() {
252
    this.warningMessage = '';
253
    this.errorMessage = '';
254
    this.showLoading = true;
255
    
256
    this.resultLandingInfo = null;
257
    
258
    this._resultLaningService.getProvenanceActionVocabulary(this.properties).subscribe(
259
      provenanceActionVocabulary => {
260
        this.getResultLandingInfo(provenanceActionVocabulary);
261
      }, err => {
262
        this.getResultLandingInfo(null);
263
        this.handleError("Error getting provenance action vocabulary for " + this.type + " with id: " + this.id, err);
264
      }
265
    );
266
    
267
  }
268
  
269
  private getResultLandingInfo(provenanceActionVocabulary: any) {
270
    this.infoSub = this._resultLaningService.getResultLandingInfo(this.id, this.type, provenanceActionVocabulary, this.properties).subscribe(
271
      data => {
272
        this.resultLandingInfo = data;
273
        if (this.type == "result") { // no type was specified - update URL based this.resultLandingInfo.resultType
274
          this.updateUrlWithType();
275
        }
276
        this.seoService.createLinkForCanonicalURL(this.properties.baseLink + this.linkToLandingPage + this.resultLandingInfo.record["result"]["header"]["dri:objIdentifier"]);
277
        if ((this.type == "publication") && (this.properties.environment == "beta" || this.properties.environment == "development") && (typeof document !== 'undefined')) {
278
          this.getOpenCitations();
279
        }
280
        
281
        if (this.resultLandingInfo.title) {
282
          this.updateTitle(this.resultLandingInfo.title);
283
          this.updateDescription((this.resultLandingInfo.description ? (this.resultLandingInfo.description) : ("," + this.resultLandingInfo.title)));
284
        }
285
        if (this.properties.enablePiwikTrack && (typeof document !== 'undefined')) {
286
          this.piwiksub = this._piwikService.trackView(this.properties, this.resultLandingInfo.title/*.name*/, this.piwikSiteId).subscribe();
287
        }
288
        
289
        let bioentitiesNum = 0;
290
        if (this.resultLandingInfo.bioentities != undefined) {
291
          this.resultLandingInfo.bioentities.forEach(function (value, key, map) {
292
            bioentitiesNum += value.size;
293
          });
294
        }
295
        this.bioentitiesNum = bioentitiesNum;
296
        if (this.resultLandingInfo.identifiers != undefined && this.resultLandingInfo.identifiers.has('doi')) {
297
          this.doi = this.resultLandingInfo.identifiers.get('doi')[0];
298
          this.metricsService.hasAltMetrics(this.properties.altMetricsAPIURL, this.doi).subscribe(hasAltMetrics => {
299
            this.hasAltMetrics = hasAltMetrics;
300
          }, error => {
301
            this.hasAltMetrics = false;
302
          });
303
        }
304
        this.showLoading = false;
305
        if (this.resultLandingInfo.references) {
306
          this.activeTab = "References";
307
        } else if (this.resultLandingInfo.relatedResearchResults) {
308
          this.activeTab = "Related Research Results";
309
        } else if (this.resultLandingInfo.similarResearchResults) {
310
          this.activeTab = "Similar Research Results";
311
        } else if (this.resultLandingInfo.organizations) {
312
          this.activeTab = "Related Organizations";
313
        } else if (this.resultLandingInfo.bioentities) {
314
          this.activeTab = "Bioentities";
315
        } else {
316
          this.activeTab = "Metrics";
317
          //this.metricsClicked = true;
318
        }
319
      },
320
      err => {
321
        this.handleError("Error getting " + this.type + " for id: " + this.id, err);
322
        
323
        if (err.status == 404) {
324
          this._router.navigate(['/error'], {queryParams: {"page": this._location.path(true), "page_type": this.type}});
325
        }
326
        
327
        if (this.type == "publication" || this.type == "software") {
328
          this.errorMessage = 'No ' + this.type + ' found';
329
        } else if (this.type == "dataset") {
330
          this.errorMessage += "No research data found";
331
        } else if (this.type == "orp") {
332
          this.errorMessage += "No research product found";
333
        }
334
        this.showLoading = false;
335
        this.seoService.createLinkForCanonicalURL(this.properties.baseLink + this.linkToSearchPage);
336
      }
337
    );
338
  }
339
  
340
  public metricsResults($event) {
341
    this.totalViews = $event.totalViews;
342
    this.totalDownloads = $event.totalDownloads;
343
    this.pageViews = $event.pageViews;
344
  }
345
  
346
  public get hasPrimaryInfo(): boolean {
347
    return !!this.resultLandingInfo && (!!this.resultLandingInfo.description || !!this.resultLandingInfo.identifiers || !!this.resultLandingInfo.subjects);
348
  }
349
  
350
  public get hasSecondaryInfo(): boolean {
351
    return (this.resultLandingInfo.fundedByProjects && this.resultLandingInfo.fundedByProjects.length > 0) ||
352
      (this.resultLandingInfo.contexts && this.resultLandingInfo.contexts.length > 0) ||
353
      (this.resultLandingInfo.hostedBy_collectedFrom && this.resultLandingInfo.hostedBy_collectedFrom.length > 0);
354
  }
355
  
356
  public get hasMetrics(): boolean {
357
    return !(this.totalViews && this.totalDownloads && this.pageViews) || this.totalViews > 0 || this.totalDownloads > 0 || this.pageViews > 0;
358
  }
359
  
360
  public buildCurationTooltip(): string {
361
    let tooltipContent: string = "<div class='uk-margin uk-padding-small'>";
362
    
363
    tooltipContent += "<h4>Record in preview</h4>";
364
    tooltipContent += "<p>Bibliographic record accepted by the system, but not yet processed by <br> OpenAIRE tools for information quality improvement and de-duplication</p>";
365
    
366
    tooltipContent += "</div>";
367
    return tooltipContent;
368
  }
369
  
370
  private updateDescription(description: string) {
371
    this._meta.updateTag({content: description.substring(0, 160)}, "name='description'");
372
    this._meta.updateTag({content: description.substring(0, 160)}, "property='og:description'");
373
  }
374
  
375
  private updateTitle(title: string) {
376
    var _prefix = "";
377
    // if(!this.communityId) {
378
    //   _prefix = "OpenAIRE | ";
379
    // }
380
    // var _title = _prefix + ((title.length > 50) ? title.substring(0, 50) : title);
381
    this._title.setTitle(title);
382
    this._meta.updateTag({content: title}, "property='og:title'");
383
  }
384
  
385
  private updateUrl(url: string) {
386
    this._meta.updateTag({content: url}, "property='og:url'");
387
  }
388
  
389
  public totalPages(totalResults: number): number {
390
    let totalPages: any = totalResults / this.pageSize;
391
    if (!(Number.isInteger(totalPages))) {
392
      totalPages = (parseInt(totalPages, this.pageSize) + 1);
393
    }
394
    return totalPages;
395
  }
396
  
397
  public updateReferencesPage($event) {
398
    this.referencesPage = $event.value;
399
  }
400
  
401
  public updateBioentitiesPage($event) {
402
    this.bioentitiesPage = $event.value;
403
  }
404
  
405
  public updateRelationPage($event) {
406
    this.relationPage = $event.value;
407
  }
408
  
409
  public updateOrganizationsPage($event) {
410
    this.organizationsPage = $event.value;
411
  }
412
  
413
  public updateSoftwarePage($event) {
414
    this.softwarePage = $event.value;
415
  }
416
  
417
  public updateOpenCitationsPage($event) {
418
    this.openCitationsPage = $event.value;
419
  }
420
  
421
  public accessClass(accessMode: string): string {
422
    if (accessMode.toLowerCase().indexOf('open') !== -1) {
423
      return 'open';
424
    } else if (accessMode.toLowerCase() === 'not available') {
425
      return 'unknown';
426
    } else {
427
      return 'closed';
428
    }
429
  }
430
  
431
  public keysToArray(bioentities: Map<string, string>): string[] {
432
    let keys: string[] = [];
433
    bioentities.forEach(function (value, key, map) {
434
      keys.push(key);
435
    });
436
    return keys;
437
  }
438
  
439
  public getKeys(map) {
440
    return Array.from(map.keys());
441
  }
442
  
443
  public scroll() {
444
    HelperFunctions.scroll();
445
  }
446
  
447
  private handleError(message: string, error) {
448
    if (this.type == "publication") {
449
      console.error("Publication Landing Page: " + message, error);
450
    } else if (this.type == "dataset") {
451
      console.error("Research Data Landing Page: " + message, error);
452
    } else if (this.type == "software") {
453
      console.error("Software Landing Page: " + message, error);
454
    } else if (this.type == "orp") {
455
      console.error("Other Research Product Landing Page: " + message, error);
456
    } else {
457
      console.error("Landing Page: " + message, error);
458
    }
459
  }
460
  
461
  isRouteAvailable(routeToCheck: string) {
462
    for (let i = 0; i < this.router.config.length; i++) {
463
      let routePath: string = this.router.config[i].path;
464
      if (routePath == routeToCheck) {
465
        return true;
466
      }
467
    }
468
    return false;
469
  }
470
  
471
  openDeletedByInference() {
472
    this.deleteByInferenceOpened = true;
473
    this.alertModalDeletedByInference.cancelButton = false;
474
    this.alertModalDeletedByInference.okButton = false;
475
    this.alertModalDeletedByInference.alertTitle = "Other versions of";
476
    this.alertModalDeletedByInference.open();
477
  }
478

    
479
  openRelationResults(title: string, relationResults: RelationResult[], relation: string = 'trust') {
480
    this.relationResults = relationResults;
481
    this.relation = relation;
482
    this.relationModal.cancelButton = false;
483
    this.relationModal.okButton = false;
484
    this.relationModal.alertTitle = title;
485
    this.relationPage = 1;
486
    this.relationModal.open();
487
  }
488
  
489
  openOrganizations() {
490
    this.relation = 'trust';
491
    this.organizationModal.cancelButton = false;
492
    this.organizationModal.okButton = false;
493
    this.organizationModal.alertTitle = 'Related organizations of';
494
    this.organizationsPage = 1;
495
    this.organizationModal.open();
496
  }
497
  
498
  public getResultPreview(result: RelationResult): ResultPreview {
499
    return ResultPreview.relationResultConvert(result, this.relation);
500
  }
501
  
502
  public getResultPreviewFromOrg(result: Organization): ResultPreview {
503
    return ResultPreview.organizationConvert(result, this.relation);
504
  }
505
  
506
  updateUrlWithType() {
507
    this.type = this.resultLandingInfo.resultType;
508
    if (this.type == "publication") {
509
      this._location.go("test");
510
      this.linkToLandingPage = this.properties.searchLinkToPublication;
511
      this.linkToSearchPage = this.properties.searchLinkToPublications;
512
    } else if (this.type == "dataset") {
513
      this.linkToLandingPage = this.properties.searchLinkToDataset;
514
      this.linkToSearchPage = this.properties.searchLinkToDatasets;
515
    } else if (this.type == "software") {
516
      this.linkToLandingPage = this.properties.searchLinkToSoftwareLanding;
517
      this.linkToSearchPage = this.properties.searchLinkToSoftware;
518
    } else if (this.type == "other") {
519
      this.type = "orp";
520
      this.linkToLandingPage = this.properties.searchLinkToOrp;
521
      this.linkToSearchPage = this.properties.searchLinkToOrps;
522
    }
523
    this._location.go(this.linkToLandingPage + this.id);
524
  }
525
  
526
  public getReferenceUrl(id: Id): string {
527
    if (id.type === "doi") {
528
      return this.properties.doiURL + id.value;
529
    } else if (id.type === "pmc") {
530
      return this.properties.pmcURL + id.value;
531
    } else if (id.type === "pmid") {
532
      return this.properties.pmidURL + id.value;
533
    } else if (id.type === "handle") {
534
      return this.properties.handleURL + id.value;
535
    } else {
536
      return null;
537
    }
538
  }
539
  
540
  public getReferenceIdName(id: Id): string {
541
    if (id.type === "doi") {
542
      return 'DOI'
543
    } else if (id.type === "pmc") {
544
      return 'Europe PMC'
545
    } else if (id.type === "pmid") {
546
      return 'PubMed';
547
    } else if (id.type === "handle") {
548
      return 'Handle.NET';
549
    } else {
550
      return null;
551
    }
552
  }
553
  
554
  public openLinkModal() {
555
    this.linkModal.cancelButton = false;
556
    this.linkModal.okButton = false;
557
    this.linkModal.alertTitle = "Link this " + this.getTypeName() + " to";
558
    this.linkModal.open();
559
  }
560
  
561
  public openCiteModal() {
562
    this.citeModal.cancelButton = false;
563
    this.citeModal.okButton = false;
564
    this.citeModal.alertTitle = "Cite this " + this.getTypeName() + " to";
565
    this.citeModal.open();
566
  }
567
}
(2-2/4)