Project

General

Profile

1
import {Component, Input, ViewChild} from '@angular/core';
2
import {ActivatedRoute, Router} from '@angular/router';
3
import {Location} from '@angular/common';
4
import {ErrorCodes} from "../../utils/properties/errorCodes";
5
import {ErrorMessagesComponent} from "../../utils/errorMessages.component";
6
import {SearchUtilsClass} from "../../searchPages/searchUtils/searchUtils.class";
7
import {RouterHelper} from "../../utils/routerHelper.class";
8
import {EnvProperties} from "../../utils/properties/env-properties";
9
import {properties} from "../../../../environments/environment";
10
import {OrcidService} from "../orcid.service";
11
import {Identifier, StringUtils} from "../../utils/string-utils.class";
12
import {SearchResearchResultsService} from "../../services/searchResearchResults.service";
13
import {SearchResult} from "../../utils/entities/searchResult";
14
import {ResultPreview} from "../../utils/result-preview/result-preview";
15
import {Meta, Title} from "@angular/platform-browser";
16
import {UserManagementService} from "../../services/user-management.service";
17
import {PiwikService} from "../../utils/piwik/piwik.service";
18

    
19
declare var UIkit: any;
20

    
21
@Component({
22
  selector: 'my-orcid-links',
23
  template: `
24
    
25
    <div class="uk-container uk-container-large">
26
      <div class="uk-margin-medium-bottom">
27
        <div class="uk-margin-top">
28
          <div class="uk-grid uk-flex uk-flex-middle">
29
            <div class="uk-article-title custom-article-title uk-width-auto">
30
              My ORCID links
31
            </div>
32
            <span *ngIf="authorNameParam" class="uk-width-1-1 uk-width-expand@m">
33
              <a class="uk-button-text uk-align-right@m" [queryParams]="authorNameParam" 
34
                  [routerLink]="properties.searchLinkToAdvancedResults" routerLinkActive="router-link-active">
35
                Discover research results related to you
36
              </a>
37
            </span>
38
          </div>
39
          
40
          <div class="uk-margin-top">
41
            <span>
42
              Did you link a result with your ORCID <img src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="">
43
              but the <span class="orcid-color">green icon</span> is missing?
44
              <br>
45
              No worries! It will appear, as soon as we synchronize again with ORCID data.
46
                  <a href="https://www.openaire.eu/openaire-explore-integration-with-the-orcid-search-and-link-wizard"
47
                     target="_blank" class="uk-display-inline-block">
48
                Read more  <span class="custom-external custom-icon space"></span>
49
              </a>
50
            </span>
51
          </div>
52
          
53
          <div *ngIf="showErrorMessage" class="uk-animation-fade uk-alert uk-alert-warning uk-margin-large-top" role="alert">
54
            An Error Occurred
55
          </div>
56
          <div *ngIf="!showLoading && !orcidQuery && !requestGrant && !showErrorMessage" 
57
                class="uk-animation-fade uk-alert uk-alert-primary uk-margin-large-top" role="alert">
58
            No ORCID links found
59
          </div>
60
          <div *ngIf="requestGrant" class="uk-margin-large-top">
61
            <div class="uk-text-center uk-padding-small">
62
              <div>
63
                This is a private page, only for users that have connected their ORCID iD with OpenAIRE.
64
                Please grant OpenAIRE to access and update your ORCID works.
65
              </div>
66
  
67
              <div class="uk-margin-medium-top uk-align-center">
68
                <button (click)="openGrantWindow()" type="submit"
69
                        class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left uk-button-primary">
70
                  <span>Grant OpenAIRE</span>
71
                </button>
72
              </div>
73
            </div>
74
          </div>
75
        </div>
76
  
77
        <div *ngIf="orcidQuery" class="tm-middle" id="tm-main">
78
          <div uk-grid="" class="uk-grid uk-grid-stack">
79
            <div class="tm-main uk-width-1-1@s uk-width-1-1@m uk-width-1-1@l uk-row-first uk-first-column">
80
              <div class="uk-container uk-container-large">
81
                <my-orcid-result [previewResults]="currentResults" 
82
                                 [status]="searchUtils.status" 
83
                                 [type]="resultType" 
84
                                 [properties]=properties
85
                                 [currentPage]="currentPage" 
86
                                 [totalResults]="totalOrcidResults" 
87
                                 [resultsPerPage]="resultsPerPage"
88
                                 (pageChange)="pageChanged($event)">
89
                </my-orcid-result>
90
              </div>
91
            </div>
92
          </div>
93
        </div>
94
      </div>
95
    </div>
96
    `,
97
  styles: ['.orcid-color { color: #a6ce39; }']
98
})
99
export class MyOrcidLinksComponent {
100
  public resultType: string = "result";
101

    
102
  private errorCodes: ErrorCodes;
103
  private errorMessages: ErrorMessagesComponent;
104
  @Input() piwikSiteId = null;
105
  public results =[];
106
  public currentResults = [];
107
  public totalResults:number  = 0 ;
108
  public baseUrl:string;
109
  public searchUtils:SearchUtilsClass = new SearchUtilsClass();
110
  public subscriptions: any[] = [];
111
  public _location:Location;
112

    
113
  public disableForms: boolean = false;
114
  public loadPaging: boolean = true;
115
  public oldTotalResults: number = 0;
116
  pagingLimit = 0;
117

    
118
  properties:EnvProperties;
119

    
120
  @Input() public communityId: string = null;
121

    
122
  public routerHelper:RouterHelper = new RouterHelper();
123
  parameters = {};
124
  keyword  = "";
125

    
126
  identifiers: string[] = [];
127
  works: any[] = [];
128

    
129
  orcidQuery: string = "";
130
  typeQuery: string = "";
131

    
132
  public showLoading: boolean = true;
133

    
134
  currentPage: number = 1;
135
  totalOrcidResults: number;
136
  resultsPerPage: number = 5;
137

    
138
  public requestGrant: boolean = false;
139
  public window: any;
140
  private tokenUrl: string;
141
  private clientId: string = "APP-A5M3KTX6NCN67L91";
142

    
143
  public authorNameParam: any = null;
144

    
145
  public showErrorMessage: boolean = false;
146

    
147
  constructor (private route: ActivatedRoute, private router: Router,
148
               private _piwikService:PiwikService,
149
               private _orcidService: OrcidService,
150
               private _searchResearchResultsService: SearchResearchResultsService,
151
               private userManagementService: UserManagementService,
152
               private _meta: Meta, private _title: Title
153
  ) {
154
    this.errorCodes = new ErrorCodes();
155
    this.errorMessages = new ErrorMessagesComponent();
156
    this.searchUtils.status = this.errorCodes.LOADING;
157
    this.searchUtils.page =1;
158

    
159
    if(typeof document !== 'undefined') {
160
      this.tokenUrl = properties.orcidTokenURL
161
        + "client_id="+properties.orcidClientId
162
        // + "&response_type=code&scope=/activities/update"
163
        // + "&response_type=code&scope=/authenticate /activities/update /person/update /read-limited"
164
        + "&response_type=code&scope=/activities/update /read-limited"
165
        + "&redirect_uri="+location.origin+"/orcid?source=openaire";
166
    }
167
  }
168

    
169
  public ngOnInit() {
170
    this.properties = properties;
171
    this.baseUrl = this.properties.myOrcidLinksPage;
172
    this.pagingLimit = this.properties.pagingLimit;
173
    var description = "Openaire, ORCID linking, publication, research data, software, other research product";
174
    this.updateTitle("My ORCID Links");
175
    this.updateDescription(description);
176
    this.updateUrl( properties.domain + properties.baseLink + this.route.url);
177

    
178
    if(this.properties.enablePiwikTrack && (typeof document !== 'undefined')){
179
      this.subscriptions.push(this._piwikService.trackView(this.properties, "My ORCID links", this.piwikSiteId).subscribe());
180
    }
181

    
182
    this.typeQuery = "&type=results";
183
    this.getLocalWorks();
184
    this.getPersonalDetails();
185
  }
186

    
187
  public ngOnDestroy() {
188
    for(let sub of this.subscriptions){
189
      sub.unsubscribe();
190
    }
191
  }
192

    
193
  private getPersonalDetails() {
194
    //get author name
195
    this.subscriptions.push(this._orcidService.getPersonalDetails().subscribe(
196
      details => {
197
        let author: string = "";
198

    
199
        if(details && details['name']) {
200
          let name: string = details['name'];
201
          if(name['given-names'] && name['given-names']['value']) {
202
            author = name['given-names']['value'];
203
          }
204
          if(name['family-name'] && name['family-name']['value']) {
205
            author += (author ? " " : "") + name['family-name']['value'];
206
          }
207
          this.authorNameParam = this.routerHelper.createQueryParams(['f0', 'fv0'], ['resultauthor', author]);
208
        }
209
      },
210
      error => {
211
        console.error("Error getting personal details", error);
212
        this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
213
          if (user) {
214
            this.authorNameParam = this.routerHelper.createQueryParams(['f0', 'fv0'], ['resultauthor', user.fullname]);
215
          }
216
        }));
217
      }
218
    ));
