Production release March 2024 [Monitor Dashboard] #38

Merged
k.triantafyllou merged 14 commits from develop into master 2024-04-01 18:02:05 +02:00
20 changed files with 302 additions and 270 deletions

View File

@ -56,57 +56,76 @@
<div *ngIf="claims && claims.length == 0" class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold"> <div *ngIf="claims && claims.length == 0" class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No links found</div> <div>No links found</div>
</div> </div>
<ul class="uk-margin-small-top uk-list uk-list-xlarge"> <ng-container *ngIf="claims && claims.length > 0">
<li *ngFor="let claim of claims; let i=index" class="uk-card uk-card-default">
<div class="uk-card-body"> <div class="uk-flex uk-flex-middle uk-margin-top uk-margin-small-bottom uk-padding-small uk-padding-remove-horizontal">
<div class="uk-grid uk-grid-small" uk-grid> <div class="uk-width-xsmall uk-flex uk-flex-center uk-flex-middle">
<div class="uk-width-expand"> <label>
<div class="uk-margin-bottom"> <input id="checkAll" type="checkbox" (click)="selectAll($event)" class="uk-checkbox" title="Select All"
<claim-entity [entity]="claim.target" [type]="claim.targetType" [properties]=properties [ngModel]="selected.length == claims.length"/>
[externalPortalUrl]=externalPortalUrl [source]="true" [linkAvailable]="isClaimAvailable(claim)"></claim-entity> </label>
</div> </div>
<div class="uk-margin-bottom"> <button class="uk-button uk-button-link" [class.uk-disabled]="selected.length == 0" [disabled]="selected.length == 0"
<span *ngIf="isClaimAvailable(claim) else notAvailable" class="uk-label uk-label-success" (click)="deleteOpen()">
[attr.uk-tooltip]="'title: The link information is available in the portal and the APIs.'">available</span> <span>Delete ({{selected.length}})</span>
<ng-template #notAvailable> </button>
<span class="uk-label uk-label-danger" </div>
[attr.uk-tooltip]="'title:The link information will be added in the portal and the APIs in the next content provision workflow.'">pending</span>
</ng-template> <ul class="uk-margin-small-top uk-list uk-list-striped">
</div> <li *ngFor="let claim of claims; let i=index" class="uk-flex uk-flex-middle uk-padding-small uk-padding-remove-horizontal">
<div class="uk-text-small"> <div class="uk-width-xsmall uk-flex uk-flex-center uk-flex-middle">
<div *ngIf="showUserEmail" class="uk-margin-small-bottom"> <input type="checkbox" class="uk-checkbox"
<span class="uk-text-meta">Claimed by:</span> [id]="claim.id" (click)="selectClaim(claim, $event)" [ngModel]="isSelectedClaim(claim.id)">
<span class="uk-margin-xsmall-left">{{claim.userMail}}</span> </div>
<div class="uk-width-expand">
<div class="uk-grid uk-grid-small uk-flex-middle" uk-grid>
<div class="uk-width-expand">
<div class="uk-margin-small-bottom">
<claim-entity [entity]="claim.target" [type]="claim.targetType" [properties]=properties
[externalPortalUrl]=externalPortalUrl [source]="true" [linkAvailable]="isClaimAvailable(claim)"></claim-entity>
</div> </div>
<div> <div class="uk-margin-small-bottom">
<span class="uk-text-meta">Claimed date:</span> <span *ngIf="isClaimAvailable(claim) else notAvailable" class="uk-label uk-label-small uk-label-success"
<span class="uk-margin-xsmall-left">{{claim.date}}</span> [attr.uk-tooltip]="'title: The link information is available in the portal and the APIs.'">available</span>
<ng-template #notAvailable>
<span class="uk-label uk-label-small uk-label-danger"
[attr.uk-tooltip]="'title:The link information will be added in the portal and the APIs in the next content provision workflow.'">pending</span>
</ng-template>
</div>
<div class="uk-text-small">
<div *ngIf="showUserEmail" class="uk-margin-xsmall-bottom">
<span class="uk-text-meta">Claimed by:</span>
<span class="uk-margin-xsmall-left">{{claim.userMail}}</span>
</div>
<div>
<span class="uk-text-meta">Claimed date:</span>
<span class="uk-margin-xsmall-left">{{claim.date}}</span>
</div>
</div> </div>
</div> </div>
</div> <div class="uk-visible@m">
<div class="uk-visible@m"> <div class="claim-divider">
<div class="claim-divider"> <icon class="uk-position-center" name="link" customClass="uk-text-primary" ratio="2" [flex]="true"></icon>
<icon class="uk-position-center" name="link" customClass="uk-text-primary" ratio="2" [flex]="true"></icon> </div>
</div>
<div class="uk-width-1-2@m uk-width-1-1">
<claim-entity [entity]="claim.source" [type]="claim.sourceType" [source]="false" [properties]=properties
[externalPortalUrl]=externalPortalUrl></claim-entity>
</div> </div>
</div>
<div class="uk-width-1-2@m uk-width-1-1 uk-flex uk-flex-column uk-flex-center">
<claim-entity [entity]="claim.source" [type]="claim.sourceType" [source]="false" [properties]=properties
[externalPortalUrl]=externalPortalUrl></claim-entity>
</div> </div>
</div> </div>
</div> <div class="uk-width-xsmall uk-flex uk-flex-center uk-flex-middle">
<div class="uk-card-footer uk-flex uk-flex-right"> <button class="uk-button uk-button-link uk-flex uk-flex-middle" (click)="deleteOpen(i)">
<button class="uk-button uk-button-link uk-flex uk-flex-middle" (click)="deleteOpen(i)"> <icon name="delete" [flex]="true"></icon>
<icon name="delete" [flex]="true"></icon> </button>
<span class="uk-margin-xsmall-left">Delete</span> </div>
</button> </li>
</div> </ul>
</li> <div class="uk-margin-medium-top uk-flex uk-flex-center uk-flex-right@m">
</ul> <paging-no-load *ngIf="resultsNum" [currentPage]="page" [totalResults]="resultsNum" [size]="size"
<div class="uk-margin-medium-top uk-flex uk-flex-center uk-flex-right@m"> (pageChange)="pageChange($event)"></paging-no-load>
<paging-no-load *ngIf="resultsNum" [currentPage]="page" [totalResults]="resultsNum" [size]="size" </div>
(pageChange)="pageChange($event)"></paging-no-load> </ng-container>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -4,14 +4,4 @@
position: relative; position: relative;
padding: 0 20px; padding: 0 20px;
height: 100%; height: 100%;
&::before {
content: '';
position: absolute;
top: 0;
left: 50%;
right: 0;
bottom: 0;
border-left: @global-border-width solid @global-border;
}
} }

View File

