Project

General

Profile

1
import {Component, Input, Output, EventEmitter, ViewChild} from '@angular/core';
2
import {Router, ActivatedRoute} from '@angular/router';
3
import {ClaimsService} from '../../claim-utils/service/claims.service';
4
import {ModalLoading} from '../../../utils/modal/loading.component';
5
import {AlertModal} from '../../../utils/modal/alert';
6
import {Md5} from 'ts-md5/dist/md5';
7
import {LoginErrorCodes} from '../../../login/utils/guardHelper.class';
8
import {EnvProperties} from '../../../utils/properties/env-properties';
9
import {
10
  ClaimEntity,
11
  ClaimRecord2Insert,
12
  ClaimsErrorMessage,
13
  DirectIndexRecord,
14
  Message
15
} from "../../claim-utils/claimHelper.class";
16
import {UserManagementService} from "../../../services/user-management.service";
17
import {Subscriber} from "rxjs";
18

    
19
@Component({
20
  selector: 'claim-insert',
21
  template: `
22

    
23

    
24
    <div class="uk-width-1-1">
25
      <modal-loading [message]="'Please wait...'"></modal-loading>
26
      <modal-alert (alertOutput)="confirmClose()">
27
        <h4 class="modal-title uk-text-bold " id="myModalLabel">Confirmation notice</h4>
28
        <p>All the links you provided will be published in the OpenAIRE platform. <br>
29
          Please make sure that the information is valid.<br>
30
          <span class="uk-text-bold">In some cases, links take some time to be published.</span><br>
31
          For more information please check the linking status in My-Links page.
32
        </p>
33
        <p>
34
          Do you confirm the information you provide is valid?
35
        </p>
36
      </modal-alert>
37
      <div class="uk-clearfix">
38

    
39
        <div>
40
          <div *ngIf="!claiming  " (click)="insert()" style="width: 350px;"
41
               [class]="getButtonClass()">CONFIRM LINKING
42
            <span [class]="(defaultColors?'':' uk-margin-small-top ')+'uk-icon uk-float-right uk-text-bold uk-margin-small-right'">
43
                          <svg width="30" height="30" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
44
                               icon="chevron-right" ratio="1.5"><polyline fill="none" stroke="#000" stroke-width="1.03"
45
                                                                          points="7 4 13 10 7 16"></polyline></svg>
46
                          </span>
47
          </div>
48

    
49
        </div>
50
      </div>
51
    </div>
52
  `
53
})
54
export class ClaimInsertComponent {
55
  constructor(private claimService: ClaimsService, private _router: Router, private route: ActivatedRoute,
56
              private userManagementService: UserManagementService) {
57
  }
58
  subscriptions = [];
59
  ngOnDestroy() {
60
    this.subscriptions.forEach(subscription => {
61
      if (subscription instanceof Subscriber) {
62
        subscription.unsubscribe();
63
      }
64
    });
65
  }
66
  ngOnInit() {
67
    this.subscriptions.push(this.route.queryParams.subscribe(params => {
68
      this.params = params;
69
    }));
70
  }
71

    
72
  params = {};
73

    
74
  @Input() public results: ClaimEntity[];
75
  @Input() inlineEntity: ClaimEntity = null;
76
  @Input() sources: ClaimEntity[] = null;
77
  @Input() public properties: EnvProperties;
78
  @Input() localStoragePrefix: string;
79
  @ViewChild(ModalLoading) loading: ModalLoading;
80
  @ViewChild(AlertModal) alert;
81
  @Input() errors: ClaimsErrorMessage[];
82
  @Output() insertFinished = new EventEmitter();
83
  @Input() defaultColors:boolean;
84
  @Input() communityId:string= null;
85
  public claiming = false;
86

    
87
  public claims: number = 0;
88

    
89
  private servicesRespond: number = 0;
90
  private insertedClaims = [];
91
  private errorInClaims: ClaimRecord2Insert[] = [];
92
  private insertedRecords = [];
93
  private errorInRecords = [];
94

    
95
  public insert() {
96
    this.confirmOpen();
97
  }
98
  saveAndNavigate(){
99
    localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
100
    if (this.sources != null) {
101
      localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
102
    }
103
    this._router.navigate(['/user-info'], {
104
      queryParams: {
105
        "errorCode": LoginErrorCodes.NOT_VALID,
106
        "redirectUrl": this._router.url
107
      }
108
    });
109
  }
110
  private insertActions() {
111
    this.servicesRespond = 0;
112
    this.insertedClaims = [];
113
    this.errorInClaims = [];
114
    this.insertedRecords = [];
115
    this.errorInRecords = [];
116
    this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
117
      if (!user) {
118
       this.saveAndNavigate();
119
      } else {
120
        this.claiming = true;
121
        this.loading.open();
122
        let claims: ClaimRecord2Insert[] = [];
123
        let directclaims: DirectIndexRecord[] = [];
124
        let dashboard = this.properties.environment+"_"+this.properties.dashboard + (this.communityId?("_"+this.communityId):'');
125
        for (let j = 0; j < this.sources.length; j++) {  // if an external result -> direct insert in the index
126
          const result: ClaimEntity = this.sources[j];
127
          if (result.result && ["crossref", "datacite", "orcid"].indexOf(result.result.source) != -1) {
128
            directclaims.push({
129
              "id": result.id,
130
              "record": ClaimInsertComponent.createDirectClaim(result, this.results)
131
            });
132
          }
133
        }
134
        for (let i = 0; i < this.results.length; i++) {
135
          const entity: ClaimEntity = this.results[i]; // this is a research result, a project or a context
136

    
137
          if (entity.result && ["crossref", "datacite", "orcid"].indexOf(entity.result.source) != -1) { // if an external result -> direct insert in the index
138
            if (this.sources.length > 0) {
139
              directclaims.push({
140
                "id": entity.id,
141
                "record": ClaimInsertComponent.createDirectClaim(entity, this.sources)
142
              });
143
            } else if (this.inlineEntity) {
144
              directclaims.push({
145
                "id": entity.id,
146
                "record": ClaimInsertComponent.createDirectClaim(entity, [this.inlineEntity])
147
              });
148
            }
149

    
150
          }
151

    
152
          for (let j = 0; j < this.sources.length; j++) {
153
            const result: ClaimEntity = this.sources[j]; // this is a research result
154
            if (entity.result) {
155
              claims.push(ClaimInsertComponent.createResultClaim(result, entity, user.email, dashboard));
156
            } else if (entity.context) {
157
              claims.push(ClaimInsertComponent.createContextClaim(result, entity, user.email, dashboard));
158
            } else if (entity.project) {
159
              claims.push(ClaimInsertComponent.createProjectClaim(result, entity, user.email, dashboard));
160
            }
161

    
162

    
163
          }
164
          if (this.inlineEntity) {
165
            if (this.inlineEntity.result) {
166
              if (entity.result) {
167

    
168
                claims.push(ClaimInsertComponent.createResultClaim(this.inlineEntity, entity, user.email, dashboard));
169
              } else if (entity.context) {
170
                claims.push(ClaimInsertComponent.createContextClaim(this.inlineEntity, entity, user.email, dashboard));
171
              } else if (entity.project) {
172
                claims.push(ClaimInsertComponent.createProjectClaim(this.inlineEntity, entity, user.email, dashboard));
173
              }
174
            } else if (this.inlineEntity.project) {
175
              if (entity.result) {
176
                claims.push(ClaimInsertComponent.createProjectClaim(entity, this.inlineEntity, user.email, dashboard));
177
              }
178
            }
179
          }
180

    
181

    
182
        }
183

    
184
        //first call direct index service - when call is done (success or error) call isertBulkClaims method to insert claims in DB
185
        // console.log("directclaims");
186
        // console.log(directclaims);
187
        if (directclaims.length > 0 && this.properties.environment != "development"){
188
          this.subscriptions.push(this.claimService.insertDirectRecords(directclaims, this.properties.claimsAPIURL).subscribe(
189
            data => {
190
              this.insertedRecords = data.insertedIds;
191

    
192
              this.errorInRecords = data.errorInClaims;
193
              this.isertBulkClaims(claims);
194
            },
195
            err => {
196
              err = err && err.error?err.error:err;
197
              if (err.code && err.code == 403) {
198
                this.saveAndNavigate();
199
              }
200
              if (err.insertedIds && err.insertedIds.length > 0) {
201
                this.insertedRecords = err.insertedIds;
202
              }
203
              if (err.errorInClaims && err.errorInClaims.length > 0) {
204
                this.errorInRecords = err.errorInClaims;
205
              }
206
              this.isertBulkClaims(claims);
207

    
208
              ClaimInsertComponent.handleError("Error inserting direct records: " + JSON.stringify(directclaims), err);
209
            }
210
          ));
211
        } else {
212
          this.isertBulkClaims(claims);
213
        }
214
      }
215
    }));
