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){ 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) { 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)); return this.cachingRequests.some(partUrl => (url.indexOf(partUrl) !== -1));
} }

View File

@ -1,5 +1,5 @@
<div> <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> <advanced-search-input>
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..." <div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..."
[options]="showOptions.selectOptions" class="uk-width-2-5"></div> [options]="showOptions.selectOptions" class="uk-width-2-5"></div>

View File

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

View File

@ -168,7 +168,7 @@ export class ShowOptions {
this.basketShowSources = false; this.basketShowSources = false;
} }
showLinkTo() { showLinkTo() {
console.log(this.linkTo, "showLinkTo") // console.log(this.linkTo, "showLinkTo")
this.show = this.linkTo; this.show = this.linkTo;
this.basketswitchToLinkTo(); this.basketswitchToLinkTo();
HelperFunctions.scroll(); 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)"> <advanced-search-input (searchEmitter)="search(page,size)">
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..." <div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..."
[options]="showOptions.selectOptions" class="uk-width-2-5"></div> [options]="showOptions.selectOptions" class="uk-width-2-5"></div>

View File

@ -21,6 +21,7 @@ declare var UIkit:any;
}) })
export class ClaimProjectsSearchFormComponent { export class ClaimProjectsSearchFormComponent {
public query = ''; public query = '';
@Input() public centerAlign: boolean = false;
@Input() public selectedProjects:ClaimEntity[]=[] ; @Input() public selectedProjects:ClaimEntity[]=[] ;
public elementRef; 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)"> <advanced-search-input (searchEmitter)="search(true)">
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..." <div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..."
[options]="showOptions.selectOptions" class="uk-width-2-5"></div> [options]="showOptions.selectOptions" class="uk-width-2-5"></div>
@ -8,7 +8,7 @@
</div> </div>
<div *ngIf="!showOptions" class="uk-width-xlarge@l uk-width-large"> <div *ngIf="!showOptions" class="uk-width-xlarge@l uk-width-large">
<div search-input [(value)]="keyword" [placeholder]="'Search for ' + openaireEntities.RESULTS.toLowerCase() + '...'" <div search-input [(value)]="keyword" [placeholder]="'Search for ' + openaireEntities.RESULTS.toLowerCase() + '...'"
(searchEmitter)="search(true)"></div> [searchInputClass]="'inner background'" (searchEmitter)="search(true)"></div>
</div> </div>
<div *ngIf="!showSearchResults"> <div *ngIf="!showSearchResults">
<div class="uk-text-center uk-text-large uk-text-meta uk-margin-large-top"> <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"; source: string = "datacite";
type: string = "dataset"; type: string = "dataset";
showSearchResults: boolean = false; showSearchResults: boolean = false;
@Input() public centerAlign: boolean = false;
@Input() public select: boolean = true; @Input() public select: boolean = true;
@Input() public keyword: string = ''; @Input() public keyword: string = '';
@Input() public selectedResults: ClaimEntity[]; @Input() public selectedResults: ClaimEntity[];

View File

@ -6,13 +6,9 @@ declare var UIkit: any;
@Component({ @Component({
selector: 'claim-results', selector: 'claim-results',
template: ` template: `
<div *ngIf="results.length > 0 " class="uk-margin-top"> <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 *ngFor="let entity of results" class="uk-card">
<div> <div class="uk-padding-small">
<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 class="uk-grid"> <div class="uk-grid">
<div class="uk-width-expand uk-margin-right"> <div class="uk-width-expand uk-margin-right">
<claim-title [entity]="entity" [showIcon]="false"></claim-title> <claim-title [entity]="entity" [showIcon]="false"></claim-title>
@ -20,27 +16,29 @@ declare var UIkit: any;
<claim-project-metadata [entity]="entity"></claim-project-metadata> <claim-project-metadata [entity]="entity"></claim-project-metadata>
</div> </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':''"> <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)"> (click)="add(entity)">
<icon name="add" [flex]="true"></icon> <icon name="add" [flex]="true"></icon>
</button> </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> <icon name="check" [flex]="true"></icon>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>`, </div>
`
}) })
export class ClaimResultsComponent { export class ClaimResultsComponent {
@Input() results: ClaimEntity[]; @Input() results: ClaimEntity[];
@Input() selectedResults: ClaimEntity[]; @Input() selectedResults: ClaimEntity[];
@Input() localStoragePrefix: string = ""; @Input() localStoragePrefix: string = "";
@Input() basketLimit; @Input() basketLimit;
ngOnInit() {
}
public isSelected(item: ClaimEntity) { public isSelected(item: ClaimEntity) {
return !!this.selectedResults.find(result => item.id === result.id); return !!this.selectedResults.find(result => item.id === result.id);
} }

View File

@ -16,7 +16,7 @@
</div> </div>
<div [class.uk-padding]="actions" class="uk-padding-remove-vertical"> <div [class.uk-padding]="actions" class="uk-padding-remove-vertical">
<div class="uk-margin-medium-top"> <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> [totalResults]="resultsNum" customClasses="uk-margin-remove"></results-and-pages>
</div> </div>
<div class="uk-grid uk-flex-middle uk-margin-medium-top" uk-grid> <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) { handleErrors(err, message) {
NotificationHandler.rise(message, "danger"); 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) { goTo(page: number = 1) {
@ -290,7 +290,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
} }
changeKeyword() { 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); this.searchTermStream.next(this.filterForm.get("keyword").value);
} }
} }

View File

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

View File