219
  }
220

    
221
  openGrantWindow() {
222
    this.window = window.open(this.tokenUrl, '_blank',
223
      'location=yes,height=700,width=540,left=500,top=100,scrollbars=yes,status=yes');
224

    
225
    let self = this;
226
    window.onmessage = function (ev) {
227
      if (ev.isTrusted && ev.origin !== location.origin && ev.data !== 'success')
228
        return;
229
      self.requestGrant = false;
230
      UIkit.notification({
231
        message: 'Thank you for <strong>connecting your ORCID iD</strong> with OpenAIRE!',
232
        status: 'success',
233
        timeout: 6000,
234
        pos: 'bottom-right'
235
      });
236
      self.getLocalWorks();
237
    };
238
  }
239

    
240
  getLocalWorks() {
241
    this.showErrorMessage = false;
242

    
243
    this.showLoading = true;
244
    this.subscriptions.push(this._orcidService.getLocalWorks().subscribe(
245
      (response: any[]) => {
246

    
247
        this.works = response;//['results'];
248
        this.totalOrcidResults = this.works.length;//response['total'];
249

    
250
        this.prepareOrcidQuery();
251
      },
252
      error => {
253
        this.handleError(error, "Could not get locally stored user's ORCID works");
254
        this.showLoading = false;
255
      }
256
    ));
257
  }