@ -52,6 +52,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
lastIndexDate = null; lastIndexDate = null;
public filterForm: FormGroup; public filterForm: FormGroup;
public entities: string[] = []; public entities: string[] = [];
selected = [];
allOptions: Option[] = [ allOptions: Option[] = [
{label: OpenaireEntities.PUBLICATIONS, value: "publication"}, {label: OpenaireEntities.PUBLICATIONS, value: "publication"},
@ -310,23 +311,34 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
} }
isSelected(value: string) { isSelected(value: string) {
return this.filterForm && this.filterForm.get('entities').value.find(entity => entity === value) return this.filterForm && this.filterForm.get('entities').value.find(entity => entity === value);
} }
deleteOpen(index: number) { deleteOpen(index: number = null) {
this.index = index; this.index = index;
this.deleteModal.alertTitle = 'Delete Confirmation'; this.deleteModal.alertTitle = 'Delete Confirmation';
this.deleteModal.message = 'Are you sure you want to delete this link?'; this.deleteModal.message = 'Are you sure you want to delete ' + (this.index != null ? '1' : this.selected.length) + ' link(s)?';
this.deleteModal.okButtonText = 'Yes'; this.deleteModal.okButtonText = 'Yes';
this.deleteModal.open(); this.deleteModal.open();
} }
delete() { delete() {
this.subscriptions.push(this._claimService.deleteBulk([this.claims[this.index].id], this.properties.claimsAPIURL).subscribe( let claimsToBeDeleted = ((this.index != null) ? [this.claims[this.index].id] : this.selected.map(claim => claim.id));
console.log(claimsToBeDeleted);
this.subscriptions.push(this._claimService.deleteBulk(claimsToBeDeleted, this.properties.claimsAPIURL).subscribe(
res => { res => {
this.claims.splice(this.index, 1); if (this.index != null) {
this.resultsNum = this.resultsNum - 1; this.claims.splice(this.index, 1);
NotificationHandler.rise('Link has been deleted successfully'); this.resultsNum = this.resultsNum - 1;
NotificationHandler.rise('Link has been deleted successfully');
} else {
claimsToBeDeleted.forEach(claimId => {
this.claims.splice(this.claims.findIndex((id) => id == claimId), 1);
});
this.resultsNum = this.resultsNum - claimsToBeDeleted.length;
NotificationHandler.rise(claimsToBeDeleted.length + ' links have been deleted successfully');
}
this.selected = [];
let goToPage = this.page; let goToPage = this.page;
if (this.totalPages(this.resultsNum) < this.page && this.page > 0) { if (this.totalPages(this.resultsNum) < this.page && this.page > 0) {
goToPage = this.page - 1; goToPage = this.page - 1;
@ -334,7 +346,8 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
this.goTo(goToPage); this.goTo(goToPage);
}, err => { }, err => {
this.handleErrors(err, "Error deleting claim with id: " + this.claims[this.index].id); this.handleErrors(err, "Error deleting claim with id: " + this.claims[this.index].id);
})); }
));
} }
pageChange($event) { pageChange($event) {
@ -362,7 +375,44 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
} }
return totalPages; return totalPages;
} }
selectClaim(item: any, event) {
let value = event.currentTarget.checked;
if (value) {
this.selected.push(item);
} else {
for (var _i = 0; _i < this.selected.length; _i++) {
let claim = this.selected[_i];
if (claim['id'] == item.id) {
this.selected.splice(_i, 1);
}
}
}
}
selectAll(event) {
let value = event.currentTarget.checked;
if (value) {
this.selected = [];
for (let _i = 0; _i < this.claims.length; _i++) {
let claim = this.claims[_i];
this.selected.push(claim);
}
} else {
this.selected = [];
}
}
isSelectedClaim(id: string) {
for (let _i = 0; _i < this.selected.length; _i++) {
let claim = this.selected[_i];
if (claim['id'] == id) {
return true;
}
}
return false;
}
private updateDescription(description: string) { private updateDescription(description: string) {
this._meta.updateTag({content: description}, "name='description'"); this._meta.updateTag({content: description}, "name='description'");
this._meta.updateTag({content: description}, "property='og:description'"); this._meta.updateTag({content: description}, "property='og:description'");

View File

@ -15,21 +15,22 @@ import {StringUtils} from "../../../utils/string-utils.class";
<div *ngIf="source" class="uk-text-small"> <div *ngIf="source" class="uk-text-small">
{{getEntityName(type)}} {{getEntityName(type)}}
</div> </div>
<div class="uk-flex"> <div>
<span *ngIf="!source" class="uk-text-meta uk-margin-small-right uk-text-large uk-text-nowrap">Link to:</span> <span *ngIf="!source" class="uk-text-meta uk-text-small uk-margin-small-right uk-text-nowrap">Link to:</span>
<publication-title [entity]="entity" param="id" <publication-title [entity]="entity" param="id"
path="/search/result" [externalPortalUrl]=externalPortalUrl [linkAvailable]="linkAvailable"></publication-title> path="/search/result" [externalPortalUrl]=externalPortalUrl [linkAvailable]="linkAvailable"></publication-title>
</div> </div>
</div> </div>
<div *ngIf="type == 'project'" [attr.uk-tooptip]="getEntityName(type)" <div *ngIf="type == 'project'" [attr.uk-tooptip]="getEntityName(type)">
class="uk-flex"> <span class="uk-text-meta uk-text-small uk-margin-small-right uk-text-nowrap">Link to:</span>
<span class="uk-text-meta uk-margin-small-right uk-text-large uk-text-nowrap">Link to:</span>
<project-title [project]="entity" [searchLink]=properties.searchLinkToProject <project-title [project]="entity" [searchLink]=properties.searchLinkToProject
[externalPortalUrl]=externalPortalUrl></project-title> [externalPortalUrl]=externalPortalUrl></project-title>
</div> </div>
<div *ngIf="type == 'context'" class="uk-flex uk-text-large"> <div *ngIf="type == 'context'">
<span class="uk-text-meta uk-margin-small-right uk-text-nowrap">Link to:</span> <span class="uk-text-meta uk-text-small uk-margin-small-right uk-text-nowrap">Link to:</span>
<span class="uk-text-truncate" uk-tooltip="Concept">{{entity.title}}</span> <h6 class="uk-h6 uk-margin-remove">
<span class="uk-text-truncate" uk-tooltip="Concept">{{entity.title}}</span>
</h6>
</div> </div>
` `
}) })

View File

@ -20,7 +20,7 @@ import {properties} from "../../../../../environments/environment";
</h6> </h6>
</ng-container> </ng-container>
<span *ngIf="project['funderName']" class="uk-margin-small-top"> <span *ngIf="project['funderName']" class="uk-margin-small-top">
<span class="uk-text-muted">Funder: </span>{{project['funderName']}} <span class="uk-text-meta">Funder: </span>{{project['funderName']}}
</span> </span>
` `
}) })

View File

@ -88,6 +88,10 @@ export class LayoutService {
* Handle it manually in the component, it doesn't use data * Handle it manually in the component, it doesn't use data
* */ * */
private rootClassSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null); private rootClassSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);
/**
* Display help pop-up on non-admin pages. (default true for the rest of the pages)
* */
private hasHelpPopUpSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
private subscriptions: any[] = []; private subscriptions: any[] = [];
ngOnDestroy() { ngOnDestroy() {
@ -343,4 +347,12 @@ export class LayoutService {
this.rootClassSubject.next(value); this.rootClassSubject.next(value);
} }
} }
get hasHelpPopUp(): Observable<boolean> {
return this.hasHelpPopUpSubject.asObservable();
}
setHasHelpPopUp(value: boolean) {
this.hasHelpPopUpSubject.next(value);
}
} }

View File

