Merge remote-tracking branch 'origin/develop' into dynamic-piwik

This commit is contained in:
Konstantinos Triantafyllou 2023-07-12 13:56:18 +03:00
commit 50422c0ab3
145 changed files with 8612 additions and 4451 deletions

View File

@ -49,6 +49,11 @@ export class CacheInterceptorService implements HttpInterceptor {
}
public checkForCachedRequests(url){
// Do not call cache when it is not enabled at all.
// This property is not correctly used here. A new property should be introduced. For now it is ok.
if (!properties.useLongCache) {
return false;
}
if(url.indexOf("refine=true") !== -1 || url.indexOf("/count?format=json") !== -1 || url.indexOf("relresulttype%3Dpublication") !== -1) {
return this.cachingRequests.some(partUrl => (url.indexOf(partUrl) !== -1));
}

View File

@ -1,5 +1,5 @@
<div>
<div class="uk-width-xlarge@l uk-width-large">
<div class="uk-width-xlarge@l uk-width-large" [ngClass]="centerAlign ? 'uk-align-center':''">
<advanced-search-input>
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..."
[options]="showOptions.selectOptions" class="uk-width-2-5"></div>

View File

@ -18,6 +18,7 @@ declare var UIkit: any;
})
export class ClaimContextSearchFormComponent {
@Input() public centerAlign: boolean = false;
@Input() public results:ClaimEntity[];
@Input() public sources;
@Input() public properties: EnvProperties;

View File

@ -168,7 +168,7 @@ export class ShowOptions {
this.basketShowSources = false;
}
showLinkTo() {
console.log(this.linkTo, "showLinkTo")
// console.log(this.linkTo, "showLinkTo")
this.show = this.linkTo;
this.basketswitchToLinkTo();
HelperFunctions.scroll();

View File

@ -1,4 +1,4 @@
<div class="uk-width-xlarge@l uk-width-large">
<div class="uk-width-xlarge@l uk-width-large" [ngClass]="centerAlign ? 'uk-align-center':''">
<advanced-search-input (searchEmitter)="search(page,size)">
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..."
[options]="showOptions.selectOptions" class="uk-width-2-5"></div>

View File

@ -21,6 +21,7 @@ declare var UIkit:any;
})
export class ClaimProjectsSearchFormComponent {
public query = '';
@Input() public centerAlign: boolean = false;
@Input() public selectedProjects:ClaimEntity[]=[] ;
public elementRef;

View File

@ -1,4 +1,4 @@
<div *ngIf="showOptions && showOptions.linkToEntities.length > 0" class="uk-width-xlarge@l uk-width-large">
<div *ngIf="showOptions && showOptions.linkToEntities.length > 0" class="uk-width-xlarge@l uk-width-large" [ngClass]="centerAlign ? 'uk-align-center':''">
<advanced-search-input (searchEmitter)="search(true)">
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..."
[options]="showOptions.selectOptions" class="uk-width-2-5"></div>
@ -8,7 +8,7 @@
</div>
<div *ngIf="!showOptions" class="uk-width-xlarge@l uk-width-large">
<div search-input [(value)]="keyword" [placeholder]="'Search for ' + openaireEntities.RESULTS.toLowerCase() + '...'"
(searchEmitter)="search(true)"></div>
[searchInputClass]="'inner background'" (searchEmitter)="search(true)"></div>
</div>
<div *ngIf="!showSearchResults">
<div class="uk-text-center uk-text-large uk-text-meta uk-margin-large-top">

View File

@ -23,6 +23,7 @@ export class ClaimResultSearchFormComponent {
source: string = "datacite";
type: string = "dataset";
showSearchResults: boolean = false;
@Input() public centerAlign: boolean = false;
@Input() public select: boolean = true;
@Input() public keyword: string = '';
@Input() public selectedResults: ClaimEntity[];

View File

@ -6,13 +6,9 @@ declare var UIkit: any;
@Component({
selector: 'claim-results',
template: `
<div *ngIf="results.length > 0 " class="uk-margin-top">
<div *ngFor=" let entity of results " [class]="(isSelected(entity))?'uk-block-muted':''" class=" uk-card uk-card-default uk-card-body uk-margin-bottom">
<div>
<div class="uk-text-small ">
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</div>
<div *ngFor="let entity of results" class="uk-card">
<div class="uk-padding-small">
<div class="uk-grid">
<div class="uk-width-expand uk-margin-right">
<claim-title [entity]="entity" [showIcon]="false"></claim-title>
@ -20,27 +16,29 @@ declare var UIkit: any;
<claim-project-metadata [entity]="entity"></claim-project-metadata>
</div>
<div class="uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left uk-margin-small-right" [title]="(this.selectedResults.length>=basketLimit)?'Basket reached the size limit':''">
<button class="linking-add-button" [class.uk-disabled]="(this.selectedResults.length>=basketLimit)" *ngIf="!isSelected(entity)"
<button class="linking-add-button uk-icon-button-small" [class.uk-disabled]="(this.selectedResults.length>=basketLimit)" *ngIf="!isSelected(entity)"
(click)="add(entity)">
<icon name="add" [flex]="true"></icon>
</button>
<button *ngIf="isSelected(entity)" class="linking-selected-button" (click)="remove(entity)">
<button *ngIf="isSelected(entity)" class="linking-selected-button uk-icon-button-small" (click)="remove(entity)">
<icon name="check" [flex]="true"></icon>
</button>
</div>
</div>
</div>
</div>
</div>`,
</div>
`
})
export class ClaimResultsComponent {
@Input() results: ClaimEntity[];
@Input() selectedResults: ClaimEntity[];
@Input() localStoragePrefix: string = "";
@Input() basketLimit;
ngOnInit() {
}
public isSelected(item: ClaimEntity) {
return !!this.selectedResults.find(result => item.id === result.id);
}

View File

@ -16,7 +16,7 @@
</div>
<div [class.uk-padding]="actions" class="uk-padding-remove-vertical">
<div class="uk-margin-medium-top">
<results-and-pages [type]="resultsNum !== 1?'Links':'Link'" [page]="page" [pageSize]="size"
<results-and-pages [type]="resultsNum !== 1?'Links':'Link'" [page]="page" [pageSize]="size" [hasSearch]="true" [searchTerm]="keyword"
[totalResults]="resultsNum" customClasses="uk-margin-remove"></results-and-pages>
</div>
<div class="uk-grid uk-flex-middle uk-margin-medium-top" uk-grid>

View File

@ -240,7 +240,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
handleErrors(err, message) {
NotificationHandler.rise(message, "danger");
console.error("Dispaly Claims (component): " + message + " " + (err && err.error ? err.error : ''));
console.error("Display Claims (component): " + message + " " + (err && err.error ? err.error : ''));
}
goTo(page: number = 1) {
@ -290,7 +290,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
}
changeKeyword() {
if (this.filterForm.get("keyword") && (this.filterForm.get("keyword").value.length >= 3 || this.filterForm.get("keyword").value.length == 0)) {
if (this.filterForm.get("keyword") && (this.filterForm.get("keyword").value?.length >= 3 || this.filterForm.get("keyword").value?.length == 0)) {
this.searchTermStream.next(this.filterForm.get("keyword").value);
}
}

View File

@ -50,7 +50,6 @@ export class SearchDataciteService {
static parse(response): ClaimEntity[] {
const results: ClaimEntity[] = [];
console.log(response);
for (let i = 0; i < response.length; i++) {
const item = response[i];
const entity: ClaimEntity = new ClaimEntity();

View File

@ -10,6 +10,7 @@ import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {StringUtils} from "../../utils/string-utils.class";
import {ClaimProjectsSearchFormComponent} from "../claim-utils/claimProjectSearchForm.component";
@Component({
@ -152,6 +153,7 @@ export class DirectLinkingComponent {
entity.type = "project";
entity.title = project.projectName;
entity.project = new ClaimProject();
entity.project.url = properties.searchLinkToProject + entity.id;
entity.project.acronym = project.projectAcronym;
entity.project.code = project.code;
entity.project.endDate = project.endDate;

View File

@ -1,20 +1,61 @@
<ng-template #destinations_basket>
<div *ngIf="(results.length)> 0 || showOptions.show=='result'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height: 17px;">
<start-over *ngIf=" (results.length)> 0"
[results]="results" [localStoragePrefix]="localStoragePrefix+'results'"
message="all results (projects, communities, research results)"
class="uk-float-right"></start-over>
<bulk-claim *ngIf="showOptions.show=='result'" [results]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit"></bulk-claim>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<div *ngIf="results.length >= basketLimit "
class="uk-alert uk-alert-warning uk-text-center">
Basket reached the size limit. No more entities can be added.
</div>
<claim-selected-results sectionTitle="Selected Results" [results]="results"
[localStoragePrefix]="localStoragePrefix+'results'" type="target">
</claim-selected-results>
<div *ngIf="(results.length) == 0 " class=" uk-text-center">
No entities to link with the sources. Start adding entities from the left panel.
</div>
</div>
</ng-template>
<div class="linking uk-background-default">
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
<div class="uk-padding-small uk-padding-remove-horizontal">
<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
<breadcrumbs *ngIf="!inlineEntity" [breadcrumbs]="breadcrumbs"></breadcrumbs>
<!-- [routerLink]="inlineEntity.result?.url.split('?')[0]"-->
<!-- [queryParams]="routerHelper.createQueryParam(inlineEntity.result?.url.split('?')[1].split('=')[0], inlineEntity.id)"-->
<a *ngIf="inlineEntity && inlineEntity.result"
(click)="back()"
class="uk-button uk-button-link uk-text-transform-none uk-flex uk-flex-middle">
<icon name="west" [flex]="true"></icon>
<span class="uk-margin-small-left">Back to {{getEntityName(inlineEntity.type, false)}}</span>
</a>
<a *ngIf="inlineEntity && inlineEntity.project"
[routerLink]="inlineEntity.project?.url?.split('?')[0]"
[queryParams]="routerHelper.createQueryParam(inlineEntity.project?.url.split('?')[1].split('=')[0], inlineEntity.id)"
class="uk-button uk-button-link uk-text-transform-none uk-flex uk-flex-middle">
<icon name="west" [flex]="true"></icon>
<span class="uk-margin-small-left">Back to {{getEntityName(inlineEntity.type, false)}}</span>
</a>
</div>
</div>
<div uk-sticky="offset: 65; bottom: #pageBottom; media: @m" class="uk-blur-background">
<div *ngIf="!inlineEntity" uk-sticky="offset: 65; bottom: #pageBottom; media: @m" class="uk-blur-background">
<div class="uk-section-xsmall">
<stepper>
<step *ngIf="!inlineEntity" [status]="stepStatus('source')" stepId="source" stepNumber="1"
<step [status]="stepStatus('source')" stepId="source" stepNumber="1"
[stepText]="'Find Sources'" (stepChanged)="stepHasChanged($event)"
[active]="this.showOptions.show" [showStepLine]="false"></step>
<step [status]="stepStatus('target')" stepId="target" [stepNumber]="inlineEntity?1:2"
[stepText]="'Link Source' + (inlineEntity?'':'s') + ' to Entities'"
<step [status]="stepStatus('target')" stepId="target" [stepNumber]="2"
[stepText]="'Link Sources to Entities'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show"
[showStepLine]="!inlineEntity"></step>
<step [status]="stepStatus('claim')" stepId="claim" [stepNumber]="inlineEntity?2:3"
[showStepLine]="true"></step>
<step [status]="stepStatus('claim')" stepId="claim" [stepNumber]="3"
[stepText]="'Summarize and finish'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show"
[showStepLine]="true"></step>
@ -37,16 +78,18 @@
<div [class]="((showOptions.show == 'claim')?'':' uk-margin-top ')+' uk-container uk-container-large '">
<div class="uk-grid basketContainer" *ngIf="showOptions.show!='claim'" uk-grid>
<div class="uk-width-2-3 uk-position-z-index">
<h2 *ngIf="inlineEntity" class="uk-text-center">Link source to</h2>
<div *ngIf="showOptions.show=='source'">
<claim-result-search-form [selectedResults]="sources" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'"
[basketLimit]="basketLimit"
[basketLimit]="basketLimit" [centerAlign]="!!inlineEntity"
></claim-result-search-form>
</div>
<div *ngIf="showOptions.show=='project'">
<claim-projects-search-form [selectedProjects]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-projects-search-form>
</div>
<div *ngIf="showOptions.show=='context'">
@ -54,12 +97,14 @@
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-contexts-search-form>
</div>
<div *ngIf="showOptions.show=='result'">
<claim-result-search-form [selectedResults]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-result-search-form>
</div>
</div>
@ -69,78 +114,70 @@
<div class="uk-card uk-card-default linkingBasket">
<div class="uk-card-body uk-padding-small">
<div class="uk-margin-right">
<ul class="uk-tab" uk-tab>
<li [class.uk-active]="showOptions.basketShowSources"
(click)="showOptions.basketswitchToSources()">
<a>
Sources to link ({{(sources.length + (inlineEntity ? 1 : 0)) |number}})
</a>
</li>
<li [class.uk-disabled]="sources.length == 0 && !inlineEntity"
[class.uk-active]="showOptions.basketShowLinksTo">
<a (click)="showOptions.basketswitchToLinkTo()">Link to <span
*ngIf="results.length> 0">({{(results.length) | number}})</span>
</a>
</li>
</ul>
<div *ngIf="showOptions.basketShowSources">
<div class="uk-height-medium uk-overflow-auto">
<div *ngIf="showOptions.show == 'source'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height:17px;">
<start-over *ngIf="showOptions.show == 'source' && sources.length> 0"
[results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'"
message="all sources" class="uk-float-right"></start-over>
<bulk-claim *ngIf="showOptions.show == 'source'" [results]="sources"
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'" [basketLimit]="basketLimit"
>
</bulk-claim>
<ng-container *ngIf="inlineEntity">
<div class="uk-margin-small-bottom">
<div class="uk-text-emphasis uk-text-bolder">Source</div>
<claim-selected-results [results]="[inlineEntity]"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="false" type="source">
</claim-selected-results>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal"><hr class="uk-margin-remove"/></div>
<div class="uk-margin-small-top">
<div class="uk-text-emphasis uk-text-bolder">Link source to <span *ngIf="results.length> 0">({{(results.length) | number}})</span></div>
<ng-container *ngTemplateOutlet="destinations_basket"></ng-container>
</div>
</ng-container>
<ng-container *ngIf="!inlineEntity">
<ul class="uk-tab" uk-tab>
<li [class.uk-active]="showOptions.basketShowSources"
(click)="showOptions.basketswitchToSources()">
<a>
Sources to link ({{(sources.length) |number}})
</a>
</li>
<li [class.uk-disabled]="sources.length == 0"
[class.uk-active]="showOptions.basketShowLinksTo">
<a (click)="showOptions.basketswitchToLinkTo()">Link to <span
*ngIf="results.length> 0">({{(results.length) | number}})</span>
</a>
</li>
</ul>
<div *ngIf="showOptions.basketShowSources">
<div class="uk-height-medium uk-overflow-auto">
<div *ngIf="showOptions.show == 'source'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height:17px;">
<start-over *ngIf="showOptions.show == 'source' && sources.length> 0"
[results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'"
message="all sources" class="uk-float-right"></start-over>
<bulk-claim *ngIf="showOptions.show == 'source'" [results]="sources"
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'" [basketLimit]="basketLimit"
>
</bulk-claim>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<div *ngIf="sources.length == 0 && !inlineEntity " class="uk-text-center uk-text-meta">
No Sources added yet. Start adding sources from the left panel. Or upload a DOI's CSV file.
</div>
<div *ngIf="sources.length >= basketLimit " class="uk-alert uk-alert-warning uk-text-center">
Basket reached the size limit. No more sources can be added.
<div class="uk-padding-small uk-padding-remove-horizontal">
<div *ngIf="sources.length == 0" class="uk-text-center uk-text-meta">
No Sources added yet. Start adding sources from the left panel. Or upload a DOI's CSV file.
</div>
<div *ngIf="sources.length >= basketLimit " class="uk-alert uk-alert-warning uk-text-center">
Basket reached the size limit. No more sources can be added.
</div>
<claim-selected-results *ngIf="sources.length > 0" [results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="true" type="source">
</claim-selected-results>
</div>
<claim-selected-results *ngIf="inlineEntity" [results]="[inlineEntity]"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="false" type="source">
</claim-selected-results>
<claim-selected-results *ngIf="sources.length > 0" [results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="true" type="source">
</claim-selected-results>
</div>
</div>
</div>
<div *ngIf="showOptions.basketShowLinksTo">
<div class="uk-height-medium uk-overflow-auto">
<div *ngIf="(results.length)> 0 || showOptions.show=='result'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height: 17px;">
<start-over *ngIf=" (results.length)> 0"
[results]="results" [localStoragePrefix]="localStoragePrefix+'results'"
message="all results (projects, communities, research results)"
class="uk-float-right"></start-over>
<bulk-claim *ngIf="showOptions.show=='result'" [results]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit"></bulk-claim>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<div *ngIf="results.length >= basketLimit "
class="uk-alert uk-alert-warning uk-text-center">
Basket reached the size limit. No more entities can be added.
</div>
<claim-selected-results sectionTitle="Selected Results" [results]="results"
[localStoragePrefix]="localStoragePrefix+'results'" type="target">
</claim-selected-results>
<div *ngIf="(results.length) == 0 " class=" uk-text-center">
No entities to link with the sources. Start adding entities from the left panel.
</div>
<div *ngIf="showOptions.basketShowLinksTo">
<div class="uk-height-medium uk-overflow-auto">
<ng-container *ngTemplateOutlet="destinations_basket"></ng-container>
</div>
</div>
</div>
</ng-container>
</div>
</div>
<div *ngIf="showOptions.show == 'source'"
@ -164,7 +201,7 @@
<button class="uk-flex uk-flex-middle uk-button uk-button-text"
[class.uk-disabled]="results.length == 0" [disabled]="results.length == 0">
<icon *ngIf="inlineEntity" name="link" visuallyHidden="link" [flex]="true"></icon>
<div class="uk-width-expand uk-margin-small-left">STEP {{inlineEntity ? '2' : '3'}} - FINALISE AND FINISH</div>
<div class="uk-width-expand uk-margin-small-left"><ng-container *ngIf="!inlineEntity">STEP {{inlineEntity ? '2' : '3'}} - </ng-container>SUMMARISE</div>
</button>
</div>
</div>

View File

@ -13,6 +13,9 @@ import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {StringUtils} from "../../utils/string-utils.class";
import {RouterHelper} from "../../utils/routerHelper.class";
import { Location } from '@angular/common';
@Component({
selector: 'linking-generic',
@ -44,10 +47,12 @@ export class LinkingGenericComponent {
@ViewChild(AlertModal) alert;
public pageContents = null;
@Input() breadcrumbs: Breadcrumb[] = [];
public routerHelper: RouterHelper = new RouterHelper();
constructor (private _router: Router, private route: ActivatedRoute, private entitySearch:EntitiesSearchService,
private _meta: Meta, private _title: Title, private _piwikService:PiwikService,
private seoService: SEOService, private helper: HelperService, private cdr: ChangeDetectorRef ) {
private seoService: SEOService, private helper: HelperService, private cdr: ChangeDetectorRef,
private location: Location) {
}
subscriptions = [];
@ -161,6 +166,7 @@ export class LinkingGenericComponent {
this.showOptions.show = 'claim';
}
this.cdr.detectChanges();
HelperFunctions.scroll(true);
console.log('stepHasChanged', stepId, this.showOptions.show)
}
@ -193,5 +199,14 @@ export class LinkingGenericComponent {
}
}
}
private getEntityName (entityType:string, plural:boolean) {
return StringUtils.getEntityName(entityType, plural);
}
back(): void {
if(typeof document !== 'undefined') {
this.location.back();
}
}
}

View File

@ -0,0 +1,11 @@
@import (reference) "~src/assets/openaire-theme/less/_import-variables";
.claim-entity-metadata {
& > *:not(:last-child):not(.other-separator)::after {
content: "\2022";
font-weight: normal;
margin-left: @global-xsmall-margin;
margin-right: @global-xsmall-margin;
}
}

View File

@ -4,18 +4,28 @@ import {ClaimEntity} from '../../claim-utils/claimHelper.class';
@Component({
selector: 'claim-project-metadata',
template: `
<div *ngIf="entity.type == 'project' && entity.project" class="uk-text-small uk-flex uk-flex-wrap" [style.grid-gap]="shortVersion?'10px':'20px'">
<div *ngIf="entity.project.funderName">
<span class="uk-text-meta">Funder: </span>{{entity.project.funderName}}
</div>
<div *ngIf="entity.project.code">
<span class="uk-text-meta">GrandID: </span>{{entity.project.code}}
</div>
<div *ngIf=" !shortVersion && (entity.project.startDate || entity.project.endDate)">
<span class="uk-text-meta">Duration: </span>{{(entity.project.startDate) ? entity.project.startDate : 'Unknown'}}{{'-' + ((entity.project.endDate) ? entity.project.endDate : 'Unknown')}}
</div>
</div>
`
<ng-container *ngIf="entity.type == 'project' && entity.project">
<div *ngIf="!shortVersion" class="claim-entity-metadata uk-flex-inline uk-flex-wrap uk-text-xsmall uk-text-emphasis"
[class.uk-margin-xsmall-top]="!shortVersion">
<span class="uk-text-capitalize">
{{entity.type}}
</span>
<span *ngIf="entity.project.startDate || entity.project.endDate">
{{(entity.project.startDate) ? entity.project.startDate : 'Unknown'}}{{'-' + ((entity.project.endDate) ? entity.project.endDate : 'Unknown')}}
</span>
</div>
<div class="uk-text-small uk-flex uk-flex-wrap" [style.grid-gap]="shortVersion?'10px':'20px'"
[class.uk-margin-small-top]="!shortVersion">
<div *ngIf="entity.project.funderName">
<span class="uk-text-meta">Funder: </span>{{entity.project.funderName}}
</div>
<div *ngIf="entity.project.code">
<span class="uk-text-meta">Project Code: </span>{{entity.project.code}}
</div>
</div>
</ng-container>
`,
styleUrls: ['ClaimEntityMetadata.component.less']
})

View File

@ -4,29 +4,37 @@ import {ClaimEntity} from '../../claim-utils/claimHelper.class';
@Component({
selector: 'claim-result-metadata',
template: `
<div *ngIf="entity.result" class="uk-text-small">
<div *ngIf="entity.result.authors && entity.result.authors.length >0 " class="uk-margin-small-bottom">
<span class="uk-text-meta">Authors: </span>{{sliceArray(entity.result.authors)}}
</div>
<div *ngIf="!shortVersion && entity.result.editors&& entity.result.editors.length > 0" class="uk-margin-small-bottom">
<span class="uk-text-meta">Editors: </span>{{sliceArray(entity.result.editors)}}
</div>
<div *ngIf="!shortVersion" class="uk-flex uk-flex-wrap" style="grid-gap: 20px;">
<span *ngIf="entity.result.publisher!=null">
<span class="uk-text-meta uk-margin-small-bottom">Publisher: </span>{{entity.result.publisher}}
<div *ngIf="entity.result">
<!-- display all existing data similar to entity-metadata -->
<div *ngIf="!shortVersion" class="claim-entity-metadata uk-flex-inline uk-flex-wrap uk-text-xsmall uk-text-emphasis uk-margin-xsmall-top">
<span class="uk-text-capitalize uk-text-italic">
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</span>
<span *ngIf="entity.result.publisher!=null">
{{entity.result.publisher}}
</span>
<span *ngIf="entity.result.journal!=null">
<span class="uk-text-meta uk-margin-small-bottom">Journal: </span>{{entity.result.journal}}
</span>
<span *ngIf="entity.result.date">
<span class="uk-text-meta uk-margin-small-bottom">Published: </span>
<span *ngIf="entity.result.date">
<span [class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')">{{entity.result.date}}</span>
</span>
<div [class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')">{{getProjectDurationMessage(entity)}}
</div>
<span *ngIf="entity.result.journal!=null">
{{entity.result.journal}}
</span>
<div *ngIf="entity.result.editors && entity.result.editors.length > 0">
{{sliceArray(entity.result.editors)}}
</div>
</div>
<div *ngIf="entity.result.authors && entity.result.authors.length > 0" class="uk-flex uk-flex-wrap uk-text-small uk-text-emphasis uk-text-italic"
[class.uk-margin-small-top]="!shortVersion">
{{sliceArray(entity.result.authors)}}
</div>
<div class="uk-text-small uk-margin-top">
<span *ngIf="getProjectDurationMessage(entity)" [class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')">
{{getProjectDurationMessage(entity)}}
</span>
</div>
</div>
`
`,
styleUrls: ['ClaimEntityMetadata.component.less']
})

View File

@ -1,64 +1,67 @@
import {Component, Input} from '@angular/core';
import {ClaimEntity} from '../../claim-utils/claimHelper.class';
import {StringUtils} from "../../../utils/string-utils.class";
@Component({
selector: 'claim-title',
template:
`
<div class="uk-grid uk-flex uk-flex-middle">
<span *ngIf="showIcon" >
<span *ngIf=" entity.result" class="material-icons uk-text-small uk-text-meta" >insert_drive_file
</span>
<span *ngIf=" entity.project"
class="material-icons uk-text-small uk-text-meta">assignment_turned_in
</span>
<span *ngIf="entity.type=='community'" style="margin-right: 2px;"
class="material-icons uk-text-small uk-text-meta">people
</span></span>
<div class="uk-width-expand " style="word-break: break-word;" [class.uk-h6]="!shortVersion" [class.uk-text-bold]="shortVersion" [class.uk-text-truncate]="shortVersion" [class.uk-margin-bottom]="!shortVersion" [class.uk-padding-remove-left]="showIcon">
<a *ngIf="entity.result && entity.result.url" target="_blank" [href]="entity.result.url"
class="uk-link uk-link-heading">{{entity.title ? sliceString(entity.title) : '[No title available]'}}</a>
<span
*ngIf="(entity.result && !entity.result.url)">{{entity.title ? sliceString(entity.title) : '[No title available]'}}</span>
<span *ngIf="entity.type=='project' && entity.project">
<a *ngIf="entity.project && entity.project.url" target="_blank" [href]="entity.project.url"
class="uk-text-link">
<span *ngIf="!shortVersion">
{{(entity.project.acronym ? '[' + entity.project.acronym + '] ' : '') + entity.title}}
</span>
<span *ngIf="shortVersion">
{{(entity.project.acronym ? sliceString(entity.project.acronym):sliceString(entity.title))}}
</span>
template: `
<div class="uk-grid uk-flex uk-flex-middle">
<span *ngIf="showIcon" class="uk-flex">
<span *ngIf="entity.result" class="material-icons uk-text-small uk-text-meta">
insert_drive_file
</span>
<span *ngIf="entity.project" class="material-icons uk-text-small uk-text-meta">
assignment_turned_in
</span>
<span *ngIf="entity.type=='community'" class="material-icons uk-text-small uk-text-meta" style="margin-right: 2px;">
people
</span>
</span>
<div class="uk-width-expand multi-line-ellipsis lines-3" style="word-break: break-word;"
[class.uk-padding-remove-left]="showIcon" [class.uk-text-truncate]="shortVersion">
<div class="uk-margin-remove uk-text-break uk-inline-block"
[class.uk-h6]="!shortVersion" [class.uk-text-bold]="shortVersion">
<a *ngIf="entity.result && entity.result.url" target="_blank" [href]="entity.result.url"
class="uk-link uk-text-decoration-none uk-width-expand">
{{entity.title ? sliceString(entity.title) : '[No title available]'}}
</a>
<span
*ngIf="(entity.project && !entity.project.url)">
<span *ngIf="!shortVersion">
{{(entity.project.acronym ? '[' + entity.project.acronym + '] ' : '') + entity.title}}
</span>
<span *ngIf="shortVersion">
{{(entity.project.acronym ? sliceString(entity.project.acronym):sliceString(entity.title))}}
</span>
</span>
</span>
<span *ngIf="entity.type=='community' && entity.context">
<span *ngIf=" entity.context.community != entity.context.concept.label">
{{entity.context.community }} > {{entity.context.category}} >
</span>
<span> {{entity.context.concept.label}}</span>
</span>
<span *ngIf="(entity.result && !entity.result.url)">
{{entity.title ? sliceString(entity.title) : '[No title available]'}}
</span>
<span *ngIf="entity.type=='project' && entity.project">
<a *ngIf="entity.project && entity.project.url" target="_blank" [href]="entity.project.url"
class="uk-link uk-text-decoration-none uk-width-expand">
<span *ngIf="!shortVersion">
{{(entity.project.acronym ? '[' + entity.project.acronym + '] ' : '') + entity.title}}
</span>
<span *ngIf="shortVersion">
{{(entity.project.acronym ? sliceString(entity.project.acronym):sliceString(entity.title))}}
</span>
</a>
<span *ngIf="(entity.project && !entity.project.url)">
<span *ngIf="!shortVersion">
{{(entity.project.acronym ? '[' + entity.project.acronym + '] ' : '') + entity.title}}
</span>
<span *ngIf="shortVersion">
{{(entity.project.acronym ? sliceString(entity.project.acronym):sliceString(entity.title))}}
</span>
</span>
</span>
<span *ngIf="entity.type=='community' && entity.context">
<span *ngIf=" entity.context.community != entity.context.concept.label">
{{entity.context.community }} > {{entity.context.category}} >
</span>
<span>
{{entity.context.concept.label}}
</span>
</span>
</div>
</div>
</div>
</div>
`
})
export class ClaimEntityTitleComponent {
@Input() entity: ClaimEntity;
@Input() slice:boolean = false;
@Input() sliceSize:number = 45;
@ -66,14 +69,13 @@ export class ClaimEntityTitleComponent {
@Input() showIcon: boolean = false;
ngOnInit() {
}
sliceString(mystr:string): string {
if(this.slice){
if(this.slice){
// return StringUtils.sliceString(mystr,this.sliceSize);
}
return mystr;
}
return mystr;
}
}

View File

@ -12,8 +12,8 @@
<div class=" uk-margin uk-animation-toggle">
<span class="uk-h6 "> SOURCES ({{sources.length + (inlineEntity ? 1 : 0) | number}})
</span>
<a *ngIf="!inlineEntity" class="uk-float-right" (click)="showOptions.showSource() "> <span
uk-icon="pencil"></span>Edit
<a *ngIf="!inlineEntity" class="uk-float-right uk-text-small" (click)="showOptions.showSource() "> <span
uk-icon="pencil" class="uk-margin-xsmall-right"></span>Edit
sources</a>
</div>
<ul *ngIf="inlineEntity" class="uk-list uk-animation-fade uk-list-divider">
@ -51,10 +51,10 @@
<ul *ngIf="!inlineEntity && sources.length > 0 " class="uk-list uk-animation-fade uk-list-divider">
<li *ngFor=" let entity of sources ">
<div class="uk-grid uk-text-small uk-margin-top">
<div class="uk-text-muted uk-width-1-2 uk-flex uk-flex-middle">
<!-- <div class="uk-text-muted uk-width-1-2 uk-flex uk-flex-middle">
<span class="material-icons uk-text-small uk-text-meta">insert_drive_file</span>
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</div>
</div> -->
<div *ngIf="entity.errorMessages.length > 0"
class="uk-text-danger uk-width-1-2"> Link couldn't be saved
</div>
@ -157,8 +157,8 @@
<span class=" uk-h6 "> LINK TO ({{results.length | number}})</span>
<a class="uk-float-right" (click)="showOptions.showLinkTo()"> <span
uk-icon="pencil"></span>Edit
<a class="uk-float-right uk-text-small" (click)="showOptions.showLinkTo()"> <span
uk-icon="pencil" class="uk-margin-xsmall-right"></span>Edit
entities</a>
</div>
<div *ngIf="results.length == 0">
@ -174,7 +174,7 @@
<li *ngFor=" let entity of results "
style="z-index: 0 !important;">
<div class="uk-grid uk-text-small uk-margin-top">
<div class="uk-text-muted uk-width-1-2 uk-flex uk-flex-middle">
<!-- <div class="uk-text-muted uk-width-1-2 uk-flex uk-flex-middle">
<span *ngIf="entity.result" class="material-icons uk-text-small uk-text-meta">insert_drive_file
</span>
<span *ngIf="entity.project"
@ -184,7 +184,7 @@
class="material-icons uk-text-small uk-text-meta">people
</span>
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</div>
</div> -->
<div *ngIf="entity.errorMessages.length > 0"
class="uk-text-danger uk-width-1-2"> Link couldn't be saved
</div>

View File

@ -23,7 +23,7 @@ export class Layout {
variables['@global-background'] = Layout.convertRGBAtoRGB(options.backgrounds.light.color);
variables['@hero-background-image'] = (options.backgrounds.form.imageFile ? (this.getUrl(properties.utilsService + '/download/' + options.backgrounds.form.imageFile)) : 'none');
variables['@hero-background-position'] = options.backgrounds.form.position;
variables['@hero-fonts-mode'] = options.backgrounds.form.fontsDarkMode?'dark':'light';
variables['@hero-fonts-mode'] = options.backgrounds.form.fontsDarkMode == true ?'dark':'light';
}
if (options.buttons) {
//general
@ -174,6 +174,9 @@ export class CustomizationOptions {
}
public static checkForObsoleteVersion(current: CustomizationOptions, communityId: string) {
if(communityId === 'connect') {
return null;
}
let defaultCO = new CustomizationOptions(CustomizationOptions.getIdentity(communityId).mainColor, CustomizationOptions.getIdentity(communityId).secondaryColor);
let updated = Object.assign({}, defaultCO);
if (!current) {
@ -197,7 +200,7 @@ export class CustomizationOptions {
if (!current.backgrounds.form.position) {
current.backgrounds.form.position = "center bottom"
}
if (!current.backgrounds.form.fontsDarkMode) {
if (current.backgrounds.form.fontsDarkMode == undefined) {
current.backgrounds.form.fontsDarkMode = true;
}
if (!current.buttons) {

View File

@ -4,27 +4,27 @@
<div class="uk-child-width-1-1 uk-grid uk-grid-margin-large" [attr.uk-scrollspy-class]="scrollspy?'':null"
[class.uk-grid-column-small]="smallForm" [class.uk-child-width-1-2@s]="!smallForm" [formGroup]="contactForm" uk-grid>
<div *ngIf="contactForm.get('name')" input placeholder="Name"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('name')"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('name')"></div>
<div *ngIf="contactForm.get('surname')" input placeholder="Surname"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('surname')"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('surname')"></div>
<div *ngIf="contactForm.get('email')" input placeholder="Email"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('email')"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('email')"></div>
<div *ngIf="contactForm.get('job')" input placeholder="Job Title"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('job')"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('job')"></div>
<div *ngIf="contactForm.get('affiliation')" input placeholder="Affiliation"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('affiliation')"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('affiliation')"></div>
<div *ngIf="contactForm.get('community')" input placeholder="Research Community or Infrastructure"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('community')"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('community')"></div>
<div *ngIf="contactForm.get('organization')" input placeholder="Organization"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('organization')"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('organization')"></div>
<div *ngIf="contactForm.get('organizationType')" input type="select" placeholder="Organization Type"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('organizationType')" [options]="organizationTypes"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('organizationType')" [options]="organizationTypes"></div>
<div *ngIf="contactForm.get('subject')" class="uk-width-1-1" input placeholder="Subject"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('subject')"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('subject')"></div>
<div *ngIf="contactForm.get('message')" class="uk-width-1-1" input type="textarea" rows="4" placeholder="Comments"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('message')"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('message')"></div>
<div *ngIf="contactForm.get('description')" class="uk-width-1-1" input type="textarea" rows="4" placeholder="Description"
[inputClass]="'inner' + (smallForm?' x-small':'')" [formInput]="contactForm.get('description')"></div>
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('description')"></div>
<div *ngIf="contactForm.get('recaptcha')" class="uk-flex uk-flex-center" [class.uk-width-1-1]="smallForm" [class.uk-flex-last@s]="!smallForm">
<re-captcha #captchaElem (resolved)="handleRecaptcha($event)" [siteKey]="properties.reCaptchaSiteKey"></re-captcha>
</div>

View File

@ -11,9 +11,9 @@ import {ActivatedRoute} from "@angular/router";
<li *ngIf="isPortalAdmin && !portal" [class.uk-active]="tab === 'portal'"><a routerLink="../portals">Portals</a></li>
<li [class.uk-active]="tab === 'page'"><a routerLink="../pages">Pages</a></li>
<li [class.uk-active]="tab === 'entity'"><a routerLink="../entities">Entities</a></li>
<li *ngIf="portal && type === 'community'" [class.uk-active]="tab === 'menu'"><a routerLink="../menu">Menus</a></li>
<li *ngIf="isPortalAdmin && !portal" [class.uk-active]="tab === 'class'"><a routerLink="../classes">Classes</a></li>
<li *ngIf="isPortalAdmin && portal=='connect'" [class.uk-active]="tab === 'customization'"><a routerLink="../customization">Customization</a></li>
<li *ngIf="portal && type === 'community'" [class.uk-active]="tab === 'menu'"><a routerLink="../menu">Menus</a></li>
<li *ngIf="isPortalAdmin && !portal" [class.uk-active]="tab === 'class'"><a routerLink="../classes">Classes</a></li>
<li *ngIf="isPortalAdmin && portal=='connect'" [class.uk-active]="tab === 'customization'"><a routerLink="../customization">Customization</a></li>
</ul>
`
})
@ -25,7 +25,7 @@ export class AdminTabsComponent implements OnInit {
@Input()
public user: User;
@Input()
public tab: "portal" | "page" | "entity" | "menu" | "class" | "customization"= 'page';
public tab: "portal" | "page" | "entity" | "menu" | "class" | "customization" = 'page';
private subscriptions: any[] = [];
constructor(private route: ActivatedRoute, private userManagementService: UserManagementService) {

View File

@ -75,6 +75,11 @@ export class LayoutService {
private isMobileSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
/** Active sidebar Item*/
private activeSidebarItemSubject: BehaviorSubject<SidebarItem> = new BehaviorSubject<SidebarItem>(null);
/**
* Add hasMenuSearchBar: false/ nothing on data of route config, if the search bar in the menu should not appear, otherwise true.
*/
private hasMenuSearchBarSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
private subscriptions: any[] = [];
ngOnDestroy() {
@ -166,6 +171,12 @@ export class LayoutService {
} else {
this.setActiveMenuItem('');
}
if (data['hasMenuSearchBar'] !== undefined &&
data['hasMenuSearchBar'] === true) {
this.setHasMenuSearchBar(true);
} else {
this.setHasMenuSearchBar(false);
}
}
}));
this.setObserver();
@ -292,4 +303,12 @@ export class LayoutService {
setActiveSidebarItem(value: SidebarItem) {
this.activeSidebarItemSubject.next(value);
}
get hasMenuSearchBar(): Observable<boolean> {
return this.hasMenuSearchBarSubject.asObservable();
}
setHasMenuSearchBar(value: boolean) {
this.hasMenuSearchBarSubject.next(value);
}
}

View File

@ -95,13 +95,16 @@
</div>
</div>
<modal-alert #inviteModal (alertOutput)="invite()" [overflowBody]="false" classTitle="uk-background-primary uk-light"
[okDisabled]="invited && invited.invalid">
[okDisabled]="!valid">
<div *ngIf="message" class="uk-margin-medium-bottom uk-text-small">
<div [innerHTML]="message | safeHtml"></div>
</div>
<div *ngIf="invited">
<div input [formInput]="invited"
placeholder="Email"></div>
<div *ngIf="emailsForm">
<div #emailInput input [formInput]="emailsForm" type="chips"
placeholder="Recipients" hint="Add a recipient" [visibleChips]="3"
[addExtraChips]="true" [validators]="validators" [separators]="[',']">
<div note>Separate emails with commas</div>
</div>
</div>
</modal-alert>
<modal-alert #deleteModal [overflowBody]="false" (alertOutput)="deleteActive()" classTitle="uk-background-primary uk-light">

View File

@ -1,5 +1,21 @@
import {Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChild} from '@angular/core';
import {UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators} from '@angular/forms';
import {
ChangeDetectorRef,
Component,
Input,
OnChanges,
OnDestroy,
OnInit,
SimpleChanges,
ViewChild
} from '@angular/core';
import {
UntypedFormArray,
UntypedFormBuilder,
UntypedFormControl,
UntypedFormGroup,
ValidatorFn,
Validators
} from '@angular/forms';
import {AlertModal} from "../../../utils/modal/alert";
import {UserRegistryService} from "../../../services/user-registry.service";
import {EnvProperties} from "../../../utils/properties/env-properties";
@ -9,9 +25,22 @@ import {UserManagementService} from "../../../services/user-management.service";
import {Router} from "@angular/router";
import {StringUtils} from "../../../utils/string-utils.class";
import {NotificationService} from "../../../notifications/notification.service";
import {Subscription} from "rxjs";
import {forkJoin, of, Subscription} from "rxjs";
import {NotificationHandler} from "../../../utils/notification-handler";
import {ClearCacheService} from "../../../services/clear-cache.service";
import {catchError, map, tap} from "rxjs/operators";
import notification = CKEDITOR.plugins.notification;
import {InputComponent} from "../../../sharedComponents/input/input.component";
class InvitationResponse {
email: string;
invitation: any;
constructor(email, invitation) {
this.email = email;
this.invitation = invitation;
}
}
@Component({
selector: 'role-users',
@ -49,7 +78,8 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
public loadActive: boolean = true;
public loadPending: boolean = true;
public selectedUser: string = null;
public invited: UntypedFormControl;
public emailsForm: UntypedFormArray;
public validators: ValidatorFn[] = [Validators.email];
public properties: EnvProperties = properties;
public exists: boolean = true;
public roleFb: UntypedFormGroup;
@ -60,6 +90,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
/** Search */
filterForm: UntypedFormGroup;
@ViewChild('inviteModal') inviteModal: AlertModal;
@ViewChild('emailInput') emailInput: InputComponent;
@ViewChild('deleteModal') deleteModal: AlertModal;
@ViewChild('deletePendingModal') deletePendingModal: AlertModal;
@ViewChild('createRoleModal') createRoleModal: AlertModal;
@ -69,6 +100,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
private clearCacheService: ClearCacheService,
private notificationService: NotificationService,
private router: Router,
private cdr: ChangeDetectorRef,
private fb: UntypedFormBuilder) {
}
@ -172,7 +204,8 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
this.inviteModal.alertTitle = 'Invite ' + this.role;
this.inviteModal.okButtonLeft = false;
this.inviteModal.okButtonText = 'Send';
this.invited = this.fb.control('', [Validators.required, Validators.email]);
this.emailsForm = this.fb.array([], Validators.required);
this.cdr.detectChanges();
this.inviteModal.open();
}
@ -224,33 +257,56 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
this.loadPending = false;
}));
}
get valid() {
return this.emailsForm && this.emailsForm.valid || (this.emailInput && this.emailInput.searchControl.getRawValue() && this.emailInput.searchControl.valid);
}
invite() {
if(this.emailInput.searchControl.getRawValue() && this.emailInput.searchControl.valid) {
this.emailInput.add(null,true);
}
this.showCurrent = false;
this.loadPending = true;
this.selectedUser = this.invited.value;
let details = {
link: this.link,
email: this.emailComposer(this.name, this.invited.value, this.role)
}
this.subs.push(this.userRegistryService.invite(this.type, this.id, details, this.role).subscribe(invitation => {
if (!this.pending.includes(this.invited.value)) {
this.pending.push(this.invited.value);
let current = null;
let invitations = (<Array<any>>this.emailsForm.value).map(email => {
current = email;
return this.userRegistryService.invite(this.type, this.id, {
link: this.link,
email: this.emailComposer(this.name, email, this.role)
}, this.role).pipe(map(invitation => new InvitationResponse(email, invitation), catchError(error => {
return of(new InvitationResponse(current, null));
})));
});
this.subs.push(forkJoin(invitations).subscribe(responses => {
let notifications = responses.map(response => {
if(response.invitation) {
NotificationHandler.rise(StringUtils.capitalize(this.role) + ' invitation to ' + response.email + ' has been <b>sent</b>');
if (!this.pending.includes(response.email)) {
this.pending.push(response.email);
}
if(this.notificationFn) {
return this.notificationService.sendNotification(this.notificationFn(this.name, response.email, this.role, response.invitation)).pipe(map(notification => {
return notification;
}), tap(() => {
NotificationHandler.rise('A notification has been <b>sent</b> successfully to ' + response.email);
}), catchError( error => {
NotificationHandler.rise('An error has occurred while sending a notification to ' + response.email + '. Please try again later', 'danger');
return of(null);
}));
} else {
return of(null);
}
} else {
NotificationHandler.rise('An error has occurred while sending the invitation mail to ' + response.email + '.Please try again later', 'danger');
return of(null);
}
});
this.subs.push(forkJoin(notifications).subscribe(() => {
this.pendingPage = Math.ceil(this.pending.length / this.pageSize);
this.filterPendingBySearch(this.filterForm.value.pending);
}
if (this.notificationFn) {
this.subs.push(this.notificationService.sendNotification(this.notificationFn(this.name, this.invited.value, this.role, invitation)).subscribe(notification => {
NotificationHandler.rise('A notification has been <b>sent</b> successfully');
}, error => {
NotificationHandler.rise('An error has occurred. Please try again later', 'danger');
}));
}
NotificationHandler.rise(StringUtils.capitalize(this.role) + ' invitation to ' + this.selectedUser + ' has been <b>sent</b>');
this.loadPending = false;
}, error => {
NotificationHandler.rise('An error has occurred. Please try again later', 'danger');
this.loadPending = false;
this.loadPending = false;
}))
}));
}

View File

@ -29,7 +29,8 @@ import {SearchForm} from "../searchPages/searchUtils/newSearchPage.component";
<div class="uk-container uk-container-large">
<div class="uk-margin-top uk-flex uk-flex-center">
<div class="uk-width-large" [class.dark]="searchForm.dark">
<div search-input [(value)]="keyword" placeholder="Search by name, description, subject..." (searchEmitter)="keywordChanged()"></div>
<div search-input [(value)]="keyword" placeholder="Search by name, description, subject..." (searchEmitter)="keywordChanged()"
[searchInputClass]="'inner background'"></div>
<div class="uk-margin-top uk-text-center uk-margin-medium-bottom">
<a *ngIf="zenodoInformation.url" [href]="zenodoInformation.url" target="_blank" class="uk-display-inline-block uk-text-uppercase uk-button uk-button-text">
<span class="uk-flex uk-flex-middle">

View File

@ -3,15 +3,25 @@ import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from "@angular/com
import {Observable, throwError, TimeoutError} from "rxjs";
import {catchError} from "rxjs/operators";
import {Session} from "./login/utils/helper.class";
import {Router} from "@angular/router";
import {GuardsCheckEnd, GuardsCheckStart, Router} from "@angular/router";
import {LoginErrorCodes} from "./login/utils/guardHelper.class";
import {properties} from "../../environments/environment";
import * as url from "url";
@Injectable()
export class ErrorInterceptorService implements HttpInterceptor {
private static UNAUTHORIZED_WHITELIST = [properties.userInfoUrl, properties.orcidAPIURL, properties.registryUrl? (properties.registryUrl + 'verification/'):null, properties.eoscDataTransferAPI].filter(value => !!value);
private url: string = null;
constructor(private router: Router) {
this.router.events.forEach(event => {
if(event instanceof GuardsCheckStart) {
this.url = event.url;
} else if(event instanceof GuardsCheckEnd) {
this.url = null;
}
})
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
@ -42,7 +52,7 @@ export class ErrorInterceptorService implements HttpInterceptor {
this.router.navigate(['/user-info'], {
queryParams: {
'errorCode': LoginErrorCodes.NOT_LOGIN,
'redirectUrl': this.router.url
'redirectUrl': this.url?this.url:this.router.url
}
});
}
@ -51,7 +61,7 @@ export class ErrorInterceptorService implements HttpInterceptor {
this.router.navigate(['/user-info'], {
queryParams: {
'errorCode': LoginErrorCodes.NOT_AUTHORIZED,
'redirectUrl': this.router.url
'redirectUrl': this.url?this.url:this.router.url
}
});
}

View File

@ -22,7 +22,7 @@
<ul *ngIf="keyword?.length" class="uk-tab uk-tab-left">
<li *ngFor="let item of viewResults; index as i"
class="uk-margin-small-bottom uk-text-capitalize" [class.uk-active]="activeSection === item.id">
<a (click)="scrollToId(item.id)">{{item.id}}</a>
<a (click)="scrollToId(item.id)">{{item.id}}</a>
</li>
</ul>
</div>

View File

@ -15,10 +15,10 @@
<span>Fields of Science <span class="uk-text-primary">.</span></span>
</h1>
<div uk-scrollspy-class>
We have integrated a Field-of-Science (FoS) taxonomy into our dataset to organize and discover research more effectively. Using the full capabilities of the OpenAIRE Research Graph (full-texts, citations, references, venues) we apply AI and bring forward any multidisciplinarity potential.
We have integrated a Field-of-Science (FoS) taxonomy into our dataset to organize and discover research more effectively. Using the full capabilities of the OpenAIRE Graph (full-texts, citations, references, venues) we apply AI and bring forward any multidisciplinarity potential.
</div>
<div class="uk-text-meta uk-margin-top" uk-scrollspy-class>
Our work is based on the work from our partner Athena Research Center: SciNoBo : A Hierarchical Multi-Label Classifier of Scientific Publications - <a href="https://doi.org/10.1145/3487553.3524677" target="_blank">https://doi.org/10.1145/3487553.3524677</a>
Our work is based on the work from our partner Athena Research Center: SciNoBo : a novel system classifying scholarly communication in a dynamically constructed hierarchical Field-of-Science taxonomy - <a href="https://doi.org/10.3389/frma.2023.1149834" target="_blank">https://doi.org/10.3389/frma.2023.1149834</a>
</div>
<!-- TODO: We need a page for the button link -->
<!-- <div>
@ -113,7 +113,7 @@
<div *ngFor="let subChild of child.children" style="margin-bottom: 5px;">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subChild.id)}"
class="uk-link-text">
{{subChild.id}}
{{subChild.label}}
</a>
</div>
</div>
@ -139,7 +139,7 @@
</h3>
<div *ngFor="let subSubItem of subItem.children" style="margin-bottom: 5px;">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subSubItem.id)}"
class="uk-link-text" [innerHTML]="highlightKeyword(subSubItem.id)">
class="uk-link-text" [innerHTML]="highlightKeyword(subSubItem.label)">
</a>
</div>
</div>

View File

@ -26,7 +26,7 @@ declare var UIkit;
export class FosComponent implements OnInit, OnDestroy {
public url: string = null;
public pageTitle: string = "OpenAIRE | Fields of Science";
public pageDescription: string = "We have integrated a Field-of-Science (FoS) taxonomy into our dataset to organize and discover research more effectively. Using the full capabilities of the OpenAIRE Research Graph (full-texts, citations, references, venues) we apply AI and bring forward any multidisciplinarity potential.";
public pageDescription: string = "We have integrated a Field-of-Science (FoS) taxonomy into our dataset to organize and discover research more effectively. Using the full capabilities of the OpenAIRE Graph (full-texts, citations, references, venues) we apply AI and bring forward any multidisciplinarity potential.";
@Input() piwikSiteId = null;
public fos: any[] = [];

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
import {ChangeDetectorRef, Component, ElementRef, HostListener, Input, ViewChild} from '@angular/core';
import {ChangeDetectorRef, Component, ElementRef, Input, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser';
@ -25,9 +25,12 @@ import {SearchResult} from "../../utils/entities/searchResult";
import {ResultPreview} from "../../utils/result-preview/result-preview";
import {IndexInfoService} from "../../utils/indexInfo.service";
import {properties} from "../../../../environments/environment";
import {Subscriber} from "rxjs";
import {TabComponent} from "../../utils/tabs/tab.component";
import {Subscriber, Subscription, zip} from "rxjs";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {MetricsService} from '../../services/metrics.service';
import {NumberUtils} from '../../utils/number-utils.class';
import {LayoutService} from '../../dashboard/sharedComponents/sidebar/layout.service';
import {FullScreenModalComponent} from '../../utils/modal/full-screen-modal/full-screen-modal.component';
declare var ResizeObserver;
@ -64,16 +67,21 @@ export class DataProviderComponent {
public metricsClicked: boolean;
public viewsFrameUrl: string;
public downloadsFrameUrl: string;
public totalViews: number;
public totalDownloads: number;
public pageViews: number;
/** @deprecated*/
public totalViews: number = null;
/** @deprecated*/
public totalDownloads: number = null;
public hasViews: boolean = false;
public hasDownloads: boolean = false;
// public pageViews: number;
// Statistics tab variables
public statsClicked: boolean = false;
// @ViewChild('statisticsModal') statisticsModal;
// @ViewChild('relatedDatasourcesModal') relatedDatasourcesModal;
@ViewChild('addThisModal') addThisModal
@ViewChild('addThisModal') addThisModal;
@ViewChild('addThisFsModal') addThisFsModal: FullScreenModalComponent;
// Variables for publications, research data, projects, datasources, related datasources tabs
public fetchPublications: FetchResearchResults;
@ -144,9 +152,25 @@ export class DataProviderComponent {
// public shouldSticky: boolean = true;
subscriptions = [];
private sub: Subscription;
properties: EnvProperties = properties;
public openaireEntities = OpenaireEntities;
public isMobile: boolean = false;
public mobileContent: "info" | "metrics" | "actions" = "info";
public tabMobile: string = "";
public viewAllMobile: string = "";
// Full screen modals for small screens (mobile)
@ViewChild('summaryFsModal') summaryFsModal: FullScreenModalComponent;
@ViewChild('projectsFsModal') projectsFsModal: FullScreenModalComponent;
@ViewChild('dataprovidersFsModal') dataprovidersFsModal: FullScreenModalComponent;
@ViewChild('publicationsFsModal') publicationsFsModal: FullScreenModalComponent;
@ViewChild('datasetsFsModal') datasetsFsModal: FullScreenModalComponent;
@ViewChild('softwareFsModal') softwareFsModal: FullScreenModalComponent;
@ViewChild('otherFsModal') otherFsModal: FullScreenModalComponent;
@ViewChild('relatedDatasourcesFsModal') relatedDatasourcesFsModal: FullScreenModalComponent;
@ViewChild('statisticsFsModal') statisticsFsModal: FullScreenModalComponent;
constructor(private _dataproviderService: DataProviderService,
private _piwikService: PiwikService,
private route: ActivatedRoute,
@ -160,7 +184,9 @@ export class DataProviderComponent {
private helper: HelperService,
private _location: Location,
private indexInfoService: IndexInfoService,
private cdr: ChangeDetectorRef) {
private metricsService: MetricsService,
private cdr: ChangeDetectorRef,
private layoutService: LayoutService) {
this.fetchPublications = new FetchResearchResults(this._searchResearchResultsService);
this.fetchDatasets = new FetchResearchResults(this._searchResearchResultsService);
this.fetchSoftware = new FetchResearchResults(this._searchResearchResultsService);
@ -171,6 +197,9 @@ export class DataProviderComponent {
}
ngOnInit() {
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
}));
if (typeof document !== 'undefined') {
this.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(lastIndexUpdate => {
if (lastIndexUpdate) {
@ -328,7 +357,8 @@ export class DataProviderComponent {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
} else if (subscription instanceof (ResizeObserver || IntersectionObserver)) {
} else if ((typeof ResizeObserver != 'undefined' && subscription instanceof ResizeObserver) ||
(typeof IntersectionObserver != 'undefined' && subscription instanceof IntersectionObserver)) {
subscription.disconnect();
}
});
@ -366,6 +396,7 @@ export class DataProviderComponent {
this.seoService.createLinkForCanonicalURL(this.properties.domain +this.properties.baseLink + this._router.url);
if (typeof document !== 'undefined') {
this.getDataProviderAggregationStatus(this.dataProviderInfo.originalId);
// this.getCollectedFulltexts();
this.countResultsWithFundingInfo();
} else {
this.aggregationStatusIsInitialized = true;
@ -381,6 +412,23 @@ export class DataProviderComponent {
}
this.showLoading = false;
this.hasViews = false;
this.hasDownloads = false;
// ensure that if the API call to index does not have metrics, we get them from old metrics service call
if(this.dataProviderInfo && !this.dataProviderInfo.measure) {
this.getMetrics();
} else if(this.dataProviderInfo && this.dataProviderInfo.measure && this.dataProviderInfo.measure.counts) {
this.dataProviderInfo.measure.counts.forEach(measure => {
if(measure.name == "views" && measure.value > 0) {
this.hasViews = true;
}
if(measure.name == "downloads" && measure.value > 0) {
this.hasDownloads = true;
}
});
}
this.cdr.detectChanges();
// if (this.dataProviderInfo.tabs != undefined && this.dataProviderInfo.tabs.length > 0) {
@ -423,6 +471,20 @@ export class DataProviderComponent {
));
}
// private getCollectedFulltexts() {
// this.subscriptions.push(this._dataproviderService.getCollectedFulltexts(this.datasourceId).subscribe(
// (data: string) => {
// this.dataProviderInfo.aggregationStatus = {"fulltexts": data};
// this.aggregationStatusIsInitialized = true;
// },
// err => {
// //console.log(err);
// this.aggregationStatusIsInitialized = true;
// this.handleError("Error getting "+this.getTypeName()+" collected fulltexts for id: " + this.datasourceId, err);
// }
// ));
// }
private countResultsWithFundingInfo() {
this.subscriptions.push(this._searchResearchResultsService.countCollectedResultsWithFundingInfo(this.datasourceId).subscribe(
fundedContent => {
@ -680,11 +742,33 @@ export class DataProviderComponent {
public metricsResults($event) {
this.totalViews = $event.totalViews;
this.totalDownloads = $event.totalDownloads;
this.pageViews = $event.pageViews;
// this.pageViews = $event.pageViews;
}
private getMetrics() {
let obs;
obs = zip(this.metricsService.getMetricsNumber(this.datasourceId, "usagestats.views.repository.local", this.properties),
this.metricsService.getMetricsNumber(this.datasourceId, "usagestats.downloads.repository.local", this.properties));
this.sub = obs.subscribe(data => {
if((data[0] && data[0] > 0) || (data[1] && data[1] > 0)) {
this.dataProviderInfo.measure = {counts: []};
if(data[0] && data[0] > 0) {
this.dataProviderInfo.measure.counts.push({name: 'views', order: 0, icon: 'visibility', value: data[0]});
this.hasViews = true;
}
if(data[1] && data[1] > 0) {
this.dataProviderInfo.measure.counts.push({name: 'downloads', order: 1, icon: 'downloads', value: data[1]});
this.hasDownloads = true;
}
this.cdr.detectChanges();
}
});
}
public get hasMetrics(): boolean {
return !(this.totalViews != null && this.totalDownloads != null && this.pageViews != null) || this.totalViews > 0 || this.totalDownloads > 0 || this.pageViews > 0;
// return !(this.totalViews != null && this.totalDownloads != null) || this.totalViews > 0 || this.totalDownloads > 0;
// return (this.totalViews != null && this.totalViews > 0) || (this.totalDownloads != null && this.totalDownloads > 0);
return this.dataProviderInfo.measure?.counts?.length > 0;
}
// public openStatistics() {
@ -715,7 +799,13 @@ export class DataProviderComponent {
if(this.dataProviderInfo.organizations.length <= this.thresholdOrganizations*2) {
this.lessBtnOrganizations = true;
} else {
this.openOrganizationsModal();
if(this.isMobile) {
this.summaryFsModal.title += " - Organizations";
this.summaryFsModal.back = true;
this.viewAllMobile = "organizations";
} else {
this.openOrganizationsModal();
}
}
}
@ -731,7 +821,13 @@ export class DataProviderComponent {
if(this.dataProviderInfo.subjects.length <= this.thresholdSubjects*2) {
this.lessBtnSubjects = true;
} else {
this.openSubjectsModal();
if(this.isMobile) {
this.summaryFsModal.title += " - Subjects";
this.summaryFsModal.back = true;
this.viewAllMobile = "subjects";
} else {
this.openSubjectsModal();
}
}
}
@ -795,7 +891,6 @@ export class DataProviderComponent {
// ((!!this.dataProviderInfo.aggregationStatus.fulltexts && parseInt(this.dataProviderInfo.aggregationStatus.fulltexts) != -1)
// || (!!this.dataProviderInfo.aggregationStatus.fundedContent && parseInt(this.dataProviderInfo.aggregationStatus.fundedContent) != -1)
// || !!this.dataProviderInfo.aggregationStatus.lastUpdateDate));
return (!!this.dataProviderInfo.aggregationStatus &&
((!!this.dataProviderInfo.aggregationStatus.fulltexts && parseInt(this.dataProviderInfo.aggregationStatus.fulltexts) != -1)));
}
@ -837,12 +932,56 @@ export class DataProviderComponent {
return StringUtils.getEntityName(this.type, false);
}
public viewAllDescriptionClicked() {
if(this.isMobile) {
this.summaryFsModal.title += " - Description";
this.summaryFsModal.back = true;
this.viewAllMobile = "description";
} else {
this.openDescriptionModal();
}
}
public openDescriptionModal() {
this.descriptionModal.alertFooter = false;
this.descriptionModal.alertTitle = "Description";
this.descriptionModal.open();
}
public clickedUsageMetrics() {
setTimeout( () => {
this.metricsClicked = true;
});
}
public formatNumber(num: number | string) {
let formatted = NumberUtils.roundNumber(+num);
return formatted.number + formatted.size;
}
public cancelSummaryClicked() {
this.summaryFsModal.title = "Summary";
this.summaryFsModal.back = false;
this.lessBtnOrganizations = false;
this.viewAllMobile = "";
}
public openFsModal(fsModal: FullScreenModalComponent, title: string) {
fsModal.title = title;
fsModal.okButton = false;
fsModal.stayOpenInBack = true;
fsModal.open();
this.tabMobile = title;
}
public getMetricsTooltip(value: string) {
if (value == 'downloads') {
return "<div class='uk-flex uk-flex-middle'><a href='https://usagecounts.openaire.eu/' target='_blank'><img src='assets/common-assets/logo-small-usage-counts.png' loading='lazy' alt='OpenAIRE UsageCounts'></a><span class='uk-text-uppercase uk-margin-small-left'>Downloads provided by <a href='https://usagecounts.openaire.eu/' target='_blank' class='uk-link-reset'><strong>UsageCounts</strong></a></div>";
} else if (value == 'views') {
return "<div class='uk-flex uk-flex-middle'><a href='https://usagecounts.openaire.eu/' target='_blank'><img class='uk-margin-small-right' src='assets/common-assets/logo-small-usage-counts.png' loading='lazy' alt='OpenAIRE UsageCounts'></a><span class='uk-text-uppercase uk-margin-small-left'>Views provided by <a href='https://usagecounts.openaire.eu/' target='_blank' class='uk-link-reset'><strong>UsageCounts</strong></a></div>";
}
}
public addEoscPrevInParams(obj) {
if(properties.adminToolsPortalType == "eosc" && this.prevPath) {
let splitted: string[] = this.prevPath.split("?");

View File

@ -34,6 +34,9 @@ import {IconsService} from "../../utils/icons/icons.service";
import {graph} from "../../utils/icons/icons";
import {LoadingModalModule} from "../../utils/modal/loadingModal.module";
import {ResultLandingUtilsModule} from "../landing-utils/resultLandingUtils.module";
import {FullScreenModalModule} from '../../utils/modal/full-screen-modal/full-screen-modal.module';
import {SafeHtmlPipeModule} from '../../utils/pipes/safeHTMLPipe.module';
import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.module";
@NgModule({
imports:
@ -42,7 +45,8 @@ import {ResultLandingUtilsModule} from "../landing-utils/resultLandingUtils.modu
DataProvidersServiceModule, ProjectsServiceModule, SearchResearchResultsServiceModule,
PagingModule, Schema2jsonldModule, SEOServiceModule, ShowPublisherModule, HelperModule,
LandingHeaderModule, AlertModalModule, NoLoadPaging, FeedbackModule,
TabsModule, SearchTabModule, LoadingModule, IconsModule, LoadingModalModule, ResultLandingUtilsModule
TabsModule, SearchTabModule, LoadingModule, IconsModule, LoadingModalModule, ResultLandingUtilsModule,
FullScreenModalModule, SafeHtmlPipeModule, EntityActionsModule
],
declarations:
[StatisticsTabComponent,

View File

@ -83,6 +83,11 @@ export class DataProviderService {
.pipe(map(res => this.parseDataproviderAggregationStatus(res)));
}
// getCollectedFulltexts(datasourceId: string) {
// return this.http.get(properties.pdfStatisticsAPIURL+"/api/stats/getNumberOfPayloadsForDatasource?datasourceId="+datasourceId)
// .pipe(map(res => res))
// }
private handleError (error: HttpErrorResponse) {
// in a real world app, we may send the error to some remote logging infrastructure
// instead of just logging it to the console
@ -360,9 +365,12 @@ export class DataProviderService {
this.dataProviderInfo.journal['lissn'] = data[6]['lissn'];
this.dataProviderInfo.journal['eissn'] = data[6]['eissn'];
}else{
}else {
this.dataProviderInfo.journal = null;
this.dataProviderInfo.journal = {"journal": "", "issn": "", "lissn": "", "eissn": ""};
// this.dataProviderInfo.journal = {"journal": "", "issn": "", "lissn": "", "eissn": ""};
}
if (data[0]?.measure) {
this.dataProviderInfo.measure = this.parsingFunctions.parseMeasures(data[0].measure);
}
return this.dataProviderInfo;

View File

@ -1,59 +1,84 @@
import {
ChangeDetectorRef,
Component,
EventEmitter,
Inject,
Inject, Input,
OnInit,
Output,
RendererFactory2,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {DOCUMENT} from "@angular/common";
import {Subscriber} from "rxjs";
interface addthis {
layers: Refresh;
init: Function;
toolbox: Function;
}
interface Refresh {
refresh: Function;
}
declare var addthis: addthis;
declare var a2a;
@Component({
selector: 'addThis',
template: `
<div id="addThis" class="addthis_inline_share_toolbox_lcx9_8cfy"></div>
<div *ngIf="showWarning" class="uk-alert uk-alert-warning uk-animation-fade" >
Do the share buttons not appear? Please make sure, any blocking addon is disabled, and then reload the page.
</div>
<div [id]="'addToAny'+(url ? ('_'+url) : '')" #addToAny class="a2a_kit a2a_kit_size_42 a2a_default_style fully_rounded" [attr.data-a2a-url]="url">
<a class="a2a_button_twitter"></a>
<a class="a2a_button_facebook"></a>
<a class="a2a_button_linkedin"></a>
<a class="a2a_button_mendeley"></a>
<a class="a2a_button_reddit"></a>
<a class="a2a_button_email"></a>
<a class="a2a_dd" href="https://www.addtoany.com/share"></a>
</div>
<div *ngIf="showWarning" class="uk-alert uk-alert-warning uk-animation-fade">
Do the share buttons not appear? Please make sure, any blocking addon is disabled, and then reload the page.
</div>
`
})
export class AddThisComponent implements OnInit {
subs=[];
subs = [];
showWarning = false;
constructor(private route: ActivatedRoute, @Inject(DOCUMENT) private document, private rendererFactory: RendererFactory2) {}
@Input() url: string = null;
constructor(private route: ActivatedRoute, @Inject(DOCUMENT) private document, private rendererFactory: RendererFactory2) {
}
public ngOnDestroy() {
for(let value of this.subs){
for (let value of this.subs) {
if (value instanceof Subscriber) {
value.unsubscribe();
} else if (value instanceof Function) {
value();
}
}
//
// if(typeof document !== 'undefined') {
// const renderer = this.rendererFactory.createRenderer(this.document, {
// id: '-1',
// encapsulation: ViewEncapsulation.None,
// styles: [],
// data: {}
// });
// const head = this.document.body;
// if (head === null) {
// throw new Error('<head> not found within DOCUMENT.');
// }
//
//
// let script = null;
// head.childNodes.forEach(node => {
// if(node.id === "addToAnyScript") {
// // script = node;
// node.remove();
// }
// })
// // let script = head.nativeElement.getElementById("script");
// // if(script) {
// // renderer.removeChild(head, script);
// // script.remove();
// // }
// }
}
ngOnInit() {
this.subs.push(this.route.queryParams.subscribe(data => {
this.showWarning = false;
try {
if (!this.document.getElementById('addThisScript') && typeof document !== 'undefined') {
// console.log(" create script AddThis");
if (!this.document.getElementById('addToAnyScript') && typeof document !== 'undefined') {
const renderer = this.rendererFactory.createRenderer(this.document, {
id: '-1',
encapsulation: ViewEncapsulation.None,
@ -65,24 +90,23 @@ export class AddThisComponent implements OnInit {
throw new Error('<head> not found within DOCUMENT.');
}
const script = renderer.createElement('script');
renderer.setAttribute(script, "id", "addThisScript");
renderer.setAttribute(script, "src", "https://s7.addthis.com/js/300/addthis_widget.js#pubid=ra-559d24521cd8c080");
renderer.setAttribute(script, "id", "addToAnyScript");
renderer.setAttribute(script, "src", "https://static.addtoany.com/menu/page.js");
renderer.setAttribute(script, "type", "text/javascript");
renderer.appendChild(head, script);
}
if (typeof document !== 'undefined') {
if(typeof addthis !== 'undefined' && addthis.layers && addthis.layers.refresh) {
// console.log("Add This: Call Refresh")
addthis.layers.refresh();
if(typeof a2a !== 'undefined' && this.document.getElementById('addToAny'+(this.url ? ('_'+this.url) : '')) && !this.document.getElementById('addToAny'+(this.url ? ('_'+this.url) : '')).innerText) {
a2a.init_all();
}
}
this.subs.push(setTimeout(() => {
if(this.document.getElementById('addThis') && !this.document.getElementById('addThis').innerText){
if (this.document.getElementById('addToAny'+(this.url ? ('_'+this.url) : '')) && !this.document.getElementById('addToAny'+(this.url ? ('_'+this.url) : '')).innerText) {
this.showWarning = true;
}
}, 4000));
}catch (e) {
// console.error(e)
} catch (e) {
// console.error(e)
}
}));

View File

@ -1,31 +1,60 @@
import {Component, EventEmitter, Input, Output} from '@angular/core';
import {Component, ElementRef, EventEmitter, Input, Output, ViewChild} from '@angular/core';
import {HostedByCollectedFrom} from "../../utils/result-preview/result-preview";
import {properties} from "../../../../environments/environment";
import {StringUtils} from '../../utils/string-utils.class';
import {FullScreenModalComponent} from "../../utils/modal/full-screen-modal/full-screen-modal.component";
declare var UIkit;
import {RouterHelper} from "../../utils/routerHelper.class";
@Component({
selector: 'availableOn',
template: `
<div class="uk-margin-small-bottom uk-flex uk-flex-between">
<span *ngIf="viewAll && !lessBtn" class="clickable uk-h6 uk-flex uk-flex-middle" (click)="viewLessClick()">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
{{title}}
</span>
<span *ngIf="!viewAll || lessBtn" class="uk-margin-small-bottom uk-flex uk-flex-middle">
<span class="uk-text-light-grey uk-margin-small-right">Download from</span>
</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;" class="view-more-less-link">View less</a>
<a *ngIf="availableOn && availableOn.length > threshold && !viewAll" class="view-more-less-link"
(click)="viewAllClick();">View all {{availableOn.length}} sources</a>
</div>
<ng-container *ngIf="availableOn && availableOn.length > 0">
<div class="uk-flex uk-flex-middle" [ngClass]="isMobile && !(usedBy == 'landing') ? 'uk-margin-left uk-margin-xsmall-bottom' : ''">
<ng-container *ngIf="availableOn[0].downloadUrl">
<span [class]="'uk-margin-xsmall-right ' + (availableOn[0].accessRightIcon == 'open_access' ? 'open-access' : 'closed-access')"
uk-tooltip [title]="getAccessLabel(availableOn[0].accessRight)">
<icon [name]="availableOn[0].accessRightIcon" [flex]="true" [ratio]="(isMobile && usedBy == 'landing') ? 1 : 0.8"></icon>
</span>
<ng-container *ngIf="!(isMobile && usedBy == 'landing')">
<a uk-tooltip="Source" target="_blank"
class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder">
<span>{{sliceString(availableOn[0].downloadNames.join("; "), 20)}}</span>
<span>
<!-- <icon [flex]="true" [name]="'expand_' + (isOpen?'less':'more')"></icon>-->
<icon [flex]="true" [name]="(isOpen?'arrow_drop_up':'arrow_drop_down')"></icon>
</span>
</a>
<div #dropElement uk-drop="mode: click; pos: bottom-left;"
class="uk-drop download-drop uk-card uk-card-default uk-padding-small uk-padding-remove-horizontal uk-text-small uk-height-max-large uk-overflow-auto">
<ng-container *ngTemplateOutlet="availableOnList"></ng-container>
</div>
</ng-container>
<ng-container *ngIf="(isMobile && usedBy == 'landing')">
<a class="uk-flex uk-flex-between uk-flex-middle uk-flex-center uk-width-expand uk-button-link" (click)="openAvailableListFsModal()">
<span uk-tooltip="Source">{{sliceString(availableOn[0].downloadNames.join("; "), 20)}}</span>
<span>
<icon [flex]="true" ratio="1.5" name="arrow_right"></icon>
</span>
</a>
<fs-modal #availableListFsModal classTitle="uk-tile-default uk-border-bottom">
<div class="uk-text-small download-drop">
<ng-container *ngTemplateOutlet="availableOnList"></ng-container>
</div>
</fs-modal>
</ng-container>
</ng-container>
</div>
</ng-container>
<div *ngIf="availableOn" class="download-from uk-margin-small-bottom">
<div *ngFor="let instance of availableOn.slice(0, viewAll?availableOn.length:threshold) let i=index"
class="uk-flex uk-flex-top uk-padding-small uk-margin-small-bottom"
uk-tooltip [title]="instance.accessRight ? instance.accessRight : 'Not available'">
<span [class]="'uk-margin-small-right ' + (instance.accessRightIcon == 'lock_open' ? 'uk-text-success' : 'uk-text-meta')"
uk-tooltip [title]="instance.accessRight ? instance.accessRight : 'Not available'">
<icon [name]="instance.accessRightIcon" flex="true" type="outlined"></icon>
<ng-template #availableOnList>
<div *ngFor="let instance of availableOn let i=index" class="download-drop-item uk-flex uk-flex-top">
<span
[class]="'uk-margin-small-right ' + (instance.accessRightIcon == 'open_access' ? 'open-access' : 'closed-access')"
uk-tooltip [title]="getAccessLabel(instance.accessRight)">
<icon [name]="instance.accessRightIcon" [flex]="true"></icon>
</span>
<div class="uk-width-expand uk-padding-small uk-padding-remove-left uk-padding-remove-vertical">
<span class="uk-text-emphasis">
@ -56,36 +85,19 @@ import {RouterHelper} from "../../utils/routerHelper.class";
</div>
</div>
</div>
</div>
<!-- <div *ngIf="showNum > threshold" class="uk-margin-bottom">-->
<!-- <a (click)="showNum = threshold;" class="uk-flex uk-flex-middle uk-flex-center">-->
<!-- <span>View less</span>-->
<!-- <span class="space uk-icon">-->
<!-- <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" data-svg="chevron-up">-->
<!-- <polyline fill="none" stroke="#000" stroke-width="1.03" points="4 13 10 7 16 13"></polyline>-->
<!-- </svg>-->
<!-- </span>-->
<!-- </a>-->
<!-- </div>-->
<!-- <div *ngIf="showNum == threshold && availableOn && availableOn.length > 5" class="uk-margin-bottom">-->
<!-- <a (click)="showNum = availableOn.length;" class="uk-flex uk-flex-middle uk-flex-center">-->
<!-- <span>View more</span>-->
<!-- <span class="space uk-icon">-->
<!-- <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" data-svg="chevron-down">-->
<!-- <polyline fill="none" stroke="#000" stroke-width="1.03" points="16 7 10 13 4 7"></polyline>-->
<!-- </svg>-->
<!-- </span>-->
<!-- </a>-->
<!-- </div>-->
</ng-template>
`
})
export class AvailableOnComponent {
@Input() isMobile: boolean = false;
@Input() usedBy: "search" | "landing" = "search";
@Input() prevPath: string = "";
@Input() availableOn: HostedByCollectedFrom[];
@Input() viewAll: boolean = false;
@Output() viewAllClicked = new EventEmitter();
public lessBtn: boolean = false;
/** @deprecated */
@Output() viewAllClicked = new EventEmitter();
@ViewChild("dropElement") dropElement: ElementRef;
@ViewChild("availableListFsModal") availableListFsModal: FullScreenModalComponent;
public threshold: number = 1;
public dataProviderUrl = properties.searchLinkToDataProvider.split('?')[0];
public title: string = "Download from";
@ -93,39 +105,39 @@ export class AvailableOnComponent {
constructor() {
}
ngOnInit() {}
public removeUnknown(value: string): string {
if (value.toLowerCase() === 'unknown') {
return null;
}
return value;
ngOnInit() {
}
public getKeys( map) {
public getKeys(map) {
return Array.from(map.keys());
}
public viewAllClick() {
if(this.availableOn.length <= this.threshold*2) {
this.viewAll = true;
this.lessBtn = true;
} else {
this.viewAll = true;
this.viewAllClicked.emit('availableOn');
}
}
public viewLessClick() {
this.viewAll = false;
this.viewAllClicked.emit("");
}
public isUrl(str: string): boolean {
return str.startsWith('http://') || str.startsWith('https://') || str.startsWith('//') || str.startsWith('www.');
}
get isOpen() {
return (typeof document !== 'undefined') && this.dropElement && UIkit.drop(this.dropElement.nativeElement).isActive();
}
public sliceString(str: string, size: number) {
return StringUtils.sliceString(str, size)
}
public openAvailableListFsModal() {
this.availableListFsModal.title = "Sources";
this.availableListFsModal.okButton = false;
this.availableListFsModal.open();
}
public getAccessLabel(accessRight) : string {
if(accessRight) {
return (accessRight + (accessRight.toLowerCase().endsWith(" access") ? "" : " access"));
}
return "Not available access";
}
public addEoscPrevInParams(obj) {
if(properties.adminToolsPortalType == "eosc" && this.prevPath) {
let splitted: string[] = this.prevPath.split("?");

View File

@ -13,6 +13,7 @@ import {DOCUMENT} from "@angular/common";
import {EnvProperties} from "../../../utils/properties/env-properties";
import {properties} from "../../../../../environments/environment";
import {PiwikService} from "../../../utils/piwik/piwik.service";
import {ResultPreview} from "../../../utils/result-preview/result-preview";
declare var Cite: any;
// Based on https://citation.js.org/api/tutorial-getting_started.html browser release
@ -20,7 +21,7 @@ declare var Cite: any;
@Component({
selector: 'citeThis',
template: `
<div class="uk-padding uk-padding-remove-top uk-height-large uk-overflow-auto">
<div class="uk-padding uk-padding-remove-top uk-height-min-large">
<div input type="select" placeholder="Select a citation style" inputClass="flat x-small"
[options]="citation.templates" [(value)]="selectedStyle"
(valueChange)="styleChanged()"></div>
@ -53,7 +54,7 @@ export class CiteThisComponent implements OnInit, OnDestroy {
properties:EnvProperties;
public citationText: string;
public citation: Citation = new Citation();
@Input() result: ResultLandingInfo;
@Input() result: any;
@Input() id: string;
@Input() type: string = "article";
@Input() piwikSiteId;
@ -256,7 +257,7 @@ export class CiteThisComponent implements OnInit, OnDestroy {
/**
* Based on this and citeproc library https://citation.js.org/api/tutorial-plugins.html
* if the template doesn;t exist add the CSL xml and the library will produce the citation
* if the template doesn't exist add the CSL xml and the library will produce the citation
* @param template
*/

View File

@ -0,0 +1,11 @@
@import (reference) "~src/assets/openaire-theme/less/_import-variables";
.entity-metadata {
& > *:not(:last-child):not(.other-separator)::after {
content: "\2022";
font-weight: normal;
margin-left: @global-xsmall-margin;
margin-right: @global-xsmall-margin;
}
}

View File

@ -0,0 +1,263 @@
import {Component, Input} from "@angular/core";
import {EnvProperties} from "../../utils/properties/env-properties";
import {properties} from "../../../../environments/environment";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {Organization, Project} from "../../utils/result-preview/result-preview";
import {RouterHelper} from "../../utils/routerHelper.class";
@Component({
selector: 'entity-metadata',
template: `
<div class="uk-text-xsmall entity-metadata uk-flex-inline uk-flex-wrap uk-text-emphasis">
<!-- oa -->
<span class="uk-flex-inline uk-flex-middle uk-flex-wrap"
*ngIf="(openAccessMandatePublications != undefined && openAccessMandatePublications) || (openAccessMandateDatasets != undefined && openAccessMandateDatasets)">
<span class="uk-margin-xsmall-right open-access">
<icon name="open_access" [flex]="true" [ratio]="0.8"></icon>
</span>
<span class="uk-text-bolder"
*ngIf="openAccessMandatePublications != undefined && openAccessMandatePublications && openAccessMandateDatasets != undefined && openAccessMandateDatasets">
Open Access Mandate for {{openaireEntities.PUBLICATIONS}} and {{openaireEntities.DATASETS}}
</span>
<span class="uk-text-bolder"
*ngIf="openAccessMandatePublications != undefined && openAccessMandatePublications && (openAccessMandateDatasets == undefined || !openAccessMandateDatasets)">
Open Access Mandate for {{openaireEntities.PUBLICATIONS}}
</span>
<span class="uk-text-bolder"
*ngIf="openAccessMandateDatasets != undefined && openAccessMandateDatasets && (openAccessMandatePublications == undefined || !openAccessMandatePublications)">
Open Access Mandate for {{openaireEntities.DATASETS}}
</span>
</span>
<!-- types -->
<span *ngIf="entityType" class="uk-flex-inline uk-flex-middle uk-flex-wrap"
[class.other-separator]="types && removeUnknown(types, true).length > 0">
<span class="uk-margin-xsmall-right">
<icon *ngIf="entityType.toLowerCase() == 'publication'" name="description" type="outlined"
[flex]="true" [ratio]="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'research data'" name="database" type="outlined"
[flex]="true" [ratio]="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'research software'" name="integration_instructions"
type="outlined" [flex]="true" [ratio]="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'other research product'" name="apps" type="outlined"
[flex]="true" [ratio]="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'project'" name="assignment_turned_in" type="outlined"
[flex]="true" [ratio]="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'data source'" name="note_add" type="outlined"
[flex]="true" [ratio]="0.8"></icon>
<icon *ngIf="entityType.toLowerCase() == 'organization'" name="corporate_fare" type="outlined"
[flex]="true" [ratio]="0.8"></icon>
</span>
<u class="uk-text-capitalize uk-text-bolder">{{entityType}}</u>
<span *ngIf="types && removeUnknown(types, true).length > 0">
<icon name="keyboard_double_arrow_right" [flex]="true" [ratio]="0.8"></icon>
</span>
</span>
<span *ngIf="types && removeUnknown(types, true).length > 0" class="uk-text-italic">
{{removeUnknown(types, true).join(' , ')}}
</span>
<!-- years -->
<ng-container *ngIf="year">
<span>{{year}}</span>
</ng-container>
<ng-container *ngIf="startYear && !endYear">
<span>{{startYear}}</span>
</ng-container>
<ng-container *ngIf="!startYear && endYear">
<span>{{endYear}}</span>
</ng-container>
<ng-container *ngIf="startYear && endYear">
<ng-container>
<span>{{startYear}} - {{endYear}}</span>
</ng-container>
</ng-container>
<!-- dates -->
<span *ngIf="startDate && !endDate">
<span class="uk-margin-xsmall-right">From</span>
<span>{{startDate | date: 'dd MMM yyyy'}}</span>
</span>
<span *ngIf="!startDate && endDate">
<span class="uk-margin-xsmall-right">Until</span>
<span>{{endDate | date: 'dd MMM yyyy'}}</span>
</span>
<span *ngIf="startDate && endDate">
<ng-container *ngIf="startDate">
<span>{{startDate | date: 'dd MMM yyyy'}}</span>
<span class="uk-margin-xsmall-left">(Started)</span>
</ng-container>
<span *ngIf="startDate && endDate" class="uk-margin-xsmall-left uk-margin-xsmall-right">-</span>
<ng-container *ngIf="endDate">
<span>{{endDate | date: 'dd MMM yyyy'}}</span>
<span class="uk-margin-xsmall-left">{{currentDate >= endDate ? '(Ended)' : '(Ending)'}}</span>
</ng-container>
</span>
<ng-container *ngIf="status">
<span>{{status}}</span>
</ng-container>
<ng-container *ngIf="date">
<span>{{date | date: 'dd MMM yyyy': 'UTC'}}</span>
</ng-container>
<ng-container *ngIf="embargoEndDate">
<span>Embargo end date: {{embargoEndDate | date: 'dd MMM yyyy'}}</span>
</ng-container>
<span *ngIf="underCuration">
<span title="{{buildCurationTooltip()}}" uk-tooltip="pos:bottom-right; delay:10;"
class="uk-text-primary">Under curation</span>
</span>
<!-- countries -->
<span *ngIf="countries && removeUnknown(countries).length > 0">
{{removeUnknown(countries).join(', ')}}
</span>
<!-- languages -->
<span *ngIf="languages && removeUnknown(languages).length > 0">
{{removeUnknown(languages).join(', ')}}
</span>
<!-- programming languages -->
<span *ngIf="programmingLanguages && removeUnknown(programmingLanguages).length > 0"
class="uk-flex uk-flex-middle uk-flex-wrap">
{{removeUnknown(programmingLanguages).join(', ')}}
</span>
<!-- published info -->
<showPublisher *ngIf="publisher || journal" [publisher]="publisher" [journal]="journal"
[properties]="properties"></showPublisher>
<!-- data provider labels -->
<ng-container *ngIf="compatibility && !(compatibility.info == 'not available' && type == 'service')">
<span uk-tooltip title="Compatibility">
<a *ngIf="compatibility.id"
[queryParams]="addEoscPrevInParams({datasourceId: compatibility.id})" routerLinkActive="router-link-active"
[routerLink]="properties.searchLinkToDataProvider.split('?')[0]">
{{compatibility.info}}
<ng-container *ngIf="compatibility.name">{{compatibility.name}}</ng-container>
</a>
<span *ngIf="!compatibility.id && compatibility.info">
<ng-container
*ngIf="compatibility.info.toLowerCase() != 'not yet registered'">{{compatibility.info}}</ng-container>
<ng-container *ngIf="compatibility.info.toLowerCase() == 'not yet registered'">
{{compatibility.info}} <span *ngIf="properties.adminToolsPortalType == 'eosc'">in OpenAIRE</span>
</ng-container>
</span>
<span *ngIf="compatibility.name && !compatibility.id">
{{compatibility.name}}
</span>
</span>
</ng-container>
<ng-container *ngIf="compatibilityString">
<span uk-tooltip title="Compatibility">{{compatibilityString}}</span>
</ng-container>
<ng-container
*ngIf="aggregationStatus && aggregationStatus.fulltexts && aggregationStatus.fulltexts > 0">
<span>OpenAIRE Text Mining</span>
</ng-container>
<ng-container *ngIf="thematic">
<span>Thematic</span>
</ng-container>
<!-- Projects -->
<span uk-tooltip="Projects" *ngIf="projects && projects.length > 0" [class.truncated]="projects.length > 3">
{{projectNames.slice(0,3).join(', ')}}
</span>
<!-- Organizations -->
<span uk-tooltip="Partners" *ngIf="organizations && organizations.length > 0" [class.truncated]="organizations.length > 3">
{{organizationNames.slice(0, 3).join(', ')}}
</span>
<!-- Subjects -->
<span uk-tooltip="Subjects" *ngIf="subjects && subjects.length > 0" [class.truncated]="subjects.length > 3">
{{subjects.slice(0, 3).join(', ')}}
</span>
<ng-container *ngIf="provenanceAction">
<span>{{provenanceAction}}</span>
</ng-container>
<ng-container *ngIf="relationName">
<span>{{relationName}}</span>
</ng-container>
</div>
`,
styleUrls: ['entity-metadata.component.less']
})
export class EntityMetadataComponent {
@Input() entityType: string;
@Input() types: string[];
@Input() year: string; // search result
@Input() startDate: number; // project landing
@Input() startYear: string; // search result
@Input() endDate: number; // project landing
@Input() endYear: string; // search result
@Input() currentDate: number; // project landing
@Input() status: string; // project landing
@Input() openAccessMandatePublications: boolean // project landing
@Input() openAccessMandateDatasets: boolean // project landing
@Input() date: Date;
@Input() embargoEndDate: Date | string;
@Input() underCuration: boolean = false;
@Input() publisher; // showPublisher component
@Input() journal; // showPublisher component
@Input() countries;
@Input() languages;
@Input() programmingLanguages;
@Input() compatibilityString: string;
@Input() compatibility; // data provider landing
@Input() aggregationStatus; // data provider landing
@Input() thematic: boolean; // data provider landing
@Input() type; // data provider landing
@Input() provenanceAction: string; // search result
@Input() relationName: string; // search result
@Input() projects: Project[];
@Input() organizations: Organization[];
@Input() subjects: string[];
@Input() prevPath: string = "";
properties: EnvProperties = properties;
public openaireEntities = OpenaireEntities;
public routerHelper: RouterHelper = new RouterHelper();
public removeUnknown(array: string[], type: boolean = false): string[] {
if (type) {
return this.removeDuplicates(array).filter(value => value.toLowerCase() !== 'unknown');
} else {
return array.filter(value => value.toLowerCase() !== 'unknown');
}
}
public removeDuplicates(array: string[]): string[] {
return array.filter(value => value.toLowerCase() !== this.entityType);
}
public buildCurationTooltip(): string {
let tooltipContent: string = "<div class='uk-padding-small'>";
tooltipContent += "<h5>Record in preview</h5>";
tooltipContent += "<p>Bibliographic record accepted by the system, but not yet processed by <br> OpenAIRE tools for information quality improvement and de-duplication</p>";
tooltipContent += "</div>";
return tooltipContent;
}
get projectNames(): string[] {
if (this.projects && this.projects.length > 0) {
return this.projects.map(project => {
let value = project.funderShortname ? project.funderShortname : project.funderName;
if (project.acronym || project.title) {
value = value + ' | ' + (project.acronym ? project.acronym :
(project.title.length > 25 ? (project.title.slice(0, 25) + '...'): project.title));
}
if(project.code) {
value = value + ' (' + project.code + ')';
}
return value;
});
}
return [];
}
get organizationNames(): string[] {
if (this.organizations && this.organizations.length > 0) {
return this.organizations.map(organization => organization.name);
}
return [];
}
public addEoscPrevInParams(obj) {
if(properties.adminToolsPortalType == "eosc" && this.prevPath) {
return this.routerHelper.addQueryParam("pv", this.prevPath, obj);
}
return obj;
}
}

View File

@ -6,45 +6,75 @@ import {StringUtils} from "../../utils/string-utils.class";
@Component({
selector: 'fos',
template: `
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
<div [class]="'uk-flex uk-flex-between uk-flex-middle uk-margin-'+(viewAll?'':'small-')+'bottom'">
<span *ngIf="viewAll" class="clickable uk-h6 uk-flex uk-flex-middle uk-margin-small-right uk-margin-remove-bottom" (click)="viewLessClick()">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
<span class="uk-text-nowrap">{{title}}</span>
</span>
<span *ngIf="!viewAll" class="uk-text-light-grey uk-text-nowrap uk-margin-small-right">{{title}}</span>
<!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>-->
<a *ngIf="properties.adminToolsPortalType == 'eosc' && subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate" uk-tooltip="View all">
<span class="">View all</span>
</a>
<a *ngIf="properties.adminToolsPortalType !== 'eosc' && subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate" uk-tooltip="View all & feedback">
<span class="">View all & feedback</span>
</a>
<a *ngIf="properties.adminToolsPortalType !== 'eosc' && (subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-text-truncate"
(click)="feedbackClick();">Feedback</a>
</div>
<div class="uk-margin-small-top">
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate">
<a *ngIf="properties.adminToolsPortalType !== 'eosc'"
[routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subject)}">
{{subject}}
<div class="uk-visible@m">
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
<div [class]="'uk-flex uk-flex-between uk-flex-middle uk-margin-'+(viewAll?'':'small-')+'bottom'">
<span *ngIf="viewAll" class="clickable uk-h6 uk-flex uk-flex-middle uk-margin-small-right uk-margin-remove-bottom" (click)="viewLessClick()">
<icon class="uk-margin-small-right" name="arrow_back" [flex]="true" [ratio]="1.2"></icon>
<span class="uk-text-nowrap">{{title}}</span>
</span>
<span *ngIf="!viewAll" class="uk-text-emphasis uk-text-bolder uk-text-nowrap uk-margin-small-right">
{{title}}
<span *ngIf="subjects && subjects.length > threshold && !viewAll">({{subjects.length}})</span>
</span>
<a *ngIf="properties.adminToolsPortalType == 'eosc' && subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-link uk-link-text uk-text-truncate">
View all
</a>
<a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank"
[href]="'https://explore.openaire.eu'+properties.searchLinkToResults+'?fos='+urlEncodeAndQuote(subject)">
{{subject}}
<!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a> -->
<a *ngIf="properties.adminToolsPortalType != 'eosc' && subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-link uk-link-text uk-text-truncate">
View all & suggest
</a>
<a *ngIf="properties.adminToolsPortalType != 'eosc' && (subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-link-text uk-text-truncate"
(click)="suggestClick();">Suggest</a>
</div>
<div class="uk-margin-small-top">
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate">
<a [routerLink]="properties.searchLinkToResults"
[queryParams]="{'fos': urlEncodeAndQuote(subject.id)}">
{{subject.label}}
</a>
</div>
</div>
</div>
<div class="uk-hidden@m">
<div class="uk-grid uk-grid-small uk-grid-divider" uk-grid>
<div class="uk-width-1-4 uk-text-meta">
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
{{title}}
</div>
<div class="uk-width-expand">
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate">
<a *ngIf="properties.adminToolsPortalType != 'eosc'"
[routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subject.id)}">
{{subject.label}}
</a>
<a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank"
[href]="'https://explore.openaire.eu'+properties.searchLinkToResults+'?fos='+urlEncodeAndQuote(subject.id)">
{{subject.label}}
</a>
</div>
</div>
</div>
<div class="uk-text-right uk-margin-small-top">
<a *ngIf="subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate">
<span class="">View all</span>
<!-- <span class="">View all & suggest</span>-->
</a>
<!-- <a *ngIf="(subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-text-truncate"-->
<!-- (click)="feedbackClick();">Feedback</a>-->
</div>
</div>
</div>
`
})
export class FosComponent {
@Input() subjects: string[];
@Input() subjects: {"id": string, "label": string}[];
@Input() viewAll: boolean = false;
@Output() viewAllClicked = new EventEmitter();
@Output() feedbackClicked = new EventEmitter();
@Output() suggestClicked = new EventEmitter();
public lessBtn: boolean = false;
public threshold: number = 2;
public routerHelper: RouterHelper = new RouterHelper();
@ -66,8 +96,8 @@ export class FosComponent {
this.viewAllClicked.emit("");
}
public feedbackClick() {
this.feedbackClicked.emit("");
public suggestClick() {
this.suggestClicked.emit('fos');
}
public urlEncodeAndQuote(str: string): string {

View File

@ -7,72 +7,94 @@ import {RouterHelper} from "../../utils/routerHelper.class";
@Component({
selector: 'fundedBy',
template: `
<div class="uk-margin-small-bottom uk-flex uk-flex-between">
<div *ngIf="!isMobile" class="uk-margin-small-bottom uk-flex uk-flex-between">
<span *ngIf="viewAll && !lessBtn" class="clickable uk-h6 uk-flex uk-flex-middle" (click)="viewLessClick()">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
{{title}}
</span>
<span *ngIf="!viewAll || lessBtn" class="uk-text-light-grey">{{title}}</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;" class="view-more-less-link">View less</a>
<span *ngIf="!viewAll || lessBtn" class="uk-text-emphasis uk-text-bolder">{{title}}</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;"
class="view-more-less-link uk-link-text">View less</a>
<a *ngIf="fundedByProjects && fundedByProjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link">View all</a>
(click)="viewAllClick();" class="view-more-less-link uk-link-text">View all</a>
</div>
<div>
<div *ngIf="!isMobile">
<span *ngFor="let item of fundedByProjects.slice(0, viewAll?fundedByProjects.length:threshold) let i=index">
<span class="uk-text-emphasis">
<a class="uk-link uk-link-text">
<span
*ngIf="item['funderShortname'] || item['funderName']">{{item['funderShortname'] ? item['funderShortname'] : item['funderName']}}</span>
<span *ngIf="!item['funderShortname'] && !item['funderName']">[no funder available]</span>
<span
*ngIf="item['acronym'] || item['title']">| {{ item['acronym'] ? item['acronym'] : item['title']}}</span>
</a>
</span>
<div class="default-dropdown uk-margin-remove-top uk-dropdown"
uk-dropdown="pos: bottom-left; mode:click">
<div class="uk-padding-small">
<span>Project</span>
<div class="uk-margin-bottom">
<a *ngIf="item.id" class="uk-h6 uk-margin-remove portal-link"
[queryParams]="addEoscPrevInParams({projectId: item.id})" [routerLink]="url">
{{item['acronym'] ? item['acronym'] : item['title']}}
</a>
<span *ngIf="!item.id" class="uk-h6 uk-margin-remove">
<span class="uk-text-emphasis">
<a class="uk-link uk-link-text">
<ng-container *ngTemplateOutlet="funder; context: {item: item}"></ng-container>
</a>
</span>
<div class="default-dropdown uk-margin-remove-top uk-dropdown"
uk-dropdown="pos: bottom-left; mode:click">
<ng-container *ngTemplateOutlet="dropInfo; context: { item: item}"></ng-container>
</div>
<span *ngIf="i < (fundedByProjects.slice(0, viewAll?fundedByProjects.length:threshold).length - 1)">, </span>
</span>
</div>
<div *ngIf="isMobile">
<div *ngFor="let item of fundedByProjects.slice(0, viewAll?fundedByProjects.length:threshold) let i=index"
class="uk-flex uk-flex-between uk-flex-middle uk-margin-small-bottom">
<span class="uk-text-emphasis">
<ng-container *ngTemplateOutlet="funder; context: {item: item}"></ng-container>
</span>
<icon name="info" visuallyHidden="info" [type]="'outlined'" class="uk-link"></icon>
<div class="default-dropdown uk-margin-remove-top uk-dropdown"
uk-dropdown="pos: bottom-left; mode:click">
<ng-container *ngTemplateOutlet="dropInfo; context: { item: item}"></ng-container>
</div>
</div>
</div>
<ng-template #funder let-item=item>
<span
*ngIf="item['funderShortname'] || item['funderName']">{{item['funderShortname'] ? item['funderShortname'] : item['funderName']}}</span>
<span *ngIf="!item['funderShortname'] && !item['funderName']">[no funder available]</span>
<span *ngIf="item['acronym'] || item['title']">| {{ item['acronym'] ? item['acronym'] : item['title']}}</span>
</ng-template>
<ng-template #dropInfo let-item=item>
<div class="uk-padding-small">
<span>Project</span>
<div class="uk-margin-bottom">
<a *ngIf="item.id" class="uk-h6 uk-margin-remove portal-link"
[queryParams]="addEoscPrevInParams({projectId: item.id})" [routerLink]="url">
{{item['acronym'] ? item['acronym'] : item['title']}}
</a>
<span *ngIf="!item.id" class="uk-h6 uk-margin-remove">
{{item['acronym'] ? item['acronym'] : item['title']}}
</span>
<div *ngIf="item.acronym && item.title" class="uk-text-meta">
{{item.title}}
</div>
</div>
<ul class="uk-list uk-padding-remove-left uk-margin-bottom">
<li *ngIf="item.funderShortname || item.funderName">
<span class="uk-text-meta">Funder: </span>
{{item.funderName ? item.funderName : item.funderShortname}}
<span *ngIf="item.funderShortname && item.funderName">
<div *ngIf="item.acronym && item.title" class="uk-text-meta">
{{item.title}}
</div>
</div>
<ul class="uk-list uk-padding-remove-left uk-margin-bottom">
<li *ngIf="item.funderShortname || item.funderName">
<span class="uk-text-meta">Funder: </span>
{{item.funderName ? item.funderName : item.funderShortname}}
<span *ngIf="item.funderShortname && item.funderName">
({{item.funderShortname}})
</span>
</li>
<li *ngIf="item.code">
<span class="uk-text-meta">Project Code: </span>{{item.code}}
</li>
<li *ngIf="item.funding">
<span class="uk-text-meta">Funding stream: </span>{{item.funding}}
</li>
</ul>
<div *ngIf="getVocabularyLabel(item, provenanceActionVocabulary, i) || item.validated" class="uk-text-meta">
<span *ngIf="item.validated">Validated by funder</span>
<span *ngIf="item.provenanceAction && item.validated"> | </span>
<span *ngIf="item.provenanceAction">{{item.provenanceAction}}</span>
</div>
</div>
</div>
<span *ngIf="i < (fundedByProjects.slice(0, viewAll?fundedByProjects.length:threshold).length - 1)">, </span>
</span>
</div>
</li>
<li *ngIf="item.code">
<span class="uk-text-meta">Project Code: </span>{{item.code}}
</li>
<li *ngIf="item.funding">
<span class="uk-text-meta">Funding stream: </span>{{item.funding}}
</li>
</ul>
<div *ngIf="getVocabularyLabel(item, provenanceActionVocabulary, i) || item.validated" class="uk-text-meta">
<span *ngIf="item.validated">Validated by funder</span>
<span *ngIf="item.provenanceAction && item.validated"> | </span>
<span *ngIf="item.provenanceAction">{{item.provenanceAction}}</span>
</div>
</div>
</ng-template>
`
})
export class FundedByComponent {
@Input() isMobile: boolean = false;
@Input() prevPath: string = "";
@Input() fundedByProjects: Project[];
@Input() viewAll: boolean = false;

View File

@ -4,100 +4,61 @@ import {Author} from "../../../utils/result-preview/result-preview";
import {AlertModal} from "../../../utils/modal/alert";
@Component({
selector: 'landing-header',
template: `
<div class="title-section" [class.uk-margin-bottom]="!isSticky" [ngClass]="titleClass">
<div class="uk-text-small">
<span *ngIf="entityType" class="uk-text-capitalize uk-text-small">
{{entityType}}
</span>
<span *ngIf="types && removeUnknown(types, true).length > 0">
{{(entityType?' . ':'') + removeUnknown(types, true).join(' . ')}}
</span>
<span>
<span *ngIf="startDate || endDate">
{{' . '}}
</span>
<span *ngIf="startDate && !endDate">
{{'from '}}
</span>
<span *ngIf="!startDate && endDate">
{{'until '}}
</span>
<span *ngIf="startDate">
{{startDate | date: 'yyyy'}}
</span>
<span *ngIf="startDate && endDate">
{{' - '}}
</span>
<span *ngIf="endDate">
{{endDate | date: 'yyyy'}}
</span>
</span>
<span *ngIf="status && status != ''">
{{' . ' + status}}
</span>
<span *ngIf="year && year != ''">
{{' . ' + year}}
</span>
<span *ngIf="embargoEndDate">
. Embargo end date: {{embargoEndDate | date: 'dd MMM yyyy'}}
</span>
<span *ngIf="underCuration">
. <span title="{{buildCurationTooltip()}}"
uk-tooltip="pos:bottom-right; delay:10;"
class="uk-text-primary">Under curation</span>
</span>
</div>
<div [class]="isSticky ? 'uk-margin-bottom' : 'uk-margin-medium-bottom'">
<showTitle [titleName]="title" classNames="uk-margin-remove-bottom"></showTitle>
<div *ngIf="subTitle">
<span class="uk-text-meta uk-text-small" [innerHTML]="subTitle"></span>
</div>
</div>
<div *ngIf="authors">
<showAuthors [authorsLimit]="authorLimit" [modal]="modal" [showAll]="showAllAuthors" [authors]="authors" [isSticky]="isSticky"></showAuthors>
</div>
</div>`
selector: 'landing-header',
template: `
<div class="title-section" [class.uk-margin-small-bottom]="!isSticky" [ngClass]="titleClass">
<div class="uk-margin-small-bottom">
<showTitle [isSticky]=isSticky [titleName]="title" classNames="uk-margin-remove-bottom"></showTitle>
<div *ngIf="subTitle && !isSticky">
<span class="uk-text-meta uk-text-small" [innerHTML]="subTitle"></span>
</div>
</div>
<div *ngIf="!isSticky" class="uk-margin-bottom">
<entity-metadata [entityType]="entityType" [types]="types" [startDate]="startDate" [endDate]="endDate"
[currentDate]="currentDate" [status]="status" [openAccessMandatePublications]="openAccessMandatePublications"
[openAccessMandateDatasets]="openAccessMandateDatasets" [date]="date" [embargoEndDate]="embargoEndDate"
[underCuration]="underCuration" [publisher]="publisher" [journal]="journal"
[languages]="languages" [programmingLanguages]="programmingLanguages"
[compatibility]="compatibility" [aggregationStatus]="aggregationStatus"
[thematic]="thematic" [type]="type" [prevPath]="prevPath"
></entity-metadata>
</div>
<div *ngIf="authors">
<showAuthors [authorsLimit]="authorLimit" [modal]="modal" [showAll]="showAllAuthors" [authors]="authors"
[isSticky]="isSticky" [isMobile]="isMobile"></showAuthors>
</div>
</div>
`
})
export class LandingHeaderComponent {
@Input() entityType: string;
@Input() properties: EnvProperties;
@Input() types: string[];
@Input() startDate: number; // project landing
@Input() endDate: number; // project landing
@Input() status: string; // project landing
@Input() year: string;
@Input() embargoEndDate: Date;
@Input() title: string;
@Input() subTitle: string;
@Input() authors: Author[];
@Input() authorLimit: number = 7;
@Input() showAllAuthors: boolean = true;
@Input() underCuration: boolean = false;
@Input() modal: AlertModal;
@Input() titleClass: string = null;
@Input() isTitleH1:boolean =true;
@Input() isSticky: boolean = false;
public removeUnknown(array: string[], type: boolean = false): string[] {
if (type) {
return this.removeDuplicates(array).filter(value => value.toLowerCase() !== 'unknown');
} else {
return array.filter(value => value.toLowerCase() !== 'unknown');
}
}
public removeDuplicates(array: string[]): string[] {
return array.filter(value => value.toLowerCase() !== this.entityType);
}
public buildCurationTooltip(): string {
let tooltipContent: string = "<div class='uk-padding-small'>";
tooltipContent += "<h5>Record in preview</h5>";
tooltipContent += "<p>Bibliographic record accepted by the system, but not yet processed by <br> OpenAIRE tools for information quality improvement and de-duplication</p>";
tooltipContent += "</div>";
return tooltipContent;
}
@Input() isMobile: boolean = false;
@Input() entityType: string;
@Input() properties: EnvProperties;
@Input() types: string[];
@Input() startDate: number; // project landing
@Input() endDate: number; // project landing
@Input() currentDate: number; // project landing
@Input() status: string; // project landing
@Input() openAccessMandatePublications: boolean // project landing
@Input() openAccessMandateDatasets: boolean // project landing
@Input() date: Date;
@Input() embargoEndDate: Date;
@Input() title: string;
@Input() subTitle: string;
@Input() authors: Author[];
@Input() authorLimit: number = 7;
@Input() showAllAuthors: boolean = true;
@Input() underCuration: boolean = false;
@Input() modal: AlertModal;
@Input() titleClass: string = null;
@Input() isSticky: boolean = false;
@Input() publisher; // showPublisher component
@Input() journal; // showPublisher component
@Input() languages;
@Input() programmingLanguages;
@Input() compatibility; // data provider landing
@Input() aggregationStatus; // data provider landing
@Input() thematic: boolean; // data provider landing
@Input() type; // data provider landing
@Input() prevPath: string = "";
}

View File

@ -3,10 +3,14 @@ import {LandingHeaderComponent} from "./landing-header.component";
import {CommonModule} from "@angular/common";
import {LandingModule} from "../landing.module";
import {ShowAuthorsModule} from "../../../utils/authors/showAuthors.module";
import {IconsModule} from "src/app/openaireLibrary/utils/icons/icons.module";
import {ShowPublisherModule} from "../showPublisher.module";
import {RouterModule} from "@angular/router";
import {ResultLandingUtilsModule} from "../resultLandingUtils.module";
@NgModule({
imports: [CommonModule, LandingModule, ShowAuthorsModule],
imports: [CommonModule, LandingModule, ShowAuthorsModule, IconsModule, ShowPublisherModule, RouterModule, ResultLandingUtilsModule],
declarations: [LandingHeaderComponent],
exports: [LandingHeaderComponent]
})
export class LandingHeaderModule {}
export class LandingHeaderModule {}

View File

@ -1,5 +1,5 @@
import {HostedByCollectedFrom, Journal, Project, RelationResult} from "../../utils/result-preview/result-preview";
import {Context, Reference} from "../../utils/entities/resultLandingInfo";
import {HostedByCollectedFrom, Project, RelationResult} from "../../utils/result-preview/result-preview";
import {Context, Measure, Metric, Reference} from "../../utils/entities/resultLandingInfo";
import {Injectable} from '@angular/core';
import {properties} from "../../../../environments/environment";
import {StringUtils} from "../../utils/string-utils.class";
@ -15,18 +15,17 @@ export class ParsingFunctions {
{label: 'EOSC::Twitter Data', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'search.marketplace.eosc-portal.eu/search/service?q=*&fq=tag_list:%22EOSC%5C:%5C:Twitter%20Data%22', value: 'Twitter Data'},
{label: 'EOSC::Data Cube', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'search.marketplace.eosc-portal.eu/search/service?q=*&fq=tag_list:%22EOSC%5C:%5C:Data%20Cube%22', value: 'Data Cube'}
]
public notebookInSubjects: boolean = false;
private notebookKeyword: string = "eosc jupyter notebook";
private notebook_label: string = "EOSC";
private notebook_value: string = "EOSC Jupyter Notebook";
public open = 'lock_open';
public closed = 'lock';
public unknown = 'question_mark';
public open = 'open_access';
public closed = 'closed_access';
public unknown = 'unknown_access';
private instanceWithDoiExists: boolean = false;
constructor() {
}
@ -49,10 +48,10 @@ export class ParsingFunctions {
fundedByProject['acronym'] = relation.acronym;
fundedByProject['title'] = relation.title;
fundedByProject['code'] = relation.code;
if(relation.validated && relation.validated.date) {
if (relation.validated && relation.validated.date) {
fundedByProject['validated'] = true;
}
fundedByProject['provenanceAction'] = relation.provenanceaction;
fundedByProject['provenanceAction'] = relation.provenanceaction;
} else {
fundedByProject['id'] = "";
fundedByProject['acronym'] = "";
@ -156,7 +155,7 @@ export class ParsingFunctions {
// publication & dataset landing : for downloadFrom
addPublisherToHostedBy_collectedFrom(hostedBy_collectedFrom: HostedByCollectedFrom[],
publisher: string, journal: Journal,
publisher: string, journal: string,
identifiers: Map<string, string[]>/*, title: { "name": string, "url": string, "accessMode": string}*/) {
if (!this.instanceWithDoiExists && publisher && identifiers != null && identifiers.has('doi')) {
if (hostedBy_collectedFrom == null) {
@ -171,14 +170,14 @@ export class ParsingFunctions {
years: [],
accessRightIcon: ""
};
if (journal && journal.journal) {
if (journal) {
available.downloadNames.push(publisher + "/ " + journal['journal']);
} else {
available.downloadNames.push(publisher);
}
available.downloadUrl = properties.doiURL + identifiers.get("doi")[0];;
available.downloadUrl = properties.doiURL + identifiers.get("doi")[0];
available.accessRightIcon = this.unknown;
/*
if(title != undefined && title['url'] == "") {
@ -250,13 +249,13 @@ export class ParsingFunctions {
mapStructure.get(key)['accessMode'].push("");
}
}
parseHostedBy_collectedFrom(hostedBy_collectedFrom: HostedByCollectedFrom[],
instance: any, url: string, globalAccessRight: string) {
if(!url) {
if (!url) {
return;
}
let available: HostedByCollectedFrom = {
"downloadNames": [],
"downloadUrl": null,
@ -278,34 +277,34 @@ export class ParsingFunctions {
}
}
available.downloadNames = Array.from(downloadNames);
if (available.downloadNames.length == 0) {
available.downloadNames.push(url.substring(0, 30) + '...'); // substring(from, to);
}
}
if (instance.hasOwnProperty("collectedfrom")) {
let length = Array.isArray(instance['collectedfrom']) ? instance['collectedfrom'].length : 1;
for (let i = 0; i < length; i++) {
let collectedFrom = Array.isArray(instance['collectedfrom']) ? instance['collectedfrom'][i] : instance['collectedfrom'];
if(collectedFrom.name && collectedFrom.id) {
if (collectedFrom.name && collectedFrom.id) {
available.collectedNamesAndIds.set(String(collectedFrom.name), collectedFrom.id);
}
}
}
if (instance.hasOwnProperty("instancetype")) {
let types: Set<string> = new Set();
let length = Array.isArray(instance['instancetype']) ? instance['instancetype'].length : 1;
for (let i = 0; i < length; i++) {
let instanceType = Array.isArray(instance['instancetype']) ? instance['instancetype'][i] : instance['instancetype'];
if(instanceType.classname && instanceType.classname.toLowerCase() !== "unknown") {
if (instanceType.classname && instanceType.classname.toLowerCase() !== "unknown") {
types.add(instanceType.classname);
}
}
available.types = Array.from(types);
}
if (instance.hasOwnProperty("dateofacceptance")) {
let years: Set<string> = new Set();
let length = Array.isArray(instance['dateofacceptance']) ? instance['dateofacceptance'].length : 1;
@ -316,17 +315,17 @@ export class ParsingFunctions {
}
available.years = Array.from(years);
}
available['downloadUrl'] = url;
if(url.includes("doi.org/")) {
if (url.includes("doi.org/")) {
this.instanceWithDoiExists = true;
}
if (instance.hasOwnProperty("accessright")) {
let length = Array.isArray(instance['accessright']) ? instance['accessright'].length : 1;
for (let i = 0; i < length; i++) {
let accessRight = Array.isArray(instance['accessright']) ? instance['accessright'][i] : instance['accessright'];
if (this.changeBestAccessMode(available.accessRight, accessRight)) {
available.accessRight = accessRight.classname;
if (this.changeBestAccessMode(globalAccessRight, accessRight)) {
@ -334,28 +333,66 @@ export class ParsingFunctions {
}
}
}
}
if (available.accessRight) {
if (available.accessRight.toLowerCase().indexOf('open') !== -1) {
available.accessRightIcon = this.open;
} else if (available.accessRight.toLowerCase().indexOf('not available') !== -1) {
}
else if (available.accessRight.toLowerCase().indexOf('not available') !== -1) {
available.accessRightIcon = this.unknown;
} else {
}
else {
available.accessRightIcon = this.closed;
}
} else {
available.accessRightIcon = this.unknown;
}
if(instance.hasOwnProperty("license")) {
if (instance.hasOwnProperty("license")) {
available.license = Array.isArray(instance['license']) ? instance['license'][0] : instance['license'];
}
hostedBy_collectedFrom.push(available);
}
compareHostedByCollectedFrom(a: HostedByCollectedFrom, b: HostedByCollectedFrom) {
let firstAccessRight: string = (a.accessRight ? a.accessRight.toLowerCase() : null);
let secondAccessRight: string = (b.accessRight ? b.accessRight.toLowerCase() : null);
if (firstAccessRight === secondAccessRight) {
return 0;
} else {
if (firstAccessRight === 'open access') {
return -1;
} else if (secondAccessRight === 'open access') {
return 1;
} else if (firstAccessRight === "open source") {
return -1;
} else if (secondAccessRight === "open source") {
return 1;
} else if (firstAccessRight === "embargo") {
return -1;
} else if (secondAccessRight === "embargo") {
return 1;
} else if (firstAccessRight === "restricted") {
return -1;
} else if (secondAccessRight === "restricted") {
return 1;
} else if (firstAccessRight === "closed access") {
return -1;
} else if (secondAccessRight === "closed access") {
return 1;
} else if (firstAccessRight === "not available") {
return -1;
} else if (secondAccessRight === "not available") {
return 1;
}
}
return 0;
}
// publication & dataset landing : for downloadFrom and publishedIn
changeBestAccessMode(currentAccessMode: string, accessMode: any): boolean {
if (!accessMode) {
@ -404,7 +441,7 @@ export class ParsingFunctions {
if (researchResults == undefined) {
researchResults = [];
}
let researchResult: RelationResult = {
name: "",
id: "",
@ -415,10 +452,10 @@ export class ParsingFunctions {
provenanceAction: provenanceAction,
relationName: relationName
};
// researchResult.relationName = relation.to.class;
if(relation['resulttype']) {
if (relation['resulttype']) {
if (relation['resulttype'].classname == "publication") {
researchResult['class'] = "publication";
} else if (relation['resulttype'].classname == "dataset") {
@ -430,10 +467,10 @@ export class ParsingFunctions {
}
}
researchResult['id'] = relation['to'].content;
if(Array.isArray(relation['title'])) {
for(let i=0; i<relation['title'].length; i++) {
if(relation['title'][i] && relation['title'][i].content) {
if(!researchResult['name'] || relation['title'][i].classid == "main title") {
if (Array.isArray(relation['title'])) {
for (let i = 0; i < relation['title'].length; i++) {
if (relation['title'][i] && relation['title'][i].content) {
if (!researchResult['name'] || relation['title'][i].classid == "main title") {
researchResult['name'] = String(relation['title'][i].content);
}
}
@ -441,7 +478,7 @@ export class ParsingFunctions {
} else {
researchResult['name'] = (relation['title'] && relation['title'].content) ? String(relation['title'].content) : "";
}
if(!researchResult['name']) {
if (!researchResult['name']) {
researchResult['name'] = "[no title available]";
}
if (relation.hasOwnProperty("dateofacceptance")) {
@ -450,19 +487,19 @@ export class ParsingFunctions {
}
//researchResult['date'] = relation.dateofacceptance.substring(0,4);;
let percentageName: string;
if(relation.trust) {
if (relation.trust) {
percentageName = "trust";
} else if(relation.similarity) {
} else if (relation.similarity) {
percentageName = "similarity";
}
if(percentageName) {
if (percentageName) {
researchResult['percentage'] = Math.round(relation[percentageName] * 100);
researchResult['percentageName'] = percentageName;
}
researchResults.push(researchResult);
return researchResults;
}
sortByPercentage(results: RelationResult[]): RelationResult[] {
if (results) {
return results.sort(function (a, b) {
@ -481,7 +518,7 @@ export class ParsingFunctions {
if (!identifiers.has(pid.classid)) {
identifiers.set(pid.classid, new Array<string>());
}
identifiers.get(pid.classid).push(pid.content+"");
identifiers.get(pid.classid).push(pid.content + "");
}
} else {
for (let i = 0; i < pid.length; i++) {
@ -489,54 +526,54 @@ export class ParsingFunctions {
if (!identifiers.has(pid[i].classid)) {
identifiers.set(pid[i].classid, new Array<string>());
}
identifiers.get(pid[i].classid).push(pid[i].content+"");
identifiers.get(pid[i].classid).push(pid[i].content + "");
}
}
}
return identifiers;
}
// publication & dataset landing : for subjects and otherSubjects and classifiedSubjects
parseEoscSubjects(_subjects: any): any[] {
let eoscSubjectsFound = [];
let setOfEoscSubjects: Set<string> = new Set();
let subject;
let length = Array.isArray(_subjects) ? _subjects.length : 1;
for (let i = 0; i < length; i++) {
subject = Array.isArray(_subjects) ? _subjects[i] : _subjects;
let content: string = subject.code+"";
let content: string = subject.code + "";
let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content);
let found: boolean = checkAndAddEoscSubjectResp["found"];
if(found) {
if (found) {
setOfEoscSubjects = checkAndAddEoscSubjectResp["setOfEoscSubject"];
eoscSubjectsFound = checkAndAddEoscSubjectResp["eoscSubjectsFound"];
}
}
return eoscSubjectsFound;
}
// publication & dataset landing : for subjects and otherSubjects and classifiedSubjects
parseAllSubjects(_subjects: any, vocabulary: any): [string[], Map<string, string[]>, Map<string, string[]>, string[], string[], ] {
parseAllSubjects(_subjects: any, vocabulary: any): [string[], Map<string, string[]>, Map<string, string[]>, string[], string[],] {
// let eoscSubjectsFound = [];
let subjects: string[];
let otherSubjects: Map<string, string[]>;
let classifiedSubjects: Map<string, string[]>;
let fos: string[];
let sdg: string[];
let setOfEoscSubjects: Set<string> = new Set();
let subject;
let length = Array.isArray(_subjects) ? _subjects.length : 1;
for (let i = 0; i < length; i++) {
subject = Array.isArray(_subjects) ? _subjects[i] : _subjects;
if (subject.classid != "") {
if (subject.classid == "keyword") {
let content: string = subject.content+"";
let content: string = subject.content + "";
// let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content);
// let found: boolean = checkAndAddEoscSubjectResp["found"];
// if(found) {
@ -550,22 +587,22 @@ export class ParsingFunctions {
// }
} else if (!vocabulary || vocabulary[subject.classid] || subject.classid === "SDG" || subject.classid === "FOS") {
// if (subject.inferred && subject.inferred == true) {
if(subject.classid === "SDG") {
if (subject.classid === "SDG") {
if (sdg == undefined) {
sdg = new Array<string>();
}
sdg.push(subject.content+"");
} else if(subject.classid === "FOS") {
sdg.push(subject.content + "");
} else if (subject.classid === "FOS") {
if (fos == undefined) {
fos = new Array<string>();
}
fos.push(subject.content+"");
fos.push(subject.content + "");
} else {
if (classifiedSubjects == undefined) {
classifiedSubjects = new Map<string, string[]>();
}
let content: string = subject.content+"";
let content: string = subject.content + "";
// let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content);
// let found: boolean = checkAndAddEoscSubjectResp["found"];
// if(found) {
@ -579,7 +616,7 @@ export class ParsingFunctions {
// }
}
} else {
let content: string = subject.content+"";
let content: string = subject.content + "";
// let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content);
// let found: boolean = checkAndAddEoscSubjectResp["found"];
// if(found) {
@ -597,11 +634,11 @@ export class ParsingFunctions {
}
return [subjects, otherSubjects, classifiedSubjects, fos, sdg];
}
checkAndAddEoscSubject(setOfEoscSubjects: Set<string>, eoscSubjectsFound, subject, content) {
let found: boolean = false;
if(!setOfEoscSubjects.has(content)) {
if (!setOfEoscSubjects.has(content)) {
// looping through our declared array
this.eoscSubjects.forEach(item => {
if (content && content == item.label) {
@ -616,7 +653,7 @@ export class ParsingFunctions {
parseContexts(_contexts: any): Context[] {
let contexts = new Array<Context>();
let position = 0;
let labels = "";
let context;
@ -637,10 +674,10 @@ export class ParsingFunctions {
let length1 = Array.isArray(category['concept']) ? category['concept'].length : 1;
for (let j = 0; j < length1; j++) {
categoryConcept = Array.isArray(category['concept']) ? category['concept'][j] : category['concept'];
// initalize if there is concept label or this is the last concept of the category and there were no concepts
// otherwise we could have multiple entries for the same category but without concepts
if(categoryConcept.label || (numOfConcepts == 0 && j == (length1 - 1))) {
if (categoryConcept.label || (numOfConcepts == 0 && j == (length1 - 1))) {
contexts[position] = {
"labelContext": "", "idContext": "",
"labelCategory": "", "idCategory": "",
@ -652,15 +689,17 @@ export class ParsingFunctions {
contexts[position]['idCategory'] = category.id;
contexts[position]['labelConcept'] = categoryConcept.label ? categoryConcept.label : null;
contexts[position]['idConcept'] = categoryConcept.label ? categoryConcept.id : null;
position++;
numOfConcepts++;
}
}
} else if(category.label || (numOfCategories == 0 && z == (length2 - 1))) {
contexts[position] = {"labelContext": "", "idContext": "",
"labelCategory": "", "idCategory": "",
"labelConcept": "", "idConcept": ""};
} else if (category.label || (numOfCategories == 0 && z == (length2 - 1))) {
contexts[position] = {
"labelContext": "", "idContext": "",
"labelCategory": "", "idCategory": "",
"labelConcept": "", "idConcept": ""
};
contexts[position]['labelContext'] = context.label;
contexts[position]['idContext'] = context.id;
contexts[position]['labelCategory'] = category.label ? category.label : null;
@ -672,9 +711,11 @@ export class ParsingFunctions {
}
}
} else {
contexts[position] = {"labelContext": "", "idContext": "",
"labelCategory": "", "idCategory": "",
"labelConcept": "", "idConcept": ""};
contexts[position] = {
"labelContext": "", "idContext": "",
"labelCategory": "", "idCategory": "",
"labelConcept": "", "idConcept": ""
};
contexts[position]['labelContext'] = context.label;
contexts[position]['idContext'] = context.id;
contexts[position]['labelCategory'] = null;
@ -688,11 +729,15 @@ export class ParsingFunctions {
}
return contexts;
}
public static getEnermapsConceptId(contexts: any): string{
let enermapsconcepts = contexts.filter(c=> {return c.idCategory == "enermaps::selection" && c.idConcept});
return enermapsconcepts && enermapsconcepts.length > 0?enermapsconcepts[0].idConcept.split("enermaps::selection::")[1]:null;
public static getEnermapsConceptId(contexts: any): string {
let enermapsconcepts = contexts.filter(c => {
return c.idCategory == "enermaps::selection" && c.idConcept
});
return enermapsconcepts && enermapsconcepts.length > 0 ? enermapsconcepts[0].idConcept.split("enermaps::selection::")[1] : null;
// return "hotmaps_heat_tot_curr_density"
}
parseTypes(types: string[], uniqueTypes: Set<string>, instance: any) {
if (instance && instance.hasOwnProperty("instancetype") && instance['instancetype'].classname) {
if (!uniqueTypes.has(instance['instancetype'].classname)) {
@ -704,7 +749,7 @@ export class ParsingFunctions {
parseLanguages(_languages: any) {
var languages = new Array<string>();
if (!Array.isArray(_languages)) {
if (_languages.classname != "Undetermined" && _languages.classname) {
languages.push(_languages.classname);
@ -727,7 +772,7 @@ export class ParsingFunctions {
countries.push(_countries.classname);
}
} else {
for (let i = 0; i < countries.length; i++) {
for (let i = 0; i < _countries.length; i++) {
if (_countries[i].classname != "Undetermined" && _countries[i].classname) {
countries.push(_countries[i].classname);
}
@ -758,10 +803,10 @@ export class ParsingFunctions {
citations = Array.isArray(citations) ? citations : [citations];
citations.forEach(citation => {
let reference: Reference = {name: null, ids: []};
if(citation.rawText) {
if (citation.rawText) {
reference.name = citation.rawText;
}
if(citation.id) {
if (citation.id) {
let ids: any[] = Array.isArray(citation.id) ? citation.id : [citation.id];
ids.forEach(id => {
reference.ids.push({
@ -775,35 +820,123 @@ export class ParsingFunctions {
});
return references;
}
static parseRelCanonicalId(record, type){
try{
if(record["result"]["metadata"]["oaf:entity"][("oaf:"+type)]["children"] && record["result"]["metadata"]["oaf:entity"][("oaf:"+type)]["children"][type]){
for(let child of record["result"]["metadata"]["oaf:entity"][("oaf:"+type)]["children"][type]){
static parseRelCanonicalId(record, type) {
try {
if (record["result"]["metadata"]["oaf:entity"][("oaf:" + type)]["children"] && record["result"]["metadata"]["oaf:entity"][("oaf:" + type)]["children"][type]) {
for (let child of record["result"]["metadata"]["oaf:entity"][("oaf:" + type)]["children"][type]) {
return child["objidentifier"];
}
}
}catch(e){
} catch (e) {
// console.error(e);
}
return record["result"]["header"]["dri:objIdentifier"];
return record["result"]["header"]["dri:objIdentifier"];
}
parseDescription(description, stripHTML: boolean = false):string {
parseDescription(description, stripHTML: boolean = false): string {
let abstracts = [];
if(!Array.isArray(description)) {
if (!Array.isArray(description)) {
abstracts = [description ? String(description) : ""];
} else {
abstracts = description.map( x => String(x));
abstracts = description.map(x => String(x));
}
try{
abstracts = abstracts.map( x => StringUtils.HTMLToString(x));
} catch (e) {}
abstracts = abstracts.sort((a,b) => b.length - a.length);
if(stripHTML) {
return abstracts.join(' ');
} else {
return abstracts.length > 0 ? ('<p>' + abstracts.join('</p> <p>') + '</p>') : abstracts.join(' ');
}
try {
abstracts = abstracts.map(x => StringUtils.HTMLToString(x));
} catch (e) {
}
abstracts = abstracts.sort((a, b) => b.length - a.length);
if (stripHTML) {
return abstracts.join(' ');
} else {
return abstracts.length > 0 ? ('<p>' + abstracts.join('</p> <p>') + '</p>') : abstracts.join(' ');
}
}
parseMeasures(elements: any[]): Measure {
if (elements && elements.length) {
let bip: Metric[] = [];
let counts: Metric[] = [];
let measure: Measure = {};
elements.forEach(element => {
if (element.id == 'views') {
counts.push({name: 'views', icon: 'visibility', value: element.count, order: 0});
measure.views = element.count;
}
if (element.id == 'downloads') {
counts.push({name: 'downloads', icon: 'download', value: element.count, order: 1});
measure.downloads = element.count;
}
if (element.id == 'influence_alt') {
bip.push({name: 'citations', icon: 'cite', value: element.score, order: 2});
measure.citations = element.score;
}
if (element.id == 'popularity') {
let metric: Metric = {name: 'popularity', icon: 'fire', value: null, order: 3};
if (element.class == 'C1') {
metric.value = 'Top 0.01%';
} else if (element.class == 'C2') {
metric.value = 'Top 0.1%';
} else if (element.class == 'C3') {
metric.value = 'Top 1%';
} else if (element.class == 'C4') {
metric.value = 'Top 10%';
} else if (element.class == 'A') {
metric.value = 'Exceptional';
} else if (element.class == 'B') {
metric.value = 'Substantial';
} else {
metric.value = 'Average';
}
measure.popularity = metric.value;
bip.push(metric);
}
if (element.id == 'influence') {
let metric: Metric = {name: 'influence', icon: 'landmark', value: null, order: 4};
if (element.class == 'C1') {
metric.value = 'Top 0.01%';
} else if (element.class == 'C2') {
metric.value = 'Top 0.1%';
} else if (element.class == 'C3') {
metric.value = 'Top 1%';
} else if (element.class == 'C4') {
metric.value = 'Top 10%';
} else if (element.class == 'A') {
metric.value = 'Exceptional';
} else if (element.class == 'B') {
metric.value = 'Substantial';
} else {
metric.value = 'Average';
}
measure.influence = metric.value;
bip.push(metric);
}
if (element.id == 'impulse') {
let metric: Metric = {name: 'impulse', icon: 'rocket', value: null, order: 5};
if (element.class == 'C1') {
metric.value = 'Top 0.01%';
} else if (element.class == 'C2') {
metric.value = 'Top 0.1%';
} else if (element.class == 'C3') {
metric.value = 'Top 1%';
} else if (element.class == 'C4') {
metric.value = 'Top 10%';
} else if (element.class == 'A') {
metric.value = 'Exceptional';
} else if (element.class == 'B') {
metric.value = 'Substantial';
} else {
metric.value = 'Average';
}
measure.impulse = metric.value;
bip.push(metric);
}
});
measure.bip = bip.sort((a, b) => a.order - b.order);
measure.counts = counts.sort((a, b) => a.order - b.order);
return measure;
}
return null;
}
}

View File

@ -13,17 +13,18 @@ import {OpenaireEntities} from "../../utils/properties/searchFields";
selector: 'relatedTo, [relatedTo]',
template: `
<ng-container *ngIf="communities && communities.length > 0">
<div class="uk-margin-small-bottom uk-flex uk-flex-between">
<div *ngIf="!mobileView" class="uk-margin-small-bottom uk-flex uk-flex-between">
<span *ngIf="viewAll && !lessBtn" class="clickable uk-h6 uk-flex uk-flex-middle" (click)="viewLessClick()">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
{{title}}
</span>
<span *ngIf="!viewAll || lessBtn" class="uk-text-light-grey">{{title}}</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;" class="view-more-less-link">View less</a>
<span *ngIf="!viewAll || lessBtn" class="uk-text-emphasis uk-text-bolder">{{title}}</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;" class="view-more-less-link uk-link-text">View less</a>
<a *ngIf="communities && communities.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link">View all</a>
(click)="viewAllClick();" class="view-more-less-link uk-link-text">View all</a>
</div>
<div *ngFor="let community of communities.slice(0, viewAll?communities.length:threshold)" class="uk-text-truncate">
<div *ngFor="let community of communities.slice(0, viewAll?communities.length:threshold)" class="uk-text-truncate"
[class.uk-margin-small-bottom]="mobileView">
<!-- If there are any communities with dashboard -->
<a *ngIf="community.link" href="{{community.link}}" target="_blank" [attr.uk-tooltip]="community.labelContext" class="custom-external">
{{community.labelContext}}
@ -44,6 +45,7 @@ import {OpenaireEntities} from "../../utils/properties/searchFields";
})
export class RelatedToComponent implements OnInit {
@Input() mobileView: boolean = false;
@Input() contexts: Context[];
@Input() viewAll: boolean = false;
@Output() viewAllClicked = new EventEmitter();

View File

@ -16,23 +16,34 @@ import {FosComponent} from "./fos.component";
import {SdgComponent} from "./sdg.component";
import {IconsModule} from "../../utils/icons/icons.module";
import {AlertModalModule} from "../../utils/modal/alertModal.module";
import { SearchInputModule } from '../../sharedComponents/search-input/search-input.module';
import {EntityMetadataComponent} from "./entity-metadata.component";
import {IconsService} from "../../utils/icons/icons.service";
import {closed_access, open_access, unknown_access} from "../../utils/icons/icons";
import {FullScreenModalModule} from "../../utils/modal/full-screen-modal/full-screen-modal.module";
@NgModule({
imports: [
CommonModule, FormsModule, RouterModule, PagingModule, ShowPublisherModule, IconsModule, AlertModalModule
CommonModule, FormsModule, RouterModule, PagingModule, ShowPublisherModule, IconsModule, AlertModalModule,
SearchInputModule, FullScreenModalModule
],
declarations: [
ShowIdentifiersComponent,ShowSubjectsComponent,
FundedByComponent,AvailableOnComponent,TabTableComponent,
RelatedToComponent, FosComponent, SdgComponent
RelatedToComponent, FosComponent, SdgComponent,
EntityMetadataComponent
],
providers:[
],
exports: [
ShowIdentifiersComponent, ShowSubjectsComponent,
FundedByComponent,AvailableOnComponent, TabTableComponent, ShowPublisherComponent,
RelatedToComponent, FosComponent, SdgComponent
RelatedToComponent, FosComponent, SdgComponent, EntityMetadataComponent
]
})
export class ResultLandingUtilsModule { }
export class ResultLandingUtilsModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([open_access, closed_access, unknown_access]);
}
}

View File

@ -0,0 +1,176 @@
import {ChangeDetectorRef, Component, Input, ViewChild} from "@angular/core";
import {FormBuilder, UntypedFormGroup, Validators} from "@angular/forms";
import {SdgSelectionComponent} from "../../../sdg/sdg-selection/sdg-selection.component";
import {FosSelectionComponent} from "../../../fos/fos-selection/fos-selection.component";
import {properties} from "../../../../../environments/environment";
import {EnvProperties} from "../../../utils/properties/env-properties";
import {EmailService} from "../../../utils/email/email.service";
import {Subscription} from "rxjs";
import {Composer} from "../../../utils/email/composer";
import {AlertModal} from "../../../utils/modal/alert";
import {StringUtils} from "../../../utils/string-utils.class";
@Component({
selector: 'sdg-fos-suggest',
template: `
<modal-alert #selectionModal [large]="true" (alertOutput)="modalOutput()" (cancelOutput)="modalCancel()"
[okDisabled]="!sent && !selectionStep1 && (form.invalid || sending)">
<sdg-selection *ngIf="subjects && subjectType == 'sdg'" #selection [class.uk-hidden]="!selectionStep1"
[subjects]="subjects" [entityType]="entityType"></sdg-selection>
<fos-selection *ngIf="subjects && subjectType == 'fos'" #selection [class.uk-hidden]="!selectionStep1"
[subjects]="subjects" [contentHeight]="selectionModal.bodyHeight" [inModal]="true"></fos-selection>
<div [class.uk-hidden]="selectionStep1">
<div class="uk-flex uk-flex-column uk-flex-middle">
<ng-container *ngIf="!sent && !error">
<div>Thank you for your feedback.</div>
<div>Before sending us your options, would you like to leave us your e-mail to notify you about the reporting status?</div>
<div input class="uk-width-1-2 uk-margin-medium-top uk-margin-medium-bottom"
[formInput]="form.get('email')" placeholder="E-mail">
<span note>(Optional)</span>
</div>
<div>
<re-captcha (resolved)="handleRecaptcha($event)" [siteKey]="properties.reCaptchaSiteKey"
[ngClass]="sending ? 'uk-hidden':''"></re-captcha>
<loading [ngClass]="sending ? '':'uk-hidden'"></loading>
</div>
</ng-container>
<ng-container *ngIf="sent">
<p>Your feedback is successfully received and it will soon be reviewed by our graph experts!</p>
<icon customClass="uk-text-background" name="check" [ratio]="4"></icon>
</ng-container>
<div *ngIf="error" class="uk-alert uk-alert-danger uk-text-center uk-width-large ng-star-inserted"
role="alert">Email sent failed! Please try again.
</div>
</div>
</div>
</modal-alert>
`
})
export class SdgFosSuggestComponent {
@Input() entityType: string;
@Input() title;
public subjectType: "fos" | "sdg" = "sdg";
public subjects;
public properties: EnvProperties = properties;
public selectionStep1: boolean = true;
@ViewChild("selectionModal") selectionModal: AlertModal;
@ViewChild("selection") selection: SdgSelectionComponent | FosSelectionComponent;
public form: UntypedFormGroup;
public url: string = null;
public sending: boolean = false;
public sent: boolean = false;
public error: boolean = false;
subscriptions: Subscription[] = [];
constructor(private emailService: EmailService, private fb: FormBuilder, private cdr: ChangeDetectorRef) {}
ngOnInit() {
if (typeof window !== "undefined") {
this.url = window.location.href;
}
this.init();
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) {
subscription.unsubscribe();
}
});
}
init() {
this.form = this.fb.group({
name: this.fb.control(this.title),
url: this.fb.control(this.url),
email: this.fb.control('', Validators.email),
subjects: this.fb.control([]),
recaptcha: this.fb.control('', Validators.required),
});
}
public openSelectionModal() {
this.sent = false;
this.sending = false;
this.error = false;
this.selectionStep1 = true;
this.init();
this.selectionModal.cancelButton = false;
if(this.subjectType == "sdg") {
this.selectionModal.alertTitle = "Please select SDGs that are the most relevant for this "+this.getEntityName(this.entityType)+".";
} else {
this.selectionModal.alertTitle = "Please select Fields of Science that are the most relevant for this "+this.getEntityName(this.entityType)+".";
}
this.selectionModal.okButtonText = "Next";
this.selectionModal.stayOpen = true;
this.cdr.detectChanges();
this.selectionModal.open();
}
public modalOutput() {
this.selectionModal.previousButton = true;
this.selectionModal.okButtonText = "Send feedback";
if(this.selectionStep1) {
this.selectionStep1 = false;
if(this.subjectType == "sdg") {
this.selectionModal.alertTitle = "Please send your feedback on most relevant SDGs for this "+this.getEntityName(this.entityType)+".";
} else {
this.selectionModal.alertTitle = "Please send your feedback on most relevant Fields of Science for this "+this.getEntityName(this.entityType)+".";
}
} else {
this.sending = true;
// email functionality
this.form.get("subjects").setValue(this.selection.getSelectedSubjects().map(subject => subject.id));
this.subscriptions.push(this.emailService.contact(this.properties,
Composer.composeEmailForSdgsSuggestion(this.form.value, [this.properties.feedbackmail], this.subjectType), this.form.get('recaptcha').value).subscribe(sent => {
this.error = !sent;
if (sent) {
if (this.form.get('email').value !== '') {
this.subscriptions.push(this.emailService.contact(this.properties,
Composer.composeEmailForUserAfterFeedback([this.form.get('email').value])).subscribe(sent => {
if (sent) {
//console.log('An email has been sent to user ' + this.form.get('email').value);
}
}));
}
this.init();
this.sent = true;
this.selectionModal.alertTitle = "Thank you for your feedback";
this.selectionModal.okButtonText = "OK";
this.selectionModal.previousButton = false;
this.selectionModal.stayOpen = false;
}
this.sending = false;
}, error => {
console.log(error);
this.error = true;
this.sending = false;
}));
}
}
public modalCancel() {
if(this.subjectType == "sdg") {
this.selectionModal.alertTitle = "Please select SDGs that are the most relevant for this "+this.getEntityName(this.entityType)+".";
} else {
this.selectionModal.alertTitle = "Please select Fields of Science that are the most relevant for this "+this.getEntityName(this.entityType)+".";
}
this.selectionStep1 = true;
this.selectionModal.previousButton = false;
this.selectionModal.okButtonText = "Next";
this.selectionModal.stayOpen = true;
this.error = false;
}
public handleRecaptcha(captchaResponse: string) {
this.form.get('recaptcha').setValue(captchaResponse);
}
private getEntityName (entityType:string) {
return StringUtils.getEntityName(entityType, false);
}
}

View File

@ -0,0 +1,29 @@
import {CommonModule} from "@angular/common";
import {NgModule} from "@angular/core";
import {FormsModule} from "@angular/forms";
import {RecaptchaModule} from "ng-recaptcha";
import {SdgSelectionModule} from "../../../sdg/sdg-selection/sdg-selection.module";
import {FosSelectionModule} from "../../../fos/fos-selection/fos-selection.module";
import {InputModule} from "../../../sharedComponents/input/input.module";
import {SdgFosSuggestComponent} from "./sdg-fos-suggest.component";
import {AlertModalModule} from "../../../utils/modal/alertModal.module";
import {IconsModule} from "../../../utils/icons/icons.module";
import {LoadingModule} from "../../../utils/loading/loading.module";
@NgModule({
imports: [
CommonModule, FormsModule, InputModule, SdgSelectionModule, FosSelectionModule, RecaptchaModule, AlertModalModule, IconsModule, LoadingModule
],
declarations: [
SdgFosSuggestComponent
],
providers: [
],
exports: [
SdgFosSuggestComponent
]
})
export class SdgFosSuggestModule {
}

View File

@ -6,41 +6,68 @@ import {StringUtils} from "../../utils/string-utils.class";
@Component({
selector: 'sdg',
template: `
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
<div [class]="'uk-flex uk-flex-between uk-flex-middle uk-margin-'+(viewAll?'':'small-')+'bottom'">
<span *ngIf="viewAll" class="clickable uk-h6 uk-flex uk-flex-middle uk-margin-small-right uk-margin-remove-bottom"
(click)="viewLessClick()">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
<span uk-tooltip="Sustainable Development Goals">{{title}}</span>
</span>
<span *ngIf="!viewAll" class="uk-text-light-grey uk-text-nowrap uk-margin-small-right" uk-tooltip="Sustainable Development Goals">{{title}}</span>
<!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>-->
<a *ngIf="properties.adminToolsPortalType == 'eosc' && subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate" uk-tooltip="View all">
View all</a>
<a *ngIf="properties.adminToolsPortalType !== 'eosc' && subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate" uk-tooltip="View all & feedback">
View all & feedback</a>
<a *ngIf="properties.adminToolsPortalType !== 'eosc' && (subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-text-truncate"
(click)="feedbackClick();">Feedback</a>
</div>
<div class="uk-margin-small-bottom uk-flex">
<img src="assets/common-assets/common/The_Global_Goals_Icon_Color.svg"
loading="lazy" alt="sdg_colors" style="width:27px; height:27px">
<div class="uk-margin-small-left">
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate">
<a *ngIf="properties.adminToolsPortalType !== 'eosc'"
[routerLink]=" properties.searchLinkToResults" [queryParams]="{'sdg': urlEncodeAndQuote(subject)}">
{{subject}}
</a>
<a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank"
[href]="'https://explore.openaire.eu'+properties.searchLinkToResults+'?sdg='+urlEncodeAndQuote(subject)">
{{subject}}
</a>
</div>
<div class="uk-visible@m">
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
<div [class]="'uk-flex uk-flex-between uk-flex-middle uk-margin-'+(viewAll?'':'small-')+'bottom'">
<span *ngIf="viewAll" class="clickable uk-h6 uk-flex uk-flex-middle uk-margin-small-right uk-margin-remove-bottom"
(click)="viewLessClick()">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
<span uk-tooltip="Sustainable Development Goals">{{title}}</span>
</span>
<span *ngIf="!viewAll" class="uk-text-emphasis uk-text-bolder uk-text-nowrap uk-margin-small-right" uk-tooltip="Sustainable Development Goals">
{{title}}
<span *ngIf="subjects && subjects.length > threshold && !viewAll">({{subjects.length}})</span>
</span>
<a *ngIf="properties.adminToolsPortalType == 'eosc' && subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-link uk-link-text uk-text-truncate">
View all</a>
<!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a> -->
<a *ngIf="properties.adminToolsPortalType != 'eosc' && subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-link uk-link-text uk-text-truncate">
View all & suggest</a>
<a *ngIf="properties.adminToolsPortalType != 'eosc' && (subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-link-text uk-text-truncate"
(click)="suggestClick();">Suggest</a>
</div>
<div class="uk-margin-small-bottom uk-flex">
<img src="assets/common-assets/common/The_Global_Goals_Icon_Color.svg"
loading="lazy" alt="sdg_colors" style="width:27px; height:27px">
<div class="uk-margin-small-left">
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate">
<a *ngIf="properties.adminToolsPortalType != 'eosc'"
[routerLink]=" properties.searchLinkToResults" [queryParams]="{'sdg': urlEncodeAndQuote(subject)}">
{{subject}}
</a>
<a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank"
[href]="'https://explore.openaire.eu'+properties.searchLinkToResults+'?sdg='+urlEncodeAndQuote(subject)">
{{subject}}
</a>
</div>
</div>
</div>
</div>
<div class="uk-hidden@m">
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
<div class="uk-flex uk-flex-middle uk-flex-wrap">
<img src="assets/common-assets/common/The_Global_Goals_Icon_Color.svg"
loading="lazy" alt="sdg_colors" style="width:18px; height:18px">
<span class="uk-margin-xsmall-left uk-margin-xsmall-right uk-text-meta">SDGs:</span>
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate">
<a [routerLink]=" properties.searchLinkToResults" [queryParams]="{'sdg': urlEncodeAndQuote(subject)}">{{subject}}</a>
<span *ngIf="(viewAll && i<subjects.length-1) || i<threshold-1">, &nbsp;</span>
</div>
<!-- <div>
{{subjects.slice(0, viewAll?subjects.length:threshold).join(", ")}}
</div> -->
</div>
<div class="uk-text-right uk-margin-small-top">
<a *ngIf="subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-link uk-text-truncate">
View all</a>
<!-- View all & suggest</a>-->
<!-- <a *ngIf="(subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-link-text uk-text-truncate"-->
<!-- (click)="suggestClick();">Suggest</a>-->
</div>
</div>
</div>
`
})
@ -48,9 +75,9 @@ export class SdgComponent {
@Input() subjects: string[];
@Input() viewAll: boolean = false;
@Output() viewAllClicked = new EventEmitter();
@Output() feedbackClicked = new EventEmitter();
@Output() suggestClicked = new EventEmitter();
public lessBtn: boolean = false;
public threshold: number = 4;
public threshold: number = 2;
public routerHelper: RouterHelper = new RouterHelper();
public properties = properties;
public title: string = "SDGs";
@ -70,8 +97,8 @@ export class SdgComponent {
this.viewAllClicked.emit("");
}
public feedbackClick() {
this.feedbackClicked.emit("");
public suggestClick() {
this.suggestClicked.emit('sdg');
}
public urlEncodeAndQuote(str: string): string {

View File

@ -47,14 +47,21 @@ import {properties} from "../../../../environments/environment";
<a (click)="openIdentifiersModal()" class="view-more-less-link">View all</a>
</div>
<modal-alert #identifiersModal>
<modal-alert *ngIf="!isMobile" #identifiersModal>
<div class="uk-text-small">
<ng-container *ngTemplateOutlet="identifiers_template; context: { modal: true}"></ng-container>
</div>
</modal-alert>
<fs-modal *ngIf="isMobile" #identifiersModal>
<div class="uk-text-small">
<ng-container *ngTemplateOutlet="identifiers_template; context: { modal: true}"></ng-container>
</div>
</fs-modal>
`
})
export class ShowIdentifiersComponent implements AfterViewInit {
@Input() isMobile: boolean = false;
@Input() identifiers: Map<string, string[]>;
@Input() showViewAll: boolean = false;
large: Map<string, boolean> = new Map<string, boolean>();
@ -121,9 +128,15 @@ export class ShowIdentifiersComponent implements AfterViewInit {
}
public openIdentifiersModal() {
this.identifiersModal.cancelButton = false;
this.identifiersModal.okButton = false;
this.identifiersModal.alertTitle = "Persistent Identifiers";
this.identifiersModal.open();
if(this.isMobile) {
this.identifiersModal.okButton = false;
this.identifiersModal.title = "Persistent Identifiers";
this.identifiersModal.open();
} else {
this.identifiersModal.cancelButton = false;
this.identifiersModal.okButton = false;
this.identifiersModal.alertTitle = "Persistent Identifiers";
this.identifiersModal.open();
}
}
}

View File

@ -4,77 +4,74 @@ import {EnvProperties} from "../../utils/properties/env-properties";
@Component({
selector: 'showPublisher, [showPublisher]',
template: `
<div *ngIf="publishDate || journal && (journal['journal'] || journal['issn'] || journal['lissn']
|| journal['volume'] || journal['eissn'] || journal['issue'])" class="uk-text-small">
<span *ngIf="publishDate" class="uk-margin-right">
<span class="uk-text-meta">Published: </span>
{{publishDate | date: 'dd MMM yyyy' : 'UTC'}}
</span>
<span *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
|| journal['volume'] || journal['eissn'] || journal['issue'])">
<span class="uk-text-meta">Journal: </span>
<span *ngIf="journal['journal']">{{journal['journal']}}</span>
<span *ngIf="journal['journal'] && (journal['volume'] || journal['issue'])">, </span>
<ng-container *ngIf="journal['volume']">
<span class="uk-display-inline-block">
volume
<span *ngIf="journal['volume'] > 0">{{journal['volume'] | number}}</span>
<span *ngIf="!(journal['volume'] > 0)">{{journal['volume']}}</span>
</span>
<span *ngIf="journal['issue'] || journal['start_page'] || journal['end_page']">, </span>
</ng-container>
<ng-container *ngIf="journal['issue']">
<span class="uk-display-inline-block">
issue
<span *ngIf="journal['issue'] > 0">{{journal['issue'] | number}}</span>
<span *ngIf="!(journal['issue'] > 0)">{{journal['issue']}}</span>
</span>
<span *ngIf="journal['start_page'] || journal['end_page']">, </span>
</ng-container>
<span *ngIf="(journal['volume'] || journal['issue']) && (journal['start_page'] || journal['end_page'])"
class="uk-display-inline-block">
{{(journal['start_page'] && journal['end_page']) ? 'pages' : 'page'}}
<span *ngIf="journal['start_page']">
<span *ngIf="journal['start_page'] > 0">{{journal['start_page'] | number}}</span>
<span *ngIf="!(journal['start_page'] > 0)">{{journal['start_page']}}</span>
</span>
<span *ngIf="journal['start_page'] && journal['end_page']">-</span>
<span *ngIf="journal['end_page']">
<span *ngIf="journal['end_page'] > 0">{{journal['end_page'] | number}}</span>
<span *ngIf="!(journal['end_page'] > 0)">{{journal['end_page']}}</span>
</span>
</span>
<span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])"> (</span>
<ng-container *ngIf="journal['issn']">
<span class="uk-display-inline-block">issn: {{journal['issn']}}</span>
<span>, </span>
</ng-container>
<ng-container *ngIf="journal['eissn']">
<span class="uk-display-inline-block">eissn: {{journal['eissn']}}</span>
<span>, </span>
</ng-container>
<span *ngIf="journal['lissn']" class="uk-display-inline-block">
<span class="uk-display-inline-block">lissn: {{journal['lissn']}}</span>
<span>, </span>
</span>
<span *ngIf="journal && (journal['issn'] ||journal['lissn'] || journal['eissn'] )">
<a target="_blank" class="uk-display-inline-block custom-external"
[href]="properties.sherpaURL+(journal['issn']?journal['issn']:(journal['eissn']?journal['eissn']:journal['lissn'] ))+properties.sherpaURLSuffix"
uk-tooltip="title: View information on Sherpa/RoMEO ">
<img src="assets/common-assets/common/SHERPA-RoMEO-short-logo.gif" width=16 height=16 alt="" loading="lazy">
Copyright policy
</a>
</span>
<span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])">)</span>
</span>
</div>
<div *ngIf="publisher" class="uk-text-small uk-margin-small-top">
<span class="uk-text-meta">Publisher: </span> {{publisher}}
</div>
<ng-container *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
|| journal['volume'] || journal['eissn'] || journal['issue'])">
<ng-container *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
|| journal['volume'] || journal['eissn'] || journal['issue'])">
<span [attr.uk-tooltip]="'cls: uk-active'" [title]="'Journal'">
<span *ngIf="journal['journal']">{{journal['journal']}}</span>
<span *ngIf="journal['journal'] && (journal['volume'] || journal['issue'])">, </span>
<ng-container *ngIf="journal['volume']">
<span class="uk-display-inline-block">
volume
<span *ngIf="journal['volume'] > 0">{{journal['volume'] | number}}</span>
<span *ngIf="!(journal['volume'] > 0)">{{journal['volume']}}</span>
</span>
<span *ngIf="journal['issue'] || journal['start_page'] || journal['end_page']">, </span>
</ng-container>
<ng-container *ngIf="journal['issue']">
<span class="uk-display-inline-block">
issue
<span *ngIf="journal['issue'] > 0">{{journal['issue'] | number}}</span>
<span *ngIf="!(journal['issue'] > 0)">{{journal['issue']}}</span>
</span>
<span *ngIf="journal['start_page'] || journal['end_page']">, </span>
</ng-container>
<span *ngIf="(journal['volume'] || journal['issue']) && (journal['start_page'] || journal['end_page'])"
class="uk-display-inline-block">
{{(journal['start_page'] && journal['end_page']) ? 'pages' : 'page'}}
<span *ngIf="journal['start_page']">
<span *ngIf="journal['start_page'] > 0">{{journal['start_page'] | number}}</span>
<span *ngIf="!(journal['start_page'] > 0)">{{journal['start_page']}}</span>
</span>
<span *ngIf="journal['start_page'] && journal['end_page']">-</span>
<span *ngIf="journal['end_page']">
<span *ngIf="journal['end_page'] > 0">{{journal['end_page'] | number}}</span>
<span *ngIf="!(journal['end_page'] > 0)">{{journal['end_page']}}</span>
</span>
</span>
<span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])"> (</span>
<ng-container *ngIf="journal['issn']">
<span class="uk-display-inline-block">issn: {{journal['issn']}}</span>
<span>, </span>
</ng-container>
<ng-container *ngIf="journal['eissn']">
<span class="uk-display-inline-block">eissn: {{journal['eissn']}}</span>
<span>, </span>
</ng-container>
<span *ngIf="journal['lissn']" class="uk-display-inline-block">
<span class="uk-display-inline-block">lissn: {{journal['lissn']}}</span>
<span>, </span>
</span>
<span *ngIf="journal && (journal['issn'] ||journal['lissn'] || journal['eissn'] )">
<a target="_blank" class="uk-display-inline-block custom-external"
[href]="properties.sherpaURL+(journal['issn']?journal['issn']:(journal['eissn']?journal['eissn']:journal['lissn'] ))+properties.sherpaURLSuffix"
uk-tooltip="title: View information on Sherpa/RoMEO ">
<img src="assets/common-assets/common/SHERPA-RoMEO-short-logo.gif" width=16 height=16 alt="" loading="lazy">
Copyright policy
</a>
</span>
<span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])">)</span>
</span>
</ng-container>
<span *ngIf="publisher" class="uk-margin-xsmall-left uk-margin-xsmall-right bullet"></span>
</ng-container>
<ng-container *ngIf="publisher">
<span [attr.uk-tooltip]="'cls: uk-active'" [title]="'Publisher'">{{publisher}}</span>
</ng-container>
`
})
export class ShowPublisherComponent {
@Input() publishDate: Date;
@Input() publisher;
@Input() journal;
//@Input() sherpaUrl = 'http://www.sherpa.ac.uk/romeo/search.php?issn=';

View File

@ -1,10 +1,11 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {ShowPublisherComponent} from "./showPublisher.component";
import {IconsModule} from '../../utils/icons/icons.module';
@NgModule({
imports: [
CommonModule
CommonModule, IconsModule
],
declarations: [
ShowPublisherComponent

View File

@ -1,9 +1,9 @@
import {
ChangeDetectorRef,
Component,
ElementRef,
ElementRef, EventEmitter,
HostListener,
Input,
Input, Output,
QueryList,
ViewChild,
ViewChildren
@ -13,24 +13,24 @@ import {properties} from "../../../../environments/environment";
@Component({
selector: 'showSubjects',
template: `
<ng-container *ngIf="(classifiedSubjects && classifiedSubjects.size > 0) || (eoscSubjects && eoscSubjects.length > 0)">
<div class="uk-text-meta">
<ng-container *ngIf="!viewAllSubjects && ((classifiedSubjects && classifiedSubjects.size > 0) || (eoscSubjects && eoscSubjects.length > 0))">
<div *ngIf="!viewAllClassifiedSubjects" class="uk-text-meta">
Subjects by Vocabulary
</div>
<ng-container *ngTemplateOutlet="subjects_by_vocabulary_template; context: {customClasses: 'multi-line-ellipsis lines-2', id: 'content'}"></ng-container>
<ng-container *ngTemplateOutlet="subjects_by_vocabulary_template; context: {customClasses: (isMobile && viewAllClassifiedSubjects) ? '' : 'multi-line-ellipsis lines-2', id: 'content'}"></ng-container>
<ng-container *ngIf="eoscSubjects && eoscSubjects.length > 0"><ng-container *ngTemplateOutlet="eosc_subjects_template"></ng-container></ng-container>
<div *ngIf="isClassifiedLarge" class="uk-text-right">
<a (click)="openSubjectsByVocabularyModal()" class="view-more-less-link">View all</a>
<div *ngIf="isClassifiedLarge && !viewAllClassifiedSubjects" class="uk-text-right">
<a (click)="viewAllSubjectsByVocabularyClicked()" class="view-more-less-link">View all</a>
</div>
</ng-container>
<ng-container *ngIf="(subjects && subjects.length > 0) || (otherSubjects && otherSubjects.size > 0)">
<div class="uk-text-meta uk-margin-small-bottom" [class.uk-margin-medium-top]="classifiedSubjects && classifiedSubjects.size > 0">
Subjects
<ng-container *ngIf="!viewAllClassifiedSubjects && ((subjects && subjects.length > 0) || (otherSubjects && otherSubjects.size > 0))">
<div *ngIf="!viewAllSubjects" class="uk-text-meta uk-margin-small-bottom" [class.uk-margin-medium-top]="classifiedSubjects && classifiedSubjects.size > 0">
Keywords
</div>
<ng-container *ngTemplateOutlet="subjects_template; context: {customClasses: 'multi-line-ellipsis lines-2', id: 'content'}"></ng-container>
<div *ngIf="isLarge" class="uk-text-right uk-margin-small-top">
<a (click)="openSubjectsModal()" class="view-more-less-link">View all</a>
<ng-container *ngTemplateOutlet="subjects_template; context: {customClasses: (isMobile && viewAllSubjects) ? '' : 'multi-line-ellipsis lines-2', id: 'content'}"></ng-container>
<div *ngIf="isLarge && !viewAllSubjects" class="uk-text-right uk-margin-small-top">
<a (click)="viewAllSubjectsClicked()" class="view-more-less-link">View all</a>
</div>
</ng-container>
@ -49,7 +49,7 @@ import {properties} from "../../../../environments/environment";
</div>
</ng-template>
<modal-alert #subjectsModal *ngIf="(subjects && subjects.length > 0) || (otherSubjects && otherSubjects.size > 0)">
<modal-alert #subjectsModal *ngIf="!isMobile && ((subjects && subjects.length > 0) || (otherSubjects && otherSubjects.size > 0))">
<div class="uk-text-small">
<ng-container *ngTemplateOutlet="subjects_template"></ng-container>
</div>
@ -94,7 +94,7 @@ import {properties} from "../../../../environments/environment";
</div>
</ng-template>
<modal-alert #subjectsByVocabularyModal *ngIf="(classifiedSubjects && classifiedSubjects.size > 0) || (eoscSubjects && eoscSubjects.length > 0)" large="true">
<modal-alert #subjectsByVocabularyModal *ngIf="!isMobile && ((classifiedSubjects && classifiedSubjects.size > 0) || (eoscSubjects && eoscSubjects.length > 0))" large="true">
<div class="uk-text-small">
<ng-container *ngTemplateOutlet="subjects_by_vocabulary_template"></ng-container>
<ng-container *ngIf="eoscSubjects && eoscSubjects.length > 0"><ng-container *ngTemplateOutlet="eosc_subjects_template"></ng-container></ng-container>
@ -104,12 +104,16 @@ import {properties} from "../../../../environments/environment";
})
export class ShowSubjectsComponent {
@Input() isMobile: boolean = false;
@Input() subjects: string[];
@Input() otherSubjects: Map<string, string[]>;
@Input() classifiedSubjects: Map<string, string[]>;
@Input() eoscSubjects: any[];
isLarge: boolean = false;
isClassifiedLarge: boolean = false;
@Input() viewAllSubjects: boolean = false;
@Input() viewAllClassifiedSubjects: boolean = false;
@Output() viewAllClicked = new EventEmitter();
properties = properties;
specialSubjects = [];
@ViewChildren("content", { read: ElementRef }) content: QueryList<ElementRef>;
@ -206,4 +210,28 @@ export class ShowSubjectsComponent {
this.subjectsByVocabularyModal.alertTitle = "Subjects by Vocabulary";
this.subjectsByVocabularyModal.open();
}
public viewAllSubjectsClicked() {
if(this.isMobile) {
this.viewAllSubjects = true;
this.viewAllClicked.emit({
subtitle: 'Keywords',
id: 'subjects'
});
} else {
this.openSubjectsModal();
}
}
public viewAllSubjectsByVocabularyClicked() {
if(this.isMobile) {
this.viewAllClassifiedSubjects = true;
this.viewAllClicked.emit({
subtitle: 'Subjects by Vocabulary',
id: 'classifiedSubjects'
});
} else {
this.openSubjectsByVocabularyModal();
}
}
}

View File

@ -1,52 +1,56 @@
import {Component, Input} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {Component, ElementRef, Input, ViewChild} from '@angular/core';
@Component({
selector: 'showTitle',
template: `
<h1 [ngClass]="classNames" class="uk-h5">
<ng-container *ngTemplateOutlet="_title;"></ng-container>
</h1>
<ng-template #_title>
<div *ngIf="title != undefined" class="landingTitle uk-text-break">
<span *ngIf="title['url'] != undefined && title['url'] != null && title['url'] != ''"
class="custom-external">
<a *ngIf="title['name'] != undefined && title['name'] != ''"
href="{{title['url']}}" target="_blank"
[innerHTML]="title['name']">
</a>
<a *ngIf="title['name'] == undefined || title['name'] == ''"
href="{{title['url']}}" target="_blank">
[no title available]
</a>
</span>
<span *ngIf="(title['name'] != undefined && title['name'] != '') &&
(title['url'] == undefined || title['url'] == null || title['url'] == '')"
[innerHTML]="title['name']">
</span>
<span *ngIf="(title['name'] == undefined || title['name'] == '') &&
(title['url'] == undefined || title['url'] == null || title['url'] == '')"
>
[no title available]
</span>
</div>
<div *ngIf="titleName" class="uk-text-break">
<span [innerHTML]="titleName"></span>
</div>
<div *ngIf="!titleName && !title">
<span>No title available</span>
</div>
</ng-template>
`
selector: 'showTitle',
template: `
<h1 [ngClass]="classNames" class="uk-h6">
<ng-container *ngTemplateOutlet="_title;"></ng-container>
</h1>
})
<ng-template #_title>
<div *ngIf="title != undefined" class="landingTitle uk-text-break">
<span *ngIf="title['url'] != undefined && title['url'] != null && title['url'] != ''"
class="custom-external">
<a *ngIf="title['name'] != undefined && title['name'] != ''"
href="{{title['url']}}" target="_blank"
[innerHTML]="title['name']">
</a>
<a *ngIf="title['name'] == undefined || title['name'] == ''"
href="{{title['url']}}" target="_blank">
[no title available]
</a>
</span>
<span *ngIf="(title['name'] != undefined && title['name'] != '') &&
(title['url'] == undefined || title['url'] == null || title['url'] == '')"
[innerHTML]="title['name']">
</span>
<span *ngIf="(title['name'] == undefined || title['name'] == '') &&
(title['url'] == undefined || title['url'] == null || title['url'] == '')">
[no title available]
</span>
</div>
<div *ngIf="titleName" #titleDiv class="uk-text-break multi-line-ellipsis" [ngClass]="isSticky ? 'lines-1' : 'lines-5'">
<span [innerHTML]="titleName" [attr.uk-tooltip]="showTitleTooltip ? 'cls: uk-active uk-width-large' : 'cls: uk-invisible'"
[title]="titleName"></span>
</div>
<div *ngIf="!titleName && !title">
<span>No title available</span>
</div>
</ng-template>
`
})
export class ShowTitleComponent {
@Input() titleName: string;
@Input() title: { [key: string]: string };
@Input() iconClass:string;
@Input() classNames: string = "";
@Input() isSticky: boolean = false;
@ViewChild("titleDiv") titleDiv: ElementRef;
constructor () {}
get showTitleTooltip():boolean {
return !!this.titleDiv && (this.titleDiv.nativeElement.clientHeight >= 5 * 21);
}
}

View File

@ -27,7 +27,7 @@ import {HelperFunctions} from "../../../utils/HelperFunctions.class";
<ul class="uk-list uk-list-divider uk-margin">
<li *ngFor="let result of results.slice((page-1)*pageSize, page*pageSize)">
<result-preview [modal]="modal" [properties]="properties" [hasLink]="false" [result]="getResultPreview(result)"
[isCard]="false" [prevPath]="prevPath"></result-preview>
[isCard]="false" [prevPath]="prevPath" [isDeletedByInferenceModal]="true"></result-preview>
</li>
</ul>
<no-load-paging *ngIf="results.length > pageSize" [type]="type"

View File

@ -1,5 +1,6 @@
<div id="tm-main" class="landing uk-section uk-padding-remove tm-middle">
<div class="tm-main">
<!-- Desktop view -->
<div id="tm-main" class="uk-visible@m landing uk-section uk-padding-remove tm-middle">
<div *ngIf="!isMobile" class="tm-main">
<div class="organization">
<div *ngIf="properties.adminToolsPortalType == 'eosc'" class="eosc-explore-back-search-bar">
<div class="uk-light uk-container uk-container-large uk-padding-small uk-height-1-1">
@ -13,13 +14,12 @@
</div>
<div *ngIf="!showFeedback" class="uk-grid uk-margin-remove-left" uk-grid>
<!-- left column -->
<div id="landing-left-sidebar" *ngIf="organizationInfo" class="uk-visible@s uk-padding-remove-horizontal">
<!-- <div id="landing-left-sidebar" *ngIf="organizationInfo" class="uk-visible@s uk-padding-remove-horizontal">
<div class="uk-flex uk-flex-column uk-flex-right uk-sticky"
uk-sticky="bottom: true" [attr.offset]="offset">
<div class="uk-margin-large-bottom uk-align-center">
<div class="uk-text-meta uk-text-uppercase">Actions</div>
<ul class="uk-list">
<!-- Share -->
<li class="uk-text-center">
<a (click)="openAddThisModal()" [title]="'Share this '+openaireEntities.ORGANIZATION+' in your social networks'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
@ -28,7 +28,6 @@
</span>
</a>
</li>
<!-- Download -->
<li class="uk-text-center"
[title]="'Download reports'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
@ -41,20 +40,14 @@
</ul>
</div>
</div>
</div>
</div> -->
<!-- center/right column -->
<div class="uk-width-expand uk-padding-remove uk-background-default">
<div *ngIf="errorMessage.length > 0 || showLoading" class="uk-container uk-flex uk-flex-center uk-height-viewport uk-position-relative">
<div *ngIf="errorMessage.length > 0" class="uk-alert uk-alert-danger uk-width-2-3 uk-margin-xlarge-top"
role="alert">{{errorMessage}}</div>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
</div>
<div id="landing-center-content" class="uk-width-expand uk-padding-remove uk-background-default">
<!-- Graph and feedback -->
<ng-template #graph_and_feedback_template>
<div class="uk-flex uk-flex-between uk-flex-wrap uk-margin-small-bottom uk-margin-small-top" [class.uk-invisible]="!organizationInfo">
<div class="uk-container uk-container-xlarge uk-flex uk-flex-between uk-flex-wrap uk-margin-small-top uk-margin-small-bottom" [class.uk-invisible]="!organizationInfo">
<!-- Last Index Info-->
<a href="https://graph.openaire.eu" target="_blank" class="uk-width-1-1 uk-width-auto@l">
<img src="assets/common-assets/openaire-badge-1.png" alt="Powered by OpenAIRE graph" style="height: 15px;">
@ -70,165 +63,206 @@
</div>
</div>
</ng-template>
<div #graph_and_feedback id="graph_and_feedback" class="uk-padding uk-padding-remove-vertical uk-blur-background uk-text-xsmall uk-visible@m"
uk-sticky="bottom: true;" [attr.offset]="graph_offset">
<div #graph_and_feedback id="graph_and_feedback" class="uk-blur-background uk-text-xsmall uk-visible@m"
uk-sticky="bottom: true;" [attr.offset]="graph_offset">
<ng-container *ngTemplateOutlet="graph_and_feedback_template"></ng-container>
</div>
<div class="uk-margin-large-left uk-margin-large-right" [style]="'margin-bottom: '+graph_height+'px'">
<ng-container *ngIf="organizationInfo">
<!-- Main content -->
<div [attr.style]="'margin-top: '+(graph_height? 'calc(40px + 20px - '+graph_height+'px)': '40px')">
<!-- Schema -->
<schema2jsonld *ngIf="organizationInfo" [data]=organizationInfo
[URL]="properties.domain + properties.baseLink+this.properties.searchLinkToOrganization+organizationInfo.relcanId"
type="organization">
</schema2jsonld>
<!-- Actions for mobile viewport -->
<div class="uk-flex uk-flex-right uk-margin-medium-bottom uk-hidden@s">
<div class="uk-margin-small-right">
<a (click)="openAddThisModal()" [title]="'Share this '+openaireEntities.ORGANIZATION+' in your social networks'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
<span class="uk-icon-button uk-icon landing-action-button landing-action-button-portal">
<icon name="share" visuallyHidden="share"></icon>
<div class="uk-container uk-container-xlarge">
<div *ngIf="errorMessage.length > 0 || showLoading" class="uk-container uk-flex uk-flex-center uk-height-viewport uk-position-relative">
<div *ngIf="errorMessage.length > 0" class="uk-alert uk-alert-danger uk-width-2-3 uk-margin-xlarge-top"
role="alert">{{errorMessage}}</div>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
</div>
<!-- new action bar -->
<div *ngIf="!showLoading && organizationInfo" class="uk-margin-top uk-margin-bottom">
<div class="uk-flex uk-flex-middle uk-flex-center">
<div class="landing-action-bar uk-box-shadow-small uk-margin-bottom">
<div class="uk-grid uk-grid-small uk-flex-between uk-text-xsmall uk-flex-middle uk-grid-divider" uk-grid>
<div *ngIf="organizationInfo?.deletedByInferenceIds" class="uk-width-auto">
<!-- Versions -->
<a (click)="openDeletedByInference()"
class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder">
<icon flex="true" ratio="0.8" name="versions" visuallyHidden="versions"></icon>
<span class="uk-margin-xsmall-left">
View all {{organizationInfo.deletedByInferenceIds.length}} versions
</span>
</a>
</div>
<div [title]="'Download reports'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
<a class="uk-link-text uk-text-bold uk-text-uppercase" (click)="buildFunderOptions(); openDownloadReportsModal()">
<span class="uk-icon-button uk-icon landing-action-button landing-action-button-portal">
<icon name="download" visuallyHidden="download"></icon>
</span>
</a>
</a>
</div>
<div class="uk-width-expand">
<entity-actions [share]="true" [type]="'organization'">
<div>
<a (click)="buildFunderOptions(); openDownloadReportsModal()"
class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder">
<icon flex="true" ratio="0.8" name="download" visuallyHidden="download"></icon>
<span class="uk-margin-xsmall-left">Download</span>
</a>
</div>
</entity-actions>
</div>
</div>
</div>
<!-- Helper -->
<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
[texts]="pageContents['top']"></helper>
<!-- Versions -->
<span *ngIf="organizationInfo.deletedByInferenceIds" class="uk-text-primary uk-flex uk-flex-middle">
<icon flex="true" ratio="0.8" name="auto_awesome_motion"></icon>
<a (click)="openDeletedByInference()" class="uk-text-primary uk-text-small uk-margin-small-left">
View all {{organizationInfo.deletedByInferenceIds.length}} versions
</a>
</span>
<!-- Landing header -->
<landing-header [properties]="properties" [title]="organizationInfo.title.name"
[subTitle]="(organizationInfo.name
&& organizationInfo.title.name !== organizationInfo.name)?organizationInfo.name:null"
[entityType]="'organization'">
</landing-header>
<!-- Basic info -->
<div class="uk-text-small">
<!-- Web Page -->
<div *ngIf="organizationInfo.title && organizationInfo.title.url" class="uk-margin-small-bottom uk-display-inline-block">
<span class="uk-text-meta">Web page: </span>
<a [href]="organizationInfo.title.url" target="_blank" class="uk-button uk-button-text uk-text-lowercase uk-text-normal custom-external">
{{organizationInfo.title.url}}
</a>
</div>
<!-- Country -->
<div *ngIf="organizationInfo.country && !organizationInfo.country.toLowerCase().includes('unknown')">
<span class="uk-text-meta">Country: </span>{{organizationInfo.country}}
</div>
</div>
</div>
<!-- Tabs section -->
<div id="main-tabs-div" class="uk-sticky uk-blur-background"
uk-sticky="bottom: true; media: @m" [attr.offset]="offset">
<div class="uk-padding uk-padding-remove-horizontal uk-padding-remove-bottom">
<!-- <showTitle *ngIf="stickyHeader" [titleName]="organizationInfo.title.name" classNames="uk-margin-remove-bottom" class="uk-visible@m"></showTitle>-->
<landing-header *ngIf="stickyHeader" class="uk-visible@m"
[properties]="properties" [title]="organizationInfo.title.name"
[subTitle]="(organizationInfo.name
&& organizationInfo.title.name !== organizationInfo.name)?organizationInfo.name:null"
[entityType]="'organization'" isSticky="true">
</landing-header>
<my-tabs (selectedActiveTab)="onSelectActiveTab($event)" [offsetForSticky]="offset" [(isSticky)]="stickyHeader">
<my-tab [active]="true" [tabTitle]="'Funding / ' +openaireEntities.PROJECTS" [tabId]="'projects'"
[tabNumber]="fetchProjects.searchUtils.totalResults > 0 ? fetchProjects.searchUtils.totalResults : ''">
</my-tab>
<my-tab *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0"
[tabTitle]="openaireEntities.DATASOURCES" [tabId]="'dataProviders'"
[tabNumber]="fetchDataproviders.searchUtils.totalResults">
</my-tab>
<my-tab *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0"
[tabNumber]="fetchPublications.searchUtils.totalResults"
[tabTitle]="openaireEntities.PUBLICATIONS" [tabId]="'publications'">
</my-tab>
<my-tab *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0"
[tabNumber]="fetchDatasets.searchUtils.totalResults"
[tabTitle]="openaireEntities.DATASETS" [tabId]="'datasets'">
</my-tab>
<my-tab *ngIf="fetchSoftware && fetchSoftware.searchUtils.totalResults > 0"
[tabNumber]="fetchSoftware.searchUtils.totalResults"
[tabTitle]="openaireEntities.SOFTWARE" [tabId]="'software'">
</my-tab>
<my-tab *ngIf="fetchOrps && fetchOrps.searchUtils.totalResults > 0"
[tabNumber]="fetchOrps.searchUtils.totalResults"
[tabTitle]="openaireEntities.OTHER" [tabId]="'other'">
</my-tab>
</my-tabs>
</div>
</div>
<!-- Tabs content section -->
<div id="landing-sections" class="uk-text-small">
<div id="projects" class="landing-section landing-section-height-auto uk-padding uk-padding-remove-horizontal">
<projectsInModal [fetchProjects]="fetchProjects"
[organizationId]="organizationId" [properties]=properties [prevPath]="prevPath">
</projectsInModal>
</div>
<div *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0"
id="dataProviders" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchDataproviders" resultType="dataprovider"
[params]="getParamsForSearchLink()"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedDataProviders"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0"
id="publications" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchPublications" resultType="publication"
[params]="getParamsForSearchLink('publications')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0"
id="datasets" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchDatasets" resultType="dataset"
[params]="getParamsForSearchLink('datasets')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="fetchSoftware && fetchSoftware.searchUtils.totalResults > 0"
id="software" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchSoftware" resultType="software"
[params]="getParamsForSearchLink('software')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="fetchOrps && fetchOrps.searchUtils.totalResults > 0"
id="other" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchOrps" resultType="other"
[params]="getParamsForSearchLink('other')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</div>
<div class="uk-text-xsmall uk-hidden@m">
<ng-container *ngTemplateOutlet="graph_and_feedback_template"></ng-container>
</div>
<!-- Helper -->
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0"
[texts]="pageContents['bottom']">
</helper>
</ng-container>
</div>
</div>
</div>
<div class="uk-margin-left uk-margin-right" [style]="'margin-bottom: '+graph_height+'px'">
<ng-container *ngIf="organizationInfo">
<!-- Main content -->
<div [attr.style]="'margin-top: '+(graph_height? 'calc(40px + 20px - '+graph_height+'px)': '40px')">
<!-- Schema -->
<schema2jsonld *ngIf="organizationInfo" [data]=organizationInfo
[URL]="properties.domain + properties.baseLink+this.properties.searchLinkToOrganization+organizationInfo.relcanId"
type="organization">
</schema2jsonld>
<!-- Actions for mobile viewport -->
<div class="uk-flex uk-flex-right uk-margin-medium-bottom uk-hidden@s">
<div class="uk-margin-small-right">
<a (click)="openAddThisModal()" [title]="'Share this '+openaireEntities.ORGANIZATION+' in your social networks'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
<span class="uk-icon-button uk-icon landing-action-button landing-action-button-portal">
<icon name="share" visuallyHidden="share"></icon>
</span>
</a>
</div>
<div [title]="'Download reports'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
<a class="uk-link-text uk-text-bold uk-text-uppercase" (click)="buildFunderOptions(); openDownloadReportsModal()">
<span class="uk-icon-button uk-icon landing-action-button landing-action-button-portal">
<icon name="download" visuallyHidden="download"></icon>
</span>
</a>
</div>
</div>
<!-- Helper -->
<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
[texts]="pageContents['top']"></helper>
<!-- Versions -->
<!-- <span *ngIf="organizationInfo.deletedByInferenceIds" class="uk-text-primary uk-flex uk-flex-middle">
<icon flex="true" ratio="0.8" name="auto_awesome_motion"></icon>
<a (click)="openDeletedByInference()" class="uk-text-primary uk-text-small uk-margin-small-left">
View all {{organizationInfo.deletedByInferenceIds.length}} versions
</a>
</span> -->
<!-- Landing header -->
<landing-header [properties]="properties" [title]="organizationInfo.title.name"
[subTitle]="(organizationInfo.name
&& organizationInfo.title.name !== organizationInfo.name)?organizationInfo.name:null"
[entityType]="'organization'" [prevPath]="prevPath">
</landing-header>
<!-- Basic info -->
<div class="uk-text-small">
<!-- Web Page -->
<div *ngIf="organizationInfo.title && organizationInfo.title.url" class="uk-margin-small-bottom uk-display-inline-block">
<span class="uk-text-meta">Web page: </span>
<a [href]="organizationInfo.title.url" target="_blank" class="uk-button uk-button-text uk-text-lowercase uk-text-normal custom-external">
{{organizationInfo.title.url}}
</a>
</div>
<!-- Country -->
<div *ngIf="organizationInfo.country && !organizationInfo.country.toLowerCase().includes('unknown')">
<span class="uk-text-meta">Country: </span>{{organizationInfo.country}}
</div>
</div>
</div>
<!-- Tabs section -->
<div id="main-tabs-div" class="uk-sticky uk-blur-background"
uk-sticky="bottom: true; media: @m" [attr.offset]="offset">
<div class="uk-padding uk-padding-remove-horizontal uk-padding-remove-bottom">
<!-- <showTitle *ngIf="stickyHeader" [titleName]="organizationInfo.title.name" classNames="uk-margin-remove-bottom" class="uk-visible@m"></showTitle>-->
<landing-header [ngClass]="stickyHeader ? 'uk-visible@m' : 'uk-invisible'"
[properties]="properties" [title]="organizationInfo.title.name"
[entityType]="'organization'" isSticky="true" [prevPath]="prevPath">
</landing-header>
<my-tabs (selectedActiveTab)="onSelectActiveTab($event)" [offsetForSticky]="offset" [(isSticky)]="stickyHeader">
<my-tab [active]="true" [tabTitle]="'Funding / ' +openaireEntities.PROJECTS" [tabId]="'projects'"
[tabNumber]="fetchProjects.searchUtils.totalResults > 0 ? fetchProjects.searchUtils.totalResults : ''">
</my-tab>
<my-tab *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0"
[tabTitle]="openaireEntities.DATASOURCES" [tabId]="'dataProviders'"
[tabNumber]="fetchDataproviders.searchUtils.totalResults">
</my-tab>
<my-tab *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0"
[tabNumber]="fetchPublications.searchUtils.totalResults"
[tabTitle]="openaireEntities.PUBLICATIONS" [tabId]="'publications'">
</my-tab>
<my-tab *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0"
[tabNumber]="fetchDatasets.searchUtils.totalResults"
[tabTitle]="openaireEntities.DATASETS" [tabId]="'datasets'">
</my-tab>
<my-tab *ngIf="fetchSoftware && fetchSoftware.searchUtils.totalResults > 0"
[tabNumber]="fetchSoftware.searchUtils.totalResults"
[tabTitle]="openaireEntities.SOFTWARE" [tabId]="'software'">
</my-tab>
<my-tab *ngIf="fetchOrps && fetchOrps.searchUtils.totalResults > 0"
[tabNumber]="fetchOrps.searchUtils.totalResults"
[tabTitle]="openaireEntities.OTHER" [tabId]="'other'">
</my-tab>
</my-tabs>
</div>
</div>
<!-- Tabs content section -->
<div id="landing-sections" class="uk-text-small">
<div id="projects" class="landing-section landing-section-height-auto">
<projectsInModal [fetchProjects]="fetchProjects"
[organizationId]="organizationId" [properties]=properties [prevPath]="prevPath">
</projectsInModal>
</div>
<div *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0"
id="dataProviders" class="landing-section">
<search-tab [fetch]="fetchDataproviders" resultType="dataprovider"
[params]="getParamsForSearchLink()"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedDataProviders"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0"
id="publications" class="landing-section">
<search-tab [fetch]="fetchPublications" resultType="publication"
[params]="getParamsForSearchLink('publications')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0"
id="datasets" class="landing-section">
<search-tab [fetch]="fetchDatasets" resultType="dataset"
[params]="getParamsForSearchLink('datasets')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="fetchSoftware && fetchSoftware.searchUtils.totalResults > 0"
id="software" class="landing-section">
<search-tab [fetch]="fetchSoftware" resultType="software"
[params]="getParamsForSearchLink('software')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="fetchOrps && fetchOrps.searchUtils.totalResults > 0"
id="other" class="landing-section">
<search-tab [fetch]="fetchOrps" resultType="other"
[params]="getParamsForSearchLink('other')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</div>
<div class="uk-text-xsmall uk-hidden@m">
<ng-container *ngTemplateOutlet="graph_and_feedback_template"></ng-container>
</div>
<!-- Helper -->
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0"
[texts]="pageContents['bottom']">
</helper>
</ng-container>
</div>
</div>
</div>
</div>
</div>
@ -240,6 +274,114 @@
</feedback>
</div>
<!-- Mobile view -->
<div *ngIf="isMobile" class="uk-hidden@m uk-position-relative landing">
<ng-container *ngIf="organizationInfo">
<div *ngIf="mobileContent == 'info'" class="uk-container uk-section">
<landing-header [properties]="properties" [title]="organizationInfo.title.name"
[subTitle]="(organizationInfo.name
&& organizationInfo.title.name !== organizationInfo.name)?organizationInfo.name:null"
[entityType]="'organization'" [prevPath]="prevPath">
</landing-header>
<div class="uk-section uk-margin-top uk-text-large uk-text-empashis uk-text-bold">
<hr>
<ng-container>
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(fsModal, 'Funding / '+openaireEntities.PROJECTS); onSelectActiveTab('projects')">
<span>Funding / {{openaireEntities.PROJECTS}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between"
(click)="openFsModal(fsModal, openaireEntities.DATASOURCES); onSelectActiveTab('dataProviders')">
<span>{{openaireEntities.DATASOURCES}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between"
(click)="openFsModal(fsModal, openaireEntities.PUBLICATIONS); onSelectActiveTab('publications')">
<span>{{openaireEntities.PUBLICATIONS}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between"
(click)="openFsModal(fsModal, openaireEntities.DATASETS); onSelectActiveTab('datasets')">
<span>{{openaireEntities.DATASETS}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchSoftware && fetchSoftware.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between"
(click)="openFsModal(fsModal, openaireEntities.SOFTWARE); onSelectActiveTab('software')">
<span>{{openaireEntities.SOFTWARE}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchOrps && fetchOrps.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between"
(click)="openFsModal(fsModal, openaireEntities.OTHER); onSelectActiveTab('other')">
<span>{{openaireEntities.OTHER}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
</div>
</div>
<div *ngIf="mobileContent == 'actions'" class="uk-container uk-section">
<ng-container *ngIf="organizationInfo?.deletedByInferenceIds">
<div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal"
(click)="deleteByInferenceOpened = true; openFsModal(alertModalDeletedByInferenceFS, 'Other versions')">
<icon [flex]="true" name="versions" visuallyHidden="versions"></icon>
<span class="uk-margin-small-left">
View all {{organizationInfo.deletedByInferenceIds.length}} versions
</span>
</div>
<hr class="uk-margin-remove">
</ng-container>
<ng-container>
<div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal"
(click)="openFsModal(addThisFsModal, 'Share this '+openaireEntities.ORGANIZATION+' in your social networks')">
<icon [flex]="true" name="share" visuallyHidden="share"></icon>
<span class="uk-margin-small-left">Share</span>
</div>
<hr class="uk-margin-remove">
</ng-container>
<ng-container>
<div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal"
(click)="buildFunderOptions(); openFsModal(downloadReportsFsModal, 'Download')">
<icon [flex]="true" name="download" visuallyHidden="download"></icon>
<span class="uk-margin-small-left">Download</span>
</div>
<hr class="uk-margin-remove">
</ng-container>
</div>
<div class="landing-action-bar-mobile uk-background-default">
<div class="uk-container uk-grid uk-flex-middle uk-child-width-1-2 uk-text-xsmall uk-text-meta">
<div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'">
<icon name="corporate_fare" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"></icon>
<span>{{openaireEntities.ORGANIZATION}}</span>
</a>
</div>
<div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'actions'">
<icon name="pending" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'actions' ? 'uk-text-primary': ''"></icon>
<span>Actions</span>
</a>
</div>
</div>
</div>
</ng-container>
</div>
<!-- MODALS -->
<!-- Other versions -->
<modal-alert #AlertModalDeletedByInference *ngIf="organizationInfo && organizationInfo.deletedByInferenceIds" large="true">
@ -259,96 +401,180 @@
<div class="uk-padding-small uk-margin-small-left uk-margin-small-right">
<div class="uk-padding-small uk-padding-remove-vertical">
<div class="uk-grid uk-grid-divider uk-child-width-1-2@m" uk-grid uk-height-match=".subtitle">
<div class="uk-animation-slide-top-small">
<div class="subtitle uk-flex uk-flex-middle">
<span class="uk-text-nowrap">Content report</span>
</div>
<ul class="uk-list uk-margin-remove-bottom" *ngIf="total > 0">
<li [attr.uk-tooltip]="total > 0 ? 'cls: uk-invisible' : 'cls: uk-active'"
title="No report available">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
[class]="total > 0 ? '' : 'uk-disabled uk-text-muted'"
(click)="downloadFile(getCSVAffiliated('results'), openaireEntities.RESULTS_FILE + '-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
all {{openaireEntities.RESULTS}} (CSV)
</div>
</li>
<li [attr.uk-tooltip]="fetchPublications.searchUtils.totalResults > 0 ? 'cls: uk-invisible' : 'cls: uk-active'"
title="No report available">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
[class]="fetchPublications.searchUtils.totalResults > 0 ? '' : 'uk-disabled uk-text-muted'"
(click)="downloadFile(getCSVAffiliated('publications'), openaireEntities.PUBLICATIONS_FILE + '-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{openaireEntities.PUBLICATIONS}} (CSV)
</div>
</li>
<li [attr.uk-tooltip]="fetchDatasets.searchUtils.totalResults > 0 ? 'cls: uk-invisible' : 'cls: uk-active'"
title="No report available">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
[class]="fetchDatasets.searchUtils.totalResults > 0 ? '' : 'uk-disabled uk-text-muted'"
(click)="downloadFile(getCSVAffiliated('datasets'), openaireEntities.DATASETS_FILE + '-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{openaireEntities.DATASETS}} (CSV)
</div>
</li>
<li [attr.uk-tooltip]="fetchSoftware.searchUtils.totalResults > 0 ? 'cls: uk-invisible' : 'cls: uk-active'"
title="No report available">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
[class]="fetchSoftware.searchUtils.totalResults > 0 ? '' : 'uk-disabled uk-text-muted'"
(click)="downloadFile(getCSVAffiliated('software'), openaireEntities.SOFTWARE_FILE + '-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{openaireEntities.SOFTWARE}} (CSV)
</div>
</li>
<li [attr.uk-tooltip]="fetchOrps.searchUtils.totalResults > 0 ? 'cls: uk-invisible' : 'cls: uk-active'"
title="No report available">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
[class]="fetchOrps.searchUtils.totalResults > 0 ? '' : 'uk-disabled uk-text-muted'"
(click)="downloadFile(getCSVAffiliated('other'), openaireEntities.OTHER_FILE + '-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{openaireEntities.OTHER}} (CSV)
</div>
</li>
</ul>
<div *ngIf="total == 0" class="uk-text-muted uk-margin-top">
No reports available
</div>
</div>
<div>
<div class="subtitle uk-flex uk-flex-middle">
<span class="uk-text-nowrap">Funder report</span>
<div input type="select" placeholder="Select a funder to download report" inputClass="flat x-small" class="uk-width-1-1 uk-margin-small-left"
[options]="funderOptions" [(value)]="funder" *ngIf="fetchProjects.funders && fetchProjects.funders.length > 0">
</div>
</div>
<div *ngIf="fetchProjects.funders && fetchProjects.funders.length > 0">
<div class="uk-animation-slide-top-small uk-margin-top" *ngIf="funder && funder != ''">
<ul class="uk-list uk-margin-remove-bottom">
<li>
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
(click)="downloadFile(getFunderProjects(), funder.name + '-'+openaireEntities.PROJECTS_FILE+'-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{openaireEntities.PROJECTS}} (CSV)
</div>
</li>
<li *ngFor="let contentType of contentTypes">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
(click)="confirmOpenApplyAll(contentType[0], contentType[2])">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{contentType[1]}} (CSV)
</div>
</li>
</ul>
</div>
</div>
<div *ngIf="!fetchProjects.funders || fetchProjects.funders.length == 0" class="uk-text-muted uk-margin-top">
No reports available
</div>
</div>
<ng-container *ngTemplateOutlet="downloadOptions"></ng-container>
</div>
</div>
</div>
</modal-alert>
<modal-alert #AlertModalApplyAll (alertOutput)="confirmCloseApplyAll()"></modal-alert>
<modal-alert #AlertModalCsvError></modal-alert>
<modal-loading></modal-loading>
<modal-loading [isMobile]="isMobile" classTitle="uk-tile-default uk-border-bottom"></modal-loading>
<ng-template #downloadOptions>
<div class="uk-animation-slide-top-small">
<div class="subtitle uk-flex uk-flex-middle">
<span class="uk-text-nowrap">Content report</span>
</div>
<ul class="uk-list uk-margin-remove-bottom" *ngIf="total > 0">
<li [attr.uk-tooltip]="total > 0 ? 'cls: uk-invisible' : 'cls: uk-active'"
title="No report available">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
[class]="total > 0 ? '' : 'uk-disabled uk-text-muted'"
(click)="downloadFile(getCSVAffiliated('results'), openaireEntities.RESULTS_FILE + '-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
all {{openaireEntities.RESULTS}} (CSV)
</div>
</li>
<li [attr.uk-tooltip]="fetchPublications.searchUtils.totalResults > 0 ? 'cls: uk-invisible' : 'cls: uk-active'"
title="No report available">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
[class]="fetchPublications.searchUtils.totalResults > 0 ? '' : 'uk-disabled uk-text-muted'"
(click)="downloadFile(getCSVAffiliated('publications'), openaireEntities.PUBLICATIONS_FILE + '-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{openaireEntities.PUBLICATIONS}} (CSV)
</div>
</li>
<li [attr.uk-tooltip]="fetchDatasets.searchUtils.totalResults > 0 ? 'cls: uk-invisible' : 'cls: uk-active'"
title="No report available">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
[class]="fetchDatasets.searchUtils.totalResults > 0 ? '' : 'uk-disabled uk-text-muted'"
(click)="downloadFile(getCSVAffiliated('datasets'), openaireEntities.DATASETS_FILE + '-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{openaireEntities.DATASETS}} (CSV)
</div>
</li>
<li [attr.uk-tooltip]="fetchSoftware.searchUtils.totalResults > 0 ? 'cls: uk-invisible' : 'cls: uk-active'"
title="No report available">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
[class]="fetchSoftware.searchUtils.totalResults > 0 ? '' : 'uk-disabled uk-text-muted'"
(click)="downloadFile(getCSVAffiliated('software'), openaireEntities.SOFTWARE_FILE + '-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{openaireEntities.SOFTWARE}} (CSV)
</div>
</li>
<li [attr.uk-tooltip]="fetchOrps.searchUtils.totalResults > 0 ? 'cls: uk-invisible' : 'cls: uk-active'"
title="No report available">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
[class]="fetchOrps.searchUtils.totalResults > 0 ? '' : 'uk-disabled uk-text-muted'"
(click)="downloadFile(getCSVAffiliated('other'), openaireEntities.OTHER_FILE + '-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{openaireEntities.OTHER}} (CSV)
</div>
</li>
</ul>
<div *ngIf="total == 0" class="uk-text-muted uk-margin-top">
No reports available
</div>
</div>
<div [ngClass]="isMobile ? 'uk-margin-large-top' : ''">
<div class="subtitle" [ngClass]="isMobile ? '' : 'uk-flex uk-flex-middle'">
<span class="uk-text-nowrap">Funder report</span>
<div input type="select" placeholder="Select a funder to download report" inputClass="flat x-small"
class="uk-width-1-1" [ngClass]="isMobile ? 'uk-margin-top' : 'uk-margin-small-left'"
[options]="funderOptions" [(value)]="funder" *ngIf="fetchProjects.funders && fetchProjects.funders.length > 0">
</div>
</div>
<div *ngIf="fetchProjects.funders && fetchProjects.funders.length > 0">
<div class="uk-animation-slide-top-small uk-margin-top" *ngIf="funder && funder != ''">
<ul class="uk-list uk-margin-remove-bottom">
<li>
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
(click)="downloadFile(getFunderProjects(), funder.name + '-'+openaireEntities.PROJECTS_FILE+'-report')">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{openaireEntities.PROJECTS}} (CSV)
</div>
</li>
<li *ngFor="let contentType of contentTypes">
<div class="uk-flex uk-flex-middle uk-button uk-button-link uk-text-normal"
(click)="confirmOpenApplyAll(contentType[0], contentType[2])">
<icon name="download" flex="true" class="uk-margin-small-right"></icon>
{{contentType[1]}} (CSV)
</div>
</li>
</ul>
</div>
</div>
<div *ngIf="!fetchProjects.funders || fetchProjects.funders.length == 0" class="uk-text-muted uk-margin-top">
No reports available
</div>
</div>
</ng-template>
<!--Mobile actions-->
<fs-modal #AlertModalDeletedByInferenceFS *ngIf="organizationInfo && organizationInfo.deletedByInferenceIds" classTitle="uk-tile-default uk-border-bottom">
<organizationsDeletedByInference *ngIf="deleteByInferenceOpened"
[id]="organizationInfo.objIdentifier"
[ids]="organizationInfo.deletedByInferenceIds"
[type]="'organizations'" [prevPath]="prevPath">
</organizationsDeletedByInference>
</fs-modal>
<!-- Share -->
<fs-modal *ngIf="organizationInfo" #addThisFsModal classTitle="uk-tile-default uk-border-bottom" classBody="uk-flex uk-flex-center uk-flex-middle">
<addThis></addThis>
</fs-modal>
<fs-modal *ngIf="organizationInfo" #downloadReportsFsModal classTitle="uk-tile-default uk-border-bottom">
<ng-container *ngTemplateOutlet="downloadOptions"></ng-container>
</fs-modal>
<fs-modal #AlertFsModalApplyAll classTitle="uk-tile-default uk-border-bottom">
<div class="uk-margin-large-top">
<div class="uk-text-center">Do you wish to download a CSV file? Note that this process may take a while.</div>
<div class="uk-margin-medium-top uk-flex uk-flex-middle uk-flex-center">
<button class="uk-button uk-button-primary" (click)="confirmCloseApplyAll()">Yes</button>
<button class="uk-button uk-button-default uk-margin-left" (click)="alertFsApplyAll.cancel()">No</button>
</div>
</div>
</fs-modal>
<fs-modal #AlertFsModalCsvError classTitle="uk-tile-default uk-border-bottom">
<div class="uk-margin-large-top uk-text-center">There was an error in csv downloading. Please try again later.</div>
</fs-modal>
<fs-modal *ngIf="isMobile" #fsModal classTitle="uk-tile-default uk-border-bottom">
<div *ngIf="activeTab == 'projects'" class="landing-section landing-section-height-auto">
<projectsInModal [fetchProjects]="fetchProjects"
[organizationId]="organizationId" [properties]=properties [prevPath]="prevPath">
</projectsInModal>
</div>
<div *ngIf="activeTab == 'dataProviders' && fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0"
class="landing-section">
<search-tab [fetch]="fetchDataproviders" resultType="dataprovider"
[params]="getParamsForSearchLink()"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedDataProviders"
[properties]="properties" [isMobile]="true" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="activeTab == 'publications' && fetchPublications && fetchPublications.searchUtils.totalResults > 0"
class="landing-section">
<search-tab [fetch]="fetchPublications" resultType="publication"
[params]="getParamsForSearchLink('publications')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [isMobile]="true" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="activeTab == 'datasets' && fetchDatasets && fetchDatasets.searchUtils.totalResults > 0"
class="landing-section">
<search-tab [fetch]="fetchDatasets" resultType="dataset"
[params]="getParamsForSearchLink('datasets')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [isMobile]="true" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="activeTab == 'software' && fetchSoftware && fetchSoftware.searchUtils.totalResults > 0"
class="landing-section">
<search-tab [fetch]="fetchSoftware" resultType="software"
[params]="getParamsForSearchLink('software')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [isMobile]="true" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="activeTab == 'other' && fetchOrps && fetchOrps.searchUtils.totalResults > 0"
class="landing-section">
<search-tab [fetch]="fetchOrps" resultType="other"
[params]="getParamsForSearchLink('other')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [isMobile]="true" [prevPath]="prevPath">
</search-tab>
</div>
</fs-modal>

View File

@ -26,6 +26,8 @@ import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {OpenaireEntities} from '../../utils/properties/searchFields';
import {Option} from '../../sharedComponents/input/input.component';
import {LayoutService} from '../../dashboard/sharedComponents/sidebar/layout.service';
import {FullScreenModalComponent} from "../../utils/modal/full-screen-modal/full-screen-modal.component";
declare var ResizeObserver;
@ -71,17 +73,23 @@ export class OrganizationComponent {
// Active tab variable for responsiveness
public activeTab: string = "";
@ViewChild('downloadReportsModal') downloadReportsModal;
@ViewChild('fsModal') fsModal: FullScreenModalComponent;
@ViewChild('downloadReportsModal') downloadReportsModal;
@ViewChild('downloadReportsFsModal') downloadReportsFsModal: FullScreenModalComponent;
// @ViewChild('downloadReportModal') downloadReportModal;
// @ViewChild('downloadFunderReportModal') downloadFunderReportModal;
@ViewChild('addThisModal') addThisModal;
@ViewChild('addThisFsModal') addThisFsModal: FullScreenModalComponent;
@ViewChild(ModalLoading) loading: ModalLoading;
// Alert box when CSV: Project Publications for a funder is requested
@ViewChild('AlertModalApplyAll') alertApplyAll;
@ViewChild('AlertFsModalApplyAll') alertFsApplyAll;
// Alert box when something is wrong with CSV requests
@ViewChild('AlertModalCsvError') alertCsvError;
@ViewChild('AlertFsModalCsvError') alertFsCsvError;
public routerHelper: RouterHelper = new RouterHelper();
public errorCodes: ErrorCodes = new ErrorCodes();
@ -121,10 +129,13 @@ export class OrganizationComponent {
public feedbackFields: string [] = ['Name', 'Country', 'Other'];
@ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference;
@ViewChild('AlertModalDeletedByInferenceFS') alertModalDeletedByInferenceFS;
// @ViewChild('projectsModal') projectsModal;
public deleteByInferenceOpened: boolean = false;
public isMobile: boolean = false;
public mobileContent: "info" | "actions" = "info";
public viewAllMobile: string = "";
constructor(private element: ElementRef,
private _organizationService: OrganizationService,
@ -141,7 +152,8 @@ export class OrganizationComponent {
private seoService: SEOService,
private _location: Location,
private indexInfoService: IndexInfoService,
private cdr: ChangeDetectorRef) {
private cdr: ChangeDetectorRef,
private layoutService: LayoutService) {
this.fetchProjects = new FetchProjects(this._searchProjectsService);
this.fetchDataproviders = new FetchDataproviders(this._searchDataprovidersService);
this.fetchPublications = new FetchResearchResults(this._searchResearchResultsService);
@ -151,19 +163,21 @@ export class OrganizationComponent {
}
ngOnInit() {
this.properties = properties;
if (typeof document !== 'undefined') {
this.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(lastIndexUpdate => {
if (lastIndexUpdate) {
this.indexUpdateDate = new Date(lastIndexUpdate);
}
}));
}
//this.getDivContents();
this.getPageContents();
this.updateUrl(this.properties.domain + this.properties.baseLink + this._router.url);
this.seoService.createLinkForCanonicalURL(this.properties.domain +this.properties.baseLink + this._router.url);
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
}));
this.properties = properties;
if (typeof document !== 'undefined') {
this.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(lastIndexUpdate => {
if (lastIndexUpdate) {
this.indexUpdateDate = new Date(lastIndexUpdate);
}
}));
}
//this.getDivContents();
this.getPageContents();
this.updateUrl(this.properties.domain + this.properties.baseLink + this._router.url);
this.seoService.createLinkForCanonicalURL(this.properties.domain +this.properties.baseLink + this._router.url);
this.subscriptions.push(this.route.queryParams.subscribe(params => {
this.organizationInfo = null;
@ -266,7 +280,8 @@ export class OrganizationComponent {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
} else if (subscription instanceof (ResizeObserver || IntersectionObserver)) {
} else if ((typeof ResizeObserver != 'undefined' && subscription instanceof ResizeObserver) ||
(typeof IntersectionObserver != 'undefined' && subscription instanceof IntersectionObserver)) {
subscription.disconnect();
}
});
@ -628,13 +643,19 @@ export class OrganizationComponent {
}
public confirmOpenApplyAll(contentType: string, contentFileName: string) {
this.alertApplyAll.cancelButton = true;
this.alertApplyAll.okButton = true;
this.alertApplyAll.alertTitle = "CSV FILE";
this.alertApplyAll.message = "Do you wish to download a CSV file? Note that this process may take a while.";
this.alertApplyAll.okButtonText = "Yes";
this.alertApplyAll.cancelButtonText = "No";
this.alertApplyAll.open();
if(this.isMobile) {
this.alertFsApplyAll.title = "CSV FILE";
this.alertFsApplyAll.okButton = false;
this.alertFsApplyAll.open();
} else {
this.alertApplyAll.cancelButton = true;
this.alertApplyAll.okButton = true;
this.alertApplyAll.alertTitle = "CSV FILE";
this.alertApplyAll.message = "Do you wish to download a CSV file? Note that this process may take a while.";
this.alertApplyAll.okButtonText = "Yes";
this.alertApplyAll.cancelButtonText = "No";
this.alertApplyAll.open();
}
this.funderId = this.funder.id;
this.funderCount = this.funder.number;
this.funderContentType = contentType;
@ -646,12 +667,19 @@ export class OrganizationComponent {
}
public confirmOpenCsvError() {
this.alertCsvError.cancelButton = false;
this.alertCsvError.okButton = true;
this.alertCsvError.alertTitle = "ERROR DOWNLOADING CSV FILE";
this.alertCsvError.message = "There was an error in csv downloading. Please try again later.";
this.alertCsvError.okButtonText = "OK";
this.alertCsvError.open();
if(this.isMobile) {
this.alertFsCsvError.okButton = true;
this.alertFsCsvError.okButtonText = "OK";
this.alertFsCsvError.title = "ERROR DOWNLOADING CSV FILE";
this.alertFsCsvError.open();
} else {
this.alertCsvError.cancelButton = false;
this.alertCsvError.okButton = true;
this.alertCsvError.alertTitle = "ERROR DOWNLOADING CSV FILE";
this.alertCsvError.message = "There was an error in csv downloading. Please try again later.";
this.alertCsvError.okButtonText = "OK";
this.alertCsvError.open();
}
}
encodeURI(input: string): string {
@ -686,7 +714,7 @@ export class OrganizationComponent {
}
openDownloadReportsModal() {
this.funder = this.fetchProjects.funders[0];
// this.funder = this.fetchProjects.funders[0];
this.downloadReportsModal.cancelButton = false;
this.downloadReportsModal.okButton = false;
this.downloadReportsModal.alertTitle = "Download";
@ -808,7 +836,7 @@ export class OrganizationComponent {
for(let funder of this.fetchProjects.funders) {
this.funderOptions.push({"label": funder.name, "value": funder});
}
this.funder = this.funderOptions[0];
this.funder = this.funderOptions[0].value;
}
}
@ -816,11 +844,18 @@ export class OrganizationComponent {
HelperFunctions.scroll();
}
public openFsModal(fsModal: FullScreenModalComponent, title: string) {
fsModal.title = title;
fsModal.okButton = false;
fsModal.stayOpenInBack = true;
fsModal.open();
}
public get eoscBackLink() {
if(this.prevPath && this.referrer && ((this.referrer == "https://eosc-search-service.grid.cyfronet.pl/") || (this.referrer == "https://beta.search.marketplace.eosc-portal.eu/") || (this.referrer == "https://search.marketplace.eosc-portal.eu/"))) {
return this.referrer+this.prevPath;
if (this.prevPath && this.referrer && ((this.referrer == "https://eosc-search-service.grid.cyfronet.pl/") || (this.referrer == "https://beta.search.marketplace.eosc-portal.eu/") || (this.referrer == "https://search.marketplace.eosc-portal.eu/"))) {
return this.referrer + this.prevPath;
} else {
return "https://"+(this.properties.environment == "beta" ? "beta." : "")+"search.marketplace.eosc-portal.eu/";
return "https://" + (this.properties.environment == "beta" ? "beta." : "") + "search.marketplace.eosc-portal.eu/";
}
}
}

View File

@ -30,7 +30,10 @@ import {LoadingModule} from '../../utils/loading/loading.module';
import {IconsModule} from '../../utils/icons/icons.module';
import {InputModule} from '../../sharedComponents/input/input.module';
import {IconsService} from '../../utils/icons/icons.service';
import {graph} from "../../utils/icons/icons";
import {graph, versions} from "../../utils/icons/icons";
import {FullScreenModalModule} from "../../utils/modal/full-screen-modal/full-screen-modal.module";
import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.module";
import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.module";
@NgModule({
@ -48,7 +51,7 @@ import {graph} from "../../utils/icons/icons";
Schema2jsonldModule, SEOServiceModule, HelperModule,
OrganizationsDeletedByInferenceModule, LandingHeaderModule, FeedbackModule,
MatSelectModule,
TabsModule, SearchTabModule, LoadingModule, IconsModule, InputModule
TabsModule, SearchTabModule, LoadingModule, IconsModule, InputModule, FullScreenModalModule, EGIDataTransferModule, EntityActionsModule
],
declarations: [
OrganizationComponent,
@ -60,6 +63,6 @@ import {graph} from "../../utils/icons/icons";
})
export class OrganizationModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([graph]);
this.iconsService.registerIcons([graph, versions]);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
import {ChangeDetectorRef, Component, ElementRef, HostListener, Input, ViewChild} from '@angular/core';
import {ChangeDetectorRef, Component, ElementRef, Input, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser';
@ -25,10 +25,14 @@ import {StringUtils} from "../../utils/string-utils.class";
import {ResultPreview} from "../../utils/result-preview/result-preview";
import {SearchResult} from "../../utils/entities/searchResult";
import {IndexInfoService} from "../../utils/indexInfo.service";
import {Subscriber} from "rxjs";
import {Subscriber, Subscription, zip} from "rxjs";
import {properties} from "../../../../environments/environment";
import {Option} from "../../sharedComponents/input/input.component";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {MetricsService} from '../../services/metrics.service';
import {NumberUtils} from '../../utils/number-utils.class';
import {LayoutService} from '../../dashboard/sharedComponents/sidebar/layout.service';
import {FullScreenModalComponent} from '../../utils/modal/full-screen-modal/full-screen-modal.component';
declare var ResizeObserver;
@ -51,9 +55,13 @@ export class ProjectComponent {
public metricsClicked: boolean;
public viewsFrameUrl: string;
public downloadsFrameUrl: string;
public totalViews: number;
public totalDownloads: number;
public pageViews: number;
/** @deprecated*/
public totalViews: number = null;
/** @deprecated*/
public totalDownloads: number = null;
public hasViews: boolean = false;
public hasDownloads: boolean = false;
// public pageViews: number;
// Statistics tab variables
public statsClicked: boolean;
@ -86,8 +94,11 @@ export class ProjectComponent {
// @ViewChild('statisticsModal') statisticsModal;
// @ViewChild('linkProjectModal') linkProjectModal;
@ViewChild('embedResultsModal') embedResultsModal;
@ViewChild('embedResultsFsModal') embedResultsFsModal: FullScreenModalComponent;
@ViewChild('downloadReportModal') downloadReportModal;
@ViewChild('addThisModal') addThisModal
@ViewChild('downloadReportFsModal') downloadReportFsModal: FullScreenModalComponent;
@ViewChild('addThisModal') addThisModal;
@ViewChild('addThisFsModal') addThisFsModal: FullScreenModalComponent;
// Request results for publications, research data and software only the one time (first time tab is clicked)
private reloadPublications: boolean = true;
@ -163,9 +174,23 @@ export class ProjectComponent {
// public shouldSticky: boolean = true;
subscriptions = [];
private sub: Subscription;
properties: EnvProperties;
public openaireEntities = OpenaireEntities;
public isMobile: boolean = false;
public mobileContent: "info" | "metrics" | "actions" = "info";
public tabMobile: string = "";
public viewAllMobile: string = "";
// Full screen modals for small screens (mobile)
@ViewChild('summaryFsModal') summaryFsModal: FullScreenModalComponent;
@ViewChild('publicationsFsModal') publicationsFsModal: FullScreenModalComponent;
@ViewChild('datasetsFsModal') datasetsFsModal: FullScreenModalComponent;
@ViewChild('softwareFsModal') softwareFsModal: FullScreenModalComponent;
@ViewChild('otherFsModal') otherFsModal: FullScreenModalComponent;
@ViewChild('dmpsFsModal') dmpsFsModal: FullScreenModalComponent;
@ViewChild('statisticsFsModal') statisticsFsModal: FullScreenModalComponent;
constructor(private route: ActivatedRoute,
private _router: Router,
private _location: Location,
@ -179,24 +204,26 @@ export class ProjectComponent {
private _reportsService: ReportsService,
private htmlService: HtmlProjectReportService,
private indexInfoService: IndexInfoService,
private cdr: ChangeDetectorRef) {}
private metricsService: MetricsService,
private cdr: ChangeDetectorRef,
private layoutService: LayoutService) {}
ngOnInit() {
this.properties = properties;
if (typeof document !== 'undefined') {
this.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(lastIndexUpdate => {
if (lastIndexUpdate) {
this.indexUpdateDate = new Date(lastIndexUpdate);
}
}));
}
//this.getDivContents();
this.getPageContents();
this.updateUrl(this.properties.domain + this.properties.baseLink + this._router.url);
this.seoService.createLinkForCanonicalURL(this.properties.domain +this.properties.baseLink + this._router.url);
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
}));
this.properties = properties;
if (typeof document !== 'undefined') {
this.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(lastIndexUpdate => {
if (lastIndexUpdate) {
this.indexUpdateDate = new Date(lastIndexUpdate);
}
}));
}
//this.getDivContents();
this.getPageContents();
this.updateUrl(this.properties.domain + this.properties.baseLink + this._router.url);
this.seoService.createLinkForCanonicalURL(this.properties.domain +this.properties.baseLink + this._router.url);
this.subscriptions.push(this.route.queryParams.subscribe(params => {
this.stickyHeader = false;
this.metricsClicked = false;
@ -353,7 +380,8 @@ export class ProjectComponent {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
} else if (subscription instanceof (ResizeObserver || IntersectionObserver)) {
} else if ((typeof ResizeObserver != 'undefined' && subscription instanceof ResizeObserver) ||
(typeof IntersectionObserver != 'undefined' && subscription instanceof IntersectionObserver)) {
subscription.disconnect();
}
});
@ -510,6 +538,23 @@ export class ProjectComponent {
startDate: this.projectInfo.startDate,
endDate: this.projectInfo.endDate
};
this.hasViews = false;
this.hasDownloads = false;
// ensure that if the API call to index does not have metrics, we get them from old metrics service call
if(this.projectInfo && !this.projectInfo.measure) {
this.getMetrics();
} else if(this.projectInfo && this.projectInfo.measure && this.projectInfo.measure.counts) {
this.projectInfo.measure.counts.forEach(measure => {
if(measure.name == "views" && measure.value > 0) {
this.hasViews = true;
}
if(measure.name == "downloads" && measure.value > 0) {
this.hasDownloads = true;
}
})
}
//old
// this.viewsFrameUrl = this.properties.framesAPIURL + 'merge.php?com=query&data=[{"query":"projRepoViews","projTitle":"' + this.projectId + '","table":"","fields":[{"fld":"sum","agg":"sum","type":"column","yaxis":1,"c":false}],"xaxis":{"name":"month","agg":"sum"},"group":"","color":"","type":"chart","size":200,"sort":"xaxis","xStyle":{"r":-30,"s":"6","l":"-","ft":"-","wt":"-"},"title":"","subtitle":"","xaxistitle":"","yaxisheaders":["Monthly views"],"generalxaxis":"","theme":0,"in":[]}]&info_types=["column"]&stacking=&steps=false&fontFamily=Courier&spacing=[5,0,0,0]&style=[{"color":"rgba(0, 0, 0, 1)","size":"18"},{"color":"rgba(0, 0, 0, 1)","size":"18"},{"color":"000000","size":""},{"color":"000000","size":""}]&backgroundColor=rgba(255,255,255,1)&colors[]=rgba(124, 181, 236, 1)&colors[]=rgba(67, 67, 72, 1)&colors[]=rgba(144, 237, 125, 1)&colors[]=rgba(247, 163, 92, 1)&colors[]=rgba(128, 133, 233, 1)&colors[]=rgba(241, 92, 128, 1)&colors[]=rgba(228, 211, 84, 1)&colors[]=rgba(43, 144, 143, 1)&colors[]=rgba(244, 91, 91, 1)&colors[]=rgba(145, 232, 225, 1)&xlinew=0&ylinew=1&legends=true&tooltips=true&persistent=false';
//
@ -567,11 +612,35 @@ export class ProjectComponent {
public metricsResults($event) {
this.totalViews = $event.totalViews;
this.totalDownloads = $event.totalDownloads;
this.pageViews = $event.pageViews;
// this.pageViews = $event.pageViews;
}
private getMetrics() {
let obs;
obs = zip(this.metricsService.getMetricsNumber(this.projectId, "usagestats.projects.views", this.properties),
this.metricsService.getMetricsNumber(this.projectId, "usagestats.projects.downloads", this.properties));
this.sub = obs.subscribe(data => {
if((data[0] && data[0] > 0) || (data[1] && data[1] > 0)) {
this.projectInfo.measure = {counts: []};
if(data[0] && data[0] > 0) {
this.projectInfo.measure.counts.push({name: 'views', order: 0, icon: 'visibility', value: data[0]});
this.hasViews = true;
}
if(data[1] && data[1] > 0) {
this.projectInfo.measure.counts.push({name: 'downloads', order: 1, icon: 'downloads', value: data[1]});
this.hasDownloads = true;
}
this.cdr.detectChanges();
}
// this.totalViews = data[0];
// this.totalDownloads = data[1];
});
}
public get hasMetrics(): boolean {
return !(this.totalViews != null && this.totalDownloads != null && this.pageViews != null) || this.totalViews > 0 || this.totalDownloads > 0||this.pageViews > 0;
// return !(this.totalViews != null && this.totalDownloads != null) || this.totalViews > 0 || this.totalDownloads > 0;
return this.projectInfo.measure?.counts?.length > 0;
}
public viewAllOrganizationsClick() {
@ -583,6 +652,13 @@ export class ProjectComponent {
}
}
public viewAllOrganizationsMobileClicked() {
this.summaryFsModal.title += " - Partners";
this.summaryFsModal.back = true;
this.lessBtnOrganizations = true;
this.viewAllMobile = "organizations";
}
public openOrganizationsModal() {
this.organizationsModal.cancelButton = false;
this.organizationsModal.okButton = false;
@ -971,12 +1047,56 @@ export class ProjectComponent {
];
}
public viewAllDescriptionClicked() {
if(this.isMobile) {
this.summaryFsModal.title += " - Description";
this.summaryFsModal.back = true;
this.viewAllMobile = "description";
} else {
this.openDescriptionModal();
}
}
public openDescriptionModal() {
this.descriptionModal.alertFooter = false;
this.descriptionModal.alertTitle = "Description";
this.descriptionModal.open();
}
public clickedUsageMetrics() {
setTimeout( () => {
this.metricsClicked = true;
});
}
public formatNumber(num: number | string) {
let formatted = NumberUtils.roundNumber(+num);
return formatted.number + formatted.size;
}
public cancelSummaryClicked() {
this.summaryFsModal.title = "Summary";
this.summaryFsModal.back = false;
this.lessBtnOrganizations = false;
this.viewAllMobile = "";
}
public openFsModal(fsModal: FullScreenModalComponent, title: string) {
fsModal.title = title;
fsModal.okButton = false;
fsModal.stayOpenInBack = true;
fsModal.open();
this.tabMobile = title;
}
public getMetricsTooltip(value: string) {
if (value == 'downloads') {
return "<div class='uk-flex uk-flex-middle'><a href='https://usagecounts.openaire.eu/' target='_blank'><img src='assets/common-assets/logo-small-usage-counts.png' loading='lazy' alt='OpenAIRE UsageCounts'></a><span class='uk-text-uppercase uk-margin-small-left'>Downloads provided by <a href='https://usagecounts.openaire.eu/' target='_blank' class='uk-link-reset'><strong>UsageCounts</strong></a></div>";
} else if (value == 'views') {
return "<div class='uk-flex uk-flex-middle'><a href='https://usagecounts.openaire.eu/' target='_blank'><img class='uk-margin-small-right' src='assets/common-assets/logo-small-usage-counts.png' loading='lazy' alt='OpenAIRE UsageCounts'></a><span class='uk-text-uppercase uk-margin-small-left'>Views provided by <a href='https://usagecounts.openaire.eu/' target='_blank' class='uk-link-reset'><strong>UsageCounts</strong></a></div>";
}
}
public addEoscPrevInParams(obj) {
if(properties.adminToolsPortalType == "eosc" && this.prevPath) {
let splitted: string[] = this.prevPath.split("?");

View File

@ -3,7 +3,7 @@ import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {RouterModule} from '@angular/router';
import { MatSelectModule } from "@angular/material/select";
import {MatSelectModule} from "@angular/material/select";
import {ProjectComponent} from './project.component';
import {ProjectServiceModule} from './projectService.module';
@ -31,7 +31,11 @@ import {LoadingModule} from "../../utils/loading/loading.module";
import {IconsModule} from "../../utils/icons/icons.module";
import {InputModule} from "../../sharedComponents/input/input.module";
import {IconsService} from "../../utils/icons/icons.service";
import {graph, link} from "../../utils/icons/icons";
import {graph, link, link_to, open_access} from "../../utils/icons/icons";
import {FullScreenModalModule} from '../../utils/modal/full-screen-modal/full-screen-modal.module';
import {SafeHtmlPipeModule} from '../../utils/pipes/safeHTMLPipe.module';
import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.module";
import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.module";
@NgModule({
imports: [
@ -41,7 +45,8 @@ import {graph, link} from "../../utils/icons/icons";
SearchResearchResultsServiceModule, ProjectServiceModule,
Schema2jsonldModule, SEOServiceModule, HelperModule,
LandingHeaderModule, MatSelectModule, FeedbackModule, AltMetricsModule,
TabsModule, SearchTabModule, LoadingModule, IconsModule, InputModule
TabsModule, SearchTabModule, LoadingModule, IconsModule, InputModule,
FullScreenModalModule, SafeHtmlPipeModule, EGIDataTransferModule, EntityActionsModule
],
declarations: [
ProjectComponent
@ -55,6 +60,6 @@ import {graph, link} from "../../utils/icons/icons";
})
export class ProjectModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([link, graph])
this.iconsService.registerIcons([link, graph, link_to, open_access])
}
}

View File

@ -236,6 +236,10 @@ export class ProjectService {
this.projectInfo.urlInfo = "Detailed project information (CORDIS)";
}
if (data[0]?.measure) {
this.projectInfo.measure = this.parsingFunctions.parseMeasures(data[0].measure);
}
return this.projectInfo;
}

View File

@ -24,10 +24,11 @@ import {HelperFunctions} from "../../../utils/HelperFunctions.class";
[page]="page" [pageSize]="pageSize"
[totalResults]="results.length">
</no-load-paging>
<ul class="uk-list uk-list-divider uk-margin">
<ul class="uk-list uk-margin">
<li *ngFor="let result of results.slice((page-1)*pageSize, page*pageSize)">
<result-preview [modal]="modal" [properties]="properties" [hasLink]="false" [result]="getResultPreview(result)"
[showOrcid]="false" [isCard]="false" [prevPath]="prevPath"></result-preview>
[showOrcid]="false" [isCard]="false" [prevPath]="prevPath" [showInline]="true"
[isDeletedByInferenceModal]="true"></result-preview>
</li>
</ul>
<no-load-paging *ngIf="results.length > pageSize" [type]="type"

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
import {ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, Input, Output, ViewChild} from '@angular/core';
import {ChangeDetectorRef, Component, ElementRef, Input, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser';
@ -18,13 +18,16 @@ import {IndexInfoService} from "../../utils/indexInfo.service";
import {Identifier, StringUtils} from "../../utils/string-utils.class";
import {properties} from "../../../../environments/environment";
import {ISVocabulariesService} from "../../utils/staticAutoComplete/ISVocabularies.service";
import {forkJoin, Observable, Subscription, zip} from "rxjs";
import {AnnotationComponent} from "../annotation/annotation.component";
import {Subscription} from "rxjs";
import {ParsingFunctions} from "../landing-utils/parsingFunctions.class";
import {ConnectHelper} from "../../connect/connectHelper";
import {UserManagementService} from "../../services/user-management.service";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {Option} from "../../sharedComponents/input/input.component";
import {NumberUtils} from '../../utils/number-utils.class';
import {FullScreenModalComponent} from "../../utils/modal/full-screen-modal/full-screen-modal.component";
import {SdgFosSuggestComponent} from '../landing-utils/sdg-fos-suggest/sdg-fos-suggest.component';
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
declare var ResizeObserver;
@ -42,8 +45,11 @@ export class ResultLandingComponent {
enermapsId;
// @ViewChild('linkModal') linkModal;
@ViewChild('citeModal') citeModal;
@ViewChild('citeFsModal') citeFsModal;
@ViewChild('addThisModal') addThisModal;
@ViewChild('addThisFsModal') addThisFsModal;
@ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference;
@ViewChild('AlertModalDeletedByInferenceFS') alertModalDeletedByInferenceFS;
// @ViewChild('relationModal') relationModal;
public deleteByInferenceOpened: boolean = false;
@Input() public resultFromInput: boolean = false;
@ -72,9 +78,14 @@ export class ResultLandingComponent {
public hasAltMetrics: boolean = false;
public viewsFrameUrl: string;
public downloadsFrameUrl: string;
/** @deprecated*/
public totalViews: number = null;
/** @deprecated*/
public totalDownloads: number = null;
public hasViews: boolean = false;
public hasDownloads: boolean = false;
public pageViews: number = null;
public bipFrameUrl: string;
// Custom tab paging variables
public referencesPage: number = 1;
@ -114,7 +125,7 @@ export class ResultLandingComponent {
'Title', 'Authors', 'Access rights',
'Publisher information', 'Funding Information',
'Persistent identifiers', 'Sustainable Development Goals (SDGs)',
'Fields of Science and Technology (FOS)', 'Other'];
'Fields of Science (FoS)', 'Other'];
public pidsArrayString: string = "";
public identifier: Identifier;
@ -142,7 +153,26 @@ export class ResultLandingComponent {
// public shouldSticky: boolean = true;
public mobileContent: "info" | "metrics" | "actions" = "info";
public tabMobile: string = "";
public viewAllMobile: string = "";
public viewAll: string = "";
@ViewChild("sdgFosSuggest") sdgFosSuggest: SdgFosSuggestComponent;
public isMobile: boolean = false;
// Full screen modals for small screens (mobile)
@ViewChild('summaryFsModal') summaryFsModal: FullScreenModalComponent;
@ViewChild('subjectsFsModal') subjectsFsModal: FullScreenModalComponent;
@ViewChild('referencesFsModal') referencesFsModal: FullScreenModalComponent;
@ViewChild('relatedResearchFsModal') relatedResearchFsModal: FullScreenModalComponent;
@ViewChild('bioentitiesFsModal') bioentitiesFsModal: FullScreenModalComponent;
@ViewChild('compatibleEOSCFsModal') compatibleEOSCFsModal: FullScreenModalComponent;
@ViewChild('fundedByFsModal') fundedByFsModal: FullScreenModalComponent;
@ViewChild('relatedCommunitiesFsModal') relatedCommunitiesFsModal: FullScreenModalComponent;
@ViewChild('enermapsToolFsModal') enermapsToolFsModal: FullScreenModalComponent;
@ViewChild('sdgsFsModal') sdgsFsModal: FullScreenModalComponent;
@ViewChild('fosFsModal') fosFsModal: FullScreenModalComponent;
public noCommunities: boolean = false;
public rightSidebarOffcanvasClicked: boolean = false;
@ -161,10 +191,14 @@ export class ResultLandingComponent {
private cdr: ChangeDetectorRef,
private _location: Location,
private indexInfoService: IndexInfoService,
private userManagementService: UserManagementService) {
private userManagementService: UserManagementService,
private layoutService: LayoutService) {
}
ngOnInit() {
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
}));
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
this.isLoggedIn = !!user;
}, error => { this.isLoggedIn = false} ));
@ -347,7 +381,8 @@ export class ResultLandingComponent {
subscription.unsubscribe();
} else if (subscription instanceof Function) {
subscription();
} else if (subscription instanceof (ResizeObserver || IntersectionObserver)) {
} else if ((typeof ResizeObserver != 'undefined' && subscription instanceof ResizeObserver) ||
(typeof IntersectionObserver != 'undefined' && subscription instanceof IntersectionObserver)) {
subscription.disconnect();
}
});
@ -470,6 +505,7 @@ export class ResultLandingComponent {
this.viewsFrameUrl = this.properties.statisticsFrameNewAPIURL + 'chart?json=' + encodeURIComponent('{"library":"HighCharts","chartDescription":{"queries":[{"name":"Monthly views","type":"column","query":{"name":"usagestats.results.views.monthly", "parameters":["' + this.id + '"], "profile":"OpenAIRE All-inclusive" }}],"chart":{"backgroundColor":"#FFFFFFFF","borderColor":"#335cadff","borderRadius":0,"borderWidth":0,"plotBorderColor":"#ccccccff","plotBorderWidth":0},"title":{"text":"Monthly views"},"subtitle":{},"yAxis":{"title":{"text":""}},"xAxis":{"title":{}},"lang":{"noData":"No Data available for the Query"},"exporting":{"enabled":false},"plotOptions":{"series":{"dataLabels":{"enabled":false}}},"legend":{"enabled":false},"credits":{"href":null,"enabled":true,"text":""}}}');
this.downloadsFrameUrl = this.properties.statisticsFrameNewAPIURL + 'chart?json=' +
encodeURIComponent('{"library":"HighCharts","chartDescription":{"queries":[{"name":"Monthly downloads","type":"column","query":{"name":"usagestats.results.downloads.monthly", "parameters":["' + this.id + '"], "profile":"OpenAIRE All-inclusive" }}],"chart":{"backgroundColor":"#FFFFFFFF","borderColor":"#335cadff","borderRadius":0,"borderWidth":0,"plotBorderColor":"#ccccccff","plotBorderWidth":0},"title":{"text":"Monthly downloads"},"subtitle":{},"yAxis":{"title":{"text":""}},"xAxis":{"title":{}},"lang":{"noData":"No Data available for the Query"},"exporting":{"enabled":false},"plotOptions":{"series":{"dataLabels":{"enabled":false}}},"legend":{"enabled":false},"credits":{"href":null,"enabled":true,"text":""}}}');
this.bipFrameUrl = this.properties.bipFrameAPIURL + this.id + (properties.environment == "beta" ? "&src=beta" : "");
let pid:Identifier = Identifier.getPIDFromIdentifiers(this.resultLandingInfo.identifiers);
if (this.type == "result") { // no type was specified - update URL based this.resultLandingInfo.resultType
this.updateUrlWithType(pid);
@ -515,7 +551,7 @@ export class ResultLandingComponent {
this.enermapsId = ParsingFunctions.getEnermapsConceptId(this.resultLandingInfo.contexts);
}
this.relatedClassFilters = [{"label": "All relations", "value": ""}];
if(this.resultLandingInfo.relatedClassFilters.size > 1) {
for (let relClass of this.resultLandingInfo.relatedClassFilters) {
this.relatedClassFilters.push({"label": HelperFunctions.getVocabularyLabel(relClass, this.relationsVocabulary), "value": relClass});
@ -526,6 +562,19 @@ export class ResultLandingComponent {
this.relatedClassSelected = "";
this.filteredRelatedResults = this.resultLandingInfo.relatedResults;
this.hasViews = false;
this.hasDownloads = false;
if(this.resultLandingInfo.measure && this.resultLandingInfo.measure.counts) {
this.resultLandingInfo.measure.counts.forEach(measure => {
if(measure.name == "views" && measure.value > 0) {
this.hasViews = true;
}
if(measure.name == "downloads" && measure.value > 0) {
this.hasDownloads = true;
}
})
}
this.showLoading = false;
this.setActiveTab();
@ -555,14 +604,12 @@ export class ResultLandingComponent {
public get hasPrimaryInfo(): boolean {
return !!this.resultLandingInfo && (
(!!this.resultLandingInfo.description && this.resultLandingInfo.description.length > 0)
|| !!this.resultLandingInfo.subjects
|| (this.resultLandingInfo.classifiedSubjects && this.resultLandingInfo.classifiedSubjects.size > 0)
|| (!!this.resultLandingInfo.organizations && this.resultLandingInfo.organizations.length > 0));
}
public get hasRightSidebarInfo(): boolean {
return (this.resultLandingInfo.eoscSubjects && this.resultLandingInfo.eoscSubjects.length
&& (properties.adminToolsPortalType == 'explore' || properties.adminToolsPortalType == 'eosc'))
&& properties.adminToolsPortalType == 'eosc')
||
(this.resultLandingInfo.sdg && this.resultLandingInfo.sdg.length > 0)
||
@ -571,8 +618,10 @@ export class ResultLandingComponent {
(this.resultLandingInfo.fundedByProjects && this.resultLandingInfo.fundedByProjects.length > 0)
||
(this.resultLandingInfo.contexts && this.resultLandingInfo.contexts.length > 0 && !this.noCommunities)
||
(this.resultLandingInfo.hostedBy_collectedFrom && this.resultLandingInfo.hostedBy_collectedFrom.length > 0);
||
(this.resultLandingInfo.measure && Object.keys(this.resultLandingInfo.measure).length > 0);
// ||
// (this.resultLandingInfo.hostedBy_collectedFrom && this.resultLandingInfo.hostedBy_collectedFrom.length > 0);
}
public get metricsCalculated(): boolean {
@ -903,6 +952,32 @@ export class ResultLandingComponent {
}
}
public viewAllSubjectsMobileClicked(event) {
this.subjectsFsModal.title += " - "+event['subtitle'];
this.subjectsFsModal.back = true;
this.viewAllMobile = event['id'];
}
public viewAllOrganizationsMobileClicked() {
this.summaryFsModal.title += " - Related "+this.openaireEntities.ORGANIZATIONS;
this.summaryFsModal.back = true;
this.lessBtnOrganizations = true;
this.viewAllMobile = "organizations";
}
public cancelSummaryClicked() {
this.summaryFsModal.title = "Summary";
this.summaryFsModal.back = false;
this.lessBtnOrganizations = false;
this.viewAllMobile = "";
}
public cancelSubjectsClicked() {
this.subjectsFsModal.title = "Subjects";
this.subjectsFsModal.back = false;
this.viewAllMobile = "";
}
public openOrganizationsModal() {
this.organizationsModal.cancelButton = false;
this.organizationsModal.okButton = false;
@ -917,12 +992,145 @@ export class ResultLandingComponent {
this.viewAll = "";
}
public sdgsFsModalCancelled() {
if(this.viewAllMobile == "sdg") {
this.viewAllMobile = "";
} else {
this.viewAllMobile = "sdg";
}
}
public fosFsModalCancelled() {
if(this.viewAllMobile == "fos") {
this.viewAllMobile = "";
} else {
this.viewAllMobile = "fos";
}
}
public suggestMobileClicked(value: string) {
if(this.viewAllMobile == 'sdg' || this.viewAllMobile == 'fos') {
this.sdgsFsModal.title += " - Suggest";
this.sdgsFsModal.back = true;
this.sdgFosSuggest.subjects=this.resultLandingInfo.sdg;
this.sdgFosSuggest.subjectType="sdg";
this.viewAllMobile = "sdgSuggest";
}
if(value == 'sdg') {
this.sdgFosSuggest.subjects=this.resultLandingInfo.sdg;
this.sdgFosSuggest.subjectType="sdg";
} else if(value == 'fos') {
this.sdgFosSuggest.subjects=this.resultLandingInfo.fos;
this.sdgFosSuggest.subjectType="fos";
}
}
public suggestClicked(value: string) {
if(value == 'sdg') {
this.sdgFosSuggest.subjects=this.resultLandingInfo.sdg;
this.sdgFosSuggest.subjectType="sdg";
} else if(value == 'fos') {
this.sdgFosSuggest.subjects=this.resultLandingInfo.fos;
this.sdgFosSuggest.subjectType="fos";
}
this.cdr.detectChanges();
this.sdgFosSuggest.openSelectionModal();
}
public viewAllDescriptionClicked() {
if(this.isMobile) {
this.summaryFsModal.title += " - Abstract";
this.summaryFsModal.back = true;
this.viewAllMobile = "description";
} else {
this.openDescriptionModal();
}
}
public openDescriptionModal() {
this.descriptionModal.alertFooter = false;
this.descriptionModal.alertTitle = "Abstract";
this.descriptionModal.open();
}
public clickedUsageMetrics() {
setTimeout( () => {
this.metricsClicked = true;
});
}
public formatNumber(num: number | string) {
let formatted = NumberUtils.roundNumber(+num);
return formatted.number + formatted.size;
}
// private openSdgSelectionModal() {
// this.sdgSelectionModal.cancelButton = false;
// this.sdgSelectionModal.alertTitle = "Please select SDGs that are the most relevant for this publication.";
// this.sdgSelectionModal.okButtonText = "Next";
// this.sdgSelectionModal.stayOpen = true;
// this.sdgSelectionModal.open();
// }
public openFsModal(fsModal: FullScreenModalComponent, title: string) {
fsModal.title = title;
fsModal.okButton = false;
fsModal.stayOpenInBack = true;
fsModal.open();
this.tabMobile = title;
}
/*private openFosSelectionModal() {
this.fosSelectionModal.cancelButton = false;
this.fosSelectionModal.alertTitle = "Please select FOS that are the most relevant for this publication.";
this.fosSelectionModal.open();
}
public sdgModalOutput() {
this.sdgFosSuggest.sdgModalOutput();
}*/
public closeFsModal(fsModal: FullScreenModalComponent) {
fsModal.cancel();
}
public getMetricsTooltip(value: string, compact: boolean) {
if (compact) {
if (value == 'citations') {
return "<div>This is an alternative to the \"Influence\" indicator, which also reflects the overall/total impact of an article in the research community at large, based on the underlying citation network (diachronically).</div>";
} else if (value == 'popularity') {
return "<div>This indicator reflects the \"current\" impact/attention (the \"hype\") of an article in the research community at large, based on the underlying citation network.</div>";
} else if (value == 'influence') {
return "<div>This indicator reflects the overall/total impact of an article in the research community at large, based on the underlying citation network (diachronically).</div>";
} else if (value == 'impulse') {
return "<div>This indicator reflects the initial momentum of an article directly after its publication, based on the underlying citation network.</div>";
}
} else {
if (value == 'citations') {
return "<div>This is an alternative to the \"Influence\" indicator, which also reflects the overall/total impact of an article in the research community at large, based on the underlying citation network (diachronically).</div><div class='uk-flex uk-margin-top'><a href='https://bip.imsi.athenarc.gr/' target='_blank'><img class='uk-margin-small-right' src='assets/common-assets/bip-minimal.svg' loading='lazy' alt='BIP!' style='width: 40px;'></a><span class='uk-text-uppercase'>Citations provided by <a href='https://bip.imsi.athenarc.gr/' target='_blank' class='uk-link-reset'><strong>BIP!</strong></a></div>";
} else if (value == 'popularity') {
return "<div>This indicator reflects the \"current\" impact/attention (the \"hype\") of an article in the research community at large, based on the underlying citation network.</div><div class='uk-flex uk-margin-top'><a href='https://bip.imsi.athenarc.gr/' target='_blank'><img class='uk-margin-small-right' src='assets/common-assets/bip-minimal.svg' loading='lazy' alt='BIP!' style='width: 40px;'></a><span class='uk-text-uppercase'>Popularity provided by <a href='https://bip.imsi.athenarc.gr/' target='_blank' class='uk-link-reset'><strong>BIP!</strong></a></div>";
} else if (value == 'influence') {
return "<div>This indicator reflects the overall/total impact of an article in the research community at large, based on the underlying citation network (diachronically).</div><div class='uk-flex uk-margin-top'><a href='https://bip.imsi.athenarc.gr/' target='_blank'><img class='uk-margin-small-right' src='assets/common-assets/bip-minimal.svg' loading='lazy' alt='BIP!' style='width: 40px;'></a><span class='uk-text-uppercase'>Influence provided by <a href='https://bip.imsi.athenarc.gr/' target='_blank' class='uk-link-reset'><strong>BIP!</strong></a></div>";
} else if (value == 'impulse') {
return "<div>This indicator reflects the initial momentum of an article directly after its publication, based on the underlying citation network.</div><div class='uk-flex uk-margin-top'><a href='https://bip.imsi.athenarc.gr/' target='_blank'><img class='uk-margin-small-right' src='assets/common-assets/bip-minimal.svg' loading='lazy' alt='BIP!' style='width: 40px;'></a><span class='uk-text-uppercase'>Impulse provided by <a href='https://bip.imsi.athenarc.gr/' target='_blank' class='uk-link-reset'><strong>BIP!</strong></a></div>";
} else if (value == 'downloads') {
return "<div class='uk-flex uk-flex-middle'><a href='https://usagecounts.openaire.eu/' target='_blank'><img src='assets/common-assets/logo-small-usage-counts.png' loading='lazy' alt='OpenAIRE UsageCounts'></a><span class='uk-text-uppercase uk-margin-small-left'>Downloads provided by <a href='https://usagecounts.openaire.eu/' target='_blank' class='uk-link-reset'><strong>UsageCounts</strong></a></div>";
} else if (value == 'views') {
return "<div class='uk-flex uk-flex-middle'><a href='https://usagecounts.openaire.eu/' target='_blank'><img src='assets/common-assets/logo-small-usage-counts.png' loading='lazy' alt='OpenAIRE UsageCounts'></a><span class='uk-text-uppercase uk-margin-small-left'>Views provided by <a href='https://usagecounts.openaire.eu/' target='_blank' class='uk-link-reset'><strong>UsageCounts</strong></a></div>";
}
}
}
public isNumber(value): boolean {
return typeof value === 'number';
}
public getAccessLabel(accessRight) : string {
if (accessRight) {
return (accessRight + (accessRight.toLowerCase().endsWith(" access") ? "" : " access"));
}
return "Not available access";
}
public getEoscParams() {
let params = "";
if(this.prevPath) {
@ -953,5 +1161,4 @@ export class ResultLandingComponent {
return "https://"+(this.properties.environment == "beta" ? "beta." : "")+"search.marketplace.eosc-portal.eu/";
}
}
}

View File

@ -1,26 +1,26 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {RouterModule} from '@angular/router';
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {RouterModule} from '@angular/router';
import {SharedModule} from '../../../openaireLibrary/shared/shared.module';
import {MetricsModule} from '../landing-utils/metrics/metrics.module';
import {LandingModule} from '../landing-utils/landing.module';
import {CiteThisModule} from '../landing-utils/citeThis/citeThis.module';
import {IFrameModule} from '../../utils/iframe.module';
import {AltMetricsModule} from '../../utils/altmetrics.module';
import {PagingModule} from '../../utils/paging.module';
import {SharedModule} from '../../../openaireLibrary/shared/shared.module';
import {MetricsModule} from '../landing-utils/metrics/metrics.module';
import {LandingModule} from '../landing-utils/landing.module';
import {CiteThisModule} from '../landing-utils/citeThis/citeThis.module';
import {IFrameModule} from '../../utils/iframe.module';
import {AltMetricsModule} from '../../utils/altmetrics.module';
import {PagingModule} from '../../utils/paging.module';
import {ResultLandingService} from './resultLanding.service';
import {ResultLandingComponent} from './resultLanding.component';
import {Schema2jsonldModule} from '../../sharedComponents/schema2jsonld/schema2jsonld.module';
import { SEOServiceModule } from '../../sharedComponents/SEO/SEOService.module';
import {ResultLandingService} from './resultLanding.service';
import {ResultLandingComponent} from './resultLanding.component';
import {Schema2jsonldModule} from '../../sharedComponents/schema2jsonld/schema2jsonld.module';
import {SEOServiceModule} from '../../sharedComponents/SEO/SEOService.module';
import {DeletedByInferenceModule} from './deletedByInference/deletedByInference.module';
import {ShowAuthorsModule} from "../../utils/authors/showAuthors.module";
import {HelperModule} from "../../utils/helper/helper.module";
import {ResultLandingUtilsModule} from "../landing-utils/resultLandingUtils.module";
import {AlertModalModule} from "../../utils/modal/alertModal.module";
import {DeletedByInferenceModule} from './deletedByInference/deletedByInference.module';
import {ShowAuthorsModule} from "../../utils/authors/showAuthors.module";
import {HelperModule} from "../../utils/helper/helper.module";
import {ResultLandingUtilsModule} from "../landing-utils/resultLandingUtils.module";
import {AlertModalModule} from "../../utils/modal/alertModal.module";
import {AnnotationModule} from "../annotation/annotation.module";
import {LandingHeaderModule} from "../landing-utils/landing-header/landing-header.module";
import {NoLoadPaging} from "../../searchPages/searchUtils/no-load-paging.module";
@ -33,9 +33,14 @@ import {MatFormFieldModule} from "@angular/material/form-field";
import {MatSelectModule} from "@angular/material/select";
import {IconsModule} from "../../utils/icons/icons.module";
import {IconsService} from "../../utils/icons/icons.service";
import {graph, link, quotes} from "../../utils/icons/icons";
import {cite, fire, graph, landmark, link, link_to, quotes, rocket, versions} from "../../utils/icons/icons";
import {InputModule} from "../../sharedComponents/input/input.module";
import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.module";
import {RecaptchaModule} from 'ng-recaptcha';
import {SdgFosSuggestModule} from '../landing-utils/sdg-fos-suggest/sdg-fos-suggest.module';
import {FullScreenModalModule} from "../../utils/modal/full-screen-modal/full-screen-modal.module";
import {SafeHtmlPipeModule} from '../../utils/pipes/safeHTMLPipe.module';
import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.module";
@NgModule({
imports: [
@ -44,7 +49,8 @@ import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.modul
MetricsModule, AltMetricsModule, Schema2jsonldModule, SEOServiceModule,
DeletedByInferenceModule, ShowAuthorsModule, HelperModule, ResultLandingUtilsModule, AlertModalModule,
AnnotationModule, LandingHeaderModule, NoLoadPaging, ResultPreviewModule, FeedbackModule, TabsModule, LoadingModule,
OrcidModule, MatFormFieldModule, MatSelectModule, IconsModule, InputModule, EGIDataTransferModule
OrcidModule, MatFormFieldModule, MatSelectModule, IconsModule, InputModule, EGIDataTransferModule, RecaptchaModule,
SdgFosSuggestModule, FullScreenModalModule, SafeHtmlPipeModule, EntityActionsModule
],
declarations: [
ResultLandingComponent
@ -58,6 +64,6 @@ import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.modul
})
export class ResultLandingModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([link, graph, quotes])
this.iconsService.registerIcons([link, graph, quotes, cite, link_to, versions, rocket, fire, landmark])
}
}

View File

@ -13,7 +13,7 @@ import {HelperFunctions} from "../../utils/HelperFunctions.class";
@Injectable()
export class ResultLandingService {
constructor(private http: HttpClient ) {
constructor(private http: HttpClient) {
this.parsingFunctions = new ParsingFunctions();
}
@ -39,7 +39,7 @@ export class ResultLandingService {
} else if (identifier) {
// pid = "10.3389/fphys.2014.00466";
let url = properties.searchAPIURLLAst + "resources2";
url += "?pid="+encodeURIComponent(identifier.id) + "&pidtype=" + identifier.class + "&type=";
url += "?pid=" + encodeURIComponent(identifier.id) + "&pidtype=" + identifier.class + "&type=";
if (type === 'publication') {
url += 'publications';
} else if (type === 'dataset') {
@ -56,50 +56,50 @@ export class ResultLandingService {
}
}
getResultLandingInfo (id: string, identifier: Identifier, type: string,
subjectsVocabulary: any,
properties: EnvProperties): any {
getResultLandingInfo(id: string, identifier: Identifier, type: string,
subjectsVocabulary: any,
properties: EnvProperties): any {
let url: string = this.buildResultLandingInfoUrl(id, identifier, type);
let finalUrl: string = (properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url;
return this.http.get(finalUrl)
.pipe(map(res => {
if(!id && identifier) {
if(!res['results'] || res['results'].length == 0) {
throw new HttpErrorResponse({
status: 404,
statusText: "Not found",
url: finalUrl,
error: "Http failure response for "+finalUrl+": 404 Not Found"
});
.pipe(map(res => {
if (!id && identifier) {
if (!res['results'] || res['results'].length == 0) {
throw new HttpErrorResponse({
status: 404,
statusText: "Not found",
url: finalUrl,
error: "Http failure response for " + finalUrl + ": 404 Not Found"
});
}
return res['results'][0];
} else {
return res;
}
return res['results'][0];
} else {
return res;
}
}))
.pipe(map(res => [res['result']['header']['dri:status'], res['result']['metadata']['oaf:entity'], res]))
.pipe(map(res => [
res[1]['oaf:result'], // 0
res[1]['oaf:result']['title'], // 1
res[1]['oaf:result']['rels']['rel'], // 2
res[1]['oaf:result']['children'], // 3
res[1]['oaf:result']['pid'], // 4
res[1]['oaf:result']['journal'], // 5
res[1]['oaf:result']['language'], // 6
res[1]['oaf:result']['eoscifguidelines'], // 7
res[1]['oaf:result']['subject'], // 8
res[1]['oaf:result']['context'], // 9
res[1]['oaf:result']['creator'], // 10
res[1]['oaf:result']['country'] , // 11
res[1]['oaf:result']['programmingLanguage'], // 12 - software
//res[1]['oaf:result']['resulttype'],
(res[1]['extraInfo'] !== undefined && res[1]['extraInfo']['references'] !== undefined)
? res[1]['extraInfo']['references']['reference'] : null, // 13
res[0], // 14
res[2], // 15
]))
.pipe(map(res => this.parseResultLandingInfo(res, subjectsVocabulary, properties)));
}))
.pipe(map(res => [res['result']['header']['dri:status'], res['result']['metadata']['oaf:entity'], res]))
.pipe(map(res => [
res[1]['oaf:result'], // 0
res[1]['oaf:result']['title'], // 1
res[1]['oaf:result']['rels']['rel'], // 2
res[1]['oaf:result']['children'], // 3
res[1]['oaf:result']['pid'], // 4
res[1]['oaf:result']['journal'], // 5
res[1]['oaf:result']['language'], // 6
res[1]['oaf:result']['eoscifguidelines'], // 7
res[1]['oaf:result']['subject'], // 8
res[1]['oaf:result']['context'], // 9
res[1]['oaf:result']['creator'], // 10
res[1]['oaf:result']['country'], // 11
res[1]['oaf:result']['programmingLanguage'], // 12 - software
//res[1]['oaf:result']['resulttype'],
(res[1]['extraInfo'] !== undefined && res[1]['extraInfo']['references'] !== undefined)
? res[1]['extraInfo']['references']['reference'] : null, // 13
res[0], // 14
res[2], // 15
]))
.pipe(map(res => this.parseResultLandingInfo(res, subjectsVocabulary, properties)));
}
// getProvenanceActionVocabulary (properties: EnvProperties): any {
@ -118,16 +118,15 @@ export class ResultLandingService {
// return provenanceActionVocabulary;
// }
private handleError (error: HttpErrorResponse) {
private handleError(error: HttpErrorResponse) {
// in a real world app, we may send the error to some remote logging infrastructure
// instead of just logging it to the console
console.log(error);
return throwError(error || 'Server error');
return throwError(error || 'Server error');
}
parseResultLandingInfo (data: any, subjectsVocabulary: any, properties: EnvProperties): any {
parseResultLandingInfo(data: any, subjectsVocabulary: any, properties: EnvProperties): any {
this.resultLandingInfo = new ResultLandingInfo();
// res
this.resultLandingInfo.record = data[15];
this.resultLandingInfo.objIdentifier = data[15]["result"]["header"]["dri:objIdentifier"];
@ -137,25 +136,25 @@ export class ResultLandingService {
// res['result']['metadata']['oaf:entity']['oaf:result']
if (data[0] != null) {
let date: string = (data[0].dateofacceptance ? data[0].dateofacceptance : '') + ''; // transform to string in case it is an integer
this.resultLandingInfo.date = (date && (date).indexOf('-') !== -1) ? date.split('-')[0] : date;
this.resultLandingInfo.dateofacceptance = data[0].dateofacceptance?Dates.getDate(data[0].dateofacceptance):null;
this.resultLandingInfo.date = (date && (date).indexOf('-') !== -1) ? date.split('-')[0] : date;
this.resultLandingInfo.dateofacceptance = data[0].dateofacceptance ? Dates.getDate(data[0].dateofacceptance) : null;
this.resultLandingInfo.publisher = data[0].publisher;
this.resultLandingInfo.description = this.parsingFunctions.parseDescription(data[0] && data[0].description?data[0].description:[]);
this.resultLandingInfo.embargoEndDate = data[0].embargoenddate?Dates.getDate(data[0].embargoenddate):null;
this.resultLandingInfo.description = this.parsingFunctions.parseDescription(data[0] && data[0].description ? data[0].description : []);
this.resultLandingInfo.embargoEndDate = data[0].embargoenddate ? Dates.getDate(data[0].embargoenddate) : null;
}
if(data[0]['bestaccessright'] && data[0]['bestaccessright'].hasOwnProperty("classname")) {
if (data[0]['bestaccessright'] && data[0]['bestaccessright'].hasOwnProperty("classname")) {
this.resultLandingInfo.accessMode = data[0]['bestaccessright'].classname;
}
// res['result']['metadata']['oaf:entity']['oaf:result']['title']
if(data[1] != null) {
if(Array.isArray(data[1])) {
for(let i=0; i<data[1].length; i++) {
if(data[1][i] && data[1][i].content) {
if(!this.resultLandingInfo.title || data[1][i].classid == "main title") {
if (data[1] != null) {
if (Array.isArray(data[1])) {
for (let i = 0; i < data[1].length; i++) {
if (data[1][i] && data[1][i].content) {
if (!this.resultLandingInfo.title || data[1][i].classid == "main title") {
this.resultLandingInfo.title = StringUtils.HTMLToString(String(data[1][i].content));
}
if(!this.resultLandingInfo.subtitle && data[1][i].classid === 'subtitle') {
if (!this.resultLandingInfo.subtitle && data[1][i].classid === 'subtitle') {
this.resultLandingInfo.subtitle = StringUtils.HTMLToString(String(data[1][i].content));
}
// if(data[1][i].classid == "main title") {
@ -163,10 +162,10 @@ export class ResultLandingService {
// }
}
}
if(this.resultLandingInfo.title === this.resultLandingInfo.subtitle) {
if (this.resultLandingInfo.title === this.resultLandingInfo.subtitle) {
this.resultLandingInfo.subtitle = "";
}
if(!this.resultLandingInfo.title) {
if (!this.resultLandingInfo.title) {
this.resultLandingInfo.title = "";
}
// this.resultLandingInfo.title = (data[1][0] && data[1][0].content) ? String(data[1][0].content) : "";
@ -176,26 +175,26 @@ export class ResultLandingService {
}
// res['result']['metadata']['oaf:entity']['oaf:result']['rels']['rel']
if(data[2] != null) {
if (data[2] != null) {
let relation;
let length = Array.isArray(data[2]) ? data[2].length : 1;
for(let i=0; i<length; i++) {
for (let i = 0; i < length; i++) {
relation = Array.isArray(data[2]) ? data[2][i] : data[2];
if(relation.hasOwnProperty("to")) {
if(relation['to'].class && relation['to'].class.toLowerCase() == "isproducedby") {
if (relation.hasOwnProperty("to")) {
if (relation['to'].class && relation['to'].class.toLowerCase() == "isproducedby") {
this.resultLandingInfo.fundedByProjects = this.parsingFunctions.parseFundingByProjects(this.resultLandingInfo.fundedByProjects, relation);
}
if(relation['to'].scheme && relation['to'].scheme == "dnet:result_result_relations") {
if (relation['to'].scheme && relation['to'].scheme == "dnet:result_result_relations") {
let relationName: string = relation.to.class;
if(!this.resultLandingInfo.relatedClassFilters.has(relationName)) {
if (!this.resultLandingInfo.relatedClassFilters.has(relationName)) {
this.resultLandingInfo.relatedClassFilters.add(relationName);
}
let provenanceAction: string = relation.provenanceaction;
this.resultLandingInfo.relatedResults = this.parsingFunctions.parseResults(this.resultLandingInfo.relatedResults, relation, provenanceAction, relationName);
} else if(relation['to'].class && relation['to'].class.toLowerCase() == "hasauthorinstitution") {
} else if (relation['to'].class && relation['to'].class.toLowerCase() == "hasauthorinstitution") {
this.resultLandingInfo.organizations = this.parseRelatedOrganizations(this.resultLandingInfo.organizations, relation);
}
}
@ -203,19 +202,19 @@ export class ResultLandingService {
}
// res['result']['metadata']['oaf:entity']['oaf:result']['children']
if(data[3] != null) {
if(data[3].hasOwnProperty("result")) {
if (data[3] != null) {
if (data[3].hasOwnProperty("result")) {
this.resultLandingInfo.deletedByInferenceIds = [];
let length = Array.isArray(data[3]['result']) ? data[3]['result'].length : 1;
for(let i=0; i<length; i++) {
for (let i = 0; i < length; i++) {
let result = Array.isArray(data[3]['result']) ? data[3]['result'][i] : data[3]['result'];
this.resultLandingInfo.deletedByInferenceIds.push(result.objidentifier);
}
}
if(data[3].hasOwnProperty("instance")) {
if (data[3].hasOwnProperty("instance")) {
this.resultLandingInfo.hostedBy_collectedFrom = new Array<HostedByCollectedFrom>();
@ -227,26 +226,24 @@ export class ResultLandingService {
let length = Array.isArray(data[3]['instance']) ? data[3]['instance'].length : 1;
for(let i=0; i<length; i++) {
for (let i = 0; i < length; i++) {
instance = Array.isArray(data[3]['instance']) ? data[3]['instance'][i] : data[3]['instance'];
this.parsingFunctions.parseTypes(this.resultLandingInfo.types, types, instance);
if(instance.hasOwnProperty("webresource")) {
if (instance.hasOwnProperty("webresource")) {
let url;
if(!Array.isArray(instance['webresource'])) {
if (!Array.isArray(instance['webresource'])) {
url = instance['webresource'].url;
} else {
url = instance['webresource'][0].url;
}
if(url.includes('&amp;')) {
let regExp = /&amp;/gmu;
let newUrl = url.replace(regExp, '&');
url = newUrl;
if (url.includes('&amp;')) {
url = url.replace(/&amp;/gmu, '&');
}
/**********************************************************/
if(instance.hasOwnProperty("hostedby")) {
if (instance.hasOwnProperty("hostedby")) {
this.parsingFunctions.parseHostedBy_collectedFrom(this.resultLandingInfo.hostedBy_collectedFrom, instance, url, this.resultLandingInfo.accessMode);
}
/**********************************************************/
@ -254,57 +251,32 @@ export class ResultLandingService {
}
/* Order Download from via openness*/
this.resultLandingInfo.hostedBy_collectedFrom.sort((a, b) => {
let firstAccessRight: string = (a.accessRight ? a.accessRight.toLowerCase() : null);
let secondAccessRight: string = (b.accessRight ? b.accessRight.toLowerCase() : null);
if (firstAccessRight === secondAccessRight) {
return 0;
} else {
if (firstAccessRight === 'open access') {
return -1;
} else if (secondAccessRight === 'open access') {
return 1;
} else if (firstAccessRight === "open source") {
return -1;
} else if (secondAccessRight === "open source") {
return 1;
} else if (firstAccessRight === "embargo") {
return -1;
} else if (secondAccessRight === "embargo") {
return 1;
} else if (firstAccessRight === "restricted") {
return -1;
} else if (secondAccessRight === "restricted") {
return 1;
} else if (firstAccessRight === "closed access") {
return -1;
} else if (secondAccessRight === "closed access") {
return 1;
} else if (firstAccessRight === "not available") {
return -1;
} else if (secondAccessRight === "not available") {
return 1;
}
}
return 0;
});
this.resultLandingInfo.hostedBy_collectedFrom.sort(this.parsingFunctions.compareHostedByCollectedFrom);
}
if(data[3].hasOwnProperty("externalreference")) {
if (data[3].hasOwnProperty("externalreference")) {
let externalResults: Map<string, Map<string, string>> = this.parseBioentitiesAndSoftware(data[3]);
this.resultLandingInfo.bioentities = externalResults;
}
}
// res['result']['metadata']['oaf:entity']['oaf:result']['pid']
if(data[4] != null) {
if (data[4] != null) {
this.resultLandingInfo.identifiers = this.parsingFunctions.parseIdentifiers(data[4]);
}
// res['result']['metadata']['oaf:entity']['oaf:result']['journal']
if(data[5] != null) {
this.resultLandingInfo.journal = {"journal": "", "issn": "", "lissn": "", "eissn": "", "issue": "", "volume": "", "start_page": "", "end_page": ""}
if (data[5] != null) {
this.resultLandingInfo.journal = {
"journal": "",
"issn": "",
"lissn": "",
"eissn": "",
"issue": "",
"volume": "",
"start_page": "",
"end_page": ""
}
this.resultLandingInfo.journal['journal'] = data[5].content;
this.resultLandingInfo.journal['issn'] = data[5].issn;
@ -317,7 +289,7 @@ export class ResultLandingService {
}
// res['result']['metadata']['oaf:entity']['oaf:result']['language']
if(data[6] != null) {
if (data[6] != null) {
this.resultLandingInfo.languages = this.parsingFunctions.parseLanguages(data[6]);
// let languagesAndCodes: string[][] = this.parsingFunctions.parseLanguages(data[6]);
// this.resultLandingInfo.languages = languagesAndCodes[0];
@ -325,27 +297,31 @@ export class ResultLandingService {
}
// res['result']['metadata']['oaf:entity']['oaf:result']['country']
if(data[11] != null) {
if (data[11] != null) {
this.resultLandingInfo.countries = this.parsingFunctions.parseCountries(data[11]);
}
// res['result']['metadata']['oaf:entity']['oaf:result']['eoscifguidelines']
if(data[7] != null) {
if (data[7] != null) {
this.resultLandingInfo.eoscSubjects = this.parsingFunctions.parseEoscSubjects(data[7]);
}
// res['result']['metadata']['oaf:entity']['oaf:result']['subject']
if(data[8] != null) {
if (data[8] != null) {
let subjectResults: [string[], Map<string, string[]>, Map<string, string[]>, string[], string[]] = this.parsingFunctions.parseAllSubjects(data[8], subjectsVocabulary);
this.resultLandingInfo.subjects = subjectResults[0];
this.resultLandingInfo.otherSubjects = subjectResults[1];
this.resultLandingInfo.classifiedSubjects = subjectResults[2];
this.resultLandingInfo.fos = subjectResults[3];
if(this.resultLandingInfo.fos) {
this.resultLandingInfo.fos.sort((a, b) => a.localeCompare(b))
if (subjectResults[3]) {
subjectResults[3].forEach(element => {
this.resultLandingInfo.fos.push({id: element, label: element.replace(/^\d+/, '').trim()});
});
}
if (this.resultLandingInfo.fos) {
this.resultLandingInfo.fos.sort((a, b) => a.id.localeCompare(b.id));
}
this.resultLandingInfo.sdg = subjectResults[4];
if(this.resultLandingInfo.sdg) {
if (this.resultLandingInfo.sdg) {
this.resultLandingInfo.sdg.sort((a, b) => {
return HelperFunctions.sortSDGs(a, b);
})
@ -357,50 +333,54 @@ export class ResultLandingService {
}
this.resultLandingInfo.hostedBy_collectedFrom = this.parsingFunctions.addPublisherToHostedBy_collectedFrom(
this.resultLandingInfo.hostedBy_collectedFrom, this.resultLandingInfo.publisher,
this.resultLandingInfo.journal, this.resultLandingInfo.identifiers);
this.resultLandingInfo.hostedBy_collectedFrom, this.resultLandingInfo.publisher,
this.resultLandingInfo.journal?.journal, this.resultLandingInfo.identifiers);
// res['result']['metadata']['oaf:entity']['oaf:result']['programmingLanguage']
if(data[12] != null) {
if (data[12] != null) {
this.resultLandingInfo.programmingLanguages = this.parsingFunctions.parseProgrammingLanguages(data[12]);
}
// res['result']['metadata']['oaf:entity']['extraInfo']['references']['reference']
if(data[13] != null) {
if (data[13] != null) {
this.resultLandingInfo.references = this.parsingFunctions.parseReferences(data[13]);
}
// res['result']['metadata']['oaf:entity']['oaf:result']['context']
if(data[9] != null) {
if (data[9] != null) {
this.resultLandingInfo.contexts = this.parsingFunctions.parseContexts(data[9]);
}
// res['result']['header']['dri:status']
if(data[14] != null && data[14] == "under curation") {
if (data[14] != null && data[14] == "under curation") {
this.resultLandingInfo.underCurationMessage = true;
} else {
this.resultLandingInfo.underCurationMessage = false;
}
// res['result']['metadata']['oaf:entity']['oaf:result']['creator']
if(data[10] != null) {
if(this.resultLandingInfo.authors == undefined) {
this.resultLandingInfo.authors = new Array<{"fullName": string, "orcid": string, "orcid_pending": string}>();
if (data[10] != null) {
if (this.resultLandingInfo.authors == undefined) {
this.resultLandingInfo.authors = new Array<{ "fullName": string, "orcid": string, "orcid_pending": string }>();
}
let authors = data[10];
let length = Array.isArray(authors) ? authors.length : 1;
for(let i=0; i<length; i++) {
for (let i = 0; i < length; i++) {
let author = Array.isArray(authors) ? authors[i] : authors;
if(author) {
if(author.orcid) {
if (author) {
if (author.orcid) {
author.orcid = author.orcid.toUpperCase();
}
if(author.orcid_pending) {
if (author.orcid_pending) {
author.orcid_pending = author.orcid_pending.toUpperCase();
}
this.resultLandingInfo['authors'][author.rank] = {"fullName": author.content, "orcid": author.orcid, "orcid_pending": author.orcid_pending};
this.resultLandingInfo['authors'][author.rank] = {
"fullName": author.content,
"orcid": author.orcid,
"orcid_pending": author.orcid_pending
};
}
}
this.resultLandingInfo.authors = this.resultLandingInfo.authors.filter(function (item) {
@ -408,17 +388,23 @@ export class ResultLandingService {
});
}
// res['result']['metadata']['oaf:entity']['oaf:result']['measure']
if (data[0]?.measure) {
this.resultLandingInfo.measure = this.parsingFunctions.parseMeasures(data[0].measure);
}
this.resultLandingInfo.relatedResults = this.parsingFunctions.sortByPercentage(this.resultLandingInfo.relatedResults);
return this.resultLandingInfo;
}
parseRelatedOrganizations(organizations: Organization[], relation: any): Organization[] {
if(organizations == undefined) {
if (organizations == undefined) {
organizations = []
}
let organization: { "name": string, "shortname": string,
let organization: {
"name": string, "shortname": string,
"id": string, "websiteUrl": string,
"country": string, "trust": number
} = {
@ -431,34 +417,34 @@ export class ResultLandingService {
organization.name = relation.legalname;
organization.shortname = relation.legalshortname;
organization.websiteUrl = relation.websiteurl;
if(relation.country) {
if (relation.country) {
organization.country = relation.country.classname;
}
if(relation.trust) {
organization.trust = Math.round(relation.trust*100);
if (relation.trust) {
organization.trust = Math.round(relation.trust * 100);
}
organizations.push(organization);
return organizations;
}
parseBioentitiesAndSoftware(children: any) : Map<string, Map<string, string>> {
parseBioentitiesAndSoftware(children: any): Map<string, Map<string, string>> {
let bioentities: Map<string, Map<string, string>>;
let length = Array.isArray(children['externalreference']) ? children['externalreference'].length : 1;
let externalreference;
for(let i=0; i<length; i++) {
for (let i = 0; i < length; i++) {
externalreference = Array.isArray(children['externalreference']) ? children['externalreference'][i] : children['externalreference'];
if(externalreference.hasOwnProperty("qualifier")) {
if(externalreference['qualifier'].classid == "accessionNumber") {
if (externalreference.hasOwnProperty("qualifier")) {
if (externalreference['qualifier'].classid == "accessionNumber") {
if(bioentities == undefined) {
if (bioentities == undefined) {
bioentities = new Map<string, Map<string, string>>();
}
if(!bioentities.has(externalreference.sitename)) {
if (!bioentities.has(externalreference.sitename)) {
bioentities.set(externalreference.sitename, new Map<string, string>());
}
bioentities.get(externalreference.sitename).set(externalreference.refidentifier, externalreference.url);
@ -471,10 +457,10 @@ export class ResultLandingService {
}
getEnermapsDetails(id: string) {
let url = properties.enermapsURL+"/api/db/metadata?shared_id=eq."+id;
return this.http.get((properties.useLongCache)? (properties.cacheUrl+encodeURIComponent(url)): url)
// return this.http.get(url)
.pipe(map(res => this.parseEnermapsDetails(res)));
let url = properties.enermapsURL + "/api/db/metadata?shared_id=eq." + id;
return this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
// return this.http.get(url)
.pipe(map(res => this.parseEnermapsDetails(res)));
}
parseEnermapsDetails(response: any) {
@ -483,9 +469,9 @@ export class ResultLandingService {
let entries = [];
let keys = metadata ? Object.keys(metadata) : null;
for(let key of keys) {
if(key != "shared_id" && key && metadata[key]) {
entries.push([key+"", metadata[key]+""]);
for (let key of keys) {
if (key != "shared_id" && key && metadata[key]) {
entries.push([key + "", metadata[key] + ""]);
}
}
return entries;

View File

@ -13,7 +13,9 @@ import {LoginErrorCodes} from './utils/guardHelper.class';
import {UserManagementService} from "../services/user-management.service";
import {map, tap} from "rxjs/operators";
@Injectable()
@Injectable({
providedIn: 'root'
})
export class AdminLoginGuard implements CanActivate, CanActivateChild {
constructor(private router: Router,

View File

@ -6,15 +6,17 @@ import {
CanLoad,
Route,
Router,
RouterStateSnapshot, UrlTree
RouterStateSnapshot,
UrlTree
} from '@angular/router';
import {Observable} from 'rxjs';
import {Session} from './utils/helper.class';
import {LoginErrorCodes} from './utils/guardHelper.class';
import {map, tap} from "rxjs/operators";
import {UserManagementService} from "../services/user-management.service";
@Injectable()
@Injectable({
providedIn: 'root'
})
export class LoginGuard implements CanActivate, CanLoad, CanActivateChild {
constructor(private router: Router,

View File

@ -6,8 +6,44 @@ export class User {
fullname: string;
expirationDate: number;
role: string[];
jwt: string;
accessToken?: string;
refreshToken?: string;
constructor(info: any) {
this.id = (info.sub && info.sub.indexOf('@')) ? info.sub.substring(0, info.sub.indexOf('@')) : info.sub;
this.firstname = (info.given_name) ? info.given_name : "";
this.lastname = (info.family_name) ? info.family_name : "";
this.email = info.email.toLowerCase(); // TODO remove, is a quick fix
if(info.accessToken) {
this.accessToken = info.accessToken;
}
if(info.refreshToken) {
this.refreshToken = info.refreshToken;
}
this.fullname = (info.name) ? info.name : "";
if (this.fullname == "") {
if (this.firstname != "") {
this.fullname += this.firstname;
}
if (this.lastname != "") {
this.fullname += this.lastname;
}
if (this.fullname == "") { //fullname is still empty set a default
this.fullname = "Anonymous user";
}
}
this.role = [];
if (info.roles) {
info.roles.forEach(role => {
this.role.push(role);
});
} else {
if (info.edu_person_entitlements) {
this.role = info.edu_person_entitlements;
}
}
this.expirationDate = info.exp_date;
}
}
export class Session {

View File

@ -12,6 +12,7 @@ export type IndicatorType = 'number' | 'chart';
export type IndicatorSize = 'small' | 'medium' | 'large';
export type IndicatorPathType = 'table' | 'bar' | 'column' | 'pie' | 'line' | 'other';
export type SourceType = 'statistics' | 'search' |'stats-tool' | 'old' | 'image';
export type Format = 'NUMBER' | 'PERCENTAGE';
export type Visibility = 'PUBLIC' | 'PRIVATE' | 'RESTRICTED';
export class Stakeholder {
@ -21,6 +22,8 @@ export class Stakeholder {
index_id;
index_name: string;
index_shortName: string;
statsProfile: string = "monitor";
locale: string = 'eu';
alias: string;
defaultId: string;
visibility: Visibility;
@ -192,8 +195,9 @@ export class IndicatorPath {
parameters: any;
filters: any;
filtersApplied: number = 0;
format: Format;
constructor(type: IndicatorPathType, source: SourceType, url: string, chartObject: string, jsonPath: string[]) {
constructor(type: IndicatorPathType, source: SourceType, url: string, chartObject: string, jsonPath: string[], format: Format = 'NUMBER') {
this.type = type;
this.url = url;
this.source = source;
@ -202,6 +206,7 @@ export class IndicatorPath {
this.parameters = {};
this.filters = {};
this.filtersApplied = 0;
this.format = format;
}
static createParameters(funderName: string = null, title: string = null, chartType: string = null): any {
@ -213,8 +218,10 @@ export class IndicatorPath {
}
}
export type FilterType = "fundingL0"|"start_year" | "end_year" | "co-funded";
export class IndicatorFilterUtils{
export class IndicatorFilterUtils {
static getFilter(fieldPath: string, filterType:FilterType) {
if((filterType == "start_year" || filterType == "end_year") && (fieldPath.indexOf(".year") != -1 || fieldPath.indexOf(".start year") != -1)

View File

@ -184,6 +184,8 @@ export class TerminologyComponent implements OnInit, OnDestroy, AfterViewInit, A
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) {
subscription.unsubscribe();
} else if(typeof ResizeObserver != 'undefined' && subscription instanceof ResizeObserver) {
subscription.disconnect();
}
});
}

View File

@ -26,27 +26,27 @@ export class ResourcesService {
constructor(private http: HttpClient) {
}
private async getResourcesItemsAsync(prefix = '', portal: string = null): Promise<MenuItem[]> {
private async getResourcesItemsAsync(prefix = '', portal: string = null, target = '_self'): Promise<MenuItem[]> {
let items = [
new MenuItem("methodology", "Methodology", "", "", false, [],
null, {}, null, null, null, null, '_self'),
ResourcesService.setLink(new MenuItem("methodological-approach", "Methodological Approach",
"", "", false, [], null, {}, null, null, null, null, '_self'),
"", "", false, [], null, {}, null, null, null, null, target),
prefix + "/methodology/methodological-approach", portal),
ResourcesService.setLink(new MenuItem("terminology", "Terminology and construction",
"", "", false, [], null, {}, null, null, null, null, '_self'),
"", "", false, [], null, {}, null, null, null, null, target),
prefix + "/methodology/terminology", portal)];
items.push(new MenuItem("indicators-page", "Indicators",
"", "", false, [], null, {}));
items.push(ResourcesService.setLink(new MenuItem("indicator-themes", "Indicator Themes",
"", "", false, [], null, {}, null, null, null, null, '_self'), prefix + "/indicators/themes", portal));
"", "", false, [], null, {}, null, null, null, null, target), prefix + "/indicators/themes", portal));
let promise = new Promise<void>(resolve => {
this.isPagesEnabled().subscribe(status => {
ResourcesService.types.forEach((type, index) => {
if (status[index]) {
items.push(ResourcesService.setLink(
new MenuItem("indicators-" + type.value, type.label,
"", "", false, [], null, {}, null, null, null, null, '_self'),
"", "", false, [], null, {}, null, null, null, null, target),
prefix + "/indicators/" + type.value, portal)
);
}
@ -61,13 +61,13 @@ export class ResourcesService {
return items;
}
setResources(items: MenuItem[], prefix = '', portal: string = null) {
setResources(items: MenuItem[], prefix = '', portal: string = null, target = '_self') {
if (this.subscription) {
this.subscription.unsubscribe();
}
let resources = new MenuItem('resources', 'Resources', "", "", false, [], null, {});
let index = items.push(resources) - 1;
this.subscription = from(this.getResourcesItemsAsync(prefix, portal)).subscribe(resourcesItems => {
this.subscription = from(this.getResourcesItemsAsync(prefix, portal, target)).subscribe(resourcesItems => {
items[index].items = resourcesItems;
});
}

View File

@ -4,13 +4,10 @@ import {BehaviorSubject, from, Observable, Subscriber} from "rxjs";
import {Indicator, Section, Stakeholder, StakeholderInfo, Visibility} from "../entities/stakeholder";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {map} from "rxjs/operators";
import {ActivatedRoute} from "@angular/router";
import {properties} from "../../../../environments/environment";
import {CustomOptions} from "../../services/servicesUtils/customOptions.class";
import {StringUtils} from "../../utils/string-utils.class";
let maps: string[] = ['parameters', 'filters'];
export interface Reorder {
action: 'moved' | 'added' | 'removed',
target: string,
@ -21,25 +18,25 @@ export interface Reorder {
providedIn: "root"
})
export class StakeholderService {
private stakeholderSubject: BehaviorSubject<Stakeholder> = null;
private promise: Promise<void>;
private sub;
constructor(private http: HttpClient) {
this.stakeholderSubject = new BehaviorSubject<Stakeholder>(null);
}
ngOnDestroy() {
this.clearSubscriptions();
}
clearSubscriptions() {
if (this.sub instanceof Subscriber) {
this.sub.unsubscribe();
}
}
getStakeholder(alias: string, shouldUpdate: boolean = false): Observable<Stakeholder> {
if (!this.stakeholderSubject.value || this.stakeholderSubject.value.alias !== alias || shouldUpdate) {
this.promise = new Promise<void>((resolve, reject) => {
@ -56,78 +53,80 @@ export class StakeholderService {
}
return from(this.getStakeholderAsync());
}
async getStakeholderAsync() {
if(this.promise) {
if (this.promise) {
await this.promise;
this.promise = null;
}
this.clearSubscriptions();
return this.stakeholderSubject.getValue();
}
getAlias(url: string): Observable<string[]> {
return this.http.get<Stakeholder[]>(url + '/stakeholder/alias', CustomOptions.registryOptions()).pipe(map(stakeholders => {
return this.formalize(stakeholders);
}));
}
getStakeholders(url: string, type: string = null, defaultId: string = null): Observable<(Stakeholder & StakeholderInfo)[]> {
return this.http.get<Stakeholder[]>(url + '/stakeholder' + ((type) ? ('?type=' + type) : '') + ((!type && defaultId)? ('?defaultId=' + defaultId):''), CustomOptions.registryOptions()).pipe(map(stakeholders => {
return this.http.get<Stakeholder[]>(url + '/stakeholder' + ((type) ? ('?type=' + type) : '') + ((!type && defaultId) ? ('?defaultId=' + defaultId) : ''), CustomOptions.registryOptions()).pipe(map(stakeholders => {
return this.formalize(this.checkIsUpload(stakeholders));
}));
}
getMyStakeholders(url: string, type: string = null): Observable<(Stakeholder & StakeholderInfo)[]> {
return this.http.get<Stakeholder[]>(url + '/my-stakeholder' + ((type) ? ('?type=' + type) : ''), CustomOptions.registryOptions()).pipe(map(stakeholders => {
return this.formalize(this.checkIsUpload(stakeholders));
}));
}
getDefaultStakeholders(url: string, type: string = null): Observable<Stakeholder[]> {
return this.http.get<Stakeholder[]>(url + '/stakeholder/default' + ((type) ? ('?type=' + type) : ''), CustomOptions.registryOptions()).pipe(map(stakeholders => {
return this.formalize(this.checkIsUpload(stakeholders));
}));
}
buildStakeholder(url: string, stakeholder: Stakeholder): Observable<Stakeholder> {
if(stakeholder.alias && stakeholder.alias.startsWith('/')) {
stakeholder.alias = stakeholder.alias.slice(1);
}
if (stakeholder.alias && stakeholder.alias.startsWith('/')) {
stakeholder.alias = stakeholder.alias.slice(1);
}
return this.http.post<Stakeholder>(url + '/build-stakeholder', stakeholder, CustomOptions.registryOptions()).pipe(map(stakeholder => {
return this.formalize(this.checkIsUpload(stakeholder));
}));
}
changeVisibility(url: string, path: string[], visibility: Visibility, propagate: boolean = false): Observable<any> {
return this.http.post<Visibility>(url + '/' + path.join('/') + '/change-visibility' + '?visibility=' + visibility + (propagate?'&propagate=true':''), null, CustomOptions.registryOptions());
return this.http.post<Visibility>(url + '/' + path.join('/') + '/change-visibility' + '?visibility=' + visibility + (propagate ? '&propagate=true' : ''), null, CustomOptions.registryOptions());
}
saveElement(url: string, element: any, path: string[] = []): Observable<any> {
if(element.alias && element.alias.startsWith('/')) {
element.alias = element.alias.slice(1);
}
if (element.alias && element.alias.startsWith('/')) {
element.alias = element.alias.slice(1);
}
path = HelperFunctions.encodeArray(path);
return this.http.post<any>(url + ((path.length > 0) ? '/' : '') + path.join('/') +
'/save', element, CustomOptions.registryOptions()).pipe(map(element => {
if(path.length === 0) {
return this.formalize(this.checkIsUpload(element));
} else {
return this.formalize(element);
}
}));
}
saveBulkElements(url: string, indicators, path: string[] = []): Observable<any> {
path = HelperFunctions.encodeArray(path);
return this.http.post<any>(url + ((path.length > 0) ? '/' : '') + path.join('/') +
'/save-bulk', indicators, CustomOptions.registryOptions()).pipe(map(element => {
if(path.length === 0) {
if (path.length === 0) {
return this.formalize(this.checkIsUpload(element));
} else {
return this.formalize(element);
}
}));
}
saveBulkElements(url: string, indicators, path: string[] = []): Observable<any> {
path = HelperFunctions.encodeArray(path);
return this.http.post<any>(url + ((path.length > 0) ? '/' : '') + path.join('/') +
'/save-bulk', indicators, CustomOptions.registryOptions()).pipe(map(element => {
if (path.length === 0) {
return this.formalize(this.checkIsUpload(element));
} else {
return this.formalize(element);
}
}));
}
saveSection(url: string, element: any, path: string[] = [], index: number = -1): Observable<Section> {
path = HelperFunctions.encodeArray(path);
return this.http.post<Section>(url + ((path.length > 0) ? '/' : '') + path.join('/') +
@ -135,7 +134,7 @@ export class StakeholderService {
return this.formalize(element);
}));
}
deleteElement(url: string, path: string[], childrenAction: string = null): Observable<any> {
path = HelperFunctions.encodeArray(path);
let params: string = "";
@ -144,29 +143,29 @@ export class StakeholderService {
}
return this.http.delete<any>(url + '/' + path.join('/') + '/delete' + params, CustomOptions.registryOptions());
}
reorderElements(url: string, path: string[], ids: string[]): Observable<any> {
path = HelperFunctions.encodeArray(path);
return this.http.post<any>(url + '/' + path.join('/') + '/reorder', ids, CustomOptions.registryOptions());
}
reorderIndicators(url: string, path: string[], reorder: Reorder, type: string = 'chart'): Observable<Indicator[]> {
path = HelperFunctions.encodeArray(path);
return this.http.post<Indicator[]>(url + '/' + path.join('/') + '/' + type + '/reorder', reorder, CustomOptions.registryOptions()).pipe(map(indicators => {
return this.formalize(indicators);
}));
}
getStakeholderAsObservable(): Observable<Stakeholder> {
return this.stakeholderSubject.asObservable();
}
setStakeholder(stakeholder: Stakeholder) {
this.stakeholderSubject.next(stakeholder);
}
private checkIsUpload(response: Stakeholder | Stakeholder[]): any | any[] {
if(Array.isArray(response)) {
if (Array.isArray(response)) {
response.forEach(value => {
value.isUpload = value.logoUrl && !StringUtils.isValidUrl(value.logoUrl);
});
@ -175,7 +174,7 @@ export class StakeholderService {
}
return response;
}
private formalize(element: any) {
return HelperFunctions.copy(element);
}

View File

@ -11,100 +11,98 @@ import {ExternalIDV3_0, WorkV3_0} from "./orcidWork";
import {EnvProperties} from "../utils/properties/env-properties";
import {UserManagementService} from "../services/user-management.service";
import {OpenaireEntities} from "../utils/properties/searchFields";
import {FullScreenModalComponent} from "../utils/modal/full-screen-modal/full-screen-modal.component";
declare var UIkit: any;
@Component({
selector: 'orcid-work',
template: `
<ng-container *ngIf="pageType == 'search'">
<ng-container *ngIf="pageType == 'landing' || pageType == 'search'">
<span *ngIf="!putCodes || putCodes.length == 0"
[attr.uk-tooltip]="(!isLoggedIn) ? tooltipNoLoggedInUser : tooltipAdd"
class="uk-margin-remove-bottom">
<a (click)="currentAction='add'; saveWorkPreparation();"
[class]="'uk-button uk-button-link uk-flex uk-flex-middle uk-flex-right@s uk-margin-right '+ ((showLoading || !isLoggedIn) ? 'uk-disabled ' : '') + (!isLoggedIn ? 'half-opacity' : '')">
<icon *ngIf="!showLoading" name="add" ratio="1" flex="true"></icon>
<span *ngIf="showLoading" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span class="uk-margin-small-left uk-flex uk-flex-middle">Add to&#160;
<span class="uk-flex uk-flex-middle">
<span>ORCID&#160;</span>
<img class="" src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="orcid" style="width:16px; height:16px" loading="lazy">&#160;
</span>
</span>
</a>
</span>
<span *ngIf="putCodes && putCodes.length > 0"
[attr.uk-tooltip]="(!isLoggedIn) ? tooltipNoLoggedInUser : tooltipDelete"
class="uk-margin-remove-bottom">
<a (click)="currentAction='delete'; deleteWorks();"
[class]="'uk-button uk-button-link uk-flex uk-flex-middle uk-flex-right@s uk-margin-right '+ (showLoading ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading" name="delete" ratio="0.8" flex="true"></icon>
<span *ngIf="showLoading" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span class="uk-margin-small-left uk-flex uk-flex-middle">Delete from&#160;
<span class="uk-flex uk-flex-middle">
<span>ORCID&#160;</span>
<img src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="" loading="lazy">&#160;
</span>
</span>
</a>
</span>
</ng-container>
<ng-container *ngIf="pageType == 'landing'">
<span *ngIf="!putCodes || putCodes.length == 0"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'"
[title]="(!pids || !isLoggedIn) ? (!pids ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipAdd">
<a *ngIf="!showLoading" (click)="currentAction='add'; saveWorkPreparation();"
class="uk-icon-button uk-icon landing-action-button landing-action-button-orcid"
[class.uk-disabled]="showLoading || !isLoggedIn || !pids"
[attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'"
[title]="((!pids && (!identifiers || identifiers.size == 0)) || !isLoggedIn) ? ((!pids && (!identifiers || identifiers.size == 0)) ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipAdd">
<a (click)="currentAction='add'; saveWorkPreparation();"
class="uk-flex uk-flex-middle uk-button-link"
[ngClass]="isMobile && !(pageType == 'landing') ? 'uk-margin-left' : 'uk-flex-center'"
[class.uk-text-bolder]="!(isMobile && pageType == 'landing')"
[class.uk-disabled]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
[class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
(mouseover)="hoverEvent($event)" (mouseout)="hoverEvent($event)">
<icon *ngIf="!hoverAdd" name="orcid_add" ratio="1.1" visuallyHidden="add"></icon>
<icon *ngIf="hoverAdd" name="add" visuallyHidden="add"></icon>
<icon *ngIf="!showLoading" [class.text-orcid]="!showLoading && isLoggedIn && (pids || identifiers?.size > 0)"
[class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))" name="orcid_add" ratio="1"
visuallyHidden="add"></icon>
<span *ngIf="showLoading" class="uk-icon"><loading
[top_margin]="false" [size]="'small'"></loading></span>
<span [ngClass]="(isMobile && pageType == 'landing') ? 'uk-margin-small-left' : 'uk-margin-xsmall-left'">Claim</span>
</a>
<span *ngIf="showLoading" class="uk-icon icon-button uk-icon-button-small"><loading
[top_margin]="false" [size]="'small'"></loading></span>
</span>
<span *ngIf="putCodes && putCodes.length > 0"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'"
[title]="(!pids || !isLoggedIn) ? (!pids ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipDelete">
<a *ngIf="!showLoading" (click)="currentAction='delete'; deleteWorks();"
class="uk-icon-button uk-icon landing-action-button landing-action-button-orcid"
[class.uk-disabled]="showLoading || !isLoggedIn || !pids"
[attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'"
[title]="((!pids && (!identifiers || identifiers.size == 0)) || !isLoggedIn) ? ((!pids && (!identifiers || identifiers.size == 0)) ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipDelete">
<a (click)="currentAction='delete'; deleteWorks();"
class="uk-flex uk-flex-middle uk-button-link"
[ngClass]="isMobile && !(pageType == 'landing') ? 'uk-margin-left' : 'uk-flex-center'"
[class.uk-text-bolder]="!(isMobile && pageType == 'landing')"
[class.uk-disabled]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
[class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
(mouseover)="hoverEvent($event, 'delete')" (mouseout)="hoverEvent($event, 'delete')">
<icon *ngIf="!showLoading" [class.text-orcid]="!showLoading && isLoggedIn && (pids || identifiers?.size > 0)"
[class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))" name="orcid_bin" ratio="1"
visuallyHidden="delete"></icon>
<span *ngIf="showLoading" class="uk-icon"><loading
[top_margin]="false" [size]="'small'"></loading></span>
<span [ngClass]="(isMobile && pageType == 'landing') ? 'uk-margin-small-left' : 'uk-margin-xsmall-left'">Remove</span>
</a>
</span>
<!-- Old 'remove' code -->
<!-- <span *ngIf="putCodes && putCodes.length > 0"
[attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'"
[title]="(!pids || !isLoggedIn) ? (!pids ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipDelete">
<a *ngIf="!showLoading" (click)="currentAction='delete'; deleteWorks();"
class="uk-icon-button uk-icon landing-action-button landing-action-button-orcid"
[class.uk-disabled]="showLoading || !isLoggedIn || !pids"
(mouseover)="hoverEvent($event, 'delete')" (mouseout)="hoverEvent($event, 'delete')">
<icon *ngIf="!hoverDelete" name="orcid_bin" ratio="1.1" visuallyHidden="delete"></icon>
<icon *ngIf="hoverDelete" name="delete_outline" class="uk-text-danger" visuallyHidden="delete"></icon>
</a>
<span *ngIf="showLoading" class="uk-icon icon-button uk-icon-button-small"><loading
[top_margin]="false" [size]="'small'"></loading></span>
</span>
</span> -->
</ng-container>
<modal-alert #grantModal [overflowBody]=false (alertOutput)="openGrantWindow()">
<modal-alert *ngIf="!isMobile" #grantModal [overflowBody]=false (alertOutput)="openGrantWindow()">
<div>
<div>{{requestGrantMessage}}</div>
<!-- <div class="uk-margin-medium-top uk-align-right">-->
<!-- <button (click)="closeGrantModal()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-button-default">-->
<!-- <span>Cancel</span>-->
<!-- </button>-->
<!-- <div class="uk-margin-medium-top uk-align-right">-->
<!-- <button (click)="closeGrantModal()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-button-default">-->
<!-- <span>Cancel</span>-->
<!-- </button>-->
<!-- <button (click)="openGrantWindow()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left uk-button-primary">-->
<!-- <span>Grant OpenAIRE</span>-->
<!-- </button>-->
<!-- <button (click)="openGrantWindow()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left uk-button-primary">-->
<!-- <span>Grant OpenAIRE</span>-->
<!-- </button>-->
<!--&lt;!&ndash; <button (click)="openGrantWindow()" type="submit"&ndash;&gt;-->
<!--&lt;!&ndash; class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left orcid-button">&ndash;&gt;-->
<!--&lt;!&ndash; <img src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="">{{" "}}&ndash;&gt;-->
<!--&lt;!&ndash; <span>Create or Connect your ORCID iD</span>&ndash;&gt;-->
<!--&lt;!&ndash; </button>&ndash;&gt;-->
<!-- </div>-->
<!--&lt;!&ndash; <button (click)="openGrantWindow()" type="submit"&ndash;&gt;-->
<!--&lt;!&ndash; class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left orcid-button">&ndash;&gt;-->
<!--&lt;!&ndash; <img src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="">{{" "}}&ndash;&gt;-->
<!--&lt;!&ndash; <span>Create or Connect your ORCID iD</span>&ndash;&gt;-->
<!--&lt;!&ndash; </button>&ndash;&gt;-->
<!-- </div>-->
</div>
</modal-alert>
<fs-modal *ngIf="isMobile" #grantFsModal classTitle="uk-tile-default uk-border-bottom">
<div>{{requestGrantMessage}}</div>
<button class="uk-margin-medium-top uk-button uk-button-primary uk-align-center" (click)="openGrantWindow()">
Grant OpenAIRE
</button>
</fs-modal>
<ng-container *ngIf="pageType == 'my_search'">
@ -113,27 +111,29 @@ declare var UIkit: any;
<img src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="" loading="lazy">
<span>&#160;ACTIONS</span>
</span>
<span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0)
<span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0)
? 'This work is currently deleted.'
: 'View this work from your ORCID record'">
<a (click)="currentAction='get'; getOrcidWorks()"
[class]="'uk-button uk-button-default action uk-flex uk-flex-middle '+ ((showLoading || !putCodes || putCodes.length == 0) ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='get'" name="visibility" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='get'" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span *ngIf="showLoading && currentAction=='get'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">View ORCID work</span>
</a>
</span>
<span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0)
<span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0)
? 'This work is currently deleted.'
: ('Update this work to your ORCID record' + ((properties.environment == 'beta') ? '. The action will affect your real ORCID iD.' : '')
: ('Update this work to your ORCID record' + ((properties.environment == 'beta') ? '. The action will affect your real ORCID iD.' : '')
+ showUpdateDatesInTooltip())">
<a (click)="currentAction='update'; updateWorkPreparation()"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ ((showLoading || !putCodes || putCodes.length == 0) ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='update'" name="refresh" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='update'" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span *ngIf="showLoading && currentAction=='update'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">Update ORCID work</span>
</a>
</span>
@ -143,8 +143,9 @@ declare var UIkit: any;
<a (click)="currentAction='add'; saveWorkPreparation();"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ (showLoading ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='add'" name="add" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='add'" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span class="uk-margin-small-left">Add to ORCID</span>
<span *ngIf="showLoading && currentAction=='add'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">Claim</span>
</a>
</span>
@ -153,8 +154,9 @@ declare var UIkit: any;
<a (click)="currentAction='delete'; deleteWorks();"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ (showLoading ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='delete'" name="delete" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='delete'" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span class="uk-margin-small-left">Delete from ORCID</span>
<span *ngIf="showLoading && currentAction=='delete'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">Remove</span>
</a>
</span>
</ng-container>
@ -173,9 +175,9 @@ declare var UIkit: any;
<div class="uk-card uk-card-default uk-padding uk-card-hover">
<div>{{work.title?.title?.value}}</div>
<div>{{work.title?.subtitle?.value}}</div>
<div class="uk-text-uppercase">{{work['journal-title']?.value}}</div>
<div *ngIf="work['publication-date'] || work['type']" class="uk-text-small uk-margin-small-bottom">
<span *ngIf="work['publication-date']">
<span *ngIf="work['publication-date']['year'] && work['publication-date']['year'].value">
@ -209,11 +211,11 @@ declare var UIkit: any;
{{work['short-description']}}
</p>
</div>
<div *ngIf="work['external-ids'] && work['external-ids']['external-id']" class="uk-margin-small-bottom">
<showIdentifiers [identifiers]="parseIdentifiers(work['external-ids']['external-id'])"></showIdentifiers>
</div>
<div *ngIf="work['contributors'] && work['contributors']['contributor']">
<div *ngFor="let contributor of work['contributors']['contributor']">
<span *ngIf="contributor['credit-name'] && contributor['credit-name'].value">
@ -223,24 +225,26 @@ declare var UIkit: any;
(contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-role'])
||
(contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-sequence'])
||
||
(contributor['contributor-orcid'] && contributor['contributor-orcid']['path'])
)">
(
</span>
<span *ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-role']">
<span
*ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-role']">
{{contributor['contributor-attributes']['contributor-role']}}
</span>
<span *ngIf="(contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-role'])
<span *ngIf="(contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-role'])
&& (contributor['contributor-attributes']['contributor-sequence'] || (contributor['contributor-orcid'] && contributor['contributor-orcid']['path']))">
,
</span>
<span *ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-sequence']">
<span
*ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-sequence']">
{{contributor['contributor-attributes']['contributor-sequence']}}
</span>
<span *ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-sequence']
<span *ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-sequence']
&& contributor['contributor-orcid'] && contributor['contributor-orcid']['path']">
,
,
</span>
<span *ngIf="contributor['contributor-orcid'] && contributor['contributor-orcid']['path']">
{{contributor['contributor-orcid']?.path}}
@ -261,33 +265,58 @@ declare var UIkit: any;
<modal-alert #propagationModal (alertOutput)="confirmedPropagation()">
<div>
This {{openaireEntities.RESULT}} is the result of <span class="uk-text-bold"> merged {{openaireEntities.RESULTS}} in OpenAIRE</span>.
This {{openaireEntities.RESULT}} is the result of <span
class="uk-text-bold"> merged {{openaireEntities.RESULTS}} in OpenAIRE</span>.
<br><br>
You have already added <span class="uk-text-bold">{{this.putCodes?.length}} works</span> in your ORCID record related to the merged {{openaireEntities.RESULT}}.
You have already added <span class="uk-text-bold">{{this.putCodes?.length}} works</span> in your ORCID record
related to the merged {{openaireEntities.RESULT}}.
<div *ngIf="currentAction == 'delete'">
If you continue with delete action, <span class="uk-text-bold">all these works will be deleted</span>.
</div>
<div *ngIf="currentAction == 'update'">
If you continue with update action, <span class="uk-text-bold">all these works will be deleted and a new merged work will be added</span> instead.
If you continue with update action, <span class="uk-text-bold">all these works will be deleted and a new merged work will be added</span>
instead.
</div>
</div>
<!-- <div class="uk-margin-medium-top uk-align-right">-->
<!-- <button (click)="closePropagationModal()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-button-default">-->
<!-- <span>Cancel</span>-->
<!-- </button>-->
<!-- <div class="uk-margin-medium-top uk-align-right">-->
<!-- <button (click)="closePropagationModal()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-button-default">-->
<!-- <span>Cancel</span>-->
<!-- </button>-->
<!-- <button (click)="confirmedPropagation()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left uk-button-primary">-->
<!-- <span>Continue</span>-->
<!-- </button>-->
<!-- </div>-->
<!-- <button (click)="confirmedPropagation()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left uk-button-primary">-->
<!-- <span>Continue</span>-->
<!-- </button>-->
<!-- </div>-->
</modal-alert>
<fs-modal #propagationFsModal classTitle="uk-tile-default uk-border-bottom">
<div>
This {{openaireEntities.RESULT}} is the result of <span
class="uk-text-bold"> merged {{openaireEntities.RESULTS}} in OpenAIRE</span>.
<br><br>
You have already added <span class="uk-text-bold">{{this.putCodes?.length}} works</span> in your ORCID record
related to the merged {{openaireEntities.RESULT}}.
<div *ngIf="currentAction == 'delete'">
If you continue with delete action, <span class="uk-text-bold">all these works will be deleted</span>.
</div>
<div *ngIf="currentAction == 'update'">
If you continue with update action, <span class="uk-text-bold">all these works will be deleted and a new merged work will be added</span>
instead.
</div>
</div>
<button class="uk-margin-medium-top uk-button uk-button-primary uk-align-center" (click)="confirmedPropagation()">
Continue
</button>
</fs-modal>
`
})
export class OrcidWorkComponent {
@Input() isMobile: boolean = false;
@Input() resultId: string = "";
@Input() resultTitle: string = "";
@Input() resultLandingInfo: ResultLandingInfo;
@ -299,54 +328,56 @@ export class OrcidWorkComponent {
@Input() updateDates: string[] = [];
@Input() givenPutCode: boolean = false;
@Input() pageType: string = "search";
public subscriptions: Subscription[] = [];
@ViewChild('workModal') workModal;
// @ViewChild('saveWorkModal') saveWorkModal;
@ViewChild('grantModal') grantModal;
@ViewChild('grantFsModal') grantFsModal: FullScreenModalComponent;
// @ViewChild('messageModal') messageModal;
@ViewChild('propagationModal') propagationModal;
@ViewChild('propagationFsModal') propagationFsModal;
public requestGrant: boolean = false;
public requestGrantMessage: string = "Please grant OpenAIRE to access and update your ORCID works.";
private tokenUrl: string;
public message: string = "";
public showLoading: boolean = false;
public works: any[] = [];
public orcidWorks: any[] = [];
public window: any;
public isLoggedIn: boolean = false;
public currentAction: string = "";
public hoverAdd: boolean = false;
public hoverDelete: boolean = false;
public properties: EnvProperties = properties;
public openaireEntities = OpenaireEntities;
constructor(private route: ActivatedRoute,
private _router: Router,
private orcidService: OrcidService,
private resultLandingService: ResultLandingService,
private userManagementService: UserManagementService) {
if(typeof document !== 'undefined') {
if (typeof document !== 'undefined') {
this.tokenUrl = properties.orcidTokenURL
+ "client_id="+properties.orcidClientId
+ "client_id=" + properties.orcidClientId
// + "&response_type=code&scope=/activities/update"
// + "&response_type=code&scope=/authenticate /activities/update /person/update /read-limited"
+ "&response_type=code&scope=/activities/update /read-limited"
+ "&redirect_uri="+location.origin+"/orcid?source=openaire";
+ "&redirect_uri=" + location.origin + "/orcid?source=openaire";
}
}
ngOnInit() {
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
if (user) {
this.isLoggedIn = true;
if(!this.givenPutCode) {
if (!this.givenPutCode) {
this.getPutCode();
}
} else {
@ -356,7 +387,7 @@ export class OrcidWorkComponent {
this.isLoggedIn = false;
}));
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
@ -365,16 +396,16 @@ export class OrcidWorkComponent {
}
});
}
public showUpdateDatesInTooltip() {
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
let response: string = "";
if(this.updateDates != null && this.updateDates.length > 0) {
if (this.updateDates != null && this.updateDates.length > 0) {
response += "<br><br> Last update in ORCID<br>";
for(let i=0; i<this.updateDates.length; i++) {
for (let i = 0; i < this.updateDates.length; i++) {
let date: Date = new Date(this.updateDates[i]);
response += "<span>"+date.getDate() + " " + monthNames[date.getMonth()] + " " + date.getFullYear();
if(i < this.updateDates.length - 1) {
response += "<span>" + date.getDate() + " " + monthNames[date.getMonth()] + " " + date.getFullYear();
if (i < this.updateDates.length - 1) {
response += "& ";
}
response += "</span>";
@ -382,29 +413,34 @@ export class OrcidWorkComponent {
}
return response;
}
public parseIdentifiers(identifiers: ExternalIDV3_0[]): Map<string, string[]> {
let identifiersMap: Map<string, string[]> = new Map<string, string[]>();
for(let identifier of identifiers) {
if(!identifiersMap.has(identifier['external-id-type'])) {
for (let identifier of identifiers) {
if (!identifiersMap.has(identifier['external-id-type'])) {
identifiersMap.set(identifier['external-id-type'], new Array<string>());
}
identifiersMap.get(identifier['external-id-type']).push(identifier['external-id-value']);
}
return identifiersMap;
}
openGrantWindow() {
if(!Session.isLoggedIn()){
if (!Session.isLoggedIn()) {
//this.userValidMessage = "User session has expired. Please login again.";
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
// this.tokenUrl = location.origin+"/orcid";
this.window = window.open(this.tokenUrl, '_blank',
'location=yes,height=700,width=540,left=500,top=100,scrollbars=yes,status=yes');
// this.requestGrant = false;
this.closeGrantModal();
let self = this;
window.onmessage = function (ev) {
if (ev.isTrusted && ev.origin == location.origin && ev.data == 'success') {
@ -426,17 +462,17 @@ export class OrcidWorkComponent {
}
}
}
private getPutCode() {
this.subscriptions.push(this.orcidService.getPutCode(this.pids).subscribe(
putCodes => {
this.putCodes = putCodes;
}, error => {
}
))
}
private getResultLandingInfo(action: string) {
this.subscriptions.push(this.resultLandingService.getResultLandingInfo(this.resultId, null, this.type, null, properties).subscribe(
resultLandingInfo => {
@ -448,7 +484,7 @@ export class OrcidWorkComponent {
}
this.pids = pidsArray.join();
}
if(action == "save") {
if (action == "save") {
this.saveWork();
} else if (action == "update") {
this.updateWork();
@ -460,18 +496,23 @@ export class OrcidWorkComponent {
}
))
}
public saveWorkPreparation() {
if(!Session.isLoggedIn()){
if (!Session.isLoggedIn()) {
//this.userValidMessage = "User session has expired. Please login again.";
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
if (this.requestGrant) {
this.openGrantModal("Add, delete or edit work in your ORCID record");
} else {
this.showLoading = true;
if (this.resultLandingInfo) {
this.saveWork();
} else {
@ -480,42 +521,42 @@ export class OrcidWorkComponent {
}
}
}
private saveWork() {
this.subscriptions.push(this.orcidService.saveWork(this.resultLandingInfo, this.pids).subscribe(
response => {
// for testing only
// this.openGrantModal("Add work in your ORCID record");
// this.requestGrant = true;
// this.requestGrantMessage = "Please grant OpenAIRE to access and update your ORCID record and works.";
if(response == null) {
if (response == null) {
this.handleError(null);
console.error("Error posting landing info: null");
} else {
this.putCodes.push(""+response['put-code']);
this.putCodes.push("" + response['put-code']);
this.creationDates.push(response['created-date']['value']);
this.updateDates.push(response['last-modified-date']['value']);
// this.closeGrantModal();
// this.message = "You have successfully added work with pids: "+this.pids+" in your ORCID record!";
this.message = "You have successfully added work \""+this.resultTitle+"\" in your ORCID record!";
this.message = "You have successfully added work \"" + this.resultTitle + "\" in your ORCID record!";
// this.openMessageModal("Work added successfully");
// message: 'You have <strong>successfully added</strong> work with pids: <strong>'+this.pids+'</strong> in your ORCID record!',
UIkit.notification({
message: 'You have <strong>successfully added</strong> work "<strong>'+this.resultTitle+'</strong>" in your ORCID record!'
// +
// '<br><br><a class="uk-link" [href]="goToOrcidLinksPage()">Manager your ORCID links</a>'
message: 'You have <strong>successfully added</strong> work "<strong>' + this.resultTitle + '</strong>" in your ORCID record!'
// +
// '<br><br><a class="uk-link" [href]="goToOrcidLinksPage()">Manager your ORCID links</a>'
,
// '<br><br><a class="uk-link" (click)="goToOrcidLinksPage()">Manager your ORCID links</a>',
// '<br><br><a class="uk-link" routerLinkActive="router-link-active" [routerLink]="myOrcidLinksPage">Manager your ORCID links</a>',
// '<br><br><a class="uk-link" (click)="goToOrcidLinksPage()">Manager your ORCID links</a>',
// '<br><br><a class="uk-link" routerLinkActive="router-link-active" [routerLink]="myOrcidLinksPage">Manager your ORCID links</a>',
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this.showLoading = false;
}
},
@ -525,23 +566,28 @@ export class OrcidWorkComponent {
}
));
}
goToOrcidLinksPage() {
this._router.navigate([this.properties.myOrcidLinksPage]);
}
private updateWorkPreparation() {
if(!Session.isLoggedIn()){
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
if (this.requestGrant) {
this.openGrantModal("Add, delete or edit work in your ORCID record");
} else if(this.putCodes.length > 1) {
} else if (this.putCodes.length > 1) {
this.openPropagationModal("Update ORCID work");
} else {
this.showLoading = true;
if (this.resultLandingInfo) {
this.updateWork();
} else {
@ -550,18 +596,18 @@ export class OrcidWorkComponent {
}
}
}
private updateWork() {
this.subscriptions.push(this.orcidService.updateWork(this.resultLandingInfo, this.pids, this.putCodes[0]).subscribe(
response => {
if(response) {
if (response) {
this.updateDates[0] = response['last-modified-date'].value;
// message: 'You have <strong>successfully updated</strong> work with pids: <strong>' + this.pids + '</strong> in your ORCID record!',
UIkit.notification({
message: 'You have <strong>successfully updated</strong> work "<strong>' + this.resultTitle + '</strong>" in your ORCID record!'
// +
// '<br><br><a routerLinkActive="router-link-active" [routerLink]="myOrcidLinksPage">Manager your ORCID links</a>'
// +
// '<br><br><a routerLinkActive="router-link-active" [routerLink]="myOrcidLinksPage">Manager your ORCID links</a>'
,
status: 'success',
timeout: 6000,
@ -576,36 +622,41 @@ export class OrcidWorkComponent {
}
));
}
public confirmedPropagation() {
this.propagationModal.cancel();
this.deleteWorks(true);
//}
// if(this.currentAction == "update") {
// this.saveWork();
// }
}
public getOrcidWorks() {
if(!Session.isLoggedIn()){
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
this.showLoading = true;
this.subscriptions.push(this.orcidService.getOrcidWorks(this.putCodes).subscribe(
(response) => {
let error: boolean = true;
if(response && response['bulk']) {
if (response && response['bulk']) {
response = response['bulk'].filter(res => {
return (!res.error && res.work);
});
if(response && response.length > 0) {
if (response && response.length > 0) {
error = false;
this.orcidWorks = response;
this.openWorkModal();
}
}
if(error) {
if (error) {
UIkit.notification({
message: 'There was an error getting this work. </br> Please make sure you have not deleted it from your ORCID iD.',
status: 'warning',
@ -622,20 +673,25 @@ export class OrcidWorkComponent {
));
}
}
public deleteWorks(confirmed: boolean = false) {
if(!Session.isLoggedIn()){
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
if (this.requestGrant) {
this.openGrantModal("Add, delete or edit work in your ORCID record");
} else if(this.putCodes.length > 1 && !confirmed) {
} else if (this.putCodes.length > 1 && !confirmed) {
this.openPropagationModal("Delete ORCID work");
} else {
this.showLoading = true;
if (!this.resultLandingInfo && this.identifiers) {
let pidsArray: string[] = [];
for (let key of Array.from(this.identifiers.keys())) {
@ -643,11 +699,11 @@ export class OrcidWorkComponent {
}
this.pids = pidsArray.join();
}
this.subscriptions.push(this.orcidService.deleteWorks(this.putCodes).subscribe(
deletedPutCodes => {
let deletedAll: boolean = true;
if (deletedPutCodes) {
for (let i = 0; i < deletedPutCodes.length; i++) {
let deletedPutCode = deletedPutCodes[i];
@ -663,24 +719,24 @@ export class OrcidWorkComponent {
} else {
deletedAll = false;
}
if (!deletedAll) {
this.handleError(null);
console.error("Error deleting landing info: null");
} else {
if(this.currentAction == "update") {
if (this.currentAction == "update") {
this.saveWork();
} else {
// this.closeGrantModal();
// this.message = "You have successfully deleted work with pids: " + this.pids + " from your ORCID record!";
this.message = "You have successfully deleted work \"" + this.resultTitle + "\" from your ORCID record!";
// this.openMessageModal("Work deleted successfully");
// message: 'You have <strong>successfully deleted</strong> work with pids: <strong>' + this.pids + '</strong> from your ORCID record!',
UIkit.notification({
message: 'You have <strong>successfully deleted</strong> work "<strong>' + this.resultTitle + '</strong>" from your ORCID record!'
// +
// '<br><br><a routerLinkActive="router-link-active" [routerLink]="myOrcidLinksPage">Manager your ORCID links</a>'
// +
// '<br><br><a routerLinkActive="router-link-active" [routerLink]="myOrcidLinksPage">Manager your ORCID links</a>'
,
status: 'success',
timeout: 6000,
@ -698,31 +754,37 @@ export class OrcidWorkComponent {
}
}
}
openGrantModal(title: string) {
this.grantModal.cancelButton = true;
this.grantModal.okButton = true;
this.grantModal.okButtonText = "Grant OpenAIRE";
this.grantModal.okButtonLeft = false;
this.grantModal.alertTitle = title;
this.grantModal.open();
if(this.isMobile) {
this.grantFsModal.okButton = false;
this.grantFsModal.title = title;
this.grantFsModal.open();
} else {
this.grantModal.cancelButton = true;
this.grantModal.okButton = true;
this.grantModal.okButtonText = "Grant OpenAIRE";
this.grantModal.okButtonLeft = false;
this.grantModal.alertTitle = title;
this.grantModal.open();
}
}
closeGrantModal() {
this.grantModal.cancel();
}
openWorkModal() {
this.workModal.cancelButton = false;
this.workModal.okButton = false;
this.workModal.alertTitle = "Work in your ORCID record";
this.workModal.open();
}
closeWorkModal() {
this.workModal.cancel();
}
// openMessageModal(title: string) {
// this.messageModal.cancelButton = false;
// this.messageModal.okButton = false;
@ -733,52 +795,58 @@ export class OrcidWorkComponent {
// closeMessageModal() {
// this.messageModal.cancel();
// }
openPropagationModal(title: string) {
this.propagationModal.cancelButton = true;
this.propagationModal.okButton = true;
this.propagationModal.okButtonText = "Continue";
this.propagationModal.okButtonLeft = false;
this.propagationModal.alertTitle = title;
this.propagationModal.open();
if(this.isMobile) {
this.propagationFsModal.okButton = false;
this.propagationFsModal.title = title;
this.propagationFsModal.open();
} else {
this.propagationModal.cancelButton = true;
this.propagationModal.okButton = true;
this.propagationModal.okButtonText = "Continue";
this.propagationModal.okButtonLeft = false;
this.propagationModal.alertTitle = title;
this.propagationModal.open();
}
}
closePropagationModal() {
this.propagationModal.cancel();
}
handleError(error) {
if(error && error.status == "401") {
if (error && error.status == "401") {
this.openGrantModal("Add, delete or edit work in your ORCID record");
this.requestGrant = true;
this.requestGrantMessage = "Please grant OpenAIRE to access and update your ORCID record and works. ";
// + "If you have already granted OpenAIRE, you just need to login again to ORCID!";
} else if(error && error.status == "403") {
// + "If you have already granted OpenAIRE, you just need to login again to ORCID!";
} else if (error && error.status == "403") {
this.openGrantModal("Add, delete or edit work in your ORCID record");
this.requestGrant = true;
this.requestGrantMessage = "Please login again to ORCID."
// this.openGrantModal();
} else {
this.message = "";
if(error && error.status == "409") {
if (error && error.status == "409") {
this.message = "There is <span class='uk-text-bold'>already a work in your ORCID record</span> with the same information of the work you are trying to add now. <br><br>";
}
if(this.currentAction == "get") {
if (this.currentAction == "get") {
// this.message += "There was an <span class='uk-text-bold'>error getting</span> work with pids: <span class='uk-text-bold'>" + this.pids + "</span> from your ORCID record. <br> Please try again later.";
this.message += "There was an <span class='uk-text-bold'>error getting</span> work \"<span class='uk-text-bold'>" + this.resultTitle + "</span>\" from your ORCID record. <br> Please try again later.";
} else if(this.currentAction == "add") {
} else if (this.currentAction == "add") {
// this.message += "There was an <span class='uk-text-bold'>error adding</span> work with pids: <span class='uk-text-bold'>"+this.pids+"</span> to your ORCID record. <br> Please try again later.";
this.message += "There was an <span class='uk-text-bold'>error adding</span> work with pids: \"<span class='uk-text-bold'>"+this.pids+"</span>\" to your ORCID record. <br> Please try again later.";
} else if(this.currentAction == "update") {
this.message += "There was an <span class='uk-text-bold'>error adding</span> work with pids: \"<span class='uk-text-bold'>" + this.pids + "</span>\" to your ORCID record. <br> Please try again later.";
} else if (this.currentAction == "update") {
// this.message += "There was an <span class='uk-text-bold'>error updating</span> work with pids: <span class='uk-text-bold'>"+this.pids+"</span> to your ORCID record. <br> Please try again later.";
this.message += "There was an <span class='uk-text-bold'>error updating</span> work \"<span class='uk-text-bold'>"+this.resultTitle+"</span>\" to your ORCID record. <br> Please try again later.";
} else if(this.currentAction == "delete") {
this.message += "There was an <span class='uk-text-bold'>error updating</span> work \"<span class='uk-text-bold'>" + this.resultTitle + "</span>\" to your ORCID record. <br> Please try again later.";
} else if (this.currentAction == "delete") {
// this.message += "There was an <span class='uk-text-bold'>error deleting</span> work with pids: <span class='uk-text-bold'>"+this.pids+"</span> from your ORCID record. <br> Please try again later.";
this.message += "There was an <span class='uk-text-bold'>error deleting</span> work \"<span class='uk-text-bold'>"+this.resultTitle+"</span>\" from your ORCID record. <br> Please try again later.";
this.message += "There was an <span class='uk-text-bold'>error deleting</span> work \"<span class='uk-text-bold'>" + this.resultTitle + "</span>\" from your ORCID record. <br> Please try again later.";
} else {
this.message += "There was an error. Please try again later."
}
UIkit.notification({
message: this.message,
status: 'danger',
@ -789,28 +857,28 @@ export class OrcidWorkComponent {
}
this.showLoading = false;
}
get tooltipAdd() {
return "Add this work to your <span class=\"text-orcid\">ORCID</span> record" + ((properties.environment == "beta") ? ". The action will affect your real ORCID iD." : "");
}
get tooltipDelete() {
return "Delete this work from your <span class=\"text-orcid\">ORCID</span> record" + ((properties.environment == "beta") ? ". The action will affect your real ORCID iD." : "");
}
get tooltipNoPid() {
return "Only resources with a PID (persistent identifier) like DOI, handle, PMID can be added or deleted from your <span class=\"text-orcid\">ORCID</span> record";
}
get tooltipNoLoggedInUser() {
return "Add or delete a work from your <span class=\"text-orcid\">ORCID</span> record. Please log in first."
return "Add or delete a work from your <span class=\"text-orcid\">ORCID</span> record. Please log in first."
}
hoverEvent($event, action: string = "add") {
if(action == "add") {
if (action == "add") {
this.hoverAdd = $event.type == "mouseover";
this.hoverDelete = false;
} else if(action == "delete") {
} else if (action == "delete") {
this.hoverDelete = $event.type == "mouseover";
this.hoverAdd = false;
}

View File

@ -15,11 +15,12 @@ import {ResultLandingUtilsModule} from '../landingPages/landing-utils/resultLand
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";
@NgModule({
imports: [
CommonModule, RouterModule, AlertModalModule, LoadingModule, ResultLandingUtilsModule,
IconsModule
IconsModule, FullScreenModalModule
],
declarations: [
OrcidComponent,

View File

@ -3,7 +3,7 @@
@sdgs: #E6233D, #DF9F00, #19A220, #D70023, #FF0B00, #00BFE8, #FFC300, #B10240, #FF5D00,
#F50D86, #FF8A00, #CA8A03, #2B772B, #0098DF, #00B91C, #0069A2, #1C336A;
custom-sdg-dot:after {
.custom-sdg-dot:after {
content: "";
background-image: url("~src/assets/common-assets/sdg/sdg-dot-img.svg");
display: inline-block;

View File

@ -10,12 +10,13 @@
<div class="uk-grid uk-flex uk-flex-middle uk-flex-center" uk-grid>
<div class="uk-width-1-1 uk-width-auto@m"><div id="searchImage"></div></div>
<advanced-search-form class="uk-width-expand uk-padding-remove-vertical"
entityType="all"
[entityType]="activeEntity"
[advancedSearchLink]="advancedSearchLink" [advancedSearchLinkParameters]="parameters"
(queryChange)="keywordChanged($event)"
[isDisabled]="disableForms"
[simpleView]="true" [formPlaceholderText]="formPlaceholderText"
[selectedFields]="selectedFields" [showSwitchSearchLink]="true" [dark]="searchForm.dark"
[fieldIdsMap]="fieldIdsMap" [fieldIds]="fieldIds" [entitiesSelection]="true" [customFilter]="customFilter"
[fieldIdsMap]="fieldIdsMap" [fieldIds]="fieldIds" [entitiesSelection]="false" [customFilter]="customFilter"
>
</advanced-search-form>
</div>
@ -26,9 +27,10 @@
</div>
<schema2jsonld *ngIf="name && logoURL" [URL]="properties.domain+ properties.baseLink +'/search/find'"
[logoURL]="properties.domain + properties.baseLink+logoURL" type="search" [name]=name
description="Search for {{openaireEntities.RESULTS}} ({{openaireEntities.PUBLICATIONS}}, {{openaireEntities.DATASETS}}, {{openaireEntities.SOFTWARE}}, {{openaireEntities.OTHER}}), {{openaireEntities.PROJECTS}}, {{openaireEntities.ORGANIZATIONS}}, {{openaireEntities.DATASOURCES}} in the OpenAIRE Research Graph. "></schema2jsonld>
<div class="uk-container-large uk-container uk-margin-large-top uk-margin-medium-bottom">
<div class="uk-width-1-1" uk-slider="finite: true">
description="Search for {{openaireEntities.RESULTS}} ({{openaireEntities.PUBLICATIONS}}, {{openaireEntities.DATASETS}}, {{openaireEntities.SOFTWARE}}, {{openaireEntities.OTHER}}), {{openaireEntities.PROJECTS}}, {{openaireEntities.ORGANIZATIONS}}, {{openaireEntities.DATASOURCES}} in the OpenAIRE Graph. "></schema2jsonld>
<div class="uk-container-large uk-container uk-margin-top">
<div class="uk-width-1-1 uk-background-default uk-padding-small uk-padding-remove-horizontal"
uk-slider="finite: true" uk-sticky="media: @m" [attr.offset]="offset">
<div class="uk-position-relative">
<div class="uk-slider-container">
<ul class="uk-slider-items uk-flex uk-flex-center" style="flex-wrap: nowrap !important;">
@ -37,7 +39,7 @@
<li [class.uk-active]="activeEntity == 'result'">
<a class="uk-text-uppercase">
{{resultsName}}
<span *ngIf=" fetchPublications.searchUtils.totalResults!=null">
<span *ngIf=" fetchPublications.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchPublications.searchUtils.totalResults | number}})</span>
</a>
</li>
@ -48,7 +50,7 @@
<li [class.uk-active]="activeEntity == 'projects'">
<a class="uk-text-uppercase">
{{projectName}}
<span *ngIf="fetchProjects.searchUtils.totalResults!=null">
<span *ngIf="fetchProjects.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchProjects.searchUtils.totalResults | number}})</span>
</a>
</li>
@ -59,7 +61,7 @@
<li [class.uk-active]="activeEntity == 'datasources'">
<a class="uk-text-uppercase">
{{dataSourcesName}}
<span *ngIf="fetchDataproviders.searchUtils.totalResults!=null">
<span *ngIf="fetchDataproviders.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchDataproviders.searchUtils.totalResults | number}})</span>
</a>
</li>
@ -70,7 +72,7 @@
<li [class.uk-active]="activeEntity == 'services'">
<a class="uk-text-uppercase">
{{servicesName}}
<span *ngIf="fetchServices.searchUtils.totalResults!=null">
<span *ngIf="fetchServices.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchServices.searchUtils.totalResults | number}})</span>
</a>
</li>
@ -81,7 +83,7 @@
<li [class.uk-active]="activeEntity == 'organizations'">
<a class="uk-text-uppercase">
{{organizationsName}}
<span *ngIf="fetchOrganizations.searchUtils.totalResults!=null">
<span *ngIf="fetchOrganizations.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchOrganizations.searchUtils.totalResults | number}})</span>
</a>
</li>
@ -99,25 +101,25 @@
<search-research-results *ngIf="activeEntity == 'result'" resultType="result" [includeOnlyResultsAndFilter]="true"
(searchPageUpdates)="activeEntityUpdate($event)" [showSwitchSearchLink]="false"
simpleSearchLink="/search/find" [customFilter]="customFilter"></search-research-results>
[simpleSearchLink]="properties.searchLinkToResults" [customFilter]="customFilter"></search-research-results>
<search-projects *ngIf="activeEntity == 'projects'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false"
(searchPageUpdates)="activeEntityUpdate($event)"
simpleSearchLink="/search/find" [customFilter]="customFilter">
[simpleSearchLink]="properties.searchLinkToProjects" [customFilter]="customFilter">
</search-projects>
<search-organizations *ngIf="activeEntity == 'organizations'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false"
(searchPageUpdates)="activeEntityUpdate($event)"
simpleSearchLink="/search/find" [customFilter]="customFilter">
[simpleSearchLink]="properties.searchLinkToOrganizations" [customFilter]="customFilter">
</search-organizations>
<search-dataproviders *ngIf="activeEntity == 'datasources'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false"
(searchPageUpdates)="activeEntityUpdate($event)"
simpleSearchLink="/search/find" [customFilter]="customFilter">
[simpleSearchLink]="properties.searchLinkToDataProviders" [customFilter]="customFilter">
</search-dataproviders>
<search-dataproviders *ngIf="activeEntity == 'services'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false"
(searchPageUpdates)="activeEntityUpdate($event)"
simpleSearchLink="/search/find" [customFilter]="customFilter"
[simpleSearchLink]="properties.searchLinkToServices" [customFilter]="customFilter"
type="services" entityType="service" [typeName]="openaireEntities.SERVICES">
</search-dataproviders>

View File

@ -32,12 +32,15 @@ import {SearchDataProvidersComponent} from "../searchDataProviders.component";
import {NewSearchPageComponent, SearchForm} from "../searchUtils/newSearchPage.component";
import {properties} from "../../../../environments/environment";
import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
@Component({
selector: 'search-all',
templateUrl: 'searchAll.component.html'
})
export class SearchAllComponent {
isMobile: boolean = false;
reload:{result:boolean, projects:boolean, datasources: boolean, services: boolean, organizations:boolean} =
{result:true, projects:true, datasources: true, services: true, organizations:true};
public pageTitle = "Search in OpenAIRE"
@ -78,17 +81,20 @@ export class SearchAllComponent {
showDataProviders: boolean = false;
showServices: boolean = false;
showOrganizations: boolean = false;
advancedSearchLink: string = "/search/advanced/publications";
advancedSearchLink: string = properties.searchLinkToAdvancedResults;
properties: EnvProperties;
offset: number;
public openaireEntities = OpenaireEntities;
@Input() logoURL;
@Input() name;
@Input() customFilter: SearchCustomFilter = null;
@Input() piwikSiteId = null;
@Input() formPlaceholderText = "Search for "+OpenaireEntities.RESULTS+", "+OpenaireEntities.PROJECTS+", "+OpenaireEntities.DATASOURCES+" & "+OpenaireEntities.ORGANIZATIONS+" in OpenAIRE";
@Input() formPlaceholderText = "Search in Explore"
// @Input() formPlaceholderText = "Search for "+OpenaireEntities.RESULTS+", "+OpenaireEntities.PROJECTS+", "+OpenaireEntities.DATASOURCES+" & "+OpenaireEntities.ORGANIZATIONS+" in OpenAIRE";
@Input() searchForm: SearchForm = {class: 'search-form', dark: true}
@Input() breadcrumbs: Breadcrumb[] = [];
@Input() openAccess: boolean = true;
subs: Subscription[] = [];
quickFilter: { filter: Filter, selected: boolean, filterId: string, value: string } = {
@ -125,6 +131,7 @@ export class SearchAllComponent {
private _title: Title,
private _piwikService: PiwikService,
private config: ConfigurationService,
private layoutService: LayoutService,
private seoService: SEOService, private router: Router, private cdr:ChangeDetectorRef) {
this.fetchPublications = new FetchResearchResults(this._searchResearchResultsService);
this.fetchDataproviders = new FetchDataproviders(this._searchDataprovidersService);
@ -141,8 +148,7 @@ export class SearchAllComponent {
public ngOnInit() {
var description = "Search for "+OpenaireEntities.RESULTS+" ("+OpenaireEntities.PUBLICATIONS+", "+OpenaireEntities.DATASETS+", "+OpenaireEntities.SOFTWARE+", "+OpenaireEntities.OTHER+"), "+OpenaireEntities.PROJECTS+", "+OpenaireEntities.ORGANIZATIONS+", "+OpenaireEntities.DATASOURCES+" in the OpenAIRE Research Graph. ";
var description = "Search for "+OpenaireEntities.RESULTS+" ("+OpenaireEntities.PUBLICATIONS+", "+OpenaireEntities.DATASETS+", "+OpenaireEntities.SOFTWARE+", "+OpenaireEntities.OTHER+"), "+OpenaireEntities.PROJECTS+", "+OpenaireEntities.ORGANIZATIONS+", "+OpenaireEntities.DATASOURCES+" in the OpenAIRE Graph. ";
var title = "OpenAIRE |Search for "+OpenaireEntities.RESULTS+", "+OpenaireEntities.PROJECTS+", "+OpenaireEntities.DATASOURCES+" & "+OpenaireEntities.ORGANIZATIONS;
this.properties = properties;
var url = this.properties.domain + this.properties.baseLink + this._router.url;
@ -195,46 +201,78 @@ export class SearchAllComponent {
this.showDataProviders = true;
this.showServices = false;
}
this.loadAll();
}
this.loadAll();
this.subs.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
if (typeof document !== 'undefined') {
if(!this.isMobile && document.getElementById("main-menu")) {
this.offset = Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--header-height'));
this.cdr.detectChanges();
} else {
this.offset = 0;
this.cdr.detectChanges();
}
}
}))
}
loadAll() {
this.reloadTabs();
this.subs.push(this.route.queryParams.subscribe(params => {
this.parameters = Object.assign({}, params);
this.keyword = (params['keyword']) ? params['keyword'] : (params["q"] ? params["q"] : (params["f0"] && params["f0"] == "q" && params["fv0"]?params["fv0"]:""));
this.subs.push(this.route.queryParams.subscribe(queryParams => {
this.parameters = Object.assign({}, queryParams);
this.keyword = (queryParams['keyword']) ? queryParams['keyword'] : (queryParams["q"] ? queryParams["q"] : (queryParams["f0"] && queryParams["f0"] == "q" && queryParams["fv0"]?queryParams["fv0"]:""));
this.selectedFields[0].value = StringUtils.URIDecode(this.keyword);
this.quickFilter.selected = ((params['qf']== undefined || params["qf"] == "true") == true);
if (params["type"] && params["type"].length > 0) {
this.resultTypes['publication'] = (params["type"].split(",").indexOf("publications") != -1);
this.resultTypes['dataset'] = (params["type"].split(",").indexOf("datasets") != -1);
this.resultTypes['software'] = (params["type"].split(",").indexOf("software") != -1);
this.resultTypes['other'] = (params["type"].split(",").indexOf("other") != -1);
this.quickFilter.selected = ((queryParams['qf']== undefined || queryParams["qf"] == "true") == true);
if (queryParams["type"] && queryParams["type"].length > 0) {
this.resultTypes['publication'] = (queryParams["type"].split(",").indexOf("publications") != -1);
this.resultTypes['dataset'] = (queryParams["type"].split(",").indexOf("datasets") != -1);
this.resultTypes['software'] = (queryParams["type"].split(",").indexOf("software") != -1);
this.resultTypes['other'] = (queryParams["type"].split(",").indexOf("other") != -1);
}
if(this.activeEntity == null && (!params["active"] || params["active"].length ==0)){
this.activeEntity = this.getDefaultEntityToShow();
}else if(params["active"] && params["active"].length >0 ){
this.activeEntity = ((["result","projects","organizations","datasources","services"]).indexOf(params["active"])!= -1)?params["active"]:this.getDefaultEntityToShow();
}else if (this.activeEntity !=null && (!params["active"] || params["active"].length ==0)){
this.parameters["active"]=this.activeEntity;
if((typeof document !== 'undefined') && location.search && location.search.indexOf("active=") == -1){
this.location.go(location.pathname, ((location.search)?(location.search+"&"):("?")) +"active=" + this.activeEntity);
let active = null;
if (queryParams["active"] && queryParams["active"].length > 0) {
active = ((["result","projects","organizations","datasources","services"]).indexOf(queryParams["active"])!= -1)?queryParams["active"]:null;
delete this.parameters['active'];
}
this.subs.push(this.route.params.subscribe(params => {
if(this.activeEntity == null && (!params["entity"] || params["entity"].length == 0)){
if (active) {
this.activeEntity = active;
if((typeof document !== 'undefined')){
if (active == "result") {
active = "research-outcomes";
}
let query = location.search.replace(/(active=)([^&]*)&?/, '');
this.location.go(location.pathname + '/' + active, query == '?' ? '' : query);
}
} else {
this.activeEntity = this.getDefaultEntityToShow();
}
} else if(params["entity"] && params["entity"].length > 0 ){
let entity = params["entity"];
if(entity == "research-outcomes") {
entity = "result";
} else if (entity == "dataproviders") {
entity = "datasources";
}
this.activeEntity = ((["result","projects","organizations","datasources","services"]).indexOf(entity)!= -1)?entity:this.getDefaultEntityToShow();
}
}
if (this.activeEntity == "result") {
this.searchResults();
} else if (this.activeEntity == "projects") {
this.searchProjects();
} else if (this.activeEntity == "datasources") {
this.searchDataProviders();
} else if (this.activeEntity == "services") {
this.searchServices();
} else if (this.activeEntity == "organizations") {
this.searchOrganizations();
}
this.count();
if (this.activeEntity == "result") {
this.searchResults();
} else if (this.activeEntity == "projects") {
this.searchProjects();
} else if (this.activeEntity == "datasources") {
this.searchDataProviders();
} else if (this.activeEntity == "services") {
this.searchServices();
} else if (this.activeEntity == "organizations") {
this.searchOrganizations();
}
this.count();
}));
}));
}
@ -265,7 +303,9 @@ export class SearchAllComponent {
}
public searchResults() {
this.advancedSearchLink = this.properties.searchLinkToAdvancedPublications;//"/search/advanced/publications";
this.advancedSearchLink = this.properties.searchLinkToAdvancedResults;//"/search/advanced/research-outcomes";
this.formPlaceholderText = "Search by title, author, abstract, DOI, orcid...";
if (this.reload[this.activeEntity] &&
this.fetchPublications.searchUtils.status != this.errorCodes.NONE) {
this.reload[this.activeEntity] = false;
@ -276,6 +316,8 @@ export class SearchAllComponent {
public searchProjects() {
this.advancedSearchLink = this.properties.searchLinkToAdvancedProjects;//"/search/advanced/projects";
this.formPlaceholderText = "Search by title, acronym, project code...";
if (this.reload[this.activeEntity] &&
this.fetchProjects.searchUtils.status != this.errorCodes.NONE ) {
this.reload[this.activeEntity] = false;
@ -285,6 +327,8 @@ export class SearchAllComponent {
public searchDataProviders() {
this.advancedSearchLink = this.properties.searchLinkToAdvancedDataProviders;//"/search/advanced/dataproviders";
this.formPlaceholderText = "Search by name, description, subject...";
if ( this.reload[this.activeEntity] &&
this.fetchDataproviders.searchUtils.status != this.errorCodes.NONE) {
this.reload[this.activeEntity] = false;
@ -294,6 +338,8 @@ export class SearchAllComponent {
public searchServices() {
this.advancedSearchLink = this.properties.searchLinkToAdvancedServices;//"/search/advanced/services";
this.formPlaceholderText = "Search by name, description, subject...";
if ( this.reload[this.activeEntity] &&
this.fetchServices.searchUtils.status != this.errorCodes.NONE) {
this.reload[this.activeEntity] = false;
@ -303,6 +349,8 @@ export class SearchAllComponent {
public searchOrganizations() {
this.advancedSearchLink = this.properties.searchLinkToAdvancedOrganizations;//"/search/advanced/organizations";
this.formPlaceholderText = "Search by organization name...";
if (this.reload[this.activeEntity] &&
this.fetchOrganizations.searchUtils.status != this.errorCodes.NONE) {
this.reload[this.activeEntity] = false;
@ -374,7 +422,7 @@ export class SearchAllComponent {
this.reload["result"] = false;
this.fetchPublications.results = [];
//Add Open Access Filter
this.subs.push(this.numOfSearchResults(this.fetchPublications, (refineParams ? (refineParams + '&') : '') + "&fq=resultbestaccessright%20exact%20%22Open%20Access%22"));
this.subs.push(this.numOfSearchResults(this.fetchPublications, (refineParams ? (refineParams + '&') : '') + (this.openAccess ? "&fq=resultbestaccessright%20exact%20%22Open%20Access%22" : "")));
}
if (this.activeEntity != "projects" && this.reload["projects"] && this.showProjects) {
@ -532,33 +580,40 @@ export class SearchAllComponent {
}
}
entityChanged(entity){
if(this.activeEntity == "result") {
this.resultTypes = {publication: true, dataset: true, software: true, other: true};
}
if(this.activeEntity == "result" && this.searchResearchResultsComponent){
this.searchResearchResultsComponent.ngOnDestroy();
}else if(this.activeEntity == "projects" && this.searchProjectsComponent){
this.searchProjectsComponent.ngOnDestroy();
}else if(this.activeEntity == "datasources" && this.searchDataprovidersComponent){
this.searchDataprovidersComponent.ngOnDestroy();
}else if(this.activeEntity == "services" && this.searchDataprovidersComponent){
this.searchDataprovidersComponent.ngOnDestroy();
}else if(this.activeEntity == "organizations" && this.searchOrganizationsComponent){
this.searchOrganizationsComponent.ngOnDestroy();
}
this.activeEntity = entity;
entityChanged(entity) {
if (this.activeEntity !== entity) {
if (this.activeEntity == "result") {
this.resultTypes = {publication: true, dataset: true, software: true, other: true};
}
if (this.activeEntity == "result" && this.searchResearchResultsComponent) {
this.searchResearchResultsComponent.ngOnDestroy();
} else if (this.activeEntity == "projects" && this.searchProjectsComponent) {
this.searchProjectsComponent.ngOnDestroy();
} else if (this.activeEntity == "datasources" && this.searchDataprovidersComponent) {
this.searchDataprovidersComponent.ngOnDestroy();
} else if (this.activeEntity == "services" && this.searchDataprovidersComponent) {
this.searchDataprovidersComponent.ngOnDestroy();
} else if (this.activeEntity == "organizations" && this.searchOrganizationsComponent) {
this.searchOrganizationsComponent.ngOnDestroy();
}
this.activeEntity = entity;
this.parameters = {};
this.reload[entity]= true;
this.parameters["active"] = entity;
if ( this.keyword.length > 0) {
this.parameters["fv0"] = this.keyword;
this.parameters["f0"] = "q";
}
if(this.customFilter){
this.parameters = this.customFilter.getParameters(this.parameters);
}
this.router.navigate(["/search/find"], {queryParams: this.parameters});
this.reload[entity] = true;
if (this.keyword.length > 0) {
this.parameters["fv0"] = this.keyword;
this.parameters["f0"] = "q";
}
if (this.customFilter) {
this.parameters = this.customFilter.getParameters(this.parameters);
}
if (entity == "result") {
entity = "research-outcomes";
if(!!this.openAccess) {
this.parameters["resultbestaccessright"] = '"' + encodeURIComponent("Open Access") + '"';
}
}
this.router.navigate(["/search/find", entity], {queryParams: this.parameters});
}
}
}

View File

@ -35,7 +35,7 @@ import {properties} from "../../../environments/environment";
[includeOnlyResultsAndFilter]="includeOnlyResultsAndFilter"
[piwikSiteId]=piwikSiteId [hasPrefix]="hasPrefix"
[searchForm]="searchForm"
[entitiesSelection]="type=='all' || type == 'services'" [showSwitchSearchLink]="showSwitchSearchLink"
[entitiesSelection]="false" [showSwitchSearchLink]="showSwitchSearchLink"
[filters]="filters"
[simpleView]="simpleView" formPlaceholderText="Search by name, description, subject..."
[showResultCount]="true" [showIndexInfo]="type!='deposit'"

View File

@ -82,7 +82,7 @@
[id]="'autocomplete-'+i">
</entities-autocomplete>
</td>
<td *ngIf="selectedField.type == 'boolean'" class="input-group">
<span class="input-group-addon">
<input type="radio" [(ngModel)]="selectedField.value" [name]=selectedField.param
@ -136,7 +136,7 @@
<span class="uk-flex uk-flex-middle">
<icon name="search" [flex]="true"></icon>
<span class="uk-margin-small-left">Search</span>
<span *ngIf="selectedFields.length >= 2" class="uk-margin-xsmall-left">({{selectedFields.length}} Rules)</span>
<!-- <span *ngIf="selectedFields.length >= 2" class="uk-margin-xsmall-left">({{selectedFields.length}} Rules)</span> -->
</span>
</button>
</a>
@ -146,7 +146,8 @@
<div *ngIf="simpleView" class="uk-flex uk-flex-center uk-flex-wrap">
<div class="uk-width-xlarge@l uk-width-large">
<div class="uk-text-small uk-flex uk-flex-right" [class.uk-light]="dark" *ngIf="showSwitchSearchLink">
<a *ngIf ="this.entityType !='all' && this.entityType == this.selectedEntity && advancedSearchLink"
<!-- && this.entityType == this.selectedEntity-->
<a *ngIf ="this.entityType !='all' && advancedSearchLink"
[routerLink]="advancedSearchLink" [queryParams]="advancedSearchLinkParameters" class="uk-margin-small-bottom"
[ngClass]="(isDisabled)?'uk-disabled uk-link-muted':null">Advanced search
</a>
@ -163,25 +164,29 @@
</div>
<div class="uk-flex uk-flex-center uk-child-width-1-1">
<ng-container *ngIf="entitiesSelection">
<advanced-search-input [class.uk-hidden]="disableSelect" [dark]="dark" [disabled]="isDisabled" (searchEmitter)="simpleKeywordChanged()">
<!-- [class.uk-hidden]="disableSelect" -->
<advanced-search-input [dark]="dark" [disabled]="isDisabled" (searchEmitter)="simpleKeywordChanged()">
<entities-selection [simpleView]="true" [currentEntity]="entityType"
(selectionChange)="simpleEntityChanged($event)" (disableSelectEmitter)="disableSelectChange($event)"
[onChangeNavigate]="true" [customFilter]="customFilter" class="uk-width-2-5"></entities-selection>
<div class="uk-width-expand" input placeholder="Scholary works" [searchable]="true" [hint]="formPlaceholderText"
[onChangeNavigate]="true" [customFilter]="customFilter" class="uk-width-2-5"></entities-selection> -->
<div class="uk-width-expand" input placeholder="Search in Explore" [searchable]="true" [hint]="formPlaceholderText"
[(value)]="selectedFields[0].value" tooltip="true"></div>
<!-- <a *ngIf="isMobile" href="#mobile-filters" filters-toggle (click)="filtersClicked.emit(true)" uk-toggle>-->
<!-- <icon name="filters"></icon>-->
<!-- </a>-->
</advanced-search-input>
<div *ngIf="selectedFields[0] && disableSelect" search-input [disabled]="isDisabled" [(value)]="selectedFields[0].value"
[placeholder]="formPlaceholderText" (searchEmitter)="simpleKeywordChanged()" [iconPosition]="isMobile?'left':'right'">
<a *ngIf="isMobile" href="#mobile-filters" filters-toggle (click)="filtersClicked.emit(true)" uk-toggle>
<icon name="filters"></icon>
</a>
</div>
[searchInputClass]="'inner background'" [placeholder]="formPlaceholderText" (searchEmitter)="simpleKeywordChanged()">
<!-- <a *ngIf="isMobile" href="#mobile-filters" filters-toggle (click)="filtersClicked.emit(true)" uk-toggle>-->
<!-- <icon name="filters"></icon>-->
<!-- </a>-->
</div>
</ng-container>
<div *ngIf="selectedFields[0] && !entitiesSelection" search-input [disabled]="isDisabled" [(value)]="selectedFields[0].value"
[placeholder]="formPlaceholderText" (searchEmitter)="simpleKeywordChanged()" [iconPosition]="isMobile?'left':'right'">
<a *ngIf="isMobile" href="#mobile-filters" filters-toggle (click)="filtersClicked.emit(true)" uk-toggle>
<icon name="filters"></icon>
</a>
[searchInputClass]="'inner background'" [placeholder]="formPlaceholderText" (searchEmitter)="simpleKeywordChanged()">
<!-- <a *ngIf="isMobile" href="#mobile-filters" filters-toggle (click)="filtersClicked.emit(true)" uk-toggle>-->
<!-- <icon name="filters"></icon>-->
<!-- </a>-->
</div>
</div>
</div>

View File

@ -116,7 +116,7 @@ export class AdvancedSearchFormComponent implements OnInit, OnDestroy, OnChanges
simpleKeywordChanged() {
// this.selectedFields[0].value = $event.value;
if (this.selectedEntity == this.entityType) {
if ((this.selectedEntity == this.entityType) || !this.entitiesSelection) {
this.queryChanged();
} else {
this.router.navigate([this.selectedEntitySimpleUrl], {queryParams: {q: this.selectedFields[0].value, op: "and"}});

View File

@ -71,6 +71,15 @@
</div>
</h1>
</ng-template>
<ng-template #search_filter let-filter="filter">
<search-filter [filterValuesNum]="filterValuesNum" [showMoreInline]="showMoreFilterValuesInline"
[isDisabled]="disabled"
[filter]="filter" [showResultCount]=showResultCount
(onFilterChange)="filterChanged($event)"
[actionRoute]="true"></search-filter>
</ng-template>
<ng-template #filters_column>
<div [class.filterLoading]="disabled">
<div class="uk-flex uk-flex-middle">
@ -91,25 +100,43 @@
<span *ngIf="searchUtils.refineStatus != errorCodes.NONE" class="uk-text-warning">Filters temporarily unavailable. Please try again later.</span>
</div>
<ul *ngIf="!showUnknownFilters" class="uk-list uk-list-xlarge">
<li *ngIf="filters.length > 0 && filters[0].values.length >0 && filters[0].filterId == 'resultbestaccessright'">
<search-filter [filterValuesNum]="filterValuesNum" [showMoreInline]="showMoreFilterValuesInline"
[isDisabled]="disabled"
[filter]="filters[0]" [showResultCount]=showResultCount
(onFilterChange)="filterChanged($event)" [quickFilter]="quickFilter"
[actionRoute]="true"></search-filter>
<li *ngIf="filters.length > 0 && getFilterById('resultbestaccessright') && getFilterById('resultbestaccessright').values.length >0">
<ng-container *ngTemplateOutlet="search_filter; context: {filter: getFilterById('resultbestaccessright')}"></ng-container>
</li>
<li *ngFor="let filter of rangeFilters">
<range-filter [isDisabled]="disabled" [filter]="filter"
(onFilterChange)="filterChanged($event)" [actionRoute]="true"></range-filter>
<li *ngIf="resultTypes && (filters.length > 0)">
<quick-selections [resultTypes]="resultTypes" (typeChange)="queryChanged($event)"
[isDisabled]="disabled" [vertical]="true"
[actionRoute]="true">
</quick-selections>
</li>
<ng-container *ngFor="let filter of filters ">
<li *ngIf="filter.values && filter.values.length > 0 && filter.filterId != 'resultbestaccessright'">
<search-filter [filterValuesNum]="filterValuesNum" [showMoreInline]="showMoreFilterValuesInline"
[isDisabled]="disabled"
[filter]="filter" [showResultCount]=showResultCount
(onFilterChange)="filterChanged($event)" [actionRoute]="true"></search-filter>
<li *ngIf="filters.length > 0 && getFilterById('instancetypename') && getFilterById('instancetypename').values.length >0">
<ng-container *ngTemplateOutlet="search_filter; context: {filter: getFilterById('instancetypename')}"></ng-container>
</li>
<ng-container *ngIf="entityType == 'result'">
<li *ngFor="let filter of rangeFilters">
<range-filter [isDisabled]="disabled" [filter]="filter"
(onFilterChange)="filterChanged($event)" [actionRoute]="true"></range-filter>
</li>
</ng-container>
<ng-container *ngFor="let filter of filters ">
<li *ngIf="filter.values && filter.values.length > 0
&& filter.filterId != 'resultbestaccessright' && filter.filterId != 'instancetypename' && filter.filterId != 'projectoamandatepublications'">
<!-- <search-filter [filterValuesNum]="filterValuesNum" [showMoreInline]="showMoreFilterValuesInline"-->
<!-- [isDisabled]="disabled"-->
<!-- [filter]="filter" [showResultCount]=showResultCount-->
<!-- (onFilterChange)="filterChanged($event)" [actionRoute]="true"></search-filter>-->
<ng-container *ngTemplateOutlet="search_filter; context: {filter: filter}"></ng-container>
</li>
</ng-container>
<ng-container *ngIf="entityType == 'project'">
<li *ngFor="let filter of rangeFilters">
<range-filter [isDisabled]="disabled" [filter]="filter"
(onFilterChange)="filterChanged($event)" [actionRoute]="true"></range-filter>
</li>
</ng-container>
<li *ngIf="filters.length > 0 && getFilterById('projectoamandatepublications') && getFilterById('projectoamandatepublications').values.length >0">
<ng-container *ngTemplateOutlet="search_filter; context: {filter: getFilterById('projectoamandatepublications')}"></ng-container>
</li>
</ul>
</div>
</ng-template>
@ -139,12 +166,23 @@
</div>
</ng-template>
<ng-template #main let-mobile="mobile">
<div *ngIf="mobile && showRefine && (searchUtils.refineStatus != errorCodes.LOADING || existingFiltersWithValues !== 0)"
class="filters-toggle-button">
<button href="#mobile-filters" uk-toggle="target: #mobile-filters"
class="uk-icon-button uk-button-secondary uk-flex uk-flex-middle"
(click)="showOffCanvas = true; detectChanges()"
[disabled]="disabled"
[class.uk-disabled]="disabled">
<icon name="filters" [flex]="true" ratio="1.2" visuallyHidden="filters"></icon>
</button>
</div>
<!-- TODO - Clean up -->
<div *ngIf="!includeOnlyResultsAndFilter" [class]="usedBy != 'deposit' && usedBy != 'orcid' && (!customFilter || customFilter.queryFieldName != 'communityId') ?
(stickyForm?'':' ') :
(+ (stickyForm?'':' uk-section') +' uk-padding-remove-bottom uk-padding-remove-top ' +
((usedBy == 'deposit' || usedBy == 'orcid') ? ' uk-padding-remove-top ' : ' '))"
[attr.uk-sticky]="((stickyForm || mobile)?'{offset:100;top:90;cls-active:uk-active uk-sticky-below;cls-inactive:uk-sticky '+
[attr.uk-sticky]="((stickyForm || (simpleView && mobile))?'{offset:100;top:90;cls-active:uk-active uk-sticky-below;cls-inactive:uk-sticky '+
(usedBy != 'deposit' && usedBy != 'orcid' && (!customFilter || customFilter.queryFieldName != 'communityId') ?
' uk-position-relative ' :(' uk-section ' ))+'}':null)">
<div class="uk-background-norepeat uk-background-bottom-center" [ngClass]="searchForm.class">
@ -171,7 +209,7 @@
[advancedSearchLinkParameters]="this.routerHelper.createQueryParams(this.parameterNames, this.parameterValues)"
[simpleView]="simpleView" [formPlaceholderText]="formPlaceholderText" [isMobile]="mobile"
[resultTypes]="resultTypes" [quickFilter]="quickFilter" [entitiesSelection]="entitiesSelection"
[showSwitchSearchLink]="showSwitchSearchLink" [customFilter]="customFilter" (filtersClicked)="showOffCanvas = $event"
[showSwitchSearchLink]="showSwitchSearchLink" [customFilter]="customFilter"
>
</advanced-search-form>
</div>
@ -191,16 +229,16 @@
<div [class.uk-margin-top]="properties.adminToolsPortalType == 'eosc'" >
<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
[texts]="pageContents['top']"></helper>
<div *ngIf="resultTypes" class="uk-flex uk-flex-center uk-padding-small uk-padding-remove-vertical uk-background-muted uk-border-rounded">
<quick-selections class="uk-margin-bottom uk-margin-top" [resultTypes]="resultTypes" (typeChange)="queryChanged($event)"
[isDisabled]="disabled" [actionRoute]="true">
</quick-selections>
</div>
<!-- <div *ngIf="resultTypes" class="uk-flex uk-flex-center uk-padding-small uk-padding-remove-vertical uk-background-muted uk-border-rounded">-->
<!-- <quick-selections class="uk-margin-bottom uk-margin-top" [resultTypes]="resultTypes" (typeChange)="queryChanged($event)"-->
<!-- [isDisabled]="disabled" [actionRoute]="true">-->
<!-- </quick-selections>-->
<!-- </div>-->
<div [class]="showRefine? 'uk-width-4-5@m uk-width-4-5@l uk-width-1-1@s' :'uk-width-1-1'">
<div *ngIf="showRefine && mobile">
<div #mobileFilters id="mobile-filters" uk-offcanvas="overlay: true">
<div class="uk-offcanvas-bar uk-padding-remove-horizontal">
<a class="uk-offcanvas-close uk-icon uk-close" (click)="showOffCanvas=false">
<a class="uk-offcanvas-close uk-icon uk-close" (click)="showOffCanvas=false; detectChanges()">
<icon name="close" ratio="1.5" visuallyHidden="close filters"></icon>
</a>
<div *ngIf="showOffCanvas" class="uk-padding-small uk-padding-remove-vertical">
@ -252,14 +290,20 @@
[href]="openaireLink+this.routerHelper.createQueryParamsString(this.parameterNames, this.parameterValues)"
target="_blank"> OpenAIRE - Explore</a>.
</div>
<div class="uk-flex uk-flex-between uk-flex-middle uk-flex-wrap">
<div class="uk-flex uk-flex-middle uk-flex-wrap uk-child-width-1-1 uk-child-width-auto@m" [class.uk-flex-between]="!mobile"
[class.uk-margin-top]="mobile">
<!-- Total results, number of pages -->
<h6 class="uk-margin-remove">
<div class="uk-width-xlarge@m uk-margin-remove-bottom uk-text-truncate uk-margin-medium-right" [class.uk-h6]="!mobile" [class.uk-text-center]="mobile">
<ng-container *ngIf="results && searchUtils.totalResults > 0">
<span>{{searchUtils.totalResults|number}}</span>
<span class="uk-text-meta uk-text-capitalize"> {{type}}, page </span>
<span>{{searchUtils.page | number}}</span>
<span class="uk-text-meta"> of {{(totalPages(searchUtils.totalResults)|number)}}</span>
<span class="uk-text-meta uk-text-capitalize"> {{type}}</span>
<ng-container *ngIf="searchTerm && simpleView">
<span class="uk-text-meta"> for </span>
<span class="uk-text-bold">{{searchTerm}}</span>
</ng-container>
<ng-container *ngIf="!simpleView && advancedSearchTerms > 0">
<span class="uk-text-bold"> ({{advancedSearchTerms}} rule{{advancedSearchTerms == 1 ? '' : 's'}} applied)</span>
</ng-container>
</ng-container>
<ng-container *ngIf="!loadPaging && oldTotalResults > 0 && searchUtils.status == errorCodes.LOADING">
<span>{{oldTotalResults|number}}</span>
@ -267,9 +311,10 @@
<span>{{searchUtils.page | number}}</span>
<span class="uk-text-meta"> of {{(totalPages(oldTotalResults)|number)}}</span>
</ng-container>
</h6>
</div>
<!-- Download results -->
<div *ngIf="showDownload && (searchUtils.status !== errorCodes.LOADING || !loadPaging)" class="uk-margin-small-bottom uk-margin-small-top">
<div *ngIf="showDownload && (searchUtils.status !== errorCodes.LOADING || !loadPaging)"
class="uk-margin-small-bottom uk-flex uk-margin-small-top" [class.uk-flex-center]="mobile" [class.uk-margin-medium-top]="mobile">
<search-download
*ngIf="( entityType !='community' && entityType != 'stakeholder') && usedBy == 'search'"
[isDisabled]="disabled"

View File

@ -132,7 +132,7 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
public pageOptions: number[] = [5, 10, 20, 50];
@Input() basicMetaDescription = [];
@Input() entitiesSelection: boolean = true;
@Input() entitiesSelection: boolean = false;
@Input() showSwitchSearchLink: boolean = true;
// on 1st load, do not show filters until results query returns.
@ -151,6 +151,8 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
showOffCanvas:boolean = false;
isMobile: boolean = false;
isServer: boolean;
searchTerm: string = null;
advancedSearchTerms: number = 0;
constructor(private route: ActivatedRoute,
private location: Location,
@ -428,7 +430,9 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
var dependentTo = this.searchFieldsHelper.DEPENDENT_FIELDS[this.refineFields[i]];
//if filter is not marked as hidden OR it is hidden but it is dependent to a field that it IS selected
if (this.searchFieldsHelper.HIDDEN_FIELDS.indexOf(this.refineFields[i]) == -1 || (selected_filters.indexOf(dependentTo) != -1) || (selected_filters.indexOf(this.refineFields[i]) != -1)) {
if (this.searchFieldsHelper.HIDDEN_FIELDS.indexOf(this.refineFields[i]) == -1
|| (selected_filters.indexOf(dependentTo) != -1) || (selected_filters.indexOf(this.refineFields[i]) != -1)
|| (this.resultTypes && this.resultTypes.filterId == dependentTo && this.resultTypes.countSelectedValues > 0)) {
fields.push(this.refineFields[i]);
}
}
@ -1689,6 +1693,14 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
this.getRangeFiltersFromURL(params);
this.getRefineFiltersFromURL(params);
this.createAdvancedSearchSelectedFiltersFromURLParameters(params);
this.searchTerm = '';
if(params && params['fv0'] && params['f0'] && params['f0'] == 'q'){
let keyword = StringUtils.URIDecode(params['fv0']);
this.searchTerm = keyword;
}
if(params){
this.advancedSearchTerms = Object.keys(params).filter(key => key.includes('fv')).length;
}
}
removeResultType(type) {
@ -1708,4 +1720,12 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
}
return totalPages;
}
}
public getFilterById(filterId: string): Filter {
return this.filters.find(filter => filter.filterId == filterId);
}
detectChanges() {
this.cdr.detectChanges();
}
}

View File

@ -11,27 +11,35 @@ import {OpenaireEntities} from "../../utils/properties/searchFields";
@Component({
selector: 'quick-selections',
template: `
<div *ngIf="quickFilter" class="uk-margin-bottom">
<mat-slide-toggle name="qf" [(ngModel)]="quickFilter.selected" (ngModelChange)="quickFilterChanged()">
<span class="uk-text-bold">{{quickFilter.value}}</span>
</mat-slide-toggle>
</div>
<div class="uk-flex uk-flex-middle uk-text-small uk-text-nowrap">
<div class="uk-width-auto@s uk-width-1-3 uk-flex uk-flex-right uk-text-meta uk-margin-small-right">Include:</div>
<div class="uk-width-expand">
<div class="uk-grid uk-grid-small uk-flex-middle uk-child-width-auto@m uk-child-width-1-2@s uk-child-width-1-1" uk-grid>
<ng-container *ngFor="let value of resultTypes.values">
<div>
<input #input type="checkbox" class="uk-checkbox" [(ngModel)]="value.selected" (ngModelChange)="changed()"/>
<label class="uk-margin-small-left" (click)="input.click()">{{value.name}}</label>
</div>
</ng-container>
<div *ngIf="!vertical && (resultTypes || quickFilter)">
<div *ngIf="quickFilter" class="uk-margin-bottom">
<mat-slide-toggle name="qf" [(ngModel)]="quickFilter.selected" (ngModelChange)="quickFilterChanged()">
<span class="uk-text-bold">{{quickFilter.value}}</span>
</mat-slide-toggle>
</div>
<div class="uk-flex uk-flex-middle uk-text-small uk-text-nowrap">
<div class="uk-width-auto@s uk-width-1-3 uk-flex uk-flex-right uk-text-meta uk-margin-small-right">Include:</div>
<div class="uk-width-expand">
<div class="uk-grid uk-grid-small uk-flex-middle uk-child-width-auto@m uk-child-width-1-2@s uk-child-width-1-1" uk-grid>
<ng-container *ngFor="let value of resultTypes.values">
<div>
<input #input type="checkbox" class="uk-checkbox" [(ngModel)]="value.selected" (ngModelChange)="changed()"/>
<label class="uk-margin-small-left" (click)="input.click()">{{value.name}}</label>
</div>
</ng-container>
</div>
</div>
</div>
</div>
<div *ngIf="vertical && (resultTypes || quickFilter)" [class.uk-disabled]="isDisabled">
<search-filter [isDisabled]="isDisabled" [filter]="resultTypes" [showResultCount]='false'
(onFilterChange)="changed()" [actionRoute]="actionRoute"></search-filter>
</div>
`
})
export class QuickSelectionsComponent {
@Input() vertical: boolean=false;
@Input() resultTypes:Filter;
@Output() typeChange = new EventEmitter();
@Input() isDisabled;

View File

@ -19,7 +19,7 @@
<div class="uk-margin-small-left">
<div class="uk-text-meta">Top 100 values are shown in the filters</div>
<div class="uk-flex uk-flex-bottom uk-margin-top">
<div input class="uk-width-1-2@m uk-margin-right" [placeholder]="{label: 'Search', static: true}" inputClass="inner small" [(value)]="keyword"></div>
<div input class="uk-width-1-2@m uk-margin-right" [placeholder]="{label: 'Search', static: true}" inputClass="inner small" [(value)]="keyword" (valueChange)="initMatching()"></div>
<div *ngIf="showResultCount === true" input type="select" class="uk-width-expand" placeholder="Sort by"
inputClass="border-bottom" [(value)]="sortBy" [options]="sortByOptions" (valueChange)="sort()"></div>
</div>
@ -27,9 +27,13 @@
<div class="uk-overflow-auto uk-height-max-small uk-margin-small-left uk-margin-small-right uk-margin-top">
<ng-container *ngFor="let value of this.sortedValues">
<div *ngIf="filterKeywords(value.name)" title="{{value.name}}"
class="uk-animation-fade uk-text-small">
<ng-container
*ngTemplateOutlet="input_label_wrapper; context: {filter: filter, value: value}"></ng-container>
class="uk-animation-fade uk-text-small">
<ng-container *ngTemplateOutlet="input_label_wrapper; context: {filter: filter, value: value}"></ng-container>
</div>
</ng-container>
<ng-container *ngIf="!hasMatch">
<div class="uk-padding-small uk-text-meta">
No filters available with that term
</div>
</ng-container>
</div>

View File

@ -5,7 +5,8 @@ import {
EventEmitter,
OnInit,
OnChanges,
SimpleChanges
SimpleChanges,
ChangeDetectorRef
} from '@angular/core';
import {Filter, Value} from './searchHelperClasses.class';
import {ActivatedRoute, Router} from "@angular/router";
@ -42,7 +43,11 @@ export class SearchFilterComponent implements OnInit, OnChanges {
sub;
public isOpen: boolean = false;
sortedValues;
constructor(private _router: Router, private route: ActivatedRoute) {
hasMatch: boolean = false;
constructor(private _router: Router,
private route: ActivatedRoute,
private cdr: ChangeDetectorRef) {
}
ngOnDestroy() {
@ -115,6 +120,10 @@ export class SearchFilterComponent implements OnInit, OnChanges {
return false;
}
}
if(!this.hasMatch) {
this.hasMatch = true;
this.cdr.detectChanges();
}
return true;
}
@ -246,9 +255,13 @@ export class SearchFilterComponent implements OnInit, OnChanges {
return 0;
}
});
}
}
this.sortedValues = Object.assign(sorted);
}
initMatching() {
this.hasMatch = false;
this.cdr.detectChanges();
}
toggle(event) {
@ -324,4 +337,4 @@ export class SearchFilterComponent implements OnInit, OnChanges {
return Object.entries(obj);
}
}
}
}

View File

@ -1,9 +1,9 @@
<ul class="uk-list uk-list-xlarge uk-margin" [ngClass]="custom_class">
<ul class="uk-list uk-margin" [ngClass]="custom_class">
<errorMessages [status]="[status]" [type]="'results'"></errorMessages>
<li *ngFor="let result of previewResults">
<result-preview [properties]="properties" [showOrganizations]="showOrganizations"
[showSubjects]="showSubjects" [result]="result" [showEnermaps]="showEnermaps"
[isCard]="true" [prevPath]="prevPath">
[isCard]="true" [isMobile]="isMobile" [prevPath]="prevPath">
</result-preview>
</li>
</ul>

View File

@ -2,19 +2,20 @@ import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'
import {SearchResult} from '../../utils/entities/searchResult';
import {EnvProperties} from '../../utils/properties/env-properties';
import {ResultPreview} from "../../utils/result-preview/result-preview";
import {HttpClient} from "@angular/common/http";
import {OrcidService} from "../../orcid/orcid.service";
import {Session} from "../../login/utils/helper.class";
import {properties} from "../../../../environments/environment";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {Subscription} from "rxjs";
@Component({
selector: 'search-result',
templateUrl: 'searchResult.component.html'
})
export class SearchResultComponent implements OnInit, OnChanges {
export class SearchResultComponent implements OnInit, OnChanges {
@Input() prevPath: string = "";
@Input() results: SearchResult[];
previewResults:ResultPreview[];
previewResults: ResultPreview[];
@Input() status: number;
@Input() type: string;
@Input() showLoading: boolean = false;
@ -23,62 +24,72 @@ export class SearchResultComponent implements OnInit, OnChanges {
@Input() custom_class: string = "";
@Input() properties: EnvProperties;
@Input() showEnermaps: boolean;
public isMobile: boolean = false;
private subscriptions: any[] = [];
constructor( private http: HttpClient/*ATHENA CODE*/
, private orcidService: OrcidService) {
constructor(private orcidService: OrcidService,
private layoutService: LayoutService) {
}
ngOnInit() {}
sub;
ngOnInit() {
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
}));
}
ngOnDestroy() {
if(this.sub){
this.sub.unsubscribe();
}
}
initialize(){
this.previewResults = [];
for(let result of this.results){
this.previewResults.push(this.getResultPreview(result));
}
if((properties.adminToolsPortalType == "explore" || properties.adminToolsPortalType == "community" || properties.adminToolsPortalType == "aggregator")
&& Session.isLoggedIn() && this.results && this.results.length > 0
&& (this.type == "result" || this.type == "publication" || this.type == "dataset" || this.type == "software" || this.type == "other")
) {
this.orcidService.getPutCodes(this.previewResults.map(
previewResult => {
if(previewResult.identifiers) {
let pidsArray: string[] = [];
for(let key of Array.from(previewResult.identifiers.keys())) {
pidsArray = pidsArray.concat(previewResult.identifiers.get(key));
}
return pidsArray;//.join();
}
})).subscribe(
putCodes => {
for (let i = 0; i < this.previewResults.length; i++) {
if(this.previewResults[i].identifiers) {
this.previewResults[i].orcidPutCodes = putCodes[i];
// console.debug(i, this.previewResults[i].orcidPutCodes);
}
}
}, error => {
}
);
}
this.subscriptions.forEach(subscription => {
if(subscription instanceof Subscription) {
subscription.unsubscribe();
}
})
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.results) {
if (changes.results) {
this.initialize();
}
}
public getResultPreview(result: SearchResult): ResultPreview {
return ResultPreview.searchResultConvert(result, (result.entityType)?result.entityType:this.type);
initialize() {
this.previewResults = [];
for (let result of this.results) {
this.previewResults.push(this.getResultPreview(result));
}
if ((properties.adminToolsPortalType == "explore" || properties.adminToolsPortalType == "community" || properties.adminToolsPortalType == "aggregator")
&& Session.isLoggedIn() && this.results && this.results.length > 0
&& (this.type == "result" || this.type == "publication" || this.type == "dataset" || this.type == "software" || this.type == "other")
) {
this.subscriptions.push(this.orcidService.getPutCodes(this.previewResults.map(
previewResult => {
if (previewResult.identifiers) {
let pidsArray: string[] = [];
for (let key of Array.from(previewResult.identifiers.keys())) {
pidsArray = pidsArray.concat(previewResult.identifiers.get(key));
}
return pidsArray;//.join();
}
})).subscribe(
putCodes => {
for (let i = 0; i < this.previewResults.length; i++) {
if (this.previewResults[i].identifiers) {
this.previewResults[i].orcidPutCodes = putCodes[i];
// console.debug(i, this.previewResults[i].orcidPutCodes);
}
}
}, error => {
}
));
}
}
public getResultPreview(result: SearchResult): ResultPreview {
return ResultPreview.searchResultConvert(result, (result.entityType) ? result.entityType : this.type);
}
public quote(params: string): string {
return '"' + params + '"';
}

View File

@ -169,6 +169,8 @@ export class SearchDataprovidersService {
if(resData['pid']) {
result.identifiers = this.parsingFunctions.parseIdentifiers(resData['pid']);
}
// Measure
result.measure = this.parsingFunctions.parseMeasures(resData['measure']);
results.push(result);
}

View File

@ -254,6 +254,8 @@ export class SearchProjectsService {
if(resData.hasOwnProperty("enddate")) {
result.endYear = resData.enddate.split('-')[0];
}
// Measure
result.measure = this.parsingFunctions.parseMeasures(resData['measure']);
results.push(result);
}

View File

@ -7,20 +7,20 @@ import {ParsingFunctions} from '../landingPages/landing-utils/parsingFunctions.c
import {EnvProperties} from '../utils/properties/env-properties';
import {map} from "rxjs/operators";
import {properties} from "../../../environments/environment";
import {HostedByCollectedFrom} from "../utils/result-preview/result-preview";
@Injectable()
export class SearchResearchResultsService {
private sizeOfDescription: number = 270;
public parsingFunctions: ParsingFunctions = new ParsingFunctions();
constructor(private http: HttpClient=null) {
constructor(private http: HttpClient = null) {
}
search(resultType: string, params: string, refineParams: string, page: number, size: number, sortBy: string, refineFields: string[], properties: EnvProperties): any {
let link = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true);
let url = link + "?";
if (params != null && params != '') {
url += params;
@ -32,21 +32,21 @@ export class SearchResearchResultsService {
url += "&sortBy=" + sortBy;
}
url += "&page=" + (page - 1) + "&size=" + size + "&format=json";
return this.http.get((properties.useCache) ? (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")]));
}
searchById(resultType: string, id: string, properties: EnvProperties): any {
let url = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true) + "/" + id + "?format=json";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => this.parseResults(resultType, res, properties)));
.pipe(map(res => this.parseResults(resultType, res, properties)));
}
searchAggregators(resultType: string, id: string, params: string, refineParams: string, page: number, size: number, properties: EnvProperties): any {
let link = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true);
let url = link + "?" + "&format=json";
if (params != null && params != '') {
url += params;
@ -55,33 +55,33 @@ export class SearchResearchResultsService {
url += refineParams;
}
url += "&page=" + (page - 1) + "&size=" + size;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => this.parseRefineResults(id, res['refineResults'])));
.pipe(map(res => this.parseRefineResults(id, res['refineResults'])));
}
searchByListOfDOI(resultType: string, DOIs: string[], refineParams: string, page: number, size: number, refineFields: string[], properties: EnvProperties): any {
let link = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true);
let url = link + "?" + "&format=json&";
var doisParams = "";
for (var i = 0; i < DOIs.length; i++) {
doisParams += (doisParams.length > 0 ? "&" : "") + 'doi="' + DOIs[i] + '"';
}
if (doisParams.length > 0) {
url += "&" + doisParams;
}
if (refineParams != null && refineParams != '') {
url += refineParams;
}
url += "&page=" + (page - 1) + "&size=" + size;
return this.http.get((properties.useCache) ? (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")]));
}
advancedSearch(resultType: string, params: string, page: number, size: number, sortBy: string, properties: EnvProperties, refineParams: string = null, refineFields: string[] = null, refineQuery: string = null): any {
let url = properties.searchResourcesAPIURL;
var basicQuery = "(oaftype exact result) and (resulttypeid exact " + this.getEntityQueryName(resultType, false) + ") ";
@ -101,14 +101,14 @@ export class SearchResearchResultsService {
if (refineQuery) {
url += "&" + refineQuery;
}
url += "&page=" + (page - 1) + "&size=" + size;
url += "&format=json";
return this.http.get((properties.useCache) ? (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")]));
}
advancedSearchResults(resultType: string, params: string, page: number, size: number, sortBy: string, properties: EnvProperties, refineParams: string = null, refineFields: string[] = null, refineQuery: string = null): any {
let url = properties.searchAPIURLLAst + "resources2/?format=json";
if (params != null && params != '') {
@ -124,30 +124,30 @@ export class SearchResearchResultsService {
if (refineQuery) {
url += "&" + refineQuery;
}
url += "&page=" + (page - 1) + "&size=" + size;
// url += "&format=json";
return this.http.get((properties.useCache) ? (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")]));
}
searchResultForEntity(resultType: string, params: string, page: number, size: number, properties: EnvProperties): any {
let link = properties.searchAPIURLLAst;
//let url = link+params+"/"+this.getEntityQueryName(resultType,true)+ "?format=json";
//url += "&page="+(page-1)+"&size="+size;
//url += "&sortBy=resultdateofacceptance,descending";
//let url = link+"/resources2?format=json&query="+params+" sortBy resultdateofacceptance/sort.descending&type="+this.getEntityQueryName(resultType,true);
let url = link + "/" + this.getEntityQueryName(resultType, true);
url += "?format=json";
url += "&fq=" + params;
url += "&sortBy=resultdateofacceptance,descending";
url += "&page=" + (page - 1) + "&size=" + size;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => [res['meta'].total, this.parseResults(resultType, res['results'], properties)]));
.pipe(map(res => [res['meta'].total, this.parseResults(resultType, res['results'], properties)]));
}
//???? why different from above?
@ -157,9 +157,9 @@ export class SearchResearchResultsService {
url += "&sortBy=resultdateofacceptance,descending";
url += "&page=" + (page - 1) + "&size=" + size + "&format=json";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => [res['meta'].total, this.parseResults(resultType, res['results'], properties)]));
.pipe(map(res => [res['meta'].total, this.parseResults(resultType, res['results'], properties)]));
}
searchForMyOrcidLinks(resultType: string, orcidQuery: string, typeQuery: string, page: number, size: number): any {
let url = properties.searchAPIURLLAst + "resources2/?format=json";
if (orcidQuery != null && orcidQuery != '') {
@ -167,14 +167,14 @@ export class SearchResearchResultsService {
}
url += typeQuery;
url += "&page=" + (page - 1) + "&size=" + size;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => [res['meta'].total, this.parseResults(resultType, res['results'], properties)]));
.pipe(map(res => [res['meta'].total, this.parseResults(resultType, res['results'], properties)]));
}
parseResults(resultType: string, data: any, properties: EnvProperties): SearchResult[] {
let results: SearchResult[] = [];
if(data == null) {
if (data == null) {
return results;
}
@ -182,139 +182,16 @@ export class SearchResearchResultsService {
for (let i = 0; i < length; i++) {
let resData = Array.isArray(data) ? data[i]['result']['metadata']['oaf:entity']['oaf:result'] : data['result']['metadata']['oaf:entity']['oaf:result'];
var result: SearchResult = new SearchResult();
if (resData['resulttype']) {
result.entityType = resData['resulttype']['classname'];
} else {
result.entityType = resultType;
}
result.types = new Array<string>();
let types = new Set<string>();
let instance;
let length = Array.isArray(resData['children']['instance']) ? resData['children']['instance'].length : 1;
for (let i = 0; i < length; i++) {
instance = Array.isArray(resData['children']['instance']) ? resData['children']['instance'][i] : resData['children']['instance'];
this.parsingFunctions.parseTypes(result.types, types, instance);
}
// Measure
result.measure = new Array<string>();
if (resData['measure'] && Array.isArray(resData['measure'])) {
for (let i = 0; i < resData['measure'].length; i++) {
if (resData['measure'][i].id == 'influence') {
result.measure[1] = resData['measure'][i].class;
if (resData['measure'][i].class == 'C1') {
result.measure[3] = 'Top 0.01% in';
} else if (resData['measure'][i].class == 'C2') {
result.measure[3] = 'Top 0.1% in';
} else if (resData['measure'][i].class == 'C3') {
result.measure[3] = 'Top 1% in';
} else if (resData['measure'][i].class == 'C4') {
result.measure[3] = 'Top 10% in';
} else if (resData['measure'][i].class == 'C5') {
result.measure[3] = 'Average/low';
} else if (resData['measure'][i].class == 'A') {
result.measure[3] = 'Exceptional';
} else if (resData['measure'][i].class == 'B') {
result.measure[3] = 'Substantial';
} else {
result.measure[3] = 'Average';
}
}
if (resData['measure'][i].id == 'popularity') {
result.measure[0] = resData['measure'][i].class;
if (resData['measure'][i].class == 'C1') {
result.measure[2] = 'Top 0.01% in';
} else if (resData['measure'][i].class == 'C2') {
result.measure[2] = 'Top 0.1% in';
} else if (resData['measure'][i].class == 'C3') {
result.measure[2] = 'Top 1% in';
} else if (resData['measure'][i].class == 'C4') {
result.measure[2] = 'Top 10% in';
} else if (resData['measure'][i].class == 'C5') {
result.measure[2] = 'Average/low';
} else if (resData['measure'][i].class == 'A') {
result.measure[2] = 'Exceptional';
} else if (resData['measure'][i].class == 'B') {
result.measure[2] = 'Substantial';
} else {
result.measure[2] = 'Average';
}
}
}
}
/////////////////////////// Athena Code ///////////////////////////
if (resData['pid']) {
if (!Array.isArray(resData['pid'])) {
if (resData['pid'].classid && resData['pid'].classid == 'doi') {
if (resData['pid'].content != '' && resData['pid'].content != null) {
result.DOIs.push((resData['pid'].content+"").replace("https://doi.org/", ""));
}
}
} else {
for (let i = 0; i < resData['pid'].length; i++) {
if (resData['pid'][i].classid == 'doi') {
if (resData['pid'][i].content != '' && resData['pid'][i].content != null && resData['pid'][i].content) {
result.DOIs.push((resData['pid'][i].content+"").replace("https://doi.org/", ""));
}
}
}
}
result.identifiers = this.parsingFunctions.parseIdentifiers(resData['pid']);
}
/////////////////////////// Athena Code ///////////////////////////
if (resData['programmingLanguage'] && resData['programmingLanguage'] != null) {
result.programmingLanguages = new Array<string>();
if (!Array.isArray(resData['programmingLanguage'])) {
if (resData['programmingLanguage'].classname != "Undetermined" && resData['programmingLanguage'].classname) {
result.programmingLanguages.push(resData['programmingLanguage'].classname);
}
} else {
for (let i = 0; i < resData['programmingLanguage'].length; i++) {
if (resData['programmingLanguage'][i].classname != "Undetermined" && resData['programmingLanguage'][i].classname) {
result.programmingLanguages.push(resData['programmingLanguage'][i].classname);
}
}
}
}
if (resData['language'] && resData['language'] != null) {
result.languages = new Array<string>();
if (!Array.isArray(resData['language'])) {
if (resData['language'].classname != "Undetermined" && resData['language'].classname) {
result.languages.push(resData['language'].classname);
}
} else {
for (let i = 0; i < resData['language'].length; i++) {
if (resData['language'][i].classname != "Undetermined" && resData['language'][i].classname) {
result.languages.push(resData['language'][i].classname);
}
}
}
}
if (resData['country'] && resData['country'] != null) {
result.countriesForResults = new Array<string>();
if (!Array.isArray(resData['country'])) {
if (resData['country'].classname != "Undetermined" && resData['country'].classname) {
result.countriesForResults.push(resData['country'].classname);
}
} else {
for (let i = 0; i < resData['country'].length; i++) {
if (resData['country'][i].classname != "Undetermined" && resData['country'][i].classname) {
result.countriesForResults.push(resData['country'][i].classname);
}
}
}
}
result['title'] = {"name": '', "accessMode": ''};
if (Array.isArray(resData['title'])) {
for (let i = 0; i < resData['title'].length; i++) {
if (resData['title'][i] && resData['title'][i].content) {
@ -333,7 +210,104 @@ export class SearchResearchResultsService {
} else {
result['title'].name = (resData['title'] && resData['title'].content) ? StringUtils.HTMLToString(String(resData['title'].content)) : "";
}
if (resData['bestaccessright'] && resData['bestaccessright'].hasOwnProperty("classname")) {
result['title'].accessMode = resData['bestaccessright'].classname;
}
result.types = new Array<string>();
let types = new Set<string>();
let instance;
let length = Array.isArray(resData['children']['instance']) ? resData['children']['instance'].length : 1;
result.hostedBy_collectedFrom = new Array<HostedByCollectedFrom>();
for (let i = 0; i < length; i++) {
instance = Array.isArray(resData['children']['instance']) ? resData['children']['instance'][i] : resData['children']['instance'];
this.parsingFunctions.parseTypes(result.types, types, instance);
if(instance?.hasOwnProperty("hostedby")) {
if(instance.hasOwnProperty("webresource")) {
let url = Array.isArray(instance['webresource'])?instance['webresource'][0].url:instance['webresource'].url;
if(url.includes('&amp;')) {
url = url.replace(/&amp;/gmu, '&');
}
if(instance.hasOwnProperty("hostedby")) {
this.parsingFunctions.parseHostedBy_collectedFrom(result.hostedBy_collectedFrom, instance, url, result.title.accessMode);
}
}
}
}
result.hostedBy_collectedFrom.sort(this.parsingFunctions.compareHostedByCollectedFrom);
// Measure
result.measure = this.parsingFunctions.parseMeasures(resData['measure']);
/////////////////////////// Athena Code ///////////////////////////
if (resData['pid']) {
if (!Array.isArray(resData['pid'])) {
if (resData['pid'].classid && resData['pid'].classid == 'doi') {
if (resData['pid'].content != '' && resData['pid'].content != null) {
result.DOIs.push((resData['pid'].content + "").replace("https://doi.org/", ""));
}
}
} else {
for (let i = 0; i < resData['pid'].length; i++) {
if (resData['pid'][i].classid == 'doi') {
if (resData['pid'][i].content != '' && resData['pid'][i].content != null && resData['pid'][i].content) {
result.DOIs.push((resData['pid'][i].content + "").replace("https://doi.org/", ""));
}
}
}
}
result.identifiers = this.parsingFunctions.parseIdentifiers(resData['pid']);
}
/////////////////////////// Athena Code ///////////////////////////
if (resData['programmingLanguage'] && resData['programmingLanguage'] != null) {
result.programmingLanguages = new Array<string>();
if (!Array.isArray(resData['programmingLanguage'])) {
if (resData['programmingLanguage'].classname != "Undetermined" && resData['programmingLanguage'].classname) {
result.programmingLanguages.push(resData['programmingLanguage'].classname);
}
} else {
for (let i = 0; i < resData['programmingLanguage'].length; i++) {
if (resData['programmingLanguage'][i].classname != "Undetermined" && resData['programmingLanguage'][i].classname) {
result.programmingLanguages.push(resData['programmingLanguage'][i].classname);
}
}
}
}
if (resData['language'] && resData['language'] != null) {
result.languages = new Array<string>();
if (!Array.isArray(resData['language'])) {
if (resData['language'].classname != "Undetermined" && resData['language'].classname) {
result.languages.push(resData['language'].classname);
}
} else {
for (let i = 0; i < resData['language'].length; i++) {
if (resData['language'][i].classname != "Undetermined" && resData['language'][i].classname) {
result.languages.push(resData['language'][i].classname);
}
}
}
}
if (resData['country'] && resData['country'] != null) {
result.countriesForResults = new Array<string>();
if (!Array.isArray(resData['country'])) {
if (resData['country'].classname != "Undetermined" && resData['country'].classname) {
result.countriesForResults.push(resData['country'].classname);
}
} else {
for (let i = 0; i < resData['country'].length; i++) {
if (resData['country'][i].classname != "Undetermined" && resData['country'][i].classname) {
result.countriesForResults.push(resData['country'][i].classname);
}
}
}
}
result['id'] = Array.isArray(data) ? data[i]['result']['header']['dri:objIdentifier'] : data['result']['header']['dri:objIdentifier'];
result['objId'] = result['id'];
let canId = ParsingFunctions.parseRelCanonicalId(Array.isArray(data) ? data[i] : data, "result");
@ -341,16 +315,13 @@ export class SearchResearchResultsService {
result['id'] = canId;
}
result['relcanId'] = result['id'];
if (resData['bestaccessright'] && resData['bestaccessright'].hasOwnProperty("classname")) {
result['title'].accessMode = resData['bestaccessright'].classname;
}
if (resData['rels'].hasOwnProperty("rel")) {
let relLength = Array.isArray(resData['rels']['rel']) ? resData['rels']['rel'].length : 1;
for (let j = 0; j < relLength; j++) {
let relation = Array.isArray(resData['rels']['rel']) ? resData['rels']['rel'][j] : resData['rels']['rel'];
if (relation.hasOwnProperty("to")) {
if (relation['to'].class && relation['to'].class.toLowerCase() == "isproducedby") {
result['projects'] = this.parseProjects(result['projects'], relation);
@ -358,22 +329,22 @@ export class SearchResearchResultsService {
}
}
}
if (resData.hasOwnProperty("creator") && resData['creator'] != null) {
if (result['authors'] == undefined) {
result['authors'] = new Array<{ "fullName": string, "orcid": string, "orcid_pending": string }>();
}
let authors = resData['creator'];
let length = Array.isArray(authors) ? authors.length : 1;
for (let i = 0; i < length; i++) {
let author = Array.isArray(authors) ? authors[i] : authors;
if (author) {
if(author.orcid) {
if (author.orcid) {
author.orcid = author.orcid.toUpperCase();
}
if(author.orcid_pending) {
if (author.orcid_pending) {
author.orcid_pending = author.orcid_pending.toUpperCase();
}
result['authors'][author.rank] = {
@ -387,20 +358,20 @@ export class SearchResearchResultsService {
return (item != undefined && item.fullName != undefined);
});
}
var date: string = (resData.dateofacceptance ? resData.dateofacceptance : '') + ''; // transform to string in case it is an integer
result.year = (date && (date).indexOf('-') !== -1) ? date.split('-')[0] : date;
let abstracts = this.parsingFunctions.parseDescription(resData.description, true);
result.description = abstracts;
result.description = abstracts;
// if (result.description && result.description.length > this.sizeOfDescription) {
// result.description = result.description.substring(0, this.sizeOfDescription) + "...";
// }
if (resData.embargoenddate && resData.embargoenddate != '') {
result.embargoEndDate = Dates.getDate(resData.embargoenddate);
}
if (!Array.isArray(resData.publisher)) {
result.publisher = resData.publisher;
} else {
@ -412,14 +383,44 @@ export class SearchResearchResultsService {
}
}
}
if(resData['context'] != null) {
if (resData['context'] != null) {
result.enermapsId = ParsingFunctions.getEnermapsConceptId(this.parsingFunctions.parseContexts(resData['context']));
}
if (resData.dateofacceptance && resData.dateofacceptance != null) {
let date: string = (resData.dateofacceptance ? resData.dateofacceptance : '') + ''; // transform to string in case it is an integer
result.date = (date && (date).indexOf('-') !== -1) ? date.split('-')[0] : date;
result.dateofacceptance = resData.dateofacceptance ? Dates.getDate(resData.dateofacceptance) : null;
}
if (resData.journal && resData.journal != null) {
result.journal = {
"journal": "",
"issn": "",
"lissn": "",
"eissn": "",
"issue": "",
"volume": "",
"start_page": "",
"end_page": ""
}
result.journal['journal'] = resData.journal.content;
result.journal['issn'] = resData.journal.issn;
result.journal['lissn'] = resData.journal.lissn;
result.journal['eissn'] = resData.journal.eissn;
result.journal['issue'] = resData.journal.iss;
result.journal['volume'] = resData.journal.vol;
result.journal['start_page'] = resData.journal.sp;
result.journal['end_page'] = resData.journal.ep;
}
result.hostedBy_collectedFrom = this.parsingFunctions.addPublisherToHostedBy_collectedFrom(
result.hostedBy_collectedFrom, result.publisher,
result['journal']?result['journal'].journal:null, result.identifiers);
results.push(result);
}
return results;
}
parseProjects(projects: {
"id": string, "acronym": string, "title": string,
"funderShortname": string, "funderName": string,
@ -436,15 +437,15 @@ export class SearchResearchResultsService {
"code": string
}>();
}
let countProjects = projects.length;
projects[countProjects] = {
"id": "", "acronym": "", "title": "",
"funderShortname": "", "funderName": "",
"code": ""
};
if (relation.title != 'unidentified') {
projects[countProjects]['id'] = relation['to'].content;
projects[countProjects]['acronym'] = relation.acronym;
@ -456,36 +457,36 @@ export class SearchResearchResultsService {
projects[countProjects]['title'] = "";
projects[countProjects]['code'] = "";
}
if (relation.hasOwnProperty("funding")) {
let fundingLength = Array.isArray(relation['funding']) ? relation['funding'].length : 1;
for (let z = 0; z < fundingLength; z++) {
let fundingData = Array.isArray(relation['funding']) ? relation['funding'][z] : relation['funding'];
if (fundingData.hasOwnProperty("funder")) {
projects[countProjects]['funderShortname'] = fundingData['funder'].shortname;
projects[countProjects]['funderName'] = fundingData['funder'].name;
}
}
}
return projects;
}
parseRefineResults(id: string, data: any): any {
var results: any = [];
if (data.hasOwnProperty("resulthostingdatasource")) {
let length = Array.isArray(data['resulthostingdatasource']) ? data['resulthostingdatasource'].length : 1;
for (let i = 0; i < length; i++) {
let datasource = Array.isArray(data['resulthostingdatasource']) ? data['resulthostingdatasource'][i] : data['resulthostingdatasource'];
let result: { "name": string, "id": string, "count": number } = {"name": "", "id": "", "count": 0};
result['name'] = datasource.name;
result['id'] = datasource.id.split("||")[0];
result['count'] = datasource.count;
if (result['id'] != id && result['name'] != "Unknown Repository") {
results.push(result);
}
@ -493,19 +494,19 @@ export class SearchResearchResultsService {
}
return results;
}
private numOfResults(url: string, properties: EnvProperties): any {
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => res['total']));
.pipe(map(res => res['total']));
}
numOfEntityResults(resultType: string, id: string, entity: string, properties: EnvProperties): any {
var parameters: string = "";
parameters = this.getEntityQueryName(entity, true) + "/" + id + "/" + this.getEntityQueryName(resultType, true) + "/count";
let url = properties.searchAPIURLLAst + parameters + "?format=json";
return this.numOfResults(url, properties);
}
numOfResearchOutcomes(params: string, properties: EnvProperties, refineParams: string = null): any {
let url = properties.searchAPIURLLAst + "resources2/?format=json&size=0&type=results";
if (params.length > 0) {
@ -522,20 +523,20 @@ export class SearchResearchResultsService {
// }
url += "&query=" + params;
}
if (refineParams != null && refineParams != '') {
url += refineParams;
}
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => res['meta']['total']));
.pipe(map(res => res['meta']['total']));
}
numOfSearchResults(resultType: string, params: string, properties: EnvProperties, refineParams: string = null): any {
let url = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true) + "/count?format=json";
if (params.length > 0) {
var DOIs: string[] = DOI.getDOIsFromString(params);
var doisParams = "";
for (var i = 0; i < DOIs.length; i++) {
doisParams += (doisParams.length > 0 ? "&" : "") + 'doi="' + DOIs[i] + '"';
}
@ -545,30 +546,30 @@ export class SearchResearchResultsService {
url += "&q=" + StringUtils.URIEncode(params);
}
}
if (refineParams != null && refineParams != '') {
url += refineParams;
}
return this.numOfResults(url, properties);
}
numOfSearchResultsLinkedToPub(resultType: string, properties: EnvProperties): any {
let url = properties.searchAPIURLLAst + "resources?query=" + encodeURIComponent("( (oaftype exact result) and (resulttypeid exact " + resultType + ") and (relresulttype=publication) )") + "&page=0&size=0&format=json";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => res['meta']['total']));
.pipe(map(res => res['meta']['total']));
}
countTotalResults(resultType: string, properties: EnvProperties, refineParams: string = null): any {
let url = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true) + "/count?format=json" + refineParams;
return this.numOfResults(url, properties);
}
/*
private quote(word: any): string {
return '"'+word+'"';
}
*/
private getEntityQueryName(entityType: string, plural: boolean) {
if (entityType == "publication" || entityType == "dataset" || entityType == "organization" || entityType == "datasource" || entityType == "project") {
if (plural) {
@ -582,8 +583,8 @@ export class SearchResearchResultsService {
}
public countCollectedResultsWithFundingInfo(datasourceId: string) {
let url = properties.searchAPIURLLAst + "resources?query=" + encodeURIComponent("(oaftype=result and collectedfromdatasourceid exact \""+datasourceId+"\" and relprojectid=*)") + "&page=0&size=0&format=json";
let url = properties.searchAPIURLLAst + "resources?query=" + encodeURIComponent("(oaftype=result and collectedfromdatasourceid exact \"" + datasourceId + "\" and relprojectid=*)") + "&page=0&size=0&format=json";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => res['meta']['total']));
.pipe(map(res => res['meta']['total']));
}
}

View File

@ -41,7 +41,7 @@ export class UserManagementService {
public updateUserInfo(resolve: Function = null) {
this.subscription = this.http.get<User>(properties.userInfoUrl, CustomOptions.registryOptions()).pipe(map(userInfo => {
return this.parseUserInfo(userInfo);
return new User(userInfo);
})).subscribe(user => {
this.getUserInfoSubject.next(user);
if (resolve) {
@ -54,39 +54,7 @@ export class UserManagementService {
}
});
}
private parseUserInfo(info: any) {
const user: User = new User();
user.id = (info.sub && info.sub.indexOf('@')) ? info.sub.substring(0, info.sub.indexOf('@')) : info.sub;
user.firstname = (info.given_name) ? info.given_name : "";
user.lastname = (info.family_name) ? info.family_name : "";
user.email = info.email.toLowerCase(); // TODO remove, is a quick fix
user.fullname = (info.name) ? info.name : "";
if (user.fullname == "") {
if (user.firstname != "") {
user.fullname += user.firstname;
}
if (user.lastname != "") {
user.fullname += user.lastname;
}
if (user.fullname == "") { //fullname is still empty set a default
user.fullname = "Anonymous user";
}
}
user.role = [];
if (info.roles) {
info.roles.forEach(role => {
user.role.push(role);
});
} else {
if (info.edu_person_entitlements) {
user.role = info.edu_person_entitlements;
}
}
user.expirationDate = info.exp_date;
return user;
}
public setRedirectUrl(url: string = null) {
if (url) {
let parts = url.split('?');

View File

@ -22,7 +22,10 @@ import {EntitiesSelectionComponent} from "../../searchPages/searchUtils/entities
<ng-content></ng-content>
</div>
</div>
<div class="uk-width-auto">
<div class="uk-width-auto filters-toggle">
<ng-content select="[filters-toggle]"></ng-content>
</div>
<div class="uk-width-auto" [class.uk-flex-first]="iconPosition === 'left'">
<div class="search-icon" [class.disabled]="disabled" (click)="searchEmitter.emit()">
<icon name="search" [flex]="true" ratio="1.3"></icon>
</div>
@ -34,6 +37,7 @@ import {EntitiesSelectionComponent} from "../../searchPages/searchUtils/entities
export class AdvancedSearchInputComponent implements AfterContentInit, OnDestroy {
@ContentChildren(InputComponent) inputs: QueryList<InputComponent>;
@ContentChildren(EntitiesSelectionComponent) entities: QueryList<EntitiesSelectionComponent>;
@Input() iconPosition: 'left' | 'right' = 'right';
@Input() disabled: boolean = false;
@Input() searchInputClass: string = 'inner';
@Input() dark: boolean;

View File

@ -113,7 +113,7 @@
<li><a target="_blank" href="https://www.openaire.eu/guides">Guides</a></li>
<li><a target="_blank" href="https://www.openaire.eu/faqs">FAQs</a></li>
<li><a target="_blank" href="https://www.openaire.eu/frontpage/webinars">Webinars</a></li>
<li><a target="_blank" href="https://www.openaire.eu/support/helpdesk">Ask a question</a></li>
<li><a target="_blank" href="https://www.openaire.eu/helpdesk">Ask a question</a></li>
</ul>
</div>
</div>

View File

@ -21,17 +21,19 @@ import {BehaviorSubject, Subscription} from "rxjs";
import {EnvProperties} from "../../utils/properties/env-properties";
import {properties} from "../../../../environments/environment";
import {ClickEvent} from "../../utils/click/click-outside-or-esc.directive";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {MobileDropdownComponent} from "../../utils/mobile-dropdown/mobile-dropdown.component";
export type InputType =
'text'
| 'URL'
| 'logoURL'
| 'autocomplete'
| 'autocomplete_soft'
| 'textarea'
| 'select'
| 'chips'
| 'year-range';
'text'
| 'URL'
| 'logoURL'
| 'autocomplete'
| 'autocomplete_soft'
| 'textarea'
| 'select'
| 'chips'
| 'year-range';
export interface Option {
icon?: string,
@ -70,144 +72,160 @@ declare var UIkit;
@Component({
selector: '[dashboard-input], [input]',
template: `
<div *ngIf="formControl" [id]="id">
<div class="input-wrapper" [class.disabled]="formControl.disabled" [class.opened]="opened"
[class.focused]="focused" [ngClass]="inputClass" [class.hint]="hint"
[class.active]="!focused && (formAsControl?.value || selectable || formAsArray?.length > 0 || getLabel(formAsControl?.value) || yearRangeActive)"
[class.danger]="(formControl.invalid && (formControl.touched || !!searchControl?.touched)) || (!!searchControl?.invalid && !!searchControl?.touched)">
<div #inputBox class="input-box" [class.select]="selectable" click-outside-or-esc
[class.static]="placeholderInfo?.static" (clickOutside)="click($event)">
<div *ngIf="!placeholderInfo?.static && placeholderInfo?.label" class="placeholder">
<label>{{placeholderInfo.label}} <sup *ngIf="required">*</sup></label>
</div>
<div class="uk-flex" [class.uk-flex-middle]="type !== 'textarea'"
[attr.uk-tooltip]="(tooltip && !focused && type !== 'chips' && type !== 'textarea' && (formControl.value || hint || placeholderInfo?.label))?('title: ' + (formControl.value ?getTooltip(formControl.value):(hint?hint:placeholderInfo?.label)) + '; delay: 500; pos: bottom-left'):null">
<ng-template [ngIf]="type === 'text' || type === 'URL' || type === 'logoURL'">
<input #input class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[type]="password?'password':'text'" [formControl]="formAsControl"
[class.uk-text-truncate]="!focused">
</ng-template>
<ng-template [ngIf]="type === 'textarea'">
<div *ngIf="formControl" [id]="id">
<div class="input-wrapper" [class.disabled]="formControl.disabled" [class.opened]="opened"
[class.focused]="focused" [ngClass]="inputClass" [class.hint]="hint"
[class.active]="!focused && (formAsControl?.value || selectable || formAsArray?.length > 0 || getLabel(formAsControl?.value) || yearRangeActive)"
[class.danger]="(formControl.invalid && (formControl.touched || !!searchControl?.touched)) || (!!searchControl?.invalid && !!searchControl?.touched)">
<div #inputBox class="input-box" [class.select]="selectable" click-outside-or-esc
[class.static]="placeholderInfo?.static" (clickOutside)="click($event)">
<div *ngIf="!placeholderInfo?.static && placeholderInfo?.label" class="placeholder">
<label>{{placeholderInfo.label}} <sup *ngIf="required">*</sup></label>
</div>
<div class="uk-flex" [class.uk-flex-middle]="type !== 'textarea'"
[attr.uk-tooltip]="(tooltip && !focused && type !== 'chips' && type !== 'textarea' && (formControl.value || hint || placeholderInfo?.label))?('title: ' + (formControl.value ?getTooltip(formControl.value):(hint?hint:placeholderInfo?.label)) + '; delay: 500; pos: bottom-left'):null">
<ng-template [ngIf]="type === 'text' || type === 'URL' || type === 'logoURL'">
<input #input class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[type]="password?'password':'text'" [formControl]="formAsControl"
[class.uk-text-truncate]="!focused">
</ng-template>
<ng-template [ngIf]="type === 'textarea'">
<textarea #textArea class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[rows]="rows" [formControl]="formAsControl"></textarea>
</ng-template>
<ng-template [ngIf]="type === 'select'">
<ng-container *ngIf="placeholderInfo?.static">
<div *ngIf="!getLabel(formControl.value)"
class="input placeholder uk-width-expand uk-text-truncate">{{placeholderInfo.label}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-width-expand uk-text-truncate">{{getLabel(formControl.value)}}</div>
</ng-container>
<ng-container *ngIf="!placeholderInfo?.static">
<div *ngIf="!getLabel(formControl.value)"
class="input uk-width-expand uk-text-truncate">{{noValueSelected}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-width-expand uk-text-truncate">{{getLabel(formControl.value)}}</div>
</ng-container>
</ng-template>
<ng-template [ngIf]="type === 'autocomplete'">
<input *ngIf="focused" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
#searchInput class="input" [formControl]="searchControl" [class.uk-text-truncate]="!focused">
<ng-container *ngIf="!focused && !selectable">
<div *ngIf="!getLabel(formControl.value)"
class="input placeholder uk-text-truncate">{{placeholderInfo?.static ? placeholderInfo.label : getLabel(formAsControl.value)}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-text-truncate">{{getLabel(formAsControl.value)}}</div>
</ng-container>
<ng-container *ngIf="!focused && selectable">
<div *ngIf="!getLabel(formControl.value)" class="input uk-text-truncate">{{noValueSelected}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-text-truncate">{{getLabel(formControl.value)}}</div>
</ng-container>
</ng-template>
<ng-template [ngIf]="type === 'autocomplete_soft'">
<input #input class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[formControl]="formAsControl" [class.uk-text-truncate]="!focused">
</ng-template>
<ng-template [ngIf]="type === 'chips'">
<div class="uk-grid uk-grid-small uk-grid-row-collapse uk-overflow-auto uk-width-expand"
[class.uk-flex-nowrap]="noWrap" [class.uk-overflow-auto]="noWrap" uk-grid>
<div *ngFor="let chip of formAsArray.controls; let i=index" #chip
[class.uk-hidden]="!focused && i > visibleChips - 1"
class="chip">
<div class="uk-label uk-label-small uk-text-transform-none uk-flex uk-flex-middle"
[attr.uk-tooltip]="(tooltip)?('title: ' + getLabel(chip.value) + '; delay: 500; pos: bottom-left'):null">
<span class="uk-text-truncate uk-width-expand">{{getLabel(chip.value)}}</span>
<icon *ngIf="focused" (click)="remove(i, $event)"
class="uk-link-text uk-margin-small-left clickable" [flex]="true"
name="close" ratio="0.7"></icon>
</ng-template>
<ng-template [ngIf]="type === 'select'">
<ng-container *ngIf="placeholderInfo?.static">
<div *ngIf="!getLabel(formControl.value)"
class="input placeholder uk-width-expand uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{placeholderInfo.label}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-width-expand uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{getLabel(formControl.value)}}</div>
</ng-container>
<ng-container *ngIf="!placeholderInfo?.static">
<div *ngIf="!getLabel(formControl.value)"
class="input uk-width-expand uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{noValueSelected}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-width-expand uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{getLabel(formControl.value)}}</div>
</ng-container>
</ng-template>
<ng-template [ngIf]="type === 'autocomplete'">
<input *ngIf="focused" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
#searchInput class="input" [formControl]="searchControl" [class.uk-text-truncate]="!focused">
<ng-container *ngIf="!focused && !selectable">
<div *ngIf="!getLabel(formControl.value)"
class="input placeholder uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{placeholderInfo?.static ? placeholderInfo.label : getLabel(formAsControl.value)}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{getLabel(formAsControl.value)}}</div>
</ng-container>
<ng-container *ngIf="!focused && selectable">
<div *ngIf="!getLabel(formControl.value)" class="input uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{noValueSelected}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{getLabel(formControl.value)}}</div>
</ng-container>
</ng-template>
<ng-template [ngIf]="type === 'autocomplete_soft'">
<input #input class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[formControl]="formAsControl" [class.uk-text-truncate]="!focused">
</ng-template>
<ng-template [ngIf]="type === 'chips'">
<div class="uk-grid uk-grid-small uk-grid-row-collapse uk-overflow-auto uk-width-expand"
[class.uk-flex-nowrap]="noWrap" [class.uk-overflow-auto]="noWrap" uk-grid>
<div *ngFor="let chip of formAsArray.controls; let i=index" #chip
[class.uk-hidden]="!focused && i > visibleChips - 1"
class="chip">
<div class="uk-label uk-label-small uk-text-transform-none uk-flex uk-flex-middle"
[attr.uk-tooltip]="(tooltip)?('title: ' + getLabel(chip.value) + '; delay: 500; pos: bottom-left'):null">
<span class="uk-text-truncate uk-width-expand">{{getLabel(chip.value)}}</span>
<icon *ngIf="focused" (click)="remove(i, $event)"
class="uk-link-text uk-margin-small-left clickable" [flex]="true"
name="close" ratio="0.7"></icon>
</div>
</div>
<div *ngIf="searchControl && (focused || formAsArray.length === 0)" #chip
class="uk-width-expand search-input uk-flex uk-flex-column uk-flex-center">
<input #searchInput class="input" [class.search]="searchControl.value"
[attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[formControl]="searchControl" [class.uk-text-truncate]="!focused">
</div>
<div *ngIf="!focused && formAsArray.length > visibleChips"
class="uk-width-expand uk-flex uk-flex-column uk-flex-center more">
+ {{(formAsArray.length - visibleChips)}} more
</div>
</div>
</ng-template>
<ng-template [ngIf]="type === 'year-range' && yearRange && formAsGroup">
<div class="uk-width-2-5">
<input #input class="input uk-text-center uk-text-truncate" [attr.placeholder]="yearRange.from.placeholder"
maxlength="4" (click)="activeIndex = 0;$event.preventDefault()" [formControl]="getFormByName(yearRange.from.control)">
</div>
<div class="uk-width-1-5 uk-text-center">-</div>
<div class="uk-width-2-5">
<input #input class="input uk-text-center uk-text-truncate" [attr.placeholder]="yearRange.to.placeholder"
maxlength="4" (click)="activeIndex = 1;$event.preventDefault()" [formControl]="getFormByName(yearRange.to.control)">
</div>
</ng-template>
<div
*ngIf="(formControl.disabled && disabledIcon) || icon || (selectable && selectArrow) || type === 'autocomplete' || searchable"
class="uk-margin-small-left icon">
<icon *ngIf="formControl.disabled && disabledIcon" [name]="disabledIcon" [flex]="true"></icon>
<ng-template [ngIf]="formControl.enabled">
<icon *ngIf="!searchControl?.value && icon" [name]="icon" [flex]="true"></icon>
<icon *ngIf="!icon && selectable && selectArrow" [name]="selectArrow" [flex]="true"></icon>
<button *ngIf="focused && type === 'autocomplete' && (!selectable || searchControl.value)" class="uk-close uk-icon"
(click)="resetSearch($event)">
<icon [flex]="true" name="close"></icon>
</button>
<button *ngIf="(!focused && type === 'autocomplete' && !selectable) || (type !== 'autocomplete' && !searchControl?.value && !!formControl?.value && (searchable || !selectable))"
class="uk-close uk-icon" (click)="resetValue($event)">
<icon [flex]="true" name="close"></icon>
</button>
</ng-template>
</div>
<!-- use action-icon class in order to apply css in your icon button-->
<ng-content select="[action]"></ng-content>
</div>
<div class="tools">
<ng-content select="[tools]"></ng-content>
</div>
</div>
<div *ngIf="searchControl && (focused || formAsArray.length === 0)" #chip
class="uk-width-expand search-input uk-flex uk-flex-column uk-flex-center">
<input #searchInput class="input" [class.search]="searchControl.value"
[attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[formControl]="searchControl" [class.uk-text-truncate]="!focused">
</div>
<div *ngIf="!focused && formAsArray.length > visibleChips"
class="uk-width-expand uk-flex uk-flex-column uk-flex-center more">
+ {{(formAsArray.length - visibleChips)}} more
</div>
</div>
</ng-template>
<ng-template [ngIf]="type === 'year-range' && yearRange && formAsGroup">
<div class="uk-width-2-5">
<input #input class="input uk-text-center uk-text-truncate" [attr.placeholder]="yearRange.from.placeholder"
maxlength="4" (click)="activeIndex = 0;$event.preventDefault()" [formControl]="getFormByName(yearRange.from.control)">
</div>
<div class="uk-width-1-5 uk-text-center">-</div>
<div class="uk-width-2-5">
<input #input class="input uk-text-center uk-text-truncate" [attr.placeholder]="yearRange.to.placeholder"
maxlength="4" (click)="activeIndex = 1;$event.preventDefault()" [formControl]="getFormByName(yearRange.to.control)">
</div>
</ng-template>
<div
*ngIf="(formControl.disabled && disabledIcon) || icon || (selectable && selectArrow) || type === 'autocomplete' || searchable"
class="uk-margin-small-left icon">
<icon *ngIf="formControl.disabled && disabledIcon" [name]="disabledIcon" [flex]="true"></icon>
<ng-template [ngIf]="formControl.enabled">
<icon *ngIf="!searchControl?.value && icon" [name]="icon" [flex]="true"></icon>
<icon *ngIf="!icon && selectable && selectArrow" [name]="selectArrow" [flex]="true"></icon>
<button *ngIf="!!searchControl?.value && type === 'autocomplete'" class="uk-close uk-icon"
(click)="resetSearch($event)">
<icon [flex]="true" name="close"></icon>
</button>
<button *ngIf="!searchControl?.value && !!formControl?.value && (searchable || !selectable)"
class="uk-close uk-icon" (click)="resetValue($event)">
<icon [flex]="true" name="close"></icon>
</button>
</ng-template>
</div>
<!-- use action-icon class in order to apply css in your icon button-->
<ng-content select="[action]"></ng-content>
</div>
<div class="tools">
<ng-content select="[tools]"></ng-content>
</div>
</div>
</div>
<div class="options uk-dropdown" *ngIf="filteredOptions && filteredOptions.length > 0 && opened" #optionBox
uk-dropdown="pos: bottom-justify; mode: none; offset: 15; boundary-align: true;" [attr.boundary]="'#' + id">
<ul class="uk-nav uk-dropdown-nav">
<li *ngFor="let option of filteredOptions; let i=index" [class.uk-hidden]="option.hidden"
[class.uk-active]="(formControl.value === option.value) || selectedIndex === i">
<a (click)="selectOption(option, $event)"
[class]="option.disabled ? 'uk-disabled uk-text-muted' : ''">
<div *ngIf="!mobile && filteredOptions && filteredOptions.length > 0 && opened" class="options uk-dropdown" #optionBox
uk-dropdown="pos: bottom-justify; mode: none; offset: 15; boundary-align: true;" [attr.boundary]="'#' + id">
<ul class="uk-nav uk-dropdown-nav">
<li *ngFor="let option of filteredOptions; let i=index" [class.uk-hidden]="option.hidden"
[class.uk-active]="(formControl.value === option.value) || selectedIndex === i">
<a (click)="selectOption(option, $event)"
[class]="option.disabled ? 'uk-disabled uk-text-muted' : ''">
<span
[attr.uk-tooltip]="(tooltip)?('title: ' + (option.tooltip ? option.tooltip : option.label) + '; delay: 500; pos:bottom-left'):null">{{option.label}}</span>
</a>
</li>
</ul>
[attr.uk-tooltip]="(tooltip)?('title: ' + (option.tooltip ? option.tooltip : option.label) + '; delay: 500; pos:bottom-left'):null">{{option.label}}</span>
</a>
</li>
</ul>
</div>
<mobile-dropdown *ngIf="mobile" #mobileDropdown>
<div *ngIf="placeholderInfo" class="uk-text-emphasis uk-text-bolder uk-text-center uk-padding-small uk-padding-remove-vertical uk-text-uppercase">
{{placeholderInfo.label}}
</div>
<div class="uk-padding uk-padding-remove-horizontal">
<ul class="uk-nav uk-nav-default">
<li *ngFor="let option of filteredOptions; let i=index" [class.uk-hidden]="option.hidden"
[class.uk-active]="formControl.value === option.value">
<a (click)="selectOption(option, $event)"
[class]="option.disabled ? 'uk-disabled uk-text-muted' : ''">
<span>{{option.label}}</span>
</a>
</li>
</ul>
</div>
</mobile-dropdown>
</div>
</div>
<span *ngIf="formControl?.invalid && formControl?.touched" class="uk-text-danger">
<span *ngIf="formControl?.invalid && formControl?.touched" class="uk-text-danger">
<span *ngIf="errors?.error">{{errors?.error}}</span>
<span *ngIf="type === 'URL' || type === 'logoURL'">Please provide a valid URL (e.g. https://example.com)</span>
</span>
<span class="uk-text-small uk-text-danger">
<span class="uk-text-small uk-text-danger">
<ng-content select="[error]"></ng-content>
</span>
<span *ngIf="formControl?.valid" class="uk-text-small uk-text-warning uk-margin-xsmall-top">
<span *ngIf="formControl?.valid" class="uk-text-small uk-text-warning uk-margin-xsmall-top">
<ng-content select="[warning]"></ng-content>
<span *ngIf="!secure">
<span class="uk-text-bold">Note:</span> Prefer urls like "<span class="uk-text-bold">https://</span>example.com/my-secure-image.png"
@ -215,9 +233,9 @@ declare var UIkit;
<span class="uk-text-bold">Browsers may not load non secure content.</span>
</span>
</span>
<i class="uk-text-small uk-text-meta uk-margin-xsmall-top">
<ng-content select="[note]"></ng-content>
</i>
<i class="uk-text-small uk-text-meta uk-margin-xsmall-top">
<ng-content select="[note]"></ng-content>
</i>
`
})
export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChanges {
@ -261,7 +279,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
/** Year Range Configuration */
@Input() yearRange: YearRange;
public activeIndex: 0 | 1 | null = null;
@Input() visibleRows: number = -1;
@Input() extendEnter: () => void = null;
@Output() focusEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
@ -273,6 +291,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
public required: boolean = false;
public focused: boolean = false;
public opened: boolean = false;
public mobile: boolean = false;
public properties: EnvProperties = properties;
private initValue: any;
private optionsArray: Option[] = [];
@ -280,9 +299,10 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
private subscriptions: any[] = [];
@ViewChild('inputBox') inputBox: ElementRef;
@ViewChild('optionBox') optionBox: ElementRef;
@ViewChild('mobileDropdown') mobileDropdown: MobileDropdownComponent;
@ViewChild('searchInput') searchInput: ElementRef;
@ViewChildren('chip') chips: QueryList<ElementRef>;
@Input()
set placeholder(placeholder: string | Placeholder) {
if(this.type === 'year-range') {
@ -297,7 +317,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.placeholderInfo = placeholder;
}
}
@Input()
set options(options: (Option | string | number) []) {
this.optionsArray = options.map(option => {
@ -322,16 +342,16 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.selectable = true;
}
}
constructor(private elementRef: ElementRef, private cdr: ChangeDetectorRef) {
constructor(private elementRef: ElementRef, private cdr: ChangeDetectorRef, private layoutService: LayoutService) {
if (elementRef.nativeElement.hasAttribute('dashboard-input') && this.properties.environment === "development") {
console.warn("'dashboard-input' selector is deprecated; use 'input' instead.");
}
}
@HostListener('window:keydown.arrowUp', ['$event'])
arrowUp(event: KeyboardEvent) {
if (this.opened) {
if (this.opened && this.optionBox) {
event.preventDefault();
if (this.selectedIndex > 0) {
this.selectedIndex--;
@ -339,10 +359,10 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
}
}
@HostListener('window:keydown.arrowDown', ['$event'])
arrowDown(event: KeyboardEvent) {
if (this.opened) {
if (this.opened && this.optionBox) {
event.preventDefault();
if (this.selectedIndex < (this.filteredOptions.length - 1)) {
this.selectedIndex++;
@ -350,7 +370,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
}
}
@HostListener('window:keydown.arrowLeft', ['$event'])
arrowLeft(event: KeyboardEvent) {
if (this.type === 'chips' && this.focused) {
@ -364,7 +384,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
}
}
@HostListener('window:keydown.arrowRight', ['$event'])
arrowRight(event: KeyboardEvent) {
if (this.type === 'chips' && this.focused) {
@ -378,9 +398,12 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
}
}
@HostListener('window:keydown.enter', ['$event'])
enter(event: KeyboardEvent) {
if (this.extendEnter) {
this.extendEnter();
}
if (this.opened && this.optionBox) {
event.preventDefault();
if (this.filteredOptions[this.selectedIndex]) {
@ -391,11 +414,8 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
} else {
this.focus(false, event);
}
if (this.extendEnter) {
this.extendEnter();
}
}
@HostListener('keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
if (this.separators.includes(event.key) || this.separators.includes(event.key.toLowerCase())) {
@ -403,12 +423,16 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.add(event, true);
}
}
click(event: ClickEvent) {
this.focus(!event.clicked, event);
this.focus(!event.clicked);
}
ngOnInit() {
this.subscriptions.push(this.layoutService.isMobile.subscribe(mobile => {
this.mobile = mobile;
this.cdr.detectChanges();
}));
InputComponent.INPUT_COUNTER++;
this.id = 'input-' + InputComponent.INPUT_COUNTER;
if (!this.formControl) {
@ -430,11 +454,11 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
})
}
ngAfterViewInit() {
this.reset();
}
ngOnChanges(changes: SimpleChanges) {
if (this.formControl) {
if (changes.value) {
@ -455,11 +479,11 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
}
}
ngOnDestroy(): void {
this.unsubscribe();
}
getFormByName(name: string): UntypedFormControl {
if (this.formControl instanceof UntypedFormGroup) {
return <UntypedFormControl>this.formControl.get(name);
@ -467,7 +491,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
return null;
}
}
get formAsGroup(): UntypedFormGroup {
if (this.formControl instanceof UntypedFormGroup) {
return this.formControl;
@ -475,7 +499,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
return null;
}
}
get formAsControl(): UntypedFormControl {
if (this.formControl instanceof UntypedFormControl) {
return this.formControl;
@ -483,7 +507,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
return null;
}
}
get formAsArray(): UntypedFormArray {
if (this.formControl instanceof UntypedFormArray) {
return this.formControl;
@ -491,26 +515,26 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
return null;
}
}
get yearRangeActive(): boolean {
if(this.yearRange) {
return this.formAsGroup && (this.getFormByName(this.yearRange.from.control)?.value || this.getFormByName(this.yearRange.to.control)?.value);
}
return false;
}
get errors(): any {
if(this.formAsGroup) {
return (this.formAsGroup.errors
?this.formAsGroup.errors:(this.getFormByName(this.yearRange.from.control).errors
?this.getFormByName(this.yearRange.from.control).errors:this.getFormByName(this.yearRange.to.control).errors));
?this.formAsGroup.errors:(this.getFormByName(this.yearRange.from.control).errors
?this.getFormByName(this.yearRange.from.control).errors:this.getFormByName(this.yearRange.to.control).errors));
} else if(this.formAsControl) {
return this.formAsControl.errors;
} else {
return this.searchControl.errors;
}
}
reset() {
this.secure = true;
this.unsubscribe();
@ -532,8 +556,10 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
if (this.focused) {
this.open(true);
setTimeout(() => {
this.searchInput.nativeElement.focus();
this.searchInput.nativeElement.value = value;
if(this.searchInput) {
this.searchInput.nativeElement.focus();
this.searchInput.nativeElement.value = value;
}
}, 0);
}
}));
@ -599,7 +625,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
});
}
}
unsubscribe() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) {
@ -607,7 +633,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
});
}
updateValidators() {
if (this.formAsArray) {
this.formAsArray.controls.forEach(control => {
@ -619,7 +645,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.formControl.updateValueAndValidity();
}
}
remove(index: number, event) {
if (this.focused) {
this.formAsArray.removeAt(index);
@ -629,7 +655,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
event.stopPropagation();
}
}
private filter(value: string): Option[] {
let options = this.optionsArray.filter(option => !option.hidden);
if (this.type === "chips") {
@ -640,14 +666,14 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
return (this.showOptionsOnEmpty) ? options : [];
}
const filterValue = value.toString().toLowerCase();
options = options.filter(option => option.label.toLowerCase().indexOf(filterValue) != -1);
options = options.filter(option => (option.label && option.label.toLowerCase().indexOf(filterValue) != -1));
this.selectedIndex = options.findIndex(option => option.value === this.formControl.value);
if (this.selectedIndex === -1) {
this.selectedIndex = 0;
}
return options;
}
add(event, addChips = false) {
if (addChips && this.searchControl.value) {
this.splitSearchControl();
@ -655,7 +681,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.searchControl.setValue('');
}
}
splitSearchControl() {
let values = [this.searchControl.value];
this.separators.forEach(separator => {
@ -679,17 +705,17 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.searchControl.setValue('');
}
}
getLabel(value: any): string {
let option = this.optionsArray.find(option => HelperFunctions.equals(option.value, value));
return (option) ? option.label : (value);
}
getTooltip(value: any): string {
let option = this.optionsArray.find(option => HelperFunctions.equals(option.value, value));
return (option) ? (option.tooltip ? option.tooltip : option.label) : (value);
}
focus(value: boolean, event = null) {
if(!this.activeIndex) {
this.activeIndex = 0;
@ -697,70 +723,81 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
if (this.focused) {
this.formControl.markAsTouched();
}
this.focused = value;
this.cdr.detectChanges();
if (this.focused) {
if (this.input?.length > 0) {
this.input.get(this.activeIndex).nativeElement.focus();
} else if (this.textArea) {
this.textArea.nativeElement.focus();
} else if (this.searchInput) {
this.searchInput.nativeElement.focus();
this.activeElement.next(this.chips.last);
}
if (this.selectArrow) {
this.open(!this.opened);
} else if (this.type !== 'autocomplete' || this.showOptionsOnEmpty || !this.formControl.value) {
this.open(true);
}
} else {
this.activeIndex = null;
this.open(false);
if (this.input) {
this.input.forEach(input => {
input.nativeElement.blur();
})
} else if (this.textArea) {
this.textArea.nativeElement.blur();
} else if (this.searchInput) {
this.searchInput.nativeElement.blur();
}
if (this.searchControl) {
this.add(event, this.addExtraChips);
if(this.formControl.enabled) {
this.focused = value;
this.cdr.detectChanges();
if (this.focused) {
if (this.input?.length > 0) {
this.input.get(this.activeIndex).nativeElement.focus();
} else if (this.textArea) {
this.textArea.nativeElement.focus();
} else if (this.searchInput) {
this.searchInput.nativeElement.focus();
this.activeElement.next(this.chips.last);
}
if (this.selectArrow) {
this.open(!this.opened);
} else if (this.type !== 'autocomplete' || this.showOptionsOnEmpty || !this.formControl.value) {
this.open(true);
}
} else {
this.activeIndex = null;
this.open(false);
if (this.input) {
this.input.forEach(input => {
input.nativeElement.blur();
})
} else if (this.textArea) {
this.textArea.nativeElement.blur();
} else if (this.searchInput) {
this.searchInput.nativeElement.blur();
}
if (this.searchControl) {
this.add(event, this.addExtraChips);
}
}
this.focusEmitter.emit(this.focused);
}
this.focusEmitter.emit(this.focused);
}
open(value: boolean) {
this.opened = value && this.formControl.enabled;
this.cdr.detectChanges();
if (this.optionBox && this.opened) {
this.selectedIndex = this.filteredOptions.findIndex(option => option.value === this.formControl.value);
if (this.selectedIndex === -1 && this.type !== 'autocomplete_soft') {
this.selectedIndex = 0;
}
UIkit.dropdown(this.optionBox.nativeElement).show();
} else {
if (this.optionBox) {
if(this.optionBox) {
if (this.opened) {
this.selectedIndex = this.filteredOptions.findIndex(option => option.value === this.formControl.value);
if (this.selectedIndex === -1 && this.type !== 'autocomplete_soft') {
this.selectedIndex = 0;
}
UIkit.dropdown(this.optionBox.nativeElement).show();
} else {
UIkit.dropdown(this.optionBox.nativeElement).hide();
this.focused = false;
}
} else if(this.mobileDropdown) {
if(this.opened) {
this.mobileDropdown.open();
if(this.searchInput) {
this.searchInput.nativeElement.blur();
}
} else {
this.mobileDropdown.close();
}
}
}
resetSearch(event: any) {
event.stopPropagation();
this.searchControl.setValue('');
this.focus(true, event);
}
resetValue(event: any) {
event.stopPropagation();
this.formControl.setValue('');
this.focus(true, event);
}
selectOption(option: Option, event) {
if (this.formControl.enabled) {
if (this.formAsControl) {

View File

@ -4,13 +4,15 @@ import {SharedModule} from "../../../openaireLibrary/shared/shared.module";
import {IconsModule} from "../../utils/icons/icons.module";
import {SafeHtmlPipeModule} from "../../utils/pipes/safeHTMLPipe.module";
import {ClickModule} from "../../utils/click/click.module";
import {MobileDropdownModule} from "../../utils/mobile-dropdown/mobile-dropdown.module";
@NgModule({
imports: [
SharedModule,
IconsModule,
SafeHtmlPipeModule,
ClickModule
ClickModule,
MobileDropdownModule
],
exports: [
InputComponent

View File

@ -41,12 +41,12 @@
*ngIf="isAtleastOneEnabled(menu.entitiesRequired,showEntity) && isAtleastOneEnabled(menu.routeRequired, showPage)">
<!--a routerLink="{{menu.rootItem.route}}" [queryParams]=menu.rootItem.params class="uk-offcanvas-close custom-offcanvas-close">{{menu.rootItem.title}}</a-->
<a *ngIf="menu.route && (isEnabled([menu.route], showPage) || !menu.routeRequired)"
routerLink="{{menu.route}}" (click)="menu.items.length === 0?closeCanvas(canvas):null"
[routerLink]="menu.items.length === 0?menu.route:null" (click)="menu.items.length === 0?closeCanvas(canvas):null"
[queryParams]="menu.params"
[fragment]="menu.fragment">{{menu.title}}</a>
<a *ngIf="!menu.route && menu.url"
href="{{menu.url}}" (click)="menu.items.length === 0?closeCanvas(canvas):null" [class.custom-external]="menu.target != '_self'"
target="{{menu.target}}">{{menu.title}}</a>
[href]="menu.items.length === 0?menu.url:null" (click)="menu.items.length === 0?closeCanvas(canvas):null"
[class.custom-external]="menu.target != '_self'" [target]="menu.target">{{menu.title}}</a>
<a *ngIf="(!menu.route && !menu.url) ||
(menu.route && menu.routeRequired && !isEnabled([menu.route], showPage)
&& isAtleastOneEnabled(menu.routeRequired, showPage))"
@ -144,6 +144,9 @@
<ng-content select="[extra-s]"></ng-content>
</ng-container>
</ul>
<div *ngIf="hasSearchBar" search-input [(value)]="keyword" placeholder="Search"
[searchInputClass]="'flat background small-vertical'" (searchEmitter)="goTo(canvas)"
class="uk-width-1-1 uk-padding-small uk-margin-medium-top"></div>
</div>
</div>
</div>
@ -170,12 +173,28 @@
<ng-container *ngIf="!activeHeader.menuPosition || activeHeader.menuPosition === 'center'">
<ng-container *ngTemplateOutlet="mainMenu"></ng-container>
</ng-container>
<div *ngIf="searchMode" #search_input search-input [(value)]="keyword" placeholder="Search"
[searchInputClass]="'flat background small-vertical'" (searchEmitter)="goTo()"
class="uk-width-large@l uk-width-medium uk-width-xlarge@xl"></div>
</div>
<div class="uk-navbar-right">
<ng-container *ngIf="activeHeader.menuPosition === 'right'">
<ng-container *ngTemplateOutlet="mainMenu"></ng-container>
</ng-container>
<user-mini *ngIf="userMenu" [user]="user"
<div *ngIf="searchMode" class="uk-flex uk-flex-middle uk-margin-medium-right" (click)="searchMode = false">
<div class="search-icon clickable">
<icon name="close" [flex]="true" ratio="1.5" visuallyHidden="close search mode"></icon>
</div>
</div>
<div *ngIf="!searchMode && hasSearchBar" class="uk-flex uk-flex-middle uk-margin-right" (click)="openSearch($event)">
<div class="search-icon clickable">
<icon name="search" [flex]="true" ratio="1" visuallyHidden="search"></icon>
</div>
</div>
<user-mini *ngIf="!searchMode && userMenu" [user]="user"
[userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl [logOutUrl]=properties.logoutUrl
[cookieDomain]=properties.cookieDomain></user-mini>
<div class="uk-visible@m">
@ -183,7 +202,7 @@
</div>
</div>
<ng-template #mainMenu>
<ul class="uk-navbar-nav" [class.uk-margin-right]="!userMenu">
<ul *ngIf="!searchMode" class="uk-navbar-nav" [class.uk-margin-right]="!userMenu">
<li class="uk-parent" *ngIf="showHomeMenuItem && currentRoute.route !== '/'">
<a routerLink="/">Home</a>
</li>

View File

@ -1,4 +1,13 @@
import {ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core';
import {
ChangeDetectorRef,
Component, ElementRef,
Input,
OnChanges,
OnDestroy,
OnInit, QueryList,
SimpleChanges, ViewChild,
ViewChildren
} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Session, User} from '../login/utils/helper.class';
import {ConfigurationService} from '../utils/configuration/configuration.service';
@ -9,6 +18,9 @@ import {HelpContentService} from '../services/help-content.service';
import {properties} from "../../../environments/environment";
import {LayoutService} from "../dashboard/sharedComponents/sidebar/layout.service";
import {NotificationConfiguration} from "../notifications/notifications-sidebar/notifications-sidebar.component";
import {SearchInputComponent} from "./search-input/search-input.component";
import {Filter} from "../searchPages/searchUtils/searchHelperClasses.class";
import {RouterHelper} from "../utils/routerHelper.class";
declare var UIkit;
@ -57,6 +69,7 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
subs: Subscription[] = [];
showEntity = {};
showPage = {};
public searchMode: boolean = false;
public additionalMenuItems: MenuItem[] = [];
public featuredMenuItems: MenuItem[] = [];
@ -64,13 +77,28 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
public isFeaturedMenuEnabled: boolean = false;
public featuredAlignment: string = MenuAlignment.CENTER.valueOf();
public hasSearchBar: boolean = false;
public resultsQuickFilter: { filter: Filter, selected: boolean, filterId: string, value: string } = {
filter: null,
selected: true,
filterId: "resultbestaccessright",
value: "Open Access"
};
@ViewChild('search_input') search_input: SearchInputComponent;
public routerHelper: RouterHelper = new RouterHelper();
constructor(private router: Router,
private route: ActivatedRoute,
private config: ConfigurationService,
private _helpContentService: HelpContentService,
private layoutService: LayoutService) {}
private layoutService: LayoutService,
private cdr: ChangeDetectorRef) {}
ngOnInit() {
this.subs.push(this.route.queryParams.subscribe(params => {
this.searchMode = false;
this.keyword = "";
}));
this.initialize();
}
@ -145,6 +173,9 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
this.subs.push(this.layoutService.replaceHeader.subscribe(replaceHeader => {
this.setHeader(replaceHeader);
}));
this.subs.push(this.layoutService.hasMenuSearchBar.subscribe(hasSearchBar => {
this.hasSearchBar = hasSearchBar;
}));
}
setHeader(replaceHeader: boolean) {
@ -204,4 +235,32 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
// return MenuItem.isTheActiveMenu(item, this.currentRoute, this.layoutService.activeMenuItem);
// }
}
openSearch(event) {
event.stopPropagation();
this.searchMode = true;
this.cdr.detectChanges();
this.search_input.input.focus(true);
}
goTo(canvas = null) {
let parameterNames = [];
let parameterValues = [];
if (this.resultsQuickFilter && this.resultsQuickFilter.selected) {
parameterNames.push(this.resultsQuickFilter.filterId);
parameterValues.push('"' + encodeURIComponent(this.resultsQuickFilter.value) + '"');
}
if (this.keyword.length > 0) {
parameterNames.push("fv0");
parameterValues.push(this.keyword);
parameterNames.push("f0");
parameterValues.push("q");
}
this.router.navigate([this.properties.searchLinkToAll ? this.properties.searchLinkToAll : this.properties.searchLinkToResults], {queryParams: this.routerHelper.createQueryParams(parameterNames, parameterValues)});
if(canvas) {
this.closeCanvas(canvas);
}
}
}

Some files were not shown because too many files have changed in this diff Show More