258

    
259
  public prepareOrcidQuery() {
260

    
261
    if(this.results.length >= this.currentPage) {
262
      this.currentResults = this.results[this.currentPage-1];
263
      return;
264
    }
265

    
266
    this.showLoading = true;
267

    
268
    this.orcidQuery = "";
269

    
270
    let from: number = (this.currentPage-1)*this.resultsPerPage;
271
    if(from >= this.works.length) {
272
      this.searchUtils.status = this.errorCodes.OUT_OF_BOUND;
273
    }
274
    let to: number = this.currentPage*this.resultsPerPage;
275

    
276
    if(to > this.works.length) {
277
      to = this.works.length;
278
    }
279

    
280
    let works = this.works.slice(from, to);
281

    
282
    for(let work of works) {
283
      for(let pid of work['pids']) {
284
        let identifier: Identifier = Identifier.getIdentifierFromString(pid, false);
285
        this.orcidQuery += (this.orcidQuery ? " or " : "") + ('(pidclassid exact "'+identifier.class+'" and pid="'+StringUtils.URIEncode(identifier.id)+'")');
286
      }
287
    }
288
    this.showLoading = false;
289
    this._getResults(works);
290
  }
291

    
292
  public _getResults(works: any) {
293
    this.searchUtils.status = this.errorCodes.LOADING;
294
    this.disableForms = true;
295
    this.currentResults = [];
296
    this.searchUtils.totalResults = 0;
297

    
298
    // let params: string = this.orcidQuery + this.typeQuery;
299
    //this.subs.push(this._searchResearchResultsService.advancedSearchResults(this.resultType, parameters, page, size, sortBy, this.properties, (refine) ? this.searchPage.getRefineFieldsQuery() : null, this.searchPage.getFields(), refineFieldsFilterQuery)
300
    this.subscriptions.push(this._searchResearchResultsService.searchForMyOrcidLinks(this.resultType, this.orcidQuery, this.typeQuery, 1, 50)
301
    //this.subs.push(this._searchResearchResultsService.advancedSearchResults(this.resultType, parameters, page, size, sortBy, this.properties, null, this.searchPage.getFields(), refineFieldsFilterQuery)
302
      .subscribe(
303
        data => {
304
          let totalResults = data[0];
305
          let results = data[1];
306

    
307
          this.resultsReturned(results, totalResults, works);
308
        },
309
        err => {
310
          console.error("Error getting " + this.getEntityName(this.resultType, true, true));
311
          this.showLoading = false;
312
          this.searchUtils.status = this.errorMessages.getErrorCode(err.status);
313
          this.disableForms = false;
314
        }
315
      )
316
    );
317
  }