@ -26,7 +26,6 @@ import {ResultPreviewModule} from "../../utils/result-preview/result-preview.mod
import {FeedbackModule} from "../feedback/feedback.module"; import {FeedbackModule} from "../feedback/feedback.module";
import {TabsModule} from "../../utils/tabs/tabs.module"; import {TabsModule} from "../../utils/tabs/tabs.module";
import {LoadingModule} from "../../utils/loading/loading.module"; import {LoadingModule} from "../../utils/loading/loading.module";
import {OrcidModule} from "../../orcid/orcid.module";
import {IconsModule} from "../../utils/icons/icons.module"; import {IconsModule} from "../../utils/icons/icons.module";
import {IconsService} from "../../utils/icons/icons.service"; import {IconsService} from "../../utils/icons/icons.service";
import {cite, fire, graph, landmark, link, link_to, quotes, rocket, versions} from "../../utils/icons/icons"; import {cite, fire, graph, landmark, link, link_to, quotes, rocket, versions} from "../../utils/icons/icons";
@ -38,6 +37,7 @@ import {FullScreenModalModule} from "../../utils/modal/full-screen-modal/full-sc
import {SafeHtmlPipeModule} from '../../utils/pipes/safeHTMLPipe.module'; import {SafeHtmlPipeModule} from '../../utils/pipes/safeHTMLPipe.module';
import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.module"; import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.module";
import {ResultLandingRoutingModule} from "./resultLanding-routing.module"; import {ResultLandingRoutingModule} from "./resultLanding-routing.module";
import {OrcidCoreModule} from "../../orcid/orcid-core.module";
@NgModule({ @NgModule({
imports: [ imports: [
@ -47,7 +47,7 @@ import {ResultLandingRoutingModule} from "./resultLanding-routing.module";
AltMetricsModule, Schema2jsonldModule, SEOServiceModule, AltMetricsModule, Schema2jsonldModule, SEOServiceModule,
DeletedByInferenceModule, ShowAuthorsModule, HelperModule, ResultLandingUtilsModule, AlertModalModule, DeletedByInferenceModule, ShowAuthorsModule, HelperModule, ResultLandingUtilsModule, AlertModalModule,
LandingHeaderModule, NoLoadPaging, ResultPreviewModule, FeedbackModule, TabsModule, LoadingModule, LandingHeaderModule, NoLoadPaging, ResultPreviewModule, FeedbackModule, TabsModule, LoadingModule,
OrcidModule, IconsModule, InputModule, EGIDataTransferModule, RecaptchaModule, OrcidCoreModule, IconsModule, InputModule, EGIDataTransferModule, RecaptchaModule,
SdgFosSuggestModule, FullScreenModalModule, SafeHtmlPipeModule, EntityActionsModule SdgFosSuggestModule, FullScreenModalModule, SafeHtmlPipeModule, EntityActionsModule
], ],
declarations: [ declarations: [

View File

@ -234,6 +234,7 @@ export class Role {
} }
public static mapType(type: string, communityMap: boolean = true): string { public static mapType(type: string, communityMap: boolean = true): string {
type = type.replace(this.GROUP, '');
if (type == "ri" && communityMap) { if (type == "ri" && communityMap) {
type = "community"; type = "community";
} else if (type == "organization") { } else if (type == "organization") {

View File

@ -14,16 +14,6 @@
(click)="deleteSectionOpen(number, i, 'number', 'delete')"> (click)="deleteSectionOpen(number, i, 'number', 'delete')">
<icon name="close" [flex]="true"></icon> <icon name="close" [flex]="true"></icon>
</a> </a>
<!-- <ng-container *ngIf="!stakeholder.defaultId">-->
<!-- <button [disabled]="editing || number.defaultId " class="md-btn md-btn-mini"-->
<!-- [title]="(number.defaultId?'Default sections cannot be deleted':'Delete all related sections')"-->
<!-- (click)="deleteSectionOpen(number, i, 'number', 'delete')"><i class="material-icons">highlight_off</i>-->
<!-- </button>-->
<!-- <button [disabled]="editing || number.defaultId " class="md-btn md-btn-mini"-->
<!-- [title]="(number.defaultId?'Default sections cannot be deleted':'Delete section and disconnect related')"-->
<!-- (click)="deleteSectionOpen(number, i, 'number', 'disconnect')"><i class="material-icons">link_off</i>-->
<!-- </button>-->
<!-- </ng-container>-->
</div> </div>
</div> </div>
<div *ngIf="numberSections.at(i)" class="uk-margin-medium-bottom"> <div *ngIf="numberSections.at(i)" class="uk-margin-medium-bottom">
@ -113,16 +103,6 @@
(click)="deleteSectionOpen(chart, i, 'chart', 'delete')"> (click)="deleteSectionOpen(chart, i, 'chart', 'delete')">
<icon name="close" [flex]="true"></icon> <icon name="close" [flex]="true"></icon>
</a> </a>
<!-- <ng-container *ngIf="!stakeholder.defaultId">-->
<!-- <button [disabled]="editing || chart.defaultId " class="md-btn md-btn-mini"-->
<!-- [title]="(chart.defaultId?'Default sections cannot be deleted':'Delete all related sections')"-->
<!-- (click)="deleteSectionOpen(chart, i, 'chart', 'delete')"><i class="material-icons">highlight_off</i>-->
<!-- </button>-->
<!-- <button [disabled]="editing || chart.defaultId " class="md-btn md-btn-mini"-->
<!-- [title]="(chart.defaultId?'Default sections cannot be deleted':'Delete section and disconnect related')"-->
<!-- (click)="deleteSectionOpen(chart, i, 'chart', 'disconnect')"><i class="material-icons">link_off</i>-->
<!-- </button>-->
<!-- </ng-container>-->
</div> </div>
</div> </div>
<div *ngIf="chartSections.at(i)" <div *ngIf="chartSections.at(i)"
@ -187,7 +167,6 @@
<img class="uk-width-1-1 uk-blend-multiply" [ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')" <img class="uk-width-1-1 uk-blend-multiply" [ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')"
[src]="indicator.indicatorPaths[0].url"> [src]="indicator.indicatorPaths[0].url">
</div> </div>
<!--<ng-container *ngTemplateOutlet="description; context: {indicator:indicator}"></ng-container>-->
</div> </div>
</div> </div>
</div> </div>
@ -219,13 +198,16 @@
</div> </div>
</div> </div>
</div> </div>
<div *ngIf="loading" class="uk-position-relative uk-height-large">
<loading class="uk-position-center"></loading>
</div>
<modal-alert #editNumberModal <modal-alert #editNumberModal
[large]="true" classTitle="uk-background-primary uk-light" [large]="true" classTitle="uk-background-primary uk-light"
(alertOutput)="saveIndicator()" (alertOutput)="saveIndicator()"
[okDisabled]="numberIndicatorFb && (numberIndicatorFb.invalid || numberIndicatorFb.pristine)"> [okDisabled]="numberIndicatorFb && (numberIndicatorFb.invalid || numberIndicatorFb.pristine)">
<div *ngIf="editing" class="uk-position-relative uk-height-large"> <div *ngIf="editing" class="uk-position-relative uk-height-large">
<loading class="uk-position-center"></loading> <loading class="uk-position-center"></loading>
</div> </div>
<div [class.uk-hidden]="editing" class="uk-padding-small"> <div [class.uk-hidden]="editing" class="uk-padding-small">
<div *ngIf="numberIndicatorFb" class="uk-grid" [formGroup]="numberIndicatorFb" uk-grid> <div *ngIf="numberIndicatorFb" class="uk-grid" [formGroup]="numberIndicatorFb" uk-grid>
<div input class="uk-width-1-1" [formInput]="numberIndicatorFb.get('name')" placeholder="Title"></div> <div input class="uk-width-1-1" [formInput]="numberIndicatorFb.get('name')" placeholder="Title"></div>
@ -440,8 +422,6 @@
<iframe *ngIf="indicator.indicatorPaths[i].source !== 'image'" [class.uk-blend-multiply]="!isFullscreen" <iframe *ngIf="indicator.indicatorPaths[i].source !== 'image'" [class.uk-blend-multiply]="!isFullscreen"
[src]="indicator.indicatorPaths[i].safeResourceUrl" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" [src]="indicator.indicatorPaths[i].safeResourceUrl" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"
class="uk-width-1-1 uk-height-large"></iframe> class="uk-width-1-1 uk-height-large"></iframe>
<!-- <div *ngIf="properties.disableFrameLoad && indicator.indicatorPaths[i].source !== 'image'" class="uk-alert uk-alert-danger uk-text-center">I frames-->
<!-- preview is disabled</div>-->
<div *ngIf="indicator.indicatorPaths[i].source === 'image'"> <div *ngIf="indicator.indicatorPaths[i].source === 'image'">
<img class="uk-width-1-1 uk-height-large uk-blend-multiply" [src]="indicator.indicatorPaths[i].url"> <img class="uk-width-1-1 uk-height-large uk-blend-multiply" [src]="indicator.indicatorPaths[i].url">
</div> </div>
@ -462,25 +442,10 @@
<div *ngIf="indicatorChildrenActionOnDelete == 'delete'" class="uk-text-bold"> <div *ngIf="indicatorChildrenActionOnDelete == 'delete'" class="uk-text-bold">
Indicators of all profiles based on this default indicator, will be deleted as well. Indicators of all profiles based on this default indicator, will be deleted as well.
</div> </div>
<!-- <span *ngIf="indicatorChildrenActionOnDelete == 'disconnect'" class="uk-text-bold">-->
<!-- Indicators of all profiles based on this default indicator, will not be marked as copied from default anymore.-->
<!-- </span>-->
Are you sure you want to proceed? Are you sure you want to proceed?
<div #deleteNotify notify-form class="uk-width-1-1 uk-margin-medium-top"></div> <div #deleteNotify notify-form class="uk-width-1-1 uk-margin-medium-top"></div>
</div> </div>
</modal-alert> </modal-alert>
<!--<modal-alert #deleteAllModal (alertOutput)="deleteIndicator('delete')">
You are about to delete <span class="uk-text-bold" *ngIf="indicator && index !== -1">
"{{indicator.name ? indicator.name : indicator.indicatorPaths[0].parameters.title}}"</span> indicator permanently.
<span class="uk-text-bold">Indicators of all profiles based on this default indicator, will be deleted as well.</span>
Are you sure you want to proceed?
</modal-alert>
<modal-alert #deleteAndDisconnectModal (alertOutput)="deleteIndicator('disconnect')">
You are about to delete <span class="uk-text-bold" *ngIf="indicator && index !== -1">
"{{indicator.name ? indicator.name : indicator.indicatorPaths[0].parameters.title}}"</span> indicator permanently.
<span class="uk-text-bold">Indicators of all profiles based on this default indicator, will not be marked as copied from default anymore.</span>
Are you sure you want to proceed?
</modal-alert>-->
<modal-alert #deleteSectionModal (alertOutput)="deleteSection()" [overflowBody]="false" classTitle="uk-background-primary uk-light"> <modal-alert #deleteSectionModal (alertOutput)="deleteSection()" [overflowBody]="false" classTitle="uk-background-primary uk-light">
<div [class.uk-invisible]="editing" class="uk-position-relative"> <div [class.uk-invisible]="editing" class="uk-position-relative">
<div *ngIf="editing"> <div *ngIf="editing">
@ -490,20 +455,9 @@
<div *ngIf="sectionChildrenActionOnDelete == 'delete' && !stakeholder.defaultId" class="uk-text-bold"> <div *ngIf="sectionChildrenActionOnDelete == 'delete' && !stakeholder.defaultId" class="uk-text-bold">
Sections of all profiles based on this default section and their contents, will be deleted as well. Sections of all profiles based on this default section and their contents, will be deleted as well.
</div> </div>
<!-- <span *ngIf="sectionChildrenActionOnDelete == 'disconnect'" class="uk-text-bold">-->
<!-- Sections of all profiles based on this default section and their contents, will not be marked as copied from default anymore.-->
<!-- </span>-->
Are you sure you want to proceed? Are you sure you want to proceed?
</div> </div>
</modal-alert> </modal-alert>
<!--<modal-alert #deleteNumberSectionModal (alertOutput)="deleteSection('number')">
You are about to delete this section and its indicators permanently.
Are you sure you want to proceed?
</modal-alert>
<modal-alert #deleteChartSectionModal (alertOutput)="deleteSection()">
You are about to delete this section and its indicators permanently.
Are you sure you want to proceed?
</modal-alert>-->
<ng-template #new_section let-type="type"> <ng-template #new_section let-type="type">
<div class="section"> <div class="section">
<div class="uk-flex uk-flex-center" (click)="createSection(-1, type)"> <div class="uk-flex uk-flex-center" (click)="createSection(-1, type)">

View File

@ -86,8 +86,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
public safeUrls: Map<string, SafeResourceUrl> = new Map<string, SafeResourceUrl>([]); public safeUrls: Map<string, SafeResourceUrl> = new Map<string, SafeResourceUrl>([]);
public numberResponses: Map<string, any> = new Map<string, any>(); public numberResponses: Map<string, any> = new Map<string, any>();
public numberResults: Map<string, number> = new Map<string, number>(); public numberResults: Map<string, number> = new Map<string, number>();
/** Import / Export Indicators */ public loading: boolean = false;
importLoading: boolean = false;
@ViewChild('editChartModal', {static: true}) editChartModal: AlertModal; @ViewChild('editChartModal', {static: true}) editChartModal: AlertModal;
@ViewChild('editNumberModal', {static: true}) editNumberModal: AlertModal; @ViewChild('editNumberModal', {static: true}) editNumberModal: AlertModal;
@ViewChild('deleteModal', {static: true}) deleteModal: AlertModal; @ViewChild('deleteModal', {static: true}) deleteModal: AlertModal;
@ -354,7 +353,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
return this.stakeholder && return this.stakeholder &&
this.stakeholder.topics[this.topicIndex] && this.stakeholder.topics[this.topicIndex] &&
this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] &&
this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]; this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex] && !this.loading;
} }
public get numberIndicatorPaths(): UntypedFormArray { public get numberIndicatorPaths(): UntypedFormArray {
@ -504,16 +503,6 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
this.numberIndicatorPaths.at(index).get('result').setValue(null); this.numberIndicatorPaths.at(index).get('result').setValue(null);
if (this.numberIndicatorPaths.at(index).get('url').valid) { if (this.numberIndicatorPaths.at(index).get('url').valid) {
let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByNumberUrl(this.indicatorUtils.getNumberSource(value), value, this.stakeholder, this.numberIndicatorPaths.at(index).get('jsonPath').value, this.indicatorUtils.numberSources.get(this.indicatorUtils.getNumberSource(value))); let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByNumberUrl(this.indicatorUtils.getNumberSource(value), value, this.stakeholder, this.numberIndicatorPaths.at(index).get('jsonPath').value, this.indicatorUtils.numberSources.get(this.indicatorUtils.getNumberSource(value)));
if (!this.isStakeholderParametersValid(indicatorPath)) {
// default profile
if (this.stakeholder.defaultId == null) {
this.urlParameterizedMessage = "This indicator couldn't be generated properly. Stakeholders based on this profile may not inherit the data correctly."
} else {
this.urlParameterizedMessage = "This indicator couldn't be generated properly. Please make sure chart data is for the current stakeholder."
}
} else {
this.urlParameterizedMessage = null;
}
this.checkForSchemaEnhancements(this.numberIndicatorPaths.at(index).get('url').value); this.checkForSchemaEnhancements(this.numberIndicatorPaths.at(index).get('url').value);
if (this.indicator.indicatorPaths[index]) { if (this.indicator.indicatorPaths[index]) {
this.indicator.indicatorPaths[index] = indicatorPath; this.indicator.indicatorPaths[index] = indicatorPath;
@ -574,16 +563,6 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
this.urlSubscriptions.push(this.chartIndicatorPaths.at(index).get('url').valueChanges.subscribe(value => { this.urlSubscriptions.push(this.chartIndicatorPaths.at(index).get('url').valueChanges.subscribe(value => {
if (this.chartIndicatorPaths.at(index).get('url').valid) { if (this.chartIndicatorPaths.at(index).get('url').valid) {
let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.indicatorUtils.getChartSource(value), value, this.chartIndicatorPaths.at(index).get('type').value, this.stakeholder); let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.indicatorUtils.getChartSource(value), value, this.chartIndicatorPaths.at(index).get('type').value, this.stakeholder);
if (!this.isStakeholderParametersValid(indicatorPath)) {
// default profile
if (this.stakeholder.defaultId == null) {
this.urlParameterizedMessage = "This chart couldn't be generated properly. Stakeholders based on this profile may not inherit the data correctly."
} else {
this.urlParameterizedMessage = "This chart couldn't be generated properly. Please make sure chart data is for the current stakeholder."
}
} else {
this.urlParameterizedMessage = null;
}
this.checkForSchemaEnhancements(this.chartIndicatorPaths.at(index).get('url').value); this.checkForSchemaEnhancements(this.chartIndicatorPaths.at(index).get('url').value);
(this.chartIndicatorPaths.at(index) as UntypedFormGroup).get('type').setValue(indicatorPath.type); (this.chartIndicatorPaths.at(index) as UntypedFormGroup).get('type').setValue(indicatorPath.type);
(this.chartIndicatorPaths.at(index) as UntypedFormGroup).setControl('parameters', this.getParametersAsFormArray(indicatorPath)); (this.chartIndicatorPaths.at(index) as UntypedFormGroup).setControl('parameters', this.getParametersAsFormArray(indicatorPath));
@ -601,12 +580,6 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
} }
} }
private isStakeholderParametersValid(indicatorPath: IndicatorPath) {
return !((indicatorPath.chartObject && Object.keys(indicatorPath.parameters).indexOf("index_id") == -1 && Object.keys(indicatorPath.parameters).indexOf("index_name") == -1 && Object.keys(indicatorPath.parameters).indexOf("index_shortName") == -1)
|| (!indicatorPath.chartObject && indicatorPath.url.indexOf("index_id") == -1 && indicatorPath.url.indexOf("index_name") == -1 && (indicatorPath.url).indexOf("index_shortName") == -1));
}
private getJsonPathAsFormArray(indicatorPath: IndicatorPath): UntypedFormArray { private getJsonPathAsFormArray(indicatorPath: IndicatorPath): UntypedFormArray {
let jsonPath = this.fb.array([]); let jsonPath = this.fb.array([]);
if (indicatorPath.jsonPath) { if (indicatorPath.jsonPath) {
@ -900,19 +873,22 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
}); });
} }
} }
this.editing = false; this.finish();
this.importLoading = false;
NotificationHandler.rise('Indicators have been <b>imported</b> successfully!'); NotificationHandler.rise('Indicators have been <b>imported</b> successfully!');
}, error => { }, error => {
this.chartIndicatorFb = null; this.chartIndicatorFb = null;
NotificationHandler.rise('An error has occurred. Please try again later', 'danger'); NotificationHandler.rise('An error has occurred. Please try again later', 'danger');
this.editing = false; this.finish();
this.importLoading = false;
})); }));
} }
finish() {
this.editing = false;
this.loading = false;
}
reorderIndicators(sectionId: string, type: IndicatorType, reorder: Reorder) { reorderIndicators(sectionId: string, type: IndicatorType, reorder: Reorder) {
this.editing = true; this.editing = true;
let path = [ let path = [
@ -1159,24 +1135,6 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
})); }));
} }
// deleteNumberSectionOpen(section: Section, index: number) {
// this.section = section;
// this.index = index;
// this.deleteNumberSectionModal.alertTitle = 'Delete Section';
// this.deleteNumberSectionModal.cancelButtonText = 'No';
// this.deleteNumberSectionModal.okButtonText = 'Yes';
// this.deleteNumberSectionModal.open();
// }
//
// deleteChartSectionOpen(section: Section, index: number) {
// this.section = section;
// this.index = index;
// this.deleteChartSectionModal.alertTitle = 'Delete Section';
// this.deleteChartSectionModal.cancelButtonText = 'No';
// this.deleteChartSectionModal.okButtonText = 'Yes';
// this.deleteChartSectionModal.open();
// }
deleteSectionOpen(section: Section, index: number, type: IndicatorType, childrenAction: string = null) { deleteSectionOpen(section: Section, index: number, type: IndicatorType, childrenAction: string = null) {
if (!this.editing && !section.defaultId) { if (!this.editing && !section.defaultId) {
this.sectionTypeToDelete = type; this.sectionTypeToDelete = type;
@ -1256,11 +1214,19 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
return charts; return charts;
} }
importIndicatorsAndSave(charts: any[]) { importIndicatorsAndSave(stakeholder: Stakeholder, charts: any[]) {
let sectionsToSave: Section[] = []; let sectionsToSave: Section[] = [];
let countIndicators = 0; let countIndicators = 0;
if(stakeholder.type !== this.stakeholder.type) {
UIkit.notification("The type of this profile is not the same with the file's one!", {
status: 'warning',
timeout: 6000,
pos: 'bottom-right'
});
this.finish();
return;
}
// name description additionalDescription, height, width, visibility // name description additionalDescription, height, width, visibility
let noValidParams = 0;
let duplicates = 0; let duplicates = 0;
charts = this.migrateFromOldImportJsonFile(charts); charts = this.migrateFromOldImportJsonFile(charts);
for (let chart of charts) { for (let chart of charts) {
@ -1290,13 +1256,12 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
timeout: 6000, timeout: 6000,
pos: 'bottom-right' pos: 'bottom-right'
}); });
this.editing = false; this.finish();
this.importLoading = false;
break; break;
} }
if (chart.type == "chart") { if (chart.type == "chart") {
indicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.indicatorUtils.getChartSource(chart.url), chart.url, chart.type, this.stakeholder); indicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.indicatorUtils.getChartSource(chart.url), chart.url, chart.type, stakeholder);
for (let section of this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index].charts) { for (let section of this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index].charts) {
for (let chart of section.indicators) { for (let chart of section.indicators) {
if (JSON.stringify(chart.indicatorPaths[0].chartObject) == JSON.stringify(indicatorPath.chartObject)) { if (JSON.stringify(chart.indicatorPaths[0].chartObject) == JSON.stringify(indicatorPath.chartObject)) {
@ -1304,10 +1269,9 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
exists = true; exists = true;
} }
} }
} }
} else if (chart.type == "number") { } else if (chart.type == "number") {
indicatorPath = this.indicatorUtils.generateIndicatorByNumberUrl(this.indicatorUtils.getNumberSource(chart.url), chart.url, this.stakeholder, indicatorPath = this.indicatorUtils.generateIndicatorByNumberUrl(this.indicatorUtils.getNumberSource(chart.url), chart.url, stakeholder,
chart.jsonPath, this.indicatorUtils.numberSources.get(this.indicatorUtils.getNumberSource(chart.url))); chart.jsonPath, this.indicatorUtils.numberSources.get(this.indicatorUtils.getNumberSource(chart.url)));
for (let section of this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index].numbers) { for (let section of this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index].numbers) {
for (let chart of section.indicators) { for (let chart of section.indicators) {
@ -1316,20 +1280,14 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
exists = true; exists = true;
} }
} }
} }
} }
if (!this.isStakeholderParametersValid(indicatorPath)) {
noValidParams++;
}
if (!exists) { if (!exists) {
let i: Indicator = new Indicator(chart.name, chart.description, chart.additionalDescription, chart.type, chart.width, chart.height, this.showVisibility?"RESTRICTED":this.stakeholderUtils.defaultValue(this.stakeholderUtils.visibilities), [indicatorPath]); let i: Indicator = new Indicator(chart.name, chart.description, chart.additionalDescription, chart.type, chart.width, chart.height, this.showVisibility?"RESTRICTED":this.stakeholderUtils.defaultValue(this.stakeholderUtils.visibilities), [indicatorPath]);
sectionsToSave[chart['sectionIndex']].indicators.push(i); sectionsToSave[chart['sectionIndex']].indicators.push(i);
countIndicators++; countIndicators++;
} }
} }
if (duplicates > 0) { if (duplicates > 0) {
UIkit.notification(duplicates + " urls already exist and will not be imported!", { UIkit.notification(duplicates + " urls already exist and will not be imported!", {
status: 'warning', status: 'warning',
@ -1337,19 +1295,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
pos: 'bottom-right' pos: 'bottom-right'
}); });
} }
if (noValidParams > 0 && !(this.stakeholder.type == 'country')) { if (sectionsToSave.length > 0 && countIndicators > 0) {
let noValidMessage = "Some indicators couldn't be generated properly. Please make sure chart data is for the current stakeholder.";
if (this.stakeholder.defaultId == null) {
noValidMessage = "Some indicators couldn't be generated properly. Stakeholders based on this profile may not inherit the data correctly.";
}
UIkit.notification(noValidMessage, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
this.editing = false;
this.importLoading = false;
} else if (sectionsToSave.length > 0 && countIndicators > 0) {
this.saveIndicators(sectionsToSave.filter(section => !!section)); this.saveIndicators(sectionsToSave.filter(section => !!section));
} }
if (sectionsToSave.length == 0 || countIndicators == 0) { if (sectionsToSave.length == 0 || countIndicators == 0) {
@ -1358,8 +1304,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
timeout: 6000, timeout: 6000,
pos: 'bottom-right' pos: 'bottom-right'
}); });
this.editing = false; this.finish();
this.importLoading = false;
} }
} }
@ -1408,8 +1353,12 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
let topic = this.stakeholder ? this.stakeholder.topics[this.topicIndex] : null; let topic = this.stakeholder ? this.stakeholder.topics[this.topicIndex] : null;
let category = topic ? topic.categories[this.categoryIndex] : null; let category = topic ? topic.categories[this.categoryIndex] : null;
let subCategory = category ? category.subCategories[subcategoryIndex] : null; let subCategory = category ? category.subCategories[subcategoryIndex] : null;
let json = {
var jsonFileUrl = window.URL.createObjectURL(new Blob([JSON.stringify(indicators)], {type: 'application/json'})); stakeholder: HelperFunctions.copy(this.stakeholder),
indicators: indicators
}
delete json.stakeholder.topics;
var jsonFileUrl = window.URL.createObjectURL(new Blob([JSON.stringify(json)], {type: 'application/json'}));
var a = window.document.createElement('a'); var a = window.document.createElement('a');
window.document.body.appendChild(a); window.document.body.appendChild(a);
a.setAttribute('style', 'display: none'); a.setAttribute('style', 'display: none');
@ -1418,14 +1367,13 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
a.click(); a.click();
window.URL.revokeObjectURL(jsonFileUrl); window.URL.revokeObjectURL(jsonFileUrl);
a.remove(); // remove the element a.remove(); // remove the element
this.finish();
this.editing = false;
} }
fileChangeEvent(fileInput: any, index) { fileChangeEvent(fileInput: any, index) {
this.index = index; this.index = index;
this.editing = true; this.editing = true;
this.importLoading = true; this.loading = true;
this.filesToUpload = <Array<File>>fileInput.target.files; this.filesToUpload = <Array<File>>fileInput.target.files;
this.upload(); this.upload();
} }
@ -1438,8 +1386,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
timeout: 6000, timeout: 6000,
pos: 'bottom-right' pos: 'bottom-right'
}); });
this.editing = false; this.finish();
this.importLoading = false;
return; return;
} else { } else {
if (this.filesToUpload[0].name.indexOf(".json") == -1 || (this.filesToUpload[0].type != "application/json")) { if (this.filesToUpload[0].name.indexOf(".json") == -1 || (this.filesToUpload[0].type != "application/json")) {
@ -1449,27 +1396,30 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
timeout: 6000, timeout: 6000,
pos: 'bottom-right' pos: 'bottom-right'
}); });
this.editing = false; this.finish();
this.importLoading = false;
return; return;
} }
} }
this.makeFileRequest(this.properties.utilsService + '/upload?type=json', [], this.filesToUpload).then(async (result: string) => { this.makeFileRequest(this.properties.utilsService + '/upload?type=json', [], this.filesToUpload).then(async (result: string) => {
let json = JSON.parse(result);
let json_result = JSON.parse(result);
// validate file // validate file
if (!json_result || json_result.length == 0) { if(json && Array.isArray(json)) {
UIkit.notification("This file is not supported any more. Please export indicators and try again!", {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
this.finish();
} else if (!json || json?.indicators.length == 0) {
UIkit.notification("Importing file is empty", { UIkit.notification("Importing file is empty", {
status: 'danger', status: 'danger',
timeout: 6000, timeout: 6000,
pos: 'bottom-right' pos: 'bottom-right'
}); });
this.editing = false; this.finish();
this.importLoading = false;
} else { } else {
this.importIndicatorsAndSave(json_result); this.importIndicatorsAndSave(json.stakeholder, json.indicators);
} }
}, (error) => { }, (error) => {
console.error("Error importing files", error); console.error("Error importing files", error);
@ -1478,8 +1428,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
timeout: 6000, timeout: 6000,
pos: 'bottom-right' pos: 'bottom-right'
}); });
this.editing = false; this.finish();
this.importLoading = false;
}); });
} }

