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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,122 +1,4 @@
<div class="linking uk-background-default">
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
<div class="uk-padding-small uk-padding-remove-horizontal">
<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
</div>
</div>
<div uk-sticky="offset: 65; bottom: #pageBottom; media: @m" class="uk-blur-background">
<div class="uk-section-xsmall">
<stepper>
<step *ngIf="!inlineEntity" [status]="stepStatus('source')" stepId="source" stepNumber="1"
[stepText]="'Find Sources'" (stepChanged)="stepHasChanged($event)"
[active]="this.showOptions.show" [showStepLine]="false"></step>
<step [status]="stepStatus('target')" stepId="target" [stepNumber]="inlineEntity?1:2"
[stepText]="'Link Source' + (inlineEntity?'':'s') + ' to Entities'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show"
[showStepLine]="!inlineEntity"></step>
<step [status]="stepStatus('claim')" stepId="claim" [stepNumber]="inlineEntity?2:3"
[stepText]="'Summarize and finish'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show"
[showStepLine]="true"></step>
</stepper>
</div>
</div>
<div id="pageTop"></div>
<metadata-preview *ngIf="showOptions.show=='claim' && properties" class="uk-margin-top"
[results]="results" [sources]="sources"
[localStoragePrefix]="localStoragePrefix" [inlineEntity]="inlineEntity"
[showOptions]="showOptions" [properties]=properties [pageContents]="pageContents"
[defaultColors]="!communityId" [communityId]="communityId"
>
</metadata-preview>
<div id="tm-main" class="uk-section uk-padding-remove-top" *ngIf="showOptions.show != 'claim'">
<div>
<schema2jsonld *ngIf="url" [URL]="url" name="Link your {{openaireEntities.RESULTS}}" type="other"></schema2jsonld>
<div [class]="((showOptions.show == 'claim')?'':' uk-margin-top ')+' uk-container uk-container-large '">
<div *ngIf="properties" class="uk-section uk-padding-remove-top">
<div [class]="((showOptions.show == 'claim')?'':' uk-margin-top ')+' uk-container uk-container-large '">
<div class="uk-grid basketContainer" *ngIf="showOptions.show!='claim'" uk-grid>
<div class="uk-width-2-3 uk-position-z-index">
<div *ngIf="showOptions.show=='source'">
<claim-result-search-form [selectedResults]="sources" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'"
[basketLimit]="basketLimit"
></claim-result-search-form>
</div>
<div *ngIf="showOptions.show=='project'">
<claim-projects-search-form [selectedProjects]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
></claim-projects-search-form>
</div>
<div *ngIf="showOptions.show=='context'">
<claim-contexts-search-form [communityId]=communityId [results]="results" [sources]="sources"
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
></claim-contexts-search-form>
</div>
<div *ngIf="showOptions.show=='result'">
<claim-result-search-form [selectedResults]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
></claim-result-search-form>
</div>
</div>
<!-- Basket-->
<div *ngIf="showOptions.show != 'claim'" class="uk-width-1-3">
<div id="basket" uk-sticky="offset: 220; bottom: !*; media: @m" style="z-index: 0!important;">
<div class="uk-card uk-card-default linkingBasket">
<div class="uk-card-body uk-padding-small">
<div class="uk-margin-right">
<ul class="uk-tab" uk-tab>
<li [class.uk-active]="showOptions.basketShowSources"
(click)="showOptions.basketswitchToSources()">
<a>
Sources to link ({{(sources.length + (inlineEntity ? 1 : 0)) |number}})
</a>
</li>
<li [class.uk-disabled]="sources.length == 0 && !inlineEntity"
[class.uk-active]="showOptions.basketShowLinksTo">
<a (click)="showOptions.basketswitchToLinkTo()">Link to <span
*ngIf="results.length> 0">({{(results.length) | number}})</span>
</a>
</li>
</ul>
<div *ngIf="showOptions.basketShowSources">
<div class="uk-height-medium uk-overflow-auto">
<div *ngIf="showOptions.show == 'source'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height:17px;">
<start-over *ngIf="showOptions.show == 'source' && sources.length> 0"
[results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'"
message="all sources" class="uk-float-right"></start-over>
<bulk-claim *ngIf="showOptions.show == 'source'" [results]="sources"
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'" [basketLimit]="basketLimit"
>
</bulk-claim>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<div *ngIf="sources.length == 0 && !inlineEntity " class="uk-text-center uk-text-meta">
No Sources added yet. Start adding sources from the left panel. Or upload a DOI's CSV file.
</div>
<div *ngIf="sources.length >= basketLimit " class="uk-alert uk-alert-warning uk-text-center">
Basket reached the size limit. No more sources can be added.
</div>
<claim-selected-results *ngIf="inlineEntity" [results]="[inlineEntity]"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="false" type="source">
</claim-selected-results>
<claim-selected-results *ngIf="sources.length > 0" [results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="true" type="source">
</claim-selected-results>
</div>
</div>
</div>
<div *ngIf="showOptions.basketShowLinksTo">
<div class="uk-height-medium uk-overflow-auto">
<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'"
@ -139,8 +21,163 @@
</div>
</div>
</ng-template>
<div class="linking uk-background-default">
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
<div class="uk-padding-small uk-padding-remove-horizontal">
<breadcrumbs *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 *ngIf="!inlineEntity" uk-sticky="offset: 65; bottom: #pageBottom; media: @m" class="uk-blur-background">
<div class="uk-section-xsmall">
<stepper>
<step [status]="stepStatus('source')" stepId="source" stepNumber="1"
[stepText]="'Find Sources'" (stepChanged)="stepHasChanged($event)"
[active]="this.showOptions.show" [showStepLine]="false"></step>
<step [status]="stepStatus('target')" stepId="target" [stepNumber]="2"
[stepText]="'Link Sources to Entities'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show"
[showStepLine]="true"></step>
<step [status]="stepStatus('claim')" stepId="claim" [stepNumber]="3"
[stepText]="'Summarize and finish'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show"
[showStepLine]="true"></step>
</stepper>
</div>
</div>
<div id="pageTop"></div>
<metadata-preview *ngIf="showOptions.show=='claim' && properties" class="uk-margin-top"
[results]="results" [sources]="sources"
[localStoragePrefix]="localStoragePrefix" [inlineEntity]="inlineEntity"
[showOptions]="showOptions" [properties]=properties [pageContents]="pageContents"
[defaultColors]="!communityId" [communityId]="communityId"
>
</metadata-preview>
<div id="tm-main" class="uk-section uk-padding-remove-top" *ngIf="showOptions.show != 'claim'">
<div>
<schema2jsonld *ngIf="url" [URL]="url" name="Link your {{openaireEntities.RESULTS}}" type="other"></schema2jsonld>
<div [class]="((showOptions.show == 'claim')?'':' uk-margin-top ')+' uk-container uk-container-large '">
<div *ngIf="properties" class="uk-section uk-padding-remove-top">
<div [class]="((showOptions.show == 'claim')?'':' uk-margin-top ')+' uk-container uk-container-large '">
<div class="uk-grid basketContainer" *ngIf="showOptions.show!='claim'" uk-grid>
<div class="uk-width-2-3 uk-position-z-index">
<h2 *ngIf="inlineEntity" class="uk-text-center">Link source to</h2>
<div *ngIf="showOptions.show=='source'">
<claim-result-search-form [selectedResults]="sources" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'"
[basketLimit]="basketLimit" [centerAlign]="!!inlineEntity"
></claim-result-search-form>
</div>
<div *ngIf="showOptions.show=='project'">
<claim-projects-search-form [selectedProjects]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-projects-search-form>
</div>
<div *ngIf="showOptions.show=='context'">
<claim-contexts-search-form [communityId]=communityId [results]="results" [sources]="sources"
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-contexts-search-form>
</div>
<div *ngIf="showOptions.show=='result'">
<claim-result-search-form [selectedResults]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-result-search-form>
</div>
</div>
<!-- Basket-->
<div *ngIf="showOptions.show != 'claim'" class="uk-width-1-3">
<div id="basket" uk-sticky="offset: 220; bottom: !*; media: @m" style="z-index: 0!important;">
<div class="uk-card uk-card-default linkingBasket">
<div class="uk-card-body uk-padding-small">
<div class="uk-margin-right">
<ng-container *ngIf="inlineEntity">
<div class="uk-margin-small-bottom">
<div class="uk-text-emphasis uk-text-bolder">Source</div>
<claim-selected-results [results]="[inlineEntity]"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="false" type="source">
</claim-selected-results>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal"><hr class="uk-margin-remove"/></div>
<div class="uk-margin-small-top">
<div class="uk-text-emphasis uk-text-bolder">Link source to <span *ngIf="results.length> 0">({{(results.length) | number}})</span></div>
<ng-container *ngTemplateOutlet="destinations_basket"></ng-container>
</div>
</ng-container>
<ng-container *ngIf="!inlineEntity">
<ul class="uk-tab" uk-tab>
<li [class.uk-active]="showOptions.basketShowSources"
(click)="showOptions.basketswitchToSources()">
<a>
Sources to link ({{(sources.length) |number}})
</a>
</li>
<li [class.uk-disabled]="sources.length == 0"
[class.uk-active]="showOptions.basketShowLinksTo">
<a (click)="showOptions.basketswitchToLinkTo()">Link to <span
*ngIf="results.length> 0">({{(results.length) | number}})</span>
</a>
</li>
</ul>
<div *ngIf="showOptions.basketShowSources">
<div class="uk-height-medium uk-overflow-auto">
<div *ngIf="showOptions.show == 'source'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height:17px;">
<start-over *ngIf="showOptions.show == 'source' && sources.length> 0"
[results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'"
message="all sources" class="uk-float-right"></start-over>
<bulk-claim *ngIf="showOptions.show == 'source'" [results]="sources"
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'" [basketLimit]="basketLimit"
>
</bulk-claim>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<div *ngIf="sources.length == 0" 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>
</div>
<div *ngIf="showOptions.basketShowLinksTo">
<div class="uk-height-medium uk-overflow-auto">
<ng-container *ngTemplateOutlet="destinations_basket"></ng-container>
</div>
</div>
</ng-container>
</div>
</div>
<div *ngIf="showOptions.show == 'source'"
@ -164,7 +201,7 @@
<button class="uk-flex uk-flex-middle uk-button uk-button-text"
[class.uk-disabled]="results.length == 0" [disabled]="results.length == 0">
<icon *ngIf="inlineEntity" name="link" visuallyHidden="link" [flex]="true"></icon>
<div class="uk-width-expand uk-margin-small-left">STEP {{inlineEntity ? '2' : '3'}} - FINALISE AND FINISH</div>
<div class="uk-width-expand uk-margin-small-left"><ng-container *ngIf="!inlineEntity">STEP {{inlineEntity ? '2' : '3'}} - </ng-container>SUMMARISE</div>
</button>
</div>
</div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
<div class="landing uk-section uk-padding-remove tm-middle">
<div class="tm-main">
<!-- Desktop view -->
<div class="uk-visible@m landing uk-section uk-padding-remove tm-middle">
<div *ngIf="!isMobile" class="tm-main">
<div class="dataprovider">
<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">
@ -14,7 +15,7 @@
<div *ngIf="!showFeedback" class="uk-grid uk-margin-remove-left" uk-grid>
<!-- left box - actions -->
<div id="landing-left-sidebar" *ngIf="dataProviderInfo" class="uk-visible@s uk-padding-remove-horizontal">
<!-- <div id="landing-left-sidebar" *ngIf="dataProviderInfo" class="uk-visible@s uk-padding-remove-horizontal">
<div class="uk-flex uk-flex-column uk-flex-between uk-flex-center uk-sticky"
uk-sticky="bottom: true" [attr.offset]="offset">
<div class="uk-align-center uk-text-center uk-margin-medium-top uk-flex uk-flex-column uk-flex-between">
@ -29,7 +30,6 @@
<div class="uk-margin-large-bottom uk-align-center">
<div class="uk-text-meta uk-text-uppercase">Actions</div>
<ul class="uk-list">
<!-- Share -->
<li class="uk-text-center">
<a (click)="openAddThisModal()"
[title]="'Share this '+openaireEntities.DATASOURCE+' in your social networks'"
@ -42,20 +42,13 @@
</ul>
</div>
</div>
</div>
</div> -->
<!-- center box-->
<div class="uk-width-expand uk-padding-remove uk-background-default">
<div *ngIf="errorMessage.length > 0 || showLoading" class="uk-container uk-flex uk-flex-center uk-height-viewport uk-position-relative">
<div *ngIf="errorMessage.length > 0" class="uk-alert uk-alert-danger uk-width-2-3 uk-margin-xlarge-top"
role="alert">{{errorMessage}}</div>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
</div>
<div id="landing-center-content" class="uk-width-expand uk-padding-remove uk-background-default">
<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]="!dataProviderInfo">
<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]="!dataProviderInfo">
<!-- Last Index Info-->
<a href="https://graph.openaire.eu" target="_blank" class="uk-width-1-1 uk-width-auto@l">
<img src="assets/common-assets/openaire-badge-1.png" alt="Powered by OpenAIRE graph" style="height: 15px;">
@ -72,15 +65,34 @@
</div>
</ng-template>
<div #graph_and_feedback id="graph_and_feedback" class="uk-padding uk-padding-remove-vertical uk-blur-background uk-text-xsmall uk-visible@m"
<div #graph_and_feedback id="graph_and_feedback" class="uk-blur-background uk-text-xsmall uk-visible@m"
uk-sticky="bottom: true;" [attr.offset]="graph_offset">
<ng-container *ngTemplateOutlet="graph_and_feedback_template"></ng-container>
</div>
<div class="uk-margin-large-left uk-margin-large-right" [style]="'margin-bottom: '+graph_height+'px'">
<div class="uk-container uk-container-xlarge">
<div *ngIf="errorMessage.length > 0 || showLoading" class="uk-container uk-flex uk-flex-center uk-height-viewport uk-position-relative">
<div *ngIf="errorMessage.length > 0" class="uk-alert uk-alert-danger uk-width-2-3 uk-margin-xlarge-top"
role="alert">{{errorMessage}}</div>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
</div>
<div *ngIf="!showLoading && dataProviderInfo" class="uk-visible@s uk-margin-top uk-margin-bottom">
<div class="uk-flex uk-flex-middle uk-flex-center">
<div class="landing-action-bar uk-text-xsmall uk-box-shadow-small uk-margin-bottom">
<entity-actions [share]="true" [type]="'dataprovider'"></entity-actions>
</div>
</div>
</div>
<div class="uk-margin-left uk-margin-right" [style]="'margin-bottom: '+graph_height+'px'">
<ng-container *ngIf="dataProviderInfo">
<div [attr.style]="'margin-top: '+(graph_height? 'calc(40px + 20px - '+graph_height+'px)': '40px')">
<div class="uk-grid uk-grid-small" uk-grid>
<div class="uk-width-expand">
<!-- schema.org-->
<schema2jsonld [data]=dataProviderInfo
[URL]="canonicalUrl"
@ -105,17 +117,23 @@
<landing-header [properties]="properties" [title]="dataProviderInfo.title.name"
[subTitle]="(dataProviderInfo.officialName
&& dataProviderInfo.title.name !== dataProviderInfo.officialName)?dataProviderInfo.officialName:null"
[types]="dataProviderInfo.type ? [dataProviderInfo.type] : null">
[types]="dataProviderInfo.type ? [dataProviderInfo.type] : null"
[entityType]="getTypeName()"
[compatibility]="dataProviderInfo.compatibility"
[aggregationStatus]="dataProviderInfo.aggregationStatus"
[thematic]="dataProviderInfo.thematic" [type]="type"
[journal]="dataProviderInfo.journal" [prevPath]="prevPath">
</landing-header>
<!-- Labels -->
<div class="uk-margin-bottom uk-grid uk-grid-small uk-flex-middle" uk-grid>
<!-- Moved inside the landing-header -->
<!-- <div class="uk-margin-bottom uk-grid uk-grid-small uk-flex-middle" uk-grid>
<ng-container *ngIf="dataProviderInfo.compatibility &&
!(dataProviderInfo.compatibility.info == 'not available' && type == 'service')">
<div>
<span class="uk-label uk-text-truncate" [class.uk-label-danger]="dataProviderInfo.compatibility.info == 'not available'" title="Compatibility">
<a *ngIf="dataProviderInfo.compatibility.id"
[queryParams]="addEoscPrevInParams({datasourceId: dataProviderInfo.compatibility.id})" routerLinkActive="router-link-active"
[queryParams]="{datasourceId: dataProviderInfo.compatibility.id}" routerLinkActive="router-link-active"
[routerLink]="properties.searchLinkToDataProvider.split('?')[0]">
{{dataProviderInfo.compatibility.info}}
<ng-container *ngIf="dataProviderInfo.compatibility.name">{{dataProviderInfo.compatibility.name}}</ng-container>
@ -149,7 +167,7 @@
<span class="uk-label uk-text-truncate">Thematic</span>
</div>
</ng-container>
</div>
</div> -->
<!-- Web Page -->
<div *ngIf="dataProviderInfo.title && dataProviderInfo.title.url"
@ -166,16 +184,58 @@
<showIdentifiers [identifiers]="dataProviderInfo.identifiers" [showViewAll]="true"></showIdentifiers>
</div>
</div>
<div *ngIf="dataProviderInfo && hasMetrics" class="uk-width-1-1 uk-width-medium@s">
<div class="landing-metrics-card uk-card uk-card-secondary uk-text-small uk-flex uk-padding-small">
<div class="uk-width-expand uk-flex uk-flex-middle">
<div class="uk-grid uk-grid-small uk-flex-nowrap" uk-grid uk-height-match="target: > div > .cell">
<div>
<ng-container>
<ng-container *ngFor="let measure of dataProviderInfo.measure.counts; let i = index">
<div *ngIf="measure.value" class="cell uk-flex uk-flex-middle" [class.uk-margin-xsmall-bottom]="i != dataProviderInfo.measure.counts.length - 1">
<icon [name]="measure.icon" [ratio]="0.8" [flex]="true"></icon>
</div>
</ng-container>
</ng-container>
</div>
<div>
<ng-container *ngFor="let measure of dataProviderInfo.measure.counts; let i = index">
<div *ngIf="measure.value" class="cell" [class.uk-margin-xsmall-bottom]="i != dataProviderInfo.measure.counts.length - 1">
<a class="uk-text-capitalize">{{measure.name}}</a>
<ng-container *ngTemplateOutlet="dropInfo; context: {option: measure.name, isCompact: false}"></ng-container>
</div>
</ng-container>
</div>
<ng-template #dropInfo let-option=option>
<div class="uk-dropdown" uk-dropdown="pos: bottom-left; mode:click; container: #modal-container;">
<div class="uk-padding-small uk-width-medium uk-text-small" [innerHTML]="getMetricsTooltip(option) | safeHtml">
</div>
</div>
</ng-template>
<div class="uk-text-uppercase uk-text-bolder">
<ng-container *ngFor="let measure of dataProviderInfo.measure.counts; let i = index">
<div *ngIf="measure.value" [attr.uk-tooltip]="measure.value >= 1000 ? 'cls: uk-active' : 'cls: uk-invisible'"
title="{{measure.value | number}}" class="cell" [class.uk-margin-xsmall-bottom]="i != dataProviderInfo.measure.counts.length - 1">
{{formatNumber(measure.value)}}
</div>
</ng-container>
</div>
</div>
</div>
<div class="uk-width-1-5 uk-flex uk-flex-bottom">
<img src="assets/common-assets/metrics-badge.svg" loading="lazy" alt="Metrics badge">
</div>
</div>
</div>
</div>
</div>
<div id="main-tabs-div" class="uk-sticky uk-blur-background"
uk-sticky="bottom: true; media: @m" [attr.offset]="offset">
<div class="uk-padding uk-padding-remove-horizontal uk-padding-remove-bottom">
<landing-header *ngIf="stickyHeader" class="uk-visible@m"
<landing-header [ngClass]="stickyHeader ? 'uk-visible@m' : 'uk-invisible'"
[properties]="properties" [title]="dataProviderInfo.title.name"
[subTitle]="(dataProviderInfo.officialName
&& dataProviderInfo.title.name !== dataProviderInfo.officialName)?dataProviderInfo.officialName:null"
[entityType]="getTypeName()"
[types]="dataProviderInfo.type ? [dataProviderInfo.type] : null"
isSticky="true">
isSticky="true" [prevPath]="prevPath">
</landing-header>
<!-- <showTitle *ngIf="stickyHeader" [titleName]="dataProviderInfo.title.name" classNames="uk-margin-remove-bottom" class="uk-visible@m"></showTitle>-->
<my-tabs (selectedActiveTab)="onSelectActiveTab($event)" [offsetForSticky]="offset" [(isSticky)]="stickyHeader">
@ -208,6 +268,9 @@
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)"
[tabTitle]="'Related '+openaireEntities.DATASOURCES" [tabId]="'relatedDatasources'">
</my-tab>
<my-tab *ngIf="dataProviderInfo && hasMetrics"
[tabTitle]="'Metrics'" [tabId]="'metrics'">
</my-tab>
<my-tab *ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)"
[tabTitle]="'Statistics'" customClass="statistics" [tabId]="'statistics'" [active]="false">
@ -217,231 +280,37 @@
</div>
<div id="landing-sections" class="uk-text-small">
<div id="summary" class="landing-section landing-section-height-auto">
<div class="uk-card uk-card-default card-tab uk-grid uk-margin-remove-left uk-margin-medium-top uk-margin-medium-bottom">
<div *ngIf="!(hasPrimaryInfo || (!aggregationStatusIsInitialized || hasAggregationStatusInfo)) && !hasSecondaryInfo"
class="uk-width-expand uk-height-small uk-flex uk-flex-center uk-flex-middle">
<div class="uk-animation-fade uk-text-meta uk-text-large">
No summary information available
</div>
</div>
<div *ngIf="hasPrimaryInfo || (!aggregationStatusIsInitialized || hasAggregationStatusInfo)"
class="uk-width-expand uk-padding uk-inline">
<!-- Description -->
<div *ngIf="dataProviderInfo.description" class="uk-margin-medium-bottom">
<div class="uk-text-justify">
<div class="uk-text-meta uk-margin-small-bottom">Description</div>
<div class="multi-line-ellipsis lines-10">
<div #descriptionDiv class="uk-margin-small-bottom"
[innerHtml]="dataProviderInfo.description"></div>
</div>
<div *ngIf="showViewMoreButton" class="uk-flex uk-flex-right">
<a (click)="openDescriptionModal();" class="view-more-less-link">
View more
</a>
</div>
</div>
</div>
<ul *ngIf="hasJournalInfo" class="uk-list uk-margin-medium-bottom uk-margin-remove-top">
<showPublisher [journal]="dataProviderInfo.journal" [properties]="properties"></showPublisher>
</ul>
<div *ngIf="hasAggregationStatusInfo || dataProviderInfo.fundedContent"
class="uk-margin-medium-bottom uk-animation-fade uk-animation-fast">
<span *ngIf="dataProviderInfo.aggregationStatus?.fulltexts && dataProviderInfo.aggregationStatus?.fulltexts != -1"
class="uk-margin-right uk-display-inline-block">
<div class="uk-text-meta uk-margin-small-bottom">Collected full-texts</div>
{{dataProviderInfo.aggregationStatus.fulltexts | number}}
</span>
<span *ngIf="dataProviderInfo.fundedContent && dataProviderInfo.fundedContent > 0"
class="uk-display-inline-block">
<div class="uk-text-meta uk-margin-small-bottom">Results with funding information</div>
{{dataProviderInfo.fundedContent | number}}
</span>
</div>
<div *ngIf="!aggregationStatusIsInitialized || !dataProviderInfo.fundedContent"
class="uk-animation-fade uk-margin-top uk-width-1-1" role="alert">
<span class="loading-gif uk-align-center"></span>
</div>
<div *ngIf="dataProviderInfo.countries != undefined && dataProviderInfo.countries.length > 0"
class="uk-margin-medium-bottom">
<div class="uk-text-meta uk-margin-small-bottom">Countries</div>
{{dataProviderInfo.countries.join(", ")}}
</div>
<div *ngIf="dataProviderInfo.jurisdiction" class="uk-margin-medium-bottom">
<div class="uk-text-meta uk-margin-small-bottom">Jurisdiction</div>
{{dataProviderInfo.jurisdiction}}
</div>
<div *ngIf="dataProviderInfo.contentpolicy" class="uk-margin-medium-bottom">
<div class="uk-text-meta uk-margin-small-bottom">Content policy</div>
{{dataProviderInfo.contentpolicy}}
</div>
<!-- Subjects -->
<div *ngIf="dataProviderInfo.subjects && dataProviderInfo.subjects.length > 0"
class="uk-margin-medium-bottom uk-margin-bottom">
<div class="uk-height-max-medium uk-overflow-auto">
<div class="uk-text-meta uk-margin-small-bottom">Subjects </div>
<span>{{dataProviderInfo.subjects.slice(0, lessBtnSubjects ? dataProviderInfo.subjects.length : thresholdSubjects).join(", ")}}</span>
<span *ngIf="dataProviderInfo.subjects.length > thresholdSubjects && !lessBtnSubjects"> ... </span>
</div>
<div *ngIf="dataProviderInfo.subjects.length > thresholdSubjects && !lessBtnSubjects"
class="uk-width-1-1 uk-text-right">
<a (click)="viewAllSubjectsClick();" class="view-more-less-link">
View all {{dataProviderInfo.subjects.length | number}} subjects
</a>
</div>
<div *ngIf="viewAllSubjects && lessBtnSubjects" class="uk-width-1-1 uk-text-right">
<a (click)="viewAllSubjects = !viewAllSubjects; lessBtnSubjects=false;" class="view-more-less-link">View less subjects</a>
</div>
</div>
</div>
<div *ngIf="hasSecondaryInfo"
[class]="'uk-inline uk-padding uk-padding-remove-horizontal ' + (hasPrimaryInfo?'uk-width-1-3@m': 'uk-width-expand')">
<div class="uk-padding uk-padding-remove-vertical uk-height-1-1">
<div *ngIf="dataProviderInfo.oaiPmhURL || dataProviderInfo.provenance?.size > 0"
class="uk-margin-medium-bottom">
<div *ngIf="dataProviderInfo.oaiPmhURL" class="uk-margin-medium-bottom">
<div class="uk-text-meta uk-margin-small-bottom">OAI-PMH</div>
<a target="_blank" href="{{dataProviderInfo.oaiPmhURL}}" class="custom-external">
{{dataProviderInfo.oaiPmhURL}}
</a>
</div>
<div *ngIf="dataProviderInfo.provenance?.size > 0" class="uk-display-inline-block">
<div class="uk-text-meta uk-margin-small-bottom">Detailed information @ </div>
<span *ngFor="let provenance of getKeys(dataProviderInfo.provenance); let i=index">
<a *ngIf="dataProviderInfo.provenance.get(provenance).url.length == 1" class="custom-external uk-link-text"
target="_blank" href="{{dataProviderInfo.provenance.get(provenance).url}}">
{{provenance}}
</a>
<ng-container *ngIf="dataProviderInfo.provenance.get(provenance).url.length > 1">
<span class="custom-external">{{provenance}}</span>
<ng-container *ngFor="let url of dataProviderInfo.provenance.get(provenance).url; let i=index">
[<a target="_blank" href="{{url}}">{{i}}</a>]
<ng-container>
<ng-container *ngTemplateOutlet="summary_content"></ng-container>
</ng-container>
</ng-container>
<span *ngIf="i < dataProviderInfo.provenance.size-1">, </span>
</span>
</div>
</div>
<div *ngIf="dataProviderInfo.organizations && dataProviderInfo.organizations.length > 0"
class="uk-margin-medium-bottom">
<div class="uk-text-meta uk-margin-small-bottom">{{openaireEntities.ORGANIZATIONS}}</div>
<ng-container *ngTemplateOutlet="organizations_template; context: { threshold: lessBtnOrganizations ? dataProviderInfo.organizations.length : thresholdOrganizations }"></ng-container>
<div *ngIf="dataProviderInfo.organizations.length > thresholdOrganizations && !lessBtnOrganizations"
class="uk-width-1-1 uk-text-right">
<a (click)="viewAllOrganizationsClick();" class="view-more-less-link">
View all {{dataProviderInfo.organizations.length | number}} organizations
</a>
</div>
<div *ngIf="viewAllOrganizations && lessBtnOrganizations" class="uk-width-1-1 uk-text-right">
<a (click)="viewAllOrganizations = !viewAllOrganizations; lessBtnOrganizations=false;" class="view-more-less-link">View less organizations</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Projects-->
<ng-container *ngIf="fetchProjects.searchUtils.totalResults > 0">
<div id="projects" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchProjects" resultType="project"
[params]="getParamsForSearchLink()"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedProjects"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<ng-container *ngTemplateOutlet="projects_content"></ng-container>
</ng-container>
<!-- Datasources -->
<ng-container *ngIf="fetchDataproviders.searchUtils.totalResults > 0">
<div id="datasources" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchDataproviders" resultType="dataprovider"
[params]="getParamsForSearchLink()"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedDataProviders"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<ng-container *ngTemplateOutlet="dataproviders_content"></ng-container>
</ng-container>
<!--Publications-->
<ng-container *ngIf="fetchPublications.searchUtils.totalResults > 0">
<div id="publications" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchPublications" resultType="publication"
[params]="getParamsForSearchLink('publications')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<ng-container *ngTemplateOutlet="publications_content"></ng-container>
</ng-container>
<!--Research Data-->
<ng-container *ngIf="fetchDatasets.searchUtils.totalResults > 0">
<div id="datasets" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchDatasets" resultType="dataset"
[params]="getParamsForSearchLink('datasets')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<ng-container *ngTemplateOutlet="datasets_content"></ng-container>
</ng-container>
<!--Software-->
<ng-container *ngIf="fetchSoftware.searchUtils.totalResults > 0">
<div id="software" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchSoftware" resultType="software"
[params]="getParamsForSearchLink('software')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<ng-container *ngTemplateOutlet="software_content"></ng-container>
</ng-container>
<!--Other-->
<ng-container *ngIf="fetchOrps.searchUtils.totalResults > 0">
<div id="other" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchOrps" resultType="other"
[params]="getParamsForSearchLink('other')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<ng-container *ngTemplateOutlet="other_content"></ng-container>
</ng-container>
<!--Related Datasources-->
<ng-container *ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)">
<div id="relatedDatasources" class="landing-section uk-padding uk-padding-remove-horizontal">
<relatedDatasourcesTab
[dataproviderId]="datasourceId"
[results]="dataProviderInfo.relatedDatasources"
[loading]="loadingRelatedDatasources"
[fetchResults]="fetchAggregatorsResults"
[collectedFromName]="dataProviderInfo.title.name"
[properties]=properties
[modal]="relatedDatasourcesModal" [prevPath]="prevPath">
</relatedDatasourcesTab>
</div>
<ng-container *ngTemplateOutlet="relatedDatasources_content"></ng-container>
</ng-container>
<ng-container *ngIf="dataProviderInfo && hasMetrics">
<ng-container *ngTemplateOutlet="metricsContent"></ng-container>
</ng-container>
<!--Statistics-->
<ng-container *ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)">
<div id="statistics" class="landing-section uk-padding uk-padding-remove-horizontal">
<div class="uk-text-meta uk-text-large uk-text-uppercase uk-margin-medium-bottom">Statistics</div>
<errorMessages [status]="[fetchPublications.searchUtils.status, fetchDatasets.searchUtils.status,
fetchSoftware.searchUtils.status, fetchOrps.searchUtils.status]"
[type]="'statistics'" tab_error_class=true></errorMessages>
<div *ngIf="statsClicked &&
(fetchPublications.searchUtils.status == errorCodes.DONE || fetchDatasets.searchUtils.status == errorCodes.DONE
|| fetchSoftware.searchUtils.status == errorCodes.DONE || fetchOrps.searchUtils.status == errorCodes.DONE)">
<statisticsTab [fetchPublications]="fetchPublications" [fetchDatasets]="fetchDatasets"
[fetchSoftware]="fetchSoftware" [fetchOther]="fetchOrps"
[datasourceId]="datasourceId">
</statisticsTab>
</div>
</div>
<ng-container *ngTemplateOutlet="statistics_content"></ng-container>
</ng-container>
</div>
<div class="uk-text-xsmall uk-hidden@m"><ng-container *ngTemplateOutlet="graph_and_feedback_template"></ng-container></div>
@ -454,6 +323,188 @@
</div>
</div>
</div>
</div>
<!-- Mobile view -->
<div *ngIf="isMobile" class="uk-hidden@m uk-position-relative landing">
<ng-container *ngIf="dataProviderInfo">
<div *ngIf="mobileContent == 'info'" class="uk-container uk-section">
<landing-header [properties]="properties" [title]="dataProviderInfo.title.name"
[subTitle]="(dataProviderInfo.officialName
&& dataProviderInfo.title.name !== dataProviderInfo.officialName)?dataProviderInfo.officialName:null"
[types]="dataProviderInfo.type ? [dataProviderInfo.type] : null"
[entityType]="getTypeName()"
[compatibility]="dataProviderInfo.compatibility"
[aggregationStatus]="dataProviderInfo.aggregationStatus"
[thematic]="dataProviderInfo.thematic" [type]="type"
[journal]="dataProviderInfo.journal" [prevPath]="prevPath">
</landing-header>
<div *ngIf="dataProviderInfo.title && dataProviderInfo.title.url"
class="uk-text-small uk-margin-small-top">
<span class="uk-text-meta">Web page: </span>
<a [href]="dataProviderInfo.title.url" target="_blank"
class="uk-button uk-button-text uk-text-lowercase uk-text-normal custom-external">
{{dataProviderInfo.title.url}}
</a>
</div>
<div *ngIf="dataProviderInfo.identifiers && dataProviderInfo.identifiers.size > 0" class="uk-margin-small-top uk-text-small">
<showIdentifiers [identifiers]="dataProviderInfo.identifiers" [showViewAll]="true"></showIdentifiers>
</div>
<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(summaryFsModal, 'Summary'); onSelectActiveTab('summary')">
<span>Summary</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchProjects.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(projectsFsModal, openaireEntities.PROJECTS); onSelectActiveTab('projects')">
<span>{{openaireEntities.PROJECTS}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchDataproviders.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(dataprovidersFsModal, openaireEntities.DATASOURCES); onSelectActiveTab('datasources')">
<span>{{openaireEntities.DATASOURCES}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchPublications.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(publicationsFsModal, 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.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(datasetsFsModal, 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.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(softwareFsModal, 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.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(otherFsModal, openaireEntities.OTHER); onSelectActiveTab('other')">
<span>{{openaireEntities.OTHER}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(relatedDatasourcesFsModal, 'Related '+openaireEntities.DATASOURCES); onSelectActiveTab('relatedDatasources')">
<span>Related {{openaireEntities.DATASOURCES}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(statisticsFsModal, 'Statistics'); onSelectActiveTab('statistics')">
<span>Statistics</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
</div>
</div>
<div *ngIf="mobileContent == 'metrics'" class="uk-container uk-section">
<ng-container *ngTemplateOutlet="metricsContent"></ng-container>
</div>
<div *ngIf="mobileContent == 'actions'" class="uk-container uk-section">
<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.DATASOURCE+' 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>
</div>
<div class="landing-action-bar-mobile uk-background-default">
<div class="uk-container uk-flex-middle uk-grid uk-text-xsmall uk-text-meta" [ngClass]="hasMetrics ? 'uk-child-width-1-3' : 'uk-child-width-1-2'">
<div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'">
<icon name="note_add" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"></icon>
<span>{{openaireEntities.DATASOURCE}}</span>
</a>
</div>
<div *ngIf="dataProviderInfo && hasMetrics">
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'metrics'">
<icon name="bar_chart" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'metrics' ? 'uk-text-primary': ''"></icon>
<span>Metrics</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>
<fs-modal #summaryFsModal classTitle="uk-tile-default uk-border-bottom" (cancelEmitter)="cancelSummaryClicked()">
<ng-container *ngTemplateOutlet="summary_content"></ng-container>
</fs-modal>
<fs-modal #projectsFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="fetchProjects.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="projects_content"></ng-container>
</fs-modal>
<fs-modal #dataprovidersFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="fetchDataproviders.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="dataproviders_content"></ng-container>
</fs-modal>
<fs-modal #publicationsFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="fetchPublications.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="publications_content"></ng-container>
</fs-modal>
<fs-modal #datasetsFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="fetchDatasets.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="datasets_content"></ng-container>
</fs-modal>
<fs-modal #softwareFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="fetchSoftware.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="software_content"></ng-container>
</fs-modal>
<fs-modal #otherFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="fetchOrps.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="other_content"></ng-container>
</fs-modal>
<fs-modal #relatedDatasourcesFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)">
<ng-container *ngTemplateOutlet="relatedDatasources_content"></ng-container>
</fs-modal>
<fs-modal #statisticsFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)">
<ng-container *ngTemplateOutlet="statistics_content"></ng-container>
</fs-modal>
</ng-container>
</div>
<feedback *ngIf="dataProviderInfo && properties.reCaptchaSiteKey" [dataProviderInfo]="dataProviderInfo"
[properties]="properties" [entityType]="getTypeName()" [fields]="feedbackFields"
@ -495,3 +546,324 @@
<modal-alert *ngIf="dataProviderInfo && dataProviderInfo.subjects" #subjectsModal>
<span>{{dataProviderInfo.subjects.join(", ")}}</span>
</modal-alert>
<ng-template #summary_content>
<div id="summary" class="landing-section landing-section-height-auto">
<div class="uk-grid uk-margin-remove-left uk-margin-medium-top uk-margin-medium-bottom" [ngClass]="isMobile ? '' : 'uk-card uk-card-default card-tab'">
<div *ngIf="!(hasPrimaryInfo || (!aggregationStatusIsInitialized || hasAggregationStatusInfo)) && !hasSecondaryInfo"
class="uk-width-expand uk-height-small uk-flex uk-flex-center uk-flex-middle">
<div class="uk-animation-fade uk-text-meta uk-text-large">
No summary information available
</div>
</div>
<div *ngIf="hasPrimaryInfo || (!aggregationStatusIsInitialized || hasAggregationStatusInfo)"
class="uk-width-expand uk-inline" [ngClass]="isMobile ? 'uk-padding-remove' : 'uk-padding'">
<!-- Description -->
<div *ngIf="dataProviderInfo.description && (!viewAllMobile || viewAllMobile == 'description')" class="uk-margin-medium-bottom">
<div class="uk-text-justify">
<div *ngIf="viewAllMobile != 'description'" class="uk-text-meta uk-margin-small-bottom">Description</div>
<div [ngClass]="viewAllMobile == 'description' ? '' : 'multi-line-ellipsis lines-10'">
<div #descriptionDiv class="uk-margin-small-bottom"
[innerHtml]="dataProviderInfo.description"></div>
</div>
<div *ngIf="showViewMoreButton && viewAllMobile != 'description'" class="uk-flex uk-flex-right">
<a (click)="viewAllDescriptionClicked();" class="view-more-less-link">
View more
</a>
</div>
</div>
</div>
<!-- <ul *ngIf="hasJournalInfo" class="uk-list uk-margin-medium-bottom uk-margin-remove-top">
<showPublisher [journal]="dataProviderInfo.journal" [properties]="properties"></showPublisher>
</ul> -->
<ng-container *ngIf="!viewAllMobile">
<div *ngIf="hasAggregationStatusInfo || (dataProviderInfo.fundedContent && dataProviderInfo.fundedContent > 0)"
class="uk-margin-medium-bottom uk-animation-fade uk-animation-fast">
<span *ngIf="dataProviderInfo.aggregationStatus?.fulltexts && dataProviderInfo.aggregationStatus?.fulltexts != -1"
class="uk-margin-right uk-display-inline-block">
<div class="uk-text-meta uk-margin-small-bottom">Collected full-texts</div>
{{dataProviderInfo.aggregationStatus.fulltexts | number}}
</span>
<span *ngIf="dataProviderInfo.fundedContent && dataProviderInfo.fundedContent > 0"
class="uk-display-inline-block">
<div class="uk-text-meta uk-margin-small-bottom">Results with funding information</div>
{{dataProviderInfo.fundedContent | number}}
</span>
</div>
<div *ngIf="!aggregationStatusIsInitialized || !dataProviderInfo.fundedContent"
class="uk-animation-fade uk-margin-top uk-width-1-1" role="alert">
<span class="loading-gif uk-align-center"></span>
</div>
<div *ngIf="dataProviderInfo.countries != undefined && dataProviderInfo.countries.length > 0"
class="uk-margin-medium-bottom">
<div class="uk-text-meta uk-margin-small-bottom">Countries</div>
{{dataProviderInfo.countries.join(", ")}}
</div>
<div *ngIf="dataProviderInfo.jurisdiction" class="uk-margin-medium-bottom">
<div class="uk-text-meta uk-margin-small-bottom">Jurisdiction</div>
{{dataProviderInfo.jurisdiction}}
</div>
<div *ngIf="dataProviderInfo.contentpolicy" class="uk-margin-medium-bottom">
<div class="uk-text-meta uk-margin-small-bottom">Content policy</div>
{{dataProviderInfo.contentpolicy}}
</div>
</ng-container>
<!-- Subjects -->
<div *ngIf="dataProviderInfo.subjects && dataProviderInfo.subjects.length > 0 && (!viewAllMobile || viewAllMobile == 'subjects')"
class="uk-margin-medium-bottom uk-margin-bottom">
<div class="uk-height-max-medium uk-overflow-auto">
<div *ngIf="viewAllMobile != 'subjects'" class="uk-text-meta uk-margin-small-bottom">Subjects </div>
<ng-container *ngIf="!viewAllMobile">
<span>{{dataProviderInfo.subjects.slice(0, lessBtnSubjects ? dataProviderInfo.subjects.length : thresholdSubjects).join(", ")}}</span>
<span *ngIf="dataProviderInfo.subjects.length > thresholdSubjects && !lessBtnSubjects"> ... </span>
</ng-container>
<ng-container *ngIf="viewAllMobile == 'subjects'">
<span>{{dataProviderInfo.subjects.join(", ")}}</span>
</ng-container>
</div>
<div *ngIf="dataProviderInfo.subjects.length > thresholdSubjects && !lessBtnSubjects && viewAllMobile != 'subjects'"
class="uk-width-1-1 uk-text-right">
<a (click)="viewAllSubjectsClick();" class="view-more-less-link">
View all {{dataProviderInfo.subjects.length | number}} subjects
</a>
</div>
<div *ngIf="viewAllSubjects && lessBtnSubjects" class="uk-width-1-1 uk-text-right">
<a (click)="viewAllSubjects = !viewAllSubjects; lessBtnSubjects=false;" class="view-more-less-link">View less subjects</a>
</div>
</div>
</div>
<div *ngIf="hasSecondaryInfo"
[class]="'uk-inline uk-padding-remove-horizontal ' + (hasPrimaryInfo?'uk-width-1-3@m': 'uk-width-expand')" [ngClass]="isMobile ? '' : 'uk-padding'">
<div class="uk-height-1-1" [ngClass]="isMobile ? '' : 'uk-padding uk-padding-remove-vertical'">
<div *ngIf="(dataProviderInfo.oaiPmhURL || dataProviderInfo.provenance?.size > 0) && !viewAllMobile"
class="uk-margin-medium-bottom">
<div *ngIf="dataProviderInfo.oaiPmhURL" class="uk-margin-medium-bottom">
<div class="uk-text-meta uk-margin-small-bottom">OAI-PMH</div>
<a target="_blank" href="{{dataProviderInfo.oaiPmhURL}}" class="custom-external">
{{dataProviderInfo.oaiPmhURL}}
</a>
</div>
<div *ngIf="dataProviderInfo.provenance?.size > 0" class="uk-display-inline-block">
<div class="uk-text-meta uk-margin-small-bottom">Detailed information @ </div>
<span *ngFor="let provenance of getKeys(dataProviderInfo.provenance); let i=index">
<a *ngIf="dataProviderInfo.provenance.get(provenance).url.length == 1" class="custom-external uk-link-text"
target="_blank" href="{{dataProviderInfo.provenance.get(provenance).url}}">
{{provenance}}
</a>
<ng-container *ngIf="dataProviderInfo.provenance.get(provenance).url.length > 1">
<span class="custom-external">{{provenance}}</span>
<ng-container *ngFor="let url of dataProviderInfo.provenance.get(provenance).url; let i=index">
[<a target="_blank" href="{{url}}">{{i}}</a>]
</ng-container>
</ng-container>
<span *ngIf="i < dataProviderInfo.provenance.size-1">, </span>
</span>
</div>
</div>
<div *ngIf="dataProviderInfo.organizations && dataProviderInfo.organizations.length > 0 && (!viewAllMobile || viewAllMobile == 'organizations')"
class="uk-margin-medium-bottom">
<div *ngIf="viewAllMobile != 'organizations'" class="uk-text-meta uk-margin-small-bottom">{{openaireEntities.ORGANIZATIONS}}</div>
<ng-container *ngTemplateOutlet="organizations_template; context: { threshold: (lessBtnOrganizations || viewAllMobile == 'organizations') ? dataProviderInfo.organizations.length : thresholdOrganizations }"></ng-container>
<div *ngIf="dataProviderInfo.organizations.length > thresholdOrganizations && !lessBtnOrganizations && viewAllMobile != 'organizations'"
class="uk-width-1-1 uk-text-right">
<a (click)="viewAllOrganizationsClick();" class="view-more-less-link">
View all {{dataProviderInfo.organizations.length | number}} organizations
</a>
</div>
<div *ngIf="viewAllOrganizations && lessBtnOrganizations" class="uk-width-1-1 uk-text-right">
<a (click)="viewAllOrganizations = !viewAllOrganizations; lessBtnOrganizations=false;" class="view-more-less-link">View less organizations</a>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template #projects_content>
<div id="projects" class="landing-section">
<search-tab [fetch]="fetchProjects" resultType="project"
[params]="getParamsForSearchLink()"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedProjects"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</ng-template>
<ng-template #dataproviders_content>
<div id="datasources" class="landing-section">
<search-tab [fetch]="fetchDataproviders" resultType="dataprovider"
[params]="getParamsForSearchLink()"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedDataProviders"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</ng-template>
<ng-template #publications_content>
<div id="publications" class="landing-section">
<search-tab [fetch]="fetchPublications" resultType="publication"
[params]="getParamsForSearchLink('publications')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</ng-template>
<ng-template #datasets_content>
<div id="datasets" class="landing-section">
<search-tab [fetch]="fetchDatasets" resultType="dataset"
[params]="getParamsForSearchLink('datasets')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</ng-template>
<ng-template #software_content>
<div id="software" class="landing-section">
<search-tab [fetch]="fetchSoftware" resultType="software"
[params]="getParamsForSearchLink('software')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</ng-template>
<ng-template #other_content>
<div id="other" class="landing-section">
<search-tab [fetch]="fetchOrps" resultType="other"
[params]="getParamsForSearchLink('other')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</ng-template>
<ng-template #relatedDatasources_content>
<div id="relatedDatasources" class="landing-section">
<relatedDatasourcesTab
[dataproviderId]="datasourceId"
[results]="dataProviderInfo.relatedDatasources"
[loading]="loadingRelatedDatasources"
[fetchResults]="fetchAggregatorsResults"
[collectedFromName]="dataProviderInfo.title.name"
[properties]=properties
[modal]="relatedDatasourcesModal" [prevPath]="prevPath">
</relatedDatasourcesTab>
</div>
</ng-template>
<ng-template #statistics_content>
<div id="statistics" class="landing-section">
<div class="uk-text-meta uk-text-large uk-text-uppercase uk-margin-medium-bottom">Statistics</div>
<errorMessages [status]="[fetchPublications.searchUtils.status, fetchDatasets.searchUtils.status,
fetchSoftware.searchUtils.status, fetchOrps.searchUtils.status]"
[type]="'statistics'" tab_error_class=true></errorMessages>
<div *ngIf="statsClicked &&
(fetchPublications.searchUtils.status == errorCodes.DONE || fetchDatasets.searchUtils.status == errorCodes.DONE
|| fetchSoftware.searchUtils.status == errorCodes.DONE || fetchOrps.searchUtils.status == errorCodes.DONE)">
<statisticsTab [fetchPublications]="fetchPublications" [fetchDatasets]="fetchDatasets"
[fetchSoftware]="fetchSoftware" [fetchOther]="fetchOrps"
[datasourceId]="datasourceId">
</statisticsTab>
</div>
</div>
</ng-template>
<ng-template #metricsContent>
<div id="metrics" class="landing-section">
<ul class="uk-subnav uk-subnav-pill-alt uk-margin-remove" uk-switcher>
<li class="uk-padding-remove">
<a href="#">Overview</a>
</li>
<li *ngIf="hasMetrics">
<a href="#" (click)="clickedUsageMetrics()">Usage</a>
</li>
</ul>
<ul class="uk-switcher uk-margin-large-top">
<!-- overview -->
<li>
<div *ngIf="hasMetrics">
<div class="uk-grid-divider" uk-grid>
<div>
<div class="uk-text-center uk-margin-small-bottom">
<a href='https://usagecounts.openaire.eu/' target='_blank'>
<img src="assets/common-assets/logo-small-usage-counts.png" loading="lazy" alt="OpenAIRE UsageCounts">
</a>
</div>
<span class="uk-text-uppercase uk-text-xsmall">Usage by</span>
<span class="uk-display-block uk-text-bolder">
<a href='https://usagecounts.openaire.eu/' target='_blank' class="uk-link-reset">UsageCounts</a>
</span>
</div>
<div>
<table class="uk-table uk-table-small">
<tbody>
<ng-container *ngFor="let measure of dataProviderInfo.measure.counts; let i = index">
<tr>
<td [class.uk-padding-remove-top]="i == 0" [class.uk-padding-remove-bottom]="i == dataProviderInfo.measure.counts.length - 1">
<icon [name]="measure.icon" [flex]="true" [ratio]="1.2" customClass="uk-text-background text-usage-counts"></icon>
</td>
<td class="uk-text-capitalize" [class.uk-padding-remove-top]="i == 0" [class.uk-padding-remove-bottom]="i == dataProviderInfo.measure.counts.length - 1">
{{measure.name}}
</td>
<td class="uk-text-uppercase uk-text-bolder" [class.uk-padding-remove-top]="i == 0" [class.uk-padding-remove-bottom]="i == dataProviderInfo.measure.counts.length - 1"
[attr.uk-tooltip]="measure.value >= 1000 ? 'cls: uk-active' : 'cls: uk-invisible'"
title="{{measure.value | number}}">
{{formatNumber(measure.value)}}
</td>
</tr>
</ng-container>
</tbody>
</table>
</div>
</div>
</div>
</li>
<!-- usage -->
<li *ngIf="hasMetrics">
<div class="uk-flex uk-flex-center uk-flex-middle uk-flex-wrap" [class.uk-flex-column]="isMobile">
<div class="uk-margin-large-right uk-flex uk-flex-center uk-flex-middle uk-flex-wrap" [class.uk-flex-column]="!isMobile">
<ng-container *ngFor="let measure of dataProviderInfo.measure.counts; let i = index">
<div *ngIf="measure.value" class="uk-text-center uk-margin-medium-bottom" [class.uk-margin-medium-right]="isMobile">
<div class="uk-text-background uk-text-bold number metrics-number"
[attr.uk-tooltip]="measure.value >= 1000 ? 'cls: uk-active' : 'cls: uk-invisible'"
title="{{measure.value | number}}">{{formatNumber(measure.value)}}</div>
<div class="uk-text-bold uk-text-capitalize">{{measure.name}}</div>
</div>
</ng-container>
</div>
<ng-container *ngIf="viewsFrameUrl || downloadsFrameUrl">
<div *ngIf="metricsClicked && viewsFrameUrl && hasViews" class="uk-margin-large-right">
<i-frame [height]="300" [url]="viewsFrameUrl" [addClass]="false"
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply uk-height-1-1">
</i-frame>
</div>
<div *ngIf="metricsClicked && downloadsFrameUrl && hasDownloads" class="uk-margin-large-right">
<i-frame [height]="300" [url]="downloadsFrameUrl" [addClass]="false"
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply uk-height-1-1"></i-frame>
</div>
</ng-container>
</div>
<div class="uk-text-center uk-margin-large-top">
<span class="uk-text-meta">Powered by</span>
<a href='https://usagecounts.openaire.eu/' target='_blank'>
<img class="uk-margin-small-left uk-margin-small-right uk-width-small" src="assets/common-assets/logo-large-usage-counts.png" loading="lazy" alt="OpenAIRE UsageCounts">
</a>
</div>
</li>
</ul>
</div>
</ng-template>
<fs-modal *ngIf="dataProviderInfo" #addThisFsModal classTitle="uk-tile-default uk-border-bottom" classBody="uk-flex uk-flex-center uk-flex-middle">
<addThis></addThis>
</fs-modal>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,29 +7,53 @@ import {RouterHelper} from "../../utils/routerHelper.class";
@Component({
selector: 'fundedBy',
template: `
<div class="uk-margin-small-bottom uk-flex uk-flex-between">
<div *ngIf="!isMobile" class="uk-margin-small-bottom uk-flex uk-flex-between">
<span *ngIf="viewAll && !lessBtn" class="clickable uk-h6 uk-flex uk-flex-middle" (click)="viewLessClick()">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
{{title}}
</span>
<span *ngIf="!viewAll || lessBtn" class="uk-text-light-grey">{{title}}</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;" class="view-more-less-link">View less</a>
<span *ngIf="!viewAll || lessBtn" class="uk-text-emphasis uk-text-bolder">{{title}}</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;"
class="view-more-less-link uk-link-text">View less</a>
<a *ngIf="fundedByProjects && fundedByProjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link">View all</a>
(click)="viewAllClick();" class="view-more-less-link uk-link-text">View all</a>
</div>
<div>
<div *ngIf="!isMobile">
<span *ngFor="let item of fundedByProjects.slice(0, viewAll?fundedByProjects.length:threshold) let i=index">
<span class="uk-text-emphasis">
<a class="uk-link uk-link-text">
<span
*ngIf="item['funderShortname'] || item['funderName']">{{item['funderShortname'] ? item['funderShortname'] : item['funderName']}}</span>
<span *ngIf="!item['funderShortname'] && !item['funderName']">[no funder available]</span>
<span
*ngIf="item['acronym'] || item['title']">| {{ item['acronym'] ? item['acronym'] : item['title']}}</span>
<ng-container *ngTemplateOutlet="funder; context: {item: item}"></ng-container>
</a>
</span>
<div class="default-dropdown uk-margin-remove-top uk-dropdown"
uk-dropdown="pos: bottom-left; mode:click">
<ng-container *ngTemplateOutlet="dropInfo; context: { item: item}"></ng-container>
</div>
<span *ngIf="i < (fundedByProjects.slice(0, viewAll?fundedByProjects.length:threshold).length - 1)">, </span>
</span>
</div>
<div *ngIf="isMobile">
<div *ngFor="let item of fundedByProjects.slice(0, viewAll?fundedByProjects.length:threshold) let i=index"
class="uk-flex uk-flex-between uk-flex-middle uk-margin-small-bottom">
<span class="uk-text-emphasis">
<ng-container *ngTemplateOutlet="funder; context: {item: item}"></ng-container>
</span>
<icon name="info" visuallyHidden="info" [type]="'outlined'" class="uk-link"></icon>
<div class="default-dropdown uk-margin-remove-top uk-dropdown"
uk-dropdown="pos: bottom-left; mode:click">
<ng-container *ngTemplateOutlet="dropInfo; context: { item: item}"></ng-container>
</div>
</div>
</div>
<ng-template #funder let-item=item>
<span
*ngIf="item['funderShortname'] || item['funderName']">{{item['funderShortname'] ? item['funderShortname'] : item['funderName']}}</span>
<span *ngIf="!item['funderShortname'] && !item['funderName']">[no funder available]</span>
<span *ngIf="item['acronym'] || item['title']">| {{ item['acronym'] ? item['acronym'] : item['title']}}</span>
</ng-template>
<ng-template #dropInfo let-item=item>
<div class="uk-padding-small">
<span>Project</span>
<div class="uk-margin-bottom">
@ -65,14 +89,12 @@ import {RouterHelper} from "../../utils/routerHelper.class";
<span *ngIf="item.provenanceAction">{{item.provenanceAction}}</span>
</div>
</div>
</div>
<span *ngIf="i < (fundedByProjects.slice(0, viewAll?fundedByProjects.length:threshold).length - 1)">, </span>
</span>
</div>
</ng-template>
`
})
export class FundedByComponent {
@Input() isMobile: boolean = false;
@Input() prevPath: string = "";
@Input() fundedByProjects: Project[];
@Input() viewAll: boolean = false;

View File

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

View File

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

View File

@ -1,5 +1,5 @@
import {HostedByCollectedFrom, Journal, Project, RelationResult} from "../../utils/result-preview/result-preview";
import {Context, Reference} from "../../utils/entities/resultLandingInfo";
import {HostedByCollectedFrom, Project, RelationResult} from "../../utils/result-preview/result-preview";
import {Context, Measure, Metric, Reference} from "../../utils/entities/resultLandingInfo";
import {Injectable} from '@angular/core';
import {properties} from "../../../../environments/environment";
import {StringUtils} from "../../utils/string-utils.class";
@ -15,15 +15,14 @@ export class ParsingFunctions {
{label: 'EOSC::Twitter Data', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'search.marketplace.eosc-portal.eu/search/service?q=*&fq=tag_list:%22EOSC%5C:%5C:Twitter%20Data%22', value: 'Twitter Data'},
{label: 'EOSC::Data Cube', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'search.marketplace.eosc-portal.eu/search/service?q=*&fq=tag_list:%22EOSC%5C:%5C:Data%20Cube%22', value: 'Data Cube'}
]
public notebookInSubjects: boolean = false;
private notebookKeyword: string = "eosc jupyter notebook";
private notebook_label: string = "EOSC";
private notebook_value: string = "EOSC Jupyter Notebook";
public open = 'lock_open';
public closed = 'lock';
public unknown = 'question_mark';
public open = 'open_access';
public closed = 'closed_access';
public unknown = 'unknown_access';
private instanceWithDoiExists: boolean = false;
@ -156,7 +155,7 @@ export class ParsingFunctions {
// publication & dataset landing : for downloadFrom
addPublisherToHostedBy_collectedFrom(hostedBy_collectedFrom: HostedByCollectedFrom[],
publisher: string, journal: Journal,
publisher: string, journal: string,
identifiers: Map<string, string[]>/*, title: { "name": string, "url": string, "accessMode": string}*/) {
if (!this.instanceWithDoiExists && publisher && identifiers != null && identifiers.has('doi')) {
if (hostedBy_collectedFrom == null) {
@ -172,13 +171,13 @@ export class ParsingFunctions {
accessRightIcon: ""
};
if (journal && journal.journal) {
if (journal) {
available.downloadNames.push(publisher + "/ " + journal['journal']);
} else {
available.downloadNames.push(publisher);
}
available.downloadUrl = properties.doiURL + identifiers.get("doi")[0];;
available.downloadUrl = properties.doiURL + identifiers.get("doi")[0];
available.accessRightIcon = this.unknown;
/*
if(title != undefined && title['url'] == "") {
@ -340,9 +339,11 @@ export class ParsingFunctions {
if (available.accessRight) {
if (available.accessRight.toLowerCase().indexOf('open') !== -1) {
available.accessRightIcon = this.open;
} else if (available.accessRight.toLowerCase().indexOf('not available') !== -1) {
}
else if (available.accessRight.toLowerCase().indexOf('not available') !== -1) {
available.accessRightIcon = this.unknown;
} else {
}
else {
available.accessRightIcon = this.closed;
}
} else {
@ -356,6 +357,42 @@ export class ParsingFunctions {
hostedBy_collectedFrom.push(available);
}
compareHostedByCollectedFrom(a: HostedByCollectedFrom, b: HostedByCollectedFrom) {
let firstAccessRight: string = (a.accessRight ? a.accessRight.toLowerCase() : null);
let secondAccessRight: string = (b.accessRight ? b.accessRight.toLowerCase() : null);
if (firstAccessRight === secondAccessRight) {
return 0;
} else {
if (firstAccessRight === 'open access') {
return -1;
} else if (secondAccessRight === 'open access') {
return 1;
} else if (firstAccessRight === "open source") {
return -1;
} else if (secondAccessRight === "open source") {
return 1;
} else if (firstAccessRight === "embargo") {
return -1;
} else if (secondAccessRight === "embargo") {
return 1;
} else if (firstAccessRight === "restricted") {
return -1;
} else if (secondAccessRight === "restricted") {
return 1;
} else if (firstAccessRight === "closed access") {
return -1;
} else if (secondAccessRight === "closed access") {
return 1;
} else if (firstAccessRight === "not available") {
return -1;
} else if (secondAccessRight === "not available") {
return 1;
}
}
return 0;
}
// publication & dataset landing : for downloadFrom and publishedIn
changeBestAccessMode(currentAccessMode: string, accessMode: any): boolean {
if (!accessMode) {
@ -658,9 +695,11 @@ export class ParsingFunctions {
}
}
} else if (category.label || (numOfCategories == 0 && z == (length2 - 1))) {
contexts[position] = {"labelContext": "", "idContext": "",
contexts[position] = {
"labelContext": "", "idContext": "",
"labelCategory": "", "idCategory": "",
"labelConcept": "", "idConcept": ""};
"labelConcept": "", "idConcept": ""
};
contexts[position]['labelContext'] = context.label;
contexts[position]['idContext'] = context.id;
contexts[position]['labelCategory'] = category.label ? category.label : null;
@ -672,9 +711,11 @@ export class ParsingFunctions {
}
}
} else {
contexts[position] = {"labelContext": "", "idContext": "",
contexts[position] = {
"labelContext": "", "idContext": "",
"labelCategory": "", "idCategory": "",
"labelConcept": "", "idConcept": ""};
"labelConcept": "", "idConcept": ""
};
contexts[position]['labelContext'] = context.label;
contexts[position]['idContext'] = context.id;
contexts[position]['labelCategory'] = null;
@ -688,11 +729,15 @@ export class ParsingFunctions {
}
return contexts;
}
public static getEnermapsConceptId(contexts: any): string {
let enermapsconcepts = contexts.filter(c=> {return c.idCategory == "enermaps::selection" && c.idConcept});
let enermapsconcepts = contexts.filter(c => {
return c.idCategory == "enermaps::selection" && c.idConcept
});
return enermapsconcepts && enermapsconcepts.length > 0 ? enermapsconcepts[0].idConcept.split("enermaps::selection::")[1] : null;
// return "hotmaps_heat_tot_curr_density"
}
parseTypes(types: string[], uniqueTypes: Set<string>, instance: any) {
if (instance && instance.hasOwnProperty("instancetype") && instance['instancetype'].classname) {
if (!uniqueTypes.has(instance['instancetype'].classname)) {
@ -727,7 +772,7 @@ export class ParsingFunctions {
countries.push(_countries.classname);
}
} else {
for (let i = 0; i < countries.length; i++) {
for (let i = 0; i < _countries.length; i++) {
if (_countries[i].classname != "Undetermined" && _countries[i].classname) {
countries.push(_countries[i].classname);
}
@ -775,6 +820,7 @@ export class ParsingFunctions {
});
return references;
}
static parseRelCanonicalId(record, type) {
try {
if (record["result"]["metadata"]["oaf:entity"][("oaf:" + type)]["children"] && record["result"]["metadata"]["oaf:entity"][("oaf:" + type)]["children"][type]) {
@ -798,7 +844,8 @@ export class ParsingFunctions {
}
try {
abstracts = abstracts.map(x => StringUtils.HTMLToString(x));
} catch (e) {}
} catch (e) {
}
abstracts = abstracts.sort((a, b) => b.length - a.length);
if (stripHTML) {
return abstracts.join(' ');
@ -806,4 +853,90 @@ export class ParsingFunctions {
return abstracts.length > 0 ? ('<p>' + abstracts.join('</p> <p>') + '</p>') : abstracts.join(' ');
}
}
parseMeasures(elements: any[]): Measure {
if (elements && elements.length) {
let bip: Metric[] = [];
let counts: Metric[] = [];
let measure: Measure = {};
elements.forEach(element => {
if (element.id == 'views') {
counts.push({name: 'views', icon: 'visibility', value: element.count, order: 0});
measure.views = element.count;
}
if (element.id == 'downloads') {
counts.push({name: 'downloads', icon: 'download', value: element.count, order: 1});
measure.downloads = element.count;
}
if (element.id == 'influence_alt') {
bip.push({name: 'citations', icon: 'cite', value: element.score, order: 2});
measure.citations = element.score;
}
if (element.id == 'popularity') {
let metric: Metric = {name: 'popularity', icon: 'fire', value: null, order: 3};
if (element.class == 'C1') {
metric.value = 'Top 0.01%';
} else if (element.class == 'C2') {
metric.value = 'Top 0.1%';
} else if (element.class == 'C3') {
metric.value = 'Top 1%';
} else if (element.class == 'C4') {
metric.value = 'Top 10%';
} else if (element.class == 'A') {
metric.value = 'Exceptional';
} else if (element.class == 'B') {
metric.value = 'Substantial';
} else {
metric.value = 'Average';
}
measure.popularity = metric.value;
bip.push(metric);
}
if (element.id == 'influence') {
let metric: Metric = {name: 'influence', icon: 'landmark', value: null, order: 4};
if (element.class == 'C1') {
metric.value = 'Top 0.01%';
} else if (element.class == 'C2') {
metric.value = 'Top 0.1%';
} else if (element.class == 'C3') {
metric.value = 'Top 1%';
} else if (element.class == 'C4') {
metric.value = 'Top 10%';
} else if (element.class == 'A') {
metric.value = 'Exceptional';
} else if (element.class == 'B') {
metric.value = 'Substantial';
} else {
metric.value = 'Average';
}
measure.influence = metric.value;
bip.push(metric);
}
if (element.id == 'impulse') {
let metric: Metric = {name: 'impulse', icon: 'rocket', value: null, order: 5};
if (element.class == 'C1') {
metric.value = 'Top 0.01%';
} else if (element.class == 'C2') {
metric.value = 'Top 0.1%';
} else if (element.class == 'C3') {
metric.value = 'Top 1%';
} else if (element.class == 'C4') {
metric.value = 'Top 10%';
} else if (element.class == 'A') {
metric.value = 'Exceptional';
} else if (element.class == 'B') {
metric.value = 'Substantial';
} else {
metric.value = 'Average';
}
measure.impulse = metric.value;
bip.push(metric);
}
});
measure.bip = bip.sort((a, b) => a.order - b.order);
measure.counts = counts.sort((a, b) => a.order - b.order);
return measure;
}
return null;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,15 +4,11 @@ import {EnvProperties} from "../../utils/properties/env-properties";
@Component({
selector: 'showPublisher, [showPublisher]',
template: `
<div *ngIf="publishDate || journal && (journal['journal'] || journal['issn'] || journal['lissn']
|| journal['volume'] || journal['eissn'] || journal['issue'])" class="uk-text-small">
<span *ngIf="publishDate" class="uk-margin-right">
<span class="uk-text-meta">Published: </span>
{{publishDate | date: 'dd MMM yyyy' : 'UTC'}}
</span>
<span *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
<ng-container *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
|| journal['volume'] || journal['eissn'] || journal['issue'])">
<span class="uk-text-meta">Journal: </span>
<ng-container *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
|| journal['volume'] || journal['eissn'] || journal['issue'])">
<span [attr.uk-tooltip]="'cls: uk-active'" [title]="'Journal'">
<span *ngIf="journal['journal']">{{journal['journal']}}</span>
<span *ngIf="journal['journal'] && (journal['volume'] || journal['issue'])">, </span>
<ng-container *ngIf="journal['volume']">
@ -67,14 +63,15 @@ import {EnvProperties} from "../../utils/properties/env-properties";
</span>
<span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])">)</span>
</span>
</div>
<div *ngIf="publisher" class="uk-text-small uk-margin-small-top">
<span class="uk-text-meta">Publisher: </span> {{publisher}}
</div>
</ng-container>
<span *ngIf="publisher" class="uk-margin-xsmall-left uk-margin-xsmall-right bullet"></span>
</ng-container>
<ng-container *ngIf="publisher">
<span [attr.uk-tooltip]="'cls: uk-active'" [title]="'Publisher'">{{publisher}}</span>
</ng-container>
`
})
export class ShowPublisherComponent {
@Input() publishDate: Date;
@Input() publisher;
@Input() journal;
//@Input() sherpaUrl = 'http://www.sherpa.ac.uk/romeo/search.php?issn=';

View File

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

View File

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

View File

@ -1,12 +1,12 @@
import {Component, Input} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {Component, ElementRef, Input, ViewChild} from '@angular/core';
@Component({
selector: 'showTitle',
template: `
<h1 [ngClass]="classNames" class="uk-h5">
<h1 [ngClass]="classNames" class="uk-h6">
<ng-container *ngTemplateOutlet="_title;"></ng-container>
</h1>
<ng-template #_title>
<div *ngIf="title != undefined" class="landingTitle uk-text-break">
<span *ngIf="title['url'] != undefined && title['url'] != null && title['url'] != ''"
@ -25,20 +25,19 @@ import {ActivatedRoute} from '@angular/router';
[innerHTML]="title['name']">
</span>
<span *ngIf="(title['name'] == undefined || title['name'] == '') &&
(title['url'] == undefined || title['url'] == null || title['url'] == '')"
>
(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 *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 {
@ -46,7 +45,12 @@ export class ShowTitleComponent {
@Input() title: { [key: string]: string };
@Input() iconClass:string;
@Input() classNames: string = "";
@Input() isSticky: boolean = false;
@ViewChild("titleDiv") titleDiv: ElementRef;
constructor () {}
get showTitleTooltip():boolean {
return !!this.titleDiv && (this.titleDiv.nativeElement.clientHeight >= 5 * 21);
}
}

View File

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

View File

@ -1,5 +1,6 @@
<div id="tm-main" class="landing uk-section uk-padding-remove tm-middle">
<div class="tm-main">
<!-- Desktop view -->
<div id="tm-main" class="uk-visible@m landing uk-section uk-padding-remove tm-middle">
<div *ngIf="!isMobile" class="tm-main">
<div class="organization">
<div *ngIf="properties.adminToolsPortalType == 'eosc'" class="eosc-explore-back-search-bar">
<div class="uk-light uk-container uk-container-large uk-padding-small uk-height-1-1">
@ -13,13 +14,12 @@
</div>
<div *ngIf="!showFeedback" class="uk-grid uk-margin-remove-left" uk-grid>
<!-- left column -->
<div id="landing-left-sidebar" *ngIf="organizationInfo" class="uk-visible@s uk-padding-remove-horizontal">
<!-- <div id="landing-left-sidebar" *ngIf="organizationInfo" class="uk-visible@s uk-padding-remove-horizontal">
<div class="uk-flex uk-flex-column uk-flex-right uk-sticky"
uk-sticky="bottom: true" [attr.offset]="offset">
<div class="uk-margin-large-bottom uk-align-center">
<div class="uk-text-meta uk-text-uppercase">Actions</div>
<ul class="uk-list">
<!-- Share -->
<li class="uk-text-center">
<a (click)="openAddThisModal()" [title]="'Share this '+openaireEntities.ORGANIZATION+' in your social networks'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
@ -28,7 +28,6 @@
</span>
</a>
</li>
<!-- Download -->
<li class="uk-text-center"
[title]="'Download reports'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
@ -41,20 +40,14 @@
</ul>
</div>
</div>
</div>
</div> -->
<!-- center/right column -->
<div class="uk-width-expand uk-padding-remove uk-background-default">
<div *ngIf="errorMessage.length > 0 || showLoading" class="uk-container uk-flex uk-flex-center uk-height-viewport uk-position-relative">
<div *ngIf="errorMessage.length > 0" class="uk-alert uk-alert-danger uk-width-2-3 uk-margin-xlarge-top"
role="alert">{{errorMessage}}</div>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
</div>
<div id="landing-center-content" class="uk-width-expand uk-padding-remove uk-background-default">
<!-- Graph and feedback -->
<ng-template #graph_and_feedback_template>
<div class="uk-flex uk-flex-between uk-flex-wrap uk-margin-small-bottom uk-margin-small-top" [class.uk-invisible]="!organizationInfo">
<div class="uk-container uk-container-xlarge uk-flex uk-flex-between uk-flex-wrap uk-margin-small-top uk-margin-small-bottom" [class.uk-invisible]="!organizationInfo">
<!-- Last Index Info-->
<a href="https://graph.openaire.eu" target="_blank" class="uk-width-1-1 uk-width-auto@l">
<img src="assets/common-assets/openaire-badge-1.png" alt="Powered by OpenAIRE graph" style="height: 15px;">
@ -70,12 +63,54 @@
</div>
</div>
</ng-template>
<div #graph_and_feedback id="graph_and_feedback" class="uk-padding uk-padding-remove-vertical uk-blur-background uk-text-xsmall uk-visible@m"
<div #graph_and_feedback id="graph_and_feedback" class="uk-blur-background uk-text-xsmall uk-visible@m"
uk-sticky="bottom: true;" [attr.offset]="graph_offset">
<ng-container *ngTemplateOutlet="graph_and_feedback_template"></ng-container>
</div>
<div class="uk-margin-large-left uk-margin-large-right" [style]="'margin-bottom: '+graph_height+'px'">
<div class="uk-container uk-container-xlarge">
<div *ngIf="errorMessage.length > 0 || showLoading" class="uk-container uk-flex uk-flex-center uk-height-viewport uk-position-relative">
<div *ngIf="errorMessage.length > 0" class="uk-alert uk-alert-danger uk-width-2-3 uk-margin-xlarge-top"
role="alert">{{errorMessage}}</div>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
</div>
<!-- new action bar -->
<div *ngIf="!showLoading && organizationInfo" class="uk-margin-top uk-margin-bottom">
<div class="uk-flex uk-flex-middle uk-flex-center">
<div class="landing-action-bar uk-box-shadow-small uk-margin-bottom">
<div class="uk-grid uk-grid-small uk-flex-between uk-text-xsmall uk-flex-middle uk-grid-divider" uk-grid>
<div *ngIf="organizationInfo?.deletedByInferenceIds" class="uk-width-auto">
<!-- Versions -->
<a (click)="openDeletedByInference()"
class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder">
<icon flex="true" ratio="0.8" name="versions" visuallyHidden="versions"></icon>
<span class="uk-margin-xsmall-left">
View all {{organizationInfo.deletedByInferenceIds.length}} versions
</span>
</a>
</div>
<div class="uk-width-expand">
<entity-actions [share]="true" [type]="'organization'">
<div>
<a (click)="buildFunderOptions(); openDownloadReportsModal()"
class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder">
<icon flex="true" ratio="0.8" name="download" visuallyHidden="download"></icon>
<span class="uk-margin-xsmall-left">Download</span>
</a>
</div>
</entity-actions>
</div>
</div>
</div>
</div>
</div>
<div class="uk-margin-left uk-margin-right" [style]="'margin-bottom: '+graph_height+'px'">
<ng-container *ngIf="organizationInfo">
<!-- Main content -->
<div [attr.style]="'margin-top: '+(graph_height? 'calc(40px + 20px - '+graph_height+'px)': '40px')">
@ -107,17 +142,17 @@
<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
[texts]="pageContents['top']"></helper>
<!-- Versions -->
<span *ngIf="organizationInfo.deletedByInferenceIds" class="uk-text-primary uk-flex uk-flex-middle">
<!-- <span *ngIf="organizationInfo.deletedByInferenceIds" class="uk-text-primary uk-flex uk-flex-middle">
<icon flex="true" ratio="0.8" name="auto_awesome_motion"></icon>
<a (click)="openDeletedByInference()" class="uk-text-primary uk-text-small uk-margin-small-left">
View all {{organizationInfo.deletedByInferenceIds.length}} versions
</a>
</span>
</span> -->
<!-- Landing header -->
<landing-header [properties]="properties" [title]="organizationInfo.title.name"
[subTitle]="(organizationInfo.name
&& organizationInfo.title.name !== organizationInfo.name)?organizationInfo.name:null"
[entityType]="'organization'">
[entityType]="'organization'" [prevPath]="prevPath">
</landing-header>
<!-- Basic info -->
<div class="uk-text-small">
@ -139,11 +174,9 @@
uk-sticky="bottom: true; media: @m" [attr.offset]="offset">
<div class="uk-padding uk-padding-remove-horizontal uk-padding-remove-bottom">
<!-- <showTitle *ngIf="stickyHeader" [titleName]="organizationInfo.title.name" classNames="uk-margin-remove-bottom" class="uk-visible@m"></showTitle>-->
<landing-header *ngIf="stickyHeader" class="uk-visible@m"
<landing-header [ngClass]="stickyHeader ? 'uk-visible@m' : 'uk-invisible'"
[properties]="properties" [title]="organizationInfo.title.name"
[subTitle]="(organizationInfo.name
&& organizationInfo.title.name !== organizationInfo.name)?organizationInfo.name:null"
[entityType]="'organization'" isSticky="true">
[entityType]="'organization'" isSticky="true" [prevPath]="prevPath">
</landing-header>
<my-tabs (selectedActiveTab)="onSelectActiveTab($event)" [offsetForSticky]="offset" [(isSticky)]="stickyHeader">
<my-tab [active]="true" [tabTitle]="'Funding / ' +openaireEntities.PROJECTS" [tabId]="'projects'"
@ -174,13 +207,13 @@
</div>
<!-- Tabs content section -->
<div id="landing-sections" class="uk-text-small">
<div id="projects" class="landing-section landing-section-height-auto uk-padding uk-padding-remove-horizontal">
<div id="projects" class="landing-section landing-section-height-auto">
<projectsInModal [fetchProjects]="fetchProjects"
[organizationId]="organizationId" [properties]=properties [prevPath]="prevPath">
</projectsInModal>
</div>
<div *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0"
id="dataProviders" class="landing-section uk-padding uk-padding-remove-horizontal">
id="dataProviders" class="landing-section">
<search-tab [fetch]="fetchDataproviders" resultType="dataprovider"
[params]="getParamsForSearchLink()"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedDataProviders"
@ -188,7 +221,7 @@
</search-tab>
</div>
<div *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0"
id="publications" class="landing-section uk-padding uk-padding-remove-horizontal">
id="publications" class="landing-section">
<search-tab [fetch]="fetchPublications" resultType="publication"
[params]="getParamsForSearchLink('publications')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
@ -196,7 +229,7 @@
</search-tab>
</div>
<div *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0"
id="datasets" class="landing-section uk-padding uk-padding-remove-horizontal">
id="datasets" class="landing-section">
<search-tab [fetch]="fetchDatasets" resultType="dataset"
[params]="getParamsForSearchLink('datasets')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
@ -204,7 +237,7 @@
</search-tab>
</div>
<div *ngIf="fetchSoftware && fetchSoftware.searchUtils.totalResults > 0"
id="software" class="landing-section uk-padding uk-padding-remove-horizontal">
id="software" class="landing-section">
<search-tab [fetch]="fetchSoftware" resultType="software"
[params]="getParamsForSearchLink('software')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
@ -212,7 +245,7 @@
</search-tab>
</div>
<div *ngIf="fetchOrps && fetchOrps.searchUtils.totalResults > 0"
id="other" class="landing-section uk-padding uk-padding-remove-horizontal">
id="other" class="landing-section">
<search-tab [fetch]="fetchOrps" resultType="other"
[params]="getParamsForSearchLink('other')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
@ -233,6 +266,7 @@
</div>
</div>
</div>
</div>
<!-- Feedback -->
<feedback *ngIf="organizationInfo && properties.reCaptchaSiteKey" [organizationInfo]="organizationInfo"
[properties]="properties" [entityType]="'organization'" [fields]="feedbackFields"
@ -240,6 +274,114 @@
</feedback>
</div>
<!-- Mobile view -->
<div *ngIf="isMobile" class="uk-hidden@m uk-position-relative landing">
<ng-container *ngIf="organizationInfo">
<div *ngIf="mobileContent == 'info'" class="uk-container uk-section">
<landing-header [properties]="properties" [title]="organizationInfo.title.name"
[subTitle]="(organizationInfo.name
&& organizationInfo.title.name !== organizationInfo.name)?organizationInfo.name:null"
[entityType]="'organization'" [prevPath]="prevPath">
</landing-header>
<div class="uk-section uk-margin-top uk-text-large uk-text-empashis uk-text-bold">
<hr>
<ng-container>
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(fsModal, 'Funding / '+openaireEntities.PROJECTS); onSelectActiveTab('projects')">
<span>Funding / {{openaireEntities.PROJECTS}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between"
(click)="openFsModal(fsModal, openaireEntities.DATASOURCES); onSelectActiveTab('dataProviders')">
<span>{{openaireEntities.DATASOURCES}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchPublications && fetchPublications.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between"
(click)="openFsModal(fsModal, openaireEntities.PUBLICATIONS); onSelectActiveTab('publications')">
<span>{{openaireEntities.PUBLICATIONS}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchDatasets && fetchDatasets.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between"
(click)="openFsModal(fsModal, openaireEntities.DATASETS); onSelectActiveTab('datasets')">
<span>{{openaireEntities.DATASETS}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchSoftware && fetchSoftware.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between"
(click)="openFsModal(fsModal, openaireEntities.SOFTWARE); onSelectActiveTab('software')">
<span>{{openaireEntities.SOFTWARE}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchOrps && fetchOrps.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between"
(click)="openFsModal(fsModal, openaireEntities.OTHER); onSelectActiveTab('other')">
<span>{{openaireEntities.OTHER}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
</div>
</div>
<div *ngIf="mobileContent == 'actions'" class="uk-container uk-section">
<ng-container *ngIf="organizationInfo?.deletedByInferenceIds">
<div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal"
(click)="deleteByInferenceOpened = true; openFsModal(alertModalDeletedByInferenceFS, 'Other versions')">
<icon [flex]="true" name="versions" visuallyHidden="versions"></icon>
<span class="uk-margin-small-left">
View all {{organizationInfo.deletedByInferenceIds.length}} versions
</span>
</div>
<hr class="uk-margin-remove">
</ng-container>
<ng-container>
<div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal"
(click)="openFsModal(addThisFsModal, 'Share this '+openaireEntities.ORGANIZATION+' in your social networks')">
<icon [flex]="true" name="share" visuallyHidden="share"></icon>
<span class="uk-margin-small-left">Share</span>
</div>
<hr class="uk-margin-remove">
</ng-container>
<ng-container>
<div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal"
(click)="buildFunderOptions(); openFsModal(downloadReportsFsModal, 'Download')">
<icon [flex]="true" name="download" visuallyHidden="download"></icon>
<span class="uk-margin-small-left">Download</span>
</div>
<hr class="uk-margin-remove">
</ng-container>
</div>
<div class="landing-action-bar-mobile uk-background-default">
<div class="uk-container uk-grid uk-flex-middle uk-child-width-1-2 uk-text-xsmall uk-text-meta">
<div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'">
<icon name="corporate_fare" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"></icon>
<span>{{openaireEntities.ORGANIZATION}}</span>
</a>
</div>
<div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'actions'">
<icon name="pending" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'actions' ? 'uk-text-primary': ''"></icon>
<span>Actions</span>
</a>
</div>
</div>
</div>
</ng-container>
</div>
<!-- MODALS -->
<!-- Other versions -->
<modal-alert #AlertModalDeletedByInference *ngIf="organizationInfo && organizationInfo.deletedByInferenceIds" large="true">
@ -259,6 +401,17 @@
<div class="uk-padding-small uk-margin-small-left uk-margin-small-right">
<div class="uk-padding-small uk-padding-remove-vertical">
<div class="uk-grid uk-grid-divider uk-child-width-1-2@m" uk-grid uk-height-match=".subtitle">
<ng-container *ngTemplateOutlet="downloadOptions"></ng-container>
</div>
</div>
</div>
</modal-alert>
<modal-alert #AlertModalApplyAll (alertOutput)="confirmCloseApplyAll()"></modal-alert>
<modal-alert #AlertModalCsvError></modal-alert>
<modal-loading [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>
@ -314,10 +467,11 @@
No reports available
</div>
</div>
<div>
<div class="subtitle uk-flex uk-flex-middle">
<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 uk-margin-small-left"
<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>
@ -345,10 +499,82 @@
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>
</modal-alert>
<modal-alert #AlertModalApplyAll (alertOutput)="confirmCloseApplyAll()"></modal-alert>
<modal-alert #AlertModalCsvError></modal-alert>
<modal-loading></modal-loading>
<div *ngIf="activeTab == 'dataProviders' && fetchDataproviders && fetchDataproviders.searchUtils.totalResults > 0"
class="landing-section">
<search-tab [fetch]="fetchDataproviders" resultType="dataprovider"
[params]="getParamsForSearchLink()"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedDataProviders"
[properties]="properties" [isMobile]="true" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="activeTab == 'publications' && fetchPublications && fetchPublications.searchUtils.totalResults > 0"
class="landing-section">
<search-tab [fetch]="fetchPublications" resultType="publication"
[params]="getParamsForSearchLink('publications')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [isMobile]="true" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="activeTab == 'datasets' && fetchDatasets && fetchDatasets.searchUtils.totalResults > 0"
class="landing-section">
<search-tab [fetch]="fetchDatasets" resultType="dataset"
[params]="getParamsForSearchLink('datasets')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [isMobile]="true" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="activeTab == 'software' && fetchSoftware && fetchSoftware.searchUtils.totalResults > 0"
class="landing-section">
<search-tab [fetch]="fetchSoftware" resultType="software"
[params]="getParamsForSearchLink('software')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [isMobile]="true" [prevPath]="prevPath">
</search-tab>
</div>
<div *ngIf="activeTab == 'other' && fetchOrps && fetchOrps.searchUtils.totalResults > 0"
class="landing-section">
<search-tab [fetch]="fetchOrps" resultType="other"
[params]="getParamsForSearchLink('other')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [isMobile]="true" [prevPath]="prevPath">
</search-tab>
</div>
</fs-modal>

View File

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

View File

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

View File

@ -1,5 +1,6 @@
<div class="landing uk-section uk-padding-remove tm-middle">
<div class="tm-main">
<!-- Desktop view -->
<div class=" uk-visible@m landing uk-section uk-padding-remove tm-middle">
<div *ngIf="!isMobile" class="tm-main">
<div class="project">
<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">
@ -14,7 +15,7 @@
<div *ngIf="!showFeedback" class="uk-grid uk-margin-remove-left" uk-grid>
<!-- left box - actions -->
<div id="landing-left-sidebar" *ngIf="projectInfo" class="uk-visible@s uk-padding-remove-horizontal">
<!-- <div id="landing-left-sidebar" *ngIf="projectInfo" class="uk-visible@s uk-padding-remove-horizontal">
<div class="uk-flex uk-flex-column uk-flex-between uk-flex-center uk-sticky"
uk-sticky="bottom: true" [attr.offset]="offset">
<div class="uk-align-center uk-text-center uk-margin-medium-top uk-flex uk-flex-column uk-flex-between">
@ -29,7 +30,6 @@
<div class="uk-margin-large-bottom uk-align-center">
<div class="uk-text-meta uk-text-uppercase">Actions</div>
<ul class="uk-list">
<!-- Share -->
<li class="uk-text-center">
<a (click)="openAddThisModal()"
[title]="'Share this '+openaireEntities.PROJECT+' in your social networks'"
@ -39,7 +39,6 @@
</span>
</a>
</li>
<!-- Link to -->
<li *ngIf="isRouteAvailable('participate/direct-claim')" class="uk-text-center"
[title]="'<span class=\'uk-flex uk-flex-middle\'>Link this project to '+openaireEntities.RESULTS+'<span class=\'material-icons uk-margin-small-left\'>east</span></span>'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
@ -67,7 +66,6 @@
<icon name="code_off" visuallyHidden="code"></icon>
</span>
</a>
</li>
<li class="uk-text-center"
[title]="'Download report'"
@ -81,20 +79,13 @@
</ul>
</div>
</div>
</div>
</div> -->
<!-- center box-->
<div class="uk-width-expand uk-padding-remove uk-background-default">
<div *ngIf="errorMessage.length > 0 || showLoading" class="uk-container uk-flex uk-flex-center uk-height-viewport uk-position-relative">
<div *ngIf="errorMessage.length > 0" class="uk-alert uk-alert-danger uk-width-2-3 uk-margin-xlarge-top"
role="alert">{{errorMessage}}</div>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
</div>
<div id="landing-center-content" class="uk-width-expand uk-padding-remove uk-background-default">
<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]="!projectInfo">
<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]="!projectInfo">
<!-- Last Index Info-->
<a href="https://graph.openaire.eu" target="_blank" class="uk-width-1-1 uk-width-auto@l">
<img src="assets/common-assets/openaire-badge-1.png" alt="Powered by OpenAIRE graph" style="height: 15px;">
@ -111,14 +102,43 @@
</div>
</ng-template>
<div #graph_and_feedback id="graph_and_feedback" class="uk-padding uk-padding-remove-vertical uk-blur-background uk-text-xsmall uk-visible@m"
<div #graph_and_feedback id="graph_and_feedback" class="uk-blur-background uk-text-xsmall uk-visible@m"
uk-sticky="bottom: true;" [attr.offset]="graph_offset">
<ng-container *ngTemplateOutlet="graph_and_feedback_template"></ng-container>
</div>
<div class="uk-margin-large-left uk-margin-large-right" [style]="'margin-bottom: '+graph_height+'px'">
<div class="uk-container uk-container-xlarge">
<div *ngIf="errorMessage.length > 0 || showLoading" class="uk-container uk-flex uk-flex-center uk-height-viewport uk-position-relative">
<div *ngIf="errorMessage.length > 0" class="uk-alert uk-alert-danger uk-width-2-3 uk-margin-xlarge-top"
role="alert">{{errorMessage}}</div>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
</div>
<!-- new action bar -->
<div *ngIf="!showLoading && projectInfo" class="uk-visible@s uk-margin-top uk-margin-bottom">
<div class="uk-flex uk-flex-middle uk-flex-center">
<div class="landing-action-bar uk-text-xsmall uk-box-shadow-small uk-margin-bottom">
<entity-actions [deposit]="true" [share]="true" [linking]="true" [embed]="true"
[type]="'project'" [result]="projectInfo" [id]="projectInfo.id">
<div>
<a (click)="openDownloadReportModal()"
class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder">
<icon flex="true" ratio="0.8" name="download" visuallyHidden="download"></icon>
<span class="uk-margin-xsmall-left">Download</span>
</a>
</div>
</entity-actions>
</div>
</div>
</div>
<div class="uk-margin-left uk-margin-right" [style]="'margin-bottom: '+graph_height+'px'">
<ng-container *ngIf="projectInfo">
<div [attr.style]="'margin-top: '+(graph_height? 'calc(40px + 20px - '+graph_height+'px)': '40px')">
<div class="uk-grid uk-grid-small" uk-grid>
<div class="uk-width-expand">
<!-- schema.org-->
<schema2jsonld [data]=projectInfo
[URL]="properties.domain+properties.baseLink+properties.searchLinkToProject+projectId"
@ -158,7 +178,7 @@
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'">
<a class="uk-link-text uk-text-bold uk-text-uppercase" (click)="openEmbedResultsModal()">
<span class="uk-icon-button uk-icon landing-action-button landing-action-button-portal">
<icon name="code_off" visuallyHidden="code"></icon>
<icon name="code" visuallyHidden="code"></icon>
</span>
</a>
</div>
@ -178,12 +198,14 @@
<landing-header [properties]="properties" [title]="projectName"
[subTitle]="projectInfo.acronym ? projectInfo.title : ''"
[entityType]="'project'"
[startDate]="projectInfo.startDate"
[endDate]="projectInfo.endDate"
[status]="projectInfo.status">
[startDate]="projectInfo.startDate" [endDate]="projectInfo.endDate"
[currentDate]="projectInfo.currentDate" [status]="projectInfo.status"
[openAccessMandatePublications]="projectInfo.openAccessMandatePublications"
[openAccessMandateDatasets]="projectInfo.openAccessMandateDatasets" [prevPath]="prevPath">
</landing-header>
<!-- Labels -->
<div class="uk-margin-bottom uk-grid uk-grid-small uk-flex-middle" uk-grid>
<!-- To be moved inside the landing-header -->
<!-- <div class="uk-margin-bottom uk-grid uk-grid-small uk-flex-middle" uk-grid>
<ng-container *ngIf="projectInfo.openAccessMandatePublications != undefined && projectInfo.openAccessMandatePublications && projectInfo.openAccessMandateDatasets != undefined && projectInfo.openAccessMandateDatasets">
<div>
<span class="uk-label uk-label-success uk-text-truncate"
@ -213,12 +235,7 @@
</span>
</div>
</ng-container>
<!-- <ng-container *ngIf="projectInfo.specialClause39">-->
<!-- <span class="uk-label custom-label label-sc39" title="Special Clause 39">-->
<!-- Special Clause 39-->
<!-- </span>&#160;-->
<!-- </ng-container>-->
</div>
</div> -->
<div class="uk-text-small">
<div *ngIf="projectInfo.funding" class="uk-margin-bottom">
<div class="uk-margin-small-bottom">
@ -252,13 +269,13 @@
</span>
</div>
</div>
<div *ngIf="projectInfo.status" class="uk-margin-right">
<!-- <div *ngIf="projectInfo.status" class="uk-margin-right">
<span>
<span class="uk-text-meta">Status: </span>
<span class="uk-text-secondary">{{projectInfo.status}}</span>
</span>
</div>
<div *ngIf="projectInfo.startDate || projectInfo.endDate" class="uk-width-large uk-margin-bottom">
</div> -->
<!-- <div *ngIf="projectInfo.startDate || projectInfo.endDate" class="uk-width-large uk-margin-bottom">
<progress *ngIf="projectInfo.startDate && projectInfo.endDate"
class="uk-progress uk-box-shadow-inner uk-margin-small-top uk-margin-small-bottom"
[value]="(projectInfo.currentDate > projectInfo.startDate ? projectInfo.currentDate-projectInfo.startDate : 0)"
@ -275,7 +292,7 @@
<ng-container *ngIf="projectInfo.currentDate < projectInfo.endDate">(Ending)</ng-container>
</span>
</div>
</div>
</div> -->
<div *ngIf="projectInfo.urlInfo" class="uk-margin-bottom">
<a target="_blank" href="{{projectInfo.url}}" class="uk-button uk-button-text custom-external uk-text-capitalize uk-text-normal">
{{projectInfo.urlInfo}}
@ -300,19 +317,62 @@
</div>
</div>
</div>
<div *ngIf="projectInfo && hasMetrics" class="uk-width-1-1 uk-width-medium@s">
<div class="landing-metrics-card uk-card uk-card-secondary uk-text-small uk-flex uk-padding-small">
<div class="uk-width-expand uk-flex uk-flex-middle">
<div class="uk-grid uk-grid-small uk-flex-nowrap" uk-grid uk-height-match="target: > div > .cell">
<div>
<ng-container>
<ng-container *ngFor="let measure of projectInfo.measure.counts; let i = index">
<div *ngIf="measure.value" class="cell uk-flex uk-flex-middle" [class.uk-margin-xsmall-bottom]="i != projectInfo.measure.counts.length - 1">
<icon [name]="measure.icon" [ratio]="0.8" [flex]="true"></icon>
</div>
</ng-container>
</ng-container>
</div>
<div>
<ng-container *ngFor="let measure of projectInfo.measure.counts; let i = index">
<div *ngIf="measure.value" class="cell" [class.uk-margin-xsmall-bottom]="i != projectInfo.measure.counts.length - 1">
<a class="uk-text-capitalize">{{measure.name}}</a>
<ng-container *ngTemplateOutlet="dropInfo; context: {option: measure.name, isCompact: false}"></ng-container>
</div>
</ng-container>
</div>
<ng-template #dropInfo let-option=option>
<div class="uk-dropdown" uk-dropdown="pos: bottom-left; mode:click; container: #modal-container;">
<div class="uk-padding-small uk-width-medium uk-text-small" [innerHTML]="getMetricsTooltip(option) | safeHtml">
</div>
</div>
</ng-template>
<div class="uk-text-uppercase uk-text-bolder">
<ng-container *ngFor="let measure of projectInfo.measure.counts; let i = index">
<div *ngIf="measure.value" [attr.uk-tooltip]="measure.value >= 1000 ? 'cls: uk-active' : 'cls: uk-invisible'"
title="{{measure.value | number}}" class="cell" [class.uk-margin-xsmall-bottom]="i != projectInfo.measure.counts.length - 1">
{{formatNumber(measure.value)}}
</div>
</ng-container>
</div>
</div>
</div>
<div class="uk-width-1-5 uk-flex uk-flex-bottom">
<img src="assets/common-assets/metrics-badge.svg" loading="lazy" alt="Metrics badge">
</div>
</div>
</div>
</div>
</div>
<div id="main-tabs-div" class="uk-sticky uk-blur-background"
uk-sticky="bottom: true; media: @m" [attr.offset]="offset">
<div class="uk-padding uk-padding-remove-horizontal uk-padding-remove-bottom">
<!-- <showTitle *ngIf="stickyHeader" [titleName]="projectName" classNames="uk-margin-remove-bottom" class="uk-visible@m"></showTitle>-->
<landing-header *ngIf="stickyHeader" class="uk-visible@m"
<landing-header [ngClass]="stickyHeader ? 'uk-visible@m' : 'uk-invisible'"
[properties]="properties" [title]="projectName"
[subTitle]="projectInfo.acronym ? projectInfo.title : ''"
[entityType]="'project'"
[startDate]="projectInfo.startDate"
[endDate]="projectInfo.endDate"
[status]="projectInfo.status"
isSticky="true">
isSticky="true" [prevPath]="prevPath">
</landing-header>
<my-tabs (selectedActiveTab)="onSelectActiveTab($event)" [offsetForSticky]="offset" [(isSticky)]="stickyHeader">
<my-tab tabTitle="Summary" [tabId]="'summary'" [active]="true"></my-tab>
@ -328,7 +388,10 @@
<my-tab *ngIf="fetchOrps.searchUtils.totalResults > 0"
[tabTitle]="openaireEntities.OTHER" [tabNumber]="fetchOrps.searchUtils.totalResults"
[tabId]="'other'"></my-tab>
<my-tab [tabTitle]="'Dmps'" [tabNumber]="fetchDmps.searchUtils.totalResults > 0 ? fetchDmps.searchUtils.totalResults : ''" [tabId]="'dmps'"></my-tab>
<my-tab [tabTitle]="'DMPs'" [tabNumber]="fetchDmps.searchUtils.totalResults > 0 ? fetchDmps.searchUtils.totalResults : ''" [tabId]="'dmps'"></my-tab>
<my-tab *ngIf="projectInfo && hasMetrics"
[tabTitle]="'Metrics'" [tabId]="'metrics'">
</my-tab>
<my-tab *ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)"
[tabTitle]="'Statistics'" customClass="statistics" [tabId]="'statistics'" [active]="false"></my-tab>
@ -337,160 +400,30 @@
</div>
<div id="landing-sections" class="uk-text-small">
<div id="summary" class="landing-section landing-section-height-auto">
<div class="uk-card uk-card-default card-tab uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-card-body">
<div class="uk-grid uk-grid-divider" uk-grid>
<div *ngIf="!hasPrimaryInfo && !hasSecondaryInfo" class="uk-width-expand uk-height-small uk-flex uk-flex-center uk-flex-middle">
<div class="uk-animation-fade uk-text-meta uk-text-large">
No summary information available
</div>
</div>
<div *ngIf="hasPrimaryInfo" class="uk-width-expand">
<!-- Description -->
<div *ngIf="projectInfo.description" class="uk-margin-medium-bottom">
<div class="uk-text-justify ">
<div class="uk-text-meta uk-margin-small-bottom">Description</div>
<div class="multi-line-ellipsis lines-10">
<div #descriptionDiv class="uk-margin-small-bottom"
[innerHtml]="projectInfo.description"></div>
</div>
<div *ngIf="showViewMoreButton" class="uk-flex uk-flex-right">
<a (click)="openDescriptionModal();" class="view-more-less-link">
View more
</a>
</div>
</div>
</div>
</div>
<div *ngIf="hasSecondaryInfo" [class.uk-width-1-3@m]="hasPrimaryInfo" class="uk-width-1-1">
<div class="uk-height-1-1">
<!-- Organizations -->
<div class="uk-text-meta uk-margin-small-bottom">Partners</div>
<div class="uk-margin-medium-bottom">
<ng-container *ngTemplateOutlet="organizations_template; context: { threshold: lessBtnOrganizations ? projectInfo.organizations.length : thresholdOrganizations }"></ng-container>
<div *ngIf="projectInfo.organizations.length > thresholdOrganizations && !lessBtnOrganizations"
class="uk-text-center">
<a (click)="viewAllOrganizationsClick();" class="view-more-less-link">
View all
</a>
</div>
<div *ngIf="viewAllOrganizations && lessBtnOrganizations" class="uk-text-center">
<a (click)="viewAllOrganizations = !viewAllOrganizations; lessBtnOrganizations=false;" class="view-more-less-link">View less</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-container *ngIf="fetchPublications.searchUtils.totalResults > 0">
<div id="publications" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchPublications" resultType="publication"
[params]="getParamsForSearchLink('publications')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<ng-container>
<ng-container *ngTemplateOutlet="summary_content"></ng-container>
</ng-container>
<ng-container *ngIf="fetchPublications.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="publications_content"></ng-container>
</ng-container>
<ng-container *ngIf="fetchDatasets.searchUtils.totalResults > 0">
<div id="datasets" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchDatasets" resultType="dataset"
[params]="getParamsForSearchLink('datasets')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<ng-container *ngTemplateOutlet="datasets_content"></ng-container>
</ng-container>
<ng-container *ngIf="fetchSoftware.searchUtils.totalResults > 0">
<div id="software" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchSoftware" resultType="software"
[params]="getParamsForSearchLink('software')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<ng-container *ngTemplateOutlet="software_content"></ng-container>
</ng-container>
<ng-container *ngIf="fetchOrps.searchUtils.totalResults > 0">
<div id="other" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchOrps" resultType="other"
[params]="getParamsForSearchLink('other')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
<ng-container *ngTemplateOutlet="other_content"></ng-container>
</ng-container>
<ng-container>
<div id="dmps" class="landing-section uk-padding uk-padding-remove-horizontal">
<search-tab [fetch]="fetchDmps" customTitle="Data Management Plans"
[properties]="properties" resultType="DMPs" [prevPath]="prevPath">
<div class="uk-margin-medium-top uk-margin-bottom uk-width-1-1 uk-flex uk-flex-center uk-flex-middle">
<a *ngIf="properties.adminToolsPortalType == 'eosc' && fetchDmps.searchUtils.totalResults > 0"
class="uk-button uk-button-text uk-margin-right custom-external"
[href]="'https://explore.openaire.eu'+properties.searchLinkToAdvancedResults+
'?f0=relprojectid&fv0='+projectId+'&type=publications&instancetypename=Data Management Plan&qf=false&sortBy=resultdateofacceptance,descending'"
target="_blank">
View all in OpenAIRE
</a>
<a *ngIf="properties.adminToolsPortalType != 'eosc' && fetchDmps.searchUtils.totalResults > 0" class="uk-button uk-button-text uk-margin-right"
[queryParams]="getParamsForSearchLink('publications', 'Data Management Plan')"
[routerLink]="properties.searchLinkToAdvancedResults">
View all
<span *ngIf="fetchDmps.searchUtils.totalResults <= searchNumber">in search page</span>
</a>
<a class="uk-button uk-button-text custom-external" href="https://argos.openaire.eu/splash/" target="_blank">
<img src="assets/common-assets/common/argos_entities.svg"
alt="argos" width="20px" height="20px" loading="lazy">
Start a new DMP in <span class="text-argos">Argos</span>
</a>
</div>
</search-tab>
</div>
<ng-container *ngTemplateOutlet="dmps_content"></ng-container>
</ng-container>
<ng-container *ngIf="projectInfo && hasMetrics">
<ng-container *ngTemplateOutlet="metricsContent"></ng-container>
</ng-container>
<ng-container *ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)">
<div id="statistics" class="landing-section uk-padding uk-padding-remove-horizontal">
<div class="uk-text-meta uk-text-large uk-text-uppercase uk-margin-medium-bottom">Statistics</div>
<errorMessages [status]="[fetchPublications.searchUtils.status, fetchDatasets.searchUtils.status,
fetchSoftware.searchUtils.status, fetchOrps.searchUtils.status]"
[type]="'statistics'" tab_error_class=true></errorMessages>
<div
*ngIf="statsClicked &&
(fetchPublications.searchUtils.status == errorCodes.DONE || fetchDatasets.searchUtils.status == errorCodes.DONE
|| fetchSoftware.searchUtils.status == errorCodes.DONE || fetchOrps.searchUtils.status == errorCodes.DONE)"
class="uk-grid uk-child-width-1-1 uk-child-width-1-2@m">
<div class="uk-padding uk-padding-remove-top">
<div class="uk-card uk-card-default uk-card-body">
<div *ngIf="!properties.useNewStatistisTool" class="uk-text-center uk-text-large">Produced
{{openaireEntities.RESULTS}} per year
</div>
<i-frame [url]=chartScientificResultsUrl
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply"></i-frame>
</div>
</div>
<div class="uk-padding uk-padding-remove-top">
<div class="uk-card uk-card-default uk-card-body">
<div *ngIf="!properties.useNewStatistisTool" class="uk-text-center uk-text-large">Access mode of
{{openaireEntities.RESULTS}}
</div>
<i-frame [url]=chartAccessModeUrl
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply"></i-frame>
</div>
</div>
<div class="uk-padding uk-padding-remove-top">
<div class="uk-card uk-card-default uk-card-body">
<div *ngIf="!properties.useNewStatistisTool" class="uk-text-center uk-text-large">
{{openaireEntities.RESULTS}} per datasource
</div>
<i-frame [url]=chartDatasourcesUrl
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply"></i-frame>
</div>
</div>
</div>
</div>
<ng-container *ngTemplateOutlet="statistics_content"></ng-container>
</ng-container>
</div>
@ -502,9 +435,188 @@
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Mobile view -->
<div *ngIf="isMobile" class="uk-hidden@m uk-position-relative landing">
<ng-container *ngIf="projectInfo">
<div *ngIf="mobileContent == 'info'" class="uk-container uk-section">
<landing-header [properties]="properties" [title]="projectName"
[subTitle]="projectInfo.acronym ? projectInfo.title : ''"
[entityType]="'project'"
[startDate]="projectInfo.startDate" [endDate]="projectInfo.endDate"
[currentDate]="projectInfo.currentDate" [status]="projectInfo.status"
[openAccessMandatePublications]="projectInfo.openAccessMandatePublications"
[openAccessMandateDatasets]="projectInfo.openAccessMandateDatasets" [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(summaryFsModal, 'Summary'); onSelectActiveTab('summary')">
<span>Summary</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="fetchPublications.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(publicationsFsModal, 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.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(datasetsFsModal, 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.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(softwareFsModal, 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.searchUtils.totalResults > 0">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(otherFsModal, openaireEntities.OTHER); onSelectActiveTab('other')">
<span>{{openaireEntities.OTHER}}</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container>
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(dmpsFsModal, 'DMPs'); onSelectActiveTab('dmps')">
<span>DMPs</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
<ng-container *ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(statisticsFsModal, 'Statistics'); onSelectActiveTab('statistics')">
<span>Statistics</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div>
<hr>
</ng-container>
</div>
</div>
<div *ngIf="mobileContent == 'metrics'" class="uk-container uk-section">
<ng-container *ngTemplateOutlet="metricsContent"></ng-container>
</div>
<div *ngIf="mobileContent == 'actions'" class="uk-container uk-section">
<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.PROJECT+' 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 *ngIf="isRouteAvailable('participate/deposit/learn-how')">
<a class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal"
routerLinkActive="router-link-active" routerLink="/participate/deposit/learn-how">
<icon [flex]="true" name="upload" visuallyHidden="upload"></icon>
<span class="uk-margin-small-left">
Deposit
</span>
</a>
<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(embedResultsFsModal, 'Embed results')">
<icon [flex]="true" name="code" visuallyHidden="code"></icon>
<span class="uk-margin-small-left">Embed</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(downloadReportFsModal, 'Download report')">
<icon [flex]="true" name="download" visuallyHidden="download"></icon>
<span class="uk-margin-small-left">Download</span>
</div>
<hr class="uk-margin-remove">
</ng-container>
<ng-container *ngIf="isRouteAvailable('participate/direct-claim')">
<a class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal"
[queryParams]="routerHelper.createQueryParams(['id','type','linkTo'],[projectId, 'project','result'])"
routerLinkActive="router-link-active" routerLink="/participate/direct-claim">
<icon [flex]="true" name="link_to" visuallyHidden="link"></icon>
<span class="uk-margin-small-left">
Link to
</span>
</a>
<hr class="uk-margin-remove">
</ng-container>
</div>
<div class="landing-action-bar-mobile uk-background-default">
<div class="uk-container uk-flex-middle uk-grid uk-text-xsmall uk-text-meta" [ngClass]="hasMetrics ? 'uk-child-width-1-3' : 'uk-child-width-1-2'">
<div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'">
<icon name="assignment_turned_in" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"></icon>
<span>{{openaireEntities.PROJECT}}</span>
</a>
</div>
<div *ngIf="projectInfo && hasMetrics">
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'metrics'">
<icon name="bar_chart" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'metrics' ? 'uk-text-primary': ''"></icon>
<span>Metrics</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>
<fs-modal #summaryFsModal classTitle="uk-tile-default uk-border-bottom" (cancelEmitter)="cancelSummaryClicked()">
<ng-container *ngTemplateOutlet="summary_content"></ng-container>
</fs-modal>
<fs-modal #publicationsFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="fetchPublications.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="publications_content"></ng-container>
</fs-modal>
<fs-modal #datasetsFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="fetchDatasets.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="datasets_content"></ng-container>
</fs-modal>
<fs-modal #softwareFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="fetchSoftware.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="software_content"></ng-container>
</fs-modal>
<fs-modal #otherFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="fetchOrps.searchUtils.totalResults > 0">
<ng-container *ngTemplateOutlet="other_content"></ng-container>
</fs-modal>
<fs-modal #dmpsFsModal classTitle="uk-tile-default uk-border-bottom">
<ng-container *ngTemplateOutlet="dmps_content"></ng-container>
</fs-modal>
<fs-modal #statisticsFsModal classTitle="uk-tile-default uk-border-bottom"
*ngIf="(fetchPublications.searchUtils.totalResults > 0 || fetchDatasets.searchUtils.totalResults > 0
|| fetchSoftware.searchUtils.totalResults > 0 || fetchOrps.searchUtils.totalResults > 0)">
<ng-container *ngTemplateOutlet="statistics_content"></ng-container>
</fs-modal>
</ng-container>
</div>
<feedback *ngIf="projectInfo && properties.reCaptchaSiteKey" [projectInfo]="projectInfo"
[properties]="properties" [entityType]="'project'" [title]="projectName" [fields]="feedbackFields"
@ -518,51 +630,11 @@
</modal-alert>
<modal-alert *ngIf="projectInfo" #embedResultsModal large="true">
<div class="uk-padding-small uk-margin-small-left uk-margin-small-right">
<div class="uk-padding-small uk-padding-remove-vertical">
<div input type="select" placeholder="Select content type to embed" inputClass="flat x-small"
[options]="resultTypesForEmbedding" [(value)]="embed_research_results_type"></div>
<div *ngIf="embed_research_results_type" class="clipboard-wrapper box-content uk-grid uk-margin-auto uk-margin-small-top ">
<pre id="dynamic_content_id" class="uk-overflow-auto uk-padding-small uk-padding-remove-vertical uk-margin-top"><code
>{{getDynamicContent(embed_research_results_type)}}</code></pre>
<div class="uk-width-1-1 uk-padding-small uk-text-right">
<a class="uk-link copy clipboard_btn" data-clipboard-target="#dynamic_content_id" title="Copy script">
COPY SCRIPT
</a>
</div>
</div>
<div class="uk-text-small uk-margin-top">
For further information contact us at
<u><a [href]="'mailto:'+properties.helpdeskEmail" class="uk-link-text">{{properties.helpdeskEmail}}</a></u>
</div>
</div>
</div>
<ng-container *ngTemplateOutlet="embed_content"></ng-container>
</modal-alert>
<modal-alert *ngIf="projectInfo" #downloadReportModal>
<div class="uk-padding-small uk-margin-small-left uk-margin-small-right">
<div class="uk-padding-small uk-padding-remove-vertical">
<div input type="select" placeholder="Select content type report to download" inputClass="flat x-small"
[options]="resultTypesForDownloading" [(value)]="download_research_results_type" (click)="buildResultTypesForDownloading()"></div>
<div *ngIf="download_research_results_type" class="uk-animation-slide-top-small uk-margin-medium-top">
<ng-container *ngTemplateOutlet="download_research_results_box;
context: { type: download_research_results_type,
fileName_type: getFileNameType(download_research_results_type),
csvParams: getCsvParams(download_research_results_type) }">
</ng-container>
</div>
<div *ngIf="!projectInfo.funding ||
(fetchPublications.searchUtils.totalResults == 0 &&
fetchDatasets.searchUtils.totalResults == 0 &&
fetchSoftware.searchUtils.totalResults == 0 &&
fetchOrps.searchUtils.totalResults == 0)"
class="uk-text-meta uk-margin-medium-top uk-text-center">
No reports available
</div>
</div>
</div>
<ng-container *ngTemplateOutlet="download_content"></ng-container>
</modal-alert>
<ng-template #download_research_results_box
@ -612,3 +684,306 @@
</span>
<span *ngIf="projectInfo.organizations.length > threshold"> ... </span>
</ng-template>
<ng-template #summary_content>
<div id="summary" class="landing-section landing-section-height-auto">
<div class="uk-margin-medium-top uk-margin-medium-bottom" [ngClass]="isMobile ? '' : 'uk-card uk-card-default card-tab'">
<div [ngClass]="isMobile ? '' : 'uk-card-body'">
<div class="uk-grid uk-grid-divider" uk-grid>
<div *ngIf="!hasPrimaryInfo && !hasSecondaryInfo" class="uk-width-expand uk-height-small uk-flex uk-flex-center uk-flex-middle">
<div class="uk-animation-fade uk-text-meta uk-text-large">
No summary information available
</div>
</div>
<div *ngIf="hasPrimaryInfo && viewAllMobile != 'organizations'" class="uk-width-expand">
<!-- Description -->
<div *ngIf="projectInfo.description && (!viewAllMobile || viewAllMobile == 'description')" class="uk-margin-medium-bottom">
<div class="uk-text-justify">
<div *ngIf="viewAllMobile != 'description'" class="uk-text-meta uk-margin-small-bottom">Description</div>
<div [ngClass]="viewAllMobile == 'description' ? '' : 'multi-line-ellipsis lines-10'">
<div #descriptionDiv class="uk-margin-small-bottom"
[innerHtml]="projectInfo.description"></div>
</div>
<div *ngIf="showViewMoreButton && viewAllMobile != 'description'" class="uk-flex uk-flex-right">
<a (click)="viewAllDescriptionClicked();" class="view-more-less-link">
View more
</a>
</div>
</div>
</div>
</div>
<div *ngIf="hasSecondaryInfo && viewAllMobile != 'description'" [class.uk-width-1-3@m]="hasPrimaryInfo" class="uk-width-1-1">
<div class="uk-height-1-1">
<!-- Organizations -->
<div *ngIf="viewAllMobile != 'organizations'" class="uk-text-meta uk-margin-small-bottom">Partners</div>
<div class="uk-margin-medium-bottom">
<ng-container *ngTemplateOutlet="organizations_template; context: { threshold: lessBtnOrganizations ? projectInfo.organizations.length : thresholdOrganizations }"></ng-container>
<div *ngIf="projectInfo.organizations.length > thresholdOrganizations && !lessBtnOrganizations"
class="uk-text-center">
<a (click)="viewAllOrganizationsClick();" class="view-more-less-link uk-visible@m">
View all
</a>
<a (click)="viewAllOrganizationsMobileClicked()" class="view-more-less-link uk-hidden@m">
View all
</a>
</div>
<div *ngIf="viewAllOrganizations && lessBtnOrganizations" class="uk-text-center">
<a (click)="viewAllOrganizations = !viewAllOrganizations; lessBtnOrganizations=false;" class="view-more-less-link">View less</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template #publications_content>
<div id="publications" class="landing-section">
<search-tab [fetch]="fetchPublications" resultType="publication"
[params]="getParamsForSearchLink('publications')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</ng-template>
<ng-template #datasets_content>
<div id="datasets" class="landing-section">
<search-tab [fetch]="fetchDatasets" resultType="dataset"
[params]="getParamsForSearchLink('datasets')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</ng-template>
<ng-template #software_content>
<div id="software" class="landing-section">
<search-tab [fetch]="fetchSoftware" resultType="software"
[params]="getParamsForSearchLink('software')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</ng-template>
<ng-template #other_content>
<div id="other" class="landing-section">
<search-tab [fetch]="fetchOrps" resultType="other"
[params]="getParamsForSearchLink('other')"
[searchLinkToAdvancedPage]="properties.searchLinkToAdvancedResults"
[properties]="properties" [prevPath]="prevPath">
</search-tab>
</div>
</ng-template>
<ng-template #dmps_content>
<div id="dmps" class="landing-section">
<search-tab [fetch]="fetchDmps" customTitle="Data Management Plans"
[properties]="properties" resultType="DMPs" [prevPath]="prevPath">
<div class="uk-margin-medium-top uk-margin-bottom uk-width-1-1 uk-flex uk-flex-center uk-flex-middle">
<a *ngIf="fetchDmps.searchUtils.totalResults > 0" class="uk-button uk-button-text uk-margin-right"
[queryParams]="getParamsForSearchLink('publications', 'Data Management Plan')"
[routerLink]="properties.searchLinkToAdvancedResults">
View all
<span *ngIf="fetchDmps.searchUtils.totalResults <= searchNumber">in search page</span>
</a>
<a class="uk-button uk-button-text custom-external" href="https://argos.openaire.eu/splash/" target="_blank">
<img src="assets/common-assets/common/argos_entities.svg"
alt="argos" width="20px" height="20px" loading="lazy">
Start a new DMP in <span class="text-argos">Argos</span>
</a>
</div>
</search-tab>
</div>
</ng-template>
<ng-template #statistics_content>
<div id="statistics" class="landing-section">
<div class="uk-text-meta uk-text-large uk-text-uppercase uk-margin-medium-bottom">Statistics</div>
<errorMessages [status]="[fetchPublications.searchUtils.status, fetchDatasets.searchUtils.status,
fetchSoftware.searchUtils.status, fetchOrps.searchUtils.status]"
[type]="'statistics'" tab_error_class=true></errorMessages>
<div
*ngIf="statsClicked &&
(fetchPublications.searchUtils.status == errorCodes.DONE || fetchDatasets.searchUtils.status == errorCodes.DONE
|| fetchSoftware.searchUtils.status == errorCodes.DONE || fetchOrps.searchUtils.status == errorCodes.DONE)"
class="uk-grid uk-child-width-1-1 uk-child-width-1-2@m">
<div class="uk-padding uk-padding-remove-top">
<div class="uk-card uk-card-default uk-card-body">
<div *ngIf="!properties.useNewStatistisTool" class="uk-text-center uk-text-large">Produced
{{openaireEntities.RESULTS}} per year
</div>
<i-frame [url]=chartScientificResultsUrl
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply"></i-frame>
</div>
</div>
<div class="uk-padding uk-padding-remove-top">
<div class="uk-card uk-card-default uk-card-body">
<div *ngIf="!properties.useNewStatistisTool" class="uk-text-center uk-text-large">Access mode of
{{openaireEntities.RESULTS}}
</div>
<i-frame [url]=chartAccessModeUrl
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply"></i-frame>
</div>
</div>
<div class="uk-padding uk-padding-remove-top">
<div class="uk-card uk-card-default uk-card-body">
<div *ngIf="!properties.useNewStatistisTool" class="uk-text-center uk-text-large">
{{openaireEntities.RESULTS}} per datasource
</div>
<i-frame [url]=chartDatasourcesUrl
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply"></i-frame>
</div>
</div>
</div>
</div>
</ng-template>
<ng-template #metricsContent>
<div id="metrics" class="landing-section">
<ul class="uk-subnav uk-subnav-pill-alt uk-margin-remove" uk-switcher>
<li class="uk-padding-remove">
<a href="#">Overview</a>
</li>
<li *ngIf="hasMetrics">
<a href="#" (click)="clickedUsageMetrics()">Usage</a>
</li>
</ul>
<ul class="uk-switcher uk-margin-large-top">
<!-- overview -->
<li>
<div *ngIf="hasMetrics">
<div class="uk-grid-divider" uk-grid>
<div>
<div class="uk-text-center uk-margin-small-bottom">
<a href='https://usagecounts.openaire.eu/' target='_blank'>
<img src="assets/common-assets/logo-small-usage-counts.png" loading="lazy" alt="OpenAIRE UsageCounts">
</a>
</div>
<span class="uk-text-uppercase uk-text-xsmall">Usage by</span>
<span class="uk-display-block uk-text-bolder">
<a href='https://usagecounts.openaire.eu/' target='_blank' class="uk-link-reset">UsageCounts</a>
</span>
</div>
<div>
<table class="uk-table uk-table-small">
<tbody>
<ng-container *ngFor="let measure of projectInfo.measure.counts; let i = index">
<tr>
<td [class.uk-padding-remove-top]="i == 0" [class.uk-padding-remove-bottom]="i == projectInfo.measure.counts.length - 1">
<icon [name]="measure.icon" [flex]="true" [ratio]="1.2" customClass="uk-text-background text-usage-counts"></icon>
</td>
<td class="uk-text-capitalize" [class.uk-padding-remove-top]="i == 0" [class.uk-padding-remove-bottom]="i == projectInfo.measure.counts.length - 1">
{{measure.name}}
</td>
<td class="uk-text-uppercase uk-text-bolder" [class.uk-padding-remove-top]="i == 0" [class.uk-padding-remove-bottom]="i == projectInfo.measure.counts.length - 1"
[attr.uk-tooltip]="measure.value >= 1000 ? 'cls: uk-active' : 'cls: uk-invisible'"
title="{{measure.value | number}}">
{{formatNumber(measure.value)}}
</td>
</tr>
</ng-container>
</tbody>
</table>
</div>
</div>
</div>
</li>
<!-- usage -->
<li *ngIf="hasMetrics">
<div class="uk-flex uk-flex-center uk-flex-middle uk-flex-wrap" [class.uk-flex-column]="isMobile">
<div class="uk-margin-large-right uk-flex uk-flex-center uk-flex-middle uk-flex-wrap" [class.uk-flex-column]="!isMobile">
<ng-container *ngFor="let measure of projectInfo.measure.counts; let i = index">
<div *ngIf="measure.value" class="uk-text-center uk-margin-medium-bottom" [class.uk-margin-medium-right]="isMobile">
<div class="uk-text-background uk-text-bold number metrics-number"
[attr.uk-tooltip]="measure.value >= 1000 ? 'cls: uk-active' : 'cls: uk-invisible'"
title="{{measure.value | number}}">{{formatNumber(measure.value)}}</div>
<div class="uk-text-bold uk-text-capitalize">{{measure.name}}</div>
</div>
</ng-container>
</div>
<ng-container *ngIf="viewsFrameUrl || downloadsFrameUrl">
<div *ngIf="metricsClicked && viewsFrameUrl && hasViews" class="uk-margin-large-right">
<i-frame [height]="300" [url]="viewsFrameUrl" [addClass]="false"
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply uk-height-1-1">
</i-frame>
</div>
<div *ngIf="metricsClicked && downloadsFrameUrl && hasDownloads" class="uk-margin-large-right">
<i-frame [height]="300" [url]="downloadsFrameUrl" [addClass]="false"
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply uk-height-1-1"></i-frame>
</div>
</ng-container>
</div>
<div class="uk-text-center uk-margin-large-top">
<span class="uk-text-meta">Powered by</span>
<a href='https://usagecounts.openaire.eu/' target='_blank'>
<img class="uk-margin-small-left uk-margin-small-right uk-width-small" src="assets/common-assets/logo-large-usage-counts.png" loading="lazy" alt="OpenAIRE UsageCounts">
</a>
</div>
</li>
</ul>
</div>
</ng-template>
<fs-modal *ngIf="projectInfo" #addThisFsModal classTitle="uk-tile-default uk-border-bottom" classBody="uk-flex uk-flex-center uk-flex-middle">
<addThis></addThis>
</fs-modal>
<fs-modal *ngIf="projectInfo" #embedResultsFsModal classTitle="uk-tile-default uk-border-bottom" classBody="uk-flex uk-flex-center uk-flex-middle">
<ng-container *ngTemplateOutlet="embed_content"></ng-container>
</fs-modal>
<fs-modal *ngIf="projectInfo" #downloadReportFsModal classTitle="uk-tile-default uk-border-bottom" classBody="uk-flex uk-flex-center uk-flex-middle">
<ng-container *ngTemplateOutlet="download_content"></ng-container>
</fs-modal>
<ng-template #embed_content>
<div [ngClass]="isMobile ? 'uk-width-1-1' : 'uk-padding-small uk-margin-small-left uk-margin-small-right'">
<div [ngClass]="isMobile ? '' : 'uk-padding-small uk-padding-remove-vertical'">
<div input type="select" placeholder="Select content type to embed" inputClass="flat x-small"
[options]="resultTypesForEmbedding" [(value)]="embed_research_results_type"></div>
<div *ngIf="embed_research_results_type" class="clipboard-wrapper box-content uk-grid uk-margin-auto uk-margin-small-top ">
<pre id="dynamic_content_id" class="uk-overflow-auto uk-padding-small uk-padding-remove-vertical uk-margin-top"><code
>{{getDynamicContent(embed_research_results_type)}}</code></pre>
<div class="uk-width-1-1 uk-padding-small uk-text-right">
<a class="uk-link copy clipboard_btn" data-clipboard-target="#dynamic_content_id" title="Copy script">
COPY SCRIPT
</a>
</div>
</div>
<div class="uk-text-small uk-margin-top">
For further information contact us at
<u><a [href]="'mailto:'+properties.helpdeskEmail" class="uk-link-text">{{properties.helpdeskEmail}}</a></u>
</div>
</div>
</div>
</ng-template>
<ng-template #download_content>
<div [ngClass]="isMobile ? 'uk-width-1-1' : 'uk-padding-small uk-margin-small-left uk-margin-small-right'">
<div [ngClass]="isMobile ? '' : 'uk-padding-small uk-padding-remove-vertical'">
<div input type="select" placeholder="Select content type report to download" inputClass="flat x-small"
[options]="resultTypesForDownloading" [(value)]="download_research_results_type" (click)="buildResultTypesForDownloading()"></div>
<div *ngIf="download_research_results_type" class="uk-animation-slide-top-small uk-margin-medium-top">
<ng-container *ngTemplateOutlet="download_research_results_box;
context: { type: download_research_results_type,
fileName_type: getFileNameType(download_research_results_type),
csvParams: getCsvParams(download_research_results_type) }">
</ng-container>
</div>
<div *ngIf="!projectInfo.funding ||
(fetchPublications.searchUtils.totalResults == 0 &&
fetchDatasets.searchUtils.totalResults == 0 &&
fetchSoftware.searchUtils.totalResults == 0 &&
fetchOrps.searchUtils.totalResults == 0)"
class="uk-text-meta uk-margin-medium-top uk-text-center">
No reports available
</div>
</div>
</div>
</ng-template>

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -33,9 +33,14 @@ import {MatFormFieldModule} from "@angular/material/form-field";
import {MatSelectModule} from "@angular/material/select";
import {IconsModule} from "../../utils/icons/icons.module";
import {IconsService} from "../../utils/icons/icons.service";
import {graph, link, quotes} from "../../utils/icons/icons";
import {cite, fire, graph, landmark, link, link_to, quotes, rocket, versions} from "../../utils/icons/icons";
import {InputModule} from "../../sharedComponents/input/input.module";
import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.module";
import {RecaptchaModule} from 'ng-recaptcha';
import {SdgFosSuggestModule} from '../landing-utils/sdg-fos-suggest/sdg-fos-suggest.module';
import {FullScreenModalModule} from "../../utils/modal/full-screen-modal/full-screen-modal.module";
import {SafeHtmlPipeModule} from '../../utils/pipes/safeHTMLPipe.module';
import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.module";
@NgModule({
imports: [
@ -44,7 +49,8 @@ import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.modul
MetricsModule, AltMetricsModule, Schema2jsonldModule, SEOServiceModule,
DeletedByInferenceModule, ShowAuthorsModule, HelperModule, ResultLandingUtilsModule, AlertModalModule,
AnnotationModule, LandingHeaderModule, NoLoadPaging, ResultPreviewModule, FeedbackModule, TabsModule, LoadingModule,
OrcidModule, MatFormFieldModule, MatSelectModule, IconsModule, InputModule, EGIDataTransferModule
OrcidModule, MatFormFieldModule, MatSelectModule, IconsModule, InputModule, EGIDataTransferModule, RecaptchaModule,
SdgFosSuggestModule, FullScreenModalModule, SafeHtmlPipeModule, EntityActionsModule
],
declarations: [
ResultLandingComponent
@ -58,6 +64,6 @@ import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.modul
})
export class ResultLandingModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([link, graph, quotes])
this.iconsService.registerIcons([link, graph, quotes, cite, link_to, versions, rocket, fire, landmark])
}
}

View File

@ -127,7 +127,6 @@ export class ResultLandingService {
parseResultLandingInfo(data: any, subjectsVocabulary: any, properties: EnvProperties): any {
this.resultLandingInfo = new ResultLandingInfo();
// res
this.resultLandingInfo.record = data[15];
this.resultLandingInfo.objIdentifier = data[15]["result"]["header"]["dri:objIdentifier"];
@ -240,9 +239,7 @@ export class ResultLandingService {
url = instance['webresource'][0].url;
}
if (url.includes('&amp;')) {
let regExp = /&amp;/gmu;
let newUrl = url.replace(regExp, '&');
url = newUrl;
url = url.replace(/&amp;/gmu, '&');
}
/**********************************************************/
@ -254,41 +251,7 @@ export class ResultLandingService {
}
/* Order Download from via openness*/
this.resultLandingInfo.hostedBy_collectedFrom.sort((a, b) => {
let firstAccessRight: string = (a.accessRight ? a.accessRight.toLowerCase() : null);
let secondAccessRight: string = (b.accessRight ? b.accessRight.toLowerCase() : null);
if (firstAccessRight === secondAccessRight) {
return 0;
} else {
if (firstAccessRight === 'open access') {
return -1;
} else if (secondAccessRight === 'open access') {
return 1;
} else if (firstAccessRight === "open source") {
return -1;
} else if (secondAccessRight === "open source") {
return 1;
} else if (firstAccessRight === "embargo") {
return -1;
} else if (secondAccessRight === "embargo") {
return 1;
} else if (firstAccessRight === "restricted") {
return -1;
} else if (secondAccessRight === "restricted") {
return 1;
} else if (firstAccessRight === "closed access") {
return -1;
} else if (secondAccessRight === "closed access") {
return 1;
} else if (firstAccessRight === "not available") {
return -1;
} else if (secondAccessRight === "not available") {
return 1;
}
}
return 0;
});
this.resultLandingInfo.hostedBy_collectedFrom.sort(this.parsingFunctions.compareHostedByCollectedFrom);
}
if (data[3].hasOwnProperty("externalreference")) {
@ -304,7 +267,16 @@ export class ResultLandingService {
// res['result']['metadata']['oaf:entity']['oaf:result']['journal']
if (data[5] != null) {
this.resultLandingInfo.journal = {"journal": "", "issn": "", "lissn": "", "eissn": "", "issue": "", "volume": "", "start_page": "", "end_page": ""}
this.resultLandingInfo.journal = {
"journal": "",
"issn": "",
"lissn": "",
"eissn": "",
"issue": "",
"volume": "",
"start_page": "",
"end_page": ""
}
this.resultLandingInfo.journal['journal'] = data[5].content;
this.resultLandingInfo.journal['issn'] = data[5].issn;
@ -340,9 +312,13 @@ export class ResultLandingService {
this.resultLandingInfo.subjects = subjectResults[0];
this.resultLandingInfo.otherSubjects = subjectResults[1];
this.resultLandingInfo.classifiedSubjects = subjectResults[2];
this.resultLandingInfo.fos = subjectResults[3];
if (subjectResults[3]) {
subjectResults[3].forEach(element => {
this.resultLandingInfo.fos.push({id: element, label: element.replace(/^\d+/, '').trim()});
});
}
if (this.resultLandingInfo.fos) {
this.resultLandingInfo.fos.sort((a, b) => a.localeCompare(b))
this.resultLandingInfo.fos.sort((a, b) => a.id.localeCompare(b.id));
}
this.resultLandingInfo.sdg = subjectResults[4];
if (this.resultLandingInfo.sdg) {
@ -358,7 +334,7 @@ export class ResultLandingService {
this.resultLandingInfo.hostedBy_collectedFrom = this.parsingFunctions.addPublisherToHostedBy_collectedFrom(
this.resultLandingInfo.hostedBy_collectedFrom, this.resultLandingInfo.publisher,
this.resultLandingInfo.journal, this.resultLandingInfo.identifiers);
this.resultLandingInfo.journal?.journal, this.resultLandingInfo.identifiers);
// res['result']['metadata']['oaf:entity']['oaf:result']['programmingLanguage']
if (data[12] != null) {
@ -400,7 +376,11 @@ export class ResultLandingService {
if (author.orcid_pending) {
author.orcid_pending = author.orcid_pending.toUpperCase();
}
this.resultLandingInfo['authors'][author.rank] = {"fullName": author.content, "orcid": author.orcid, "orcid_pending": author.orcid_pending};
this.resultLandingInfo['authors'][author.rank] = {
"fullName": author.content,
"orcid": author.orcid,
"orcid_pending": author.orcid_pending
};
}
}
this.resultLandingInfo.authors = this.resultLandingInfo.authors.filter(function (item) {
@ -408,6 +388,11 @@ export class ResultLandingService {
});
}
// res['result']['metadata']['oaf:entity']['oaf:result']['measure']
if (data[0]?.measure) {
this.resultLandingInfo.measure = this.parsingFunctions.parseMeasures(data[0].measure);
}
this.resultLandingInfo.relatedResults = this.parsingFunctions.sortByPercentage(this.resultLandingInfo.relatedResults);
return this.resultLandingInfo;
@ -418,7 +403,8 @@ export class ResultLandingService {
organizations = []
}
let organization: { "name": string, "shortname": string,
let organization: {
"name": string, "shortname": string,
"id": string, "websiteUrl": string,
"country": string, "trust": number
} = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,13 +4,10 @@ import {BehaviorSubject, from, Observable, Subscriber} from "rxjs";
import {Indicator, Section, Stakeholder, StakeholderInfo, Visibility} from "../entities/stakeholder";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {map} from "rxjs/operators";
import {ActivatedRoute} from "@angular/router";
import {properties} from "../../../../environments/environment";
import {CustomOptions} from "../../services/servicesUtils/customOptions.class";
import {StringUtils} from "../../utils/string-utils.class";
let maps: string[] = ['parameters', 'filters'];
export interface Reorder {
action: 'moved' | 'added' | 'removed',
target: string,
@ -117,6 +114,7 @@ export class StakeholderService {
}
}));
}
saveBulkElements(url: string, indicators, path: string[] = []): Observable<any> {
path = HelperFunctions.encodeArray(path);
return this.http.post<any>(url + ((path.length > 0) ? '/' : '') + path.join('/') +
@ -128,6 +126,7 @@ export class StakeholderService {
}
}));
}
saveSection(url: string, element: any, path: string[] = [], index: number = -1): Observable<Section> {
path = HelperFunctions.encodeArray(path);
return this.http.post<Section>(url + ((path.length > 0) ? '/' : '') + path.join('/') +

View File

@ -11,64 +11,55 @@ import {ExternalIDV3_0, WorkV3_0} from "./orcidWork";
import {EnvProperties} from "../utils/properties/env-properties";
import {UserManagementService} from "../services/user-management.service";
import {OpenaireEntities} from "../utils/properties/searchFields";
import {FullScreenModalComponent} from "../utils/modal/full-screen-modal/full-screen-modal.component";
declare var UIkit: any;
@Component({
selector: 'orcid-work',
template: `
<ng-container *ngIf="pageType == 'search'">
<ng-container *ngIf="pageType == 'landing' || pageType == 'search'">
<span *ngIf="!putCodes || putCodes.length == 0"
[attr.uk-tooltip]="(!isLoggedIn) ? tooltipNoLoggedInUser : tooltipAdd"
class="uk-margin-remove-bottom">
[attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'"
[title]="((!pids && (!identifiers || identifiers.size == 0)) || !isLoggedIn) ? ((!pids && (!identifiers || identifiers.size == 0)) ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipAdd">
<a (click)="currentAction='add'; saveWorkPreparation();"
[class]="'uk-button uk-button-link uk-flex uk-flex-middle uk-flex-right@s uk-margin-right '+ ((showLoading || !isLoggedIn) ? 'uk-disabled ' : '') + (!isLoggedIn ? 'half-opacity' : '')">
<icon *ngIf="!showLoading" name="add" ratio="1" flex="true"></icon>
<span *ngIf="showLoading" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span class="uk-margin-small-left uk-flex uk-flex-middle">Add to&#160;
<span class="uk-flex uk-flex-middle">
<span>ORCID&#160;</span>
<img class="" src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="orcid" style="width:16px; height:16px" loading="lazy">&#160;
</span>
</span>
</a>
</span>
<span *ngIf="putCodes && putCodes.length > 0"
[attr.uk-tooltip]="(!isLoggedIn) ? tooltipNoLoggedInUser : tooltipDelete"
class="uk-margin-remove-bottom">
<a (click)="currentAction='delete'; deleteWorks();"
[class]="'uk-button uk-button-link uk-flex uk-flex-middle uk-flex-right@s uk-margin-right '+ (showLoading ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading" name="delete" ratio="0.8" flex="true"></icon>
<span *ngIf="showLoading" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span class="uk-margin-small-left uk-flex uk-flex-middle">Delete from&#160;
<span class="uk-flex uk-flex-middle">
<span>ORCID&#160;</span>
<img src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="" loading="lazy">&#160;
</span>
</span>
</a>
</span>
</ng-container>
<ng-container *ngIf="pageType == 'landing'">
<span *ngIf="!putCodes || putCodes.length == 0"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'"
[title]="(!pids || !isLoggedIn) ? (!pids ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipAdd">
<a *ngIf="!showLoading" (click)="currentAction='add'; saveWorkPreparation();"
class="uk-icon-button uk-icon landing-action-button landing-action-button-orcid"
[class.uk-disabled]="showLoading || !isLoggedIn || !pids"
class="uk-flex uk-flex-middle uk-button-link"
[ngClass]="isMobile && !(pageType == 'landing') ? 'uk-margin-left' : 'uk-flex-center'"
[class.uk-text-bolder]="!(isMobile && pageType == 'landing')"
[class.uk-disabled]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
[class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
(mouseover)="hoverEvent($event)" (mouseout)="hoverEvent($event)">
<icon *ngIf="!hoverAdd" name="orcid_add" ratio="1.1" visuallyHidden="add"></icon>
<icon *ngIf="hoverAdd" name="add" visuallyHidden="add"></icon>
</a>
<span *ngIf="showLoading" class="uk-icon icon-button uk-icon-button-small"><loading
<icon *ngIf="!showLoading" [class.text-orcid]="!showLoading && isLoggedIn && (pids || identifiers?.size > 0)"
[class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))" name="orcid_add" ratio="1"
visuallyHidden="add"></icon>
<span *ngIf="showLoading" class="uk-icon"><loading
[top_margin]="false" [size]="'small'"></loading></span>
<span [ngClass]="(isMobile && pageType == 'landing') ? 'uk-margin-small-left' : 'uk-margin-xsmall-left'">Claim</span>
</a>
</span>
<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 && (!identifiers || identifiers.size == 0)) || !isLoggedIn) ? ((!pids && (!identifiers || identifiers.size == 0)) ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipDelete">
<a (click)="currentAction='delete'; deleteWorks();"
class="uk-flex uk-flex-middle uk-button-link"
[ngClass]="isMobile && !(pageType == 'landing') ? 'uk-margin-left' : 'uk-flex-center'"
[class.uk-text-bolder]="!(isMobile && pageType == 'landing')"
[class.uk-disabled]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
[class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
(mouseover)="hoverEvent($event, 'delete')" (mouseout)="hoverEvent($event, 'delete')">
<icon *ngIf="!showLoading" [class.text-orcid]="!showLoading && isLoggedIn && (pids || identifiers?.size > 0)"
[class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))" name="orcid_bin" ratio="1"
visuallyHidden="delete"></icon>
<span *ngIf="showLoading" class="uk-icon"><loading
[top_margin]="false" [size]="'small'"></loading></span>
<span [ngClass]="(isMobile && pageType == 'landing') ? 'uk-margin-small-left' : 'uk-margin-xsmall-left'">Remove</span>
</a>
</span>
<!-- Old 'remove' code -->
<!-- <span *ngIf="putCodes && putCodes.length > 0"
[attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'"
[title]="(!pids || !isLoggedIn) ? (!pids ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipDelete">
<a *ngIf="!showLoading" (click)="currentAction='delete'; deleteWorks();"
class="uk-icon-button uk-icon landing-action-button landing-action-button-orcid"
@ -79,10 +70,10 @@ declare var UIkit: any;
</a>
<span *ngIf="showLoading" class="uk-icon icon-button uk-icon-button-small"><loading
[top_margin]="false" [size]="'small'"></loading></span>
</span>
</span> -->
</ng-container>
<modal-alert #grantModal [overflowBody]=false (alertOutput)="openGrantWindow()">
<modal-alert *ngIf="!isMobile" #grantModal [overflowBody]=false (alertOutput)="openGrantWindow()">
<div>
<div>{{requestGrantMessage}}</div>
@ -106,6 +97,13 @@ declare var UIkit: any;
</div>
</modal-alert>
<fs-modal *ngIf="isMobile" #grantFsModal classTitle="uk-tile-default uk-border-bottom">
<div>{{requestGrantMessage}}</div>
<button class="uk-margin-medium-top uk-button uk-button-primary uk-align-center" (click)="openGrantWindow()">
Grant OpenAIRE
</button>
</fs-modal>
<ng-container *ngIf="pageType == 'my_search'">
<span class="uk-margin-bottom uk-flex uk-flex-middle uk-flex-center">
@ -121,7 +119,8 @@ declare var UIkit: any;
[class]="'uk-button uk-button-default action uk-flex uk-flex-middle '+ ((showLoading || !putCodes || putCodes.length == 0) ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='get'" name="visibility" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='get'" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span *ngIf="showLoading && currentAction=='get'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">View ORCID work</span>
</a>
</span>
@ -133,7 +132,8 @@ declare var UIkit: any;
<a (click)="currentAction='update'; updateWorkPreparation()"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ ((showLoading || !putCodes || putCodes.length == 0) ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='update'" name="refresh" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='update'" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span *ngIf="showLoading && currentAction=='update'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">Update ORCID work</span>
</a>
</span>
@ -143,8 +143,9 @@ declare var UIkit: any;
<a (click)="currentAction='add'; saveWorkPreparation();"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ (showLoading ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='add'" name="add" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='add'" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span class="uk-margin-small-left">Add to ORCID</span>
<span *ngIf="showLoading && currentAction=='add'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">Claim</span>
</a>
</span>
@ -153,8 +154,9 @@ declare var UIkit: any;
<a (click)="currentAction='delete'; deleteWorks();"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ (showLoading ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='delete'" name="delete" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='delete'" class="uk-icon icon-button"><loading [top_margin]="false" [size]="'small'"></loading></span>
<span class="uk-margin-small-left">Delete from ORCID</span>
<span *ngIf="showLoading && currentAction=='delete'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">Remove</span>
</a>
</span>
</ng-container>
@ -228,14 +230,16 @@ declare var UIkit: any;
)">
(
</span>
<span *ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-role']">
<span
*ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-role']">
{{contributor['contributor-attributes']['contributor-role']}}
</span>
<span *ngIf="(contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-role'])
&& (contributor['contributor-attributes']['contributor-sequence'] || (contributor['contributor-orcid'] && contributor['contributor-orcid']['path']))">
,
</span>
<span *ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-sequence']">
<span
*ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-sequence']">
{{contributor['contributor-attributes']['contributor-sequence']}}
</span>
<span *ngIf="contributor['contributor-attributes'] && contributor['contributor-attributes']['contributor-sequence']
@ -261,14 +265,17 @@ declare var UIkit: any;
<modal-alert #propagationModal (alertOutput)="confirmedPropagation()">
<div>
This {{openaireEntities.RESULT}} is the result of <span class="uk-text-bold"> merged {{openaireEntities.RESULTS}} in OpenAIRE</span>.
This {{openaireEntities.RESULT}} is the result of <span
class="uk-text-bold"> merged {{openaireEntities.RESULTS}} in OpenAIRE</span>.
<br><br>
You have already added <span class="uk-text-bold">{{this.putCodes?.length}} works</span> in your ORCID record related to the merged {{openaireEntities.RESULT}}.
You have already added <span class="uk-text-bold">{{this.putCodes?.length}} works</span> in your ORCID record
related to the merged {{openaireEntities.RESULT}}.
<div *ngIf="currentAction == 'delete'">
If you continue with delete action, <span class="uk-text-bold">all these works will be deleted</span>.
</div>
<div *ngIf="currentAction == 'update'">
If you continue with update action, <span class="uk-text-bold">all these works will be deleted and a new merged work will be added</span> instead.
If you continue with update action, <span class="uk-text-bold">all these works will be deleted and a new merged work will be added</span>
instead.
</div>
</div>
@ -284,10 +291,32 @@ declare var UIkit: any;
<!-- </button>-->
<!-- </div>-->
</modal-alert>
<fs-modal #propagationFsModal classTitle="uk-tile-default uk-border-bottom">
<div>
This {{openaireEntities.RESULT}} is the result of <span
class="uk-text-bold"> merged {{openaireEntities.RESULTS}} in OpenAIRE</span>.
<br><br>
You have already added <span class="uk-text-bold">{{this.putCodes?.length}} works</span> in your ORCID record
related to the merged {{openaireEntities.RESULT}}.
<div *ngIf="currentAction == 'delete'">
If you continue with delete action, <span class="uk-text-bold">all these works will be deleted</span>.
</div>
<div *ngIf="currentAction == 'update'">
If you continue with update action, <span class="uk-text-bold">all these works will be deleted and a new merged work will be added</span>
instead.
</div>
</div>
<button class="uk-margin-medium-top uk-button uk-button-primary uk-align-center" (click)="confirmedPropagation()">
Continue
</button>
</fs-modal>
`
})
export class OrcidWorkComponent {
@Input() isMobile: boolean = false;
@Input() resultId: string = "";
@Input() resultTitle: string = "";
@Input() resultLandingInfo: ResultLandingInfo;
@ -304,8 +333,10 @@ export class OrcidWorkComponent {
@ViewChild('workModal') workModal;
// @ViewChild('saveWorkModal') saveWorkModal;
@ViewChild('grantModal') grantModal;
@ViewChild('grantFsModal') grantFsModal: FullScreenModalComponent;
// @ViewChild('messageModal') messageModal;
@ViewChild('propagationModal') propagationModal;
@ViewChild('propagationFsModal') propagationFsModal;
public requestGrant: boolean = false;
public requestGrantMessage: string = "Please grant OpenAIRE to access and update your ORCID works.";
@ -397,7 +428,12 @@ export class OrcidWorkComponent {
openGrantWindow() {
if (!Session.isLoggedIn()) {
//this.userValidMessage = "User session has expired. Please login again.";
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
// this.tokenUrl = location.origin+"/orcid";
this.window = window.open(this.tokenUrl, '_blank',
@ -464,7 +500,12 @@ export class OrcidWorkComponent {
public saveWorkPreparation() {
if (!Session.isLoggedIn()) {
//this.userValidMessage = "User session has expired. Please login again.";
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
if (this.requestGrant) {
@ -532,7 +573,12 @@ export class OrcidWorkComponent {
private updateWorkPreparation() {
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 {
if (this.requestGrant) {
@ -589,7 +635,12 @@ export class OrcidWorkComponent {
public getOrcidWorks() {
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 {
this.showLoading = true;
this.subscriptions.push(this.orcidService.getOrcidWorks(this.putCodes).subscribe(
@ -626,7 +677,12 @@ export class OrcidWorkComponent {
public deleteWorks(confirmed: boolean = false) {
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
if (this.requestGrant) {
@ -700,6 +756,11 @@ export class OrcidWorkComponent {
}
openGrantModal(title: string) {
if(this.isMobile) {
this.grantFsModal.okButton = false;
this.grantFsModal.title = title;
this.grantFsModal.open();
} else {
this.grantModal.cancelButton = true;
this.grantModal.okButton = true;
this.grantModal.okButtonText = "Grant OpenAIRE";
@ -707,6 +768,7 @@ export class OrcidWorkComponent {
this.grantModal.alertTitle = title;
this.grantModal.open();
}
}
closeGrantModal() {
this.grantModal.cancel();
@ -735,6 +797,11 @@ export class OrcidWorkComponent {
// }
openPropagationModal(title: string) {
if(this.isMobile) {
this.propagationFsModal.okButton = false;
this.propagationFsModal.title = title;
this.propagationFsModal.open();
} else {
this.propagationModal.cancelButton = true;
this.propagationModal.okButton = true;
this.propagationModal.okButtonText = "Continue";
@ -742,6 +809,7 @@ export class OrcidWorkComponent {
this.propagationModal.alertTitle = title;
this.propagationModal.open();
}
}
closePropagationModal() {
this.propagationModal.cancel();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,6 +11,7 @@ import {OpenaireEntities} from "../../utils/properties/searchFields";
@Component({
selector: 'quick-selections',
template: `
<div *ngIf="!vertical && (resultTypes || quickFilter)">
<div *ngIf="quickFilter" class="uk-margin-bottom">
<mat-slide-toggle name="qf" [(ngModel)]="quickFilter.selected" (ngModelChange)="quickFilterChanged()">
<span class="uk-text-bold">{{quickFilter.value}}</span>
@ -29,9 +30,16 @@ import {OpenaireEntities} from "../../utils/properties/searchFields";
</div>
</div>
</div>
</div>
<div *ngIf="vertical && (resultTypes || quickFilter)" [class.uk-disabled]="isDisabled">
<search-filter [isDisabled]="isDisabled" [filter]="resultTypes" [showResultCount]='false'
(onFilterChange)="changed()" [actionRoute]="actionRoute"></search-filter>
</div>
`
})
export class QuickSelectionsComponent {
@Input() vertical: boolean=false;
@Input() resultTypes:Filter;
@Output() typeChange = new EventEmitter();
@Input() isDisabled;

View File

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

View File

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

View File

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

View File

@ -2,10 +2,11 @@ import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'
import {SearchResult} from '../../utils/entities/searchResult';
import {EnvProperties} from '../../utils/properties/env-properties';
import {ResultPreview} from "../../utils/result-preview/result-preview";
import {HttpClient} from "@angular/common/http";
import {OrcidService} from "../../orcid/orcid.service";
import {Session} from "../../login/utils/helper.class";
import {properties} from "../../../../environments/environment";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {Subscription} from "rxjs";
@Component({
selector: 'search-result',
@ -23,18 +24,33 @@ export class SearchResultComponent implements OnInit, OnChanges {
@Input() custom_class: string = "";
@Input() properties: EnvProperties;
@Input() showEnermaps: boolean;
public isMobile: boolean = false;
private subscriptions: any[] = [];
constructor( private http: HttpClient/*ATHENA CODE*/
, private orcidService: OrcidService) {
constructor(private orcidService: OrcidService,
private layoutService: LayoutService) {
}
ngOnInit() {
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
}));
}
ngOnInit() {}
sub;
ngOnDestroy() {
if(this.sub){
this.sub.unsubscribe();
this.subscriptions.forEach(subscription => {
if(subscription instanceof Subscription) {
subscription.unsubscribe();
}
})
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.results) {
this.initialize();
}
}
initialize() {
this.previewResults = [];
for (let result of this.results) {
@ -45,7 +61,7 @@ export class SearchResultComponent implements OnInit, OnChanges {
&& 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(
this.subscriptions.push(this.orcidService.getPutCodes(this.previewResults.map(
previewResult => {
if (previewResult.identifiers) {
let pidsArray: string[] = [];
@ -65,15 +81,10 @@ export class SearchResultComponent implements OnInit, OnChanges {
}, error => {
}
);
));
}
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.results) {
this.initialize();
}
}
public getResultPreview(result: SearchResult): ResultPreview {
return ResultPreview.searchResultConvert(result, (result.entityType) ? result.entityType : this.type);
}

View File

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

View File

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

View File

@ -7,11 +7,11 @@ import {ParsingFunctions} from '../landingPages/landing-utils/parsingFunctions.c
import {EnvProperties} from '../utils/properties/env-properties';
import {map} from "rxjs/operators";
import {properties} from "../../../environments/environment";
import {HostedByCollectedFrom} from "../utils/result-preview/result-preview";
@Injectable()
export class SearchResearchResultsService {
private sizeOfDescription: number = 270;
public parsingFunctions: ParsingFunctions = new ParsingFunctions();
constructor(private http: HttpClient = null) {
@ -189,62 +189,57 @@ export class SearchResearchResultsService {
} else {
result.entityType = resultType;
}
result['title'] = {"name": '', "accessMode": ''};
if (Array.isArray(resData['title'])) {
for (let i = 0; i < resData['title'].length; i++) {
if (resData['title'][i] && resData['title'][i].content) {
if (!result.title.name || resData['title'][i].classid == "main title") {
result['title'].name = StringUtils.HTMLToString(String(resData['title'][i].content));
}
if (resData['title'][i].classid == "main title") {
break;
}
}
}
if (!result.title.name) {
result['title'].name = "";
}
// result['title'].name = (resData['title'][0] && resData['title'][0].content) ? String(resData['title'][0].content) : "";
} else {
result['title'].name = (resData['title'] && resData['title'].content) ? StringUtils.HTMLToString(String(resData['title'].content)) : "";
}
if (resData['bestaccessright'] && resData['bestaccessright'].hasOwnProperty("classname")) {
result['title'].accessMode = resData['bestaccessright'].classname;
}
result.types = new Array<string>();
let types = new Set<string>();
let instance;
let length = Array.isArray(resData['children']['instance']) ? resData['children']['instance'].length : 1;
result.hostedBy_collectedFrom = new Array<HostedByCollectedFrom>();
for (let i = 0; i < length; i++) {
instance = Array.isArray(resData['children']['instance']) ? resData['children']['instance'][i] : resData['children']['instance'];
this.parsingFunctions.parseTypes(result.types, types, instance);
if(instance?.hasOwnProperty("hostedby")) {
if(instance.hasOwnProperty("webresource")) {
let url = Array.isArray(instance['webresource'])?instance['webresource'][0].url:instance['webresource'].url;
if(url.includes('&amp;')) {
url = url.replace(/&amp;/gmu, '&');
}
if(instance.hasOwnProperty("hostedby")) {
this.parsingFunctions.parseHostedBy_collectedFrom(result.hostedBy_collectedFrom, instance, url, result.title.accessMode);
}
}
}
}
result.hostedBy_collectedFrom.sort(this.parsingFunctions.compareHostedByCollectedFrom);
// Measure
result.measure = 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';
}
}
}
}
result.measure = this.parsingFunctions.parseMeasures(resData['measure']);
/////////////////////////// Athena Code ///////////////////////////
if (resData['pid']) {
if (!Array.isArray(resData['pid'])) {
@ -313,27 +308,6 @@ export class SearchResearchResultsService {
}
}
result['title'] = {"name": '', "accessMode": ''};
if (Array.isArray(resData['title'])) {
for (let i = 0; i < resData['title'].length; i++) {
if (resData['title'][i] && resData['title'][i].content) {
if (!result.title.name || resData['title'][i].classid == "main title") {
result['title'].name = StringUtils.HTMLToString(String(resData['title'][i].content));
}
if (resData['title'][i].classid == "main title") {
break;
}
}
}
if (!result.title.name) {
result['title'].name = "";
}
// result['title'].name = (resData['title'][0] && resData['title'][0].content) ? String(resData['title'][0].content) : "";
} else {
result['title'].name = (resData['title'] && resData['title'].content) ? StringUtils.HTMLToString(String(resData['title'].content)) : "";
}
result['id'] = Array.isArray(data) ? data[i]['result']['header']['dri:objIdentifier'] : data['result']['header']['dri:objIdentifier'];
result['objId'] = result['id'];
let canId = ParsingFunctions.parseRelCanonicalId(Array.isArray(data) ? data[i] : data, "result");
@ -342,9 +316,6 @@ export class SearchResearchResultsService {
}
result['relcanId'] = result['id'];
if (resData['bestaccessright'] && resData['bestaccessright'].hasOwnProperty("classname")) {
result['title'].accessMode = resData['bestaccessright'].classname;
}
if (resData['rels'].hasOwnProperty("rel")) {
let relLength = Array.isArray(resData['rels']['rel']) ? resData['rels']['rel'].length : 1;
@ -415,6 +386,36 @@ export class SearchResearchResultsService {
if (resData['context'] != null) {
result.enermapsId = ParsingFunctions.getEnermapsConceptId(this.parsingFunctions.parseContexts(resData['context']));
}
if (resData.dateofacceptance && resData.dateofacceptance != null) {
let date: string = (resData.dateofacceptance ? resData.dateofacceptance : '') + ''; // transform to string in case it is an integer
result.date = (date && (date).indexOf('-') !== -1) ? date.split('-')[0] : date;
result.dateofacceptance = resData.dateofacceptance ? Dates.getDate(resData.dateofacceptance) : null;
}
if (resData.journal && resData.journal != null) {
result.journal = {
"journal": "",
"issn": "",
"lissn": "",
"eissn": "",
"issue": "",
"volume": "",
"start_page": "",
"end_page": ""
}
result.journal['journal'] = resData.journal.content;
result.journal['issn'] = resData.journal.issn;
result.journal['lissn'] = resData.journal.lissn;
result.journal['eissn'] = resData.journal.eissn;
result.journal['issue'] = resData.journal.iss;
result.journal['volume'] = resData.journal.vol;
result.journal['start_page'] = resData.journal.sp;
result.journal['end_page'] = resData.journal.ep;
}
result.hostedBy_collectedFrom = this.parsingFunctions.addPublisherToHostedBy_collectedFrom(
result.hostedBy_collectedFrom, result.publisher,
result['journal']?result['journal'].journal:null, result.identifiers);
results.push(result);
}
return results;

View File

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

View File

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

View File

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

View File

@ -21,6 +21,8 @@ import {BehaviorSubject, Subscription} from "rxjs";
import {EnvProperties} from "../../utils/properties/env-properties";
import {properties} from "../../../../environments/environment";
import {ClickEvent} from "../../utils/click/click-outside-or-esc.directive";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {MobileDropdownComponent} from "../../utils/mobile-dropdown/mobile-dropdown.component";
export type InputType =
'text'
@ -94,15 +96,15 @@ declare var UIkit;
<ng-template [ngIf]="type === 'select'">
<ng-container *ngIf="placeholderInfo?.static">
<div *ngIf="!getLabel(formControl.value)"
class="input placeholder uk-width-expand uk-text-truncate">{{placeholderInfo.label}}</div>
class="input placeholder uk-width-expand uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{placeholderInfo.label}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-width-expand uk-text-truncate">{{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 *ngIf="!placeholderInfo?.static">
<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)"
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-template>
<ng-template [ngIf]="type === 'autocomplete'">
@ -110,14 +112,14 @@ declare var UIkit;
#searchInput class="input" [formControl]="searchControl" [class.uk-text-truncate]="!focused">
<ng-container *ngIf="!focused && !selectable">
<div *ngIf="!getLabel(formControl.value)"
class="input placeholder uk-text-truncate">{{placeholderInfo?.static ? placeholderInfo.label : getLabel(formAsControl.value)}}</div>
class="input placeholder uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{placeholderInfo?.static ? placeholderInfo.label : getLabel(formAsControl.value)}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-text-truncate">{{getLabel(formAsControl.value)}}</div>
class="input uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{getLabel(formAsControl.value)}}</div>
</ng-container>
<ng-container *ngIf="!focused && selectable">
<div *ngIf="!getLabel(formControl.value)" class="input uk-text-truncate">{{noValueSelected}}</div>
<div *ngIf="!getLabel(formControl.value)" class="input uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{noValueSelected}}</div>
<div *ngIf="getLabel(formControl.value)"
class="input uk-text-truncate">{{getLabel(formControl.value)}}</div>
class="input uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{getLabel(formControl.value)}}</div>
</ng-container>
</ng-template>
<ng-template [ngIf]="type === 'autocomplete_soft'">
@ -168,11 +170,11 @@ declare var UIkit;
<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"
<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="!searchControl?.value && !!formControl?.value && (searchable || !selectable)"
<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>
@ -186,7 +188,7 @@ declare var UIkit;
</div>
</div>
</div>
<div class="options uk-dropdown" *ngIf="filteredOptions && filteredOptions.length > 0 && opened" #optionBox
<div *ngIf="!mobile && filteredOptions && filteredOptions.length > 0 && opened" class="options uk-dropdown" #optionBox
uk-dropdown="pos: bottom-justify; mode: none; offset: 15; boundary-align: true;" [attr.boundary]="'#' + id">
<ul class="uk-nav uk-dropdown-nav">
<li *ngFor="let option of filteredOptions; let i=index" [class.uk-hidden]="option.hidden"
@ -199,6 +201,22 @@ declare var UIkit;
</li>
</ul>
</div>
<mobile-dropdown *ngIf="mobile" #mobileDropdown>
<div *ngIf="placeholderInfo" class="uk-text-emphasis uk-text-bolder uk-text-center uk-padding-small uk-padding-remove-vertical uk-text-uppercase">
{{placeholderInfo.label}}
</div>
<div class="uk-padding uk-padding-remove-horizontal">
<ul class="uk-nav uk-nav-default">
<li *ngFor="let option of filteredOptions; let i=index" [class.uk-hidden]="option.hidden"
[class.uk-active]="formControl.value === option.value">
<a (click)="selectOption(option, $event)"
[class]="option.disabled ? 'uk-disabled uk-text-muted' : ''">
<span>{{option.label}}</span>
</a>
</li>
</ul>
</div>
</mobile-dropdown>
</div>
<span *ngIf="formControl?.invalid && formControl?.touched" class="uk-text-danger">
<span *ngIf="errors?.error">{{errors?.error}}</span>
@ -273,6 +291,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
public required: boolean = false;
public focused: boolean = false;
public opened: boolean = false;
public mobile: boolean = false;
public properties: EnvProperties = properties;
private initValue: any;
private optionsArray: Option[] = [];
@ -280,6 +299,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
private subscriptions: any[] = [];
@ViewChild('inputBox') inputBox: ElementRef;
@ViewChild('optionBox') optionBox: ElementRef;
@ViewChild('mobileDropdown') mobileDropdown: MobileDropdownComponent;
@ViewChild('searchInput') searchInput: ElementRef;
@ViewChildren('chip') chips: QueryList<ElementRef>;
@ -323,7 +343,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
}
constructor(private elementRef: ElementRef, private cdr: ChangeDetectorRef) {
constructor(private elementRef: ElementRef, private cdr: ChangeDetectorRef, private layoutService: LayoutService) {
if (elementRef.nativeElement.hasAttribute('dashboard-input') && this.properties.environment === "development") {
console.warn("'dashboard-input' selector is deprecated; use 'input' instead.");
}
@ -331,7 +351,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
@HostListener('window:keydown.arrowUp', ['$event'])
arrowUp(event: KeyboardEvent) {
if (this.opened) {
if (this.opened && this.optionBox) {
event.preventDefault();
if (this.selectedIndex > 0) {
this.selectedIndex--;
@ -342,7 +362,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
@HostListener('window:keydown.arrowDown', ['$event'])
arrowDown(event: KeyboardEvent) {
if (this.opened) {
if (this.opened && this.optionBox) {
event.preventDefault();
if (this.selectedIndex < (this.filteredOptions.length - 1)) {
this.selectedIndex++;
@ -381,6 +401,9 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
@HostListener('window:keydown.enter', ['$event'])
enter(event: KeyboardEvent) {
if (this.extendEnter) {
this.extendEnter();
}
if (this.opened && this.optionBox) {
event.preventDefault();
if (this.filteredOptions[this.selectedIndex]) {
@ -391,9 +414,6 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
} else {
this.focus(false, event);
}
if (this.extendEnter) {
this.extendEnter();
}
}
@HostListener('keydown', ['$event'])
@ -405,10 +425,14 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
click(event: ClickEvent) {
this.focus(!event.clicked, event);
this.focus(!event.clicked);
}
ngOnInit() {
this.subscriptions.push(this.layoutService.isMobile.subscribe(mobile => {
this.mobile = mobile;
this.cdr.detectChanges();
}));
InputComponent.INPUT_COUNTER++;
this.id = 'input-' + InputComponent.INPUT_COUNTER;
if (!this.formControl) {
@ -532,8 +556,10 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
if (this.focused) {
this.open(true);
setTimeout(() => {
if(this.searchInput) {
this.searchInput.nativeElement.focus();
this.searchInput.nativeElement.value = value;
}
}, 0);
}
}));
@ -640,7 +666,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
return (this.showOptionsOnEmpty) ? options : [];
}
const filterValue = value.toString().toLowerCase();
options = options.filter(option => option.label.toLowerCase().indexOf(filterValue) != -1);
options = options.filter(option => (option.label && option.label.toLowerCase().indexOf(filterValue) != -1));
this.selectedIndex = options.findIndex(option => option.value === this.formControl.value);
if (this.selectedIndex === -1) {
this.selectedIndex = 0;
@ -697,6 +723,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
if (this.focused) {
this.formControl.markAsTouched();
}
if(this.formControl.enabled) {
this.focused = value;
this.cdr.detectChanges();
if (this.focused) {
@ -731,21 +758,31 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
this.focusEmitter.emit(this.focused);
}
}
open(value: boolean) {
this.opened = value && this.formControl.enabled;
this.cdr.detectChanges();
if (this.optionBox && this.opened) {
if(this.optionBox) {
if (this.opened) {
this.selectedIndex = this.filteredOptions.findIndex(option => option.value === this.formControl.value);
if (this.selectedIndex === -1 && this.type !== 'autocomplete_soft') {
this.selectedIndex = 0;
}
UIkit.dropdown(this.optionBox.nativeElement).show();
} else {
if (this.optionBox) {
UIkit.dropdown(this.optionBox.nativeElement).hide();
this.focused = false;
}
} else if(this.mobileDropdown) {
if(this.opened) {
this.mobileDropdown.open();
if(this.searchInput) {
this.searchInput.nativeElement.blur();
}
} else {
this.mobileDropdown.close();
}
}
}

View File

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

View File

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

View File

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

View File

@ -10,12 +10,13 @@ import { UserMiniModule} from '../login/userMiniModule.module';
import {SearchBarModule} from "./searchBar/searchBar.module";
import {HelpContentService} from '../services/help-content.service';
import {IconsModule} from "../utils/icons/icons.module";
import {SearchInputModule} from "./search-input/search-input.module";
@NgModule({
imports: [
CommonModule, FormsModule,
RouterModule,
UserMiniModule, IconsModule,
UserMiniModule, IconsModule, SearchInputModule,
// , SearchBarModule
],
declarations: [

View File

@ -5,7 +5,7 @@ import { BehaviorSubject, Observable } from "rxjs";
providedIn: "root"
})
export class QuickContactService {
private display: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
private display: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
public get isDisplayed(): Observable<boolean> {
return this.display.asObservable();

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