@ -10,6 +10,7 @@ import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {OpenaireEntities} from "../../utils/properties/searchFields"; import {OpenaireEntities} from "../../utils/properties/searchFields";
import {StringUtils} from "../../utils/string-utils.class"; import {StringUtils} from "../../utils/string-utils.class";
import {ClaimProjectsSearchFormComponent} from "../claim-utils/claimProjectSearchForm.component";
@Component({ @Component({
@ -152,6 +153,7 @@ export class DirectLinkingComponent {
entity.type = "project"; entity.type = "project";
entity.title = project.projectName; entity.title = project.projectName;
entity.project = new ClaimProject(); entity.project = new ClaimProject();
entity.project.url = properties.searchLinkToProject + entity.id;
entity.project.acronym = project.projectAcronym; entity.project.acronym = project.projectAcronym;
entity.project.code = project.code; entity.project.code = project.code;
entity.project.endDate = project.endDate; 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="linking uk-background-default">
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom"> <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"> <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> </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"> <div class="uk-section-xsmall">
<stepper> <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)" [stepText]="'Find Sources'" (stepChanged)="stepHasChanged($event)"
[active]="this.showOptions.show" [showStepLine]="false"></step> [active]="this.showOptions.show" [showStepLine]="false"></step>
<step [status]="stepStatus('target')" stepId="target" [stepNumber]="inlineEntity?1:2" <step [status]="stepStatus('target')" stepId="target" [stepNumber]="2"
[stepText]="'Link Source' + (inlineEntity?'':'s') + ' to Entities'" [stepText]="'Link Sources to Entities'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show" (stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show"
[showStepLine]="!inlineEntity"></step> [showStepLine]="true"></step>
<step [status]="stepStatus('claim')" stepId="claim" [stepNumber]="inlineEntity?2:3" <step [status]="stepStatus('claim')" stepId="claim" [stepNumber]="3"
[stepText]="'Summarize and finish'" [stepText]="'Summarize and finish'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show" (stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show"
[showStepLine]="true"></step> [showStepLine]="true"></step>
@ -37,16 +78,18 @@
<div [class]="((showOptions.show == 'claim')?'':' uk-margin-top ')+' uk-container uk-container-large '"> <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-grid basketContainer" *ngIf="showOptions.show!='claim'" uk-grid>
<div class="uk-width-2-3 uk-position-z-index"> <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'"> <div *ngIf="showOptions.show=='source'">
<claim-result-search-form [selectedResults]="sources" [properties]=properties <claim-result-search-form [selectedResults]="sources" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'" [localStoragePrefix]="localStoragePrefix+'sources'"
[basketLimit]="basketLimit" [basketLimit]="basketLimit" [centerAlign]="!!inlineEntity"
></claim-result-search-form> ></claim-result-search-form>
</div> </div>
<div *ngIf="showOptions.show=='project'"> <div *ngIf="showOptions.show=='project'">
<claim-projects-search-form [selectedProjects]="results" [properties]=properties <claim-projects-search-form [selectedProjects]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'" [localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions" [basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-projects-search-form> ></claim-projects-search-form>
</div> </div>
<div *ngIf="showOptions.show=='context'"> <div *ngIf="showOptions.show=='context'">
@ -54,12 +97,14 @@
[properties]=properties [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'" [localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions" [basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-contexts-search-form> ></claim-contexts-search-form>
</div> </div>
<div *ngIf="showOptions.show=='result'"> <div *ngIf="showOptions.show=='result'">
<claim-result-search-form [selectedResults]="results" [properties]=properties <claim-result-search-form [selectedResults]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'" [localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions" [basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-result-search-form> ></claim-result-search-form>
</div> </div>
</div> </div>
@ -69,78 +114,70 @@
<div class="uk-card uk-card-default linkingBasket"> <div class="uk-card uk-card-default linkingBasket">
<div class="uk-card-body uk-padding-small"> <div class="uk-card-body uk-padding-small">
<div class="uk-margin-right"> <div class="uk-margin-right">
<ul class="uk-tab" uk-tab> <ng-container *ngIf="inlineEntity">
<li [class.uk-active]="showOptions.basketShowSources" <div class="uk-margin-small-bottom">
(click)="showOptions.basketswitchToSources()"> <div class="uk-text-emphasis uk-text-bolder">Source</div>
<a> <claim-selected-results [results]="[inlineEntity]"
Sources to link ({{(sources.length + (inlineEntity ? 1 : 0)) |number}}) [localStoragePrefix]="localStoragePrefix+'sources'" class=""
</a> [enableRemove]="false" type="source">
</li> </claim-selected-results>
<li [class.uk-disabled]="sources.length == 0 && !inlineEntity" </div>
[class.uk-active]="showOptions.basketShowLinksTo"> <div class="uk-padding-small uk-padding-remove-horizontal"><hr class="uk-margin-remove"/></div>
<a (click)="showOptions.basketswitchToLinkTo()">Link to <span <div class="uk-margin-small-top">
*ngIf="results.length> 0">({{(results.length) | number}})</span> <div class="uk-text-emphasis uk-text-bolder">Link source to <span *ngIf="results.length> 0">({{(results.length) | number}})</span></div>
</a> <ng-container *ngTemplateOutlet="destinations_basket"></ng-container>
</li> </div>
</ul> </ng-container>
<div *ngIf="showOptions.basketShowSources">
<div class="uk-height-medium uk-overflow-auto"> <ng-container *ngIf="!inlineEntity">
<div *ngIf="showOptions.show == 'source'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height:17px;"> <ul class="uk-tab" uk-tab>
<start-over *ngIf="showOptions.show == 'source' && sources.length> 0" <li [class.uk-active]="showOptions.basketShowSources"
[results]="sources" (click)="showOptions.basketswitchToSources()">
[localStoragePrefix]="localStoragePrefix+'sources'" <a>
message="all sources" class="uk-float-right"></start-over> Sources to link ({{(sources.length) |number}})
<bulk-claim *ngIf="showOptions.show == 'source'" [results]="sources" </a>
[properties]=properties </li>
[localStoragePrefix]="localStoragePrefix+'sources'" [basketLimit]="basketLimit" <li [class.uk-disabled]="sources.length == 0"
> [class.uk-active]="showOptions.basketShowLinksTo">
</bulk-claim> <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>
<div *ngIf="sources.length >= basketLimit " class="uk-alert uk-alert-warning uk-text-center"> <div class="uk-padding-small uk-padding-remove-horizontal">
Basket reached the size limit. No more sources can be added. <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> </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>
</div> <div *ngIf="showOptions.basketShowLinksTo">
<div *ngIf="showOptions.basketShowLinksTo"> <div class="uk-height-medium uk-overflow-auto">
<div class="uk-height-medium uk-overflow-auto"> <ng-container *ngTemplateOutlet="destinations_basket"></ng-container>
<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> </div>
</div> </div>
</div> </ng-container>
</div> </div>
</div> </div>
<div *ngIf="showOptions.show == 'source'" <div *ngIf="showOptions.show == 'source'"
@ -164,7 +201,7 @@
<button class="uk-flex uk-flex-middle uk-button uk-button-text" <button class="uk-flex uk-flex-middle uk-button uk-button-text"
[class.uk-disabled]="results.length == 0" [disabled]="results.length == 0"> [class.uk-disabled]="results.length == 0" [disabled]="results.length == 0">
<icon *ngIf="inlineEntity" name="link" visuallyHidden="link" [flex]="true"></icon> <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> </button>
</div> </div>
</div> </div>

View File

@ -13,6 +13,9 @@ import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component"; import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
import {OpenaireEntities} from "../../utils/properties/searchFields"; 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({ @Component({
selector: 'linking-generic', selector: 'linking-generic',
@ -44,10 +47,12 @@ export class LinkingGenericComponent {
@ViewChild(AlertModal) alert; @ViewChild(AlertModal) alert;
public pageContents = null; public pageContents = null;
@Input() breadcrumbs: Breadcrumb[] = []; @Input() breadcrumbs: Breadcrumb[] = [];
public routerHelper: RouterHelper = new RouterHelper();
constructor (private _router: Router, private route: ActivatedRoute, private entitySearch:EntitiesSearchService, constructor (private _router: Router, private route: ActivatedRoute, private entitySearch:EntitiesSearchService,
private _meta: Meta, private _title: Title, private _piwikService:PiwikService, 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 = []; subscriptions = [];
@ -161,6 +166,7 @@ export class LinkingGenericComponent {
this.showOptions.show = 'claim'; this.showOptions.show = 'claim';
} }
this.cdr.detectChanges(); this.cdr.detectChanges();
HelperFunctions.scroll(true);
console.log('stepHasChanged', stepId, this.showOptions.show) 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({ @Component({
selector: 'claim-project-metadata', selector: 'claim-project-metadata',
template: ` template: `
<div *ngIf="entity.type == 'project' && entity.project" class="uk-text-small uk-flex uk-flex-wrap" [style.grid-gap]="shortVersion?'10px':'20px'"> <ng-container *ngIf="entity.type == 'project' && entity.project">
<div *ngIf="entity.project.funderName"> <div *ngIf="!shortVersion" class="claim-entity-metadata uk-flex-inline uk-flex-wrap uk-text-xsmall uk-text-emphasis"
<span class="uk-text-meta">Funder: </span>{{entity.project.funderName}} [class.uk-margin-xsmall-top]="!shortVersion">
</div> <span class="uk-text-capitalize">
<div *ngIf="entity.project.code"> {{entity.type}}
<span class="uk-text-meta">GrandID: </span>{{entity.project.code}} </span>
</div> <span *ngIf="entity.project.startDate || entity.project.endDate">
<div *ngIf=" !shortVersion && (entity.project.startDate || entity.project.endDate)"> {{(entity.project.startDate) ? entity.project.startDate : 'Unknown'}}{{'-' + ((entity.project.endDate) ? entity.project.endDate : 'Unknown')}}
<span class="uk-text-meta">Duration: </span>{{(entity.project.startDate) ? entity.project.startDate : 'Unknown'}}{{'-' + ((entity.project.endDate) ? entity.project.endDate : 'Unknown')}} </span>
</div> </div>
</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({ @Component({
selector: 'claim-result-metadata', selector: 'claim-result-metadata',
template: ` template: `
<div *ngIf="entity.result" class="uk-text-small"> <div *ngIf="entity.result">
<div *ngIf="entity.result.authors && entity.result.authors.length >0 " class="uk-margin-small-bottom"> <!-- display all existing data similar to entity-metadata -->
<span class="uk-text-meta">Authors: </span>{{sliceArray(entity.result.authors)}} <div *ngIf="!shortVersion" class="claim-entity-metadata uk-flex-inline uk-flex-wrap uk-text-xsmall uk-text-emphasis uk-margin-xsmall-top">
</div> <span class="uk-text-capitalize uk-text-italic">
<div *ngIf="!shortVersion && entity.result.editors&& entity.result.editors.length > 0" class="uk-margin-small-bottom"> {{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
<span class="uk-text-meta">Editors: </span>{{sliceArray(entity.result.editors)}} </span>
</div> <span *ngIf="entity.result.publisher!=null">
<div *ngIf="!shortVersion" class="uk-flex uk-flex-wrap" style="grid-gap: 20px;"> {{entity.result.publisher}}
<span *ngIf="entity.result.publisher!=null">
<span class="uk-text-meta uk-margin-small-bottom">Publisher: </span>{{entity.result.publisher}}
</span> </span>
<span *ngIf="entity.result.journal!=null"> <span *ngIf="entity.result.date">
<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 [class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')">{{entity.result.date}}</span> <span [class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')">{{entity.result.date}}</span>
</span> </span>
<div [class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')">{{getProjectDurationMessage(entity)}} <span *ngIf="entity.result.journal!=null">
</div> {{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>
</div> </div>
` `,
styleUrls: ['ClaimEntityMetadata.component.less']
}) })

View File

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

View File

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

View File

@ -23,7 +23,7 @@ export class Layout {
variables['@global-background'] = Layout.convertRGBAtoRGB(options.backgrounds.light.color); 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-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-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) { if (options.buttons) {
//general //general
@ -174,6 +174,9 @@ export class CustomizationOptions {
} }
public static checkForObsoleteVersion(current: CustomizationOptions, communityId: string) { 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 defaultCO = new CustomizationOptions(CustomizationOptions.getIdentity(communityId).mainColor, CustomizationOptions.getIdentity(communityId).secondaryColor);
let updated = Object.assign({}, defaultCO); let updated = Object.assign({}, defaultCO);
if (!current) { if (!current) {
@ -197,7 +200,7 @@ export class CustomizationOptions {
if (!current.backgrounds.form.position) { if (!current.backgrounds.form.position) {
current.backgrounds.form.position = "center bottom" current.backgrounds.form.position = "center bottom"
} }
if (!current.backgrounds.form.fontsDarkMode) { if (current.backgrounds.form.fontsDarkMode == undefined) {
current.backgrounds.form.fontsDarkMode = true; current.backgrounds.form.fontsDarkMode = true;
} }
if (!current.buttons) { 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" <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> [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" <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" <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" <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" <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" <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" <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" <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" <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" <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" <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" <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"> <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> <re-captcha #captchaElem (resolved)="handleRecaptcha($event)" [siteKey]="properties.reCaptchaSiteKey"></re-captcha>
</div> </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 *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 === 'page'"><a routerLink="../pages">Pages</a></li>
<li [class.uk-active]="tab === 'entity'"><a routerLink="../entities">Entities</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="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" [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="isPortalAdmin && portal=='connect'" [class.uk-active]="tab === 'customization'"><a routerLink="../customization">Customization</a></li>
</ul> </ul>
` `
}) })
@ -25,7 +25,7 @@ export class AdminTabsComponent implements OnInit {
@Input() @Input()
public user: User; public user: User;
@Input() @Input()
public tab: "portal" | "page" | "entity" | "menu" | "class" | "customization"= 'page'; public tab: "portal" | "page" | "entity" | "menu" | "class" | "customization" = 'page';
private subscriptions: any[] = []; private subscriptions: any[] = [];
constructor(private route: ActivatedRoute, private userManagementService: UserManagementService) { constructor(private route: ActivatedRoute, private userManagementService: UserManagementService) {

View File

@ -75,6 +75,11 @@ export class LayoutService {
private isMobileSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); private isMobileSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
/** Active sidebar Item*/ /** Active sidebar Item*/
private activeSidebarItemSubject: BehaviorSubject<SidebarItem> = new BehaviorSubject<SidebarItem>(null); 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[] = []; private subscriptions: any[] = [];
ngOnDestroy() { ngOnDestroy() {
@ -166,6 +171,12 @@ export class LayoutService {
} else { } else {
this.setActiveMenuItem(''); this.setActiveMenuItem('');
} }
if (data['hasMenuSearchBar'] !== undefined &&
data['hasMenuSearchBar'] === true) {
this.setHasMenuSearchBar(true);
} else {
this.setHasMenuSearchBar(false);
}
} }
})); }));
this.setObserver(); this.setObserver();
@ -292,4 +303,12 @@ export class LayoutService {
setActiveSidebarItem(value: SidebarItem) { setActiveSidebarItem(value: SidebarItem) {
this.activeSidebarItemSubject.next(value); 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>
</div> </div>
<modal-alert #inviteModal (alertOutput)="invite()" [overflowBody]="false" classTitle="uk-background-primary uk-light" <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 *ngIf="message" class="uk-margin-medium-bottom uk-text-small">
<div [innerHTML]="message | safeHtml"></div> <div [innerHTML]="message | safeHtml"></div>
</div> </div>
<div *ngIf="invited"> <div *ngIf="emailsForm">
<div input [formInput]="invited" <div #emailInput input [formInput]="emailsForm" type="chips"
placeholder="Email"></div> placeholder="Recipients" hint="Add a recipient" [visibleChips]="3"
[addExtraChips]="true" [validators]="validators" [separators]="[',']">
<div note>Separate emails with commas</div>
</div>
</div> </div>
</modal-alert> </modal-alert>
<modal-alert #deleteModal [overflowBody]="false" (alertOutput)="deleteActive()" classTitle="uk-background-primary uk-light"> <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 {
import {UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators} from '@angular/forms'; 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 {AlertModal} from "../../../utils/modal/alert";
import {UserRegistryService} from "../../../services/user-registry.service"; import {UserRegistryService} from "../../../services/user-registry.service";
import {EnvProperties} from "../../../utils/properties/env-properties"; import {EnvProperties} from "../../../utils/properties/env-properties";
@ -9,9 +25,22 @@ import {UserManagementService} from "../../../services/user-management.service";
import {Router} from "@angular/router"; import {Router} from "@angular/router";
import {StringUtils} from "../../../utils/string-utils.class"; import {StringUtils} from "../../../utils/string-utils.class";
import {NotificationService} from "../../../notifications/notification.service"; import {NotificationService} from "../../../notifications/notification.service";
import {Subscription} from "rxjs"; import {forkJoin, of, Subscription} from "rxjs";
import {NotificationHandler} from "../../../utils/notification-handler"; import {NotificationHandler} from "../../../utils/notification-handler";
import {ClearCacheService} from "../../../services/clear-cache.service"; 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({ @Component({
selector: 'role-users', selector: 'role-users',
@ -49,7 +78,8 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
public loadActive: boolean = true; public loadActive: boolean = true;
public loadPending: boolean = true; public loadPending: boolean = true;
public selectedUser: string = null; public selectedUser: string = null;
public invited: UntypedFormControl; public emailsForm: UntypedFormArray;
public validators: ValidatorFn[] = [Validators.email];
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public exists: boolean = true; public exists: boolean = true;
public roleFb: UntypedFormGroup; public roleFb: UntypedFormGroup;
@ -60,6 +90,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
/** Search */ /** Search */
filterForm: UntypedFormGroup; filterForm: UntypedFormGroup;
@ViewChild('inviteModal') inviteModal: AlertModal; @ViewChild('inviteModal') inviteModal: AlertModal;
@ViewChild('emailInput') emailInput: InputComponent;
@ViewChild('deleteModal') deleteModal: AlertModal; @ViewChild('deleteModal') deleteModal: AlertModal;
@ViewChild('deletePendingModal') deletePendingModal: AlertModal; @ViewChild('deletePendingModal') deletePendingModal: AlertModal;
@ViewChild('createRoleModal') createRoleModal: AlertModal; @ViewChild('createRoleModal') createRoleModal: AlertModal;
@ -69,6 +100,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
private clearCacheService: ClearCacheService, private clearCacheService: ClearCacheService,
private notificationService: NotificationService, private notificationService: NotificationService,
private router: Router, private router: Router,
private cdr: ChangeDetectorRef,
private fb: UntypedFormBuilder) { private fb: UntypedFormBuilder) {
} }
@ -172,7 +204,8 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
this.inviteModal.alertTitle = 'Invite ' + this.role; this.inviteModal.alertTitle = 'Invite ' + this.role;
this.inviteModal.okButtonLeft = false; this.inviteModal.okButtonLeft = false;
this.inviteModal.okButtonText = 'Send'; 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(); this.inviteModal.open();
} }
@ -224,33 +257,56 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
this.loadPending = false; this.loadPending = false;
})); }));
} }
get valid() {
return this.emailsForm && this.emailsForm.valid || (this.emailInput && this.emailInput.searchControl.getRawValue() && this.emailInput.searchControl.valid);
}
invite() { invite() {
if(this.emailInput.searchControl.getRawValue() && this.emailInput.searchControl.valid) {
this.emailInput.add(null,true);
}
this.showCurrent = false; this.showCurrent = false;
this.loadPending = true; this.loadPending = true;
this.selectedUser = this.invited.value; let current = null;
let details = { let invitations = (<Array<any>>this.emailsForm.value).map(email => {
link: this.link, current = email;
email: this.emailComposer(this.name, this.invited.value, this.role) return this.userRegistryService.invite(this.type, this.id, {
} link: this.link,
this.subs.push(this.userRegistryService.invite(this.type, this.id, details, this.role).subscribe(invitation => { email: this.emailComposer(this.name, email, this.role)
if (!this.pending.includes(this.invited.value)) { }, this.role).pipe(map(invitation => new InvitationResponse(email, invitation), catchError(error => {
this.pending.push(this.invited.value); 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.pendingPage = Math.ceil(this.pending.length / this.pageSize);
this.filterPendingBySearch(this.filterForm.value.pending); this.filterPendingBySearch(this.filterForm.value.pending);
} this.loadPending = false;
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;
})); }));
} }

View File

@ -29,7 +29,8 @@ import {SearchForm} from "../searchPages/searchUtils/newSearchPage.component";
<div class="uk-container uk-container-large"> <div class="uk-container uk-container-large">
<div class="uk-margin-top uk-flex uk-flex-center"> <div class="uk-margin-top uk-flex uk-flex-center">
<div class="uk-width-large" [class.dark]="searchForm.dark"> <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"> <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"> <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"> <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 {Observable, throwError, TimeoutError} from "rxjs";
import {catchError} from "rxjs/operators"; import {catchError} from "rxjs/operators";
import {Session} from "./login/utils/helper.class"; 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 {LoginErrorCodes} from "./login/utils/guardHelper.class";
import {properties} from "../../environments/environment"; import {properties} from "../../environments/environment";
import * as url from "url";
@Injectable() @Injectable()
export class ErrorInterceptorService implements HttpInterceptor { 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 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) { 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>> { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
@ -42,7 +52,7 @@ export class ErrorInterceptorService implements HttpInterceptor {
this.router.navigate(['/user-info'], { this.router.navigate(['/user-info'], {
queryParams: { queryParams: {
'errorCode': LoginErrorCodes.NOT_LOGIN, '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'], { this.router.navigate(['/user-info'], {
queryParams: { queryParams: {
'errorCode': LoginErrorCodes.NOT_AUTHORIZED, '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"> <ul *ngIf="keyword?.length" class="uk-tab uk-tab-left">
<li *ngFor="let item of viewResults; index as i" <li *ngFor="let item of viewResults; index as i"
class="uk-margin-small-bottom uk-text-capitalize" [class.uk-active]="activeSection === item.id"> 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> </li>
</ul> </ul>
</div> </div>

View File

@ -15,10 +15,10 @@
<span>Fields of Science <span class="uk-text-primary">.</span></span> <span>Fields of Science <span class="uk-text-primary">.</span></span>
</h1> </h1>
<div uk-scrollspy-class> <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>
<div class="uk-text-meta uk-margin-top" uk-scrollspy-class> <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> </div>
<!-- TODO: We need a page for the button link --> <!-- TODO: We need a page for the button link -->
<!-- <div> <!-- <div>
@ -113,7 +113,7 @@
<div *ngFor="let subChild of child.children" style="margin-bottom: 5px;"> <div *ngFor="let subChild of child.children" style="margin-bottom: 5px;">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subChild.id)}" <a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subChild.id)}"
class="uk-link-text"> class="uk-link-text">
{{subChild.id}} {{subChild.label}}
</a> </a>
</div> </div>
</div> </div>
@ -139,7 +139,7 @@
</h3> </h3>
<div *ngFor="let subSubItem of subItem.children" style="margin-bottom: 5px;"> <div *ngFor="let subSubItem of subItem.children" style="margin-bottom: 5px;">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subSubItem.id)}" <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> </a>
</div> </div>
</div> </div>

View File

@ -26,7 +26,7 @@ declare var UIkit;
export class FosComponent implements OnInit, OnDestroy { export class FosComponent implements OnInit, OnDestroy {
public url: string = null; public url: string = null;
public pageTitle: string = "OpenAIRE | Fields of Science"; 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; @Input() piwikSiteId = null;
public fos: any[] = []; 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 {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser'; 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 {ResultPreview} from "../../utils/result-preview/result-preview";
import {IndexInfoService} from "../../utils/indexInfo.service"; import {IndexInfoService} from "../../utils/indexInfo.service";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {Subscriber} from "rxjs"; import {Subscriber, Subscription, zip} from "rxjs";
import {TabComponent} from "../../utils/tabs/tab.component";
import {OpenaireEntities} from "../../utils/properties/searchFields"; 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; declare var ResizeObserver;
@ -64,16 +67,21 @@ export class DataProviderComponent {
public metricsClicked: boolean; public metricsClicked: boolean;
public viewsFrameUrl: string; public viewsFrameUrl: string;
public downloadsFrameUrl: string; public downloadsFrameUrl: string;
public totalViews: number; /** @deprecated*/
public totalDownloads: number; public totalViews: number = null;
public pageViews: number; /** @deprecated*/
public totalDownloads: number = null;
public hasViews: boolean = false;
public hasDownloads: boolean = false;
// public pageViews: number;
// Statistics tab variables // Statistics tab variables
public statsClicked: boolean = false; public statsClicked: boolean = false;
// @ViewChild('statisticsModal') statisticsModal; // @ViewChild('statisticsModal') statisticsModal;
// @ViewChild('relatedDatasourcesModal') relatedDatasourcesModal; // @ViewChild('relatedDatasourcesModal') relatedDatasourcesModal;
@ViewChild('addThisModal') addThisModal @ViewChild('addThisModal') addThisModal;
@ViewChild('addThisFsModal') addThisFsModal: FullScreenModalComponent;
// Variables for publications, research data, projects, datasources, related datasources tabs // Variables for publications, research data, projects, datasources, related datasources tabs
public fetchPublications: FetchResearchResults; public fetchPublications: FetchResearchResults;
@ -144,9 +152,25 @@ export class DataProviderComponent {
// public shouldSticky: boolean = true; // public shouldSticky: boolean = true;
subscriptions = []; subscriptions = [];
private sub: Subscription;
properties: EnvProperties = properties; properties: EnvProperties = properties;
public openaireEntities = OpenaireEntities; 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, constructor(private _dataproviderService: DataProviderService,
private _piwikService: PiwikService, private _piwikService: PiwikService,
private route: ActivatedRoute, private route: ActivatedRoute,
@ -160,7 +184,9 @@ export class DataProviderComponent {
private helper: HelperService, private helper: HelperService,
private _location: Location, private _location: Location,
private indexInfoService: IndexInfoService, private indexInfoService: IndexInfoService,
private cdr: ChangeDetectorRef) { private metricsService: MetricsService,
private cdr: ChangeDetectorRef,
private layoutService: LayoutService) {
this.fetchPublications = new FetchResearchResults(this._searchResearchResultsService); this.fetchPublications = new FetchResearchResults(this._searchResearchResultsService);
this.fetchDatasets = new FetchResearchResults(this._searchResearchResultsService); this.fetchDatasets = new FetchResearchResults(this._searchResearchResultsService);
this.fetchSoftware = new FetchResearchResults(this._searchResearchResultsService); this.fetchSoftware = new FetchResearchResults(this._searchResearchResultsService);
@ -171,6 +197,9 @@ export class DataProviderComponent {
} }
ngOnInit() { ngOnInit() {
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
}));
if (typeof document !== 'undefined') { if (typeof document !== 'undefined') {
this.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(lastIndexUpdate => { this.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(lastIndexUpdate => {
if (lastIndexUpdate) { if (lastIndexUpdate) {
@ -328,7 +357,8 @@ export class DataProviderComponent {
this.subscriptions.forEach(subscription => { this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) { if (subscription instanceof Subscriber) {
subscription.unsubscribe(); subscription.unsubscribe();
} else if (subscription instanceof (ResizeObserver || IntersectionObserver)) { } else if ((typeof ResizeObserver != 'undefined' && subscription instanceof ResizeObserver) ||
(typeof IntersectionObserver != 'undefined' && subscription instanceof IntersectionObserver)) {
subscription.disconnect(); subscription.disconnect();
} }
}); });
@ -366,6 +396,7 @@ export class DataProviderComponent {
this.seoService.createLinkForCanonicalURL(this.properties.domain +this.properties.baseLink + this._router.url); this.seoService.createLinkForCanonicalURL(this.properties.domain +this.properties.baseLink + this._router.url);
if (typeof document !== 'undefined') { if (typeof document !== 'undefined') {
this.getDataProviderAggregationStatus(this.dataProviderInfo.originalId); this.getDataProviderAggregationStatus(this.dataProviderInfo.originalId);
// this.getCollectedFulltexts();
this.countResultsWithFundingInfo(); this.countResultsWithFundingInfo();
} else { } else {
this.aggregationStatusIsInitialized = true; this.aggregationStatusIsInitialized = true;
@ -381,6 +412,23 @@ export class DataProviderComponent {
} }
this.showLoading = false; 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(); this.cdr.detectChanges();
// if (this.dataProviderInfo.tabs != undefined && this.dataProviderInfo.tabs.length > 0) { // 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() { private countResultsWithFundingInfo() {
this.subscriptions.push(this._searchResearchResultsService.countCollectedResultsWithFundingInfo(this.datasourceId).subscribe( this.subscriptions.push(this._searchResearchResultsService.countCollectedResultsWithFundingInfo(this.datasourceId).subscribe(
fundedContent => { fundedContent => {
@ -680,11 +742,33 @@ export class DataProviderComponent {
public metricsResults($event) { public metricsResults($event) {
this.totalViews = $event.totalViews; this.totalViews = $event.totalViews;
this.totalDownloads = $event.totalDownloads; 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 { 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() { // public openStatistics() {
@ -715,7 +799,13 @@ export class DataProviderComponent {
if(this.dataProviderInfo.organizations.length <= this.thresholdOrganizations*2) { if(this.dataProviderInfo.organizations.length <= this.thresholdOrganizations*2) {
this.lessBtnOrganizations = true; this.lessBtnOrganizations = true;
} else { } 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) { if(this.dataProviderInfo.subjects.length <= this.thresholdSubjects*2) {
this.lessBtnSubjects = true; this.lessBtnSubjects = true;
} else { } 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.fulltexts && parseInt(this.dataProviderInfo.aggregationStatus.fulltexts) != -1)
// || (!!this.dataProviderInfo.aggregationStatus.fundedContent && parseInt(this.dataProviderInfo.aggregationStatus.fundedContent) != -1) // || (!!this.dataProviderInfo.aggregationStatus.fundedContent && parseInt(this.dataProviderInfo.aggregationStatus.fundedContent) != -1)
// || !!this.dataProviderInfo.aggregationStatus.lastUpdateDate)); // || !!this.dataProviderInfo.aggregationStatus.lastUpdateDate));
return (!!this.dataProviderInfo.aggregationStatus && return (!!this.dataProviderInfo.aggregationStatus &&
((!!this.dataProviderInfo.aggregationStatus.fulltexts && parseInt(this.dataProviderInfo.aggregationStatus.fulltexts) != -1))); ((!!this.dataProviderInfo.aggregationStatus.fulltexts && parseInt(this.dataProviderInfo.aggregationStatus.fulltexts) != -1)));
} }
@ -837,12 +932,56 @@ export class DataProviderComponent {
return StringUtils.getEntityName(this.type, false); 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() { public openDescriptionModal() {
this.descriptionModal.alertFooter = false; this.descriptionModal.alertFooter = false;
this.descriptionModal.alertTitle = "Description"; this.descriptionModal.alertTitle = "Description";
this.descriptionModal.open(); 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) { public addEoscPrevInParams(obj) {
if(properties.adminToolsPortalType == "eosc" && this.prevPath) { if(properties.adminToolsPortalType == "eosc" && this.prevPath) {
let splitted: string[] = this.prevPath.split("?"); 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 {graph} from "../../utils/icons/icons";
import {LoadingModalModule} from "../../utils/modal/loadingModal.module"; import {LoadingModalModule} from "../../utils/modal/loadingModal.module";
import {ResultLandingUtilsModule} from "../landing-utils/resultLandingUtils.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({ @NgModule({
imports: imports:
@ -42,7 +45,8 @@ import {ResultLandingUtilsModule} from "../landing-utils/resultLandingUtils.modu
DataProvidersServiceModule, ProjectsServiceModule, SearchResearchResultsServiceModule, DataProvidersServiceModule, ProjectsServiceModule, SearchResearchResultsServiceModule,
PagingModule, Schema2jsonldModule, SEOServiceModule, ShowPublisherModule, HelperModule, PagingModule, Schema2jsonldModule, SEOServiceModule, ShowPublisherModule, HelperModule,
LandingHeaderModule, AlertModalModule, NoLoadPaging, FeedbackModule, LandingHeaderModule, AlertModalModule, NoLoadPaging, FeedbackModule,
TabsModule, SearchTabModule, LoadingModule, IconsModule, LoadingModalModule, ResultLandingUtilsModule TabsModule, SearchTabModule, LoadingModule, IconsModule, LoadingModalModule, ResultLandingUtilsModule,
FullScreenModalModule, SafeHtmlPipeModule, EntityActionsModule
], ],
declarations: declarations:
[StatisticsTabComponent, [StatisticsTabComponent,

View File

@ -83,6 +83,11 @@ export class DataProviderService {
.pipe(map(res => this.parseDataproviderAggregationStatus(res))); .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) { private handleError (error: HttpErrorResponse) {
// in a real world app, we may send the error to some remote logging infrastructure // in a real world app, we may send the error to some remote logging infrastructure
// instead of just logging it to the console // 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['lissn'] = data[6]['lissn'];
this.dataProviderInfo.journal['eissn'] = data[6]['eissn']; this.dataProviderInfo.journal['eissn'] = data[6]['eissn'];
}else{ }else {
this.dataProviderInfo.journal = null; 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; return this.dataProviderInfo;

View File

@ -1,59 +1,84 @@
import { import {
ChangeDetectorRef,
Component, Component,
EventEmitter, Inject, Input,
Inject,
OnInit, OnInit,
Output,
RendererFactory2, RendererFactory2,
ViewChild,
ViewEncapsulation ViewEncapsulation
} from '@angular/core'; } from '@angular/core';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import {DOCUMENT} from "@angular/common"; import {DOCUMENT} from "@angular/common";
import {Subscriber} from "rxjs"; import {Subscriber} from "rxjs";
interface addthis { declare var a2a;
layers: Refresh;
init: Function;
toolbox: Function;
}
interface Refresh {
refresh: Function;
}
declare var addthis: addthis;
@Component({ @Component({
selector: 'addThis', selector: 'addThis',
template: ` template: `
<div id="addThis" class="addthis_inline_share_toolbox_lcx9_8cfy"></div> <div [id]="'addToAny'+(url ? ('_'+url) : '')" #addToAny class="a2a_kit a2a_kit_size_42 a2a_default_style fully_rounded" [attr.data-a2a-url]="url">
<div *ngIf="showWarning" class="uk-alert uk-alert-warning uk-animation-fade" > <a class="a2a_button_twitter"></a>
Do the share buttons not appear? Please make sure, any blocking addon is disabled, and then reload the page. <a class="a2a_button_facebook"></a>
</div> <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 { export class AddThisComponent implements OnInit {
subs=[]; subs = [];
showWarning = false; 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() { public ngOnDestroy() {
for(let value of this.subs){ for (let value of this.subs) {
if (value instanceof Subscriber) { if (value instanceof Subscriber) {
value.unsubscribe(); value.unsubscribe();
} else if (value instanceof Function) { } else if (value instanceof Function) {
value(); 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() { ngOnInit() {
this.subs.push(this.route.queryParams.subscribe(data => { this.subs.push(this.route.queryParams.subscribe(data => {
this.showWarning = false; this.showWarning = false;
try { try {
if (!this.document.getElementById('addThisScript') && typeof document !== 'undefined') { if (!this.document.getElementById('addToAnyScript') && typeof document !== 'undefined') {
// console.log(" create script AddThis");
const renderer = this.rendererFactory.createRenderer(this.document, { const renderer = this.rendererFactory.createRenderer(this.document, {
id: '-1', id: '-1',
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@ -65,24 +90,23 @@ export class AddThisComponent implements OnInit {
throw new Error('<head> not found within DOCUMENT.'); throw new Error('<head> not found within DOCUMENT.');
} }
const script = renderer.createElement('script'); const script = renderer.createElement('script');
renderer.setAttribute(script, "id", "addThisScript"); renderer.setAttribute(script, "id", "addToAnyScript");
renderer.setAttribute(script, "src", "https://s7.addthis.com/js/300/addthis_widget.js#pubid=ra-559d24521cd8c080"); renderer.setAttribute(script, "src", "https://static.addtoany.com/menu/page.js");
renderer.setAttribute(script, "type", "text/javascript"); renderer.setAttribute(script, "type", "text/javascript");
renderer.appendChild(head, script); renderer.appendChild(head, script);
} }
if (typeof document !== 'undefined') { if (typeof document !== 'undefined') {
if(typeof addthis !== 'undefined' && addthis.layers && addthis.layers.refresh) { if(typeof a2a !== 'undefined' && this.document.getElementById('addToAny'+(this.url ? ('_'+this.url) : '')) && !this.document.getElementById('addToAny'+(this.url ? ('_'+this.url) : '')).innerText) {
// console.log("Add This: Call Refresh") a2a.init_all();
addthis.layers.refresh();
} }
} }
this.subs.push(setTimeout(() => { 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; this.showWarning = true;
} }
}, 4000)); }, 4000));
}catch (e) { } catch (e) {
// console.error(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 {HostedByCollectedFrom} from "../../utils/result-preview/result-preview";
import {properties} from "../../../../environments/environment"; 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"; import {RouterHelper} from "../../utils/routerHelper.class";
@Component({ @Component({
selector: 'availableOn', selector: 'availableOn',
template: ` template: `
<div class="uk-margin-small-bottom uk-flex uk-flex-between"> <ng-container *ngIf="availableOn && availableOn.length > 0">
<span *ngIf="viewAll && !lessBtn" class="clickable uk-h6 uk-flex uk-flex-middle" (click)="viewLessClick()"> <div class="uk-flex uk-flex-middle" [ngClass]="isMobile && !(usedBy == 'landing') ? 'uk-margin-left uk-margin-xsmall-bottom' : ''">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon> <ng-container *ngIf="availableOn[0].downloadUrl">
{{title}} <span [class]="'uk-margin-xsmall-right ' + (availableOn[0].accessRightIcon == 'open_access' ? 'open-access' : 'closed-access')"
</span> uk-tooltip [title]="getAccessLabel(availableOn[0].accessRight)">
<span *ngIf="!viewAll || lessBtn" class="uk-margin-small-bottom uk-flex uk-flex-middle"> <icon [name]="availableOn[0].accessRightIcon" [flex]="true" [ratio]="(isMobile && usedBy == 'landing') ? 1 : 0.8"></icon>
<span class="uk-text-light-grey uk-margin-small-right">Download from</span> </span>
</span> <ng-container *ngIf="!(isMobile && usedBy == 'landing')">
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;" class="view-more-less-link">View less</a> <a uk-tooltip="Source" target="_blank"
<a *ngIf="availableOn && availableOn.length > threshold && !viewAll" class="view-more-less-link" class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder">
(click)="viewAllClick();">View all {{availableOn.length}} sources</a> <span>{{sliceString(availableOn[0].downloadNames.join("; "), 20)}}</span>
</div> <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"> <ng-template #availableOnList>
<div *ngFor="let instance of availableOn.slice(0, viewAll?availableOn.length:threshold) let i=index" <div *ngFor="let instance of availableOn let i=index" class="download-drop-item uk-flex uk-flex-top">
class="uk-flex uk-flex-top uk-padding-small uk-margin-small-bottom" <span
uk-tooltip [title]="instance.accessRight ? instance.accessRight : 'Not available'"> [class]="'uk-margin-small-right ' + (instance.accessRightIcon == 'open_access' ? 'open-access' : 'closed-access')"
<span [class]="'uk-margin-small-right ' + (instance.accessRightIcon == 'lock_open' ? 'uk-text-success' : 'uk-text-meta')" uk-tooltip [title]="getAccessLabel(instance.accessRight)">
uk-tooltip [title]="instance.accessRight ? instance.accessRight : 'Not available'"> <icon [name]="instance.accessRightIcon" [flex]="true"></icon>
<icon [name]="instance.accessRightIcon" flex="true" type="outlined"></icon>
</span> </span>
<div class="uk-width-expand uk-padding-small uk-padding-remove-left uk-padding-remove-vertical"> <div class="uk-width-expand uk-padding-small uk-padding-remove-left uk-padding-remove-vertical">
<span class="uk-text-emphasis"> <span class="uk-text-emphasis">
@ -56,36 +85,19 @@ import {RouterHelper} from "../../utils/routerHelper.class";
</div> </div>
</div> </div>
</div> </div>
</div> </ng-template>
<!-- <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>-->
` `
}) })
export class AvailableOnComponent { export class AvailableOnComponent {
@Input() isMobile: boolean = false;
@Input() usedBy: "search" | "landing" = "search";
@Input() prevPath: string = ""; @Input() prevPath: string = "";
@Input() availableOn: HostedByCollectedFrom[]; @Input() availableOn: HostedByCollectedFrom[];
@Input() viewAll: boolean = false; /** @deprecated */
@Output() viewAllClicked = new EventEmitter(); @Output() viewAllClicked = new EventEmitter();
public lessBtn: boolean = false; @ViewChild("dropElement") dropElement: ElementRef;
@ViewChild("availableListFsModal") availableListFsModal: FullScreenModalComponent;
public threshold: number = 1; public threshold: number = 1;
public dataProviderUrl = properties.searchLinkToDataProvider.split('?')[0]; public dataProviderUrl = properties.searchLinkToDataProvider.split('?')[0];
public title: string = "Download from"; public title: string = "Download from";
@ -93,39 +105,39 @@ export class AvailableOnComponent {
constructor() { constructor() {
} }
ngOnInit() {} ngOnInit() {
public removeUnknown(value: string): string {
if (value.toLowerCase() === 'unknown') {
return null;
}
return value;
} }
public getKeys( map) { public getKeys(map) {
return Array.from(map.keys()); 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 { public isUrl(str: string): boolean {
return str.startsWith('http://') || str.startsWith('https://') || str.startsWith('//') || str.startsWith('www.'); 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) { public addEoscPrevInParams(obj) {
if(properties.adminToolsPortalType == "eosc" && this.prevPath) { if(properties.adminToolsPortalType == "eosc" && this.prevPath) {
let splitted: string[] = this.prevPath.split("?"); 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 {EnvProperties} from "../../../utils/properties/env-properties";
import {properties} from "../../../../../environments/environment"; import {properties} from "../../../../../environments/environment";
import {PiwikService} from "../../../utils/piwik/piwik.service"; import {PiwikService} from "../../../utils/piwik/piwik.service";
import {ResultPreview} from "../../../utils/result-preview/result-preview";
declare var Cite: any; declare var Cite: any;
// Based on https://citation.js.org/api/tutorial-getting_started.html browser release // Based on https://citation.js.org/api/tutorial-getting_started.html browser release
@ -20,7 +21,7 @@ declare var Cite: any;
@Component({ @Component({
selector: 'citeThis', selector: 'citeThis',
template: ` 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" <div input type="select" placeholder="Select a citation style" inputClass="flat x-small"
[options]="citation.templates" [(value)]="selectedStyle" [options]="citation.templates" [(value)]="selectedStyle"
(valueChange)="styleChanged()"></div> (valueChange)="styleChanged()"></div>
@ -53,7 +54,7 @@ export class CiteThisComponent implements OnInit, OnDestroy {
properties:EnvProperties; properties:EnvProperties;
public citationText: string; public citationText: string;
public citation: Citation = new Citation(); public citation: Citation = new Citation();
@Input() result: ResultLandingInfo; @Input() result: any;
@Input() id: string; @Input() id: string;
@Input() type: string = "article"; @Input() type: string = "article";
@Input() piwikSiteId; @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 * 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 * @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({ @Component({
selector: 'fos', selector: 'fos',
template: ` template: `
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div> <div class="uk-visible@m">
<div [class]="'uk-flex uk-flex-between uk-flex-middle uk-margin-'+(viewAll?'':'small-')+'bottom'"> <div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
<span *ngIf="viewAll" class="clickable uk-h6 uk-flex uk-flex-middle uk-margin-small-right uk-margin-remove-bottom" (click)="viewLessClick()"> <div [class]="'uk-flex uk-flex-between uk-flex-middle uk-margin-'+(viewAll?'':'small-')+'bottom'">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon> <span *ngIf="viewAll" class="clickable uk-h6 uk-flex uk-flex-middle uk-margin-small-right uk-margin-remove-bottom" (click)="viewLessClick()">
<span class="uk-text-nowrap">{{title}}</span> <icon class="uk-margin-small-right" name="arrow_back" [flex]="true" [ratio]="1.2"></icon>
</span> <span class="uk-text-nowrap">{{title}}</span>
<span *ngIf="!viewAll" class="uk-text-light-grey uk-text-nowrap uk-margin-small-right">{{title}}</span> </span>
<!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>--> <span *ngIf="!viewAll" class="uk-text-emphasis uk-text-bolder uk-text-nowrap uk-margin-small-right">
<a *ngIf="properties.adminToolsPortalType == 'eosc' && subjects && subjects.length > threshold && !viewAll" {{title}}
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate" uk-tooltip="View all"> <span *ngIf="subjects && subjects.length > threshold && !viewAll">({{subjects.length}})</span>
<span class="">View all</span> </span>
</a> <a *ngIf="properties.adminToolsPortalType == 'eosc' && subjects && subjects.length > threshold && !viewAll"
<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">
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate" uk-tooltip="View all & feedback"> View all
<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}}
</a> </a>
<a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank" <!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a> -->
[href]="'https://explore.openaire.eu'+properties.searchLinkToResults+'?fos='+urlEncodeAndQuote(subject)"> <a *ngIf="properties.adminToolsPortalType != 'eosc' && subjects && subjects.length > threshold && !viewAll"
{{subject}} (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>
<!-- <a *ngIf="(subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-text-truncate"-->
<!-- (click)="feedbackClick();">Feedback</a>-->
</div> </div>
</div> </div>
` `
}) })
export class FosComponent { export class FosComponent {
@Input() subjects: string[]; @Input() subjects: {"id": string, "label": string}[];
@Input() viewAll: boolean = false; @Input() viewAll: boolean = false;
@Output() viewAllClicked = new EventEmitter(); @Output() viewAllClicked = new EventEmitter();
@Output() feedbackClicked = new EventEmitter(); @Output() suggestClicked = new EventEmitter();
public lessBtn: boolean = false; public lessBtn: boolean = false;
public threshold: number = 2; public threshold: number = 2;
public routerHelper: RouterHelper = new RouterHelper(); public routerHelper: RouterHelper = new RouterHelper();
@ -66,8 +96,8 @@ export class FosComponent {
this.viewAllClicked.emit(""); this.viewAllClicked.emit("");
} }
public feedbackClick() { public suggestClick() {
this.feedbackClicked.emit(""); this.suggestClicked.emit('fos');
} }
public urlEncodeAndQuote(str: string): string { public urlEncodeAndQuote(str: string): string {

View File

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

View File

@ -4,100 +4,61 @@ import {Author} from "../../../utils/result-preview/result-preview";
import {AlertModal} from "../../../utils/modal/alert"; import {AlertModal} from "../../../utils/modal/alert";
@Component({ @Component({
selector: 'landing-header', selector: 'landing-header',
template: ` template: `
<div class="title-section" [class.uk-margin-bottom]="!isSticky" [ngClass]="titleClass"> <div class="title-section" [class.uk-margin-small-bottom]="!isSticky" [ngClass]="titleClass">
<div class="uk-text-small"> <div class="uk-margin-small-bottom">
<span *ngIf="entityType" class="uk-text-capitalize uk-text-small"> <showTitle [isSticky]=isSticky [titleName]="title" classNames="uk-margin-remove-bottom"></showTitle>
{{entityType}} <div *ngIf="subTitle && !isSticky">
</span> <span class="uk-text-meta uk-text-small" [innerHTML]="subTitle"></span>
<span *ngIf="types && removeUnknown(types, true).length > 0"> </div>
{{(entityType?' . ':'') + removeUnknown(types, true).join(' . ')}} </div>
</span> <div *ngIf="!isSticky" class="uk-margin-bottom">
<span> <entity-metadata [entityType]="entityType" [types]="types" [startDate]="startDate" [endDate]="endDate"
<span *ngIf="startDate || endDate"> [currentDate]="currentDate" [status]="status" [openAccessMandatePublications]="openAccessMandatePublications"
{{' . '}} [openAccessMandateDatasets]="openAccessMandateDatasets" [date]="date" [embargoEndDate]="embargoEndDate"
</span> [underCuration]="underCuration" [publisher]="publisher" [journal]="journal"
<span *ngIf="startDate && !endDate"> [languages]="languages" [programmingLanguages]="programmingLanguages"
{{'from '}} [compatibility]="compatibility" [aggregationStatus]="aggregationStatus"
</span> [thematic]="thematic" [type]="type" [prevPath]="prevPath"
<span *ngIf="!startDate && endDate"> ></entity-metadata>
{{'until '}} </div>
</span> <div *ngIf="authors">
<span *ngIf="startDate"> <showAuthors [authorsLimit]="authorLimit" [modal]="modal" [showAll]="showAllAuthors" [authors]="authors"
{{startDate | date: 'yyyy'}} [isSticky]="isSticky" [isMobile]="isMobile"></showAuthors>
</span> </div>
<span *ngIf="startDate && endDate"> </div>
{{' - '}} `
</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>`
}) })
export class LandingHeaderComponent { export class LandingHeaderComponent {
@Input() entityType: string; @Input() isMobile: boolean = false;
@Input() properties: EnvProperties; @Input() entityType: string;
@Input() types: string[]; @Input() properties: EnvProperties;
@Input() startDate: number; // project landing @Input() types: string[];
@Input() endDate: number; // project landing @Input() startDate: number; // project landing
@Input() status: string; // project landing @Input() endDate: number; // project landing
@Input() year: string; @Input() currentDate: number; // project landing
@Input() embargoEndDate: Date; @Input() status: string; // project landing
@Input() title: string; @Input() openAccessMandatePublications: boolean // project landing
@Input() subTitle: string; @Input() openAccessMandateDatasets: boolean // project landing
@Input() authors: Author[]; @Input() date: Date;
@Input() authorLimit: number = 7; @Input() embargoEndDate: Date;
@Input() showAllAuthors: boolean = true; @Input() title: string;
@Input() underCuration: boolean = false; @Input() subTitle: string;
@Input() modal: AlertModal; @Input() authors: Author[];
@Input() titleClass: string = null; @Input() authorLimit: number = 7;
@Input() isTitleH1:boolean =true; @Input() showAllAuthors: boolean = true;
@Input() isSticky: boolean = false; @Input() underCuration: boolean = false;
public removeUnknown(array: string[], type: boolean = false): string[] { @Input() modal: AlertModal;
if (type) { @Input() titleClass: string = null;
return this.removeDuplicates(array).filter(value => value.toLowerCase() !== 'unknown'); @Input() isSticky: boolean = false;
} else { @Input() publisher; // showPublisher component
return array.filter(value => value.toLowerCase() !== 'unknown'); @Input() journal; // showPublisher component
} @Input() languages;
} @Input() programmingLanguages;
@Input() compatibility; // data provider landing
public removeDuplicates(array: string[]): string[] { @Input() aggregationStatus; // data provider landing
return array.filter(value => value.toLowerCase() !== this.entityType); @Input() thematic: boolean; // data provider landing
} @Input() type; // data provider landing
@Input() prevPath: string = "";
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;
}
} }

View File

@ -3,10 +3,14 @@ import {LandingHeaderComponent} from "./landing-header.component";
import {CommonModule} from "@angular/common"; import {CommonModule} from "@angular/common";
import {LandingModule} from "../landing.module"; import {LandingModule} from "../landing.module";
import {ShowAuthorsModule} from "../../../utils/authors/showAuthors.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({ @NgModule({
imports: [CommonModule, LandingModule, ShowAuthorsModule], imports: [CommonModule, LandingModule, ShowAuthorsModule, IconsModule, ShowPublisherModule, RouterModule, ResultLandingUtilsModule],
declarations: [LandingHeaderComponent], declarations: [LandingHeaderComponent],
exports: [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 {HostedByCollectedFrom, Project, RelationResult} from "../../utils/result-preview/result-preview";
import {Context, Reference} from "../../utils/entities/resultLandingInfo"; import {Context, Measure, Metric, Reference} from "../../utils/entities/resultLandingInfo";
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {StringUtils} from "../../utils/string-utils.class"; 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::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'} {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; public notebookInSubjects: boolean = false;
private notebookKeyword: string = "eosc jupyter notebook"; private notebookKeyword: string = "eosc jupyter notebook";
private notebook_label: string = "EOSC"; private notebook_label: string = "EOSC";
private notebook_value: string = "EOSC Jupyter Notebook"; private notebook_value: string = "EOSC Jupyter Notebook";
public open = 'lock_open'; public open = 'open_access';
public closed = 'lock'; public closed = 'closed_access';
public unknown = 'question_mark'; public unknown = 'unknown_access';
private instanceWithDoiExists: boolean = false; private instanceWithDoiExists: boolean = false;
constructor() { constructor() {
} }
@ -49,10 +48,10 @@ export class ParsingFunctions {
fundedByProject['acronym'] = relation.acronym; fundedByProject['acronym'] = relation.acronym;
fundedByProject['title'] = relation.title; fundedByProject['title'] = relation.title;
fundedByProject['code'] = relation.code; fundedByProject['code'] = relation.code;
if(relation.validated && relation.validated.date) { if (relation.validated && relation.validated.date) {
fundedByProject['validated'] = true; fundedByProject['validated'] = true;
} }
fundedByProject['provenanceAction'] = relation.provenanceaction; fundedByProject['provenanceAction'] = relation.provenanceaction;
} else { } else {
fundedByProject['id'] = ""; fundedByProject['id'] = "";
fundedByProject['acronym'] = ""; fundedByProject['acronym'] = "";
@ -156,7 +155,7 @@ export class ParsingFunctions {
// publication & dataset landing : for downloadFrom // publication & dataset landing : for downloadFrom
addPublisherToHostedBy_collectedFrom(hostedBy_collectedFrom: HostedByCollectedFrom[], addPublisherToHostedBy_collectedFrom(hostedBy_collectedFrom: HostedByCollectedFrom[],
publisher: string, journal: Journal, publisher: string, journal: string,
identifiers: Map<string, string[]>/*, title: { "name": string, "url": string, "accessMode": string}*/) { identifiers: Map<string, string[]>/*, title: { "name": string, "url": string, "accessMode": string}*/) {
if (!this.instanceWithDoiExists && publisher && identifiers != null && identifiers.has('doi')) { if (!this.instanceWithDoiExists && publisher && identifiers != null && identifiers.has('doi')) {
if (hostedBy_collectedFrom == null) { if (hostedBy_collectedFrom == null) {
@ -171,14 +170,14 @@ export class ParsingFunctions {
years: [], years: [],
accessRightIcon: "" accessRightIcon: ""
}; };
if (journal && journal.journal) { if (journal) {
available.downloadNames.push(publisher + "/ " + journal['journal']); available.downloadNames.push(publisher + "/ " + journal['journal']);
} else { } else {
available.downloadNames.push(publisher); available.downloadNames.push(publisher);
} }
available.downloadUrl = properties.doiURL + identifiers.get("doi")[0];; available.downloadUrl = properties.doiURL + identifiers.get("doi")[0];
available.accessRightIcon = this.unknown; available.accessRightIcon = this.unknown;
/* /*
if(title != undefined && title['url'] == "") { if(title != undefined && title['url'] == "") {
@ -250,13 +249,13 @@ export class ParsingFunctions {
mapStructure.get(key)['accessMode'].push(""); mapStructure.get(key)['accessMode'].push("");
} }
} }
parseHostedBy_collectedFrom(hostedBy_collectedFrom: HostedByCollectedFrom[], parseHostedBy_collectedFrom(hostedBy_collectedFrom: HostedByCollectedFrom[],
instance: any, url: string, globalAccessRight: string) { instance: any, url: string, globalAccessRight: string) {
if(!url) { if (!url) {
return; return;
} }
let available: HostedByCollectedFrom = { let available: HostedByCollectedFrom = {
"downloadNames": [], "downloadNames": [],
"downloadUrl": null, "downloadUrl": null,
@ -278,34 +277,34 @@ export class ParsingFunctions {
} }
} }
available.downloadNames = Array.from(downloadNames); available.downloadNames = Array.from(downloadNames);
if (available.downloadNames.length == 0) { if (available.downloadNames.length == 0) {
available.downloadNames.push(url.substring(0, 30) + '...'); // substring(from, to); available.downloadNames.push(url.substring(0, 30) + '...'); // substring(from, to);
} }
} }
if (instance.hasOwnProperty("collectedfrom")) { if (instance.hasOwnProperty("collectedfrom")) {
let length = Array.isArray(instance['collectedfrom']) ? instance['collectedfrom'].length : 1; let length = Array.isArray(instance['collectedfrom']) ? instance['collectedfrom'].length : 1;
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
let collectedFrom = Array.isArray(instance['collectedfrom']) ? instance['collectedfrom'][i] : instance['collectedfrom']; 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); available.collectedNamesAndIds.set(String(collectedFrom.name), collectedFrom.id);
} }
} }
} }
if (instance.hasOwnProperty("instancetype")) { if (instance.hasOwnProperty("instancetype")) {
let types: Set<string> = new Set(); let types: Set<string> = new Set();
let length = Array.isArray(instance['instancetype']) ? instance['instancetype'].length : 1; let length = Array.isArray(instance['instancetype']) ? instance['instancetype'].length : 1;
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
let instanceType = Array.isArray(instance['instancetype']) ? instance['instancetype'][i] : instance['instancetype']; 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); types.add(instanceType.classname);
} }
} }
available.types = Array.from(types); available.types = Array.from(types);
} }
if (instance.hasOwnProperty("dateofacceptance")) { if (instance.hasOwnProperty("dateofacceptance")) {
let years: Set<string> = new Set(); let years: Set<string> = new Set();
let length = Array.isArray(instance['dateofacceptance']) ? instance['dateofacceptance'].length : 1; let length = Array.isArray(instance['dateofacceptance']) ? instance['dateofacceptance'].length : 1;
@ -316,17 +315,17 @@ export class ParsingFunctions {
} }
available.years = Array.from(years); available.years = Array.from(years);
} }
available['downloadUrl'] = url; available['downloadUrl'] = url;
if(url.includes("doi.org/")) { if (url.includes("doi.org/")) {
this.instanceWithDoiExists = true; this.instanceWithDoiExists = true;
} }
if (instance.hasOwnProperty("accessright")) { if (instance.hasOwnProperty("accessright")) {
let length = Array.isArray(instance['accessright']) ? instance['accessright'].length : 1; let length = Array.isArray(instance['accessright']) ? instance['accessright'].length : 1;
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
let accessRight = Array.isArray(instance['accessright']) ? instance['accessright'][i] : instance['accessright']; let accessRight = Array.isArray(instance['accessright']) ? instance['accessright'][i] : instance['accessright'];
if (this.changeBestAccessMode(available.accessRight, accessRight)) { if (this.changeBestAccessMode(available.accessRight, accessRight)) {
available.accessRight = accessRight.classname; available.accessRight = accessRight.classname;
if (this.changeBestAccessMode(globalAccessRight, accessRight)) { if (this.changeBestAccessMode(globalAccessRight, accessRight)) {
@ -334,28 +333,66 @@ export class ParsingFunctions {
} }
} }
} }
} }
if (available.accessRight) { if (available.accessRight) {
if (available.accessRight.toLowerCase().indexOf('open') !== -1) { if (available.accessRight.toLowerCase().indexOf('open') !== -1) {
available.accessRightIcon = this.open; 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; available.accessRightIcon = this.unknown;
} else { }
else {
available.accessRightIcon = this.closed; available.accessRightIcon = this.closed;
} }
} else { } else {
available.accessRightIcon = this.unknown; available.accessRightIcon = this.unknown;
} }
if(instance.hasOwnProperty("license")) { if (instance.hasOwnProperty("license")) {
available.license = Array.isArray(instance['license']) ? instance['license'][0] : instance['license']; available.license = Array.isArray(instance['license']) ? instance['license'][0] : instance['license'];
} }
hostedBy_collectedFrom.push(available); 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 // publication & dataset landing : for downloadFrom and publishedIn
changeBestAccessMode(currentAccessMode: string, accessMode: any): boolean { changeBestAccessMode(currentAccessMode: string, accessMode: any): boolean {
if (!accessMode) { if (!accessMode) {
@ -404,7 +441,7 @@ export class ParsingFunctions {
if (researchResults == undefined) { if (researchResults == undefined) {
researchResults = []; researchResults = [];
} }
let researchResult: RelationResult = { let researchResult: RelationResult = {
name: "", name: "",
id: "", id: "",
@ -415,10 +452,10 @@ export class ParsingFunctions {
provenanceAction: provenanceAction, provenanceAction: provenanceAction,
relationName: relationName relationName: relationName
}; };
// researchResult.relationName = relation.to.class; // researchResult.relationName = relation.to.class;
if(relation['resulttype']) { if (relation['resulttype']) {
if (relation['resulttype'].classname == "publication") { if (relation['resulttype'].classname == "publication") {
researchResult['class'] = "publication"; researchResult['class'] = "publication";
} else if (relation['resulttype'].classname == "dataset") { } else if (relation['resulttype'].classname == "dataset") {
@ -430,10 +467,10 @@ export class ParsingFunctions {
} }
} }
researchResult['id'] = relation['to'].content; researchResult['id'] = relation['to'].content;
if(Array.isArray(relation['title'])) { if (Array.isArray(relation['title'])) {
for(let i=0; i<relation['title'].length; i++) { for (let i = 0; i < relation['title'].length; i++) {
if(relation['title'][i] && relation['title'][i].content) { if (relation['title'][i] && relation['title'][i].content) {
if(!researchResult['name'] || relation['title'][i].classid == "main title") { if (!researchResult['name'] || relation['title'][i].classid == "main title") {
researchResult['name'] = String(relation['title'][i].content); researchResult['name'] = String(relation['title'][i].content);
} }
} }
@ -441,7 +478,7 @@ export class ParsingFunctions {
} else { } else {
researchResult['name'] = (relation['title'] && relation['title'].content) ? String(relation['title'].content) : ""; researchResult['name'] = (relation['title'] && relation['title'].content) ? String(relation['title'].content) : "";
} }
if(!researchResult['name']) { if (!researchResult['name']) {
researchResult['name'] = "[no title available]"; researchResult['name'] = "[no title available]";
} }
if (relation.hasOwnProperty("dateofacceptance")) { if (relation.hasOwnProperty("dateofacceptance")) {
@ -450,19 +487,19 @@ export class ParsingFunctions {
} }
//researchResult['date'] = relation.dateofacceptance.substring(0,4);; //researchResult['date'] = relation.dateofacceptance.substring(0,4);;
let percentageName: string; let percentageName: string;
if(relation.trust) { if (relation.trust) {
percentageName = "trust"; percentageName = "trust";
} else if(relation.similarity) { } else if (relation.similarity) {
percentageName = "similarity"; percentageName = "similarity";
} }
if(percentageName) { if (percentageName) {
researchResult['percentage'] = Math.round(relation[percentageName] * 100); researchResult['percentage'] = Math.round(relation[percentageName] * 100);
researchResult['percentageName'] = percentageName; researchResult['percentageName'] = percentageName;
} }
researchResults.push(researchResult); researchResults.push(researchResult);
return researchResults; return researchResults;
} }
sortByPercentage(results: RelationResult[]): RelationResult[] { sortByPercentage(results: RelationResult[]): RelationResult[] {
if (results) { if (results) {
return results.sort(function (a, b) { return results.sort(function (a, b) {
@ -481,7 +518,7 @@ export class ParsingFunctions {
if (!identifiers.has(pid.classid)) { if (!identifiers.has(pid.classid)) {
identifiers.set(pid.classid, new Array<string>()); identifiers.set(pid.classid, new Array<string>());
} }
identifiers.get(pid.classid).push(pid.content+""); identifiers.get(pid.classid).push(pid.content + "");
} }
} else { } else {
for (let i = 0; i < pid.length; i++) { for (let i = 0; i < pid.length; i++) {
@ -489,54 +526,54 @@ export class ParsingFunctions {
if (!identifiers.has(pid[i].classid)) { if (!identifiers.has(pid[i].classid)) {
identifiers.set(pid[i].classid, new Array<string>()); 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; return identifiers;
} }
// publication & dataset landing : for subjects and otherSubjects and classifiedSubjects // publication & dataset landing : for subjects and otherSubjects and classifiedSubjects
parseEoscSubjects(_subjects: any): any[] { parseEoscSubjects(_subjects: any): any[] {
let eoscSubjectsFound = []; let eoscSubjectsFound = [];
let setOfEoscSubjects: Set<string> = new Set(); let setOfEoscSubjects: Set<string> = new Set();
let subject; let subject;
let length = Array.isArray(_subjects) ? _subjects.length : 1; let length = Array.isArray(_subjects) ? _subjects.length : 1;
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
subject = Array.isArray(_subjects) ? _subjects[i] : _subjects; 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 checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content);
let found: boolean = checkAndAddEoscSubjectResp["found"]; let found: boolean = checkAndAddEoscSubjectResp["found"];
if(found) { if (found) {
setOfEoscSubjects = checkAndAddEoscSubjectResp["setOfEoscSubject"]; setOfEoscSubjects = checkAndAddEoscSubjectResp["setOfEoscSubject"];
eoscSubjectsFound = checkAndAddEoscSubjectResp["eoscSubjectsFound"]; eoscSubjectsFound = checkAndAddEoscSubjectResp["eoscSubjectsFound"];
} }
} }
return eoscSubjectsFound; return eoscSubjectsFound;
} }
// publication & dataset landing : for subjects and otherSubjects and classifiedSubjects // 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 eoscSubjectsFound = [];
let subjects: string[]; let subjects: string[];
let otherSubjects: Map<string, string[]>; let otherSubjects: Map<string, string[]>;
let classifiedSubjects: Map<string, string[]>; let classifiedSubjects: Map<string, string[]>;
let fos: string[]; let fos: string[];
let sdg: string[]; let sdg: string[];
let setOfEoscSubjects: Set<string> = new Set(); let setOfEoscSubjects: Set<string> = new Set();
let subject; let subject;
let length = Array.isArray(_subjects) ? _subjects.length : 1; let length = Array.isArray(_subjects) ? _subjects.length : 1;
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
subject = Array.isArray(_subjects) ? _subjects[i] : _subjects; subject = Array.isArray(_subjects) ? _subjects[i] : _subjects;
if (subject.classid != "") { if (subject.classid != "") {
if (subject.classid == "keyword") { if (subject.classid == "keyword") {
let content: string = subject.content+""; let content: string = subject.content + "";
// let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content); // let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content);
// let found: boolean = checkAndAddEoscSubjectResp["found"]; // let found: boolean = checkAndAddEoscSubjectResp["found"];
// if(found) { // if(found) {
@ -550,22 +587,22 @@ export class ParsingFunctions {
// } // }
} else if (!vocabulary || vocabulary[subject.classid] || subject.classid === "SDG" || subject.classid === "FOS") { } else if (!vocabulary || vocabulary[subject.classid] || subject.classid === "SDG" || subject.classid === "FOS") {
// if (subject.inferred && subject.inferred == true) { // if (subject.inferred && subject.inferred == true) {
if(subject.classid === "SDG") { if (subject.classid === "SDG") {
if (sdg == undefined) { if (sdg == undefined) {
sdg = new Array<string>(); sdg = new Array<string>();
} }
sdg.push(subject.content+""); sdg.push(subject.content + "");
} else if(subject.classid === "FOS") { } else if (subject.classid === "FOS") {
if (fos == undefined) { if (fos == undefined) {
fos = new Array<string>(); fos = new Array<string>();
} }
fos.push(subject.content+""); fos.push(subject.content + "");
} else { } else {
if (classifiedSubjects == undefined) { if (classifiedSubjects == undefined) {
classifiedSubjects = new Map<string, string[]>(); classifiedSubjects = new Map<string, string[]>();
} }
let content: string = subject.content+""; let content: string = subject.content + "";
// let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content); // let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content);
// let found: boolean = checkAndAddEoscSubjectResp["found"]; // let found: boolean = checkAndAddEoscSubjectResp["found"];
// if(found) { // if(found) {
@ -579,7 +616,7 @@ export class ParsingFunctions {
// } // }
} }
} else { } else {
let content: string = subject.content+""; let content: string = subject.content + "";
// let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content); // let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content);
// let found: boolean = checkAndAddEoscSubjectResp["found"]; // let found: boolean = checkAndAddEoscSubjectResp["found"];
// if(found) { // if(found) {
@ -597,11 +634,11 @@ export class ParsingFunctions {
} }
return [subjects, otherSubjects, classifiedSubjects, fos, sdg]; return [subjects, otherSubjects, classifiedSubjects, fos, sdg];
} }
checkAndAddEoscSubject(setOfEoscSubjects: Set<string>, eoscSubjectsFound, subject, content) { checkAndAddEoscSubject(setOfEoscSubjects: Set<string>, eoscSubjectsFound, subject, content) {
let found: boolean = false; let found: boolean = false;
if(!setOfEoscSubjects.has(content)) { if (!setOfEoscSubjects.has(content)) {
// looping through our declared array // looping through our declared array
this.eoscSubjects.forEach(item => { this.eoscSubjects.forEach(item => {
if (content && content == item.label) { if (content && content == item.label) {
@ -616,7 +653,7 @@ export class ParsingFunctions {
parseContexts(_contexts: any): Context[] { parseContexts(_contexts: any): Context[] {
let contexts = new Array<Context>(); let contexts = new Array<Context>();
let position = 0; let position = 0;
let labels = ""; let labels = "";
let context; let context;
@ -637,10 +674,10 @@ export class ParsingFunctions {
let length1 = Array.isArray(category['concept']) ? category['concept'].length : 1; let length1 = Array.isArray(category['concept']) ? category['concept'].length : 1;
for (let j = 0; j < length1; j++) { for (let j = 0; j < length1; j++) {
categoryConcept = Array.isArray(category['concept']) ? category['concept'][j] : category['concept']; 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 // 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 // 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] = { contexts[position] = {
"labelContext": "", "idContext": "", "labelContext": "", "idContext": "",
"labelCategory": "", "idCategory": "", "labelCategory": "", "idCategory": "",
@ -652,15 +689,17 @@ export class ParsingFunctions {
contexts[position]['idCategory'] = category.id; contexts[position]['idCategory'] = category.id;
contexts[position]['labelConcept'] = categoryConcept.label ? categoryConcept.label : null; contexts[position]['labelConcept'] = categoryConcept.label ? categoryConcept.label : null;
contexts[position]['idConcept'] = categoryConcept.label ? categoryConcept.id : null; contexts[position]['idConcept'] = categoryConcept.label ? categoryConcept.id : null;
position++; position++;
numOfConcepts++; numOfConcepts++;
} }
} }
} else if(category.label || (numOfCategories == 0 && z == (length2 - 1))) { } else if (category.label || (numOfCategories == 0 && z == (length2 - 1))) {
contexts[position] = {"labelContext": "", "idContext": "", contexts[position] = {
"labelCategory": "", "idCategory": "", "labelContext": "", "idContext": "",
"labelConcept": "", "idConcept": ""}; "labelCategory": "", "idCategory": "",
"labelConcept": "", "idConcept": ""
};
contexts[position]['labelContext'] = context.label; contexts[position]['labelContext'] = context.label;
contexts[position]['idContext'] = context.id; contexts[position]['idContext'] = context.id;
contexts[position]['labelCategory'] = category.label ? category.label : null; contexts[position]['labelCategory'] = category.label ? category.label : null;
@ -672,9 +711,11 @@ export class ParsingFunctions {
} }
} }
} else { } else {
contexts[position] = {"labelContext": "", "idContext": "", contexts[position] = {
"labelCategory": "", "idCategory": "", "labelContext": "", "idContext": "",
"labelConcept": "", "idConcept": ""}; "labelCategory": "", "idCategory": "",
"labelConcept": "", "idConcept": ""
};
contexts[position]['labelContext'] = context.label; contexts[position]['labelContext'] = context.label;
contexts[position]['idContext'] = context.id; contexts[position]['idContext'] = context.id;
contexts[position]['labelCategory'] = null; contexts[position]['labelCategory'] = null;
@ -688,11 +729,15 @@ export class ParsingFunctions {
} }
return contexts; return contexts;
} }
public static getEnermapsConceptId(contexts: any): string{
let enermapsconcepts = contexts.filter(c=> {return c.idCategory == "enermaps::selection" && c.idConcept}); public static getEnermapsConceptId(contexts: any): string {
return enermapsconcepts && enermapsconcepts.length > 0?enermapsconcepts[0].idConcept.split("enermaps::selection::")[1]:null; 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" // return "hotmaps_heat_tot_curr_density"
} }
parseTypes(types: string[], uniqueTypes: Set<string>, instance: any) { parseTypes(types: string[], uniqueTypes: Set<string>, instance: any) {
if (instance && instance.hasOwnProperty("instancetype") && instance['instancetype'].classname) { if (instance && instance.hasOwnProperty("instancetype") && instance['instancetype'].classname) {
if (!uniqueTypes.has(instance['instancetype'].classname)) { if (!uniqueTypes.has(instance['instancetype'].classname)) {
@ -704,7 +749,7 @@ export class ParsingFunctions {
parseLanguages(_languages: any) { parseLanguages(_languages: any) {
var languages = new Array<string>(); var languages = new Array<string>();
if (!Array.isArray(_languages)) { if (!Array.isArray(_languages)) {
if (_languages.classname != "Undetermined" && _languages.classname) { if (_languages.classname != "Undetermined" && _languages.classname) {
languages.push(_languages.classname); languages.push(_languages.classname);
@ -727,7 +772,7 @@ export class ParsingFunctions {
countries.push(_countries.classname); countries.push(_countries.classname);
} }
} else { } 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) { if (_countries[i].classname != "Undetermined" && _countries[i].classname) {
countries.push(_countries[i].classname); countries.push(_countries[i].classname);
} }
@ -758,10 +803,10 @@ export class ParsingFunctions {
citations = Array.isArray(citations) ? citations : [citations]; citations = Array.isArray(citations) ? citations : [citations];
citations.forEach(citation => { citations.forEach(citation => {
let reference: Reference = {name: null, ids: []}; let reference: Reference = {name: null, ids: []};
if(citation.rawText) { if (citation.rawText) {
reference.name = citation.rawText; reference.name = citation.rawText;
} }
if(citation.id) { if (citation.id) {
let ids: any[] = Array.isArray(citation.id) ? citation.id : [citation.id]; let ids: any[] = Array.isArray(citation.id) ? citation.id : [citation.id];
ids.forEach(id => { ids.forEach(id => {
reference.ids.push({ reference.ids.push({
@ -775,35 +820,123 @@ export class ParsingFunctions {
}); });
return references; return references;
} }
static parseRelCanonicalId(record, type){
try{ static parseRelCanonicalId(record, type) {
if(record["result"]["metadata"]["oaf:entity"][("oaf:"+type)]["children"] && record["result"]["metadata"]["oaf:entity"][("oaf:"+type)]["children"][type]){ try {
for(let child of record["result"]["metadata"]["oaf:entity"][("oaf:"+type)]["children"][type]){ 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"]; return child["objidentifier"];
} }
} }
}catch(e){ } catch (e) {
// console.error(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 = []; let abstracts = [];
if(!Array.isArray(description)) { if (!Array.isArray(description)) {
abstracts = [description ? String(description) : ""]; abstracts = [description ? String(description) : ""];
} else { } else {
abstracts = description.map( x => String(x)); abstracts = description.map(x => String(x));
} }
try{ try {
abstracts = abstracts.map( x => StringUtils.HTMLToString(x)); abstracts = abstracts.map(x => StringUtils.HTMLToString(x));
} catch (e) {} } catch (e) {
abstracts = abstracts.sort((a,b) => b.length - a.length); }
if(stripHTML) { abstracts = abstracts.sort((a, b) => b.length - a.length);
return abstracts.join(' '); if (stripHTML) {
} else { return abstracts.join(' ');
return abstracts.length > 0 ? ('<p>' + abstracts.join('</p> <p>') + '</p>') : 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]', selector: 'relatedTo, [relatedTo]',
template: ` template: `
<ng-container *ngIf="communities && communities.length > 0"> <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()"> <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> <icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
{{title}} {{title}}
</span> </span>
<span *ngIf="!viewAll || lessBtn" class="uk-text-light-grey">{{title}}</span> <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">View less</a> <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" <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>
<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 --> <!-- If there are any communities with dashboard -->
<a *ngIf="community.link" href="{{community.link}}" target="_blank" [attr.uk-tooltip]="community.labelContext" class="custom-external"> <a *ngIf="community.link" href="{{community.link}}" target="_blank" [attr.uk-tooltip]="community.labelContext" class="custom-external">
{{community.labelContext}} {{community.labelContext}}
@ -44,6 +45,7 @@ import {OpenaireEntities} from "../../utils/properties/searchFields";
}) })
export class RelatedToComponent implements OnInit { export class RelatedToComponent implements OnInit {
@Input() mobileView: boolean = false;
@Input() contexts: Context[]; @Input() contexts: Context[];
@Input() viewAll: boolean = false; @Input() viewAll: boolean = false;
@Output() viewAllClicked = new EventEmitter(); @Output() viewAllClicked = new EventEmitter();

View File

@ -16,23 +16,34 @@ import {FosComponent} from "./fos.component";
import {SdgComponent} from "./sdg.component"; import {SdgComponent} from "./sdg.component";
import {IconsModule} from "../../utils/icons/icons.module"; import {IconsModule} from "../../utils/icons/icons.module";
import {AlertModalModule} from "../../utils/modal/alertModal.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({ @NgModule({
imports: [ imports: [
CommonModule, FormsModule, RouterModule, PagingModule, ShowPublisherModule, IconsModule, AlertModalModule CommonModule, FormsModule, RouterModule, PagingModule, ShowPublisherModule, IconsModule, AlertModalModule,
SearchInputModule, FullScreenModalModule
], ],
declarations: [ declarations: [
ShowIdentifiersComponent,ShowSubjectsComponent, ShowIdentifiersComponent,ShowSubjectsComponent,
FundedByComponent,AvailableOnComponent,TabTableComponent, FundedByComponent,AvailableOnComponent,TabTableComponent,
RelatedToComponent, FosComponent, SdgComponent RelatedToComponent, FosComponent, SdgComponent,
EntityMetadataComponent
], ],
providers:[ providers:[
], ],
exports: [ exports: [
ShowIdentifiersComponent, ShowSubjectsComponent, ShowIdentifiersComponent, ShowSubjectsComponent,
FundedByComponent,AvailableOnComponent, TabTableComponent, ShowPublisherComponent, 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({ @Component({
selector: 'sdg', selector: 'sdg',
template: ` template: `
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div> <div class="uk-visible@m">
<div [class]="'uk-flex uk-flex-between uk-flex-middle uk-margin-'+(viewAll?'':'small-')+'bottom'"> <div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
<span *ngIf="viewAll" class="clickable uk-h6 uk-flex uk-flex-middle uk-margin-small-right uk-margin-remove-bottom" <div [class]="'uk-flex uk-flex-between uk-flex-middle uk-margin-'+(viewAll?'':'small-')+'bottom'">
(click)="viewLessClick()"> <span *ngIf="viewAll" class="clickable uk-h6 uk-flex uk-flex-middle uk-margin-small-right uk-margin-remove-bottom"
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon> (click)="viewLessClick()">
<span uk-tooltip="Sustainable Development Goals">{{title}}</span> <icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
</span> <span uk-tooltip="Sustainable Development Goals">{{title}}</span>
<span *ngIf="!viewAll" class="uk-text-light-grey uk-text-nowrap uk-margin-small-right" uk-tooltip="Sustainable Development Goals">{{title}}</span> </span>
<!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>--> <span *ngIf="!viewAll" class="uk-text-emphasis uk-text-bolder uk-text-nowrap uk-margin-small-right" uk-tooltip="Sustainable Development Goals">
<a *ngIf="properties.adminToolsPortalType == 'eosc' && subjects && subjects.length > threshold && !viewAll" {{title}}
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate" uk-tooltip="View all"> <span *ngIf="subjects && subjects.length > threshold && !viewAll">({{subjects.length}})</span>
View all</a> </span>
<a *ngIf="properties.adminToolsPortalType !== 'eosc' && subjects && subjects.length > threshold && !viewAll" <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"> (click)="viewAllClick();" class="view-more-less-link uk-link uk-link-text uk-text-truncate">
View all & feedback</a> View all</a>
<a *ngIf="properties.adminToolsPortalType !== 'eosc' && (subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-text-truncate" <!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a> -->
(click)="feedbackClick();">Feedback</a> <a *ngIf="properties.adminToolsPortalType != 'eosc' && subjects && subjects.length > threshold && !viewAll"
</div> (click)="viewAllClick();" class="view-more-less-link uk-link uk-link-text uk-text-truncate">
View all & suggest</a>
<div class="uk-margin-small-bottom uk-flex"> <a *ngIf="properties.adminToolsPortalType != 'eosc' && (subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-link-text uk-text-truncate"
<img src="assets/common-assets/common/The_Global_Goals_Icon_Color.svg" (click)="suggestClick();">Suggest</a>
loading="lazy" alt="sdg_colors" style="width:27px; height:27px"> </div>
<div class="uk-margin-small-left"> <div class="uk-margin-small-bottom uk-flex">
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate"> <img src="assets/common-assets/common/The_Global_Goals_Icon_Color.svg"
<a *ngIf="properties.adminToolsPortalType !== 'eosc'" loading="lazy" alt="sdg_colors" style="width:27px; height:27px">
[routerLink]=" properties.searchLinkToResults" [queryParams]="{'sdg': urlEncodeAndQuote(subject)}"> <div class="uk-margin-small-left">
{{subject}} <div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate">
</a> <a *ngIf="properties.adminToolsPortalType != 'eosc'"
<a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank" [routerLink]=" properties.searchLinkToResults" [queryParams]="{'sdg': urlEncodeAndQuote(subject)}">
[href]="'https://explore.openaire.eu'+properties.searchLinkToResults+'?sdg='+urlEncodeAndQuote(subject)"> {{subject}}
{{subject}} </a>
</a> <a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank"
</div> [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> </div>
` `
}) })
@ -48,9 +75,9 @@ export class SdgComponent {
@Input() subjects: string[]; @Input() subjects: string[];
@Input() viewAll: boolean = false; @Input() viewAll: boolean = false;
@Output() viewAllClicked = new EventEmitter(); @Output() viewAllClicked = new EventEmitter();
@Output() feedbackClicked = new EventEmitter(); @Output() suggestClicked = new EventEmitter();
public lessBtn: boolean = false; public lessBtn: boolean = false;
public threshold: number = 4; public threshold: number = 2;
public routerHelper: RouterHelper = new RouterHelper(); public routerHelper: RouterHelper = new RouterHelper();
public properties = properties; public properties = properties;
public title: string = "SDGs"; public title: string = "SDGs";
@ -70,8 +97,8 @@ export class SdgComponent {
this.viewAllClicked.emit(""); this.viewAllClicked.emit("");
} }
public feedbackClick() { public suggestClick() {
this.feedbackClicked.emit(""); this.suggestClicked.emit('sdg');
} }
public urlEncodeAndQuote(str: string): string { 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> <a (click)="openIdentifiersModal()" class="view-more-less-link">View all</a>
</div> </div>
<modal-alert #identifiersModal> <modal-alert *ngIf="!isMobile" #identifiersModal>
<div class="uk-text-small"> <div class="uk-text-small">
<ng-container *ngTemplateOutlet="identifiers_template; context: { modal: true}"></ng-container> <ng-container *ngTemplateOutlet="identifiers_template; context: { modal: true}"></ng-container>
</div> </div>
</modal-alert> </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 { export class ShowIdentifiersComponent implements AfterViewInit {
@Input() isMobile: boolean = false;
@Input() identifiers: Map<string, string[]>; @Input() identifiers: Map<string, string[]>;
@Input() showViewAll: boolean = false; @Input() showViewAll: boolean = false;
large: Map<string, boolean> = new Map<string, boolean>(); large: Map<string, boolean> = new Map<string, boolean>();
@ -121,9 +128,15 @@ export class ShowIdentifiersComponent implements AfterViewInit {
} }
public openIdentifiersModal() { public openIdentifiersModal() {
this.identifiersModal.cancelButton = false; if(this.isMobile) {
this.identifiersModal.okButton = false; this.identifiersModal.okButton = false;
this.identifiersModal.alertTitle = "Persistent Identifiers"; this.identifiersModal.title = "Persistent Identifiers";
this.identifiersModal.open(); 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({ @Component({
selector: 'showPublisher, [showPublisher]', selector: 'showPublisher, [showPublisher]',
template: ` template: `
<div *ngIf="publishDate || journal && (journal['journal'] || journal['issn'] || journal['lissn'] <ng-container *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
|| journal['volume'] || journal['eissn'] || journal['issue'])" class="uk-text-small"> || journal['volume'] || journal['eissn'] || journal['issue'])">
<span *ngIf="publishDate" class="uk-margin-right"> <ng-container *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
<span class="uk-text-meta">Published: </span> || journal['volume'] || journal['eissn'] || journal['issue'])">
{{publishDate | date: 'dd MMM yyyy' : 'UTC'}} <span [attr.uk-tooltip]="'cls: uk-active'" [title]="'Journal'">
</span> <span *ngIf="journal['journal']">{{journal['journal']}}</span>
<span *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn'] <span *ngIf="journal['journal'] && (journal['volume'] || journal['issue'])">, </span>
|| journal['volume'] || journal['eissn'] || journal['issue'])"> <ng-container *ngIf="journal['volume']">
<span class="uk-text-meta">Journal: </span> <span class="uk-display-inline-block">
<span *ngIf="journal['journal']">{{journal['journal']}}</span> volume
<span *ngIf="journal['journal'] && (journal['volume'] || journal['issue'])">, </span> <span *ngIf="journal['volume'] > 0">{{journal['volume'] | number}}</span>
<ng-container *ngIf="journal['volume']"> <span *ngIf="!(journal['volume'] > 0)">{{journal['volume']}}</span>
<span class="uk-display-inline-block"> </span>
volume <span *ngIf="journal['issue'] || journal['start_page'] || journal['end_page']">, </span>
<span *ngIf="journal['volume'] > 0">{{journal['volume'] | number}}</span> </ng-container>
<span *ngIf="!(journal['volume'] > 0)">{{journal['volume']}}</span> <ng-container *ngIf="journal['issue']">
</span> <span class="uk-display-inline-block">
<span *ngIf="journal['issue'] || journal['start_page'] || journal['end_page']">, </span> issue
</ng-container> <span *ngIf="journal['issue'] > 0">{{journal['issue'] | number}}</span>
<ng-container *ngIf="journal['issue']"> <span *ngIf="!(journal['issue'] > 0)">{{journal['issue']}}</span>
<span class="uk-display-inline-block"> </span>
issue <span *ngIf="journal['start_page'] || journal['end_page']">, </span>
<span *ngIf="journal['issue'] > 0">{{journal['issue'] | number}}</span> </ng-container>
<span *ngIf="!(journal['issue'] > 0)">{{journal['issue']}}</span> <span *ngIf="(journal['volume'] || journal['issue']) && (journal['start_page'] || journal['end_page'])"
</span> class="uk-display-inline-block">
<span *ngIf="journal['start_page'] || journal['end_page']">, </span> {{(journal['start_page'] && journal['end_page']) ? 'pages' : 'page'}}
</ng-container> <span *ngIf="journal['start_page']">
<span *ngIf="(journal['volume'] || journal['issue']) && (journal['start_page'] || journal['end_page'])" <span *ngIf="journal['start_page'] > 0">{{journal['start_page'] | number}}</span>
class="uk-display-inline-block"> <span *ngIf="!(journal['start_page'] > 0)">{{journal['start_page']}}</span>
{{(journal['start_page'] && journal['end_page']) ? 'pages' : 'page'}} </span>
<span *ngIf="journal['start_page']"> <span *ngIf="journal['start_page'] && journal['end_page']">-</span>
<span *ngIf="journal['start_page'] > 0">{{journal['start_page'] | number}}</span> <span *ngIf="journal['end_page']">
<span *ngIf="!(journal['start_page'] > 0)">{{journal['start_page']}}</span> <span *ngIf="journal['end_page'] > 0">{{journal['end_page'] | number}}</span>
</span> <span *ngIf="!(journal['end_page'] > 0)">{{journal['end_page']}}</span>
<span *ngIf="journal['start_page'] && journal['end_page']">-</span> </span>
<span *ngIf="journal['end_page']"> </span>
<span *ngIf="journal['end_page'] > 0">{{journal['end_page'] | number}}</span> <span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])"> (</span>
<span *ngIf="!(journal['end_page'] > 0)">{{journal['end_page']}}</span> <ng-container *ngIf="journal['issn']">
</span> <span class="uk-display-inline-block">issn: {{journal['issn']}}</span>
</span> <span>, </span>
<span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])"> (</span> </ng-container>
<ng-container *ngIf="journal['issn']"> <ng-container *ngIf="journal['eissn']">
<span class="uk-display-inline-block">issn: {{journal['issn']}}</span> <span class="uk-display-inline-block">eissn: {{journal['eissn']}}</span>
<span>, </span> <span>, </span>
</ng-container> </ng-container>
<ng-container *ngIf="journal['eissn']"> <span *ngIf="journal['lissn']" class="uk-display-inline-block">
<span class="uk-display-inline-block">eissn: {{journal['eissn']}}</span> <span class="uk-display-inline-block">lissn: {{journal['lissn']}}</span>
<span>, </span> <span>, </span>
</ng-container> </span>
<span *ngIf="journal['lissn']" class="uk-display-inline-block"> <span *ngIf="journal && (journal['issn'] ||journal['lissn'] || journal['eissn'] )">
<span class="uk-display-inline-block">lissn: {{journal['lissn']}}</span> <a target="_blank" class="uk-display-inline-block custom-external"
<span>, </span> [href]="properties.sherpaURL+(journal['issn']?journal['issn']:(journal['eissn']?journal['eissn']:journal['lissn'] ))+properties.sherpaURLSuffix"
</span> uk-tooltip="title: View information on Sherpa/RoMEO ">
<span *ngIf="journal && (journal['issn'] ||journal['lissn'] || journal['eissn'] )"> <img src="assets/common-assets/common/SHERPA-RoMEO-short-logo.gif" width=16 height=16 alt="" loading="lazy">
<a target="_blank" class="uk-display-inline-block custom-external" Copyright policy
[href]="properties.sherpaURL+(journal['issn']?journal['issn']:(journal['eissn']?journal['eissn']:journal['lissn'] ))+properties.sherpaURLSuffix" </a>
uk-tooltip="title: View information on Sherpa/RoMEO "> </span>
<img src="assets/common-assets/common/SHERPA-RoMEO-short-logo.gif" width=16 height=16 alt="" loading="lazy"> <span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])">)</span>
Copyright policy </span>
</a> </ng-container>
</span> <span *ngIf="publisher" class="uk-margin-xsmall-left uk-margin-xsmall-right bullet"></span>
<span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])">)</span> </ng-container>
</span> <ng-container *ngIf="publisher">
</div> <span [attr.uk-tooltip]="'cls: uk-active'" [title]="'Publisher'">{{publisher}}</span>
<div *ngIf="publisher" class="uk-text-small uk-margin-small-top"> </ng-container>
<span class="uk-text-meta">Publisher: </span> {{publisher}}
</div>
` `
}) })
export class ShowPublisherComponent { export class ShowPublisherComponent {
@Input() publishDate: Date;
@Input() publisher; @Input() publisher;
@Input() journal; @Input() journal;
//@Input() sherpaUrl = 'http://www.sherpa.ac.uk/romeo/search.php?issn='; //@Input() sherpaUrl = 'http://www.sherpa.ac.uk/romeo/search.php?issn=';

View File

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

View File

@ -1,9 +1,9 @@
import { import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ElementRef, ElementRef, EventEmitter,
HostListener, HostListener,
Input, Input, Output,
QueryList, QueryList,
ViewChild, ViewChild,
ViewChildren ViewChildren
@ -13,24 +13,24 @@ import {properties} from "../../../../environments/environment";
@Component({ @Component({
selector: 'showSubjects', selector: 'showSubjects',
template: ` template: `
<ng-container *ngIf="(classifiedSubjects && classifiedSubjects.size > 0) || (eoscSubjects && eoscSubjects.length > 0)"> <ng-container *ngIf="!viewAllSubjects && ((classifiedSubjects && classifiedSubjects.size > 0) || (eoscSubjects && eoscSubjects.length > 0))">
<div class="uk-text-meta"> <div *ngIf="!viewAllClassifiedSubjects" class="uk-text-meta">
Subjects by Vocabulary Subjects by Vocabulary
</div> </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> <ng-container *ngIf="eoscSubjects && eoscSubjects.length > 0"><ng-container *ngTemplateOutlet="eosc_subjects_template"></ng-container></ng-container>
<div *ngIf="isClassifiedLarge" class="uk-text-right"> <div *ngIf="isClassifiedLarge && !viewAllClassifiedSubjects" class="uk-text-right">
<a (click)="openSubjectsByVocabularyModal()" class="view-more-less-link">View all</a> <a (click)="viewAllSubjectsByVocabularyClicked()" class="view-more-less-link">View all</a>
</div> </div>
</ng-container> </ng-container>
<ng-container *ngIf="(subjects && subjects.length > 0) || (otherSubjects && otherSubjects.size > 0)"> <ng-container *ngIf="!viewAllClassifiedSubjects && ((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"> <div *ngIf="!viewAllSubjects" class="uk-text-meta uk-margin-small-bottom" [class.uk-margin-medium-top]="classifiedSubjects && classifiedSubjects.size > 0">
Subjects Keywords
</div> </div>
<ng-container *ngTemplateOutlet="subjects_template; context: {customClasses: 'multi-line-ellipsis lines-2', id: 'content'}"></ng-container> <ng-container *ngTemplateOutlet="subjects_template; context: {customClasses: (isMobile && viewAllSubjects) ? '' : 'multi-line-ellipsis lines-2', id: 'content'}"></ng-container>
<div *ngIf="isLarge" class="uk-text-right uk-margin-small-top"> <div *ngIf="isLarge && !viewAllSubjects" class="uk-text-right uk-margin-small-top">
<a (click)="openSubjectsModal()" class="view-more-less-link">View all</a> <a (click)="viewAllSubjectsClicked()" class="view-more-less-link">View all</a>
</div> </div>
</ng-container> </ng-container>
@ -49,7 +49,7 @@ import {properties} from "../../../../environments/environment";
</div> </div>
</ng-template> </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"> <div class="uk-text-small">
<ng-container *ngTemplateOutlet="subjects_template"></ng-container> <ng-container *ngTemplateOutlet="subjects_template"></ng-container>
</div> </div>
@ -94,7 +94,7 @@ import {properties} from "../../../../environments/environment";
</div> </div>
</ng-template> </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"> <div class="uk-text-small">
<ng-container *ngTemplateOutlet="subjects_by_vocabulary_template"></ng-container> <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> <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 { export class ShowSubjectsComponent {
@Input() isMobile: boolean = false;
@Input() subjects: string[]; @Input() subjects: string[];
@Input() otherSubjects: Map<string, string[]>; @Input() otherSubjects: Map<string, string[]>;
@Input() classifiedSubjects: Map<string, string[]>; @Input() classifiedSubjects: Map<string, string[]>;
@Input() eoscSubjects: any[]; @Input() eoscSubjects: any[];
isLarge: boolean = false; isLarge: boolean = false;
isClassifiedLarge: boolean = false; isClassifiedLarge: boolean = false;
@Input() viewAllSubjects: boolean = false;
@Input() viewAllClassifiedSubjects: boolean = false;
@Output() viewAllClicked = new EventEmitter();
properties = properties; properties = properties;
specialSubjects = []; specialSubjects = [];
@ViewChildren("content", { read: ElementRef }) content: QueryList<ElementRef>; @ViewChildren("content", { read: ElementRef }) content: QueryList<ElementRef>;
@ -206,4 +210,28 @@ export class ShowSubjectsComponent {
this.subjectsByVocabularyModal.alertTitle = "Subjects by Vocabulary"; this.subjectsByVocabularyModal.alertTitle = "Subjects by Vocabulary";
this.subjectsByVocabularyModal.open(); 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 {Component, ElementRef, Input, ViewChild} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
@Component({ @Component({
selector: 'showTitle', selector: 'showTitle',
template: ` template: `
<h1 [ngClass]="classNames" class="uk-h5"> <h1 [ngClass]="classNames" class="uk-h6">
<ng-container *ngTemplateOutlet="_title;"></ng-container> <ng-container *ngTemplateOutlet="_title;"></ng-container>
</h1> </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>
`
}) <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 { export class ShowTitleComponent {
@Input() titleName: string; @Input() titleName: string;
@Input() title: { [key: string]: string }; @Input() title: { [key: string]: string };
@Input() iconClass:string; @Input() iconClass:string;
@Input() classNames: string = ""; @Input() classNames: string = "";
@Input() isSticky: boolean = false;
@ViewChild("titleDiv") titleDiv: ElementRef;
constructor () {} 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"> <ul class="uk-list uk-list-divider uk-margin">
<li *ngFor="let result of results.slice((page-1)*pageSize, page*pageSize)"> <li *ngFor="let result of results.slice((page-1)*pageSize, page*pageSize)">
<result-preview [modal]="modal" [properties]="properties" [hasLink]="false" [result]="getResultPreview(result)" <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> </li>
</ul> </ul>
<no-load-paging *ngIf="results.length > pageSize" [type]="type" <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"> <!-- Desktop view -->
<div class="tm-main"> <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 class="organization">
<div *ngIf="properties.adminToolsPortalType == 'eosc'" class="eosc-explore-back-search-bar"> <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"> <div class="uk-light uk-container uk-container-large uk-padding-small uk-height-1-1">
@ -13,13 +14,12 @@
</div> </div>
<div *ngIf="!showFeedback" class="uk-grid uk-margin-remove-left" uk-grid> <div *ngIf="!showFeedback" class="uk-grid uk-margin-remove-left" uk-grid>
<!-- left column --> <!-- 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" <div class="uk-flex uk-flex-column uk-flex-right uk-sticky"
uk-sticky="bottom: true" [attr.offset]="offset"> uk-sticky="bottom: true" [attr.offset]="offset">
<div class="uk-margin-large-bottom uk-align-center"> <div class="uk-margin-large-bottom uk-align-center">
<div class="uk-text-meta uk-text-uppercase">Actions</div> <div class="uk-text-meta uk-text-uppercase">Actions</div>
<ul class="uk-list"> <ul class="uk-list">
<!-- Share -->
<li class="uk-text-center"> <li class="uk-text-center">
<a (click)="openAddThisModal()" [title]="'Share this '+openaireEntities.ORGANIZATION+' in your social networks'" <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'"> [attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
@ -28,7 +28,6 @@
</span> </span>
</a> </a>
</li> </li>
<!-- Download -->
<li class="uk-text-center" <li class="uk-text-center"
[title]="'Download reports'" [title]="'Download reports'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'"> [attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
@ -41,20 +40,14 @@
</ul> </ul>
</div> </div>
</div> </div>
</div> </div> -->
<!-- center/right column --> <!-- center/right column -->
<div class="uk-width-expand uk-padding-remove uk-background-default"> <div id="landing-center-content" 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>
<!-- Graph and feedback --> <!-- Graph and feedback -->
<ng-template #graph_and_feedback_template> <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--> <!-- Last Index Info-->
<a href="https://graph.openaire.eu" target="_blank" class="uk-width-1-1 uk-width-auto@l"> <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;"> <img src="assets/common-assets/openaire-badge-1.png" alt="Powered by OpenAIRE graph" style="height: 15px;">
@ -70,165 +63,206 @@
</div> </div>
</div> </div>
</ng-template> </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> <ng-container *ngTemplateOutlet="graph_and_feedback_template"></ng-container>
</div> </div>
<div class="uk-margin-large-left uk-margin-large-right" [style]="'margin-bottom: '+graph_height+'px'"> <div class="uk-container uk-container-xlarge">
<ng-container *ngIf="organizationInfo">
<!-- Main content --> <div *ngIf="errorMessage.length > 0 || showLoading" class="uk-container uk-flex uk-flex-center uk-height-viewport uk-position-relative">
<div [attr.style]="'margin-top: '+(graph_height? 'calc(40px + 20px - '+graph_height+'px)': '40px')"> <div *ngIf="errorMessage.length > 0" class="uk-alert uk-alert-danger uk-width-2-3 uk-margin-xlarge-top"
<!-- Schema --> role="alert">{{errorMessage}}</div>
<schema2jsonld *ngIf="organizationInfo" [data]=organizationInfo <div *ngIf="showLoading" class="uk-position-center">
[URL]="properties.domain + properties.baseLink+this.properties.searchLinkToOrganization+organizationInfo.relcanId" <loading></loading>
type="organization"> </div>
</schema2jsonld> </div>
<!-- Actions for mobile viewport -->
<div class="uk-flex uk-flex-right uk-margin-medium-bottom uk-hidden@s"> <!-- new action bar -->
<div class="uk-margin-small-right"> <div *ngIf="!showLoading && organizationInfo" class="uk-margin-top uk-margin-bottom">
<a (click)="openAddThisModal()" [title]="'Share this '+openaireEntities.ORGANIZATION+' in your social networks'" <div class="uk-flex uk-flex-middle uk-flex-center">
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'"> <div class="landing-action-bar uk-box-shadow-small uk-margin-bottom">
<span class="uk-icon-button uk-icon landing-action-button landing-action-button-portal"> <div class="uk-grid uk-grid-small uk-flex-between uk-text-xsmall uk-flex-middle uk-grid-divider" uk-grid>
<icon name="share" visuallyHidden="share"></icon> <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> </span>
</a> </a>
</div> </div>
<div [title]="'Download reports'" <div class="uk-width-expand">
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'"> <entity-actions [share]="true" [type]="'organization'">
<a class="uk-link-text uk-text-bold uk-text-uppercase" (click)="buildFunderOptions(); openDownloadReportsModal()"> <div>
<span class="uk-icon-button uk-icon landing-action-button landing-action-button-portal"> <a (click)="buildFunderOptions(); openDownloadReportsModal()"
<icon name="download" visuallyHidden="download"></icon> class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder">
</span> <icon flex="true" ratio="0.8" name="download" visuallyHidden="download"></icon>
</a> <span class="uk-margin-xsmall-left">Download</span>
</a>
</div>
</entity-actions>
</div>
</div> </div>
</div> </div>
<!-- Helper --> </div>
<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0" </div>
[texts]="pageContents['top']"></helper>
<!-- Versions --> <div class="uk-margin-left uk-margin-right" [style]="'margin-bottom: '+graph_height+'px'">
<span *ngIf="organizationInfo.deletedByInferenceIds" class="uk-text-primary uk-flex uk-flex-middle"> <ng-container *ngIf="organizationInfo">
<icon flex="true" ratio="0.8" name="auto_awesome_motion"></icon> <!-- Main content -->
<a (click)="openDeletedByInference()" class="uk-text-primary uk-text-small uk-margin-small-left"> <div [attr.style]="'margin-top: '+(graph_height? 'calc(40px + 20px - '+graph_height+'px)': '40px')">
View all {{organizationInfo.deletedByInferenceIds.length}} versions <!-- Schema -->
</a> <schema2jsonld *ngIf="organizationInfo" [data]=organizationInfo
</span> [URL]="properties.domain + properties.baseLink+this.properties.searchLinkToOrganization+organizationInfo.relcanId"
<!-- Landing header --> type="organization">
<landing-header [properties]="properties" [title]="organizationInfo.title.name" </schema2jsonld>
[subTitle]="(organizationInfo.name <!-- Actions for mobile viewport -->
&& organizationInfo.title.name !== organizationInfo.name)?organizationInfo.name:null" <div class="uk-flex uk-flex-right uk-margin-medium-bottom uk-hidden@s">
[entityType]="'organization'"> <div class="uk-margin-small-right">
</landing-header> <a (click)="openAddThisModal()" [title]="'Share this '+openaireEntities.ORGANIZATION+' in your social networks'"
<!-- Basic info --> [attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
<div class="uk-text-small"> <span class="uk-icon-button uk-icon landing-action-button landing-action-button-portal">
<!-- Web Page --> <icon name="share" visuallyHidden="share"></icon>
<div *ngIf="organizationInfo.title && organizationInfo.title.url" class="uk-margin-small-bottom uk-display-inline-block"> </span>
<span class="uk-text-meta">Web page: </span> </a>
<a [href]="organizationInfo.title.url" target="_blank" class="uk-button uk-button-text uk-text-lowercase uk-text-normal custom-external"> </div>
{{organizationInfo.title.url}} <div [title]="'Download reports'"
</a> [attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
</div> <a class="uk-link-text uk-text-bold uk-text-uppercase" (click)="buildFunderOptions(); openDownloadReportsModal()">
<!-- Country --> <span class="uk-icon-button uk-icon landing-action-button landing-action-button-portal">
<div *ngIf="organizationInfo.country && !organizationInfo.country.toLowerCase().includes('unknown')"> <icon name="download" visuallyHidden="download"></icon>
<span class="uk-text-meta">Country: </span>{{organizationInfo.country}} </span>
</div> </a>
</div> </div>
</div> </div>
<!-- Tabs section --> <!-- Helper -->
<div id="main-tabs-div" class="uk-sticky uk-blur-background" <helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
uk-sticky="bottom: true; media: @m" [attr.offset]="offset"> [texts]="pageContents['top']"></helper>
<div class="uk-padding uk-padding-remove-horizontal uk-padding-remove-bottom"> <!-- Versions -->
<!-- <showTitle *ngIf="stickyHeader" [titleName]="organizationInfo.title.name" classNames="uk-margin-remove-bottom" class="uk-visible@m"></showTitle>--> <!-- <span *ngIf="organizationInfo.deletedByInferenceIds" class="uk-text-primary uk-flex uk-flex-middle">
<landing-header *ngIf="stickyHeader" class="uk-visible@m" <icon flex="true" ratio="0.8" name="auto_awesome_motion"></icon>
[properties]="properties" [title]="organizationInfo.title.name" <a (click)="openDeletedByInference()" class="uk-text-primary uk-text-small uk-margin-small-left">
[subTitle]="(organizationInfo.name View all {{organizationInfo.deletedByInferenceIds.length}} versions
&& organizationInfo.title.name !== organizationInfo.name)?organizationInfo.name:null" </a>
[entityType]="'organization'" isSticky="true"> </span> -->
</landing-header> <!-- Landing header -->
<my-tabs (selectedActiveTab)="onSelectActiveTab($event)" [offsetForSticky]="offset" [(isSticky)]="stickyHeader"> <landing-header [properties]="properties" [title]="organizationInfo.title.name"
<my-tab [active]="true" [tabTitle]="'Funding / ' +openaireEntities.PROJECTS" [tabId]="'projects'" [subTitle]="(organizationInfo.name
[tabNumber]="fetchProjects.searchUtils.totalResults > 0 ? fetchProjects.searchUtils.totalResults : ''"> && organizationInfo.title.name !== organizationInfo.name)?organizationInfo.name:null"
</my-tab> [entityType]="'organization'" [prevPath]="prevPath">
<my-tab *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0" </landing-header>
[tabTitle]="openaireEntities.DATASOURCES" [tabId]="'dataProviders'" <!-- Basic info -->
[tabNumber]="fetchDataproviders.searchUtils.totalResults"> <div class="uk-text-small">
</my-tab> <!-- Web Page -->
<my-tab *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0" <div *ngIf="organizationInfo.title && organizationInfo.title.url" class="uk-margin-small-bottom uk-display-inline-block">
[tabNumber]="fetchPublications.searchUtils.totalResults" <span class="uk-text-meta">Web page: </span>
[tabTitle]="openaireEntities.PUBLICATIONS" [tabId]="'publications'"> <a [href]="organizationInfo.title.url" target="_blank" class="uk-button uk-button-text uk-text-lowercase uk-text-normal custom-external">
</my-tab> {{organizationInfo.title.url}}
<my-tab *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0" </a>
[tabNumber]="fetchDatasets.searchUtils.totalResults" </div>
[tabTitle]="openaireEntities.DATASETS" [tabId]="'datasets'"> <!-- Country -->
</my-tab> <div *ngIf="organizationInfo.country && !organizationInfo.country.toLowerCase().includes('unknown')">
<my-tab *ngIf="fetchSoftware && fetchSoftware.searchUtils.totalResults > 0" <span class="uk-text-meta">Country: </span>{{organizationInfo.country}}
[tabNumber]="fetchSoftware.searchUtils.totalResults" </div>
[tabTitle]="openaireEntities.SOFTWARE" [tabId]="'software'"> </div>
</my-tab> </div>
<my-tab *ngIf="fetchOrps && fetchOrps.searchUtils.totalResults > 0" <!-- Tabs section -->
[tabNumber]="fetchOrps.searchUtils.totalResults" <div id="main-tabs-div" class="uk-sticky uk-blur-background"
[tabTitle]="openaireEntities.OTHER" [tabId]="'other'"> uk-sticky="bottom: true; media: @m" [attr.offset]="offset">
</my-tab> <div class="uk-padding uk-padding-remove-horizontal uk-padding-remove-bottom">
</my-tabs> <!-- <showTitle *ngIf="stickyHeader" [titleName]="organizationInfo.title.name" classNames="uk-margin-remove-bottom" class="uk-visible@m"></showTitle>-->
</div> <landing-header [ngClass]="stickyHeader ? 'uk-visible@m' : 'uk-invisible'"
</div> [properties]="properties" [title]="organizationInfo.title.name"
<!-- Tabs content section --> [entityType]="'organization'" isSticky="true" [prevPath]="prevPath">
<div id="landing-sections" class="uk-text-small"> </landing-header>
<div id="projects" class="landing-section landing-section-height-auto uk-padding uk-padding-remove-horizontal"> <my-tabs (selectedActiveTab)="onSelectActiveTab($event)" [offsetForSticky]="offset" [(isSticky)]="stickyHeader">
<projectsInModal [fetchProjects]="fetchProjects" <my-tab [active]="true" [tabTitle]="'Funding / ' +openaireEntities.PROJECTS" [tabId]="'projects'"
[organizationId]="organizationId" [properties]=properties [prevPath]="prevPath"> [tabNumber]="fetchProjects.searchUtils.totalResults > 0 ? fetchProjects.searchUtils.totalResults : ''">
</projectsInModal> </my-tab>
</div> <my-tab *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0"
<div *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0" [tabTitle]="openaireEntities.DATASOURCES" [tabId]="'dataProviders'"
id="dataProviders" class="landing-section uk-padding uk-padding-remove-horizontal"> [tabNumber]="fetchDataproviders.searchUtils.totalResults">
<search-tab [fetch]="fetchDataproviders" resultType="dataprovider" </my-tab>
[params]="getParamsForSearchLink()" <my-tab *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedDataProviders" [tabNumber]="fetchPublications.searchUtils.totalResults"
[properties]="properties" [prevPath]="prevPath"> [tabTitle]="openaireEntities.PUBLICATIONS" [tabId]="'publications'">
</search-tab> </my-tab>
</div> <my-tab *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0"
<div *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0" [tabNumber]="fetchDatasets.searchUtils.totalResults"
id="publications" class="landing-section uk-padding uk-padding-remove-horizontal"> [tabTitle]="openaireEntities.DATASETS" [tabId]="'datasets'">
<search-tab [fetch]="fetchPublications" resultType="publication" </my-tab>
[params]="getParamsForSearchLink('publications')" <my-tab *ngIf="fetchSoftware && fetchSoftware.searchUtils.totalResults > 0"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults" [tabNumber]="fetchSoftware.searchUtils.totalResults"
[properties]="properties" [prevPath]="prevPath"> [tabTitle]="openaireEntities.SOFTWARE" [tabId]="'software'">
</search-tab> </my-tab>
</div> <my-tab *ngIf="fetchOrps && fetchOrps.searchUtils.totalResults > 0"
<div *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0" [tabNumber]="fetchOrps.searchUtils.totalResults"
id="datasets" class="landing-section uk-padding uk-padding-remove-horizontal"> [tabTitle]="openaireEntities.OTHER" [tabId]="'other'">
<search-tab [fetch]="fetchDatasets" resultType="dataset" </my-tab>
[params]="getParamsForSearchLink('datasets')" </my-tabs>
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults" </div>
[properties]="properties" [prevPath]="prevPath"> </div>
</search-tab> <!-- Tabs content section -->
</div> <div id="landing-sections" class="uk-text-small">
<div *ngIf="fetchSoftware && fetchSoftware.searchUtils.totalResults > 0" <div id="projects" class="landing-section landing-section-height-auto">
id="software" class="landing-section uk-padding uk-padding-remove-horizontal"> <projectsInModal [fetchProjects]="fetchProjects"
<search-tab [fetch]="fetchSoftware" resultType="software" [organizationId]="organizationId" [properties]=properties [prevPath]="prevPath">
[params]="getParamsForSearchLink('software')" </projectsInModal>
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults" </div>
[properties]="properties" [prevPath]="prevPath"> <div *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0"
</search-tab> id="dataProviders" class="landing-section">
</div> <search-tab [fetch]="fetchDataproviders" resultType="dataprovider"
<div *ngIf="fetchOrps && fetchOrps.searchUtils.totalResults > 0" [params]="getParamsForSearchLink()"
id="other" class="landing-section uk-padding uk-padding-remove-horizontal"> [searchLinkToAdvancedPage]="properties.searchLinkToAdvancedDataProviders"
<search-tab [fetch]="fetchOrps" resultType="other" [properties]="properties" [prevPath]="prevPath">
[params]="getParamsForSearchLink('other')" </search-tab>
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults" </div>
[properties]="properties" [prevPath]="prevPath"> <div *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0"
</search-tab> id="publications" class="landing-section">
</div> <search-tab [fetch]="fetchPublications" resultType="publication"
</div> [params]="getParamsForSearchLink('publications')"
<div class="uk-text-xsmall uk-hidden@m"> [searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
<ng-container *ngTemplateOutlet="graph_and_feedback_template"></ng-container> [properties]="properties" [prevPath]="prevPath">
</div> </search-tab>
<!-- Helper --> </div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0" <div *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0"
[texts]="pageContents['bottom']"> id="datasets" class="landing-section">
</helper> <search-tab [fetch]="fetchDatasets" resultType="dataset"
</ng-container> [params]="getParamsForSearchLink('datasets')"
</div> [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> </div>
</div> </div>
@ -240,6 +274,114 @@
</feedback> </feedback>
</div> </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 --> <!-- MODALS -->
<!-- Other versions --> <!-- Other versions -->
<modal-alert #AlertModalDeletedByInference *ngIf="organizationInfo && organizationInfo.deletedByInferenceIds" large="true"> <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-margin-small-left uk-margin-small-right">
<div class="uk-padding-small uk-padding-remove-vertical"> <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-grid uk-grid-divider uk-child-width-1-2@m" uk-grid uk-height-match=".subtitle">
<div class="uk-animation-slide-top-small"> <ng-container *ngTemplateOutlet="downloadOptions"></ng-container>
<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>
</div> </div>
</div> </div>
</div> </div>
</modal-alert> </modal-alert>
<modal-alert #AlertModalApplyAll (alertOutput)="confirmCloseApplyAll()"></modal-alert> <modal-alert #AlertModalApplyAll (alertOutput)="confirmCloseApplyAll()"></modal-alert>
<modal-alert #AlertModalCsvError></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 {properties} from "../../../../environments/environment";
import {OpenaireEntities} from '../../utils/properties/searchFields'; import {OpenaireEntities} from '../../utils/properties/searchFields';
import {Option} from '../../sharedComponents/input/input.component'; 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; declare var ResizeObserver;
@ -71,17 +73,23 @@ export class OrganizationComponent {
// Active tab variable for responsiveness // Active tab variable for responsiveness
public activeTab: string = ""; public activeTab: string = "";
@ViewChild('fsModal') fsModal: FullScreenModalComponent;
@ViewChild('downloadReportsModal') downloadReportsModal;
@ViewChild('downloadReportsModal') downloadReportsModal;
@ViewChild('downloadReportsFsModal') downloadReportsFsModal: FullScreenModalComponent;
// @ViewChild('downloadReportModal') downloadReportModal; // @ViewChild('downloadReportModal') downloadReportModal;
// @ViewChild('downloadFunderReportModal') downloadFunderReportModal; // @ViewChild('downloadFunderReportModal') downloadFunderReportModal;
@ViewChild('addThisModal') addThisModal; @ViewChild('addThisModal') addThisModal;
@ViewChild('addThisFsModal') addThisFsModal: FullScreenModalComponent;
@ViewChild(ModalLoading) loading: ModalLoading; @ViewChild(ModalLoading) loading: ModalLoading;
// Alert box when CSV: Project Publications for a funder is requested // Alert box when CSV: Project Publications for a funder is requested
@ViewChild('AlertModalApplyAll') alertApplyAll; @ViewChild('AlertModalApplyAll') alertApplyAll;
@ViewChild('AlertFsModalApplyAll') alertFsApplyAll;
// Alert box when something is wrong with CSV requests // Alert box when something is wrong with CSV requests
@ViewChild('AlertModalCsvError') alertCsvError; @ViewChild('AlertModalCsvError') alertCsvError;
@ViewChild('AlertFsModalCsvError') alertFsCsvError;
public routerHelper: RouterHelper = new RouterHelper(); public routerHelper: RouterHelper = new RouterHelper();
public errorCodes: ErrorCodes = new ErrorCodes(); public errorCodes: ErrorCodes = new ErrorCodes();
@ -121,10 +129,13 @@ export class OrganizationComponent {
public feedbackFields: string [] = ['Name', 'Country', 'Other']; public feedbackFields: string [] = ['Name', 'Country', 'Other'];
@ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference; @ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference;
@ViewChild('AlertModalDeletedByInferenceFS') alertModalDeletedByInferenceFS;
// @ViewChild('projectsModal') projectsModal; // @ViewChild('projectsModal') projectsModal;
public deleteByInferenceOpened: boolean = false; public deleteByInferenceOpened: boolean = false;
public isMobile: boolean = false;
public mobileContent: "info" | "actions" = "info";
public viewAllMobile: string = "";
constructor(private element: ElementRef, constructor(private element: ElementRef,
private _organizationService: OrganizationService, private _organizationService: OrganizationService,
@ -141,7 +152,8 @@ export class OrganizationComponent {
private seoService: SEOService, private seoService: SEOService,
private _location: Location, private _location: Location,
private indexInfoService: IndexInfoService, private indexInfoService: IndexInfoService,
private cdr: ChangeDetectorRef) { private cdr: ChangeDetectorRef,
private layoutService: LayoutService) {
this.fetchProjects = new FetchProjects(this._searchProjectsService); this.fetchProjects = new FetchProjects(this._searchProjectsService);
this.fetchDataproviders = new FetchDataproviders(this._searchDataprovidersService); this.fetchDataproviders = new FetchDataproviders(this._searchDataprovidersService);
this.fetchPublications = new FetchResearchResults(this._searchResearchResultsService); this.fetchPublications = new FetchResearchResults(this._searchResearchResultsService);
@ -151,19 +163,21 @@ export class OrganizationComponent {
} }
ngOnInit() { ngOnInit() {
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.properties = properties; this.isMobile = isMobile;
if (typeof document !== 'undefined') { }));
this.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(lastIndexUpdate => { this.properties = properties;
if (lastIndexUpdate) { if (typeof document !== 'undefined') {
this.indexUpdateDate = new Date(lastIndexUpdate); 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.getDivContents();
this.seoService.createLinkForCanonicalURL(this.properties.domain +this.properties.baseLink + this._router.url); 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.subscriptions.push(this.route.queryParams.subscribe(params => {
this.organizationInfo = null; this.organizationInfo = null;
@ -266,7 +280,8 @@ export class OrganizationComponent {
this.subscriptions.forEach(subscription => { this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) { if (subscription instanceof Subscriber) {
subscription.unsubscribe(); subscription.unsubscribe();
} else if (subscription instanceof (ResizeObserver || IntersectionObserver)) { } else if ((typeof ResizeObserver != 'undefined' && subscription instanceof ResizeObserver) ||
(typeof IntersectionObserver != 'undefined' && subscription instanceof IntersectionObserver)) {
subscription.disconnect(); subscription.disconnect();
} }
}); });
@ -628,13 +643,19 @@ export class OrganizationComponent {
} }
public confirmOpenApplyAll(contentType: string, contentFileName: string) { public confirmOpenApplyAll(contentType: string, contentFileName: string) {
this.alertApplyAll.cancelButton = true; if(this.isMobile) {
this.alertApplyAll.okButton = true; this.alertFsApplyAll.title = "CSV FILE";
this.alertApplyAll.alertTitle = "CSV FILE"; this.alertFsApplyAll.okButton = false;
this.alertApplyAll.message = "Do you wish to download a CSV file? Note that this process may take a while."; this.alertFsApplyAll.open();
this.alertApplyAll.okButtonText = "Yes"; } else {
this.alertApplyAll.cancelButtonText = "No"; this.alertApplyAll.cancelButton = true;
this.alertApplyAll.open(); 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.funderId = this.funder.id;
this.funderCount = this.funder.number; this.funderCount = this.funder.number;
this.funderContentType = contentType; this.funderContentType = contentType;
@ -646,12 +667,19 @@ export class OrganizationComponent {
} }
public confirmOpenCsvError() { public confirmOpenCsvError() {
this.alertCsvError.cancelButton = false; if(this.isMobile) {
this.alertCsvError.okButton = true; this.alertFsCsvError.okButton = true;
this.alertCsvError.alertTitle = "ERROR DOWNLOADING CSV FILE"; this.alertFsCsvError.okButtonText = "OK";
this.alertCsvError.message = "There was an error in csv downloading. Please try again later."; this.alertFsCsvError.title = "ERROR DOWNLOADING CSV FILE";
this.alertCsvError.okButtonText = "OK"; this.alertFsCsvError.open();
this.alertCsvError.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 { encodeURI(input: string): string {
@ -686,7 +714,7 @@ export class OrganizationComponent {
} }
openDownloadReportsModal() { openDownloadReportsModal() {
this.funder = this.fetchProjects.funders[0]; // this.funder = this.fetchProjects.funders[0];
this.downloadReportsModal.cancelButton = false; this.downloadReportsModal.cancelButton = false;
this.downloadReportsModal.okButton = false; this.downloadReportsModal.okButton = false;
this.downloadReportsModal.alertTitle = "Download"; this.downloadReportsModal.alertTitle = "Download";
@ -808,7 +836,7 @@ export class OrganizationComponent {
for(let funder of this.fetchProjects.funders) { for(let funder of this.fetchProjects.funders) {
this.funderOptions.push({"label": funder.name, "value": funder}); 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(); HelperFunctions.scroll();
} }
public openFsModal(fsModal: FullScreenModalComponent, title: string) {
fsModal.title = title;
fsModal.okButton = false;
fsModal.stayOpenInBack = true;
fsModal.open();
}
public get eoscBackLink() { 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/"))) { 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; return this.referrer + this.prevPath;
} else { } 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 {IconsModule} from '../../utils/icons/icons.module';
import {InputModule} from '../../sharedComponents/input/input.module'; import {InputModule} from '../../sharedComponents/input/input.module';
import {IconsService} from '../../utils/icons/icons.service'; 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({ @NgModule({
@ -48,7 +51,7 @@ import {graph} from "../../utils/icons/icons";
Schema2jsonldModule, SEOServiceModule, HelperModule, Schema2jsonldModule, SEOServiceModule, HelperModule,
OrganizationsDeletedByInferenceModule, LandingHeaderModule, FeedbackModule, OrganizationsDeletedByInferenceModule, LandingHeaderModule, FeedbackModule,
MatSelectModule, MatSelectModule,
TabsModule, SearchTabModule, LoadingModule, IconsModule, InputModule TabsModule, SearchTabModule, LoadingModule, IconsModule, InputModule, FullScreenModalModule, EGIDataTransferModule, EntityActionsModule
], ],
declarations: [ declarations: [
OrganizationComponent, OrganizationComponent,
@ -60,6 +63,6 @@ import {graph} from "../../utils/icons/icons";
}) })
export class OrganizationModule { export class OrganizationModule {
constructor(private iconsService: IconsService) { 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 {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser'; 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 {ResultPreview} from "../../utils/result-preview/result-preview";
import {SearchResult} from "../../utils/entities/searchResult"; import {SearchResult} from "../../utils/entities/searchResult";
import {IndexInfoService} from "../../utils/indexInfo.service"; import {IndexInfoService} from "../../utils/indexInfo.service";
import {Subscriber} from "rxjs"; import {Subscriber, Subscription, zip} from "rxjs";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {Option} from "../../sharedComponents/input/input.component"; import {Option} from "../../sharedComponents/input/input.component";
import {OpenaireEntities} from "../../utils/properties/searchFields"; 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; declare var ResizeObserver;
@ -51,9 +55,13 @@ export class ProjectComponent {
public metricsClicked: boolean; public metricsClicked: boolean;
public viewsFrameUrl: string; public viewsFrameUrl: string;
public downloadsFrameUrl: string; public downloadsFrameUrl: string;
public totalViews: number; /** @deprecated*/
public totalDownloads: number; public totalViews: number = null;
public pageViews: number; /** @deprecated*/
public totalDownloads: number = null;
public hasViews: boolean = false;
public hasDownloads: boolean = false;
// public pageViews: number;
// Statistics tab variables // Statistics tab variables
public statsClicked: boolean; public statsClicked: boolean;
@ -86,8 +94,11 @@ export class ProjectComponent {
// @ViewChild('statisticsModal') statisticsModal; // @ViewChild('statisticsModal') statisticsModal;
// @ViewChild('linkProjectModal') linkProjectModal; // @ViewChild('linkProjectModal') linkProjectModal;
@ViewChild('embedResultsModal') embedResultsModal; @ViewChild('embedResultsModal') embedResultsModal;
@ViewChild('embedResultsFsModal') embedResultsFsModal: FullScreenModalComponent;
@ViewChild('downloadReportModal') downloadReportModal; @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) // Request results for publications, research data and software only the one time (first time tab is clicked)
private reloadPublications: boolean = true; private reloadPublications: boolean = true;
@ -163,9 +174,23 @@ export class ProjectComponent {
// public shouldSticky: boolean = true; // public shouldSticky: boolean = true;
subscriptions = []; subscriptions = [];
private sub: Subscription;
properties: EnvProperties; properties: EnvProperties;
public openaireEntities = OpenaireEntities; 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, constructor(private route: ActivatedRoute,
private _router: Router, private _router: Router,
private _location: Location, private _location: Location,
@ -179,24 +204,26 @@ export class ProjectComponent {
private _reportsService: ReportsService, private _reportsService: ReportsService,
private htmlService: HtmlProjectReportService, private htmlService: HtmlProjectReportService,
private indexInfoService: IndexInfoService, private indexInfoService: IndexInfoService,
private cdr: ChangeDetectorRef) {} private metricsService: MetricsService,
private cdr: ChangeDetectorRef,
private layoutService: LayoutService) {}
ngOnInit() { ngOnInit() {
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.properties = properties; this.isMobile = isMobile;
if (typeof document !== 'undefined') { }));
this.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(lastIndexUpdate => { this.properties = properties;
if (lastIndexUpdate) { if (typeof document !== 'undefined') {
this.indexUpdateDate = new Date(lastIndexUpdate); 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.getDivContents();
this.seoService.createLinkForCanonicalURL(this.properties.domain +this.properties.baseLink + this._router.url); 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.subscriptions.push(this.route.queryParams.subscribe(params => {
this.stickyHeader = false; this.stickyHeader = false;
this.metricsClicked = false; this.metricsClicked = false;
@ -353,7 +380,8 @@ export class ProjectComponent {
this.subscriptions.forEach(subscription => { this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) { if (subscription instanceof Subscriber) {
subscription.unsubscribe(); subscription.unsubscribe();
} else if (subscription instanceof (ResizeObserver || IntersectionObserver)) { } else if ((typeof ResizeObserver != 'undefined' && subscription instanceof ResizeObserver) ||
(typeof IntersectionObserver != 'undefined' && subscription instanceof IntersectionObserver)) {
subscription.disconnect(); subscription.disconnect();
} }
}); });
@ -510,6 +538,23 @@ export class ProjectComponent {
startDate: this.projectInfo.startDate, startDate: this.projectInfo.startDate,
endDate: this.projectInfo.endDate 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 //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'; // 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) { public metricsResults($event) {
this.totalViews = $event.totalViews; this.totalViews = $event.totalViews;
this.totalDownloads = $event.totalDownloads; 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 { 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() { 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() { public openOrganizationsModal() {
this.organizationsModal.cancelButton = false; this.organizationsModal.cancelButton = false;
this.organizationsModal.okButton = 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() { public openDescriptionModal() {
this.descriptionModal.alertFooter = false; this.descriptionModal.alertFooter = false;
this.descriptionModal.alertTitle = "Description"; this.descriptionModal.alertTitle = "Description";
this.descriptionModal.open(); 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) { public addEoscPrevInParams(obj) {
if(properties.adminToolsPortalType == "eosc" && this.prevPath) { if(properties.adminToolsPortalType == "eosc" && this.prevPath) {
let splitted: string[] = this.prevPath.split("?"); let splitted: string[] = this.prevPath.split("?");

View File

@ -3,7 +3,7 @@ import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {RouterModule} from '@angular/router'; import {RouterModule} from '@angular/router';
import { MatSelectModule } from "@angular/material/select"; import {MatSelectModule} from "@angular/material/select";
import {ProjectComponent} from './project.component'; import {ProjectComponent} from './project.component';
import {ProjectServiceModule} from './projectService.module'; import {ProjectServiceModule} from './projectService.module';
@ -31,7 +31,11 @@ import {LoadingModule} from "../../utils/loading/loading.module";
import {IconsModule} from "../../utils/icons/icons.module"; import {IconsModule} from "../../utils/icons/icons.module";
import {InputModule} from "../../sharedComponents/input/input.module"; import {InputModule} from "../../sharedComponents/input/input.module";
import {IconsService} from "../../utils/icons/icons.service"; 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({ @NgModule({
imports: [ imports: [
@ -41,7 +45,8 @@ import {graph, link} from "../../utils/icons/icons";
SearchResearchResultsServiceModule, ProjectServiceModule, SearchResearchResultsServiceModule, ProjectServiceModule,
Schema2jsonldModule, SEOServiceModule, HelperModule, Schema2jsonldModule, SEOServiceModule, HelperModule,
LandingHeaderModule, MatSelectModule, FeedbackModule, AltMetricsModule, LandingHeaderModule, MatSelectModule, FeedbackModule, AltMetricsModule,
TabsModule, SearchTabModule, LoadingModule, IconsModule, InputModule TabsModule, SearchTabModule, LoadingModule, IconsModule, InputModule,
FullScreenModalModule, SafeHtmlPipeModule, EGIDataTransferModule, EntityActionsModule
], ],
declarations: [ declarations: [
ProjectComponent ProjectComponent
@ -55,6 +60,6 @@ import {graph, link} from "../../utils/icons/icons";
}) })
export class ProjectModule { export class ProjectModule {
constructor(private iconsService: IconsService) { 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)"; this.projectInfo.urlInfo = "Detailed project information (CORDIS)";
} }
if (data[0]?.measure) {
this.projectInfo.measure = this.parsingFunctions.parseMeasures(data[0].measure);
}
return this.projectInfo; return this.projectInfo;
} }

View File

@ -24,10 +24,11 @@ import {HelperFunctions} from "../../../utils/HelperFunctions.class";
[page]="page" [pageSize]="pageSize" [page]="page" [pageSize]="pageSize"
[totalResults]="results.length"> [totalResults]="results.length">
</no-load-paging> </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)"> <li *ngFor="let result of results.slice((page-1)*pageSize, page*pageSize)">
<result-preview [modal]="modal" [properties]="properties" [hasLink]="false" [result]="getResultPreview(result)" <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> </li>
</ul> </ul>
<no-load-paging *ngIf="results.length > pageSize" [type]="type" <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 {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser'; 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 {Identifier, StringUtils} from "../../utils/string-utils.class";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {ISVocabulariesService} from "../../utils/staticAutoComplete/ISVocabularies.service"; import {ISVocabulariesService} from "../../utils/staticAutoComplete/ISVocabularies.service";
import {forkJoin, Observable, Subscription, zip} from "rxjs"; import {Subscription} from "rxjs";
import {AnnotationComponent} from "../annotation/annotation.component";
import {ParsingFunctions} from "../landing-utils/parsingFunctions.class"; import {ParsingFunctions} from "../landing-utils/parsingFunctions.class";
import {ConnectHelper} from "../../connect/connectHelper"; import {ConnectHelper} from "../../connect/connectHelper";
import {UserManagementService} from "../../services/user-management.service"; import {UserManagementService} from "../../services/user-management.service";
import {OpenaireEntities} from "../../utils/properties/searchFields"; import {OpenaireEntities} from "../../utils/properties/searchFields";
import {Option} from "../../sharedComponents/input/input.component"; 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; declare var ResizeObserver;
@ -42,8 +45,11 @@ export class ResultLandingComponent {
enermapsId; enermapsId;
// @ViewChild('linkModal') linkModal; // @ViewChild('linkModal') linkModal;
@ViewChild('citeModal') citeModal; @ViewChild('citeModal') citeModal;
@ViewChild('citeFsModal') citeFsModal;
@ViewChild('addThisModal') addThisModal; @ViewChild('addThisModal') addThisModal;
@ViewChild('addThisFsModal') addThisFsModal;
@ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference; @ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference;
@ViewChild('AlertModalDeletedByInferenceFS') alertModalDeletedByInferenceFS;
// @ViewChild('relationModal') relationModal; // @ViewChild('relationModal') relationModal;
public deleteByInferenceOpened: boolean = false; public deleteByInferenceOpened: boolean = false;
@Input() public resultFromInput: boolean = false; @Input() public resultFromInput: boolean = false;
@ -72,9 +78,14 @@ export class ResultLandingComponent {
public hasAltMetrics: boolean = false; public hasAltMetrics: boolean = false;
public viewsFrameUrl: string; public viewsFrameUrl: string;
public downloadsFrameUrl: string; public downloadsFrameUrl: string;
/** @deprecated*/
public totalViews: number = null; public totalViews: number = null;
/** @deprecated*/
public totalDownloads: number = null; public totalDownloads: number = null;
public hasViews: boolean = false;
public hasDownloads: boolean = false;
public pageViews: number = null; public pageViews: number = null;
public bipFrameUrl: string;
// Custom tab paging variables // Custom tab paging variables
public referencesPage: number = 1; public referencesPage: number = 1;
@ -114,7 +125,7 @@ export class ResultLandingComponent {
'Title', 'Authors', 'Access rights', 'Title', 'Authors', 'Access rights',
'Publisher information', 'Funding Information', 'Publisher information', 'Funding Information',
'Persistent identifiers', 'Sustainable Development Goals (SDGs)', 'Persistent identifiers', 'Sustainable Development Goals (SDGs)',
'Fields of Science and Technology (FOS)', 'Other']; 'Fields of Science (FoS)', 'Other'];
public pidsArrayString: string = ""; public pidsArrayString: string = "";
public identifier: Identifier; public identifier: Identifier;
@ -142,7 +153,26 @@ export class ResultLandingComponent {
// public shouldSticky: boolean = true; // public shouldSticky: boolean = true;
public mobileContent: "info" | "metrics" | "actions" = "info";
public tabMobile: string = "";
public viewAllMobile: string = "";
public viewAll: 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 noCommunities: boolean = false;
public rightSidebarOffcanvasClicked: boolean = false; public rightSidebarOffcanvasClicked: boolean = false;
@ -161,10 +191,14 @@ export class ResultLandingComponent {
private cdr: ChangeDetectorRef, private cdr: ChangeDetectorRef,
private _location: Location, private _location: Location,
private indexInfoService: IndexInfoService, private indexInfoService: IndexInfoService,
private userManagementService: UserManagementService) { private userManagementService: UserManagementService,
private layoutService: LayoutService) {
} }
ngOnInit() { ngOnInit() {
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
}));
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
this.isLoggedIn = !!user; this.isLoggedIn = !!user;
}, error => { this.isLoggedIn = false} )); }, error => { this.isLoggedIn = false} ));
@ -347,7 +381,8 @@ export class ResultLandingComponent {
subscription.unsubscribe(); subscription.unsubscribe();
} else if (subscription instanceof Function) { } else if (subscription instanceof Function) {
subscription(); subscription();
} else if (subscription instanceof (ResizeObserver || IntersectionObserver)) { } else if ((typeof ResizeObserver != 'undefined' && subscription instanceof ResizeObserver) ||
(typeof IntersectionObserver != 'undefined' && subscription instanceof IntersectionObserver)) {
subscription.disconnect(); 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.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=' + 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":""}}}'); 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); let pid:Identifier = Identifier.getPIDFromIdentifiers(this.resultLandingInfo.identifiers);
if (this.type == "result") { // no type was specified - update URL based this.resultLandingInfo.resultType if (this.type == "result") { // no type was specified - update URL based this.resultLandingInfo.resultType
this.updateUrlWithType(pid); this.updateUrlWithType(pid);
@ -515,7 +551,7 @@ export class ResultLandingComponent {
this.enermapsId = ParsingFunctions.getEnermapsConceptId(this.resultLandingInfo.contexts); this.enermapsId = ParsingFunctions.getEnermapsConceptId(this.resultLandingInfo.contexts);
} }
this.relatedClassFilters = [{"label": "All relations", "value": ""}];
if(this.resultLandingInfo.relatedClassFilters.size > 1) { if(this.resultLandingInfo.relatedClassFilters.size > 1) {
for (let relClass of this.resultLandingInfo.relatedClassFilters) { for (let relClass of this.resultLandingInfo.relatedClassFilters) {
this.relatedClassFilters.push({"label": HelperFunctions.getVocabularyLabel(relClass, this.relationsVocabulary), "value": relClass}); this.relatedClassFilters.push({"label": HelperFunctions.getVocabularyLabel(relClass, this.relationsVocabulary), "value": relClass});
@ -526,6 +562,19 @@ export class ResultLandingComponent {
this.relatedClassSelected = ""; this.relatedClassSelected = "";
this.filteredRelatedResults = this.resultLandingInfo.relatedResults; 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.showLoading = false;
this.setActiveTab(); this.setActiveTab();
@ -555,14 +604,12 @@ export class ResultLandingComponent {
public get hasPrimaryInfo(): boolean { public get hasPrimaryInfo(): boolean {
return !!this.resultLandingInfo && ( return !!this.resultLandingInfo && (
(!!this.resultLandingInfo.description && this.resultLandingInfo.description.length > 0) (!!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)); || (!!this.resultLandingInfo.organizations && this.resultLandingInfo.organizations.length > 0));
} }
public get hasRightSidebarInfo(): boolean { public get hasRightSidebarInfo(): boolean {
return (this.resultLandingInfo.eoscSubjects && this.resultLandingInfo.eoscSubjects.length 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) (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.fundedByProjects && this.resultLandingInfo.fundedByProjects.length > 0)
|| ||
(this.resultLandingInfo.contexts && this.resultLandingInfo.contexts.length > 0 && !this.noCommunities) (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 { 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() { public openOrganizationsModal() {
this.organizationsModal.cancelButton = false; this.organizationsModal.cancelButton = false;
this.organizationsModal.okButton = false; this.organizationsModal.okButton = false;
@ -917,12 +992,145 @@ export class ResultLandingComponent {
this.viewAll = ""; 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() { public openDescriptionModal() {
this.descriptionModal.alertFooter = false; this.descriptionModal.alertFooter = false;
this.descriptionModal.alertTitle = "Abstract"; this.descriptionModal.alertTitle = "Abstract";
this.descriptionModal.open(); 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() { public getEoscParams() {
let params = ""; let params = "";
if(this.prevPath) { if(this.prevPath) {
@ -953,5 +1161,4 @@ export class ResultLandingComponent {
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

@ -1,26 +1,26 @@
import {NgModule} from '@angular/core'; import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {RouterModule} from '@angular/router'; import {RouterModule} from '@angular/router';
import {SharedModule} from '../../../openaireLibrary/shared/shared.module'; import {SharedModule} from '../../../openaireLibrary/shared/shared.module';
import {MetricsModule} from '../landing-utils/metrics/metrics.module'; import {MetricsModule} from '../landing-utils/metrics/metrics.module';
import {LandingModule} from '../landing-utils/landing.module'; import {LandingModule} from '../landing-utils/landing.module';
import {CiteThisModule} from '../landing-utils/citeThis/citeThis.module'; import {CiteThisModule} from '../landing-utils/citeThis/citeThis.module';
import {IFrameModule} from '../../utils/iframe.module'; import {IFrameModule} from '../../utils/iframe.module';
import {AltMetricsModule} from '../../utils/altmetrics.module'; import {AltMetricsModule} from '../../utils/altmetrics.module';
import {PagingModule} from '../../utils/paging.module'; import {PagingModule} from '../../utils/paging.module';
import {ResultLandingService} from './resultLanding.service'; import {ResultLandingService} from './resultLanding.service';
import {ResultLandingComponent} from './resultLanding.component'; import {ResultLandingComponent} from './resultLanding.component';
import {Schema2jsonldModule} from '../../sharedComponents/schema2jsonld/schema2jsonld.module'; import {Schema2jsonldModule} from '../../sharedComponents/schema2jsonld/schema2jsonld.module';
import { SEOServiceModule } from '../../sharedComponents/SEO/SEOService.module'; import {SEOServiceModule} from '../../sharedComponents/SEO/SEOService.module';
import {DeletedByInferenceModule} from './deletedByInference/deletedByInference.module'; import {DeletedByInferenceModule} from './deletedByInference/deletedByInference.module';
import {ShowAuthorsModule} from "../../utils/authors/showAuthors.module"; import {ShowAuthorsModule} from "../../utils/authors/showAuthors.module";
import {HelperModule} from "../../utils/helper/helper.module"; import {HelperModule} from "../../utils/helper/helper.module";
import {ResultLandingUtilsModule} from "../landing-utils/resultLandingUtils.module"; import {ResultLandingUtilsModule} from "../landing-utils/resultLandingUtils.module";
import {AlertModalModule} from "../../utils/modal/alertModal.module"; import {AlertModalModule} from "../../utils/modal/alertModal.module";
import {AnnotationModule} from "../annotation/annotation.module"; import {AnnotationModule} from "../annotation/annotation.module";
import {LandingHeaderModule} from "../landing-utils/landing-header/landing-header.module"; import {LandingHeaderModule} from "../landing-utils/landing-header/landing-header.module";
import {NoLoadPaging} from "../../searchPages/searchUtils/no-load-paging.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 {MatSelectModule} from "@angular/material/select";
import {IconsModule} from "../../utils/icons/icons.module"; import {IconsModule} from "../../utils/icons/icons.module";
import {IconsService} from "../../utils/icons/icons.service"; import {IconsService} from "../../utils/icons/icons.service";
import {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 {InputModule} from "../../sharedComponents/input/input.module";
import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.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({ @NgModule({
imports: [ imports: [
@ -44,7 +49,8 @@ import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.modul
MetricsModule, AltMetricsModule, Schema2jsonldModule, SEOServiceModule, MetricsModule, AltMetricsModule, Schema2jsonldModule, SEOServiceModule,
DeletedByInferenceModule, ShowAuthorsModule, HelperModule, ResultLandingUtilsModule, AlertModalModule, DeletedByInferenceModule, ShowAuthorsModule, HelperModule, ResultLandingUtilsModule, AlertModalModule,
AnnotationModule, LandingHeaderModule, NoLoadPaging, ResultPreviewModule, FeedbackModule, TabsModule, LoadingModule, 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: [ declarations: [
ResultLandingComponent ResultLandingComponent
@ -58,6 +64,6 @@ import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.modul
}) })
export class ResultLandingModule { export class ResultLandingModule {
constructor(private iconsService: IconsService) { 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() @Injectable()
export class ResultLandingService { export class ResultLandingService {
constructor(private http: HttpClient ) { constructor(private http: HttpClient) {
this.parsingFunctions = new ParsingFunctions(); this.parsingFunctions = new ParsingFunctions();
} }
@ -39,7 +39,7 @@ export class ResultLandingService {
} else if (identifier) { } else if (identifier) {
// pid = "10.3389/fphys.2014.00466"; // pid = "10.3389/fphys.2014.00466";
let url = properties.searchAPIURLLAst + "resources2"; 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') { if (type === 'publication') {
url += 'publications'; url += 'publications';
} else if (type === 'dataset') { } else if (type === 'dataset') {
@ -56,50 +56,50 @@ export class ResultLandingService {
} }
} }
getResultLandingInfo (id: string, identifier: Identifier, type: string, getResultLandingInfo(id: string, identifier: Identifier, type: string,
subjectsVocabulary: any, subjectsVocabulary: any,
properties: EnvProperties): any { properties: EnvProperties): any {
let url: string = this.buildResultLandingInfoUrl(id, identifier, type); let url: string = this.buildResultLandingInfoUrl(id, identifier, type);
let finalUrl: string = (properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url; let finalUrl: string = (properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url;
return this.http.get(finalUrl) return this.http.get(finalUrl)
.pipe(map(res => { .pipe(map(res => {
if(!id && identifier) { if (!id && identifier) {
if(!res['results'] || res['results'].length == 0) { if (!res['results'] || res['results'].length == 0) {
throw new HttpErrorResponse({ throw new HttpErrorResponse({
status: 404, status: 404,
statusText: "Not found", statusText: "Not found",
url: finalUrl, url: finalUrl,
error: "Http failure response for "+finalUrl+": 404 Not Found" error: "Http failure response for " + finalUrl + ": 404 Not Found"
}); });
}
return res['results'][0];
} else {
return res;
} }
return res['results'][0]; }))
} else { .pipe(map(res => [res['result']['header']['dri:status'], res['result']['metadata']['oaf:entity'], res]))
return res; .pipe(map(res => [
} res[1]['oaf:result'], // 0
})) res[1]['oaf:result']['title'], // 1
.pipe(map(res => [res['result']['header']['dri:status'], res['result']['metadata']['oaf:entity'], res])) res[1]['oaf:result']['rels']['rel'], // 2
.pipe(map(res => [ res[1]['oaf:result']['children'], // 3
res[1]['oaf:result'], // 0 res[1]['oaf:result']['pid'], // 4
res[1]['oaf:result']['title'], // 1 res[1]['oaf:result']['journal'], // 5
res[1]['oaf:result']['rels']['rel'], // 2 res[1]['oaf:result']['language'], // 6
res[1]['oaf:result']['children'], // 3 res[1]['oaf:result']['eoscifguidelines'], // 7
res[1]['oaf:result']['pid'], // 4 res[1]['oaf:result']['subject'], // 8
res[1]['oaf:result']['journal'], // 5 res[1]['oaf:result']['context'], // 9
res[1]['oaf:result']['language'], // 6 res[1]['oaf:result']['creator'], // 10
res[1]['oaf:result']['eoscifguidelines'], // 7 res[1]['oaf:result']['country'], // 11
res[1]['oaf:result']['subject'], // 8 res[1]['oaf:result']['programmingLanguage'], // 12 - software
res[1]['oaf:result']['context'], // 9 //res[1]['oaf:result']['resulttype'],
res[1]['oaf:result']['creator'], // 10 (res[1]['extraInfo'] !== undefined && res[1]['extraInfo']['references'] !== undefined)
res[1]['oaf:result']['country'] , // 11 ? res[1]['extraInfo']['references']['reference'] : null, // 13
res[1]['oaf:result']['programmingLanguage'], // 12 - software res[0], // 14
//res[1]['oaf:result']['resulttype'], res[2], // 15
(res[1]['extraInfo'] !== undefined && res[1]['extraInfo']['references'] !== undefined) ]))
? res[1]['extraInfo']['references']['reference'] : null, // 13 .pipe(map(res => this.parseResultLandingInfo(res, subjectsVocabulary, properties)));
res[0], // 14
res[2], // 15
]))
.pipe(map(res => this.parseResultLandingInfo(res, subjectsVocabulary, properties)));
} }
// getProvenanceActionVocabulary (properties: EnvProperties): any { // getProvenanceActionVocabulary (properties: EnvProperties): any {
@ -118,16 +118,15 @@ export class ResultLandingService {
// return provenanceActionVocabulary; // 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 // in a real world app, we may send the error to some remote logging infrastructure
// instead of just logging it to the console // instead of just logging it to the console
console.log(error); 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(); this.resultLandingInfo = new ResultLandingInfo();
// res // res
this.resultLandingInfo.record = data[15]; this.resultLandingInfo.record = data[15];
this.resultLandingInfo.objIdentifier = data[15]["result"]["header"]["dri:objIdentifier"]; this.resultLandingInfo.objIdentifier = data[15]["result"]["header"]["dri:objIdentifier"];
@ -137,25 +136,25 @@ export class ResultLandingService {
// res['result']['metadata']['oaf:entity']['oaf:result'] // res['result']['metadata']['oaf:entity']['oaf:result']
if (data[0] != null) { if (data[0] != null) {
let date: string = (data[0].dateofacceptance ? data[0].dateofacceptance : '') + ''; // transform to string in case it is an integer 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.date = (date && (date).indexOf('-') !== -1) ? date.split('-')[0] : date;
this.resultLandingInfo.dateofacceptance = data[0].dateofacceptance?Dates.getDate(data[0].dateofacceptance):null; this.resultLandingInfo.dateofacceptance = data[0].dateofacceptance ? Dates.getDate(data[0].dateofacceptance) : null;
this.resultLandingInfo.publisher = data[0].publisher; this.resultLandingInfo.publisher = data[0].publisher;
this.resultLandingInfo.description = this.parsingFunctions.parseDescription(data[0] && data[0].description?data[0].description:[]); 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.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; this.resultLandingInfo.accessMode = data[0]['bestaccessright'].classname;
} }
// res['result']['metadata']['oaf:entity']['oaf:result']['title'] // res['result']['metadata']['oaf:entity']['oaf:result']['title']
if(data[1] != null) { if (data[1] != null) {
if(Array.isArray(data[1])) { if (Array.isArray(data[1])) {
for(let i=0; i<data[1].length; i++) { for (let i = 0; i < data[1].length; i++) {
if(data[1][i] && data[1][i].content) { if (data[1][i] && data[1][i].content) {
if(!this.resultLandingInfo.title || data[1][i].classid == "main title") { if (!this.resultLandingInfo.title || data[1][i].classid == "main title") {
this.resultLandingInfo.title = StringUtils.HTMLToString(String(data[1][i].content)); 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)); this.resultLandingInfo.subtitle = StringUtils.HTMLToString(String(data[1][i].content));
} }
// if(data[1][i].classid == "main title") { // 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 = ""; this.resultLandingInfo.subtitle = "";
} }
if(!this.resultLandingInfo.title) { if (!this.resultLandingInfo.title) {
this.resultLandingInfo.title = ""; this.resultLandingInfo.title = "";
} }
// this.resultLandingInfo.title = (data[1][0] && data[1][0].content) ? String(data[1][0].content) : ""; // 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'] // res['result']['metadata']['oaf:entity']['oaf:result']['rels']['rel']
if(data[2] != null) { if (data[2] != null) {
let relation; let relation;
let length = Array.isArray(data[2]) ? data[2].length : 1; 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]; relation = Array.isArray(data[2]) ? data[2][i] : data[2];
if(relation.hasOwnProperty("to")) { if (relation.hasOwnProperty("to")) {
if(relation['to'].class && relation['to'].class.toLowerCase() == "isproducedby") { if (relation['to'].class && relation['to'].class.toLowerCase() == "isproducedby") {
this.resultLandingInfo.fundedByProjects = this.parsingFunctions.parseFundingByProjects(this.resultLandingInfo.fundedByProjects, relation); 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; let relationName: string = relation.to.class;
if(!this.resultLandingInfo.relatedClassFilters.has(relationName)) { if (!this.resultLandingInfo.relatedClassFilters.has(relationName)) {
this.resultLandingInfo.relatedClassFilters.add(relationName); this.resultLandingInfo.relatedClassFilters.add(relationName);
} }
let provenanceAction: string = relation.provenanceaction; let provenanceAction: string = relation.provenanceaction;
this.resultLandingInfo.relatedResults = this.parsingFunctions.parseResults(this.resultLandingInfo.relatedResults, relation, provenanceAction, relationName); 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); this.resultLandingInfo.organizations = this.parseRelatedOrganizations(this.resultLandingInfo.organizations, relation);
} }
} }
@ -203,19 +202,19 @@ export class ResultLandingService {
} }
// res['result']['metadata']['oaf:entity']['oaf:result']['children'] // res['result']['metadata']['oaf:entity']['oaf:result']['children']
if(data[3] != null) { if (data[3] != null) {
if(data[3].hasOwnProperty("result")) { if (data[3].hasOwnProperty("result")) {
this.resultLandingInfo.deletedByInferenceIds = []; this.resultLandingInfo.deletedByInferenceIds = [];
let length = Array.isArray(data[3]['result']) ? data[3]['result'].length : 1; 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']; let result = Array.isArray(data[3]['result']) ? data[3]['result'][i] : data[3]['result'];
this.resultLandingInfo.deletedByInferenceIds.push(result.objidentifier); this.resultLandingInfo.deletedByInferenceIds.push(result.objidentifier);
} }
} }
if(data[3].hasOwnProperty("instance")) { if (data[3].hasOwnProperty("instance")) {
this.resultLandingInfo.hostedBy_collectedFrom = new Array<HostedByCollectedFrom>(); 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; 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']; instance = Array.isArray(data[3]['instance']) ? data[3]['instance'][i] : data[3]['instance'];
this.parsingFunctions.parseTypes(this.resultLandingInfo.types, types, instance); this.parsingFunctions.parseTypes(this.resultLandingInfo.types, types, instance);
if(instance.hasOwnProperty("webresource")) { if (instance.hasOwnProperty("webresource")) {
let url; let url;
if(!Array.isArray(instance['webresource'])) { if (!Array.isArray(instance['webresource'])) {
url = instance['webresource'].url; url = instance['webresource'].url;
} else { } else {
url = instance['webresource'][0].url; url = instance['webresource'][0].url;
} }
if(url.includes('&amp;')) { if (url.includes('&amp;')) {
let regExp = /&amp;/gmu; url = url.replace(/&amp;/gmu, '&');
let newUrl = url.replace(regExp, '&');
url = newUrl;
} }
/**********************************************************/ /**********************************************************/
if(instance.hasOwnProperty("hostedby")) { if (instance.hasOwnProperty("hostedby")) {
this.parsingFunctions.parseHostedBy_collectedFrom(this.resultLandingInfo.hostedBy_collectedFrom, instance, url, this.resultLandingInfo.accessMode); 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*/ /* Order Download from via openness*/
this.resultLandingInfo.hostedBy_collectedFrom.sort((a, b) => { this.resultLandingInfo.hostedBy_collectedFrom.sort(this.parsingFunctions.compareHostedByCollectedFrom);
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;
});
} }
if(data[3].hasOwnProperty("externalreference")) { if (data[3].hasOwnProperty("externalreference")) {
let externalResults: Map<string, Map<string, string>> = this.parseBioentitiesAndSoftware(data[3]); let externalResults: Map<string, Map<string, string>> = this.parseBioentitiesAndSoftware(data[3]);
this.resultLandingInfo.bioentities = externalResults; this.resultLandingInfo.bioentities = externalResults;
} }
} }
// res['result']['metadata']['oaf:entity']['oaf:result']['pid'] // res['result']['metadata']['oaf:entity']['oaf:result']['pid']
if(data[4] != null) { if (data[4] != null) {
this.resultLandingInfo.identifiers = this.parsingFunctions.parseIdentifiers(data[4]); this.resultLandingInfo.identifiers = this.parsingFunctions.parseIdentifiers(data[4]);
} }
// res['result']['metadata']['oaf:entity']['oaf:result']['journal'] // res['result']['metadata']['oaf:entity']['oaf:result']['journal']
if(data[5] != null) { if (data[5] != null) {
this.resultLandingInfo.journal = {"journal": "", "issn": "", "lissn": "", "eissn": "", "issue": "", "volume": "", "start_page": "", "end_page": ""} this.resultLandingInfo.journal = {
"journal": "",
"issn": "",
"lissn": "",
"eissn": "",
"issue": "",
"volume": "",
"start_page": "",
"end_page": ""
}
this.resultLandingInfo.journal['journal'] = data[5].content; this.resultLandingInfo.journal['journal'] = data[5].content;
this.resultLandingInfo.journal['issn'] = data[5].issn; this.resultLandingInfo.journal['issn'] = data[5].issn;
@ -317,7 +289,7 @@ export class ResultLandingService {
} }
// res['result']['metadata']['oaf:entity']['oaf:result']['language'] // res['result']['metadata']['oaf:entity']['oaf:result']['language']
if(data[6] != null) { if (data[6] != null) {
this.resultLandingInfo.languages = this.parsingFunctions.parseLanguages(data[6]); this.resultLandingInfo.languages = this.parsingFunctions.parseLanguages(data[6]);
// let languagesAndCodes: string[][] = this.parsingFunctions.parseLanguages(data[6]); // let languagesAndCodes: string[][] = this.parsingFunctions.parseLanguages(data[6]);
// this.resultLandingInfo.languages = languagesAndCodes[0]; // this.resultLandingInfo.languages = languagesAndCodes[0];
@ -325,27 +297,31 @@ export class ResultLandingService {
} }
// res['result']['metadata']['oaf:entity']['oaf:result']['country'] // res['result']['metadata']['oaf:entity']['oaf:result']['country']
if(data[11] != null) { if (data[11] != null) {
this.resultLandingInfo.countries = this.parsingFunctions.parseCountries(data[11]); this.resultLandingInfo.countries = this.parsingFunctions.parseCountries(data[11]);
} }
// res['result']['metadata']['oaf:entity']['oaf:result']['eoscifguidelines'] // res['result']['metadata']['oaf:entity']['oaf:result']['eoscifguidelines']
if(data[7] != null) { if (data[7] != null) {
this.resultLandingInfo.eoscSubjects = this.parsingFunctions.parseEoscSubjects(data[7]); this.resultLandingInfo.eoscSubjects = this.parsingFunctions.parseEoscSubjects(data[7]);
} }
// res['result']['metadata']['oaf:entity']['oaf:result']['subject'] // 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); let subjectResults: [string[], Map<string, string[]>, Map<string, string[]>, string[], string[]] = this.parsingFunctions.parseAllSubjects(data[8], subjectsVocabulary);
this.resultLandingInfo.subjects = subjectResults[0]; this.resultLandingInfo.subjects = subjectResults[0];
this.resultLandingInfo.otherSubjects = subjectResults[1]; this.resultLandingInfo.otherSubjects = subjectResults[1];
this.resultLandingInfo.classifiedSubjects = subjectResults[2]; this.resultLandingInfo.classifiedSubjects = subjectResults[2];
this.resultLandingInfo.fos = subjectResults[3]; if (subjectResults[3]) {
if(this.resultLandingInfo.fos) { subjectResults[3].forEach(element => {
this.resultLandingInfo.fos.sort((a, b) => a.localeCompare(b)) 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]; this.resultLandingInfo.sdg = subjectResults[4];
if(this.resultLandingInfo.sdg) { if (this.resultLandingInfo.sdg) {
this.resultLandingInfo.sdg.sort((a, b) => { this.resultLandingInfo.sdg.sort((a, b) => {
return HelperFunctions.sortSDGs(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.parsingFunctions.addPublisherToHostedBy_collectedFrom(
this.resultLandingInfo.hostedBy_collectedFrom, this.resultLandingInfo.publisher, this.resultLandingInfo.hostedBy_collectedFrom, this.resultLandingInfo.publisher,
this.resultLandingInfo.journal, this.resultLandingInfo.identifiers); this.resultLandingInfo.journal?.journal, this.resultLandingInfo.identifiers);
// res['result']['metadata']['oaf:entity']['oaf:result']['programmingLanguage'] // res['result']['metadata']['oaf:entity']['oaf:result']['programmingLanguage']
if(data[12] != null) { if (data[12] != null) {
this.resultLandingInfo.programmingLanguages = this.parsingFunctions.parseProgrammingLanguages(data[12]); this.resultLandingInfo.programmingLanguages = this.parsingFunctions.parseProgrammingLanguages(data[12]);
} }
// res['result']['metadata']['oaf:entity']['extraInfo']['references']['reference'] // res['result']['metadata']['oaf:entity']['extraInfo']['references']['reference']
if(data[13] != null) { if (data[13] != null) {
this.resultLandingInfo.references = this.parsingFunctions.parseReferences(data[13]); this.resultLandingInfo.references = this.parsingFunctions.parseReferences(data[13]);
} }
// res['result']['metadata']['oaf:entity']['oaf:result']['context'] // res['result']['metadata']['oaf:entity']['oaf:result']['context']
if(data[9] != null) { if (data[9] != null) {
this.resultLandingInfo.contexts = this.parsingFunctions.parseContexts(data[9]); this.resultLandingInfo.contexts = this.parsingFunctions.parseContexts(data[9]);
} }
// res['result']['header']['dri:status'] // 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; this.resultLandingInfo.underCurationMessage = true;
} else { } else {
this.resultLandingInfo.underCurationMessage = false; this.resultLandingInfo.underCurationMessage = false;
} }
// res['result']['metadata']['oaf:entity']['oaf:result']['creator'] // res['result']['metadata']['oaf:entity']['oaf:result']['creator']
if(data[10] != null) { if (data[10] != null) {
if(this.resultLandingInfo.authors == undefined) { if (this.resultLandingInfo.authors == undefined) {
this.resultLandingInfo.authors = new Array<{"fullName": string, "orcid": string, "orcid_pending": string}>(); this.resultLandingInfo.authors = new Array<{ "fullName": string, "orcid": string, "orcid_pending": string }>();
} }
let authors = data[10]; let authors = data[10];
let length = Array.isArray(authors) ? authors.length : 1; 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; let author = Array.isArray(authors) ? authors[i] : authors;
if(author) { if (author) {
if(author.orcid) { if (author.orcid) {
author.orcid = author.orcid.toUpperCase(); author.orcid = author.orcid.toUpperCase();
} }
if(author.orcid_pending) { if (author.orcid_pending) {
author.orcid_pending = author.orcid_pending.toUpperCase(); 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) { 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); this.resultLandingInfo.relatedResults = this.parsingFunctions.sortByPercentage(this.resultLandingInfo.relatedResults);
return this.resultLandingInfo; return this.resultLandingInfo;
} }
parseRelatedOrganizations(organizations: Organization[], relation: any): Organization[] { parseRelatedOrganizations(organizations: Organization[], relation: any): Organization[] {
if(organizations == undefined) { if (organizations == undefined) {
organizations = [] organizations = []
} }
let organization: { "name": string, "shortname": string, let organization: {
"name": string, "shortname": string,
"id": string, "websiteUrl": string, "id": string, "websiteUrl": string,
"country": string, "trust": number "country": string, "trust": number
} = { } = {
@ -431,34 +417,34 @@ export class ResultLandingService {
organization.name = relation.legalname; organization.name = relation.legalname;
organization.shortname = relation.legalshortname; organization.shortname = relation.legalshortname;
organization.websiteUrl = relation.websiteurl; organization.websiteUrl = relation.websiteurl;
if(relation.country) { if (relation.country) {
organization.country = relation.country.classname; organization.country = relation.country.classname;
} }
if(relation.trust) { if (relation.trust) {
organization.trust = Math.round(relation.trust*100); organization.trust = Math.round(relation.trust * 100);
} }
organizations.push(organization); organizations.push(organization);
return organizations; 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 bioentities: Map<string, Map<string, string>>;
let length = Array.isArray(children['externalreference']) ? children['externalreference'].length : 1; let length = Array.isArray(children['externalreference']) ? children['externalreference'].length : 1;
let externalreference; 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']; externalreference = Array.isArray(children['externalreference']) ? children['externalreference'][i] : children['externalreference'];
if(externalreference.hasOwnProperty("qualifier")) { if (externalreference.hasOwnProperty("qualifier")) {
if(externalreference['qualifier'].classid == "accessionNumber") { if (externalreference['qualifier'].classid == "accessionNumber") {
if(bioentities == undefined) { if (bioentities == undefined) {
bioentities = new Map<string, Map<string, string>>(); 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.set(externalreference.sitename, new Map<string, string>());
} }
bioentities.get(externalreference.sitename).set(externalreference.refidentifier, externalreference.url); bioentities.get(externalreference.sitename).set(externalreference.refidentifier, externalreference.url);
@ -471,10 +457,10 @@ export class ResultLandingService {
} }
getEnermapsDetails(id: string) { getEnermapsDetails(id: string) {
let url = properties.enermapsURL+"/api/db/metadata?shared_id=eq."+id; 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((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
// return this.http.get(url) // return this.http.get(url)
.pipe(map(res => this.parseEnermapsDetails(res))); .pipe(map(res => this.parseEnermapsDetails(res)));
} }
parseEnermapsDetails(response: any) { parseEnermapsDetails(response: any) {
@ -483,9 +469,9 @@ export class ResultLandingService {
let entries = []; let entries = [];
let keys = metadata ? Object.keys(metadata) : null; let keys = metadata ? Object.keys(metadata) : null;
for(let key of keys) { for (let key of keys) {
if(key != "shared_id" && key && metadata[key]) { if (key != "shared_id" && key && metadata[key]) {
entries.push([key+"", metadata[key]+""]); entries.push([key + "", metadata[key] + ""]);
} }
} }
return entries; return entries;

View File

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

View File

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

View File

@ -6,8 +6,44 @@ export class User {
fullname: string; fullname: string;
expirationDate: number; expirationDate: number;
role: string[]; 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 { export class Session {

View File

@ -12,6 +12,7 @@ export type IndicatorType = 'number' | 'chart';
export type IndicatorSize = 'small' | 'medium' | 'large'; export type IndicatorSize = 'small' | 'medium' | 'large';
export type IndicatorPathType = 'table' | 'bar' | 'column' | 'pie' | 'line' | 'other'; export type IndicatorPathType = 'table' | 'bar' | 'column' | 'pie' | 'line' | 'other';
export type SourceType = 'statistics' | 'search' |'stats-tool' | 'old' | 'image'; export type SourceType = 'statistics' | 'search' |'stats-tool' | 'old' | 'image';
export type Format = 'NUMBER' | 'PERCENTAGE';
export type Visibility = 'PUBLIC' | 'PRIVATE' | 'RESTRICTED'; export type Visibility = 'PUBLIC' | 'PRIVATE' | 'RESTRICTED';
export class Stakeholder { export class Stakeholder {
@ -21,6 +22,8 @@ export class Stakeholder {
index_id; index_id;
index_name: string; index_name: string;
index_shortName: string; index_shortName: string;
statsProfile: string = "monitor";
locale: string = 'eu';
alias: string; alias: string;
defaultId: string; defaultId: string;
visibility: Visibility; visibility: Visibility;
@ -192,8 +195,9 @@ export class IndicatorPath {
parameters: any; parameters: any;
filters: any; filters: any;
filtersApplied: number = 0; 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.type = type;
this.url = url; this.url = url;
this.source = source; this.source = source;
@ -202,6 +206,7 @@ export class IndicatorPath {
this.parameters = {}; this.parameters = {};
this.filters = {}; this.filters = {};
this.filtersApplied = 0; this.filtersApplied = 0;
this.format = format;
} }
static createParameters(funderName: string = null, title: string = null, chartType: string = null): any { 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 type FilterType = "fundingL0"|"start_year" | "end_year" | "co-funded";
export class IndicatorFilterUtils{
export class IndicatorFilterUtils {
static getFilter(fieldPath: string, filterType:FilterType) { static getFilter(fieldPath: string, filterType:FilterType) {
if((filterType == "start_year" || filterType == "end_year") && (fieldPath.indexOf(".year") != -1 || fieldPath.indexOf(".start year") != -1) 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 => { this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) { if (subscription instanceof Subscription) {
subscription.unsubscribe(); 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) { 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 = [ let items = [
new MenuItem("methodology", "Methodology", "", "", false, [], new MenuItem("methodology", "Methodology", "", "", false, [],
null, {}, null, null, null, null, '_self'), null, {}, null, null, null, null, '_self'),
ResourcesService.setLink(new MenuItem("methodological-approach", "Methodological Approach", 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), prefix + "/methodology/methodological-approach", portal),
ResourcesService.setLink(new MenuItem("terminology", "Terminology and construction", 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)]; prefix + "/methodology/terminology", portal)];
items.push(new MenuItem("indicators-page", "Indicators", items.push(new MenuItem("indicators-page", "Indicators",
"", "", false, [], null, {})); "", "", false, [], null, {}));
items.push(ResourcesService.setLink(new MenuItem("indicator-themes", "Indicator Themes", 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 => { let promise = new Promise<void>(resolve => {
this.isPagesEnabled().subscribe(status => { this.isPagesEnabled().subscribe(status => {
ResourcesService.types.forEach((type, index) => { ResourcesService.types.forEach((type, index) => {
if (status[index]) { if (status[index]) {
items.push(ResourcesService.setLink( items.push(ResourcesService.setLink(
new MenuItem("indicators-" + type.value, type.label, 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) prefix + "/indicators/" + type.value, portal)
); );
} }
@ -61,13 +61,13 @@ export class ResourcesService {
return items; return items;
} }
setResources(items: MenuItem[], prefix = '', portal: string = null) { setResources(items: MenuItem[], prefix = '', portal: string = null, target = '_self') {
if (this.subscription) { if (this.subscription) {
this.subscription.unsubscribe(); this.subscription.unsubscribe();
} }
let resources = new MenuItem('resources', 'Resources', "", "", false, [], null, {}); let resources = new MenuItem('resources', 'Resources', "", "", false, [], null, {});
let index = items.push(resources) - 1; 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; 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 {Indicator, Section, Stakeholder, StakeholderInfo, Visibility} from "../entities/stakeholder";
import {HelperFunctions} from "../../utils/HelperFunctions.class"; import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {map} from "rxjs/operators"; import {map} from "rxjs/operators";
import {ActivatedRoute} from "@angular/router";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {CustomOptions} from "../../services/servicesUtils/customOptions.class"; import {CustomOptions} from "../../services/servicesUtils/customOptions.class";
import {StringUtils} from "../../utils/string-utils.class"; import {StringUtils} from "../../utils/string-utils.class";
let maps: string[] = ['parameters', 'filters'];
export interface Reorder { export interface Reorder {
action: 'moved' | 'added' | 'removed', action: 'moved' | 'added' | 'removed',
target: string, target: string,
@ -21,25 +18,25 @@ export interface Reorder {
providedIn: "root" providedIn: "root"
}) })
export class StakeholderService { export class StakeholderService {
private stakeholderSubject: BehaviorSubject<Stakeholder> = null; private stakeholderSubject: BehaviorSubject<Stakeholder> = null;
private promise: Promise<void>; private promise: Promise<void>;
private sub; private sub;
constructor(private http: HttpClient) { constructor(private http: HttpClient) {
this.stakeholderSubject = new BehaviorSubject<Stakeholder>(null); this.stakeholderSubject = new BehaviorSubject<Stakeholder>(null);
} }
ngOnDestroy() { ngOnDestroy() {
this.clearSubscriptions(); this.clearSubscriptions();
} }
clearSubscriptions() { clearSubscriptions() {
if (this.sub instanceof Subscriber) { if (this.sub instanceof Subscriber) {
this.sub.unsubscribe(); this.sub.unsubscribe();
} }
} }
getStakeholder(alias: string, shouldUpdate: boolean = false): Observable<Stakeholder> { getStakeholder(alias: string, shouldUpdate: boolean = false): Observable<Stakeholder> {
if (!this.stakeholderSubject.value || this.stakeholderSubject.value.alias !== alias || shouldUpdate) { if (!this.stakeholderSubject.value || this.stakeholderSubject.value.alias !== alias || shouldUpdate) {
this.promise = new Promise<void>((resolve, reject) => { this.promise = new Promise<void>((resolve, reject) => {
@ -56,78 +53,80 @@ export class StakeholderService {
} }
return from(this.getStakeholderAsync()); return from(this.getStakeholderAsync());
} }
async getStakeholderAsync() { async getStakeholderAsync() {
if(this.promise) { if (this.promise) {
await this.promise; await this.promise;
this.promise = null; this.promise = null;
} }
this.clearSubscriptions(); this.clearSubscriptions();
return this.stakeholderSubject.getValue(); return this.stakeholderSubject.getValue();
} }
getAlias(url: string): Observable<string[]> { getAlias(url: string): Observable<string[]> {
return this.http.get<Stakeholder[]>(url + '/stakeholder/alias', CustomOptions.registryOptions()).pipe(map(stakeholders => { return this.http.get<Stakeholder[]>(url + '/stakeholder/alias', CustomOptions.registryOptions()).pipe(map(stakeholders => {
return this.formalize(stakeholders); return this.formalize(stakeholders);
})); }));
} }
getStakeholders(url: string, type: string = null, defaultId: string = null): Observable<(Stakeholder & StakeholderInfo)[]> { 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)); return this.formalize(this.checkIsUpload(stakeholders));
})); }));
} }
getMyStakeholders(url: string, type: string = null): Observable<(Stakeholder & StakeholderInfo)[]> { 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.http.get<Stakeholder[]>(url + '/my-stakeholder' + ((type) ? ('?type=' + type) : ''), CustomOptions.registryOptions()).pipe(map(stakeholders => {
return this.formalize(this.checkIsUpload(stakeholders)); return this.formalize(this.checkIsUpload(stakeholders));
})); }));
} }
getDefaultStakeholders(url: string, type: string = null): Observable<Stakeholder[]> { 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.http.get<Stakeholder[]>(url + '/stakeholder/default' + ((type) ? ('?type=' + type) : ''), CustomOptions.registryOptions()).pipe(map(stakeholders => {
return this.formalize(this.checkIsUpload(stakeholders)); return this.formalize(this.checkIsUpload(stakeholders));
})); }));
} }
buildStakeholder(url: string, stakeholder: Stakeholder): Observable<Stakeholder> { buildStakeholder(url: string, stakeholder: Stakeholder): Observable<Stakeholder> {
if(stakeholder.alias && stakeholder.alias.startsWith('/')) { if (stakeholder.alias && stakeholder.alias.startsWith('/')) {
stakeholder.alias = stakeholder.alias.slice(1); stakeholder.alias = stakeholder.alias.slice(1);
} }
return this.http.post<Stakeholder>(url + '/build-stakeholder', stakeholder, CustomOptions.registryOptions()).pipe(map(stakeholder => { return this.http.post<Stakeholder>(url + '/build-stakeholder', stakeholder, CustomOptions.registryOptions()).pipe(map(stakeholder => {
return this.formalize(this.checkIsUpload(stakeholder)); return this.formalize(this.checkIsUpload(stakeholder));
})); }));
} }
changeVisibility(url: string, path: string[], visibility: Visibility, propagate: boolean = false): Observable<any> { 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> { saveElement(url: string, element: any, path: string[] = []): Observable<any> {
if(element.alias && element.alias.startsWith('/')) { if (element.alias && element.alias.startsWith('/')) {
element.alias = element.alias.slice(1); element.alias = element.alias.slice(1);
} }
path = HelperFunctions.encodeArray(path); path = HelperFunctions.encodeArray(path);
return this.http.post<any>(url + ((path.length > 0) ? '/' : '') + path.join('/') + return this.http.post<any>(url + ((path.length > 0) ? '/' : '') + path.join('/') +
'/save', element, CustomOptions.registryOptions()).pipe(map(element => { '/save', element, 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)); return this.formalize(this.checkIsUpload(element));
} else { } else {
return this.formalize(element); 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> { saveSection(url: string, element: any, path: string[] = [], index: number = -1): Observable<Section> {
path = HelperFunctions.encodeArray(path); path = HelperFunctions.encodeArray(path);
return this.http.post<Section>(url + ((path.length > 0) ? '/' : '') + path.join('/') + return this.http.post<Section>(url + ((path.length > 0) ? '/' : '') + path.join('/') +
@ -135,7 +134,7 @@ export class StakeholderService {
return this.formalize(element); return this.formalize(element);
})); }));
} }
deleteElement(url: string, path: string[], childrenAction: string = null): Observable<any> { deleteElement(url: string, path: string[], childrenAction: string = null): Observable<any> {
path = HelperFunctions.encodeArray(path); path = HelperFunctions.encodeArray(path);
let params: string = ""; let params: string = "";
@ -144,29 +143,29 @@ export class StakeholderService {
} }
return this.http.delete<any>(url + '/' + path.join('/') + '/delete' + params, CustomOptions.registryOptions()); return this.http.delete<any>(url + '/' + path.join('/') + '/delete' + params, CustomOptions.registryOptions());
} }
reorderElements(url: string, path: string[], ids: string[]): Observable<any> { reorderElements(url: string, path: string[], ids: string[]): Observable<any> {
path = HelperFunctions.encodeArray(path); path = HelperFunctions.encodeArray(path);
return this.http.post<any>(url + '/' + path.join('/') + '/reorder', ids, CustomOptions.registryOptions()); return this.http.post<any>(url + '/' + path.join('/') + '/reorder', ids, CustomOptions.registryOptions());
} }
reorderIndicators(url: string, path: string[], reorder: Reorder, type: string = 'chart'): Observable<Indicator[]> { reorderIndicators(url: string, path: string[], reorder: Reorder, type: string = 'chart'): Observable<Indicator[]> {
path = HelperFunctions.encodeArray(path); path = HelperFunctions.encodeArray(path);
return this.http.post<Indicator[]>(url + '/' + path.join('/') + '/' + type + '/reorder', reorder, CustomOptions.registryOptions()).pipe(map(indicators => { return this.http.post<Indicator[]>(url + '/' + path.join('/') + '/' + type + '/reorder', reorder, CustomOptions.registryOptions()).pipe(map(indicators => {
return this.formalize(indicators); return this.formalize(indicators);
})); }));
} }
getStakeholderAsObservable(): Observable<Stakeholder> { getStakeholderAsObservable(): Observable<Stakeholder> {
return this.stakeholderSubject.asObservable(); return this.stakeholderSubject.asObservable();
} }
setStakeholder(stakeholder: Stakeholder) { setStakeholder(stakeholder: Stakeholder) {
this.stakeholderSubject.next(stakeholder); this.stakeholderSubject.next(stakeholder);
} }
private checkIsUpload(response: Stakeholder | Stakeholder[]): any | any[] { private checkIsUpload(response: Stakeholder | Stakeholder[]): any | any[] {
if(Array.isArray(response)) { if (Array.isArray(response)) {
response.forEach(value => { response.forEach(value => {
value.isUpload = value.logoUrl && !StringUtils.isValidUrl(value.logoUrl); value.isUpload = value.logoUrl && !StringUtils.isValidUrl(value.logoUrl);
}); });
@ -175,7 +174,7 @@ export class StakeholderService {
} }
return response; return response;
} }
private formalize(element: any) { private formalize(element: any) {
return HelperFunctions.copy(element); 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 {EnvProperties} from "../utils/properties/env-properties";
import {UserManagementService} from "../services/user-management.service"; import {UserManagementService} from "../services/user-management.service";
import {OpenaireEntities} from "../utils/properties/searchFields"; import {OpenaireEntities} from "../utils/properties/searchFields";
import {FullScreenModalComponent} from "../utils/modal/full-screen-modal/full-screen-modal.component";
declare var UIkit: any; declare var UIkit: any;
@Component({ @Component({
selector: 'orcid-work', selector: 'orcid-work',
template: ` template: `
<ng-container *ngIf="pageType == 'search'"> <ng-container *ngIf="pageType == 'landing' || pageType == 'search'">
<span *ngIf="!putCodes || putCodes.length == 0" <span *ngIf="!putCodes || putCodes.length == 0"
[attr.uk-tooltip]="(!isLoggedIn) ? tooltipNoLoggedInUser : tooltipAdd" [attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'"
class="uk-margin-remove-bottom"> [title]="((!pids && (!identifiers || identifiers.size == 0)) || !isLoggedIn) ? ((!pids && (!identifiers || identifiers.size == 0)) ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipAdd">
<a (click)="currentAction='add'; saveWorkPreparation();"
<a (click)="currentAction='add'; saveWorkPreparation();" class="uk-flex uk-flex-middle uk-button-link"
[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' : '')"> [ngClass]="isMobile && !(pageType == 'landing') ? 'uk-margin-left' : 'uk-flex-center'"
<icon *ngIf="!showLoading" name="add" ratio="1" flex="true"></icon> [class.uk-text-bolder]="!(isMobile && pageType == 'landing')"
<span *ngIf="showLoading" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span> [class.uk-disabled]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
<span class="uk-margin-small-left uk-flex uk-flex-middle">Add to&#160; [class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
<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"
(mouseover)="hoverEvent($event)" (mouseout)="hoverEvent($event)"> (mouseover)="hoverEvent($event)" (mouseout)="hoverEvent($event)">
<icon *ngIf="!hoverAdd" name="orcid_add" ratio="1.1" visuallyHidden="add"></icon> <icon *ngIf="!showLoading" [class.text-orcid]="!showLoading && isLoggedIn && (pids || identifiers?.size > 0)"
<icon *ngIf="hoverAdd" name="add" visuallyHidden="add"></icon> [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> </a>
<span *ngIf="showLoading" class="uk-icon icon-button uk-icon-button-small"><loading
[top_margin]="false" [size]="'small'"></loading></span>
</span> </span>
<span *ngIf="putCodes && putCodes.length > 0" <span *ngIf="putCodes && putCodes.length > 0"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'" [attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'"
[title]="(!pids || !isLoggedIn) ? (!pids ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipDelete"> [title]="((!pids && (!identifiers || identifiers.size == 0)) || !isLoggedIn) ? ((!pids && (!identifiers || identifiers.size == 0)) ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipDelete">
<a *ngIf="!showLoading" (click)="currentAction='delete'; deleteWorks();" <a (click)="currentAction='delete'; deleteWorks();"
class="uk-icon-button uk-icon landing-action-button landing-action-button-orcid" class="uk-flex uk-flex-middle uk-button-link"
[class.uk-disabled]="showLoading || !isLoggedIn || !pids" [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')"> (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="orcid_bin" ratio="1.1" visuallyHidden="delete"></icon>
<icon *ngIf="hoverDelete" name="delete_outline" class="uk-text-danger" visuallyHidden="delete"></icon> <icon *ngIf="hoverDelete" name="delete_outline" class="uk-text-danger" visuallyHidden="delete"></icon>
</a> </a>
<span *ngIf="showLoading" class="uk-icon icon-button uk-icon-button-small"><loading <span *ngIf="showLoading" class="uk-icon icon-button uk-icon-button-small"><loading
[top_margin]="false" [size]="'small'"></loading></span> [top_margin]="false" [size]="'small'"></loading></span>
</span> </span> -->
</ng-container> </ng-container>
<modal-alert #grantModal [overflowBody]=false (alertOutput)="openGrantWindow()"> <modal-alert *ngIf="!isMobile" #grantModal [overflowBody]=false (alertOutput)="openGrantWindow()">
<div> <div>
<div>{{requestGrantMessage}}</div> <div>{{requestGrantMessage}}</div>
<!-- <div class="uk-margin-medium-top uk-align-right">--> <!-- <div class="uk-margin-medium-top uk-align-right">-->
<!-- <button (click)="closeGrantModal()" type="submit"--> <!-- <button (click)="closeGrantModal()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-button-default">--> <!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-button-default">-->
<!-- <span>Cancel</span>--> <!-- <span>Cancel</span>-->
<!-- </button>--> <!-- </button>-->
<!-- <button (click)="openGrantWindow()" type="submit"--> <!-- <button (click)="openGrantWindow()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left uk-button-primary">--> <!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left uk-button-primary">-->
<!-- <span>Grant OpenAIRE</span>--> <!-- <span>Grant OpenAIRE</span>-->
<!-- </button>--> <!-- </button>-->
<!--&lt;!&ndash; <button (click)="openGrantWindow()" type="submit"&ndash;&gt;--> <!--&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; 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; <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; <span>Create or Connect your ORCID iD</span>&ndash;&gt;-->
<!--&lt;!&ndash; </button>&ndash;&gt;--> <!--&lt;!&ndash; </button>&ndash;&gt;-->
<!-- </div>--> <!-- </div>-->
</div> </div>
</modal-alert> </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'"> <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"> <img src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="" loading="lazy">
<span>&#160;ACTIONS</span> <span>&#160;ACTIONS</span>
</span> </span>
<span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0) <span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0)
? 'This work is currently deleted.' ? 'This work is currently deleted.'
: 'View this work from your ORCID record'"> : 'View this work from your ORCID record'">
<a (click)="currentAction='get'; getOrcidWorks()" <a (click)="currentAction='get'; getOrcidWorks()"
[class]="'uk-button uk-button-default action uk-flex uk-flex-middle '+ ((showLoading || !putCodes || putCodes.length == 0) ? 'uk-disabled' : '')"> [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> <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> <span class="uk-margin-small-left">View ORCID work</span>
</a> </a>
</span> </span>
<span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0) <span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0)
? 'This work is currently deleted.' ? '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())"> + showUpdateDatesInTooltip())">
<a (click)="currentAction='update'; updateWorkPreparation()" <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' : '')"> [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> <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> <span class="uk-margin-small-left">Update ORCID work</span>
</a> </a>
</span> </span>
@ -143,8 +143,9 @@ declare var UIkit: any;
<a (click)="currentAction='add'; saveWorkPreparation();" <a (click)="currentAction='add'; saveWorkPreparation();"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ (showLoading ? 'uk-disabled' : '')"> [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> <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 *ngIf="showLoading && currentAction=='add'" class="uk-icon icon-button"><loading [top_margin]="false"
<span class="uk-margin-small-left">Add to ORCID</span> [size]="'small'"></loading></span>
<span class="uk-margin-small-left">Claim</span>
</a> </a>
</span> </span>
@ -153,8 +154,9 @@ declare var UIkit: any;
<a (click)="currentAction='delete'; deleteWorks();" <a (click)="currentAction='delete'; deleteWorks();"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ (showLoading ? 'uk-disabled' : '')"> [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> <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 *ngIf="showLoading && currentAction=='delete'" class="uk-icon icon-button"><loading [top_margin]="false"
<span class="uk-margin-small-left">Delete from ORCID</span> [size]="'small'"></loading></span>
<span class="uk-margin-small-left">Remove</span>
</a> </a>
</span> </span>
</ng-container> </ng-container>
@ -173,9 +175,9 @@ declare var UIkit: any;
<div class="uk-card uk-card-default uk-padding uk-card-hover"> <div class="uk-card uk-card-default uk-padding uk-card-hover">
<div>{{work.title?.title?.value}}</div> <div>{{work.title?.title?.value}}</div>
<div>{{work.title?.subtitle?.value}}</div> <div>{{work.title?.subtitle?.value}}</div>
<div class="uk-text-uppercase">{{work['journal-title']?.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"> <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']">
<span *ngIf="work['publication-date']['year'] && work['publication-date']['year'].value"> <span *ngIf="work['publication-date']['year'] && work['publication-date']['year'].value">
@ -209,11 +211,11 @@ declare var UIkit: any;
{{work['short-description']}} {{work['short-description']}}
</p> </p>
</div> </div>
<div *ngIf="work['external-ids'] && work['external-ids']['external-id']" class="uk-margin-small-bottom"> <div *ngIf="work['external-ids'] && work['external-ids']['external-id']" class="uk-margin-small-bottom">
<showIdentifiers [identifiers]="parseIdentifiers(work['external-ids']['external-id'])"></showIdentifiers> <showIdentifiers [identifiers]="parseIdentifiers(work['external-ids']['external-id'])"></showIdentifiers>
</div> </div>
<div *ngIf="work['contributors'] && work['contributors']['contributor']"> <div *ngIf="work['contributors'] && work['contributors']['contributor']">
<div *ngFor="let contributor of work['contributors']['contributor']"> <div *ngFor="let contributor of work['contributors']['contributor']">
<span *ngIf="contributor['credit-name'] && contributor['credit-name'].value"> <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-role'])
|| ||
(contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-sequence']) (contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-sequence'])
|| ||
(contributor['contributor-orcid'] && contributor['contributor-orcid']['path']) (contributor['contributor-orcid'] && contributor['contributor-orcid']['path'])
)"> )">
( (
</span> </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']}} {{contributor['contributor-attributes']['contributor-role']}}
</span> </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']))"> && (contributor['contributor-attributes']['contributor-sequence'] || (contributor['contributor-orcid'] && contributor['contributor-orcid']['path']))">
, ,
</span> </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']}} {{contributor['contributor-attributes']['contributor-sequence']}}
</span> </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']"> && contributor['contributor-orcid'] && contributor['contributor-orcid']['path']">
, ,
</span> </span>
<span *ngIf="contributor['contributor-orcid'] && contributor['contributor-orcid']['path']"> <span *ngIf="contributor['contributor-orcid'] && contributor['contributor-orcid']['path']">
{{contributor['contributor-orcid']?.path}} {{contributor['contributor-orcid']?.path}}
@ -261,33 +265,58 @@ declare var UIkit: any;
<modal-alert #propagationModal (alertOutput)="confirmedPropagation()"> <modal-alert #propagationModal (alertOutput)="confirmedPropagation()">
<div> <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> <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'"> <div *ngIf="currentAction == 'delete'">
If you continue with delete action, <span class="uk-text-bold">all these works will be deleted</span>. If you continue with delete action, <span class="uk-text-bold">all these works will be deleted</span>.
</div> </div>
<div *ngIf="currentAction == 'update'"> <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> </div>
<!-- <div class="uk-margin-medium-top uk-align-right">--> <!-- <div class="uk-margin-medium-top uk-align-right">-->
<!-- <button (click)="closePropagationModal()" type="submit"--> <!-- <button (click)="closePropagationModal()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-button-default">--> <!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-button-default">-->
<!-- <span>Cancel</span>--> <!-- <span>Cancel</span>-->
<!-- </button>--> <!-- </button>-->
<!-- <button (click)="confirmedPropagation()" type="submit"--> <!-- <button (click)="confirmedPropagation()" type="submit"-->
<!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left uk-button-primary">--> <!-- class="uk-button uk-padding-small uk-padding-remove-vertical uk-margin-left uk-button-primary">-->
<!-- <span>Continue</span>--> <!-- <span>Continue</span>-->
<!-- </button>--> <!-- </button>-->
<!-- </div>--> <!-- </div>-->
</modal-alert> </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 { export class OrcidWorkComponent {
@Input() isMobile: boolean = false;
@Input() resultId: string = ""; @Input() resultId: string = "";
@Input() resultTitle: string = ""; @Input() resultTitle: string = "";
@Input() resultLandingInfo: ResultLandingInfo; @Input() resultLandingInfo: ResultLandingInfo;
@ -299,54 +328,56 @@ export class OrcidWorkComponent {
@Input() updateDates: string[] = []; @Input() updateDates: string[] = [];
@Input() givenPutCode: boolean = false; @Input() givenPutCode: boolean = false;
@Input() pageType: string = "search"; @Input() pageType: string = "search";
public subscriptions: Subscription[] = []; public subscriptions: Subscription[] = [];
@ViewChild('workModal') workModal; @ViewChild('workModal') workModal;
// @ViewChild('saveWorkModal') saveWorkModal; // @ViewChild('saveWorkModal') saveWorkModal;
@ViewChild('grantModal') grantModal; @ViewChild('grantModal') grantModal;
@ViewChild('grantFsModal') grantFsModal: FullScreenModalComponent;
// @ViewChild('messageModal') messageModal; // @ViewChild('messageModal') messageModal;
@ViewChild('propagationModal') propagationModal; @ViewChild('propagationModal') propagationModal;
@ViewChild('propagationFsModal') propagationFsModal;
public requestGrant: boolean = false; public requestGrant: boolean = false;
public requestGrantMessage: string = "Please grant OpenAIRE to access and update your ORCID works."; public requestGrantMessage: string = "Please grant OpenAIRE to access and update your ORCID works.";
private tokenUrl: string; private tokenUrl: string;
public message: string = ""; public message: string = "";
public showLoading: boolean = false; public showLoading: boolean = false;
public works: any[] = []; public works: any[] = [];
public orcidWorks: any[] = []; public orcidWorks: any[] = [];
public window: any; public window: any;
public isLoggedIn: boolean = false; public isLoggedIn: boolean = false;
public currentAction: string = ""; public currentAction: string = "";
public hoverAdd: boolean = false; public hoverAdd: boolean = false;
public hoverDelete: boolean = false; public hoverDelete: boolean = false;
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public openaireEntities = OpenaireEntities; public openaireEntities = OpenaireEntities;
constructor(private route: ActivatedRoute, constructor(private route: ActivatedRoute,
private _router: Router, private _router: Router,
private orcidService: OrcidService, private orcidService: OrcidService,
private resultLandingService: ResultLandingService, private resultLandingService: ResultLandingService,
private userManagementService: UserManagementService) { private userManagementService: UserManagementService) {
if(typeof document !== 'undefined') { if (typeof document !== 'undefined') {
this.tokenUrl = properties.orcidTokenURL this.tokenUrl = properties.orcidTokenURL
+ "client_id="+properties.orcidClientId + "client_id=" + properties.orcidClientId
// + "&response_type=code&scope=/activities/update" // + "&response_type=code&scope=/activities/update"
// + "&response_type=code&scope=/authenticate /activities/update /person/update /read-limited" // + "&response_type=code&scope=/authenticate /activities/update /person/update /read-limited"
+ "&response_type=code&scope=/activities/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() { ngOnInit() {
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
if (user) { if (user) {
this.isLoggedIn = true; this.isLoggedIn = true;
if(!this.givenPutCode) { if (!this.givenPutCode) {
this.getPutCode(); this.getPutCode();
} }
} else { } else {
@ -356,7 +387,7 @@ export class OrcidWorkComponent {
this.isLoggedIn = false; this.isLoggedIn = false;
})); }));
} }
ngOnDestroy() { ngOnDestroy() {
this.subscriptions.forEach(subscription => { this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) { if (subscription instanceof Subscriber) {
@ -365,16 +396,16 @@ export class OrcidWorkComponent {
} }
}); });
} }
public showUpdateDatesInTooltip() { public showUpdateDatesInTooltip() {
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
let response: string = ""; 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>"; 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]); let date: Date = new Date(this.updateDates[i]);
response += "<span>"+date.getDate() + " " + monthNames[date.getMonth()] + " " + date.getFullYear(); response += "<span>" + date.getDate() + " " + monthNames[date.getMonth()] + " " + date.getFullYear();
if(i < this.updateDates.length - 1) { if (i < this.updateDates.length - 1) {
response += "& "; response += "& ";
} }
response += "</span>"; response += "</span>";
@ -382,29 +413,34 @@ export class OrcidWorkComponent {
} }
return response; return response;
} }
public parseIdentifiers(identifiers: ExternalIDV3_0[]): Map<string, string[]> { public parseIdentifiers(identifiers: ExternalIDV3_0[]): Map<string, string[]> {
let identifiersMap: Map<string, string[]> = new Map<string, string[]>(); let identifiersMap: Map<string, string[]> = new Map<string, string[]>();
for(let identifier of identifiers) { for (let identifier of identifiers) {
if(!identifiersMap.has(identifier['external-id-type'])) { if (!identifiersMap.has(identifier['external-id-type'])) {
identifiersMap.set(identifier['external-id-type'], new Array<string>()); identifiersMap.set(identifier['external-id-type'], new Array<string>());
} }
identifiersMap.get(identifier['external-id-type']).push(identifier['external-id-value']); identifiersMap.get(identifier['external-id-type']).push(identifier['external-id-value']);
} }
return identifiersMap; return identifiersMap;
} }
openGrantWindow() { openGrantWindow() {
if(!Session.isLoggedIn()){ if (!Session.isLoggedIn()) {
//this.userValidMessage = "User session has expired. Please login again."; //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 { } else {
// this.tokenUrl = location.origin+"/orcid"; // this.tokenUrl = location.origin+"/orcid";
this.window = window.open(this.tokenUrl, '_blank', this.window = window.open(this.tokenUrl, '_blank',
'location=yes,height=700,width=540,left=500,top=100,scrollbars=yes,status=yes'); 'location=yes,height=700,width=540,left=500,top=100,scrollbars=yes,status=yes');
// this.requestGrant = false; // this.requestGrant = false;
this.closeGrantModal(); this.closeGrantModal();
let self = this; let self = this;
window.onmessage = function (ev) { window.onmessage = function (ev) {
if (ev.isTrusted && ev.origin == location.origin && ev.data == 'success') { if (ev.isTrusted && ev.origin == location.origin && ev.data == 'success') {
@ -426,17 +462,17 @@ export class OrcidWorkComponent {
} }
} }
} }
private getPutCode() { private getPutCode() {
this.subscriptions.push(this.orcidService.getPutCode(this.pids).subscribe( this.subscriptions.push(this.orcidService.getPutCode(this.pids).subscribe(
putCodes => { putCodes => {
this.putCodes = putCodes; this.putCodes = putCodes;
}, error => { }, error => {
} }
)) ))
} }
private getResultLandingInfo(action: string) { private getResultLandingInfo(action: string) {
this.subscriptions.push(this.resultLandingService.getResultLandingInfo(this.resultId, null, this.type, null, properties).subscribe( this.subscriptions.push(this.resultLandingService.getResultLandingInfo(this.resultId, null, this.type, null, properties).subscribe(
resultLandingInfo => { resultLandingInfo => {
@ -448,7 +484,7 @@ export class OrcidWorkComponent {
} }
this.pids = pidsArray.join(); this.pids = pidsArray.join();
} }
if(action == "save") { if (action == "save") {
this.saveWork(); this.saveWork();
} else if (action == "update") { } else if (action == "update") {
this.updateWork(); this.updateWork();
@ -460,18 +496,23 @@ export class OrcidWorkComponent {
} }
)) ))
} }
public saveWorkPreparation() { public saveWorkPreparation() {
if(!Session.isLoggedIn()){ if (!Session.isLoggedIn()) {
//this.userValidMessage = "User session has expired. Please login again."; //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 { } else {
if (this.requestGrant) { if (this.requestGrant) {
this.openGrantModal("Add, delete or edit work in your ORCID record"); this.openGrantModal("Add, delete or edit work in your ORCID record");
} else { } else {
this.showLoading = true; this.showLoading = true;
if (this.resultLandingInfo) { if (this.resultLandingInfo) {
this.saveWork(); this.saveWork();
} else { } else {
@ -480,42 +521,42 @@ export class OrcidWorkComponent {
} }
} }
} }
private saveWork() { private saveWork() {
this.subscriptions.push(this.orcidService.saveWork(this.resultLandingInfo, this.pids).subscribe( this.subscriptions.push(this.orcidService.saveWork(this.resultLandingInfo, this.pids).subscribe(
response => { response => {
// for testing only // for testing only
// this.openGrantModal("Add work in your ORCID record"); // this.openGrantModal("Add work in your ORCID record");
// this.requestGrant = true; // this.requestGrant = true;
// this.requestGrantMessage = "Please grant OpenAIRE to access and update your ORCID record and works."; // this.requestGrantMessage = "Please grant OpenAIRE to access and update your ORCID record and works.";
if(response == null) { if (response == null) {
this.handleError(null); this.handleError(null);
console.error("Error posting landing info: null"); console.error("Error posting landing info: null");
} else { } else {
this.putCodes.push(""+response['put-code']); this.putCodes.push("" + response['put-code']);
this.creationDates.push(response['created-date']['value']); this.creationDates.push(response['created-date']['value']);
this.updateDates.push(response['last-modified-date']['value']); this.updateDates.push(response['last-modified-date']['value']);
// this.closeGrantModal(); // this.closeGrantModal();
// this.message = "You have successfully added work with pids: "+this.pids+" in your ORCID record!"; // 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"); // this.openMessageModal("Work added successfully");
// message: 'You have <strong>successfully added</strong> work with pids: <strong>'+this.pids+'</strong> in your ORCID record!', // message: 'You have <strong>successfully added</strong> work with pids: <strong>'+this.pids+'</strong> in your ORCID record!',
UIkit.notification({ UIkit.notification({
message: 'You have <strong>successfully added</strong> work "<strong>'+this.resultTitle+'</strong>" in your ORCID record!' 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" [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" (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" routerLinkActive="router-link-active" [routerLink]="myOrcidLinksPage">Manager your ORCID links</a>',
status: 'success', status: 'success',
timeout: 6000, timeout: 6000,
pos: 'bottom-right' pos: 'bottom-right'
}); });
this.showLoading = false; this.showLoading = false;
} }
}, },
@ -525,23 +566,28 @@ export class OrcidWorkComponent {
} }
)); ));
} }
goToOrcidLinksPage() { goToOrcidLinksPage() {
this._router.navigate([this.properties.myOrcidLinksPage]); this._router.navigate([this.properties.myOrcidLinksPage]);
} }
private updateWorkPreparation() { private updateWorkPreparation() {
if(!Session.isLoggedIn()){ if (!Session.isLoggedIn()) {
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 { } else {
if (this.requestGrant) { if (this.requestGrant) {
this.openGrantModal("Add, delete or edit work in your ORCID record"); 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"); this.openPropagationModal("Update ORCID work");
} else { } else {
this.showLoading = true; this.showLoading = true;
if (this.resultLandingInfo) { if (this.resultLandingInfo) {
this.updateWork(); this.updateWork();
} else { } else {
@ -550,18 +596,18 @@ export class OrcidWorkComponent {
} }
} }
} }
private updateWork() { private updateWork() {
this.subscriptions.push(this.orcidService.updateWork(this.resultLandingInfo, this.pids, this.putCodes[0]).subscribe( this.subscriptions.push(this.orcidService.updateWork(this.resultLandingInfo, this.pids, this.putCodes[0]).subscribe(
response => { response => {
if(response) { if (response) {
this.updateDates[0] = response['last-modified-date'].value; 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!', // message: 'You have <strong>successfully updated</strong> work with pids: <strong>' + this.pids + '</strong> in your ORCID record!',
UIkit.notification({ UIkit.notification({
message: 'You have <strong>successfully updated</strong> work "<strong>' + this.resultTitle + '</strong>" in your ORCID record!' 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', status: 'success',
timeout: 6000, timeout: 6000,
@ -576,36 +622,41 @@ export class OrcidWorkComponent {
} }
)); ));
} }
public confirmedPropagation() { public confirmedPropagation() {
this.propagationModal.cancel(); this.propagationModal.cancel();
this.deleteWorks(true); this.deleteWorks(true);
//} //}
// if(this.currentAction == "update") { // if(this.currentAction == "update") {
// this.saveWork(); // this.saveWork();
// } // }
} }
public getOrcidWorks() { public getOrcidWorks() {
if(!Session.isLoggedIn()){ if (!Session.isLoggedIn()) {
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 { } else {
this.showLoading = true; this.showLoading = true;
this.subscriptions.push(this.orcidService.getOrcidWorks(this.putCodes).subscribe( this.subscriptions.push(this.orcidService.getOrcidWorks(this.putCodes).subscribe(
(response) => { (response) => {
let error: boolean = true; let error: boolean = true;
if(response && response['bulk']) { if (response && response['bulk']) {
response = response['bulk'].filter(res => { response = response['bulk'].filter(res => {
return (!res.error && res.work); return (!res.error && res.work);
}); });
if(response && response.length > 0) { if (response && response.length > 0) {
error = false; error = false;
this.orcidWorks = response; this.orcidWorks = response;
this.openWorkModal(); this.openWorkModal();
} }
} }
if(error) { if (error) {
UIkit.notification({ UIkit.notification({
message: 'There was an error getting this work. </br> Please make sure you have not deleted it from your ORCID iD.', message: 'There was an error getting this work. </br> Please make sure you have not deleted it from your ORCID iD.',
status: 'warning', status: 'warning',
@ -622,20 +673,25 @@ export class OrcidWorkComponent {
)); ));
} }
} }
public deleteWorks(confirmed: boolean = false) { public deleteWorks(confirmed: boolean = false) {
if(!Session.isLoggedIn()){ if (!Session.isLoggedIn()) {
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 { } else {
if (this.requestGrant) { if (this.requestGrant) {
this.openGrantModal("Add, delete or edit work in your ORCID record"); 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"); this.openPropagationModal("Delete ORCID work");
} else { } else {
this.showLoading = true; this.showLoading = true;
if (!this.resultLandingInfo && this.identifiers) { if (!this.resultLandingInfo && this.identifiers) {
let pidsArray: string[] = []; let pidsArray: string[] = [];
for (let key of Array.from(this.identifiers.keys())) { for (let key of Array.from(this.identifiers.keys())) {
@ -643,11 +699,11 @@ export class OrcidWorkComponent {
} }
this.pids = pidsArray.join(); this.pids = pidsArray.join();
} }
this.subscriptions.push(this.orcidService.deleteWorks(this.putCodes).subscribe( this.subscriptions.push(this.orcidService.deleteWorks(this.putCodes).subscribe(
deletedPutCodes => { deletedPutCodes => {
let deletedAll: boolean = true; let deletedAll: boolean = true;
if (deletedPutCodes) { if (deletedPutCodes) {
for (let i = 0; i < deletedPutCodes.length; i++) { for (let i = 0; i < deletedPutCodes.length; i++) {
let deletedPutCode = deletedPutCodes[i]; let deletedPutCode = deletedPutCodes[i];
@ -663,24 +719,24 @@ export class OrcidWorkComponent {
} else { } else {
deletedAll = false; deletedAll = false;
} }
if (!deletedAll) { if (!deletedAll) {
this.handleError(null); this.handleError(null);
console.error("Error deleting landing info: null"); console.error("Error deleting landing info: null");
} else { } else {
if(this.currentAction == "update") { if (this.currentAction == "update") {
this.saveWork(); this.saveWork();
} else { } else {
// this.closeGrantModal(); // this.closeGrantModal();
// this.message = "You have successfully deleted work with pids: " + this.pids + " from your ORCID record!"; // 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.message = "You have successfully deleted work \"" + this.resultTitle + "\" from your ORCID record!";
// this.openMessageModal("Work deleted successfully"); // this.openMessageModal("Work deleted successfully");
// message: 'You have <strong>successfully deleted</strong> work with pids: <strong>' + this.pids + '</strong> from your ORCID record!', // message: 'You have <strong>successfully deleted</strong> work with pids: <strong>' + this.pids + '</strong> from your ORCID record!',
UIkit.notification({ UIkit.notification({
message: 'You have <strong>successfully deleted</strong> work "<strong>' + this.resultTitle + '</strong>" from your ORCID record!' 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', status: 'success',
timeout: 6000, timeout: 6000,
@ -698,31 +754,37 @@ export class OrcidWorkComponent {
} }
} }
} }
openGrantModal(title: string) { openGrantModal(title: string) {
this.grantModal.cancelButton = true; if(this.isMobile) {
this.grantModal.okButton = true; this.grantFsModal.okButton = false;
this.grantModal.okButtonText = "Grant OpenAIRE"; this.grantFsModal.title = title;
this.grantModal.okButtonLeft = false; this.grantFsModal.open();
this.grantModal.alertTitle = title; } else {
this.grantModal.open(); 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() { closeGrantModal() {
this.grantModal.cancel(); this.grantModal.cancel();
} }
openWorkModal() { openWorkModal() {
this.workModal.cancelButton = false; this.workModal.cancelButton = false;
this.workModal.okButton = false; this.workModal.okButton = false;
this.workModal.alertTitle = "Work in your ORCID record"; this.workModal.alertTitle = "Work in your ORCID record";
this.workModal.open(); this.workModal.open();
} }
closeWorkModal() { closeWorkModal() {
this.workModal.cancel(); this.workModal.cancel();
} }
// openMessageModal(title: string) { // openMessageModal(title: string) {
// this.messageModal.cancelButton = false; // this.messageModal.cancelButton = false;
// this.messageModal.okButton = false; // this.messageModal.okButton = false;
@ -733,52 +795,58 @@ export class OrcidWorkComponent {
// closeMessageModal() { // closeMessageModal() {
// this.messageModal.cancel(); // this.messageModal.cancel();
// } // }
openPropagationModal(title: string) { openPropagationModal(title: string) {
this.propagationModal.cancelButton = true; if(this.isMobile) {
this.propagationModal.okButton = true; this.propagationFsModal.okButton = false;
this.propagationModal.okButtonText = "Continue"; this.propagationFsModal.title = title;
this.propagationModal.okButtonLeft = false; this.propagationFsModal.open();
this.propagationModal.alertTitle = title; } else {
this.propagationModal.open(); this.propagationModal.cancelButton = true;
this.propagationModal.okButton = true;
this.propagationModal.okButtonText = "Continue";
this.propagationModal.okButtonLeft = false;
this.propagationModal.alertTitle = title;
this.propagationModal.open();
}
} }
closePropagationModal() { closePropagationModal() {
this.propagationModal.cancel(); this.propagationModal.cancel();
} }
handleError(error) { handleError(error) {
if(error && error.status == "401") { if (error && error.status == "401") {
this.openGrantModal("Add, delete or edit work in your ORCID record"); this.openGrantModal("Add, delete or edit work in your ORCID record");
this.requestGrant = true; this.requestGrant = true;
this.requestGrantMessage = "Please grant OpenAIRE to access and update your ORCID record and works. "; 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!"; // + "If you have already granted OpenAIRE, you just need to login again to ORCID!";
} else if(error && error.status == "403") { } else if (error && error.status == "403") {
this.openGrantModal("Add, delete or edit work in your ORCID record"); this.openGrantModal("Add, delete or edit work in your ORCID record");
this.requestGrant = true; this.requestGrant = true;
this.requestGrantMessage = "Please login again to ORCID." this.requestGrantMessage = "Please login again to ORCID."
// this.openGrantModal(); // this.openGrantModal();
} else { } else {
this.message = ""; 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>"; 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 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."; 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.";
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") { } 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 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."; 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") { } 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 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 { } else {
this.message += "There was an error. Please try again later." this.message += "There was an error. Please try again later."
} }
UIkit.notification({ UIkit.notification({
message: this.message, message: this.message,
status: 'danger', status: 'danger',
@ -789,28 +857,28 @@ export class OrcidWorkComponent {
} }
this.showLoading = false; this.showLoading = false;
} }
get tooltipAdd() { 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." : ""); 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() { 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." : ""); 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() { 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"; 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() { 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") { hoverEvent($event, action: string = "add") {
if(action == "add") { if (action == "add") {
this.hoverAdd = $event.type == "mouseover"; this.hoverAdd = $event.type == "mouseover";
this.hoverDelete = false; this.hoverDelete = false;
} else if(action == "delete") { } else if (action == "delete") {
this.hoverDelete = $event.type == "mouseover"; this.hoverDelete = $event.type == "mouseover";
this.hoverAdd = false; this.hoverAdd = false;
} }

View File

@ -15,11 +15,12 @@ import {ResultLandingUtilsModule} from '../landingPages/landing-utils/resultLand
import {IconsModule} from '../utils/icons/icons.module'; import {IconsModule} from '../utils/icons/icons.module';
import {IconsService} from "../utils/icons/icons.service"; import {IconsService} from "../utils/icons/icons.service";
import {orcid_add, orcid_bin} from "../utils/icons/icons"; import {orcid_add, orcid_bin} from "../utils/icons/icons";
import {FullScreenModalModule} from "../utils/modal/full-screen-modal/full-screen-modal.module";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, RouterModule, AlertModalModule, LoadingModule, ResultLandingUtilsModule, CommonModule, RouterModule, AlertModalModule, LoadingModule, ResultLandingUtilsModule,
IconsModule IconsModule, FullScreenModalModule
], ],
declarations: [ declarations: [
OrcidComponent, OrcidComponent,

View File

@ -3,7 +3,7 @@
@sdgs: #E6233D, #DF9F00, #19A220, #D70023, #FF0B00, #00BFE8, #FFC300, #B10240, #FF5D00, @sdgs: #E6233D, #DF9F00, #19A220, #D70023, #FF0B00, #00BFE8, #FFC300, #B10240, #FF5D00,
#F50D86, #FF8A00, #CA8A03, #2B772B, #0098DF, #00B91C, #0069A2, #1C336A; #F50D86, #FF8A00, #CA8A03, #2B772B, #0098DF, #00B91C, #0069A2, #1C336A;
custom-sdg-dot:after { .custom-sdg-dot:after {
content: ""; content: "";
background-image: url("~src/assets/common-assets/sdg/sdg-dot-img.svg"); background-image: url("~src/assets/common-assets/sdg/sdg-dot-img.svg");
display: inline-block; 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-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> <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" <advanced-search-form class="uk-width-expand uk-padding-remove-vertical"
entityType="all" [entityType]="activeEntity"
[advancedSearchLink]="advancedSearchLink" [advancedSearchLinkParameters]="parameters"
(queryChange)="keywordChanged($event)" (queryChange)="keywordChanged($event)"
[isDisabled]="disableForms" [isDisabled]="disableForms"
[simpleView]="true" [formPlaceholderText]="formPlaceholderText" [simpleView]="true" [formPlaceholderText]="formPlaceholderText"
[selectedFields]="selectedFields" [showSwitchSearchLink]="true" [dark]="searchForm.dark" [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> </advanced-search-form>
</div> </div>
@ -26,9 +27,10 @@
</div> </div>
<schema2jsonld *ngIf="name && logoURL" [URL]="properties.domain+ properties.baseLink +'/search/find'" <schema2jsonld *ngIf="name && logoURL" [URL]="properties.domain+ properties.baseLink +'/search/find'"
[logoURL]="properties.domain + properties.baseLink+logoURL" type="search" [name]=name [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> 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-large-top uk-margin-medium-bottom"> <div class="uk-container-large uk-container uk-margin-top">
<div class="uk-width-1-1" uk-slider="finite: true"> <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-position-relative">
<div class="uk-slider-container"> <div class="uk-slider-container">
<ul class="uk-slider-items uk-flex uk-flex-center" style="flex-wrap: nowrap !important;"> <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'"> <li [class.uk-active]="activeEntity == 'result'">
<a class="uk-text-uppercase"> <a class="uk-text-uppercase">
{{resultsName}} {{resultsName}}
<span *ngIf=" fetchPublications.searchUtils.totalResults!=null"> <span *ngIf=" fetchPublications.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchPublications.searchUtils.totalResults | number}})</span> ({{fetchPublications.searchUtils.totalResults | number}})</span>
</a> </a>
</li> </li>
@ -48,7 +50,7 @@
<li [class.uk-active]="activeEntity == 'projects'"> <li [class.uk-active]="activeEntity == 'projects'">
<a class="uk-text-uppercase"> <a class="uk-text-uppercase">
{{projectName}} {{projectName}}
<span *ngIf="fetchProjects.searchUtils.totalResults!=null"> <span *ngIf="fetchProjects.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchProjects.searchUtils.totalResults | number}})</span> ({{fetchProjects.searchUtils.totalResults | number}})</span>
</a> </a>
</li> </li>
@ -59,7 +61,7 @@
<li [class.uk-active]="activeEntity == 'datasources'"> <li [class.uk-active]="activeEntity == 'datasources'">
<a class="uk-text-uppercase"> <a class="uk-text-uppercase">
{{dataSourcesName}} {{dataSourcesName}}
<span *ngIf="fetchDataproviders.searchUtils.totalResults!=null"> <span *ngIf="fetchDataproviders.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchDataproviders.searchUtils.totalResults | number}})</span> ({{fetchDataproviders.searchUtils.totalResults | number}})</span>
</a> </a>
</li> </li>
@ -70,7 +72,7 @@
<li [class.uk-active]="activeEntity == 'services'"> <li [class.uk-active]="activeEntity == 'services'">
<a class="uk-text-uppercase"> <a class="uk-text-uppercase">
{{servicesName}} {{servicesName}}
<span *ngIf="fetchServices.searchUtils.totalResults!=null"> <span *ngIf="fetchServices.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchServices.searchUtils.totalResults | number}})</span> ({{fetchServices.searchUtils.totalResults | number}})</span>
</a> </a>
</li> </li>
@ -81,7 +83,7 @@
<li [class.uk-active]="activeEntity == 'organizations'"> <li [class.uk-active]="activeEntity == 'organizations'">
<a class="uk-text-uppercase"> <a class="uk-text-uppercase">
{{organizationsName}} {{organizationsName}}
<span *ngIf="fetchOrganizations.searchUtils.totalResults!=null"> <span *ngIf="fetchOrganizations.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchOrganizations.searchUtils.totalResults | number}})</span> ({{fetchOrganizations.searchUtils.totalResults | number}})</span>
</a> </a>
</li> </li>
@ -99,25 +101,25 @@
<search-research-results *ngIf="activeEntity == 'result'" resultType="result" [includeOnlyResultsAndFilter]="true" <search-research-results *ngIf="activeEntity == 'result'" resultType="result" [includeOnlyResultsAndFilter]="true"
(searchPageUpdates)="activeEntityUpdate($event)" [showSwitchSearchLink]="false" (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" <search-projects *ngIf="activeEntity == 'projects'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false"
(searchPageUpdates)="activeEntityUpdate($event)" (searchPageUpdates)="activeEntityUpdate($event)"
simpleSearchLink="/search/find" [customFilter]="customFilter"> [simpleSearchLink]="properties.searchLinkToProjects" [customFilter]="customFilter">
</search-projects> </search-projects>
<search-organizations *ngIf="activeEntity == 'organizations'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false" <search-organizations *ngIf="activeEntity == 'organizations'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false"
(searchPageUpdates)="activeEntityUpdate($event)" (searchPageUpdates)="activeEntityUpdate($event)"
simpleSearchLink="/search/find" [customFilter]="customFilter"> [simpleSearchLink]="properties.searchLinkToOrganizations" [customFilter]="customFilter">
</search-organizations> </search-organizations>
<search-dataproviders *ngIf="activeEntity == 'datasources'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false" <search-dataproviders *ngIf="activeEntity == 'datasources'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false"
(searchPageUpdates)="activeEntityUpdate($event)" (searchPageUpdates)="activeEntityUpdate($event)"
simpleSearchLink="/search/find" [customFilter]="customFilter"> [simpleSearchLink]="properties.searchLinkToDataProviders" [customFilter]="customFilter">
</search-dataproviders> </search-dataproviders>
<search-dataproviders *ngIf="activeEntity == 'services'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false" <search-dataproviders *ngIf="activeEntity == 'services'" [includeOnlyResultsAndFilter]="true" [showSwitchSearchLink]="false"
(searchPageUpdates)="activeEntityUpdate($event)" (searchPageUpdates)="activeEntityUpdate($event)"
simpleSearchLink="/search/find" [customFilter]="customFilter" [simpleSearchLink]="properties.searchLinkToServices" [customFilter]="customFilter"
type="services" entityType="service" [typeName]="openaireEntities.SERVICES"> type="services" entityType="service" [typeName]="openaireEntities.SERVICES">
</search-dataproviders> </search-dataproviders>

View File

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

View File

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

View File

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

View File

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

View File

@ -132,7 +132,7 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
public pageOptions: number[] = [5, 10, 20, 50]; public pageOptions: number[] = [5, 10, 20, 50];
@Input() basicMetaDescription = []; @Input() basicMetaDescription = [];
@Input() entitiesSelection: boolean = true; @Input() entitiesSelection: boolean = false;
@Input() showSwitchSearchLink: boolean = true; @Input() showSwitchSearchLink: boolean = true;
// on 1st load, do not show filters until results query returns. // 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; showOffCanvas:boolean = false;
isMobile: boolean = false; isMobile: boolean = false;
isServer: boolean; isServer: boolean;
searchTerm: string = null;
advancedSearchTerms: number = 0;
constructor(private route: ActivatedRoute, constructor(private route: ActivatedRoute,
private location: Location, private location: Location,
@ -428,7 +430,9 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
var dependentTo = this.searchFieldsHelper.DEPENDENT_FIELDS[this.refineFields[i]]; 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 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]); fields.push(this.refineFields[i]);
} }
} }
@ -1689,6 +1693,14 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
this.getRangeFiltersFromURL(params); this.getRangeFiltersFromURL(params);
this.getRefineFiltersFromURL(params); this.getRefineFiltersFromURL(params);
this.createAdvancedSearchSelectedFiltersFromURLParameters(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) { removeResultType(type) {
@ -1708,4 +1720,12 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
} }
return totalPages; 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({ @Component({
selector: 'quick-selections', selector: 'quick-selections',
template: ` template: `
<div *ngIf="quickFilter" class="uk-margin-bottom"> <div *ngIf="!vertical && (resultTypes || quickFilter)">
<mat-slide-toggle name="qf" [(ngModel)]="quickFilter.selected" (ngModelChange)="quickFilterChanged()"> <div *ngIf="quickFilter" class="uk-margin-bottom">
<span class="uk-text-bold">{{quickFilter.value}}</span> <mat-slide-toggle name="qf" [(ngModel)]="quickFilter.selected" (ngModelChange)="quickFilterChanged()">
</mat-slide-toggle> <span class="uk-text-bold">{{quickFilter.value}}</span>
</div> </mat-slide-toggle>
<div class="uk-flex uk-flex-middle uk-text-small uk-text-nowrap"> </div>
<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-flex uk-flex-middle uk-text-small uk-text-nowrap">
<div class="uk-width-expand"> <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-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> <div class="uk-width-expand">
<ng-container *ngFor="let value of resultTypes.values"> <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>
<div> <ng-container *ngFor="let value of resultTypes.values">
<input #input type="checkbox" class="uk-checkbox" [(ngModel)]="value.selected" (ngModelChange)="changed()"/> <div>
<label class="uk-margin-small-left" (click)="input.click()">{{value.name}}</label> <input #input type="checkbox" class="uk-checkbox" [(ngModel)]="value.selected" (ngModelChange)="changed()"/>
</div> <label class="uk-margin-small-left" (click)="input.click()">{{value.name}}</label>
</ng-container> </div>
</ng-container>
</div>
</div> </div>
</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 { export class QuickSelectionsComponent {
@Input() vertical: boolean=false;
@Input() resultTypes:Filter; @Input() resultTypes:Filter;
@Output() typeChange = new EventEmitter(); @Output() typeChange = new EventEmitter();
@Input() isDisabled; @Input() isDisabled;

View File

@ -19,7 +19,7 @@
<div class="uk-margin-small-left"> <div class="uk-margin-small-left">
<div class="uk-text-meta">Top 100 values are shown in the filters</div> <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 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" <div *ngIf="showResultCount === true" input type="select" class="uk-width-expand" placeholder="Sort by"
inputClass="border-bottom" [(value)]="sortBy" [options]="sortByOptions" (valueChange)="sort()"></div> inputClass="border-bottom" [(value)]="sortBy" [options]="sortByOptions" (valueChange)="sort()"></div>
</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"> <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"> <ng-container *ngFor="let value of this.sortedValues">
<div *ngIf="filterKeywords(value.name)" title="{{value.name}}" <div *ngIf="filterKeywords(value.name)" title="{{value.name}}"
class="uk-animation-fade uk-text-small"> class="uk-animation-fade uk-text-small">
<ng-container <ng-container *ngTemplateOutlet="input_label_wrapper; context: {filter: filter, value: value}"></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> </div>
</ng-container> </ng-container>
</div> </div>

View File

@ -5,7 +5,8 @@ import {
EventEmitter, EventEmitter,
OnInit, OnInit,
OnChanges, OnChanges,
SimpleChanges SimpleChanges,
ChangeDetectorRef
} from '@angular/core'; } from '@angular/core';
import {Filter, Value} from './searchHelperClasses.class'; import {Filter, Value} from './searchHelperClasses.class';
import {ActivatedRoute, Router} from "@angular/router"; import {ActivatedRoute, Router} from "@angular/router";
@ -42,7 +43,11 @@ export class SearchFilterComponent implements OnInit, OnChanges {
sub; sub;
public isOpen: boolean = false; public isOpen: boolean = false;
sortedValues; sortedValues;
constructor(private _router: Router, private route: ActivatedRoute) { hasMatch: boolean = false;
constructor(private _router: Router,
private route: ActivatedRoute,
private cdr: ChangeDetectorRef) {
} }
ngOnDestroy() { ngOnDestroy() {
@ -115,6 +120,10 @@ export class SearchFilterComponent implements OnInit, OnChanges {
return false; return false;
} }
} }
if(!this.hasMatch) {
this.hasMatch = true;
this.cdr.detectChanges();
}
return true; return true;
} }
@ -246,9 +255,13 @@ export class SearchFilterComponent implements OnInit, OnChanges {
return 0; return 0;
} }
}); });
} }
this.sortedValues = Object.assign(sorted); this.sortedValues = Object.assign(sorted);
}
initMatching() {
this.hasMatch = false;
this.cdr.detectChanges();
} }
toggle(event) { toggle(event) {
@ -324,4 +337,4 @@ export class SearchFilterComponent implements OnInit, OnChanges {
return Object.entries(obj); 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> <errorMessages [status]="[status]" [type]="'results'"></errorMessages>
<li *ngFor="let result of previewResults"> <li *ngFor="let result of previewResults">
<result-preview [properties]="properties" [showOrganizations]="showOrganizations" <result-preview [properties]="properties" [showOrganizations]="showOrganizations"
[showSubjects]="showSubjects" [result]="result" [showEnermaps]="showEnermaps" [showSubjects]="showSubjects" [result]="result" [showEnermaps]="showEnermaps"
[isCard]="true" [prevPath]="prevPath"> [isCard]="true" [isMobile]="isMobile" [prevPath]="prevPath">
</result-preview> </result-preview>
</li> </li>
</ul> </ul>

View File

@ -2,19 +2,20 @@ import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'
import {SearchResult} from '../../utils/entities/searchResult'; import {SearchResult} from '../../utils/entities/searchResult';
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
import {ResultPreview} from "../../utils/result-preview/result-preview"; import {ResultPreview} from "../../utils/result-preview/result-preview";
import {HttpClient} from "@angular/common/http";
import {OrcidService} from "../../orcid/orcid.service"; import {OrcidService} from "../../orcid/orcid.service";
import {Session} from "../../login/utils/helper.class"; import {Session} from "../../login/utils/helper.class";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {Subscription} from "rxjs";
@Component({ @Component({
selector: 'search-result', selector: 'search-result',
templateUrl: 'searchResult.component.html' templateUrl: 'searchResult.component.html'
}) })
export class SearchResultComponent implements OnInit, OnChanges { export class SearchResultComponent implements OnInit, OnChanges {
@Input() prevPath: string = ""; @Input() prevPath: string = "";
@Input() results: SearchResult[]; @Input() results: SearchResult[];
previewResults:ResultPreview[]; previewResults: ResultPreview[];
@Input() status: number; @Input() status: number;
@Input() type: string; @Input() type: string;
@Input() showLoading: boolean = false; @Input() showLoading: boolean = false;
@ -23,62 +24,72 @@ export class SearchResultComponent implements OnInit, OnChanges {
@Input() custom_class: string = ""; @Input() custom_class: string = "";
@Input() properties: EnvProperties; @Input() properties: EnvProperties;
@Input() showEnermaps: boolean; @Input() showEnermaps: boolean;
public isMobile: boolean = false;
private subscriptions: any[] = [];
constructor( private http: HttpClient/*ATHENA CODE*/ constructor(private orcidService: OrcidService,
, private orcidService: OrcidService) { private layoutService: LayoutService) {
} }
ngOnInit() {} ngOnInit() {
sub; this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
}));
}
ngOnDestroy() { ngOnDestroy() {
if(this.sub){ this.subscriptions.forEach(subscription => {
this.sub.unsubscribe(); if(subscription instanceof Subscription) {
} subscription.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 => {
}
);
}
} }
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
if (changes.results) { if (changes.results) {
this.initialize(); 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 { public quote(params: string): string {
return '"' + params + '"'; return '"' + params + '"';
} }

View File

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

View File

@ -254,6 +254,8 @@ export class SearchProjectsService {
if(resData.hasOwnProperty("enddate")) { if(resData.hasOwnProperty("enddate")) {
result.endYear = resData.enddate.split('-')[0]; result.endYear = resData.enddate.split('-')[0];
} }
// Measure
result.measure = this.parsingFunctions.parseMeasures(resData['measure']);
results.push(result); 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 {EnvProperties} from '../utils/properties/env-properties';
import {map} from "rxjs/operators"; import {map} from "rxjs/operators";
import {properties} from "../../../environments/environment"; import {properties} from "../../../environments/environment";
import {HostedByCollectedFrom} from "../utils/result-preview/result-preview";
@Injectable() @Injectable()
export class SearchResearchResultsService { export class SearchResearchResultsService {
private sizeOfDescription: number = 270;
public parsingFunctions: ParsingFunctions = new ParsingFunctions(); 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 { 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 link = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true);
let url = link + "?"; let url = link + "?";
if (params != null && params != '') { if (params != null && params != '') {
url += params; url += params;
@ -32,21 +32,21 @@ export class SearchResearchResultsService {
url += "&sortBy=" + sortBy; url += "&sortBy=" + sortBy;
} }
url += "&page=" + (page - 1) + "&size=" + size + "&format=json"; url += "&page=" + (page - 1) + "&size=" + size + "&format=json";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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 { searchById(resultType: string, id: string, properties: EnvProperties): any {
let url = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true) + "/" + id + "?format=json"; let url = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true) + "/" + id + "?format=json";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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 { 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 link = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true);
let url = link + "?" + "&format=json"; let url = link + "?" + "&format=json";
if (params != null && params != '') { if (params != null && params != '') {
url += params; url += params;
@ -55,33 +55,33 @@ export class SearchResearchResultsService {
url += refineParams; url += refineParams;
} }
url += "&page=" + (page - 1) + "&size=" + size; url += "&page=" + (page - 1) + "&size=" + size;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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 { 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 link = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true);
let url = link + "?" + "&format=json&"; let url = link + "?" + "&format=json&";
var doisParams = ""; var doisParams = "";
for (var i = 0; i < DOIs.length; i++) { for (var i = 0; i < DOIs.length; i++) {
doisParams += (doisParams.length > 0 ? "&" : "") + 'doi="' + DOIs[i] + '"'; doisParams += (doisParams.length > 0 ? "&" : "") + 'doi="' + DOIs[i] + '"';
} }
if (doisParams.length > 0) { if (doisParams.length > 0) {
url += "&" + doisParams; url += "&" + doisParams;
} }
if (refineParams != null && refineParams != '') { if (refineParams != null && refineParams != '') {
url += refineParams; url += refineParams;
} }
url += "&page=" + (page - 1) + "&size=" + size; url += "&page=" + (page - 1) + "&size=" + size;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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 { 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; let url = properties.searchResourcesAPIURL;
var basicQuery = "(oaftype exact result) and (resulttypeid exact " + this.getEntityQueryName(resultType, false) + ") "; var basicQuery = "(oaftype exact result) and (resulttypeid exact " + this.getEntityQueryName(resultType, false) + ") ";
@ -101,14 +101,14 @@ export class SearchResearchResultsService {
if (refineQuery) { if (refineQuery) {
url += "&" + refineQuery; url += "&" + refineQuery;
} }
url += "&page=" + (page - 1) + "&size=" + size; url += "&page=" + (page - 1) + "&size=" + size;
url += "&format=json"; url += "&format=json";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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 { 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"; let url = properties.searchAPIURLLAst + "resources2/?format=json";
if (params != null && params != '') { if (params != null && params != '') {
@ -124,30 +124,30 @@ export class SearchResearchResultsService {
if (refineQuery) { if (refineQuery) {
url += "&" + refineQuery; url += "&" + refineQuery;
} }
url += "&page=" + (page - 1) + "&size=" + size; url += "&page=" + (page - 1) + "&size=" + size;
// url += "&format=json"; // url += "&format=json";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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 { searchResultForEntity(resultType: string, params: string, page: number, size: number, properties: EnvProperties): any {
let link = properties.searchAPIURLLAst; let link = properties.searchAPIURLLAst;
//let url = link+params+"/"+this.getEntityQueryName(resultType,true)+ "?format=json"; //let url = link+params+"/"+this.getEntityQueryName(resultType,true)+ "?format=json";
//url += "&page="+(page-1)+"&size="+size; //url += "&page="+(page-1)+"&size="+size;
//url += "&sortBy=resultdateofacceptance,descending"; //url += "&sortBy=resultdateofacceptance,descending";
//let url = link+"/resources2?format=json&query="+params+" sortBy resultdateofacceptance/sort.descending&type="+this.getEntityQueryName(resultType,true); //let url = link+"/resources2?format=json&query="+params+" sortBy resultdateofacceptance/sort.descending&type="+this.getEntityQueryName(resultType,true);
let url = link + "/" + this.getEntityQueryName(resultType, true); let url = link + "/" + this.getEntityQueryName(resultType, true);
url += "?format=json"; url += "?format=json";
url += "&fq=" + params; url += "&fq=" + params;
url += "&sortBy=resultdateofacceptance,descending"; url += "&sortBy=resultdateofacceptance,descending";
url += "&page=" + (page - 1) + "&size=" + size; url += "&page=" + (page - 1) + "&size=" + size;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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? //???? why different from above?
@ -157,9 +157,9 @@ export class SearchResearchResultsService {
url += "&sortBy=resultdateofacceptance,descending"; url += "&sortBy=resultdateofacceptance,descending";
url += "&page=" + (page - 1) + "&size=" + size + "&format=json"; url += "&page=" + (page - 1) + "&size=" + size + "&format=json";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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 { searchForMyOrcidLinks(resultType: string, orcidQuery: string, typeQuery: string, page: number, size: number): any {
let url = properties.searchAPIURLLAst + "resources2/?format=json"; let url = properties.searchAPIURLLAst + "resources2/?format=json";
if (orcidQuery != null && orcidQuery != '') { if (orcidQuery != null && orcidQuery != '') {
@ -167,14 +167,14 @@ export class SearchResearchResultsService {
} }
url += typeQuery; url += typeQuery;
url += "&page=" + (page - 1) + "&size=" + size; url += "&page=" + (page - 1) + "&size=" + size;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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[] { parseResults(resultType: string, data: any, properties: EnvProperties): SearchResult[] {
let results: SearchResult[] = []; let results: SearchResult[] = [];
if(data == null) { if (data == null) {
return results; return results;
} }
@ -182,139 +182,16 @@ export class SearchResearchResultsService {
for (let i = 0; i < length; i++) { 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']; 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(); var result: SearchResult = new SearchResult();
if (resData['resulttype']) { if (resData['resulttype']) {
result.entityType = resData['resulttype']['classname']; result.entityType = resData['resulttype']['classname'];
} else { } else {
result.entityType = resultType; 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": ''}; result['title'] = {"name": '', "accessMode": ''};
if (Array.isArray(resData['title'])) { if (Array.isArray(resData['title'])) {
for (let i = 0; i < resData['title'].length; i++) { for (let i = 0; i < resData['title'].length; i++) {
if (resData['title'][i] && resData['title'][i].content) { if (resData['title'][i] && resData['title'][i].content) {
@ -333,7 +210,104 @@ export class SearchResearchResultsService {
} else { } else {
result['title'].name = (resData['title'] && resData['title'].content) ? StringUtils.HTMLToString(String(resData['title'].content)) : ""; 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['id'] = Array.isArray(data) ? data[i]['result']['header']['dri:objIdentifier'] : data['result']['header']['dri:objIdentifier'];
result['objId'] = result['id']; result['objId'] = result['id'];
let canId = ParsingFunctions.parseRelCanonicalId(Array.isArray(data) ? data[i] : data, "result"); let canId = ParsingFunctions.parseRelCanonicalId(Array.isArray(data) ? data[i] : data, "result");
@ -341,16 +315,13 @@ export class SearchResearchResultsService {
result['id'] = canId; result['id'] = canId;
} }
result['relcanId'] = result['id']; result['relcanId'] = result['id'];
if (resData['bestaccessright'] && resData['bestaccessright'].hasOwnProperty("classname")) {
result['title'].accessMode = resData['bestaccessright'].classname;
}
if (resData['rels'].hasOwnProperty("rel")) { if (resData['rels'].hasOwnProperty("rel")) {
let relLength = Array.isArray(resData['rels']['rel']) ? resData['rels']['rel'].length : 1; let relLength = Array.isArray(resData['rels']['rel']) ? resData['rels']['rel'].length : 1;
for (let j = 0; j < relLength; j++) { for (let j = 0; j < relLength; j++) {
let relation = Array.isArray(resData['rels']['rel']) ? resData['rels']['rel'][j] : resData['rels']['rel']; let relation = Array.isArray(resData['rels']['rel']) ? resData['rels']['rel'][j] : resData['rels']['rel'];
if (relation.hasOwnProperty("to")) { if (relation.hasOwnProperty("to")) {
if (relation['to'].class && relation['to'].class.toLowerCase() == "isproducedby") { if (relation['to'].class && relation['to'].class.toLowerCase() == "isproducedby") {
result['projects'] = this.parseProjects(result['projects'], relation); result['projects'] = this.parseProjects(result['projects'], relation);
@ -358,22 +329,22 @@ export class SearchResearchResultsService {
} }
} }
} }
if (resData.hasOwnProperty("creator") && resData['creator'] != null) { if (resData.hasOwnProperty("creator") && resData['creator'] != null) {
if (result['authors'] == undefined) { if (result['authors'] == undefined) {
result['authors'] = new Array<{ "fullName": string, "orcid": string, "orcid_pending": string }>(); result['authors'] = new Array<{ "fullName": string, "orcid": string, "orcid_pending": string }>();
} }
let authors = resData['creator']; let authors = resData['creator'];
let length = Array.isArray(authors) ? authors.length : 1; 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; let author = Array.isArray(authors) ? authors[i] : authors;
if (author) { if (author) {
if(author.orcid) { if (author.orcid) {
author.orcid = author.orcid.toUpperCase(); author.orcid = author.orcid.toUpperCase();
} }
if(author.orcid_pending) { if (author.orcid_pending) {
author.orcid_pending = author.orcid_pending.toUpperCase(); author.orcid_pending = author.orcid_pending.toUpperCase();
} }
result['authors'][author.rank] = { result['authors'][author.rank] = {
@ -387,20 +358,20 @@ export class SearchResearchResultsService {
return (item != undefined && item.fullName != undefined); return (item != undefined && item.fullName != undefined);
}); });
} }
var date: string = (resData.dateofacceptance ? resData.dateofacceptance : '') + ''; // transform to string in case it is an integer 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; result.year = (date && (date).indexOf('-') !== -1) ? date.split('-')[0] : date;
let abstracts = this.parsingFunctions.parseDescription(resData.description, true); let abstracts = this.parsingFunctions.parseDescription(resData.description, true);
result.description = abstracts; result.description = abstracts;
// if (result.description && result.description.length > this.sizeOfDescription) { // if (result.description && result.description.length > this.sizeOfDescription) {
// result.description = result.description.substring(0, this.sizeOfDescription) + "..."; // result.description = result.description.substring(0, this.sizeOfDescription) + "...";
// } // }
if (resData.embargoenddate && resData.embargoenddate != '') { if (resData.embargoenddate && resData.embargoenddate != '') {
result.embargoEndDate = Dates.getDate(resData.embargoenddate); result.embargoEndDate = Dates.getDate(resData.embargoenddate);
} }
if (!Array.isArray(resData.publisher)) { if (!Array.isArray(resData.publisher)) {
result.publisher = resData.publisher; result.publisher = resData.publisher;
} else { } 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'])); 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); results.push(result);
} }
return results; return results;
} }
parseProjects(projects: { parseProjects(projects: {
"id": string, "acronym": string, "title": string, "id": string, "acronym": string, "title": string,
"funderShortname": string, "funderName": string, "funderShortname": string, "funderName": string,
@ -436,15 +437,15 @@ export class SearchResearchResultsService {
"code": string "code": string
}>(); }>();
} }
let countProjects = projects.length; let countProjects = projects.length;
projects[countProjects] = { projects[countProjects] = {
"id": "", "acronym": "", "title": "", "id": "", "acronym": "", "title": "",
"funderShortname": "", "funderName": "", "funderShortname": "", "funderName": "",
"code": "" "code": ""
}; };
if (relation.title != 'unidentified') { if (relation.title != 'unidentified') {
projects[countProjects]['id'] = relation['to'].content; projects[countProjects]['id'] = relation['to'].content;
projects[countProjects]['acronym'] = relation.acronym; projects[countProjects]['acronym'] = relation.acronym;
@ -456,36 +457,36 @@ export class SearchResearchResultsService {
projects[countProjects]['title'] = ""; projects[countProjects]['title'] = "";
projects[countProjects]['code'] = ""; projects[countProjects]['code'] = "";
} }
if (relation.hasOwnProperty("funding")) { if (relation.hasOwnProperty("funding")) {
let fundingLength = Array.isArray(relation['funding']) ? relation['funding'].length : 1; let fundingLength = Array.isArray(relation['funding']) ? relation['funding'].length : 1;
for (let z = 0; z < fundingLength; z++) { for (let z = 0; z < fundingLength; z++) {
let fundingData = Array.isArray(relation['funding']) ? relation['funding'][z] : relation['funding']; let fundingData = Array.isArray(relation['funding']) ? relation['funding'][z] : relation['funding'];
if (fundingData.hasOwnProperty("funder")) { if (fundingData.hasOwnProperty("funder")) {
projects[countProjects]['funderShortname'] = fundingData['funder'].shortname; projects[countProjects]['funderShortname'] = fundingData['funder'].shortname;
projects[countProjects]['funderName'] = fundingData['funder'].name; projects[countProjects]['funderName'] = fundingData['funder'].name;
} }
} }
} }
return projects; return projects;
} }
parseRefineResults(id: string, data: any): any { parseRefineResults(id: string, data: any): any {
var results: any = []; var results: any = [];
if (data.hasOwnProperty("resulthostingdatasource")) { if (data.hasOwnProperty("resulthostingdatasource")) {
let length = Array.isArray(data['resulthostingdatasource']) ? data['resulthostingdatasource'].length : 1; let length = Array.isArray(data['resulthostingdatasource']) ? data['resulthostingdatasource'].length : 1;
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
let datasource = Array.isArray(data['resulthostingdatasource']) ? data['resulthostingdatasource'][i] : data['resulthostingdatasource']; let datasource = Array.isArray(data['resulthostingdatasource']) ? data['resulthostingdatasource'][i] : data['resulthostingdatasource'];
let result: { "name": string, "id": string, "count": number } = {"name": "", "id": "", "count": 0}; let result: { "name": string, "id": string, "count": number } = {"name": "", "id": "", "count": 0};
result['name'] = datasource.name; result['name'] = datasource.name;
result['id'] = datasource.id.split("||")[0]; result['id'] = datasource.id.split("||")[0];
result['count'] = datasource.count; result['count'] = datasource.count;
if (result['id'] != id && result['name'] != "Unknown Repository") { if (result['id'] != id && result['name'] != "Unknown Repository") {
results.push(result); results.push(result);
} }
@ -493,19 +494,19 @@ export class SearchResearchResultsService {
} }
return results; return results;
} }
private numOfResults(url: string, properties: EnvProperties): any { private numOfResults(url: string, properties: EnvProperties): any {
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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 { numOfEntityResults(resultType: string, id: string, entity: string, properties: EnvProperties): any {
var parameters: string = ""; var parameters: string = "";
parameters = this.getEntityQueryName(entity, true) + "/" + id + "/" + this.getEntityQueryName(resultType, true) + "/count"; parameters = this.getEntityQueryName(entity, true) + "/" + id + "/" + this.getEntityQueryName(resultType, true) + "/count";
let url = properties.searchAPIURLLAst + parameters + "?format=json"; let url = properties.searchAPIURLLAst + parameters + "?format=json";
return this.numOfResults(url, properties); return this.numOfResults(url, properties);
} }
numOfResearchOutcomes(params: string, properties: EnvProperties, refineParams: string = null): any { numOfResearchOutcomes(params: string, properties: EnvProperties, refineParams: string = null): any {
let url = properties.searchAPIURLLAst + "resources2/?format=json&size=0&type=results"; let url = properties.searchAPIURLLAst + "resources2/?format=json&size=0&type=results";
if (params.length > 0) { if (params.length > 0) {
@ -522,20 +523,20 @@ export class SearchResearchResultsService {
// } // }
url += "&query=" + params; url += "&query=" + params;
} }
if (refineParams != null && refineParams != '') { if (refineParams != null && refineParams != '') {
url += refineParams; url += refineParams;
} }
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) 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 { numOfSearchResults(resultType: string, params: string, properties: EnvProperties, refineParams: string = null): any {
let url = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true) + "/count?format=json"; let url = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true) + "/count?format=json";
if (params.length > 0) { if (params.length > 0) {
var DOIs: string[] = DOI.getDOIsFromString(params); var DOIs: string[] = DOI.getDOIsFromString(params);
var doisParams = ""; var doisParams = "";
for (var i = 0; i < DOIs.length; i++) { for (var i = 0; i < DOIs.length; i++) {
doisParams += (doisParams.length > 0 ? "&" : "") + 'doi="' + DOIs[i] + '"'; doisParams += (doisParams.length > 0 ? "&" : "") + 'doi="' + DOIs[i] + '"';
} }
@ -545,30 +546,30 @@ export class SearchResearchResultsService {
url += "&q=" + StringUtils.URIEncode(params); url += "&q=" + StringUtils.URIEncode(params);
} }
} }
if (refineParams != null && refineParams != '') { if (refineParams != null && refineParams != '') {
url += refineParams; url += refineParams;
} }
return this.numOfResults(url, properties); return this.numOfResults(url, properties);
} }
numOfSearchResultsLinkedToPub(resultType: string, properties: EnvProperties): any { 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"; 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) 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 { countTotalResults(resultType: string, properties: EnvProperties, refineParams: string = null): any {
let url = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true) + "/count?format=json" + refineParams; let url = properties.searchAPIURLLAst + this.getEntityQueryName(resultType, true) + "/count?format=json" + refineParams;
return this.numOfResults(url, properties); return this.numOfResults(url, properties);
} }
/* /*
private quote(word: any): string { private quote(word: any): string {
return '"'+word+'"'; return '"'+word+'"';
} }
*/ */
private getEntityQueryName(entityType: string, plural: boolean) { private getEntityQueryName(entityType: string, plural: boolean) {
if (entityType == "publication" || entityType == "dataset" || entityType == "organization" || entityType == "datasource" || entityType == "project") { if (entityType == "publication" || entityType == "dataset" || entityType == "organization" || entityType == "datasource" || entityType == "project") {
if (plural) { if (plural) {
@ -582,8 +583,8 @@ export class SearchResearchResultsService {
} }
public countCollectedResultsWithFundingInfo(datasourceId: string) { 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) 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) { public updateUserInfo(resolve: Function = null) {
this.subscription = this.http.get<User>(properties.userInfoUrl, CustomOptions.registryOptions()).pipe(map(userInfo => { this.subscription = this.http.get<User>(properties.userInfoUrl, CustomOptions.registryOptions()).pipe(map(userInfo => {
return this.parseUserInfo(userInfo); return new User(userInfo);
})).subscribe(user => { })).subscribe(user => {
this.getUserInfoSubject.next(user); this.getUserInfoSubject.next(user);
if (resolve) { 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) { public setRedirectUrl(url: string = null) {
if (url) { if (url) {
let parts = url.split('?'); let parts = url.split('?');

View File

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

View File

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

View File

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

View File

@ -41,12 +41,12 @@
*ngIf="isAtleastOneEnabled(menu.entitiesRequired,showEntity) && isAtleastOneEnabled(menu.routeRequired, showPage)"> *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 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)" <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" [queryParams]="menu.params"
[fragment]="menu.fragment">{{menu.title}}</a> [fragment]="menu.fragment">{{menu.title}}</a>
<a *ngIf="!menu.route && menu.url" <a *ngIf="!menu.route && menu.url"
href="{{menu.url}}" (click)="menu.items.length === 0?closeCanvas(canvas):null" [class.custom-external]="menu.target != '_self'" [href]="menu.items.length === 0?menu.url:null" (click)="menu.items.length === 0?closeCanvas(canvas):null"
target="{{menu.target}}">{{menu.title}}</a> [class.custom-external]="menu.target != '_self'" [target]="menu.target">{{menu.title}}</a>
<a *ngIf="(!menu.route && !menu.url) || <a *ngIf="(!menu.route && !menu.url) ||
(menu.route && menu.routeRequired && !isEnabled([menu.route], showPage) (menu.route && menu.routeRequired && !isEnabled([menu.route], showPage)
&& isAtleastOneEnabled(menu.routeRequired, showPage))" && isAtleastOneEnabled(menu.routeRequired, showPage))"
@ -144,6 +144,9 @@
<ng-content select="[extra-s]"></ng-content> <ng-content select="[extra-s]"></ng-content>
</ng-container> </ng-container>
</ul> </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> </div>
</div> </div>
@ -170,12 +173,28 @@
<ng-container *ngIf="!activeHeader.menuPosition || activeHeader.menuPosition === 'center'"> <ng-container *ngIf="!activeHeader.menuPosition || activeHeader.menuPosition === 'center'">
<ng-container *ngTemplateOutlet="mainMenu"></ng-container> <ng-container *ngTemplateOutlet="mainMenu"></ng-container>
</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>
<div class="uk-navbar-right"> <div class="uk-navbar-right">
<ng-container *ngIf="activeHeader.menuPosition === 'right'"> <ng-container *ngIf="activeHeader.menuPosition === 'right'">
<ng-container *ngTemplateOutlet="mainMenu"></ng-container> <ng-container *ngTemplateOutlet="mainMenu"></ng-container>
</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 [userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl [logOutUrl]=properties.logoutUrl
[cookieDomain]=properties.cookieDomain></user-mini> [cookieDomain]=properties.cookieDomain></user-mini>
<div class="uk-visible@m"> <div class="uk-visible@m">
@ -183,7 +202,7 @@
</div> </div>
</div> </div>
<ng-template #mainMenu> <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 !== '/'"> <li class="uk-parent" *ngIf="showHomeMenuItem && currentRoute.route !== '/'">
<a routerLink="/">Home</a> <a routerLink="/">Home</a>
</li> </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 {ActivatedRoute, Router} from '@angular/router';
import {Session, User} from '../login/utils/helper.class'; import {Session, User} from '../login/utils/helper.class';
import {ConfigurationService} from '../utils/configuration/configuration.service'; import {ConfigurationService} from '../utils/configuration/configuration.service';
@ -9,6 +18,9 @@ import {HelpContentService} from '../services/help-content.service';
import {properties} from "../../../environments/environment"; import {properties} from "../../../environments/environment";
import {LayoutService} from "../dashboard/sharedComponents/sidebar/layout.service"; import {LayoutService} from "../dashboard/sharedComponents/sidebar/layout.service";
import {NotificationConfiguration} from "../notifications/notifications-sidebar/notifications-sidebar.component"; 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; declare var UIkit;
@ -57,6 +69,7 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
subs: Subscription[] = []; subs: Subscription[] = [];
showEntity = {}; showEntity = {};
showPage = {}; showPage = {};
public searchMode: boolean = false;
public additionalMenuItems: MenuItem[] = []; public additionalMenuItems: MenuItem[] = [];
public featuredMenuItems: MenuItem[] = []; public featuredMenuItems: MenuItem[] = [];
@ -64,13 +77,28 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
public isFeaturedMenuEnabled: boolean = false; public isFeaturedMenuEnabled: boolean = false;
public featuredAlignment: string = MenuAlignment.CENTER.valueOf(); 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, constructor(private router: Router,
private route: ActivatedRoute, private route: ActivatedRoute,
private config: ConfigurationService, private config: ConfigurationService,
private _helpContentService: HelpContentService, private _helpContentService: HelpContentService,
private layoutService: LayoutService) {} private layoutService: LayoutService,
private cdr: ChangeDetectorRef) {}
ngOnInit() { ngOnInit() {
this.subs.push(this.route.queryParams.subscribe(params => {
this.searchMode = false;
this.keyword = "";
}));
this.initialize(); this.initialize();
} }
@ -145,6 +173,9 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
this.subs.push(this.layoutService.replaceHeader.subscribe(replaceHeader => { this.subs.push(this.layoutService.replaceHeader.subscribe(replaceHeader => {
this.setHeader(replaceHeader); this.setHeader(replaceHeader);
})); }));
this.subs.push(this.layoutService.hasMenuSearchBar.subscribe(hasSearchBar => {
this.hasSearchBar = hasSearchBar;
}));
} }
setHeader(replaceHeader: boolean) { setHeader(replaceHeader: boolean) {
@ -204,4 +235,32 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
// return MenuItem.isTheActiveMenu(item, this.currentRoute, this.layoutService.activeMenuItem); // 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