View File

@ -6,15 +6,15 @@ import {RouterModule} from '@angular/router';
import {ResultPreviewModule} from "../../utils/result-preview/result-preview.module"; import {ResultPreviewModule} from "../../utils/result-preview/result-preview.module";
import {ErrorMessagesModule} from "../../utils/errorMessages.module"; import {ErrorMessagesModule} from "../../utils/errorMessages.module";
import {searcMyOrcidResultsComponent} from "./searchMyOrcidResults.component"; import {searcMyOrcidResultsComponent} from "./searchMyOrcidResults.component";
import {OrcidModule} from "../orcid.module";
import {NoLoadPaging} from "../../searchPages/searchUtils/no-load-paging.module"; import {NoLoadPaging} from "../../searchPages/searchUtils/no-load-paging.module";
import {PagingModule} from "../../utils/paging.module"; import {PagingModule} from "../../utils/paging.module";
import {OrcidCoreModule} from "../orcid-core.module";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, FormsModule, CommonModule, FormsModule,
RouterModule, ErrorMessagesModule, RouterModule, ErrorMessagesModule,
ResultPreviewModule, OrcidModule, NoLoadPaging, PagingModule ResultPreviewModule, OrcidCoreModule, NoLoadPaging, PagingModule
], ],
declarations: [ declarations: [
searcMyOrcidResultsComponent searcMyOrcidResultsComponent

View File

@ -0,0 +1,43 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {RouterModule} from '@angular/router';
import {OrcidComponent} from './orcid.component';
import {OrcidService} from './orcid.service';
import {OrcidWorkComponent} from './orcid-work.component';
import {AlertModalModule} from '../utils/modal/alertModal.module';
import {ResultLandingService} from '../landingPages/result/resultLanding.service';
import {LoadingModule} from '../utils/loading/loading.module';
import {ResultLandingUtilsModule} from '../landingPages/landing-utils/resultLandingUtils.module';
import {IconsModule} from '../utils/icons/icons.module';
import {IconsService} from "../utils/icons/icons.service";
import {orcid_add, orcid_bin} from "../utils/icons/icons";
import {FullScreenModalModule} from "../utils/modal/full-screen-modal/full-screen-modal.module";
import {LogServiceModule} from "../utils/log/LogService.module";
import {OrcidRoutingModule} from "./orcid-routing.module";
@NgModule({
imports: [
CommonModule, RouterModule, AlertModalModule, LoadingModule, ResultLandingUtilsModule,
IconsModule, FullScreenModalModule, LogServiceModule
],
declarations: [
OrcidComponent,
OrcidWorkComponent
],
providers:[
OrcidService, ResultLandingService
],
exports: [
OrcidComponent,
OrcidWorkComponent
]
})
export class OrcidCoreModule{
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([orcid_add, orcid_bin])
}
}

View File

@ -1,43 +1,15 @@
import {NgModule} from '@angular/core'; import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {RouterModule} from '@angular/router';
import {OrcidComponent} from './orcid.component';
import {OrcidService} from './orcid.service';
import {OrcidWorkComponent} from './orcid-work.component';
import {AlertModalModule} from '../utils/modal/alertModal.module';
import {ResultLandingService} from '../landingPages/result/resultLanding.service';
import {LoadingModule} from '../utils/loading/loading.module';
import {ResultLandingUtilsModule} from '../landingPages/landing-utils/resultLandingUtils.module';
import {IconsModule} from '../utils/icons/icons.module';
import {IconsService} from "../utils/icons/icons.service"; import {IconsService} from "../utils/icons/icons.service";
import {orcid_add, orcid_bin} from "../utils/icons/icons"; import {orcid_add, orcid_bin} from "../utils/icons/icons";
import {FullScreenModalModule} from "../utils/modal/full-screen-modal/full-screen-modal.module";
import {LogServiceModule} from "../utils/log/LogService.module";
import {OrcidRoutingModule} from "./orcid-routing.module"; import {OrcidRoutingModule} from "./orcid-routing.module";
import {OrcidCoreModule} from "./orcid-core.module";
import {OrcidComponent} from "./orcid.component";
@NgModule({ @NgModule({
imports: [ imports: [OrcidCoreModule, OrcidRoutingModule],
CommonModule, RouterModule, OrcidRoutingModule, AlertModalModule, LoadingModule, ResultLandingUtilsModule, exports: [OrcidComponent]
IconsModule, FullScreenModalModule, LogServiceModule
],
declarations: [
OrcidComponent,
OrcidWorkComponent
],
providers:[
OrcidService, ResultLandingService
],
exports: [
OrcidComponent,
OrcidWorkComponent
]
}) })
export class OrcidModule{ export class OrcidModule{
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([orcid_add, orcid_bin])
}
} }

