import {Component, Input, Output, EventEmitter, ViewChild} from '@angular/core';
import {Router, ActivatedRoute} from '@angular/router';
import {ClaimsService} from '../../claim-utils/service/claims.service';
import {ModalLoading} from '../../../utils/modal/loading.component';
import {AlertModal} from '../../../utils/modal/alert';
import {Md5} from 'ts-md5/dist/md5';
import {LoginErrorCodes} from '../../../login/utils/guardHelper.class';
import {EnvProperties} from '../../../utils/properties/env-properties';
import {
ClaimEntity,
ClaimRecord2Insert,
ClaimsErrorMessage,
DirectIndexRecord,
Message
} from "../../claim-utils/claimHelper.class";
import {UserManagementService} from "../../../services/user-management.service";
import {Subscriber, timer} from "rxjs";
import {map} from "rxjs/operators";
@Component({
selector: 'claim-insert',
template: `
Initiating process....
0" class="uk-text-meta uk-text-small">
{{claimsJob.insertedIds.length}} out of {{claims2Insert}} links created.
0" class="uk-text-meta uk-text-small">
{{feedRecordsJob.insertedIds.length}} out of {{records2Insert}} records added in the index...
Please don't close the window, process is ongoing...
Confirmation notice
All the links you provided will be published in the OpenAIRE platform.
Please make sure that the information is valid.
In some cases, links take some time to be published.
For more information please check the linking status in My-Links page.
Do you confirm the information you provide is valid?
`
})
export class ClaimInsertComponent {
constructor(private claimService: ClaimsService, private _router: Router, private route: ActivatedRoute,
private userManagementService: UserManagementService) {
}
subscriptions = [];
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
ngOnInit() {
this.subscriptions.push(this.route.queryParams.subscribe(params => {
this.params = params;
}));
if(localStorage.getItem(this.localStoragePrefix + "claimsJob")){
this.claimsJob = JSON.parse(localStorage.getItem(this.localStoragePrefix + "claimsJob"));
this.feedRecordsJob = JSON.parse(localStorage.getItem(this.localStoragePrefix + "feedRecordsJob"));
if(this.claimsJob.status != "COMPLETE"){
this.claiming = true;
let loadingTimerSubscription = timer(0, 1000).pipe(
map(() => {
if(this.loading) {
this.loading.open();
loadingTimerSubscription.unsubscribe();
}
})
).subscribe();
this.subscriptions.push(loadingTimerSubscription);
let timerSubscription = timer(0, 10000).pipe(
map(() => {
this.getStatus(); // load data contains the http request
})
).subscribe();
this.subscriptions.push(timerSubscription);
}else{
this.claimsJob = null;
}
}
}
params = {};
@Input() public results: ClaimEntity[];
@Input() inlineEntity: ClaimEntity = null;
@Input() sources: ClaimEntity[] = null;
@Input() public properties: EnvProperties;
@Input() localStoragePrefix: string;
@ViewChild(ModalLoading) loading: ModalLoading;
@ViewChild(AlertModal) alert;
@Input() errors: ClaimsErrorMessage[];
@Output() insertFinished = new EventEmitter();
@Input() defaultColors:boolean;
@Input() communityId:string= null;
public claiming = false;
public claims: number = 0;
private servicesRespond: number = 0;
private insertedClaims = [];
private errorInClaims: ClaimRecord2Insert[] = [];
private insertedRecords = [];
private errorInRecords = [];
public claimsJob;
public feedRecordsJob;
public claims2Insert;
public records2Insert
public insert() {
this.confirmOpen();
}
saveAndNavigate(){
this.saveLocalStorage();
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
}
private insertActions() {
this.servicesRespond = 0;
this.insertedClaims = [];
this.errorInClaims = [];
this.insertedRecords = [];
this.errorInRecords = [];
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
if (!user) {
this.saveAndNavigate();
} else {
this.claiming = true;
this.loading.open();
let claims: ClaimRecord2Insert[] = [];
let directclaims: DirectIndexRecord[] = [];
let dashboard = this.properties.environment+"_"+this.properties.dashboard + (this.communityId?("_"+this.communityId):'');
for (let j = 0; j < this.sources.length; j++) { // if an external result -> direct insert in the index
const result: ClaimEntity = this.sources[j];
if (result.result && ["crossref", "datacite", "orcid"].indexOf(result.result.source) != -1) {
directclaims.push({
"id": result.id,
"record": ClaimInsertComponent.createDirectClaim(result, this.results)
});
}
}
for (let i = 0; i < this.results.length; i++) {
const entity: ClaimEntity = this.results[i]; // this is a research result, a project or a context
if (entity.result && ["crossref", "datacite", "orcid"].indexOf(entity.result.source) != -1) { // if an external result -> direct insert in the index
if (this.sources.length > 0) {
directclaims.push({
"id": entity.id,
"record": ClaimInsertComponent.createDirectClaim(entity, this.sources)
});
} else if (this.inlineEntity) {
directclaims.push({
"id": entity.id,
"record": ClaimInsertComponent.createDirectClaim(entity, [this.inlineEntity])
});
}
}
for (let j = 0; j < this.sources.length; j++) {
const result: ClaimEntity = this.sources[j]; // this is a research result
if (entity.result) {
claims.push(ClaimInsertComponent.createResultClaim(result, entity, user.email, dashboard));
} else if (entity.context) {
claims.push(ClaimInsertComponent.createContextClaim(result, entity, user.email, dashboard));
} else if (entity.project) {
claims.push(ClaimInsertComponent.createProjectClaim(result, entity, user.email, dashboard));
}
}
if (this.inlineEntity) {
if (this.inlineEntity.result) {
if (entity.result) {
claims.push(ClaimInsertComponent.createResultClaim(this.inlineEntity, entity, user.email, dashboard));
} else if (entity.context) {
claims.push(ClaimInsertComponent.createContextClaim(this.inlineEntity, entity, user.email, dashboard));
} else if (entity.project) {
claims.push(ClaimInsertComponent.createProjectClaim(this.inlineEntity, entity, user.email, dashboard));
}
} else if (this.inlineEntity.project) {
if (entity.result) {
claims.push(ClaimInsertComponent.createProjectClaim(entity, this.inlineEntity, user.email, dashboard));
}
}
}
}
//first call direct index service - when call is done (success or error) call isertBulkClaims method to insert claims in DB
// console.log("directclaims");
// console.log(directclaims);
if (directclaims.length > 0/* && this.properties.environment != "development"*/){
this.subscriptions.push(this.claimService.insertDirectRecords(directclaims, this.properties.claimsAPIURL).subscribe(
data => {
this.feedRecordsJob = data.data;
this.records2Insert = directclaims.length;
console.log(data);
// this.insertedRecords = data.insertedIds;
//
// this.errorInRecords = data.errorInClaims;
this.isertBulkClaims(claims);
},
err => {
err = err && err.error?err.error:err;
if (err.code && err.code == 403) {
this.saveAndNavigate();
}
/* if (err.insertedIds && err.insertedIds.length > 0) {
this.insertedRecords = err.insertedIds;
}
if (err.errorInClaims && err.errorInClaims.length > 0) {
this.errorInRecords = err.errorInClaims;
}*/
this.isertBulkClaims(claims);
ClaimInsertComponent.handleError("Error inserting direct records: " + JSON.stringify(directclaims), err);
}
));
} else {
this.isertBulkClaims(claims);
}
}
}));
}
private isertBulkClaims(claims: ClaimRecord2Insert[]) {
this.errors.splice(0, this.errors.length);
this.subscriptions.push(this.claimService.insertBulkClaims(claims, this.properties.claimsAPIURL).subscribe(
data => {
this.claims2Insert = claims.length;
this.claimsJob = data.data;
this.saveLocalStorage();
let timerSubscription = timer(0, 10000).pipe(
map(() => {
this.getStatus(); // load data contains the http request
})
).subscribe();
this.subscriptions.push(timerSubscription);
},
err => {
err = err && err.error?err.error:err;
if (err.code && err.code == 403) {
this.saveAndNavigate();
}
let error: ClaimsErrorMessage = new ClaimsErrorMessage();
error.type = "claimServiceFail";
if (err.insertedIds && err.insertedIds.length > 0) {
this.insertedClaims = err.insertedIds;
error.inserted = err.insertedIds.length;
}
if (err.errorInClaims && err.errorInClaims.length > 0) {
this.errorInClaims = err.errorInClaims;
error.failed = err.errorInClaims.length;
} else {
error.failed = claims.length;
}
if (this.results != null) {
localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
}
if (this.sources != null) {
localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
}
console.log(error);
this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
this.errors.push(error);
this.afterclaimsInsertion();
ClaimInsertComponent.handleError("Error inserting bulk claims: " + JSON.stringify(claims), err);
}
));
}
createErrorMessagesPerEntity(applyToAll: boolean) {
let errorsInIds: string[] = [];
let savedIds: string[] = [];
if (!applyToAll) {
for (let claim of this.errorInClaims) {
errorsInIds.push(claim.sourceId);
errorsInIds.push(claim.targetId);
}
}
for (let i = 0; i < this.sources.length; i++) {
let entity: ClaimEntity = this.sources[i];
if (errorsInIds.indexOf(entity.id) != -1 || applyToAll) {
let error: Message = new Message();
error.type = "fail2Insert";
entity.errorMessages.push(error);
} else {
savedIds.push(entity.id);
}
}
for (let entity of this.results) {
if (errorsInIds.indexOf(entity.id) != -1 || applyToAll) {
let error: Message = new Message();
error.type = "fail2Insert";
entity.errorMessages.push(error);
} else {
savedIds.push(entity.id);
}
}
if (this.inlineEntity && (errorsInIds.indexOf(this.inlineEntity.id) != -1 || applyToAll)) {
let error: Message = new Message();
error.type = "fail2Insert";
this.inlineEntity.errorMessages.push(error);
}
//remove entities that have been saved
for (let id of savedIds) {
//remove sources
let sourceIndex = -1;
for (let i = 0; i < this.sources.length; i++) {
if (this.sources[i].id == id) {
sourceIndex = i;
break;
}
}
if (sourceIndex != -1) {
this.sources.splice(sourceIndex, 1);
} else {
//remove results
let resutsIndex = -1;
for (let i = 0; i < this.results.length; i++) {
if (this.results[i].id == id) {
resutsIndex = i;
break;
}
}
if (resutsIndex != -1) {
this.results.splice(resutsIndex, 1);
}
}
}
this.insertFinished.emit();
}
private afterclaimsInsertion() {
this.claiming = false;
this.loading.close();
if (this.errorInClaims.length == 0 && this.insertedClaims.length > 0) {
localStorage.removeItem(this.localStoragePrefix + "sources");
localStorage.removeItem(this.localStoragePrefix + "results");
localStorage.removeItem(this.localStoragePrefix + "claimsJob");
localStorage.removeItem(this.localStoragePrefix + "feedRecordsJob");
this._router.navigate(['/myclaims'], {queryParams: this.params});
}
}
private static createContextClaim(resultEntity: ClaimEntity, contextEntity: ClaimEntity, user: any, dashboard:string): ClaimRecord2Insert {
return {
claimedBy: user,
sourceId: contextEntity.context.concept.id,
sourceType: "context",
sourceCollectedFrom: "openaire",
sourceAccessRights: "OPEN",
sourceEmbargoEndDate: "",
targetId: resultEntity.id,
targetType: resultEntity.type,
targetCollectedFrom: resultEntity.result.source,
targetAccessRights: resultEntity.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
claimedInDashboard : dashboard
};
}
private static createProjectClaim(resultEntity: ClaimEntity, projectEntity: ClaimEntity, user: any, dashboard:string): ClaimRecord2Insert {
return {
claimedBy: user,
sourceId: projectEntity.id,
sourceType: "project",
sourceCollectedFrom: "openaire",
sourceAccessRights: "OPEN",
sourceEmbargoEndDate: "",
targetId: resultEntity.id,
targetType: resultEntity.type,
targetCollectedFrom: resultEntity.result.source,
targetAccessRights: resultEntity.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
claimedInDashboard : dashboard
};
}
private static createResultClaim(inlineResult: ClaimEntity, resultEntity: ClaimEntity, user: string, dashboard:string): ClaimRecord2Insert {
return {
claimedBy: user,
sourceId: resultEntity.id,
sourceType: resultEntity.type,
sourceCollectedFrom: resultEntity.result.source,
sourceAccessRights: resultEntity.result.accessRights,
sourceEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
targetId: inlineResult.id,
targetType: inlineResult.type,
targetCollectedFrom: inlineResult.result.source,
targetAccessRights: inlineResult.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(inlineResult),
claimedInDashboard : dashboard
};
}
static getEmbargoEndDate(resultEntity: ClaimEntity): string {
if (resultEntity.result && resultEntity.result.accessRights == "EMBARGO" && resultEntity.result.embargoEndDate != null) {
return resultEntity.result.embargoEndDate;
}
return ""
}
static createDirectClaim(resultEntity: ClaimEntity, results: ClaimEntity[]) {
let entity = {};
const md5_id = Md5.hashStr(resultEntity.id);
entity["originalId"] = "userclaim___::" + md5_id;
entity["openaireId"] = "userclaim___::" + md5_id;
entity["title"] = resultEntity.title;
entity["title"] = (Array.isArray(resultEntity.title) && resultEntity.title.length > 0) ? resultEntity.title[0] : resultEntity.title;
if (resultEntity.result.authors && resultEntity.result.authors.length > 0) {
entity["authors"] = resultEntity.result.authors;
}
if (resultEntity.result.publisher) {
entity["publisher"] = resultEntity.result.publisher;
}
if (resultEntity.result.description) {
entity["description"] = resultEntity.result.description;
}
// entity["language"]=""; no info
entity["type"] = resultEntity.type;
if (resultEntity.result.source == "crossref" || resultEntity.result.source == "datacite") {
entity["pids"] = [];//{type:string, value:string}[];
entity["pids"].push({type: "doi", value: resultEntity.id})
}
entity["licenseCode"] = resultEntity.result.accessRights;
if (resultEntity.result.accessRights == "EMBARGO") {
entity["embargoEndDate"] = resultEntity.result.embargoEndDate;
}
if (resultEntity.type == "publication") {
entity["resourceType"] = "0001";
} else if (resultEntity.type == "dataset") {
entity["resourceType"] = "0021";
} else if (resultEntity.type == "software") {
entity["resourceType"] = "0029";
} else if (resultEntity.type == "other") {
entity["resourceType"] = "0020";
}
entity["url"] = resultEntity.result.url;
entity["hostedById"] = "openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18";
if (resultEntity.result.source == "crossref") {
entity["collectedFromId"] = "openaire____::crossref";
} else if (resultEntity.result.source == "datacite") {
entity["collectedFromId"] = "openaire____::datacite";
} else if (resultEntity.result.source == "orcid") {
entity["collectedFromId"] = "openaire____::orcid";
} else if (resultEntity.result.source == "orpenaire") {
entity["collectedFromId"] = "openaire____::driver";
}
for (let i = 0; i < results.length; i++) {
if (results[i].project) {
if (!entity["linksToProjects"]) {
entity["linksToProjects"] = [];
}
let project: ClaimEntity = results[i];
entity["linksToProjects"].push("info:eu-repo/grantAgreement/" + project.project.funderName + "/" + project.project.fundingLevel0 + "/" + project.project.code + "/" + project.project.jurisdiction + "/" + project.title + "/" + project.project.acronym);
} else if (results[i].context) {
if (!entity["contexts"]) {
entity["contexts"] = [];
}
let context: ClaimEntity = results[i];
entity["contexts"].push(context.context.concept.id);
}
}
// var json = JSON.stringify(entity);
//console.log("\nJSON:\n"+json);
return entity;
}
confirmOpen() {
this.alert.cancelButton = true;
this.alert.okButton = true;
this.alert.alertTitle = "";//"Final Confirmation notice";
this.alert.okButtonLeft = false;
// this.alert.message = "All the links you provided will be published in the OpenAIRE platform. " +
// "
Make sure you have checked all the information you provided. In some cases some links take more time to be published. " +
// "
For more information please check the linking status in My-Links page. " +
// "
Do you confirm the information you provide are valid?
";
this.alert.okButtonText = "CONFIRM";
this.alert.cancelButtonText = "CANCEL";
this.alert.open();
}
confirmClose() {
this.insertActions();
}
private static handleError(message: string, error) {
console.error("Insert Claim (component): " + message, error);
}
getButtonClass(){
// [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
// }
// [class]="(((sources.length>0||inlineEntity) && results.length > 0 && (!claiming && errors.length == 0))?'linksbaskettitlesPortalColor ':'uk-disabled')+ ' linksbaskettitles uk-padding-small uk-text-center'">CONFIRM LINKING
//
let buttonClass= "";
if((this.sources.length>0||this.inlineEntity) && this.results.length > 0 && (!this.claiming && this.errors.length == 0)){
if(this.defaultColors){
buttonClass+=" linksbaskettitlesPortalColor ";
}
}else{
buttonClass+=" uk-disabled ";
}
if(this.defaultColors){
buttonClass+=" linksbaskettitles uk-padding-small ";
}
return buttonClass + "uk-text-center ";
}
getStatus(){
if(this.feedRecordsJob && ! (this.feedRecordsJob.status == "COMPLETE" || this.feedRecordsJob.status == "ERROR") ) {
this.subscriptions.push(this.claimService.getStatus(this.feedRecordsJob.id, this.properties.claimsAPIURL).subscribe(data => {
this.feedRecordsJob = data.data;
// console.log("feed", this.feedRecordsJob.status);
if (this.feedRecordsJob.status == "COMPLETE" || data.data.status == "ERROR") {
this.insertedRecords = this.feedRecordsJob.insertedIds;
this.errorInRecords = this.feedRecordsJob.errorInClaims;
}
}, err => {
let error: ClaimsErrorMessage = new ClaimsErrorMessage();
error.type = "jobError";
this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
this.errors.push(error);
this.afterclaimsInsertion();
this.feedRecordsJob = null;
localStorage.removeItem(this.localStoragePrefix + "feedRecordsJob");
}
));
}
if(this.claimsJob) {
this.subscriptions.push(this.claimService.getStatus(this.claimsJob.id, this.properties.claimsAPIURL).subscribe(data => {
this.claimsJob = data.data;
// console.log("claim: ", this.claimsJob.status, this.feedRecordsJob.status?this.feedRecordsJob.status:" no feed job");
if ((this.claimsJob.status == "COMPLETE" || data.data.status == "ERROR") && ( !this.feedRecordsJob || (this.feedRecordsJob.status == "COMPLETE" || data.data.status == "ERROR")) ) {
this.insertedClaims = this.claimsJob.insertedIds;
this.errorInClaims = this.claimsJob.errorInClaims;
if (this.claims2Insert != this.insertedClaims.length) {
let error: ClaimsErrorMessage = new ClaimsErrorMessage();
error.type = "claimServiceFail2Insert";
error.inserted = this.insertedClaims.length;
error.failed = this.errorInClaims.length;
this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
this.errors.push(error);
}
this.afterclaimsInsertion();
}
}, err => {
let error: ClaimsErrorMessage = new ClaimsErrorMessage();
error.type = "jobError";
this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
this.errors.push(error);
this.afterclaimsInsertion();
this.claimsJob = null;
localStorage.removeItem(this.localStoragePrefix + "claimsJob");
}
));
}
}
saveLocalStorage(){
if (this.results != null) {
localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
}
if (this.sources != null) {
localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
}
if (this.claimsJob != null) {
localStorage.setItem(this.localStoragePrefix + "claimsJob", JSON.stringify(this.claimsJob));
}
if (this.feedRecordsJob != null) {
localStorage.setItem(this.localStoragePrefix + "feedRecordsJob", JSON.stringify(this.feedRecordsJob));
}
}
}