216
  }
217

    
218
  private isertBulkClaims(claims: ClaimRecord2Insert[]) {
219
    console.log("claims");
220
    console.log(claims);
221
    this.errors.splice(0, this.errors.length);
222
    this.subscriptions.push(this.claimService.insertBulkClaims(claims, this.properties.claimsAPIURL).subscribe(
223
      data => {
224
        this.insertedClaims = data.insertedIds;
225
        this.errorInClaims = data.errorInClaims;
226
        //TODO remove - testing having errors in claims
227
        // this.insertedClaims.pop();
228
        // this.insertedClaims.pop();
229
        // this.errorInClaims.push(claims[1]);
230
        // this.insertedClaims.splice(0,this.insertedClaims.length);
231
        //  this.errorInClaims = claims;
232
        //remove till here
233

    
234
        if (claims.length != this.insertedClaims.length) {
235
          let error: ClaimsErrorMessage = new ClaimsErrorMessage();
236
          error.type = "claimServiceFail2Insert";
237
          error.inserted = this.insertedClaims.length;
238
          error.failed = this.errorInClaims.length;
239
          this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
240
          this.errors.push(error);
241
        }
242
        this.afterclaimsInsertion();
243
      },
244
      err => {
245
        err = err && err.error?err.error:err;
246
        if (err.code && err.code == 403) {
247
          this.saveAndNavigate();
248
        }
249
        let error: ClaimsErrorMessage = new ClaimsErrorMessage();
250
        error.type = "claimServiceFail";
251
        if (err.insertedIds && err.insertedIds.length > 0) {
252
          this.insertedClaims = err.insertedIds;
253
          error.inserted = err.insertedIds.length;
254
        }
255
        if (err.errorInClaims && err.errorInClaims.length > 0) {
256
          this.errorInClaims = err.errorInClaims;
257
          error.failed = err.errorInClaims.length;
258
        } else {
259
          error.failed = claims.length;
260
        }
261

    
262
        if (this.results != null) {
263
          localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
264
        }
265
        if (this.sources != null) {
266
          localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
267
        }
268
        console.log(error);
269
        this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
270
        this.errors.push(error);
271
        this.afterclaimsInsertion();
272

    
273
        ClaimInsertComponent.handleError("Error inserting bulk claims: " + JSON.stringify(claims), err);
274
      }
275
    ));
276
  }