318

    
319
  public resultsReturned(results: any, totalResults, works: any[]) {
320
    this.searchUtils.totalResults = totalResults;
321

    
322
    let resultsFound: Map<string[], number> = new Map<string[], number>();
323

    
324
    for(let work of works) {
325
      results.forEach(result => {
326
        let identifierValues: string[] = [].concat(...Array.from(result.identifiers.values()));
327
        if(work['pids'].some(pid => identifierValues.includes(pid))) {
328

    
329
          let index: number = resultsFound.get(identifierValues);
330
          if(!index) {
331
            this.currentResults.push(this.getResultPreview(result));
332
            index = this.currentResults.length - 1;
333

    
334
            this.currentResults[index].orcidPutCodes = [];
335
            this.currentResults[index].orcidCreationDates = [];
336
            this.currentResults[index].orcidUpdateDates = [];
337
          }
338

    
339
          if (work['putCode']) {
340
            this.currentResults[index].orcidPutCodes.push(work['putCode']);
341
          }
342
          if (work['creationDate']) {
343
            this.currentResults[index].orcidCreationDates.push(work['creationDate']);
344
          }
345
          if (work['updateDate']) {
346
            this.currentResults[index].orcidUpdateDates.push(work['updateDate']);
347
          }
348
        }
349
      })
350
    }
351

    
352
    this.results[this.currentPage-1] = this.currentResults;
353

    
354
    this.searchUtils.status = this.errorCodes.DONE;
355
    if (this.searchUtils.totalResults == 0) {
356
      this.searchUtils.status = this.errorCodes.NONE;
357
    }
358

    
359
    this.disableForms = false;
360
  }
361

    
362
  public resultsReturned2(results: any, totalResults, works: any[]) {
363
    this.searchUtils.totalResults = totalResults;
364

    
365
    for(let result of results) {
366
      let identifierValues: string[] = [].concat(...Array.from(result.identifiers.values()));
367

    
368
      this.currentResults.push(this.getResultPreview(result));
369

    
370
      let filteredWorks = works.filter(work => {
371
        return work['pids'].some(pid => identifierValues.includes(pid));
372
      })
373

    
374
      this.currentResults[this.currentResults.length - 1].orcidPutCodes = [];
375
      this.currentResults[this.currentResults.length - 1].orcidCreationDates = [];
376
      this.currentResults[this.currentResults.length - 1].orcidUpdateDates = [];
377

    
378
      filteredWorks.forEach(work => {
379
        if(work['putCode']) {
380
          this.currentResults[this.currentResults.length - 1].orcidPutCodes.push(work['putCode']);
381
        }
382
        if(work['creationDate']) {
383
          this.currentResults[this.currentResults.length - 1].orcidCreationDates.push(work['creationDate']);
384
        }
385
        if(work['updateDate']) {
386
          this.currentResults[this.currentResults.length - 1].orcidUpdateDates.push(work['updateDate']);
387
        }
388
      });
389
    }
390

    
391
    this.results[this.currentPage-1] = this.currentResults;
392
    this.searchUtils.status = this.errorCodes.DONE;
393
    if (this.searchUtils.totalResults == 0) {
394
      this.searchUtils.status = this.errorCodes.NONE;
395
    }
396

    
397
    this.disableForms = false;
398
  }
399

    
400
  public getResultPreview(result: SearchResult): ResultPreview {
401
    return ResultPreview.searchResultConvert(result, (result.entityType)?result.entityType:this.resultType);
402
  }
403

    
404
  public getEntityName(entityType: string, plural: boolean, full: boolean): string {
405
    if (entityType == "publication") {
406
      return "publication" + (plural ? "s" : "");
407
    } else if (entityType == "dataset") {
408
      return (full ? "research data" : ("dataset" + (plural ? "s" : "")));
409
    } else if (entityType == "software") {
410
      return "software";
411
    } else if (entityType == "other") {
412
      return (full ? ("other research product" + (plural ? "s" : "")) : "other");
413
    } else if (entityType == "result") {
414
      return (full ? ("research outcome" + (plural ? "s" : "")) : "result");
415
    }
416
  }
417

    
418
  public pageChanged($event) {
419
    this.currentPage = $event.value;
420
    this.prepareOrcidQuery();
421
  }
422

    
423
  handleError(error, errorMsg: string) {
424
    if(error && (error.status == "401" || error.status == "403")) {
425
      this.requestGrant = true;
426
    } else {
427
      this.showErrorMessage = true;
428
    }
429
    this.showLoading = false;
430
  }
431

    
432
  private updateTitle(title: string) {
433
    this._title.setTitle(title);
434
    this._meta.updateTag({content: title}, "property='og:title'");
435
  }
436

    
437
  private updateDescription(description: string) {
438
    this._meta.updateTag({content: description}, "name='description'");
439
    this._meta.updateTag({content: description}, "property='og:description'");
440
  }
441

    
442
  private updateUrl(url: string) {
443
    this._meta.updateTag({content: url}, "property='og:url'");
444
  }
445
}
(1-1/5)