View File

@ -93,6 +93,8 @@ export class RoleVerificationComponent extends BaseComponent implements OnInit,
public userInfoLinkPrefix = ''; public userInfoLinkPrefix = '';
@Input() @Input()
public userInfoLink = null; public userInfoLink = null;
@Input()
public relativeTo: ActivatedRoute = this._route;
public user: User; public user: User;
public verification: any; public verification: any;
public code: UntypedFormControl; public code: UntypedFormControl;
@ -150,7 +152,7 @@ export class RoleVerificationComponent extends BaseComponent implements OnInit,
'errorCode': LoginErrorCodes.NOT_LOGIN, 'errorCode': LoginErrorCodes.NOT_LOGIN,
'redirectUrl': this._router.url 'redirectUrl': this._router.url
}, },
relativeTo: this._route relativeTo: this.relativeTo
}); });
} }
} else if(this.isMember) { } else if(this.isMember) {

View File

@ -133,7 +133,14 @@ export class SearchResearchResultsService {
return this.http.get((properties.useLongCache && size == 0 && !params && (!refineQuery || !refineQuery.includes("fq="))) ? (properties.cacheUrl + encodeURIComponent(url)) : url) return this.http.get((properties.useLongCache && size == 0 && !params && (!refineQuery || !refineQuery.includes("fq="))) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => [res['meta'].total, this.parseResults(resultType, res['results'], properties), RefineResultsUtils.parse(res['refineResults'], refineFields, "publication")])); .pipe(map(res => [res['meta'].total, this.parseResults(resultType, res['results'], properties), RefineResultsUtils.parse(res['refineResults'], refineFields, "publication")]));
} }
countResults(field:string,value:string): any {
let url = properties.utilsService + "/portals/countResults";
if (field && value) {
url += "?field=" + encodeURIComponent(field) + "&value="+encodeURIComponent(value);
}
return this.http.get((properties.useLongCache ) ? (properties.cacheUrl + encodeURIComponent(url)) : url);
}
searchResultForEntity(resultType: string, params: string, page: number, size: number, properties: EnvProperties): any { searchResultForEntity(resultType: string, params: string, page: number, size: number, properties: EnvProperties): any {
let link = properties.searchAPIURLLAst; let link = properties.searchAPIURLLAst;
//let url = link+params+"/"+this.getEntityQueryName(resultType,true)+ "?format=json"; //let url = link+params+"/"+this.getEntityQueryName(resultType,true)+ "?format=json";

View File

@ -23,10 +23,11 @@ export class MenuItem {
isFeatured: boolean; isFeatured: boolean;
isActive: boolean; isActive: boolean;
target: string = "_blank"; target: string = "_blank";
badge?: string = ""; // used only for RDGraph portal (FAIRCORE4EOSC)
constructor(id: string, title: string, url: string, route: string, needsAuthorization: boolean, entitiesRequired: string[], constructor(id: string, title: string, url: string, route: string, needsAuthorization: boolean, entitiesRequired: string[],
routeRequired: string[], params, icon: Icon = null, fragment = null, customClass = null, routeActive = null, routeRequired: string[], params, icon: Icon = null, fragment = null, customClass = null, routeActive = null,
target: string = "_blank", type: string = "internal", isFeatured: boolean = false, items: MenuItem[] = []) { target: string = "_blank", type: string = "internal", isFeatured: boolean = false, items: MenuItem[] = [], badge: string = "") {
this._id = id; this._id = id;
this.title = title; this.title = title;
this.url = url; this.url = url;
@ -43,6 +44,7 @@ export class MenuItem {
this.target = target; this.target = target;
this.type = type; this.type = type;
this.isFeatured = isFeatured; this.isFeatured = isFeatured;
this.badge = badge;
} }
public static isTheActiveMenu(menu: MenuItem, currentRoute: any, activeMenuItem: string = ""): boolean { public static isTheActiveMenu(menu: MenuItem, currentRoute: any, activeMenuItem: string = ""): boolean {

View File

@ -41,7 +41,9 @@
<a *ngIf="!menu.url" [routerLink]="menu.route && (isEnabled([menu.route], showPage) || !menu.routeRequired) && menu.items.length === 0?menu.route:null" <a *ngIf="!menu.url" [routerLink]="menu.route && (isEnabled([menu.route], showPage) || !menu.routeRequired) && menu.items.length === 0?menu.route:null"
(click)="menu.items.length === 0?closeCanvas(canvas):null" (click)="menu.items.length === 0?closeCanvas(canvas):null"
[queryParams]="menu.params" [queryParams]="menu.params"
[fragment]="menu.fragment">{{menu.title}}<span *ngIf="menu.items.length > 0" class="uk-nav-parent-icon"></span></a> [fragment]="menu.fragment">
<span *ngIf="menu.badge" style="position: relative"><span class="badge-mobile">{{menu.badge}}</span></span>
{{menu.title}}<span *ngIf="menu.items.length > 0" class="uk-nav-parent-icon"></span></a>
<a *ngIf="menu.url" <a *ngIf="menu.url"
(click)="menu.items.length === 0?closeCanvas(canvas):null" (click)="menu.items.length === 0?closeCanvas(canvas):null"
[href]="menu.items.length === 0?menu.url:null" [href]="menu.items.length === 0?menu.url:null"
@ -215,7 +217,9 @@
<a *ngIf="menu.route.length == 0 && menu.url.length > 0" <a *ngIf="menu.route.length == 0 && menu.url.length > 0"
href="{{menu.url}}" target="{{menu.target}}" href="{{menu.url}}" target="{{menu.target}}"
[class.custom-external]="menu.target != '_self'">{{menu.title}}</a> [class.custom-external]="menu.target != '_self'">{{menu.title}}</a>
<a *ngIf="(menu.route.length == 0 && menu.url.length == 0) || ( menu.route.length >0 && menu.routeRequired && !isEnabled([menu.route], showPage) && isAtleastOneEnabled(menu.routeRequired, showPage))">{{menu.title}}</a> <a *ngIf="(menu.route.length == 0 && menu.url.length == 0) || ( menu.route.length >0 && menu.routeRequired && !isEnabled([menu.route], showPage) && isAtleastOneEnabled(menu.routeRequired, showPage))">
<span *ngIf="menu.badge" class="badge">{{menu.badge}}</span>
{{menu.title}}</a>
<div *ngIf="menu.items.length > 0" class="uk-navbar-dropdown uk-navbar-dropdown-bottom-left uk-height-max-medium uk-overflow-auto"> <div *ngIf="menu.items.length > 0" class="uk-navbar-dropdown uk-navbar-dropdown-bottom-left uk-height-max-medium uk-overflow-auto">
<!-- Do not delete this div, because it will remove the margin bottom of navbar --> <!-- Do not delete this div, because it will remove the margin bottom of navbar -->
<div> <div>

View File

@ -6,11 +6,14 @@ import {
ElementRef, EventEmitter, ElementRef, EventEmitter,
Input, OnDestroy, Output, Input, OnDestroy, Output,
QueryList, QueryList,
ViewChild ViewChild,
Inject,
PLATFORM_ID
} from "@angular/core"; } from "@angular/core";
import {SliderTabComponent} from "./slider-tab.component"; import {SliderTabComponent} from "./slider-tab.component";
import {ActivatedRoute, Router} from "@angular/router"; import {ActivatedRoute, Router} from "@angular/router";
import {Subscription} from "rxjs"; import {Subscription} from "rxjs";
import {isPlatformServer} from "@angular/common";
import Timeout = NodeJS.Timeout; import Timeout = NodeJS.Timeout;
declare var UIkit; declare var UIkit;
@ -20,7 +23,7 @@ declare var UIkit;
template: ` template: `
<div #sliderElement class="uk-position-relative" [class.uk-slider]="position === 'horizontal'" <div #sliderElement class="uk-position-relative" [class.uk-slider]="position === 'horizontal'"
[ngClass]="customClass"> [ngClass]="customClass">
<div [class.uk-slider-container-tabs]="position === 'horizontal'" [class.uk-border-bottom]="border && position === 'horizontal'"> <div [class.uk-slider-container-tabs]="position === 'horizontal'" [class.uk-border-bottom]="border && position === 'horizontal'" [ngClass]="containerClass">
<ul #tabsElement [class.uk-flex-nowrap]="position === 'horizontal'" <ul #tabsElement [class.uk-flex-nowrap]="position === 'horizontal'"
[class.uk-slider-items]="position === 'horizontal'" [class.uk-slider-items]="position === 'horizontal'"
[class.uk-tab-left]="position === 'left'" [class.uk-tab-right]="position === 'right'" [class.uk-tab-left]="position === 'left'" [class.uk-tab-right]="position === 'right'"
@ -78,8 +81,10 @@ declare var UIkit;
</ng-container> </ng-container>
</ul> </ul>
</div> </div>
<slider-arrow *ngIf="position === 'horizontal' && arrows" type="previous"></slider-arrow> <ng-container *ngIf="!isServer">
<slider-arrow *ngIf="position === 'horizontal' && arrows" type="next"></slider-arrow> <slider-arrow *ngIf="position === 'horizontal' && arrows" type="previous"></slider-arrow>
<slider-arrow *ngIf="position === 'horizontal' && arrows" type="next"></slider-arrow>
</ng-container>
</div> </div>
`, `,
}) })
@ -112,6 +117,11 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
* */ * */
@Input() @Input()
public flexPosition: 'center' | 'left' | 'right' = 'left'; public flexPosition: 'center' | 'left' | 'right' = 'left';
/**
* Set a class for the container
* */
@Input()
public containerClass: string;
/** /**
* Set a class above tabs * Set a class above tabs
* */ * */
@ -138,10 +148,13 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
private subscriptions: any[] = []; private subscriptions: any[] = [];
private observer: IntersectionObserver; private observer: IntersectionObserver;
private timeout: Timeout; private timeout: Timeout;
isServer: boolean;
constructor(private route: ActivatedRoute, constructor(private route: ActivatedRoute,
private router: Router, private router: Router,
private cdr: ChangeDetectorRef) { private cdr: ChangeDetectorRef,
@Inject(PLATFORM_ID) private platform: any) {
this.isServer = isPlatformServer(this.platform);
} }
ngAfterViewInit() { ngAfterViewInit() {
@ -164,7 +177,7 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
} }
}); });
if (this.type === 'static') { if (this.type === 'static') {
let tabs = UIkit.tab(this.tabsElement.nativeElement, {connect: this.connect}); let tabs = UIkit.switcher(this.tabsElement.nativeElement, {connect: this.connect});
tabs.show(this.activeIndex); tabs.show(this.activeIndex);
if (this.connect.includes('#')) { if (this.connect.includes('#')) {
this.scrollToStart(); this.scrollToStart();

View File

@ -333,6 +333,14 @@ export class SearchFieldsBase {
operator: "pf", operator: "pf",
equalityOperator: " = ", equalityOperator: " = ",
filterType: "triplet" filterType: "triplet"
},
["haslicense"]: {
name: "License",
type: "triplet",
param: "haslicense",
operator: "hl",
equalityOperator: " = ",
filterType: "triplet"
} }
}; };
@ -369,6 +377,11 @@ export class SearchFieldsBase {
{ name: "All", id: "", count: "0" }, { name: "All", id: "", count: "0" },
{ name: "Yes", id: "true", count: "0" }, { name: "Yes", id: "true", count: "0" },
{ name: "No", id: "false", count: "0" } { name: "No", id: "false", count: "0" }
],
["haslicense"]: [
{ name: "All", id: "", count: "0" },
{ name: "Yes", id: "true", count: "0" },
{ name: "No", id: "false", count: "0" }
] ]
}; };