277

    
278
  createErrorMessagesPerEntity(applyToAll: boolean) {
279
    let errorsInIds: string[] = [];
280
    let savedIds: string[] = [];
281
    if (!applyToAll) {
282
      for (let claim of this.errorInClaims) {
283
        errorsInIds.push(claim.sourceId);
284
        errorsInIds.push(claim.targetId);
285
      }
286
    }
287
    for (let i = 0; i < this.sources.length; i++) {
288
      let entity: ClaimEntity = this.sources[i];
289
      if (errorsInIds.indexOf(entity.id) != -1 || applyToAll) {
290
        let error: Message = new Message();
291
        error.type = "fail2Insert";
292
        entity.errorMessages.push(error);
293
      } else {
294
        savedIds.push(entity.id);
295
      }
296
    }
297

    
298
    for (let entity of this.results) {
299
      if (errorsInIds.indexOf(entity.id) != -1 || applyToAll) {
300
        let error: Message = new Message();
301
        error.type = "fail2Insert";
302
        entity.errorMessages.push(error);
303
      } else {
304
        savedIds.push(entity.id);
305
      }
306
    }
307
    if (this.inlineEntity && (errorsInIds.indexOf(this.inlineEntity.id) != -1 || applyToAll)) {
308
      let error: Message = new Message();
309
      error.type = "fail2Insert";
310
      this.inlineEntity.errorMessages.push(error);
311
    }
312
    //remove entities that have been saved
313
    for (let id of savedIds) {
314

    
315
      //remove sources
316
      let sourceIndex = -1;
317
      for (let i = 0; i < this.sources.length; i++) {
318
        if (this.sources[i].id == id) {
319
          sourceIndex = i;
320
          break;
321
        }
322
      }
323
      if (sourceIndex != -1) {
324
        this.sources.splice(sourceIndex, 1);
325
      } else {
326
        //remove results
327
        let resutsIndex = -1;
328
        for (let i = 0; i < this.results.length; i++) {
329
          if (this.results[i].id == id) {
330
            resutsIndex = i;
331
            break;
332
          }
333
        }
334
        if (resutsIndex != -1) {
335
          this.results.splice(resutsIndex, 1);
336
        }
337

    
338

    
339
      }
340
    }
341
    this.insertFinished.emit();
342
  }
