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 {Session} from '../../../login/utils/helper.class';
8
import {LoginErrorCodes} from '../../../login/utils/guardHelper.class';
9
import {EnvProperties} from '../../../utils/properties/env-properties';
10
import {
11
  ClaimEntity,
12
  ClaimRecord2Insert,
13
  ClaimsErrorMessage,
14
  DirectIndexRecord,
15
  Message
16
} from "../../claim-utils/claimHelper.class";
17
import {UserManagementService} from "../../../services/user-management.service";
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

    
59
  ngOnInit() {
60
    this.route.queryParams.subscribe(params => {
61
      this.params = params;
62
    });
63
  }
64

    
65
  params = {};
66

    
67
  @Input() public results: ClaimEntity[];
68
  @Input() inlineEntity: ClaimEntity = null;
69
  @Input() sources: ClaimEntity[] = null;
70
  @Input() public properties: EnvProperties;
71
  @Input() localStoragePrefix: string;
72
  @ViewChild(ModalLoading) loading: ModalLoading;
73
  @ViewChild(AlertModal) alert;
74
  @Input() errors: ClaimsErrorMessage[];
75
  @Output() insertFinished = new EventEmitter();
76
  @Input() defaultColors:boolean;
77

    
78
  public claiming = false;
79

    
80
  public claims: number = 0;
81

    
82
  private servicesRespond: number = 0;
83
  private insertedClaims = [];
84
  private errorInClaims: ClaimRecord2Insert[] = [];
85
  private insertedRecords = [];
86
  private errorInRecords = [];
87

    
88
  public insert() {
89
    this.confirmOpen();
90
  }
91

    
92
  private insertActions() {
93
    this.servicesRespond = 0;
94
    this.insertedClaims = [];
95
    this.errorInClaims = [];
96
    this.insertedRecords = [];
97
    this.errorInRecords = [];
98
    this.userManagementService.getUserInfo(this.properties.userInfoUrl).subscribe(user => {
99
      if (!user) {
100
        localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
101
        if (this.sources != null) {
102
          localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
103
        }
104

    
105
        this._router.navigate(['/user-info'], {
106
          queryParams: {
107
            "errorCode": LoginErrorCodes.NOT_VALID,
108
            "redirectUrl": this._router.url
109
          }
110
        });
111

    
112
      } else {
113
        this.claiming = true;
114
        this.loading.open();
115
        let claims: ClaimRecord2Insert[] = [];
116
        let directclaims: DirectIndexRecord[] = [];
117
        let dashboard = this.properties.environment+"_"+this.properties.dashboard;
118
        for (let j = 0; j < this.sources.length; j++) {  // if an external result -> direct insert in the index
119
          const result: ClaimEntity = this.sources[j];
120
          if (result.result && ["crossref", "datacite", "orcid"].indexOf(result.result.source) != -1) {
121
            directclaims.push({
122
              "id": result.id,
123
              "record": ClaimInsertComponent.createDirectClaim(result, this.results)
124
            });
125
          }
126
        }
127
        for (let i = 0; i < this.results.length; i++) {
128
          const entity: ClaimEntity = this.results[i]; // this is a research result, a project or a context
129

    
130
          if (entity.result && ["crossref", "datacite", "orcid"].indexOf(entity.result.source) != -1) { // if an external result -> direct insert in the index
131
            if (this.sources.length > 0) {
132
              directclaims.push({
133
                "id": entity.id,
134
                "record": ClaimInsertComponent.createDirectClaim(entity, this.sources)
135
              });
136
            } else if (this.inlineEntity) {
137
              directclaims.push({
138
                "id": entity.id,
139
                "record": ClaimInsertComponent.createDirectClaim(entity, [this.inlineEntity])
140
              });
141
            }
142

    
143
          }
144

    
145
          for (let j = 0; j < this.sources.length; j++) {
146
            const result: ClaimEntity = this.sources[j]; // this is a research result
147
            if (entity.result) {
148
              claims.push(ClaimInsertComponent.createResultClaim(result, entity, user.email, dashboard));
149
            } else if (entity.context) {
150
              claims.push(ClaimInsertComponent.createContextClaim(result, entity, user.email, dashboard));
151
            } else if (entity.project) {
152
              claims.push(ClaimInsertComponent.createProjectClaim(result, entity, user.email, dashboard));
153
            }
154

    
155

    
156
          }
157
          if (this.inlineEntity) {
158
            if (this.inlineEntity.result) {
159
              if (entity.result) {
160

    
161
                claims.push(ClaimInsertComponent.createResultClaim(this.inlineEntity, entity, user.email, dashboard));
162
              } else if (entity.context) {
163
                claims.push(ClaimInsertComponent.createContextClaim(this.inlineEntity, entity, user.email, dashboard));
164
              } else if (entity.project) {
165
                claims.push(ClaimInsertComponent.createProjectClaim(this.inlineEntity, entity, user.email, dashboard));
166
              }
167
            } else if (this.inlineEntity.project) {
168
              if (entity.result) {
169
                claims.push(ClaimInsertComponent.createProjectClaim(entity, this.inlineEntity, user.email, dashboard));
170
              }
171
            }
172
          }
173

    
174

    
175
        }
176

    
177
        //first call direct index service - when call is done (success or error) call isertBulkClaims method to insert claims in DB
178
        console.log("directclaims");
179
        console.log(directclaims);
180
        if (directclaims.length > 0) {
181
          this.claimService.insertDirectRecords(directclaims, this.properties.claimsAPIURL).subscribe(
182
            data => {
183
              this.insertedRecords = data.insertedIds;
184

    
185
              this.errorInRecords = data.errorInClaims;
186
              this.isertBulkClaims(claims);
187
            },
188
            err => {
189
              try {
190
                err = err.json();
191
              } catch (error) {
192
                console.log(error);
193
              }
194
              if (err.insertedIds && err.insertedIds.length > 0) {
195
                this.insertedRecords = err.insertedIds;
196
              }
197
              if (err.errorInClaims && err.errorInClaims.length > 0) {
198
                this.errorInRecords = err.errorInClaims;
199
              }
200
              this.isertBulkClaims(claims);
201

    
202
              ClaimInsertComponent.handleError("Error inserting direct records: " + JSON.stringify(directclaims), err);
203
            }
204
          );
205
        } else {
206
          this.isertBulkClaims(claims);
207
        }
208
      }
209
    });
210
  }