View File

@ -4,15 +4,15 @@ import {ResultPreviewComponent} from "./result-preview.component";
import {RouterModule} from "@angular/router"; import {RouterModule} from "@angular/router";
import {ShowAuthorsModule} from "../authors/showAuthors.module"; import {ShowAuthorsModule} from "../authors/showAuthors.module";
import {ResultLandingUtilsModule} from "../../landingPages/landing-utils/resultLandingUtils.module"; import {ResultLandingUtilsModule} from "../../landingPages/landing-utils/resultLandingUtils.module";
import {OrcidModule} from "../../orcid/orcid.module";
import {IconsModule} from "../icons/icons.module"; import {IconsModule} from "../icons/icons.module";
import {IconsService} from "../icons/icons.service"; import {IconsService} from "../icons/icons.service";
import {cite, fire, landmark, link, link_to, quotes, rocket} from "../icons/icons"; import {cite, fire, landmark, link, link_to, quotes, rocket} from "../icons/icons";
import {EntityActionsModule} from "../entity-actions/entity-actions.module"; import {EntityActionsModule} from "../entity-actions/entity-actions.module";
import {EntityMetadataModule} from "../../landingPages/landing-utils/entity-metadata.module"; import {EntityMetadataModule} from "../../landingPages/landing-utils/entity-metadata.module";
import {OrcidCoreModule} from "../../orcid/orcid-core.module";
@NgModule({ @NgModule({
imports: [CommonModule, RouterModule, ShowAuthorsModule, ResultLandingUtilsModule, OrcidModule, IconsModule, EntityActionsModule, EntityMetadataModule], imports: [CommonModule, RouterModule, ShowAuthorsModule, ResultLandingUtilsModule, OrcidCoreModule, IconsModule, EntityActionsModule, EntityMetadataModule],
declarations: [ResultPreviewComponent], declarations: [ResultPreviewComponent],
exports: [ResultPreviewComponent] exports: [ResultPreviewComponent]
}) })