343

    
344
  private afterclaimsInsertion() {
345

    
346
    this.loading.close();
347
    this.claiming = false;
348

    
349
    if (this.errorInClaims.length == 0 && this.insertedClaims.length > 0) {
350
      localStorage.removeItem(this.localStoragePrefix + "sources");
351
      localStorage.removeItem(this.localStoragePrefix + "results");
352
      this._router.navigate(['/myclaims'], {queryParams: this.params});
353
    }
354
  }
355

    
356

    
357
  private static createContextClaim(resultEntity: ClaimEntity, contextEntity: ClaimEntity, user: any, dashboard:string): ClaimRecord2Insert {
358
    return {
359
      claimedBy: user,
360
      sourceId: contextEntity.context.concept.id,
361
      sourceType: "context",
362
      sourceCollectedFrom: "openaire",
363
      sourceAccessRights: "OPEN",
364
      sourceEmbargoEndDate: "",
365
      targetId: resultEntity.id,
366
      targetType: resultEntity.type,
367
      targetCollectedFrom: resultEntity.result.source,
368
      targetAccessRights: resultEntity.result.accessRights,
369
      targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
370
      claimedInDashboard : dashboard
371
    };
372
  }
373

    
374
  private static createProjectClaim(resultEntity: ClaimEntity, projectEntity: ClaimEntity, user: any, dashboard:string): ClaimRecord2Insert {
375
    return {
376
      claimedBy: user,
377
      sourceId: projectEntity.id,
378
      sourceType: "project",
379
      sourceCollectedFrom: "openaire",
380
      sourceAccessRights: "OPEN",
381
      sourceEmbargoEndDate: "",
382
      targetId: resultEntity.id,
383
      targetType: resultEntity.type,
384
      targetCollectedFrom: resultEntity.result.source,
385
      targetAccessRights: resultEntity.result.accessRights,
386
      targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
387
      claimedInDashboard : dashboard
388
    };
389
  }
390

    
391
  private static createResultClaim(inlineResult: ClaimEntity, resultEntity: ClaimEntity, user: string, dashboard:string): ClaimRecord2Insert {
392

    
393
    return {
394
      claimedBy: user,
395
      sourceId: resultEntity.id,
396
      sourceType: resultEntity.type,
397
      sourceCollectedFrom: resultEntity.result.source,
398
      sourceAccessRights: resultEntity.result.accessRights,
399
      sourceEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
400
      targetId: inlineResult.id,
401
      targetType: inlineResult.type,
402
      targetCollectedFrom: inlineResult.result.source,
403
      targetAccessRights: inlineResult.result.accessRights,
404
      targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(inlineResult),
405
      claimedInDashboard : dashboard
406
    };
407
  }
408

    
409
  static getEmbargoEndDate(resultEntity: ClaimEntity): string {
410
    if (resultEntity.result && resultEntity.result.accessRights == "EMBARGO" && resultEntity.result.embargoEndDate != null) {
411
      return resultEntity.result.embargoEndDate;
412
    }
413
    return ""
414
  }