211

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

    
228
        if (claims.length != this.insertedClaims.length) {
229
          let error: ClaimsErrorMessage = new ClaimsErrorMessage();
230
          error.type = "claimServiceFail2Insert";
231
          error.inserted = this.insertedClaims.length;
232
          error.failed = this.errorInClaims.length;
233
          this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
234
          this.errors.push(error);
235
        }
236
        this.afterclaimsInsertion();
237
      },
238
      err => {
239
        try {
240
          err = err.json();
241
        } catch (e) {
242

    
243
        }
244
        let error: ClaimsErrorMessage = new ClaimsErrorMessage();
245
        error.type = "claimServiceFail";
246
        if (err.insertedIds && err.insertedIds.length > 0) {
247
          this.insertedClaims = err.insertedIds;
248
          error.inserted = err.insertedIds.length;
249
        }
250
        if (err.errorInClaims && err.errorInClaims.length > 0) {
251
          this.errorInClaims = err.errorInClaims;
252
          error.failed = err.errorInClaims.length;
253
        } else {
254
          error.failed = claims.length;
255
        }
256

    
257
        if (this.results != null) {
258
          localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
259
        }
260
        if (this.sources != null) {
261
          localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
262
        }
263
        console.log(error);
264
        this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
265
        this.errors.push(error);
266
        this.afterclaimsInsertion();
267

    
268
        ClaimInsertComponent.handleError("Error inserting bulk claims: " + JSON.stringify(claims), err);
269
      }
270
    );
271
  }
272

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

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

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

    
333

    
334
      }
335
    }
336
    this.insertFinished.emit();
337
  }
338

    
339
  private afterclaimsInsertion() {
340

    
341
    this.loading.close();
342
    this.claiming = false;
343

    
344
    if (this.errorInClaims.length == 0 && this.insertedClaims.length > 0) {
345
      localStorage.removeItem(this.localStoragePrefix + "sources");
346
      localStorage.removeItem(this.localStoragePrefix + "results");
347
      this._router.navigate(['/myclaims'], {queryParams: this.params});
348
    }
349
  }
350

    
351

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

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

    
386
  private static createResultClaim(inlineResult: ClaimEntity, resultEntity: ClaimEntity, user: string, dashboard:string): ClaimRecord2Insert {
387

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

    
404
  static getEmbargoEndDate(resultEntity: ClaimEntity): string {
405
    if (resultEntity.result && resultEntity.result.accessRights == "EMBARGO" && resultEntity.result.embargoEndDate != null) {
406
      return resultEntity.result.embargoEndDate;
407
    }
408
    return ""
409
  }
410

    
411
  static createDirectClaim(resultEntity: ClaimEntity, results: ClaimEntity[]) {
412
    let entity = {};
413
    const md5_id = Md5.hashStr(resultEntity.id);
414
    entity["originalId"] = "userclaim___::" + md5_id;
415
    entity["openaireId"] = "userclaim___::" + md5_id;
416
    entity["title"] = resultEntity.title;
417
    entity["title"] = (Array.isArray(resultEntity.title) && resultEntity.title.length > 0) ? resultEntity.title[0] : resultEntity.title;
418

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

    
466
      } else if (results[i].context) {
467

    
468
        if (!entity["contexts"]) {
469
          entity["contexts"] = [];
470
        }
471
        let context: ClaimEntity = results[i];
472
        entity["contexts"].push(context.context.concept.id);
473

    
474
      }
475
    }
476
    // var json = JSON.stringify(entity);
477
    //console.log("\nJSON:\n"+json);
478
    return entity;
479

    
480

    
481
  }
482

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

    
497
  confirmClose() {
498
    this.insertActions();
499
  }
500

    
501
  private static handleError(message: string, error) {
502

    
503
    console.error("Insert Claim (component): " + message, error);
504
  }
505

    
506
  getButtonClass(){
507
  //   [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
508
  //   <span class="  uk-margin-small-top uk-icon uk-float-right uk-text-bold uk-margin-small-right">  }
509
  // [class]="(((sources.length>0||inlineEntity) && results.length > 0 && (!claiming  && errors.length == 0))?'linksbaskettitlesPortalColor ':'uk-disabled')+ ' linksbaskettitles uk-padding-small uk-text-center'">CONFIRM LINKING
510
  // <span class="uk-icon uk-float-right uk-text-bold uk-margin-small-right">
511
    let buttonClass= "";
512
    if((this.sources.length>0||this.inlineEntity) && this.results.length > 0 && (!this.claiming  && this.errors.length == 0)){
513
      if(this.defaultColors){
514
        buttonClass+=" linksbaskettitlesPortalColor ";
515
      }
516
    }else{
517
      buttonClass+=" uk-disabled ";
518

    
519
    }
520
    if(this.defaultColors){
521
      buttonClass+=" linksbaskettitles  uk-padding-small ";
522
    }else{
523
      buttonClass+="  uk-button  uk-button-large  ";
524
    }
525
    return buttonClass + "uk-text-center ";
526
  }
527
}
528

    
(1-1/2)