415

    
416
  static createDirectClaim(resultEntity: ClaimEntity, results: ClaimEntity[]) {
417
    let entity = {};
418
    const md5_id = Md5.hashStr(resultEntity.id);
419
    entity["originalId"] = "userclaim___::" + md5_id;
420
    entity["openaireId"] = "userclaim___::" + md5_id;
421
    entity["title"] = resultEntity.title;
422
    entity["title"] = (Array.isArray(resultEntity.title) && resultEntity.title.length > 0) ? resultEntity.title[0] : resultEntity.title;
423

    
424
    if (resultEntity.result.authors && resultEntity.result.authors.length > 0) {
425
      entity["authors"] = resultEntity.result.authors;
426
    }
427
    if (resultEntity.result.publisher) {
428
      entity["publisher"] = resultEntity.result.publisher;
429
    }
430
    if (resultEntity.result.description) {
431
      entity["description"] = resultEntity.result.description;
432
    }
433
    // entity["language"]=""; no info
434
    entity["type"] = resultEntity.type;
435
    if (resultEntity.result.source == "crossref" || resultEntity.result.source == "datacite") {
436
      entity["pids"] = [];//{type:string, value:string}[];
437
      entity["pids"].push({type: "doi", value: resultEntity.id})
438
    }
439
    entity["licenseCode"] = resultEntity.result.accessRights;
440
    if (resultEntity.result.accessRights == "EMBARGO") {
441
      entity["embargoEndDate"] = resultEntity.result.embargoEndDate;
442
    }
443
    if (resultEntity.type == "publication") {
444
      entity["resourceType"] = "0001";
445
    } else if (resultEntity.type == "dataset") {
446
      entity["resourceType"] = "0021";
447
    } else if (resultEntity.type == "software") {
448
      entity["resourceType"] = "0029";
449
    } else if (resultEntity.type == "other") {
450
      entity["resourceType"] = "0020";
451
    }
452
    entity["url"] = resultEntity.result.url;
453
    entity["hostedById"] = "openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18";
454
    if (resultEntity.result.source == "crossref") {
455
      entity["collectedFromId"] = "openaire____::crossref";
456
    } else if (resultEntity.result.source == "datacite") {
457
      entity["collectedFromId"] = "openaire____::datacite";
458
    } else if (resultEntity.result.source == "orcid") {
459
      entity["collectedFromId"] = "openaire____::orcid";
460
    } else if (resultEntity.result.source == "orpenaire") {
461
      entity["collectedFromId"] = "openaire____::driver";
462
    }
463
    for (let i = 0; i < results.length; i++) {
464
      if (results[i].project) {
465
        if (!entity["linksToProjects"]) {
466
          entity["linksToProjects"] = [];
467
        }
468
        let project: ClaimEntity = results[i];
469
        entity["linksToProjects"].push("info:eu-repo/grantAgreement/" + project.project.funderName + "/" + project.project.fundingLevel0 + "/" + project.project.code + "/" + project.project.jurisdiction + "/" + project.title + "/" + project.project.acronym);
470

    
471
      } else if (results[i].context) {
472

    
473
        if (!entity["contexts"]) {
474
          entity["contexts"] = [];
475
        }
476
        let context: ClaimEntity = results[i];
477
        entity["contexts"].push(context.context.concept.id);
478

    
479
      }
480
    }
481
    // var json = JSON.stringify(entity);
482
    //console.log("\nJSON:\n"+json);
483
    return entity;
484

    
485

    
486
  }
487

    
488
  confirmOpen() {
489
    this.alert.cancelButton = true;
490
    this.alert.okButton = true;
491
    this.alert.alertTitle = "";//"Final Confirmation notice";
492
    this.alert.okButtonLeft = false;
493
    // this.alert.message = "<div>All the links you provided will be published in the OpenAIRE platform. " +
494
    //   "<br>Make sure you have checked all the information you provided. In some cases some links take more time to be published. " +
495
    //   "<br>For more information please check the linking status in My-Links page. " +
496
    //   "<br><br>Do you confirm the information you provide are valid?</div>";
497
    this.alert.okButtonText = "CONFIRM";
498
    this.alert.cancelButtonText = "CANCEL";
499
    this.alert.open();
500
  }
501

    
502
  confirmClose() {
503
    this.insertActions();
504
  }
505

    
506
  private static handleError(message: string, error) {
507

    
508
    console.error("Insert Claim (component): " + message, error);
509
  }
510

    
511
  getButtonClass(){
512
  //   [class]="(((sources.length>0||inlineEntity) && results.length > 0 && (!claiming  && errors.length == 0))?' ':'uk-disabled')+ ' uk-button  uk-button-large uk-text-center'+((defaultColors)?'':'')">CONFIRM LINKING
513
  //   <span class="  uk-margin-small-top uk-icon uk-float-right uk-text-bold uk-margin-small-right">  }
514
  // [class]="(((sources.length>0||inlineEntity) && results.length > 0 && (!claiming  && errors.length == 0))?'linksbaskettitlesPortalColor ':'uk-disabled')+ ' linksbaskettitles uk-padding-small uk-text-center'">CONFIRM LINKING
515
  // <span class="uk-icon uk-float-right uk-text-bold uk-margin-small-right">
516
    let buttonClass= "";
517
    if((this.sources.length>0||this.inlineEntity) && this.results.length > 0 && (!this.claiming  && this.errors.length == 0)){
518
      if(this.defaultColors){
519
        buttonClass+=" linksbaskettitlesPortalColor ";
520
      }
521
    }else{
522
      buttonClass+=" uk-disabled ";
523

    
524
    }
525
    if(this.defaultColors){
526
      buttonClass+=" linksbaskettitles  uk-padding-small ";
527
    }else{
528
      buttonClass+="  uk-button  uk-button-large  ";
529
    }
530
    return buttonClass + "uk-text-center ";
531
  }
532
}
533

    
(1-1/2)