Merge branch 'develop' into plugins-functionality

This commit is contained in:
argirok 2023-10-06 21:09:10 +03:00
commit 225a9a113f
71 changed files with 1254 additions and 1184 deletions

View File

@ -8,13 +8,14 @@ export class SearchCommunityProjectsService {
constructor(private http: HttpClient ) {} constructor(private http: HttpClient ) {}
searchProjects (properties:EnvProperties, pid: string, page=1, size=500):any { searchProjects (properties:EnvProperties, pid: string, page=1, size=500):any {
this.searchProjectsWithPaging(properties,pid,page, size, null, null); return this.searchProjectsWithPaging(properties,pid,page, size, null, null);
} }
searchProjectsWithPaging (properties:EnvProperties, pid: string, page=1, size=500, searchFilter, funder):any { searchProjectsWithPaging (properties:EnvProperties, pid: string, page=1, size=500, searchFilter, funder, orderBy = "name"):any {
let params = funder ? ["funder="+ funder] :[]; let params = funder ? ["funder="+ funder] :[];
if (searchFilter) { if (searchFilter) {
params.push("searchFilter="+ searchFilter) params.push("searchFilter="+ searchFilter)
} }
params.push("orderBy="+ orderBy);
let url = properties.communityAPI+pid+"/projects/"+ (page-1) + "/" + size + (params.length > 0?"?" + params.join("&"):""); let url = properties.communityAPI+pid+"/projects/"+ (page-1) + "/" + size + (params.length > 0?"?" + params.join("&"):"");
return this.http.get((properties.useCache)? (properties.cacheUrl+encodeURIComponent(url)): url); return this.http.get((properties.useCache)? (properties.cacheUrl+encodeURIComponent(url)): url);
} }
@ -23,4 +24,8 @@ export class SearchCommunityProjectsService {
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => res['totalElements'])); .pipe(map(res => res['totalElements']));
} }
getProjectFunders(properties:EnvProperties,pid:string) {
let url = properties.communityAPI+pid+"/funders";
return this.http.get<string[]>((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url);
}
} }

View File

@ -48,7 +48,7 @@ import {FullScreenModalComponent} from '../utils/modal/full-screen-modal/full-sc
1. Find the appropriate repository or journal 1. Find the appropriate repository or journal
</div> </div>
<div> <div>
Find the appropriate repository to deposit your research products of any type (publication, data, software, other) or to include in your data management plan. Search and browse for OpenAIRE compliant repositories registered in OpenDOAR and re3data. Find the appropriate repository to deposit your research products of any type (publication, data, software, other) or to include in your data management plan. Search and browse for OpenAIRE compliant repositories registered in OpenDOAR, re3data and FAIRsharing.
Looking for Open Access journals? Find those that suit your needs among the journals registered in the Directory of Open Access Journals (DOAJ). Looking for Open Access journals? Find those that suit your needs among the journals registered in the Directory of Open Access Journals (DOAJ).
To know more, read the OpenAIRE Open Access primer (<a target="_blank" href="https://www.openaire.eu/oa-basics">https://www.openaire.eu/oa-basics</a>) To know more, read the OpenAIRE Open Access primer (<a target="_blank" href="https://www.openaire.eu/oa-basics">https://www.openaire.eu/oa-basics</a>)
</div> </div>
@ -110,7 +110,7 @@ import {FullScreenModalComponent} from '../utils/modal/full-screen-modal/full-sc
<div class="uk-card-body uk-text-small"> <div class="uk-card-body uk-text-small">
<img src="assets/common-assets/common/Logo_Horizontal.png" alt="OpenAIRE logo" class="uk-width-small uk-margin-bottom"> <img src="assets/common-assets/common/Logo_Horizontal.png" alt="OpenAIRE logo" class="uk-width-small uk-margin-bottom">
<div> <div>
Search and browse for <span class="uk-text-bold">OpenAIRE compliant repositories</span> registered in OpenDOAR and re3data. Search and browse for <span class="uk-text-bold">OpenAIRE compliant repositories</span> registered in OpenDOAR, re3data and FAIRsharing.
</div> </div>
</div> </div>
<div class="uk-card-footer uk-padding-small uk-tile-primary uk-flex uk-flex-center uk-light"> <div class="uk-card-footer uk-padding-small uk-tile-primary uk-flex uk-flex-center uk-light">

View File

@ -72,8 +72,9 @@ export class FosSelectionComponent {
} else { } else {
this.activeSection = this.fos[0].id; this.activeSection = this.fos[0].id;
} }
if(typeof IntersectionObserver !== "undefined") {
this.setObserver(); this.setObserver();
}
this.cdr.detectChanges(); this.cdr.detectChanges();
}); });
} }
@ -93,7 +94,7 @@ export class FosSelectionComponent {
this.subscriptions.push(this.keywordControl.valueChanges.pipe(debounceTime(500), distinctUntilChanged()).subscribe(value => { this.subscriptions.push(this.keywordControl.valueChanges.pipe(debounceTime(500), distinctUntilChanged()).subscribe(value => {
this.keyword = value; this.keyword = value;
this.findMatches(this.keyword); this.findMatches(this.keyword);
if (typeof document !== 'undefined') { if (typeof IntersectionObserver !== 'undefined') {
setTimeout(() => { setTimeout(() => {
this.setObserver(); this.setObserver();
}); });

View File

@ -95,7 +95,7 @@
<div [id]="item.id" *ngFor="let item of fos; index as i"> <div [id]="item.id" *ngFor="let item of fos; index as i">
<div class="uk-text-capitalize"> <div class="uk-text-capitalize">
<h2 class="uk-h4 uk-margin-remove"> <h2 class="uk-h4 uk-margin-remove">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(item.id)}" <a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(item)"
class="uk-link-text"> class="uk-link-text">
{{item.id}} {{item.id}}
</a> </a>
@ -105,13 +105,13 @@
<div *ngFor="let child of item.children"> <div *ngFor="let child of item.children">
<div class="uk-text-capitalize"> <div class="uk-text-capitalize">
<h3 class="uk-h6 uk-margin-small-bottom"> <h3 class="uk-h6 uk-margin-small-bottom">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(child.id)}" <a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(child)"
class="uk-link-text"> class="uk-link-text">
{{child.id}} {{child.id}}
</a> </a>
</h3> </h3>
<div *ngFor="let subChild of child.children" style="margin-bottom: 5px;"> <div *ngFor="let subChild of child.children" style="margin-bottom: 5px;">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subChild.id)}" <a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(subChild)"
class="uk-link-text"> class="uk-link-text">
{{subChild.label}} {{subChild.label}}
</a> </a>
@ -126,19 +126,19 @@
<div <div
class="uk-margin-large-bottom uk-padding uk-padding-remove-top uk-padding-remove-horizontal uk-text-capitalize" [class.custom-bottom-border]="i < viewResults.length - 1"> class="uk-margin-large-bottom uk-padding uk-padding-remove-top uk-padding-remove-horizontal uk-text-capitalize" [class.custom-bottom-border]="i < viewResults.length - 1">
<h2 class="uk-h4 uk-margin-remove"> <h2 class="uk-h4 uk-margin-remove">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(item.id)}" <a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(item)"
class="uk-link-text" [innerHTML]="highlightKeyword(item.id)"> class="uk-link-text" [innerHTML]="highlightKeyword(item.id)">
</a> </a>
</h2> </h2>
<div class="uk-grid uk-child-width-1-3 uk-margin-large-top uk-margin-medium-bottom" uk-grid="masonry: false"> <div class="uk-grid uk-child-width-1-3 uk-margin-large-top uk-margin-medium-bottom" uk-grid="masonry: false">
<div *ngFor="let subItem of item.children"> <div *ngFor="let subItem of item.children">
<h3 class="uk-h6 uk-margin-small-bottom"> <h3 class="uk-h6 uk-margin-small-bottom">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subItem.id)}" <a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(subItem)"
class="uk-link-text" [innerHTML]="highlightKeyword(subItem.id)"> class="uk-link-text" [innerHTML]="highlightKeyword(subItem.id)">
</a> </a>
</h3> </h3>
<div *ngFor="let subSubItem of subItem.children" style="margin-bottom: 5px;"> <div *ngFor="let subSubItem of subItem.children" style="margin-bottom: 5px;">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subSubItem.id)}" <a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(subSubItem)"
class="uk-link-text" [innerHTML]="highlightKeyword(subSubItem.label)"> class="uk-link-text" [innerHTML]="highlightKeyword(subSubItem.label)">
</a> </a>
</div> </div>

View File

@ -105,7 +105,7 @@ export class FosComponent implements OnInit, OnDestroy {
this.subscriptions.push(this.keywordControl.valueChanges.pipe(debounceTime(500), distinctUntilChanged()).subscribe(value => { this.subscriptions.push(this.keywordControl.valueChanges.pipe(debounceTime(500), distinctUntilChanged()).subscribe(value => {
this.keyword = value; this.keyword = value;
this.findMatches(this.keyword); this.findMatches(this.keyword);
if (typeof document !== 'undefined') { if (typeof IntersectionObserver !== 'undefined') {
setTimeout(() => { setTimeout(() => {
this.setObserver(); this.setObserver();
}); });
@ -214,4 +214,9 @@ export class FosComponent implements OnInit, OnDestroy {
this._meta.updateTag({content: description}, "name='description'"); this._meta.updateTag({content: description}, "name='description'");
this._meta.updateTag({content: description}, "property='og:description'"); this._meta.updateTag({content: description}, "property='og:description'");
} }
public buildFosQueryParam(fos) {
// return {'foslabel': this.urlEncodeAndQuote(fos.id+"||"+fos.label)};
return (properties.environment !== 'production' ? ({'foslabel': this.urlEncodeAndQuote(fos.id+"||"+fos.label)}) : ({'fos': this.urlEncodeAndQuote(fos.id)}));
}
} }

View File

@ -425,32 +425,36 @@
</div> </div>
<div *ngIf="mobileContent == 'actions'" class="uk-container uk-section"> <div *ngIf="mobileContent == 'actions'" class="uk-container uk-section">
<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" <div class="uk-padding-small uk-padding-remove-horizontal">
(click)="openFsModal(addThisFsModal, 'Share this '+openaireEntities.DATASOURCE+' in your social networks')"> <div class="clickable" (click)="openFsModal(addThisFsModal, 'Share this '+openaireEntities.DATASOURCE+' in your social networks')">
<icon [flex]="true" name="share" visuallyHidden="share"></icon> <div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
<span class="uk-margin-small-left">Share</span> <icon [flex]="true" name="share" visuallyHidden="share"></icon>
<span class="uk-margin-small-left">Share</span>
</div>
<div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall">Share this {{openaireEntities.DATASOURCE}} in your social networks</div>
</div>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
</div> </div>
<div class="landing-action-bar-mobile uk-background-default"> <div class="landing-action-bar-mobile uk-tile-default uk-blur-background">
<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 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> <div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'; scroll()">
<icon name="note_add" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"></icon> <icon name="note_add" type="outlined" [flex]="true" [ratio]="1.4" [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"></icon>
<span>{{openaireEntities.DATASOURCE}}</span> <span>{{openaireEntities.DATASOURCE}}</span>
</a> </a>
</div> </div>
<div *ngIf="dataProviderInfo && hasMetrics"> <div *ngIf="dataProviderInfo && hasMetrics">
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'metrics'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'metrics'; scroll()">
<icon name="bar_chart" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'metrics' ? 'uk-text-primary': ''"></icon> <icon name="bar_chart" type="outlined" [flex]="true" [ratio]="1.4" [ngClass]="mobileContent == 'metrics' ? 'uk-text-primary': ''"></icon>
<span>Metrics</span> <span>Metrics</span>
</a> </a>
</div> </div>
<div> <div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'actions'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'actions'; scroll()">
<icon name="pending" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'actions' ? 'uk-text-primary': ''"></icon> <icon name="pending" type="outlined" [flex]="true" [ratio]="1.4" [ngClass]="mobileContent == 'actions' ? 'uk-text-primary': ''"></icon>
<span>Actions</span> <span>Actions</span>
</a> </a>
</div> </div>

View File

@ -5,7 +5,6 @@ import { RouterModule } from '@angular/router';
import {IFrameModule} from '../../utils/iframe.module'; import {IFrameModule} from '../../utils/iframe.module';
import {ErrorMessagesModule} from '../../utils/errorMessages.module'; import {ErrorMessagesModule} from '../../utils/errorMessages.module';
import {MetricsModule} from '../landing-utils/metrics/metrics.module';
import {LandingModule} from '../landing-utils/landing.module'; import {LandingModule} from '../landing-utils/landing.module';
import {PagingModule} from '../../utils/paging.module'; import {PagingModule} from '../../utils/paging.module';
@ -41,7 +40,7 @@ import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.mod
@NgModule({ @NgModule({
imports: imports:
[CommonModule, FormsModule, RouterModule, [CommonModule, FormsModule, RouterModule,
IFrameModule, ErrorMessagesModule, MetricsModule, LandingModule, IFrameModule, ErrorMessagesModule, LandingModule,
DataProvidersServiceModule, ProjectsServiceModule, SearchResearchResultsServiceModule, DataProvidersServiceModule, ProjectsServiceModule, SearchResearchResultsServiceModule,
PagingModule, Schema2jsonldModule, SEOServiceModule, ShowPublisherModule, HelperModule, PagingModule, Schema2jsonldModule, SEOServiceModule, ShowPublisherModule, HelperModule,
LandingHeaderModule, AlertModalModule, NoLoadPaging, FeedbackModule, LandingHeaderModule, AlertModalModule, NoLoadPaging, FeedbackModule,

View File

@ -17,7 +17,7 @@ import {RouterHelper} from "../../utils/routerHelper.class";
uk-tooltip [title]="getAccessLabel(availableOn[0].accessRight)"> uk-tooltip [title]="getAccessLabel(availableOn[0].accessRight)">
<icon [name]="availableOn[0].accessRightIcon" [flex]="true" [ratio]="(isMobile && usedBy == 'landing') ? 1 : 0.8"></icon> <icon [name]="availableOn[0].accessRightIcon" [flex]="true" [ratio]="(isMobile && usedBy == 'landing') ? 1 : 0.8"></icon>
</span> </span>
<ng-container *ngIf="!(isMobile && usedBy == 'landing')"> <ng-container *ngIf="!isMobile">
<a uk-tooltip="Source" target="_blank" <a uk-tooltip="Source" target="_blank"
class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder"> class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder">
<span>{{sliceString(availableOn[0].downloadNames.join("; "), 20)}}</span> <span>{{sliceString(availableOn[0].downloadNames.join("; "), 20)}}</span>
@ -32,18 +32,21 @@ import {RouterHelper} from "../../utils/routerHelper.class";
</div> </div>
</ng-container> </ng-container>
<ng-container *ngIf="(isMobile && usedBy == 'landing')"> <ng-container *ngIf="isMobile">
<a class="uk-flex uk-flex-between uk-flex-middle uk-flex-center uk-width-expand uk-button-link" (click)="openAvailableListFsModal()"> <a #toggle class="uk-flex uk-flex-between uk-flex-middle uk-flex-center uk-width-expand uk-button-link">
<span uk-tooltip="Source">{{sliceString(availableOn[0].downloadNames.join("; "), 20)}}</span> <span>{{sliceString(availableOn[0].downloadNames.join("; "), 20)}}</span>
<span> <span>
<icon [flex]="true" ratio="1.5" name="arrow_right"></icon> <icon [flex]="true" ratio="1.5" name="arrow_right"></icon>
</span> </span>
</a> </a>
<fs-modal #availableListFsModal classTitle="uk-tile-default uk-border-bottom"> <mobile-dropdown [toggle]="toggle">
<div class="uk-text-small download-drop"> <div class="uk-text-emphasis uk-text-bolder uk-text-center uk-padding-small uk-padding-remove-vertical uk-text-uppercase">
Sources
</div>
<div class="uk-text-small download-drop uk-padding uk-padding-remove-horizontal">
<ng-container *ngTemplateOutlet="availableOnList"></ng-container> <ng-container *ngTemplateOutlet="availableOnList"></ng-container>
</div> </div>
</fs-modal> </mobile-dropdown>
</ng-container> </ng-container>
</ng-container> </ng-container>
</div> </div>
@ -97,7 +100,6 @@ export class AvailableOnComponent {
/** @deprecated */ /** @deprecated */
@Output() viewAllClicked = new EventEmitter(); @Output() viewAllClicked = new EventEmitter();
@ViewChild("dropElement") dropElement: ElementRef; @ViewChild("dropElement") dropElement: ElementRef;
@ViewChild("availableListFsModal") availableListFsModal: FullScreenModalComponent;
public threshold: number = 1; public threshold: number = 1;
public dataProviderUrl = properties.searchLinkToDataProvider.split('?')[0]; public dataProviderUrl = properties.searchLinkToDataProvider.split('?')[0];
public title: string = "Download from"; public title: string = "Download from";
@ -125,12 +127,6 @@ export class AvailableOnComponent {
return StringUtils.sliceString(str, size) return StringUtils.sliceString(str, size)
} }
public openAvailableListFsModal() {
this.availableListFsModal.title = "Sources";
this.availableListFsModal.okButton = false;
this.availableListFsModal.open();
}
public getAccessLabel(accessRight) : string { public getAccessLabel(accessRight) : string {
if(accessRight) { if(accessRight) {
return (accessRight + (accessRight.toLowerCase().endsWith(" access") ? "" : " access")); return (accessRight + (accessRight.toLowerCase().endsWith(" access") ? "" : " access"));

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
import {Component, Input} from "@angular/core"; import {Component, Input, ViewChild} from "@angular/core";
import {EnvProperties} from "../../utils/properties/env-properties"; import {EnvProperties} from "../../utils/properties/env-properties";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {OpenaireEntities} from "../../utils/properties/searchFields"; import {OpenaireEntities} from "../../utils/properties/searchFields";
@ -60,10 +60,10 @@ import {RouterHelper} from "../../utils/routerHelper.class";
<span>{{year}}</span> <span>{{year}}</span>
</ng-container> </ng-container>
<ng-container *ngIf="startYear && !endYear"> <ng-container *ngIf="startYear && !endYear">
<span>{{startYear}}</span> <span>From {{startYear}}</span>
</ng-container> </ng-container>
<ng-container *ngIf="!startYear && endYear"> <ng-container *ngIf="!startYear && endYear">
<span>{{endYear}}</span> <span>Until {{endYear}}</span>
</ng-container> </ng-container>
<ng-container *ngIf="startYear && endYear"> <ng-container *ngIf="startYear && endYear">
<ng-container> <ng-container>
@ -151,12 +151,32 @@ import {RouterHelper} from "../../utils/routerHelper.class";
<span>Thematic</span> <span>Thematic</span>
</ng-container> </ng-container>
<!-- Projects --> <!-- Projects -->
<span uk-tooltip="Projects" *ngIf="projects && projects.length > 0" [class.truncated]="projects.length > 3"> <span *ngIf="projects && projects.length > 0"
{{projectNames.slice(0,3).join(', ')}} [attr.uk-tooltip]="projects.length > projectsLimit ? 'cls: uk-invisible' : 'pos: top; cls: uk-active'" title="Funded by">
{{showInline ? projectNames.join(', ') : projectNames.slice(0, projectsLimit).join(', ')}}
<span *ngIf="projects.length > projectsLimit">
<a *ngIf="!showInline" (click)="viewAllProjectsClick();" class="uk-background-muted custom-extra-entities">
+{{projects.length - projectsLimit | number}} projects
</a>
<a *ngIf="showInline && lessBtn" (click)="showInline = !showInline; lessBtn = false;"
class="uk-background-muted custom-extra-entities">
View less
</a>
</span>
</span> </span>
<!-- Organizations --> <!-- Organizations -->
<span uk-tooltip="Partners" *ngIf="organizations && organizations.length > 0" [class.truncated]="organizations.length > 3"> <span *ngIf="organizations && organizations.length > 0"
{{organizationNames.slice(0, 3).join(', ')}} [attr.uk-tooltip]="organizations.length > organizationsLimit ? 'cls: uk-invisible' : 'pos: top; cls: uk-active'" title="Partners">
{{showInline ? organizationNames.join(', ') : organizationNames.slice(0, organizationsLimit).join(', ')}}
<span *ngIf="organizations.length > organizationsLimit">
<a *ngIf="!showInline" (click)="viewAllPartnersClick();" class="uk-background-muted custom-extra-entities">
+{{organizations.length - organizationsLimit | number}} partners
</a>
<a *ngIf="showInline && lessBtn" (click)="showInline = !showInline; lessBtn = false;"
class="uk-background-muted custom-extra-entities">
View less
</a>
</span>
</span> </span>
<!-- Subjects --> <!-- Subjects -->
<span uk-tooltip="Subjects" *ngIf="subjects && subjects.length > 0" [class.truncated]="subjects.length > 3"> <span uk-tooltip="Subjects" *ngIf="subjects && subjects.length > 0" [class.truncated]="subjects.length > 3">
@ -169,10 +189,37 @@ import {RouterHelper} from "../../utils/routerHelper.class";
<span>{{relationName}}</span> <span>{{relationName}}</span>
</ng-container> </ng-container>
</div> </div>
<modal-alert *ngIf="!isMobile" #partnersModal>
<div class="uk-text-small uk-text-emphasis uk-grid uk-grid-column-collapse uk-grid-row-small" uk-grid>
<ng-container *ngFor="let item of organizations; let i = index">
<div class="uk-margin-xsmall-right">
{{item.name}}{{i == organizations.length - 1 ? '' : ','}}
</div>
</ng-container>
</div>
</modal-alert>
<modal-alert *ngIf="!isMobile" #projectsModal>
<div class="uk-text-small uk-text-emphasis uk-grid uk-grid-column-collapse uk-grid-row-small" uk-grid>
<ng-container *ngFor="let item of projects; let i = index">
<div class="uk-margin-xsmall-right">
<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>
{{i == projects.length - 1 ? '' : ','}}
</div>
</ng-container>
</div>
</modal-alert>
`, `,
styleUrls: ['entity-metadata.component.less'] styleUrls: ['entity-metadata.component.less']
}) })
export class EntityMetadataComponent { export class EntityMetadataComponent {
@Input() isMobile: boolean = false;
@Input() entityType: string; @Input() entityType: string;
@Input() types: string[]; @Input() types: string[];
@Input() year: string; // search result @Input() year: string; // search result
@ -204,6 +251,14 @@ export class EntityMetadataComponent {
@Input() subjects: string[]; @Input() subjects: string[];
@Input() prevPath: string = ""; @Input() prevPath: string = "";
@ViewChild('partnersModal') partnersModal;
@ViewChild('projectsModal') projectsModal;
organizationsLimit: number = 5;
projectsLimit: number = 3;
showInline: boolean = false;
lessBtn: boolean = false;
properties: EnvProperties = properties; properties: EnvProperties = properties;
public openaireEntities = OpenaireEntities; public openaireEntities = OpenaireEntities;
public routerHelper: RouterHelper = new RouterHelper(); public routerHelper: RouterHelper = new RouterHelper();
@ -238,9 +293,9 @@ export class EntityMetadataComponent {
value = value + ' | ' + (project.acronym ? project.acronym : value = value + ' | ' + (project.acronym ? project.acronym :
(project.title.length > 25 ? (project.title.slice(0, 25) + '...'): project.title)); (project.title.length > 25 ? (project.title.slice(0, 25) + '...'): project.title));
} }
if(project.code) { // if(project.code) {
value = value + ' (' + project.code + ')'; // value = value + ' (' + project.code + ')';
} // }
return value; return value;
}); });
} }
@ -260,4 +315,48 @@ export class EntityMetadataComponent {
} }
return obj; return obj;
} }
}
public viewAllPartnersClick() {
if(this.organizations.length <= this.organizationsLimit * 2) {
this.showInline = true;
this.lessBtn = true;
} else {
this.openPartnersModal();
}
}
public openPartnersModal() {
if (this.isMobile) {
this.partnersModal.okButton = false;
this.partnersModal.title = "Partners";
this.partnersModal.open();
} else {
this.partnersModal.cancelButton = false;
this.partnersModal.okButton = false;
this.partnersModal.alertTitle = "Partners";
this.partnersModal.open();
}
}
public viewAllProjectsClick() {
if(this.projects.length <= this.projectsLimit * 2) {
this.showInline = true;
this.lessBtn = true;
} else {
this.openProjectsModal();
}
}
public openProjectsModal() {
if (this.isMobile) {
this.projectsModal.okButton = false;
this.projectsModal.title = "Projects";
this.projectsModal.open();
} else {
this.projectsModal.cancelButton = false;
this.projectsModal.okButton = false;
this.projectsModal.alertTitle = "Projects";
this.projectsModal.open();
}
}
}

View File

@ -31,15 +31,19 @@ import {StringUtils} from "../../utils/string-utils.class";
</div> </div>
<div class="uk-margin-small-top"> <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"> <div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate">
<a [routerLink]="properties.searchLinkToResults" <a *ngIf="properties.adminToolsPortalType != 'eosc'"
[queryParams]="{'fos': urlEncodeAndQuote(subject.id)}"> [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(subject)">
{{subject.label}} {{subject.label}}
</a> </a>
<a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank"
[href]="'https://explore.openaire.eu'+properties.searchLinkToResults+'?fos='+urlEncodeAndQuote(subject.label)">
{{subject.label}}
</a>
</div> </div>
</div> </div>
</div> </div>
<div class="uk-hidden@m"> <div class="uk-hidden@m">
<div class="uk-grid uk-grid-small uk-grid-divider" uk-grid> <div *ngIf="!viewAll" class="uk-grid uk-grid-small uk-grid-divider" uk-grid>
<div class="uk-width-1-4 uk-text-meta"> <div class="uk-width-1-4 uk-text-meta">
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div> <div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
{{title}} {{title}}
@ -47,16 +51,28 @@ import {StringUtils} from "../../utils/string-utils.class";
<div class="uk-width-expand"> <div class="uk-width-expand">
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate"> <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]="{'fos': urlEncodeAndQuote(subject.id)}"> [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(subject)">
{{subject.label}} {{subject.label}}
</a> </a>
<a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank" <a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank"
[href]="'https://explore.openaire.eu'+properties.searchLinkToResults+'?fos='+urlEncodeAndQuote(subject.id)"> [href]="'https://explore.openaire.eu'+properties.searchLinkToResults+'?'+buildFosHrefParam(subject)">
{{subject.label}} {{subject.label}}
</a> </a>
</div> </div>
</div> </div>
</div> </div>
<div *ngIf="viewAll">
<div *ngFor="let subject of subjects; let i=index" class="uk-text-truncate">
<a *ngIf="properties.adminToolsPortalType != 'eosc'"
[routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(subject)">
{{subject.label}}
</a>
<a *ngIf="properties.adminToolsPortalType == 'eosc'" class="custom-external" target="_blank"
[href]="'https://explore.openaire.eu'+properties.searchLinkToResults+'?'+buildFosHrefParam(subject)">
{{subject.label}}
</a>
</div>
</div>
<div class="uk-text-right uk-margin-small-top"> <div class="uk-text-right uk-margin-small-top">
<a *ngIf="subjects && subjects.length > threshold && !viewAll" <a *ngIf="subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate"> (click)="viewAllClick();" class="view-more-less-link uk-text-truncate">
@ -103,4 +119,14 @@ export class FosComponent {
public urlEncodeAndQuote(str: string): string { public urlEncodeAndQuote(str: string): string {
return StringUtils.quote(StringUtils.URIEncode(str)); return StringUtils.quote(StringUtils.URIEncode(str));
} }
public buildFosQueryParam(fos) {
// return {'foslabel': this.urlEncodeAndQuote(fos.id+"||"+fos.label)};
return (properties.environment !== 'production' ? ({'foslabel': this.urlEncodeAndQuote(fos.id+"||"+fos.label)}) : ({'fos': this.urlEncodeAndQuote(fos.id)}));
}
public buildFosHrefParam(fos): string {
// return ('foslabel='+this.urlEncodeAndQuote(fos.id+"||"+fos.label));
return (properties.environment !== 'production' ? ('foslabel='+this.urlEncodeAndQuote(fos.id+"||"+fos.label)) : ('fos='+this.urlEncodeAndQuote(fos.id)));
}
} }

View File

@ -34,15 +34,16 @@ import {RouterHelper} from "../../utils/routerHelper.class";
</div> </div>
<div *ngIf="isMobile"> <div *ngIf="isMobile">
<div *ngFor="let item of fundedByProjects.slice(0, viewAll?fundedByProjects.length:threshold) let i=index" <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"> class="uk-flex uk-flex-middle uk-margin-small-bottom">
<span class="uk-text-emphasis"> <span class="uk-text-emphasis uk-width-expand">
<ng-container *ngTemplateOutlet="funder; context: {item: item}"></ng-container> <ng-container *ngTemplateOutlet="funder; context: {item: item}"></ng-container>
</span> </span>
<icon name="info" visuallyHidden="info" [type]="'outlined'" class="uk-link"></icon> <a #toggle><icon name="info" visuallyHidden="info" [type]="'outlined'"></icon></a>
<div class="default-dropdown uk-margin-remove-top uk-dropdown" <mobile-dropdown [toggle]="toggle">
uk-dropdown="pos: bottom-left; mode:click"> <div class="uk-margin-remove-top">
<ng-container *ngTemplateOutlet="dropInfo; context: { item: item}"></ng-container> <ng-container *ngTemplateOutlet="dropInfo; context: { item: item}"></ng-container>
</div> </div>
</mobile-dropdown>
</div> </div>
</div> </div>

View File

@ -21,6 +21,7 @@ import {AlertModal} from "../../../utils/modal/alert";
[languages]="languages" [programmingLanguages]="programmingLanguages" [languages]="languages" [programmingLanguages]="programmingLanguages"
[compatibility]="compatibility" [aggregationStatus]="aggregationStatus" [compatibility]="compatibility" [aggregationStatus]="aggregationStatus"
[thematic]="thematic" [type]="type" [prevPath]="prevPath" [thematic]="thematic" [type]="type" [prevPath]="prevPath"
[countries]="countries" [projects]="projects"
></entity-metadata> ></entity-metadata>
</div> </div>
<div *ngIf="authors"> <div *ngIf="authors">
@ -61,4 +62,6 @@ export class LandingHeaderComponent {
@Input() thematic: boolean; // data provider landing @Input() thematic: boolean; // data provider landing
@Input() type; // data provider landing @Input() type; // data provider landing
@Input() prevPath: string = ""; @Input() prevPath: string = "";
@Input() countries;
@Input() projects;
} }

View File

@ -1,48 +0,0 @@
.metrics {
@import (reference) "~src/assets/openaire-theme/less/_import-variables";
position: relative;
display: inline-block;
.uk-text-primary {
color: @global-primary-background !important;
}
.uk-text-background {
background-image: @global-primary-gradient;
}
.uk-dropdown {
&::before {
position: absolute;
left: 0;
transform: translateX(-100%);
top: 14px;
width: 0;
height: 0;
content: '';
border-left: 21px solid transparent;
border-right: 21px solid @global-border;
border-bottom: 21px solid transparent;
border-top: 21px solid transparent;
}
&::after {
position: absolute;
left: 0;
transform: translateX(-100%);
top: 15px;
width: 0;
height: 0;
content: '';
border-left: 20px solid transparent;
border-right: 20px solid @global-background;
border-bottom: 20px solid transparent;
border-top: 20px solid transparent;
}
}
.m-badge img {
width: 35px;
}
}

View File

@ -1,331 +0,0 @@
import {Component, Input, Output, EventEmitter, ChangeDetectorRef} from '@angular/core';
import {Metrics} from '../../../utils/entities/metrics';
import {MetricsService} from '../../../services/metrics.service';
import {ErrorCodes} from '../../../utils/properties/errorCodes';
import {Subscription, zip} from 'rxjs';
import {EnvProperties} from '../../../utils/properties/env-properties';
import {ClickEvent} from "../../../utils/click/click-outside-or-esc.directive";
import {NumberUtils} from "../../../utils/number-utils.class";
import {OpenaireEntities} from "../../../utils/properties/searchFields";
import {StringUtils} from "../../../utils/string-utils.class";
import {properties} from "../../../../../environments/environment";
import {RouterHelper} from "../../../utils/routerHelper.class";
@Component({
selector: 'metrics',
template: `
<div *ngIf="metrics && (pageViews >0 || metrics.totalViews > 0|| metrics.totalDownloads >0)" class="metrics">
<a class="m-badge uk-link-reset uk-display-block" (click)="clickedMetrics()">
<img src="assets/common-assets/logo-small-usage-counts.png" loading="lazy" alt="usage counts">
<div class="uk-margin-xsmall-top uk-text-primary uk-text-small uk-text-bold uk-text-center">
<ng-container *ngIf="isNumberLarge(total, true); else notFormattedTotal">{{formatNumber(total)}}</ng-container>
<ng-template #notFormattedTotal>{{total | number}}</ng-template>
</div>
</a>
<div class="uk-dropdown uk-background-default" uk-dropdown="pos: right-top; mode: click; offset: 30; animation: uk-animation-fade">
<div class="uk-padding-small uk-width-large@s uk-width-medium">
<div *ngIf="entityType == 'projects'" class="uk-alert uk-alert-primary uk-margin-small-bottom">
<span class="uk-text-center uk-text-small">{{openaireEntities.PROJECT}} metrics
are derived from aggregating individual {{openaireEntities.RESULTS}} metrics.
</span>
</div>
<div class="uk-child-width-1-3@m uk-grid-small uk-grid-divider uk-margin-top" uk-grid>
<div class="uk-text-center">
<div class="number uk-text-bold uk-text-background">
<ng-container *ngIf="metrics.totalDownloads == 0">-</ng-container>
<span *ngIf="metrics.totalDownloads > 0" [attr.uk-tooltip]="metrics.totalDownloads >= 1000 ? 'cls: uk-active' : 'cls: uk-invisible'"
title="{{metrics.totalDownloads | number}}">{{formatNumber(metrics.totalDownloads)}}</span>
<!-- <ng-container *ngIf="isNumberLarge(metrics.totalDownloads); else notFormattedDownloads">{{formatNumber(metrics.totalDownloads)}}</ng-container>-->
<!-- <ng-template #notFormattedDownloads>{{metrics.totalDownloads | number}}</ng-template>-->
</div>
<div>Downloads</div>
</div>
<div class="uk-text-center">
<div class="number uk-text-bold uk-text-background">
<ng-container *ngIf="pageViews == 0">-</ng-container>
<span *ngIf="pageViews > 0" [attr.uk-tooltip]="pageViews >= 1000 ? 'cls: uk-active' : 'cls: uk-invisible'"
title="{{pageViews | number}}">{{formatNumber(pageViews)}}</span>
<!-- <ng-container *ngIf="isNumberLarge(pageViews); else notFormattedPageviews">{{formatNumber(pageViews)}}</ng-container>-->
<!-- <ng-template #notFormattedPageviews>{{pageViews | number}}</ng-template>-->
</div>
<div>OpenAIRE views</div>
</div>
<div class="uk-text-center">
<div class="number uk-text-bold uk-text-background">
<ng-container *ngIf="metrics.totalViews == 0">-</ng-container>
<span *ngIf="metrics.totalViews > 0" [attr.uk-tooltip]="metrics.totalViews >= 1000 ? 'cls: uk-active' : 'cls: uk-invisible'"
title="{{metrics.totalViews | number}}">{{formatNumber(metrics.totalViews)}}</span>
<!-- <ng-container *ngIf="isNumberLarge(metrics.totalViews); else notFormattedTotalviews">{{formatNumber(metrics.totalViews)}}</ng-container>-->
<!-- <ng-template #notFormattedTotalviews>{{metrics.totalViews | number}}</ng-template> -->
</div>
<div>Total views</div>
</div>
</div>
<div class="uk-padding">
<div *ngIf="metricsClicked && (metrics.infos?.size > 0 || (metrics.totalViews > 0 && viewsFrameUrl) || (metrics.totalDownloads > 0 && downloadsFrameUrl))"
class="uk-position-relative uk-visible-toggle uk-slider uk-margin-small-top" tabIndex="1" uk-slider>
<div class="uk-slider-container">
<ul class="uk-slider-items uk-child-width-1-1">
<li *ngIf="metrics && metrics.infos.size > 0" class="uk-overflow-auto" style="height: 200px">
<table
class="uk-table uk-table-small uk-table-striped">
<thead>
<tr>
<th class="uk-text-center uk-text-bold">From</th>
<th class="uk-text-center uk-text-bold">Views</th>
<th class="uk-text-center uk-text-bold">Downloads</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let key of getKeys(metrics.infos)">
<td class="uk-width-1-3 uk-text-center uk-text-truncate" uk-tooltip [title]="metrics.infos.get(key).name">
<a [queryParams]="addEoscPrevInParams({datasourceId: metrics.infos.get(key).url})" [routerLink]="properties.searchLinkToDataProvider.split('?')[0]">
{{metrics.infos.get(key).name}}
</a>
</td>
<td class="uk-text-center">
<ng-container *ngIf="isNumberLarge(metrics.infos.get(key).numOfViews, true); else notFormattedNumViews">{{formatNumber(metrics.infos.get(key).numOfViews)}}</ng-container>
<ng-template #notFormattedNumViews>{{metrics.infos.get(key).numOfViews | number}}</ng-template>
<!-- <span *ngIf="metrics.infos.get(key).numOfViews > 0 && metrics.infos.get(key).openaireViews > 0">
( {{metrics.infos.get(key).openaireViews | number}} from OpenAIRE )
</span>-->
</td>
<td class="uk-text-center">
<ng-container *ngIf="isNumberLarge(metrics.infos.get(key).numOfDownloads, true); else notFormattedNumDownloads">{{formatNumber(metrics.infos.get(key).numOfDownloads)}}</ng-container>
<ng-template #notFormattedNumDownloads>{{metrics.infos.get(key).numOfDownloads | number}}</ng-template>
<!--<span *ngIf="metrics.infos.get(key).numOfDownloads > 0 && metrics.infos.get(key).openaireDownloads > 0">
( {{metrics.infos.get(key).openaireDownloads | number}} from OpenAIRE )
</span>-->
</td>
</tr>
</tbody>
</table>
</li>
<!-- remove check for datasources when with the new charts -->
<li *ngIf="metricsClicked && metrics.totalViews > 0 && viewsFrameUrl">
<i-frame [height]="200" [url]=viewsFrameUrl [addClass]="false"
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply"></i-frame>
</li>
<li *ngIf="metricsClicked && metrics.totalDownloads > 0 && downloadsFrameUrl">
<i-frame [height]="200" [url]=downloadsFrameUrl [addClass]="false"
customContainerClass="uk-background-default" customIframeClass="uk-blend-multiply"></i-frame>
</li>
</ul>
</div>
<a class="uk-position-center-left-out" uk-slider-item="previous"><span uk-icon="icon: chevron-left; ratio: 2"></span></a>
<a class="uk-position-center-right-out" uk-slider-item="next"><span uk-icon="icon: chevron-right; ratio: 2"></span></a>
</div>
</div>
<div class="uk-flex uk-flex-center uk-flex-middle">
<span class="uk-margin-small-right uk-text-small uk-text-meta">Powered by</span>
<a href="https://usagecounts.openaire.eu" target="_blank">
<img width="120" src="assets/common-assets/logo-large-usage-counts.png" loading="lazy" alt="usage counts">
</a>
</div>
</div>
</div>
</div>
`,
styleUrls: ['metrics.component.less']
})
export class MetricsComponent {
@Input() prevPath: string = "";
@Output() metricsResults = new EventEmitter();
@Input() id: string;
@Input() entityType: string;
@Input() entity: string;
//@Input() name: string = "";
@Input() pageViews: number = 0;
@Input() properties: EnvProperties;
@Input() shortView: boolean = false;
@Input() open = false;
@Input() viewsFrameUrl: string;
@Input() downloadsFrameUrl: string;
public metrics: Metrics;
public errorCodes: ErrorCodes;
private sub: Subscription;
private timeouts: any[] = [];
public metricsClicked: boolean = false;
public status: number;
public state: number = -1;
public openaireEntities = OpenaireEntities;
public routerHelper:RouterHelper = new RouterHelper();
constructor(private metricsService: MetricsService, private cdr: ChangeDetectorRef) {
}
ngOnInit() {
this.errorCodes = new ErrorCodes();
if (typeof document !== 'undefined') {
this.status = this.errorCodes.LOADING;
this.getMetrics();
}
}
ngOnDestroy() {
if(this.sub) {
this.sub.unsubscribe();
}
}
public get total(): number {
return +this.pageViews + +this.metrics.totalViews + +this.metrics.totalDownloads;
}
private getMetrics() {
//queries from old API - replaced with queries to the stats tool
/* this.sub = this.metricsService.getMetrics(this.id, this.entityType, this.properties).subscribe(
data => {
this.metrics = data;
this.cdr.detectChanges();
this.status = this.errorCodes.DONE;
this.metricsResults.emit({
totalViews: this.metrics.totalViews,
totalDownloads: this.metrics.totalDownloads,
pageViews: this.metrics.pageViews
});
},
err => {
if (err.status == '404') {
this.status = this.errorCodes.NOT_FOUND;
} else if (err.status == '500') {
this.status = this.errorCodes.ERROR;
} else {
this.status = this.errorCodes.NOT_AVAILABLE;
}
this.metricsResults.emit({
totalViews: 0,
totalDownloads: 0
});
}
);*/
let obs;
if (this.entityType == "results") {
obs = zip(this.metricsService.getMetricsNumber(this.id, "usagestats.results.views", this.properties),
this.metricsService.getMetricsNumber(this.id, "usagestats.results.downloads", this.properties),
this.metricsService.getMetricsNumber(this.id, "usagestats.results.views.openaire", this.properties),
this.metricsService.getMetricsNumbersByRepository(this.id, "usagestats.results.viewsdownloads.repository", this.properties)
);
} else if (this.entityType == "projects") {
obs = zip(this.metricsService.getMetricsNumber(this.id, "usagestats.projects.views", this.properties),
this.metricsService.getMetricsNumber(this.id, "usagestats.projects.downloads", this.properties),
this.metricsService.getMetricsNumber(this.id, "usagestats.projects.views.openaire", this.properties));
} else if (this.entityType == "datasources") {
obs = zip(this.metricsService.getMetricsNumber(this.id, "usagestats.views.repository.local", this.properties),
this.metricsService.getMetricsNumber(this.id, "usagestats.downloads.repository.local", this.properties),
this.metricsService.getMetricsNumber(this.id, "usagestats.views.openaire", this.properties),
// this.metricsService.getMetricsNumber(this.id, "usagestats.downloads.repository.openaire", this.properties)
);
}
this.sub = obs.subscribe(
data => {
this.metrics = new Metrics();
this.metrics.infos = new Map<string, { "name": string, "url": string, "numOfDownloads": string, "numOfViews": string, "openaireDownloads": string, "openaireViews": string }>();
this.metrics.totalViews = data[0] ? data[0] : 0;
this.metrics.totalDownloads = data[1] ? data[1] : 0;
this.metrics.pageViews = data[2] ? data[2] : 0;
this.metrics.infos = data[3] ? data[3] : 0;
this.cdr.detectChanges();
this.status = this.errorCodes.DONE;
this.metricsResults.emit({
totalViews: this.metrics.totalViews,
totalDownloads: this.metrics.totalDownloads,
pageViews: this.metrics.pageViews
});
},
err => {
if (err.status == '404') {
this.status = this.errorCodes.NOT_FOUND;
} else if (err.status == '500') {
this.status = this.errorCodes.ERROR;
} else {
this.status = this.errorCodes.NOT_AVAILABLE;
}
this.metricsResults.emit({
totalViews: 0,
totalDownloads: 0,
pageViews: 0
});
}
);
}
public close(event: ClickEvent) {
if(event.clicked && this.state !== -1) {
this.timeouts.forEach(timeout => {
clearTimeout(timeout);
});
this.state = -1;
this.timeouts = [];
}
}
public clickedMetrics() {
setTimeout( () => {
this.metricsClicked = true;
});
}
public toggle(event) {
this.metricsClicked = true;
event.stopPropagation();
if(this.state !== -1) {
this.timeouts.forEach(timeout => {
clearTimeout(timeout);
});
this.state = -1;
this.timeouts = [];
} else {
this.state++;
this.timeouts.push(setTimeout(() => {
this.state++;
this.timeouts.push(setTimeout(() => {
this.state++;
this.timeouts.push(setTimeout(() => {
this.state++;
this.timeouts.push(setTimeout(() => {
this.state++;
}, 400));
}, 800));
}, 300));
}, 100));
}
this.cdr.detectChanges();
}
public getKeys(map) {
return Array.from(map.keys());
}
public isNumberLarge(num: number | string, bigNum: boolean = false) {
let limit: number = bigNum ? 100000000 : 100000;
return (+num) >= limit;
}
public formatNumber(num: number | string) {
let formatted = NumberUtils.roundNumber(+num);
return formatted.number + formatted.size;
}
public addEoscPrevInParams(obj) {
if(properties.adminToolsPortalType == "eosc" && this.prevPath) {
let splitted: string[] = this.prevPath.split("?");
obj = this.routerHelper.addQueryParam("return_path", splitted[0], obj);
if(splitted.length > 0) {
obj = this.routerHelper.addQueryParam("search_params", splitted[1], obj);
}
}
return obj;
}
}

View File

@ -1,29 +0,0 @@
/* This module contains all common components for all landing pages */
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {MetricsComponent} from './metrics.component';
import {MetricsService} from '../../../services/metrics.service';
import {ErrorMessagesModule} from '../../../utils/errorMessages.module';
import {IFrameModule} from "../../../utils/iframe.module";
import {IconsModule} from "../../../utils/icons/icons.module";
import {RouterModule} from "@angular/router";
@NgModule({
imports: [
CommonModule, FormsModule, RouterModule, ErrorMessagesModule, IFrameModule, IconsModule
],
declarations: [
MetricsComponent
],
providers:[
MetricsService
],
exports: [
MetricsComponent
]
})
export class MetricsModule { }

View File

@ -514,7 +514,8 @@ export class ParsingFunctions {
let identifiers = new Map<string, string[]>(); let identifiers = new Map<string, string[]>();
if (pid.hasOwnProperty("classid") && pid['classid'] != "") { if (pid.hasOwnProperty("classid") && pid['classid'] != "") {
if (pid.classid == "doi" || pid.classid == "pmc" || pid.classid == "handle" || pid.classid == "pmid" || pid.classid == "re3data") { if (pid.classid == "doi" || pid.classid == "pmc" || pid.classid == "handle" || pid.classid == "pmid" || pid.classid == "re3data"
|| pid.classid == "swhid") {
if (!identifiers.has(pid.classid)) { if (!identifiers.has(pid.classid)) {
identifiers.set(pid.classid, new Array<string>()); identifiers.set(pid.classid, new Array<string>());
} }
@ -522,7 +523,8 @@ export class ParsingFunctions {
} }
} else { } else {
for (let i = 0; i < pid.length; i++) { for (let i = 0; i < pid.length; i++) {
if (pid[i].classid == "doi" || pid[i].classid == "pmc" || pid[i].classid == "handle" || pid[i].classid == "pmid" || pid[i].classid == "re3data") { if (pid[i].classid == "doi" || pid[i].classid == "pmc" || pid[i].classid == "handle" || pid[i].classid == "pmid" || pid[i].classid == "re3data"
|| pid[i].classid == "swhid") {
if (!identifiers.has(pid[i].classid)) { if (!identifiers.has(pid[i].classid)) {
identifiers.set(pid[i].classid, new Array<string>()); identifiers.set(pid[i].classid, new Array<string>());
} }

View File

@ -1,8 +1,6 @@
import {Component, Input} from '@angular/core'; import {Component, Input} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {FetchProjects} from '../../utils/fetchEntitiesClasses/fetchProjects.class'; import {FetchProjects} from '../../utils/fetchEntitiesClasses/fetchProjects.class';
import {SearchProjectsService} from '../../services/searchProjects.service';
import {ErrorCodes} from '../../utils/properties/errorCodes'; import {ErrorCodes} from '../../utils/properties/errorCodes';
import {StringUtils} from '../../utils/string-utils.class'; import {StringUtils} from '../../utils/string-utils.class';
@ -18,7 +16,7 @@ import {OpenaireEntities} from '../../utils/properties/searchFields';
<ng-container *ngFor="let filter of fetchProjects.filters"> <ng-container *ngFor="let filter of fetchProjects.filters">
<div class="uk-inline"> <div class="uk-inline">
<dropdown-filter #dropdownFilter dropdownClass="uk-width-large uk-padding-small uk-margin-medium-bottom" <dropdown-filter #dropdownFilter dropdownClass="uk-width-large uk-padding-small uk-margin-medium-bottom"
[name]="filter.title" [count]="filter.countSelectedValues"> [name]="filter.title" [count]="filter.countSelectedValues" [isMobile]="isMobile">
<div class="uk-padding-small uk-overflow-auto uk-height-max-large uk-height-min-medium"> <div class="uk-padding-small uk-overflow-auto uk-height-max-large uk-height-min-medium">
<search-filter [filter]="filter" <search-filter [filter]="filter"
[showResultCount]=true filterValuesNum="0" [showResultCount]=true filterValuesNum="0"
@ -57,6 +55,7 @@ export class ProjectsInModalComponent {
@Input() organizationId: string = ""; @Input() organizationId: string = "";
@Input() properties: EnvProperties; @Input() properties: EnvProperties;
@Input() modal: AlertModal; @Input() modal: AlertModal;
@Input() isMobile: boolean = false;
public page: number = 1; public page: number = 1;
public size: number = 5; public size: number = 5;
@ -66,12 +65,7 @@ export class ProjectsInModalComponent {
private filterQuery: string = ""; private filterQuery: string = "";
public openaireEntities = OpenaireEntities; public openaireEntities = OpenaireEntities;
constructor(private route: ActivatedRoute,
private _searchProjectsService: SearchProjectsService) {
}
ngOnInit() { ngOnInit() {
if (this.organizationId) { if (this.organizationId) {
if (this.fetchProjects.searchUtils.totalResults > 0) { if (this.fetchProjects.searchUtils.totalResults > 0) {

View File

@ -19,14 +19,15 @@ import {AlertModalModule} from "../../utils/modal/alertModal.module";
import { SearchInputModule } from '../../sharedComponents/search-input/search-input.module'; import { SearchInputModule } from '../../sharedComponents/search-input/search-input.module';
import {EntityMetadataComponent} from "./entity-metadata.component"; import {EntityMetadataComponent} from "./entity-metadata.component";
import {IconsService} from "../../utils/icons/icons.service"; import {IconsService} from "../../utils/icons/icons.service";
import {closed_access, open_access, unknown_access} from "../../utils/icons/icons"; import {book, closed_access, cog, database, earth, open_access, unknown_access} from "../../utils/icons/icons";
import {FullScreenModalModule} from "../../utils/modal/full-screen-modal/full-screen-modal.module"; import {FullScreenModalModule} from "../../utils/modal/full-screen-modal/full-screen-modal.module";
import {MobileDropdownModule} from "../../utils/mobile-dropdown/mobile-dropdown.module";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, FormsModule, RouterModule, PagingModule, ShowPublisherModule, IconsModule, AlertModalModule, CommonModule, FormsModule, RouterModule, PagingModule, ShowPublisherModule, IconsModule, AlertModalModule,
SearchInputModule, FullScreenModalModule SearchInputModule, FullScreenModalModule, MobileDropdownModule
], ],
declarations: [ declarations: [
ShowIdentifiersComponent,ShowSubjectsComponent, ShowIdentifiersComponent,ShowSubjectsComponent,
@ -44,6 +45,6 @@ import {FullScreenModalModule} from "../../utils/modal/full-screen-modal/full-sc
}) })
export class ResultLandingUtilsModule { export class ResultLandingUtilsModule {
constructor(private iconsService: IconsService) { constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([open_access, closed_access, unknown_access]); this.iconsService.registerIcons([open_access, closed_access, unknown_access, book, cog, database, earth]);
} }
} }

View File

@ -46,19 +46,26 @@ import {StringUtils} from "../../utils/string-utils.class";
</div> </div>
</div> </div>
<div class="uk-hidden@m"> <div class="uk-hidden@m">
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div> <div *ngIf="!viewAll">
<div class="uk-flex uk-flex-middle uk-flex-wrap"> <div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
<img src="assets/common-assets/common/The_Global_Goals_Icon_Color.svg" <div class="uk-flex uk-flex-middle uk-flex-wrap">
loading="lazy" alt="sdg_colors" style="width:18px; height:18px"> <img src="assets/common-assets/common/The_Global_Goals_Icon_Color.svg"
<span class="uk-margin-xsmall-left uk-margin-xsmall-right uk-text-meta">SDGs:</span> loading="lazy" alt="sdg_colors" style="width:18px; height:18px">
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate"> <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>
<div *ngIf="viewAll">
<div *ngFor="let subject of subjects; let i=index" class="uk-text-truncate">
<a [routerLink]=" properties.searchLinkToResults" [queryParams]="{'sdg': urlEncodeAndQuote(subject)}">{{subject}}</a> <a [routerLink]=" properties.searchLinkToResults" [queryParams]="{'sdg': urlEncodeAndQuote(subject)}">{{subject}}</a>
<span *ngIf="(viewAll && i<subjects.length-1) || i<threshold-1">, &nbsp;</span>
</div> </div>
<!-- <div> </div>
{{subjects.slice(0, viewAll?subjects.length:threshold).join(", ")}}
</div> -->
</div>
<div class="uk-text-right uk-margin-small-top"> <div class="uk-text-right uk-margin-small-top">
<a *ngIf="subjects && subjects.length > threshold && !viewAll" <a *ngIf="subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-link uk-text-truncate"> (click)="viewAllClick();" class="view-more-less-link uk-link uk-text-truncate">

View File

@ -26,7 +26,7 @@ import {properties} from "../../../../environments/environment";
<span class="uk-text-meta uk-text-small" [class.uk-text-uppercase]="key != 're3data'">{{key}}: </span> <span class="uk-text-meta uk-text-small" [class.uk-text-uppercase]="key != 're3data'">{{key}}: </span>
<span [class.uk-margin-small-left]="modal"> <span [class.uk-margin-small-left]="modal">
<ng-container *ngFor="let item of identifiers.get(key) let j=index"> <ng-container *ngFor="let item of identifiers.get(key) let j=index">
<a *ngIf="key == 'doi' || key == 'pmc' || key == 'pmid' || key == 'handle' || key == 're3data'" <a *ngIf="key == 'doi' || key == 'pmc' || key == 'pmid' || key == 'handle' || key == 're3data' || key == 'swhid'"
[href]="getUrl(key) + item" target="_blank" class="uk-display-inline-block custom-external"> [href]="getUrl(key) + item" target="_blank" class="uk-display-inline-block custom-external">
{{item}} {{item}}
</a> </a>
@ -53,7 +53,7 @@ import {properties} from "../../../../environments/environment";
</div> </div>
</modal-alert> </modal-alert>
<fs-modal *ngIf="isMobile" #identifiersModal> <fs-modal *ngIf="isMobile" #identifiersModal classTitle="uk-tile-default uk-border-bottom">
<div class="uk-text-small"> <div class="uk-text-small">
<ng-container *ngTemplateOutlet="identifiers_template; context: { modal: true}"></ng-container> <ng-container *ngTemplateOutlet="identifiers_template; context: { modal: true}"></ng-container>
</div> </div>
@ -124,6 +124,8 @@ export class ShowIdentifiersComponent implements AfterViewInit {
return properties.handleURL; return properties.handleURL;
} else if(key == "re3data") { } else if(key == "re3data") {
return properties.r3DataURL; return properties.r3DataURL;
} else if(key == "swhid") {
return properties.swhURL;
} }
} }

View File

@ -4,6 +4,12 @@ import {EnvProperties} from "../../utils/properties/env-properties";
@Component({ @Component({
selector: 'showPublisher, [showPublisher]', selector: 'showPublisher, [showPublisher]',
template: ` template: `
<ng-container *ngIf="publisher">
<span [attr.uk-tooltip]="'cls: uk-active'" [title]="'Publisher'">{{publisher}}</span>
<span *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
|| journal['volume'] || journal['eissn'] || journal['issue'])"
class="uk-margin-xsmall-left uk-margin-xsmall-right bullet"></span>
</ng-container>
<ng-container *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn'] <ng-container *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
|| journal['volume'] || journal['eissn'] || journal['issue'])"> || journal['volume'] || journal['eissn'] || journal['issue'])">
<ng-container *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn'] <ng-container *ngIf="journal && (journal['journal'] || journal['issn'] || journal['lissn']
@ -64,10 +70,6 @@ import {EnvProperties} from "../../utils/properties/env-properties";
<span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])">)</span> <span *ngIf=" journal['journal'] && (journal['issn'] || journal['eissn'] || journal['lissn'])">)</span>
</span> </span>
</ng-container> </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> </ng-container>
` `
}) })

View File

@ -208,7 +208,7 @@
<!-- Tabs content section --> <!-- Tabs content section -->
<div id="landing-sections" class="uk-text-small"> <div id="landing-sections" class="uk-text-small">
<div id="projects" class="landing-section landing-section-height-auto"> <div id="projects" class="landing-section landing-section-height-auto">
<projectsInModal [fetchProjects]="fetchProjects" <projectsInModal [fetchProjects]="fetchProjects" [isMobile]="isMobile"
[organizationId]="organizationId" [properties]=properties [prevPath]="prevPath"> [organizationId]="organizationId" [properties]=properties [prevPath]="prevPath">
</projectsInModal> </projectsInModal>
</div> </div>
@ -336,44 +336,54 @@
</div> </div>
<div *ngIf="mobileContent == 'actions'" class="uk-container uk-section"> <div *ngIf="mobileContent == 'actions'" class="uk-container uk-section">
<ng-container *ngIf="organizationInfo?.deletedByInferenceIds"> <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" <div class="uk-padding-small uk-padding-remove-horizontal">
(click)="deleteByInferenceOpened = true; openFsModal(alertModalDeletedByInferenceFS, 'Other versions')"> <div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove"
<icon [flex]="true" name="versions" visuallyHidden="versions"></icon> (click)="deleteByInferenceOpened = true; openFsModal(alertModalDeletedByInferenceFS, 'Other versions')">
<span class="uk-margin-small-left"> <icon [flex]="true" name="versions" visuallyHidden="versions"></icon>
View all {{organizationInfo.deletedByInferenceIds.length}} versions <span class="uk-margin-small-left">
</span> View all {{organizationInfo.deletedByInferenceIds.length}} versions
</span>
</div>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
<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" <div class="uk-padding-small uk-padding-remove-horizontal">
(click)="openFsModal(addThisFsModal, 'Share this '+openaireEntities.ORGANIZATION+' in your social networks')"> <div class="clickable" (click)="openFsModal(addThisFsModal, 'Share this '+openaireEntities.ORGANIZATION+' in your social networks')">
<icon [flex]="true" name="share" visuallyHidden="share"></icon> <div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
<span class="uk-margin-small-left">Share</span> <icon [flex]="true" name="share" visuallyHidden="share"></icon>
<span class="uk-margin-small-left">Share</span>
</div>
<div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall">Share this {{openaireEntities.ORGANIZATION}} in your social networks</div>
</div>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
<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" <div class="uk-padding-small uk-padding-remove-horizontal">
(click)="buildFunderOptions(); openFsModal(downloadReportsFsModal, 'Download')"> <div class="clickable" (click)="buildFunderOptions(); openFsModal(downloadReportsFsModal, 'Download')">
<icon [flex]="true" name="download" visuallyHidden="download"></icon> <div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
<span class="uk-margin-small-left">Download</span> <icon [flex]="true" name="download" visuallyHidden="download"></icon>
<span class="uk-margin-small-left">Download</span>
</div>
<div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall">Download reports</div>
</div>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
</div> </div>
<div class="landing-action-bar-mobile uk-background-default"> <div class="landing-action-bar-mobile uk-tile-default uk-blur-background">
<div class="uk-container uk-grid uk-flex-middle uk-child-width-1-2 uk-text-xsmall uk-text-meta"> <div class="uk-container uk-grid uk-flex-middle uk-child-width-1-2 uk-text-xsmall uk-text-meta">
<div> <div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'; scroll()">
<icon name="corporate_fare" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"></icon> <icon name="corporate_fare" type="outlined" [flex]="true" [ratio]="1.4" [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"></icon>
<span>{{openaireEntities.ORGANIZATION}}</span> <span>{{openaireEntities.ORGANIZATION}}</span>
</a> </a>
</div> </div>
<div> <div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'actions'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'actions'; scroll()">
<icon name="pending" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'actions' ? 'uk-text-primary': ''"></icon> <icon name="pending" type="outlined" [flex]="true" [ratio]="1.4" [ngClass]="mobileContent == 'actions' ? 'uk-text-primary': ''"></icon>
<span>Actions</span> <span>Actions</span>
</a> </a>
</div> </div>
@ -533,7 +543,7 @@
<fs-modal *ngIf="isMobile" #fsModal classTitle="uk-tile-default uk-border-bottom"> <fs-modal *ngIf="isMobile" #fsModal classTitle="uk-tile-default uk-border-bottom">
<div *ngIf="activeTab == 'projects'" class="landing-section landing-section-height-auto"> <div *ngIf="activeTab == 'projects'" class="landing-section landing-section-height-auto">
<projectsInModal [fetchProjects]="fetchProjects" <projectsInModal [fetchProjects]="fetchProjects" [isMobile]="isMobile"
[organizationId]="organizationId" [properties]=properties [prevPath]="prevPath"> [organizationId]="organizationId" [properties]=properties [prevPath]="prevPath">
</projectsInModal> </projectsInModal>
</div> </div>

View File

@ -512,69 +512,90 @@
</div> </div>
<div *ngIf="mobileContent == 'actions'" class="uk-container uk-section"> <div *ngIf="mobileContent == 'actions'" class="uk-container uk-section">
<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" <div class="uk-padding-small uk-padding-remove-horizontal">
(click)="openFsModal(addThisFsModal, 'Share this '+openaireEntities.PROJECT+' in your social networks')"> <div class="clickable" (click)="openFsModal(addThisFsModal, 'Share this '+openaireEntities.PROJECT+' in your social networks')">
<icon [flex]="true" name="share" visuallyHidden="share"></icon> <div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
<span class="uk-margin-small-left">Share</span> <icon [flex]="true" name="share" visuallyHidden="share"></icon>
<span class="uk-margin-small-left">Share</span>
</div>
<div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall">Share this {{openaireEntities.PROJECT}} in your social networks</div>
</div>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
<ng-container *ngIf="isRouteAvailable('participate/deposit/learn-how')"> <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" <div class="uk-padding-small uk-padding-remove-horizontal">
routerLinkActive="router-link-active" routerLink="/participate/deposit/learn-how"> <a class="uk-link-reset" routerLinkActive="router-link-active" routerLink="/participate/deposit/learn-how">
<icon [flex]="true" name="upload" visuallyHidden="upload"></icon> <div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
<span class="uk-margin-small-left"> <icon [flex]="true" name="upload" visuallyHidden="upload"></icon>
Deposit <span class="uk-margin-small-left">
</span> Deposit
</a> </span>
<hr class="uk-margin-remove"> </div>
</ng-container> <div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall"><span class="uk-flex uk-flex-middle">Deposit your research</span></div>
<ng-container> </a>
<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> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
<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" <div class="uk-padding-small uk-padding-remove-horizontal">
(click)="openFsModal(downloadReportFsModal, 'Download report')"> <div class="clickable" (click)="openFsModal(embedResultsFsModal, 'Embed results')">
<icon [flex]="true" name="download" visuallyHidden="download"></icon> <div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
<span class="uk-margin-small-left">Download</span> <icon [flex]="true" name="code" visuallyHidden="code"></icon>
<span class="uk-margin-small-left">Embed</span>
</div>
<div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall">Emded results</div>
</div>
</div>
<hr class="uk-margin-remove">
</ng-container>
<ng-container>
<div class="uk-padding-small uk-padding-remove-horizontal">
<div class="clickable" (click)="openFsModal(downloadReportFsModal, 'Download report')">
<div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
<icon [flex]="true" name="download" visuallyHidden="download"></icon>
<span class="uk-margin-small-left">Download</span>
</div>
<div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall">Download report</div>
</div>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
<ng-container *ngIf="isRouteAvailable('participate/direct-claim')"> <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" <div class="uk-padding-small uk-padding-remove-horizontal">
[queryParams]="routerHelper.createQueryParams(['id','type','linkTo'],[projectId, 'project','result'])" <a class="uk-link-reset"
routerLinkActive="router-link-active" routerLink="/participate/direct-claim"> [queryParams]="routerHelper.createQueryParams(['id','type','linkTo'],[projectId, 'project','result'])"
<icon [flex]="true" name="link_to" visuallyHidden="link"></icon> routerLinkActive="router-link-active" routerLink="/participate/direct-claim">
<span class="uk-margin-small-left"> <div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
Link to <icon [flex]="true" name="link_to" visuallyHidden="link"></icon>
</span> <span class="uk-margin-small-left">
</a> Link to
</span>
</div>
<div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall"><span class="uk-flex uk-flex-middle">Link this project to {{openaireEntities.RESULTS}}</span></div>
</a>
</div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
</div> </div>
<div class="landing-action-bar-mobile uk-background-default"> <div class="landing-action-bar-mobile uk-tile-default uk-blur-background">
<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 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> <div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'; scroll()">
<icon name="assignment_turned_in" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"></icon> <icon name="assignment_turned_in" type="outlined" [flex]="true" [ratio]="1.4" [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"></icon>
<span>{{openaireEntities.PROJECT}}</span> <span>{{openaireEntities.PROJECT}}</span>
</a> </a>
</div> </div>
<div *ngIf="projectInfo && hasMetrics"> <div *ngIf="projectInfo && hasMetrics">
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'metrics'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'metrics'; scroll()">
<icon name="bar_chart" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'metrics' ? 'uk-text-primary': ''"></icon> <icon name="bar_chart" type="outlined" [flex]="true" [ratio]="1.4" [ngClass]="mobileContent == 'metrics' ? 'uk-text-primary': ''"></icon>
<span>Metrics</span> <span>Metrics</span>
</a> </a>
</div> </div>
<div> <div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'actions'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'actions'; scroll()">
<icon name="pending" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'actions' ? 'uk-text-primary': ''"></icon> <icon name="pending" type="outlined" [flex]="true" [ratio]="1.4" [ngClass]="mobileContent == 'actions' ? 'uk-text-primary': ''"></icon>
<span>Actions</span> <span>Actions</span>
</a> </a>
</div> </div>

View File

@ -464,6 +464,7 @@ export class ProjectComponent {
this.subscriptions.push(this._projectService.getProjectInfo(id, this.properties).subscribe( this.subscriptions.push(this._projectService.getProjectInfo(id, this.properties).subscribe(
data => { data => {
this.projectInfo = data; this.projectInfo = data;
this.projectInfo.id = this.projectId;
this.actionsAfterGettingProjectInfo(); this.actionsAfterGettingProjectInfo();
}, },

View File

@ -1,4 +1,3 @@
//import {MaterialModule} from '@angular/material';
import {NgModule} from '@angular/core'; import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
@ -10,8 +9,6 @@ import {ProjectServiceModule} from './projectService.module';
import {HtmlProjectReportService} from "../htmlProjectReport/htmlProjectReport.service"; import {HtmlProjectReportService} from "../htmlProjectReport/htmlProjectReport.service";
import {ReportsServiceModule} from '../../services/reportsService.module'; import {ReportsServiceModule} from '../../services/reportsService.module';
import {SearchResearchResultsServiceModule} from '../../services/searchResearchResultsService.module'; import {SearchResearchResultsServiceModule} from '../../services/searchResearchResultsService.module';
import {MetricsModule} from '../landing-utils/metrics/metrics.module';
import {LandingModule} from '../landing-utils/landing.module'; import {LandingModule} from '../landing-utils/landing.module';
import {LandingHeaderModule} from "../landing-utils/landing-header/landing-header.module"; import {LandingHeaderModule} from "../landing-utils/landing-header/landing-header.module";
@ -41,7 +38,7 @@ import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.mod
imports: [ imports: [
CommonModule, FormsModule, RouterModule, LandingModule, CommonModule, FormsModule, RouterModule, LandingModule,
LoadingModalModule, AlertModalModule, ErrorMessagesModule, LoadingModalModule, AlertModalModule, ErrorMessagesModule,
IFrameModule, MetricsModule, ReportsServiceModule, IFrameModule, ReportsServiceModule,
SearchResearchResultsServiceModule, ProjectServiceModule, SearchResearchResultsServiceModule, ProjectServiceModule,
Schema2jsonldModule, SEOServiceModule, HelperModule, Schema2jsonldModule, SEOServiceModule, HelperModule,
LandingHeaderModule, MatSelectModule, FeedbackModule, AltMetricsModule, LandingHeaderModule, MatSelectModule, FeedbackModule, AltMetricsModule,

View File

@ -3,7 +3,7 @@
<div *ngIf="!isMobile" class="tm-main"> <div *ngIf="!isMobile" class="tm-main">
<div class="publication"> <div class="publication">
<div *ngIf="properties.adminToolsPortalType == 'eosc'" class="eosc-explore-back-search-bar"> <div *ngIf="properties.adminToolsPortalType == 'eosc'" class="eosc-explore-back-search-bar">
<div class="uk-light uk-container uk-container-large uk-padding-small uk-height-1-1"> <div class="uk-light uk-container uk-container-large uk-margin-left uk-height-1-1">
<div class="uk-flex uk-flex-inline uk-flex-middle uk-height-1-1"> <div class="uk-flex uk-flex-inline uk-flex-middle uk-height-1-1">
<a [href]="eoscBackLink" target="_self" class="uk-link-reset uk-flex uk-flex-middle uk-text-light uk-text-small"> <a [href]="eoscBackLink" target="_self" class="uk-link-reset uk-flex uk-flex-middle uk-text-light uk-text-small">
<icon name="arrow_back" visuallyHidden="back" flex="true" ratio="0.7" customClass="uk-text-light"></icon> <icon name="arrow_back" visuallyHidden="back" flex="true" ratio="0.7" customClass="uk-text-light"></icon>
@ -205,7 +205,7 @@
</orcid-work> </orcid-work>
</div> </div>
<div *ngIf=" properties.enableEoscDataTransfer && resultLandingInfo.resultType == 'dataset' && <div *ngIf=" properties.enableEoscDataTransfer && resultLandingInfo.resultType == 'dataset' &&
resultLandingInfo.identifiers && resultLandingInfo.identifiers.get('doi') && resultLandingInfo.identifiers && resultLandingInfo.identifiers.get('doi') &&
resultLandingInfo.identifiers.get('doi').join('').indexOf('zenodo.')!=-1" resultLandingInfo.identifiers.get('doi').join('').indexOf('zenodo.')!=-1"
class=""> class="">
<egi-transfer-data [dois]="resultLandingInfo.identifiers.get('doi')" [isOpen]="egiTransferModalOpen"></egi-transfer-data> <egi-transfer-data [dois]="resultLandingInfo.identifiers.get('doi')" [isOpen]="egiTransferModalOpen"></egi-transfer-data>
@ -213,7 +213,10 @@
</div> </div>
<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0" <helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
[texts]="pageContents['top']"></helper> [texts]="pageContents['top']"></helper>
<i class="uk-text-meta uk-text-xsmall" *ngIf="properties.adminToolsPortalType == 'eosc' && !belongsInEOSC && properties.environment !== 'production'">
This {{getTypeName() | lowercase}} is not part of the European Open Science Cloud
</i>
<landing-header [properties]="properties" [title]="resultLandingInfo.title" <landing-header [properties]="properties" [title]="resultLandingInfo.title"
[subTitle]="resultLandingInfo.subtitle" [subTitle]="resultLandingInfo.subtitle"
[authors]="resultLandingInfo.authors" [authors]="resultLandingInfo.authors"
@ -222,7 +225,8 @@
[date]="resultLandingInfo.dateofacceptance" [embargoEndDate]="resultLandingInfo.embargoEndDate" [date]="resultLandingInfo.dateofacceptance" [embargoEndDate]="resultLandingInfo.embargoEndDate"
[publisher]="resultLandingInfo.publisher" [journal]="resultLandingInfo.journal" [publisher]="resultLandingInfo.publisher" [journal]="resultLandingInfo.journal"
[languages]="resultLandingInfo.languages" [programmingLanguages]="resultLandingInfo.programmingLanguages" [languages]="resultLandingInfo.languages" [programmingLanguages]="resultLandingInfo.programmingLanguages"
[prevPath]="prevPath"> [prevPath]="prevPath" [countries]="resultLandingInfo.countries"
[projects]="resultLandingInfo.fundedByProjects">
</landing-header> </landing-header>
<!-- Labels --> <!-- Labels -->
<!-- Not used anymore - access labels will be in action bars, languages in the landing-header component --> <!-- Not used anymore - access labels will be in action bars, languages in the landing-header component -->
@ -488,6 +492,16 @@
<!-- Mobile view --> <!-- Mobile view -->
<div *ngIf="isMobile" class="uk-hidden@m uk-position-relative landing"> <div *ngIf="isMobile" class="uk-hidden@m uk-position-relative landing">
<ng-container *ngIf="resultLandingInfo"> <ng-container *ngIf="resultLandingInfo">
<div *ngIf="properties.adminToolsPortalType == 'eosc'" class="eosc-explore-back-search-bar">
<div class="uk-light uk-container uk-height-1-1">
<div class="uk-flex uk-flex-inline uk-flex-middle uk-height-1-1">
<a [href]="eoscBackLink" target="_self" class="uk-link-reset uk-flex uk-flex-middle uk-text-light uk-text-small">
<icon name="arrow_back" visuallyHidden="back" flex="true" ratio="0.7" customClass="uk-text-light"></icon>
<span class="uk-margin-small-left">Go to Search</span>
</a>
</div>
</div>
</div>
<div *ngIf="mobileContent == 'info'" class="uk-container uk-section"> <div *ngIf="mobileContent == 'info'" class="uk-container uk-section">
<div *ngIf="resultLandingInfo.hostedBy_collectedFrom && resultLandingInfo.hostedBy_collectedFrom.length > 0" <div *ngIf="resultLandingInfo.hostedBy_collectedFrom && resultLandingInfo.hostedBy_collectedFrom.length > 0"
class="uk-margin-small-bottom uk-flex uk-flex-middle" class="uk-margin-small-bottom uk-flex uk-flex-middle"
@ -495,6 +509,9 @@
<icon [name]="resultLandingInfo.hostedBy_collectedFrom[0].accessRightIcon" [flex]="true" [ratio]="1"></icon> <icon [name]="resultLandingInfo.hostedBy_collectedFrom[0].accessRightIcon" [flex]="true" [ratio]="1"></icon>
<span class="uk-margin-xsmall-left uk-text-small uk-text-uppercase uk-text-bolder">{{getAccessLabel(resultLandingInfo.hostedBy_collectedFrom[0].accessRight)}}</span> <span class="uk-margin-xsmall-left uk-text-small uk-text-uppercase uk-text-bolder">{{getAccessLabel(resultLandingInfo.hostedBy_collectedFrom[0].accessRight)}}</span>
</div> </div>
<i class="uk-text-meta uk-text-xsmall" *ngIf="properties.adminToolsPortalType == 'eosc' && !belongsInEOSC && properties.environment !== 'production'">
This {{getTypeName() | lowercase}} is not part of the European Open Science Cloud
</i>
<landing-header [properties]="properties" [title]="resultLandingInfo.title" <landing-header [properties]="properties" [title]="resultLandingInfo.title"
[subTitle]="resultLandingInfo.subtitle" [subTitle]="resultLandingInfo.subtitle"
[authors]="resultLandingInfo.authors" [authors]="resultLandingInfo.authors"
@ -564,6 +581,7 @@
<span>Compatible EOSC Services</span> <span>Compatible EOSC Services</span>
<icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon> <icon name="chevron_right" [ratio]="1.5" [flex]="true"></icon>
</div> </div>
<hr>
</ng-container> </ng-container>
<ng-container *ngIf="resultLandingInfo.fundedByProjects && resultLandingInfo.fundedByProjects.length > 0 && (!viewAll || viewAll=='fundedBy')"> <ng-container *ngIf="resultLandingInfo.fundedByProjects && resultLandingInfo.fundedByProjects.length > 0 && (!viewAll || viewAll=='fundedBy')">
<div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(fundedByFsModal, 'Funded by'); onSelectActiveTab('summary')"> <div class="clickable uk-flex uk-flex-middle uk-flex-between" (click)="openFsModal(fundedByFsModal, 'Funded by'); onSelectActiveTab('summary')">
@ -593,88 +611,118 @@
</div> </div>
<div *ngIf="mobileContent == 'actions'" class="uk-container uk-section"> <div *ngIf="mobileContent == 'actions'" class="uk-container uk-section">
<ng-container *ngIf="resultLandingInfo?.hostedBy_collectedFrom"> <ng-container *ngIf="resultLandingInfo?.hostedBy_collectedFrom">
<div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal" <div class="uk-padding-small uk-padding-remove-horizontal">
(click)=" onSelectActiveTab('availableOn')"> <div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove"
<availableOn [availableOn]="resultLandingInfo.hostedBy_collectedFrom" (viewAllClicked)="viewAll=$event" (click)=" onSelectActiveTab('availableOn')">
[isMobile]="true" [usedBy]="'landing'" class="uk-width-1-1" [prevPath]="prevPath"></availableOn> <availableOn [availableOn]="resultLandingInfo.hostedBy_collectedFrom" (viewAllClicked)="viewAll=$event"
[isMobile]="true" [usedBy]="'landing'" class="uk-width-1-1" [prevPath]="prevPath"></availableOn>
</div>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
<ng-container *ngIf="resultLandingInfo?.deletedByInferenceIds"> <ng-container *ngIf="resultLandingInfo?.deletedByInferenceIds">
<div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal" <div class="uk-padding-small uk-padding-remove-horizontal">
(click)="deleteByInferenceOpened = true; openFsModal(alertModalDeletedByInferenceFS, 'Other versions')"> <div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove"
<icon [flex]="true" name="versions" visuallyHidden="versions"></icon> (click)="deleteByInferenceOpened = true; openFsModal(alertModalDeletedByInferenceFS, 'Other versions')">
<span class="uk-margin-small-left"> <icon [flex]="true" name="versions" visuallyHidden="versions"></icon>
View all {{resultLandingInfo.deletedByInferenceIds.length}} versions <span class="uk-margin-small-left">
</span> View all {{resultLandingInfo.deletedByInferenceIds.length}} versions
</span>
</div>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
<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" <div class="uk-padding-small uk-padding-remove-horizontal">
(click)="openFsModal(addThisFsModal, 'Share this '+getTypeName()+' in your social networks')"> <div class="clickable"
<icon [flex]="true" name="share" visuallyHidden="share"></icon> (click)="openFsModal(addThisFsModal, 'Share this '+getTypeName()+' in your social networks')">
<span class="uk-margin-small-left">Share</span> <div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
<icon [flex]="true" name="share" visuallyHidden="share"></icon>
<span class="uk-margin-small-left">Share</span>
</div>
<div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall">Share this {{getTypeName()}} in your social networks</div>
</div>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
<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" <div class="uk-padding-small uk-padding-remove-horizontal">
(click)="citeThisClicked=true; openFsModal(citeFsModal, 'Cite this '+getTypeName())"> <div class="clickable"
<icon [flex]="true" name="cite" visuallyHidden="cite"></icon> (click)="citeThisClicked=true; openFsModal(citeFsModal, 'Cite this '+getTypeName())">
<span class="uk-margin-small-left">Cite</span> <div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
<icon [flex]="true" name="cite" visuallyHidden="cite"></icon>
<span class="uk-margin-small-left">Cite</span>
</div>
<div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall">Cite this {{getTypeName()}}</div>
</div>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
<ng-container *ngIf="properties.adminToolsPortalType == 'explore' || properties.adminToolsPortalType == 'community' || properties.adminToolsPortalType == 'aggregator'" > <ng-container *ngIf="properties.adminToolsPortalType == 'explore' || properties.adminToolsPortalType == 'community' || properties.adminToolsPortalType == 'aggregator'" >
<div class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove uk-padding-small uk-padding-remove-horizontal"> <div class="uk-padding-small uk-padding-remove-horizontal ">
<orcid-work [resultId]="id" [resultTitle]="resultLandingInfo?.title" [resultLandingInfo]="resultLandingInfo" <orcid-work [resultId]="id" [resultTitle]="resultLandingInfo?.title" [resultLandingInfo]="resultLandingInfo"
[pids]="pidsArrayString" [pageType]="'landing'" [isMobile]="true"> [pids]="pidsArrayString" [pageType]="'landing'" [isMobile]="true"
class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove">
</orcid-work> </orcid-work>
</div> </div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
<ng-container *ngIf="isRouteAvailable('participate/direct-claim')"> <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" <div class="uk-padding-small uk-padding-remove-horizontal">
[queryParams]="routerHelper.createQueryParams(['id','type','linkTo'],[id,type,'project'])" <a class="uk-link-reset uk-margin-remove"
routerLinkActive="router-link-active" routerLink="/participate/direct-claim"> [queryParams]="routerHelper.createQueryParams(['id','type','linkTo'],[id,type,'project'])"
<icon [flex]="true" name="link_to" visuallyHidden="link"></icon> routerLinkActive="router-link-active" routerLink="/participate/direct-claim">
<span class="uk-margin-small-left" <div class="uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-xsmall-bottom">
[title]="'<span class=\'uk-flex uk-flex-middle\'>Link this '+getTypeName()+' to ...<span class=\'material-icons uk-margin-small-left\'>east</span></span>'" <icon [flex]="true" name="link_to" visuallyHidden="link"></icon>
[attr.uk-tooltip]="'pos: bottom-left; cls: uk-active uk-text-small uk-padding-small'"> <span class="uk-margin-small-left">
Link to Link to
</span> </span>
</a> </div>
<div class="uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall">
<span class="uk-flex uk-flex-middle">Link this {{getTypeName()}} to ...</span>
</div>
</a>
</div>
<hr class="uk-margin-remove">
</ng-container>
<ng-container>
<div class="uk-padding-small uk-padding-remove-horizontal">
<div *ngIf="properties.enableEoscDataTransfer && resultLandingInfo.resultType == 'dataset' &&
resultLandingInfo.identifiers && resultLandingInfo.identifiers.get('doi') &&
resultLandingInfo.identifiers.get('doi').join('').indexOf('zenodo.')!=-1"
class="clickable uk-button-link uk-flex uk-flex-middle uk-h6 uk-margin-remove">
<egi-transfer-data class="uk-width-1-1" [dois]="resultLandingInfo.identifiers.get('doi')" [isOpen]="egiTransferModalOpen" [isMobile]="true"></egi-transfer-data>
</div>
</div>
<hr class="uk-margin-remove"> <hr class="uk-margin-remove">
</ng-container> </ng-container>
</div> </div>
<div class="landing-action-bar-mobile uk-background-default"> <div class="landing-action-bar-mobile uk-tile-default uk-blur-background">
<div class="uk-container uk-flex-middle uk-grid uk-text-xsmall uk-text-meta" [ngClass]="(resultLandingInfo.measure || hasAltMetrics) ? 'uk-child-width-1-3' : 'uk-child-width-1-2'"> <div class="uk-container uk-flex-middle uk-grid uk-text-xsmall uk-text-meta" [ngClass]="(resultLandingInfo.measure || hasAltMetrics) ? 'uk-child-width-1-3' : 'uk-child-width-1-2'">
<div> <div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'info'; egiTransferModalOpen = false; scroll();">
<span [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''"> <span [ngClass]="mobileContent == 'info' ? 'uk-text-primary': ''">
<icon *ngIf="getTypeName().toLowerCase() == 'publication'" name="description" type="outlined" [flex]="true" [ratio]="2"></icon> <icon *ngIf="getTypeName().toLowerCase() == 'publication'" name="description" type="outlined" [flex]="true" [ratio]="1.4"></icon>
<icon *ngIf="getTypeName().toLowerCase() == 'research data'" name="database" type="outlined" [flex]="true" [ratio]="2"></icon> <icon *ngIf="getTypeName().toLowerCase() == 'research data'" name="database" type="outlined" [flex]="true" [ratio]="1.4"></icon>
<icon *ngIf="getTypeName().toLowerCase() == 'research software'" name="integration_instructions" type="outlined" [flex]="true" [ratio]="2"></icon> <icon *ngIf="getTypeName().toLowerCase() == 'research software'" name="integration_instructions" type="outlined" [flex]="true" [ratio]="1.4"></icon>
<icon *ngIf="getTypeName().toLowerCase() == 'other research product'" name="apps" type="outlined" [flex]="true" [ratio]="2"></icon> <icon *ngIf="getTypeName().toLowerCase() == 'other research product'" name="apps" type="outlined" [flex]="true" [ratio]="1.4"></icon>
<icon *ngIf="getTypeName().toLowerCase() == 'project'" name="assignment_turned_in" type="outlined" [flex]="true" [ratio]="2"></icon> <icon *ngIf="getTypeName().toLowerCase() == 'project'" name="assignment_turned_in" type="outlined" [flex]="true" [ratio]="1.4"></icon>
<icon *ngIf="getTypeName().toLowerCase() == 'data source'" name="note_add" type="outlined" [flex]="true" [ratio]="2"></icon> <icon *ngIf="getTypeName().toLowerCase() == 'data source'" name="note_add" type="outlined" [flex]="true" [ratio]="1.4"></icon>
<icon *ngIf="getTypeName().toLowerCase() == 'organization'" name="corporate_fare" type="outlined" [flex]="true" [ratio]="2"></icon> <icon *ngIf="getTypeName().toLowerCase() == 'organization'" name="corporate_fare" type="outlined" [flex]="true" [ratio]="1.4"></icon>
</span> </span>
<span>{{getTypeName()}}</span> <span>{{getTypeName()}}</span>
</a> </a>
</div> </div>
<div *ngIf="resultLandingInfo && (resultLandingInfo.measure || hasAltMetrics)"> <div *ngIf="resultLandingInfo && (resultLandingInfo.measure || hasAltMetrics)">
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'metrics'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'metrics'; scroll()">
<icon name="bar_chart" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'metrics' ? 'uk-text-primary': ''"></icon> <icon name="bar_chart" type="outlined" [flex]="true" [ratio]="1.4" [ngClass]="mobileContent == 'metrics' ? 'uk-text-primary': ''"></icon>
<span>Metrics</span> <span>Metrics</span>
</a> </a>
</div> </div>
<div> <div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'actions'"> <a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset" (click)="mobileContent = 'actions'; scroll()">
<icon name="pending" type="outlined" [flex]="true" [ratio]="2" [ngClass]="mobileContent == 'actions' ? 'uk-text-primary': ''"></icon> <icon name="pending" type="outlined" [flex]="true" [ratio]="1.4" [ngClass]="mobileContent == 'actions' ? 'uk-text-primary': ''"></icon>
<span>Actions</span> <span>Actions</span>
</a> </a>
</div> </div>

View File

@ -28,6 +28,7 @@ import {NumberUtils} from '../../utils/number-utils.class';
import {FullScreenModalComponent} from "../../utils/modal/full-screen-modal/full-screen-modal.component"; 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 {SdgFosSuggestComponent} from '../landing-utils/sdg-fos-suggest/sdg-fos-suggest.component';
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service"; import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {ContextsService} from "../../claims/claim-utils/service/contexts.service";
declare var ResizeObserver; declare var ResizeObserver;
@ -54,6 +55,7 @@ export class ResultLandingComponent {
public deleteByInferenceOpened: boolean = false; public deleteByInferenceOpened: boolean = false;
@Input() public resultFromInput: boolean = false; @Input() public resultFromInput: boolean = false;
@Input() public resultLandingInfo: ResultLandingInfo; @Input() public resultLandingInfo: ResultLandingInfo;
public belongsInEOSC: boolean = false;
public supplementaryResults: RelationResult[]; public supplementaryResults: RelationResult[];
public relation: string = 'trust'; public relation: string = 'trust';
public id: string; public id: string;
@ -174,6 +176,8 @@ export class ResultLandingComponent {
@ViewChild('fosFsModal') fosFsModal: FullScreenModalComponent; @ViewChild('fosFsModal') fosFsModal: FullScreenModalComponent;
public noCommunities: boolean = false; public noCommunities: boolean = false;
private promise: Promise<void> = null;
private publicCommunities: string[] = [];
public rightSidebarOffcanvasClicked: boolean = false; public rightSidebarOffcanvasClicked: boolean = false;
public egiTransferModalOpen = false; public egiTransferModalOpen = false;
@ -192,7 +196,8 @@ export class ResultLandingComponent {
private _location: Location, private _location: Location,
private indexInfoService: IndexInfoService, private indexInfoService: IndexInfoService,
private userManagementService: UserManagementService, private userManagementService: UserManagementService,
private layoutService: LayoutService) { private layoutService: LayoutService,
private _contextService: ContextsService) {
} }
ngOnInit() { ngOnInit() {
@ -239,6 +244,7 @@ export class ResultLandingComponent {
this.initMetaAndLinks(this.type); this.initMetaAndLinks(this.type);
} }
if(data["egiTransfer"] && data["egiTransfer"] == 't'){ if(data["egiTransfer"] && data["egiTransfer"] == 't'){
this.mobileContent = 'actions';
this.egiTransferModalOpen = true; this.egiTransferModalOpen = true;
} }
this.updateDescription(""); this.updateDescription("");
@ -255,6 +261,7 @@ export class ResultLandingComponent {
this.type="publication"; this.type="publication";
} }
if ((this.id && StringUtils.isOpenAIREID(this.id)) || (this.identifier)) { if ((this.id && StringUtils.isOpenAIREID(this.id)) || (this.identifier)) {
this.getPublicCommunities();
this.getVocabulariesAndResultLandingInfo(); this.getVocabulariesAndResultLandingInfo();
} else { } else {
this.showLoading = false; this.showLoading = false;
@ -495,29 +502,32 @@ export class ResultLandingComponent {
this.resultLandingInfo = null; this.resultLandingInfo = null;
this.hasAltMetrics = false; this.hasAltMetrics = false;
this.subscriptions.push(this._resultLandingService.getResultLandingInfo(this.id, this.identifier, this.type, subjectsVocabulary, this.properties).subscribe( this.subscriptions.push(this._resultLandingService.getResultLandingInfo(this.id, this.identifier, this.type, subjectsVocabulary, this.properties).subscribe(
data => { async data => {
let contexts = data.contexts;
data.contexts = [];
this.resultLandingInfo = data; this.resultLandingInfo = data;
this.id = this.resultLandingInfo.objIdentifier; this.id = this.resultLandingInfo.objIdentifier;
//old //old
// this.viewsFrameUrl = this.properties.framesAPIURL + 'merge.php?com=query&data=[{"query":"resRepoViews", "resTitle":"' + this.id + '", "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":"Repository","yaxisheaders":["Monthly views"],"generalxaxis":"","theme":0,"in":[],"filters":[{"name":"","values":[""],"to":"-1"}]}]&info_types=["column"]&stacking=normal&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(67, 67, 72, 1)&colors[]=rgba(144, 237, 125, 1)&colors[]=rgba(247, 163, 92, 1)&colors[]=rgba(128, 133, 233, 1)&colors[]=rgba(241, 92, 128, 1)&colors[]=rgba(228, 211, 84, 1)&colors[]=rgba(43, 144, 143, 1)&colors[]=rgba(244, 91, 91, 1)&colors[]=rgba(145, 232, 225, 1)&xlinew=0&ylinew=1&legends=true&tooltips=true&persistent=false'; // this.viewsFrameUrl = this.properties.framesAPIURL + 'merge.php?com=query&data=[{"query":"resRepoViews", "resTitle":"' + this.id + '", "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":"Repository","yaxisheaders":["Monthly views"],"generalxaxis":"","theme":0,"in":[],"filters":[{"name":"","values":[""],"to":"-1"}]}]&info_types=["column"]&stacking=normal&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(67, 67, 72, 1)&colors[]=rgba(144, 237, 125, 1)&colors[]=rgba(247, 163, 92, 1)&colors[]=rgba(128, 133, 233, 1)&colors[]=rgba(241, 92, 128, 1)&colors[]=rgba(228, 211, 84, 1)&colors[]=rgba(43, 144, 143, 1)&colors[]=rgba(244, 91, 91, 1)&colors[]=rgba(145, 232, 225, 1)&xlinew=0&ylinew=1&legends=true&tooltips=true&persistent=false';
// this.downloadsFrameUrl = this.properties.framesAPIURL + 'merge.php?com=query&data=[{"query":"resRepoDownloads", "resTitle":"' + this.id + '", "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":"Repository","yaxisheaders":["Monthly downloads"],"generalxaxis":"","theme":0,"in":[],"filters":[{"name":"","values":[""],"to":"-1"}]}]&info_types=["column"]&stacking=normal&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(67, 67, 72, 1)&colors[]=rgba(144, 237, 125, 1)&colors[]=rgba(247, 163, 92, 1)&colors[]=rgba(128, 133, 233, 1)&colors[]=rgba(241, 92, 128, 1)&colors[]=rgba(228, 211, 84, 1)&colors[]=rgba(43, 144, 143, 1)&colors[]=rgba(244, 91, 91, 1)&colors[]=rgba(145, 232, 225, 1)&xlinew=0&ylinew=1&legends=true&tooltips=true&persistent=false'; // this.downloadsFrameUrl = this.properties.framesAPIURL + 'merge.php?com=query&data=[{"query":"resRepoDownloads", "resTitle":"' + this.id + '", "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":"Repository","yaxisheaders":["Monthly downloads"],"generalxaxis":"","theme":0,"in":[],"filters":[{"name":"","values":[""],"to":"-1"}]}]&info_types=["column"]&stacking=normal&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(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';
//new //new
this.viewsFrameUrl = this.properties.statisticsFrameNewAPIURL + 'chart?json=' + encodeURIComponent('{"library":"HighCharts","chartDescription":{"queries":[{"name":"Monthly views","type":"column","query":{"name":"usagestats.results.views.monthly", "parameters":["' + this.id + '"], "profile":"OpenAIRE All-inclusive" }}],"chart":{"backgroundColor":"#FFFFFFFF","borderColor":"#335cadff","borderRadius":0,"borderWidth":0,"plotBorderColor":"#ccccccff","plotBorderWidth":0},"title":{"text":"Monthly views"},"subtitle":{},"yAxis":{"title":{"text":""}},"xAxis":{"title":{}},"lang":{"noData":"No Data available for the Query"},"exporting":{"enabled":false},"plotOptions":{"series":{"dataLabels":{"enabled":false}}},"legend":{"enabled":false},"credits":{"href":null,"enabled":true,"text":""}}}'); this.viewsFrameUrl = this.properties.statisticsFrameNewAPIURL + 'chart?json=' + encodeURIComponent('{"library":"HighCharts","chartDescription":{"queries":[{"name":"Monthly views","type":"column","query":{"name":"usagestats.results.views.monthly", "parameters":["' + this.id + '"], "profile":"OpenAIRE All-inclusive" }}],"chart":{"backgroundColor":"#FFFFFFFF","borderColor":"#335cadff","borderRadius":0,"borderWidth":0,"plotBorderColor":"#ccccccff","plotBorderWidth":0},"title":{"text":"Monthly views"},"subtitle":{},"yAxis":{"title":{"text":""}},"xAxis":{"title":{}},"lang":{"noData":"No Data available for the Query"},"exporting":{"enabled":false},"plotOptions":{"series":{"dataLabels":{"enabled":false}}},"legend":{"enabled":false},"credits":{"href":null,"enabled":true,"text":""}}}');
this.downloadsFrameUrl = this.properties.statisticsFrameNewAPIURL + 'chart?json=' + this.downloadsFrameUrl = this.properties.statisticsFrameNewAPIURL + 'chart?json=' +
encodeURIComponent('{"library":"HighCharts","chartDescription":{"queries":[{"name":"Monthly downloads","type":"column","query":{"name":"usagestats.results.downloads.monthly", "parameters":["' + this.id + '"], "profile":"OpenAIRE All-inclusive" }}],"chart":{"backgroundColor":"#FFFFFFFF","borderColor":"#335cadff","borderRadius":0,"borderWidth":0,"plotBorderColor":"#ccccccff","plotBorderWidth":0},"title":{"text":"Monthly downloads"},"subtitle":{},"yAxis":{"title":{"text":""}},"xAxis":{"title":{}},"lang":{"noData":"No Data available for the Query"},"exporting":{"enabled":false},"plotOptions":{"series":{"dataLabels":{"enabled":false}}},"legend":{"enabled":false},"credits":{"href":null,"enabled":true,"text":""}}}'); encodeURIComponent('{"library":"HighCharts","chartDescription":{"queries":[{"name":"Monthly downloads","type":"column","query":{"name":"usagestats.results.downloads.monthly", "parameters":["' + this.id + '"], "profile":"OpenAIRE All-inclusive" }}],"chart":{"backgroundColor":"#FFFFFFFF","borderColor":"#335cadff","borderRadius":0,"borderWidth":0,"plotBorderColor":"#ccccccff","plotBorderWidth":0},"title":{"text":"Monthly downloads"},"subtitle":{},"yAxis":{"title":{"text":""}},"xAxis":{"title":{}},"lang":{"noData":"No Data available for the Query"},"exporting":{"enabled":false},"plotOptions":{"series":{"dataLabels":{"enabled":false}}},"legend":{"enabled":false},"credits":{"href":null,"enabled":true,"text":""}}}');
this.bipFrameUrl = this.properties.bipFrameAPIURL + this.id + (properties.environment == "beta" ? "&src=beta" : ""); this.bipFrameUrl = this.properties.bipFrameAPIURL + this.id + (properties.environment == "beta" ? "&src=beta" : "");
let pid:Identifier = Identifier.getPIDFromIdentifiers(this.resultLandingInfo.identifiers); let pid: Identifier = Identifier.getPIDFromIdentifiers(this.resultLandingInfo.identifiers);
if (this.type == "result") { // no type was specified - update URL based this.resultLandingInfo.resultType if (this.type == "result") { // no type was specified - update URL based this.resultLandingInfo.resultType
this.updateUrlWithType(pid); this.updateUrlWithType(pid);
} }
this.canonicalUrl = this.properties.domain+ properties.baseLink + ( pid ? (this.linkToLandingPage.split("?")[0] + "?pid=" + encodeURIComponent(pid.id)): this.canonicalUrl = this.properties.domain + properties.baseLink + (pid ? (this.linkToLandingPage.split("?")[0] + "?pid=" + encodeURIComponent(pid.id)) :
(this.linkToLandingPage + this.resultLandingInfo.relcanId)); (this.linkToLandingPage + this.resultLandingInfo.relcanId));
this.seoService.createLinkForCanonicalURL(this.canonicalUrl); this.seoService.createLinkForCanonicalURL(this.canonicalUrl);
this.updateUrl(this.canonicalUrl); this.updateUrl(this.canonicalUrl);
this.addNoIndexFilter(); this.addNoIndexFilter();
if (this.resultLandingInfo.title) { if (this.resultLandingInfo.title) {
this.updateTitle(this.resultLandingInfo.title); this.updateTitle(this.resultLandingInfo.title);
this.updateDescription((this.resultLandingInfo.description ? (this.resultLandingInfo.description.substr(0,157) + (this.resultLandingInfo.description.substr(0,157).length == 157?"...":"")) : (this.resultLandingInfo.title))); this.updateDescription((this.resultLandingInfo.description ? (this.resultLandingInfo.description.substr(0, 157) + (this.resultLandingInfo.description.substr(0, 157).length == 157 ? "..." : "")) : (this.resultLandingInfo.title)));
} }
this.subscriptions.push(this._piwikService.trackViewForCustomUrl(this.properties, this.resultLandingInfo.title, this.linkToLandingPage.split("?")[1] + this.id).subscribe()); this.subscriptions.push(this._piwikService.trackViewForCustomUrl(this.properties, this.resultLandingInfo.title, this.linkToLandingPage.split("?")[1] + this.id).subscribe());
let bioentitiesNum = 0; let bioentitiesNum = 0;
@ -528,9 +538,9 @@ export class ResultLandingComponent {
} }
this.bioentitiesNum = bioentitiesNum; this.bioentitiesNum = bioentitiesNum;
if (typeof document !== 'undefined') { if (typeof document !== 'undefined') {
if(this.resultLandingInfo.identifiers) { if (this.resultLandingInfo.identifiers) {
let pidsArray: string[] = []; let pidsArray: string[] = [];
for(let key of Array.from(this.resultLandingInfo.identifiers.keys())) { for (let key of Array.from(this.resultLandingInfo.identifiers.keys())) {
pidsArray = pidsArray.concat(this.resultLandingInfo.identifiers.get(key)); pidsArray = pidsArray.concat(this.resultLandingInfo.identifiers.get(key));
this.pidsArrayString = pidsArray.join(); this.pidsArrayString = pidsArray.join();
} }
@ -544,14 +554,17 @@ export class ResultLandingComponent {
} }
} }
} }
if(this.communityId && this.communityId == "enermaps" && properties.enermapsURL){ if (this.communityId && this.communityId == "enermaps" && properties.enermapsURL) {
this.enermapsId = ParsingFunctions.getEnermapsConceptId(this.resultLandingInfo.contexts); this.enermapsId = ParsingFunctions.getEnermapsConceptId(this.resultLandingInfo.contexts);
} }
this.relatedClassFilters = [{"label": "All relations", "value": ""}]; this.relatedClassFilters = [{"label": "All relations", "value": ""}];
if(this.resultLandingInfo.relatedClassFilters.size > 1) { if (this.resultLandingInfo.relatedClassFilters.size > 1) {
for (let relClass of this.resultLandingInfo.relatedClassFilters) { for (let relClass of this.resultLandingInfo.relatedClassFilters) {
this.relatedClassFilters.push({"label": HelperFunctions.getVocabularyLabel(relClass, this.relationsVocabulary), "value": relClass}); this.relatedClassFilters.push({
"label": HelperFunctions.getVocabularyLabel(relClass, this.relationsVocabulary),
"value": relClass
});
} }
} else { } else {
this.relatedClassFilters.pop(); this.relatedClassFilters.pop();
@ -561,12 +574,12 @@ export class ResultLandingComponent {
this.hasViews = false; this.hasViews = false;
this.hasDownloads = false; this.hasDownloads = false;
if(this.resultLandingInfo.measure && this.resultLandingInfo.measure.counts) { if (this.resultLandingInfo.measure && this.resultLandingInfo.measure.counts) {
this.resultLandingInfo.measure.counts.forEach(measure => { this.resultLandingInfo.measure.counts.forEach(measure => {
if(measure.name == "views" && measure.value > 0) { if (measure.name == "views" && measure.value > 0) {
this.hasViews = true; this.hasViews = true;
} }
if(measure.name == "downloads" && measure.value > 0) { if (measure.name == "downloads" && measure.value > 0) {
this.hasDownloads = true; this.hasDownloads = true;
} }
}) })
@ -576,6 +589,19 @@ export class ResultLandingComponent {
this.setActiveTab(); this.setActiveTab();
this.cdr.detectChanges(); this.cdr.detectChanges();
if (contexts) {
await this.promise;
if(this.publicCommunities && this.publicCommunities.length > 0) {
this.resultLandingInfo.contexts = contexts.filter(context => {
if(context.idContext == "eosc") {
this.belongsInEOSC = true;
}
return this.publicCommunities.includes(context.idContext)
});
this.cdr.detectChanges();
}
}
}, },
err => { err => {
this.handleError("Error getting " + this.type + " for " + (this.id ? ("id: " + this.id) : ("pid: " + this.identifier.id + " ("+this.identifier.class+")")), err); this.handleError("Error getting " + this.type + " for " + (this.id ? ("id: " + this.id) : ("pid: " + this.identifier.id + " ("+this.identifier.class+")")), err);
@ -592,6 +618,21 @@ export class ResultLandingComponent {
)); ));
} }
public getPublicCommunities() {
this.promise = new Promise<void>(resolve => {
this._contextService.getPublicCommunitiesByState().subscribe(
data => {
this.publicCommunities = data.map(value => value.id);
// this.publicCommunities = data;
resolve();
},
error => {
this.handleError("Error getting communities status", error);
resolve();
});
});
}
public metricsResults($event) { public metricsResults($event) {
this.totalViews = $event.totalViews; this.totalViews = $event.totalViews;
this.totalDownloads = $event.totalDownloads; this.totalDownloads = $event.totalDownloads;
@ -784,6 +825,8 @@ export class ResultLandingComponent {
return this.properties.pmidURL + id.value; return this.properties.pmidURL + id.value;
} else if (id.type === "handle") { } else if (id.type === "handle") {
return this.properties.handleURL + id.value; return this.properties.handleURL + id.value;
} else if (id.type === "swhid") {
return this.properties.swhURL + id.value;
} else { } else {
return null; return null;
} }
@ -798,6 +841,8 @@ export class ResultLandingComponent {
return 'PubMed'; return 'PubMed';
} else if (id.type === "handle") { } else if (id.type === "handle") {
return 'Handle.NET'; return 'Handle.NET';
} else if(id.type == "swhid") {
return 'Software Heritage';
} else { } else {
return null; return null;
} }

View File

@ -3,8 +3,7 @@ import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {RouterModule} from '@angular/router'; import {RouterModule} from '@angular/router';
import {SharedModule} from '../../../openaireLibrary/shared/shared.module'; import {SharedModule} from '../../shared/shared.module';
import {MetricsModule} from '../landing-utils/metrics/metrics.module';
import {LandingModule} from '../landing-utils/landing.module'; import {LandingModule} from '../landing-utils/landing.module';
import {CiteThisModule} from '../landing-utils/citeThis/citeThis.module'; import {CiteThisModule} from '../landing-utils/citeThis/citeThis.module';
import {IFrameModule} from '../../utils/iframe.module'; import {IFrameModule} from '../../utils/iframe.module';
@ -46,7 +45,7 @@ import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.mod
imports: [ imports: [
CommonModule, FormsModule, LandingModule, SharedModule, RouterModule, CommonModule, FormsModule, LandingModule, SharedModule, RouterModule,
CiteThisModule, PagingModule, IFrameModule, CiteThisModule, PagingModule, IFrameModule,
MetricsModule, AltMetricsModule, Schema2jsonldModule, SEOServiceModule, AltMetricsModule, Schema2jsonldModule, SEOServiceModule,
DeletedByInferenceModule, ShowAuthorsModule, HelperModule, ResultLandingUtilsModule, AlertModalModule, DeletedByInferenceModule, ShowAuthorsModule, HelperModule, ResultLandingUtilsModule, AlertModalModule,
AnnotationModule, LandingHeaderModule, NoLoadPaging, ResultPreviewModule, FeedbackModule, TabsModule, LoadingModule, AnnotationModule, LandingHeaderModule, NoLoadPaging, ResultPreviewModule, FeedbackModule, TabsModule, LoadingModule,
OrcidModule, MatFormFieldModule, MatSelectModule, IconsModule, InputModule, EGIDataTransferModule, RecaptchaModule, OrcidModule, MatFormFieldModule, MatSelectModule, IconsModule, InputModule, EGIDataTransferModule, RecaptchaModule,

View File

@ -17,13 +17,13 @@
<div *ngIf="user.role.length > 1"> <div *ngIf="user.role.length > 1">
<span class="uk-text-muted"> Roles </span> <span> {{getTheRolesFormatted(user.role)}} </span> <span class="uk-text-muted"> Roles </span> <span> {{getTheRolesFormatted(user.role)}} </span>
</div> </div>
<div class="uk-margin-top" *ngIf="user.role.length > 1"> <div class="uk-margin-top" *ngIf="user.role.length > 1 && isPortalAdministrator">
<a *ngIf="isCurator" class="uk-button uk-button-primary" href="https://aai.openaire.eu/roles/index.php" <a class="uk-button uk-button-primary" href="https://aai.openaire.eu/roles/index.php"
target="_blank">Manage your roles</a> {{" "}} target="_blank">Manage your roles</a> {{" "}}
<a *ngIf="isUserManager" class="uk-button uk-button-primary uk-margin-top" <a class="uk-button uk-button-primary uk-margin-top"
href="https://aai.openaire.eu/roles/admin.php" href="https://aai.openaire.eu/roles/admin.php"
target="_blank">Manage role requests</a>{{" "}} target="_blank">Manage role requests</a>{{" "}}
<a *ngIf="isUserManager" class="uk-button uk-button-primary uk-margin-top" <a class="uk-button uk-button-primary uk-margin-top"
href="https://aai.openaire.eu/registry" href="https://aai.openaire.eu/registry"
target="_blank">Manage users</a> target="_blank">Manage users</a>
</div> </div>

View File

@ -100,12 +100,9 @@ export class UserComponent {
return formattedRoles.join(", "); return formattedRoles.join(", ");
} }
get isCurator() { get isPortalAdministrator() {
return Session.isPortalAdministrator(this.user) || Session.isMonitorCurator(this.user); return Session.isPortalAdministrator(this.user);
} }
get isUserManager() {
return Session.isUserManager(this.user);
}
} }

View File

@ -131,6 +131,7 @@ export class Session {
} else if (type == 'project') { } else if (type == 'project') {
return user && this.isProjectCurator(user); return user && this.isProjectCurator(user);
} }
return false;
} }
public static isPortalAdministrator(user: User): boolean { public static isPortalAdministrator(user: User): boolean {

View File

@ -29,6 +29,7 @@ export class Stakeholder {
visibility: Visibility; visibility: Visibility;
creationDate: Date = null; creationDate: Date = null;
updateDate: Date; updateDate: Date;
projectUpdateDate: Date;
/** @warning Use pipe in HTML or StringUtils.getLogoUrl in components */ /** @warning Use pipe in HTML or StringUtils.getLogoUrl in components */
logoUrl: string; logoUrl: string;
isUpload: boolean = false; isUpload: boolean = false;
@ -245,6 +246,8 @@ export class IndicatorFilterUtils {
}else if (table == "organization"){ }else if (table == "organization"){
return this.getOrganizationFilter(filterType); return this.getOrganizationFilter(filterType);
} }
return "";
} }
static getResultFilter(table: string = null, filterType:FilterType) { static getResultFilter(table: string = null, filterType:FilterType) {
//works for tables ["publication", "software", "dataset", "other", "result"] //works for tables ["publication", "software", "dataset", "other", "result"]
@ -257,24 +260,28 @@ export class IndicatorFilterUtils {
}else if (filterType == "co-funded") { }else if (filterType == "co-funded") {
return '{"groupFilters":[{"field":"' + table + '.No of funders","type":">","values":["1"]}],"op":"AND"}'; return '{"groupFilters":[{"field":"' + table + '.No of funders","type":">","values":["1"]}],"op":"AND"}';
} }
return "";
} }
static getProjectFilter( filterType:FilterType) { static getProjectFilter( filterType:FilterType) {
//works for table "project" //works for table "project"
if (filterType == "fundingL0") { if (filterType == "fundingL0") {
return '{"groupFilters":[{"field":"project.funding level 0","type":"=","values":["' + ChartHelper.prefix + 'fundingL0' + ChartHelper.suffix + '"]}],"op":"AND"}'; return '{"groupFilters":[{"field":"project.funding level 0","type":"=","values":["' + ChartHelper.prefix + 'fundingL0' + ChartHelper.suffix + '"]}],"op":"AND"}';
} }
return "";
} }
static getOrganizationFilter( filterType:FilterType) { static getOrganizationFilter( filterType:FilterType) {
//works for table "organization" //works for table "organization"
if (filterType == "fundingL0") { if (filterType == "fundingL0") {
return '{"groupFilters":[{"field":"organization.project.funding level 0","type":"=","values":["' + ChartHelper.prefix + 'fundingL0' + ChartHelper.suffix + '"]}],"op":"AND"}'; return '{"groupFilters":[{"field":"organization.project.funding level 0","type":"=","values":["' + ChartHelper.prefix + 'fundingL0' + ChartHelper.suffix + '"]}],"op":"AND"}';
} }
return "";
} }
static getCountryFilter( filterType:FilterType) { static getCountryFilter( filterType:FilterType) {
//works for table "country" //works for table "country"
if (filterType == "fundingL0") { if (filterType == "fundingL0") {
return '{"groupFilters":[{"field":"country.organization.project.funding level 0","type":"=","values":["' + ChartHelper.prefix + 'fundingL0' + ChartHelper.suffix + '"]}],"op":"AND"}'; return '{"groupFilters":[{"field":"country.organization.project.funding level 0","type":"=","values":["' + ChartHelper.prefix + 'fundingL0' + ChartHelper.suffix + '"]}],"op":"AND"}';
} }
return "";
} }
static filterIndexOf(filterToAdd, currentFilters):any{ static filterIndexOf(filterToAdd, currentFilters):any{

View File

@ -104,8 +104,8 @@ export class MyOrcidLinksComponent {
private errorCodes: ErrorCodes; private errorCodes: ErrorCodes;
private errorMessages: ErrorMessagesComponent; private errorMessages: ErrorMessagesComponent;
public results =[]; public results:Map<number,{"work":{},results:ResultPreview[]}[]> = new Map();
public currentResults = []; public currentResults:{"work":{},results:ResultPreview[]}[] = [];
public totalResults:number = 0 ; public totalResults:number = 0 ;
public baseUrl:string; public baseUrl:string;
public searchUtils:SearchUtilsClass = new SearchUtilsClass(); public searchUtils:SearchUtilsClass = new SearchUtilsClass();
@ -163,7 +163,7 @@ export class MyOrcidLinksComponent {
if(typeof document !== 'undefined') { if(typeof document !== 'undefined') {
this.tokenUrl = properties.orcidTokenURL this.tokenUrl = properties.orcidTokenURL
+ "client_id="+properties.orcidClientId + "client_id=" + properties.orcidClientId
// + "&response_type=code&scope=/activities/update" // + "&response_type=code&scope=/activities/update"
// + "&response_type=code&scope=/authenticate /activities/update /person/update /read-limited" // + "&response_type=code&scope=/authenticate /activities/update /person/update /read-limited"
+ "&response_type=code&scope=/activities/update /read-limited" + "&response_type=code&scope=/activities/update /read-limited"
@ -253,6 +253,18 @@ export class MyOrcidLinksComponent {
(response: any[]) => { (response: any[]) => {
this.works = response;//['results']; this.works = response;//['results'];
/* this.works=[
{ "id" : "60391ad16c2043536ca44ea4", "pids" : [ "10.5281/zeno(do.4304132", "10.5281/zenodo.3974605" ], "putCode" : "89558576", "orcid" : "0000-0002-3880-0244", "creationDate" : "2021-02-26T15:59:13.098Z", "updateDate" : "2021-02-26T15:59:13.098Z", "dashboard" : "production_explore" },
{ "id" : "60391ceb7a767127ea9a4d06", "pids" : [ "10.5281/zenodo.4095044", "10.5281/zenodo.4095043" ], "putCode" : "89559422", "orcid" : "0000-0002-3880-0244", "creationDate" : "2021-02-26T16:08:11.930Z", "updateDate" : "2021-02-26T16:27:12.835Z", "dashboard" : "production_explore" },
{ "id" : "604244fb7a767127ea9a4d0b", "pids" : [ "10.5281/zenodo.3467103", "10.5281/zenodo.3467104", "10.1007/978-3-030-30760-8_5", "1822/62856" ], "putCode" : "90020579", "orcid" : "0000-0002-3880-0244", "creationDate" : "2021-03-05T14:49:31.972Z", "updateDate" : "2022-06-20T08:28:08.539Z", "dashboard" : "production_explore" },
{ "id" : "60744bb46c20432760765b9f", "pids" : [ "10.5281/zenodo.3701379", "10.5281/zenodo.3701380" ], "putCode" : "92074390", "orcid" : "0000-0002-3880-0244", "creationDate" : "2021-04-12T13:31:32.476Z", "updateDate" : "2021-04-12T13:31:32.476Z", "dashboard" : "production_explore" },
{ "id" : "6077f0047a767112e847f9f8", "pids" : [ "10.5281/zenodo.4559726" ], "putCode" : "92235922", "orcid" : "0000-0002-3880-0244", "creationDate" : "2021-04-15T07:49:24.078Z", "updateDate" : "2021-04-21T09:43:40.147Z", "dashboard" : "production_explore" },
{ "id" : "6079752b7a767112e847fa5b", "pids" : [ "10.5281/zenodo.4304047", "10.5281/zenodo.3980491" ], "putCode" : "92304809", "orcid" : "0000-0002-3880-0244", "creationDate" : "2021-04-16T11:29:47.905Z", "updateDate" : "2021-04-16T11:29:47.905Z", "dashboard" : "production_explore" },
{ "id" : "63186abb7a767129935f495b", "pids" : [ "10.5281/zenodo.1314672", "10.5281/zenodo.1412509", "10.5281/zenodo.1314671" ], "putCode" : "118582128", "orcid" : "0000-0002-3880-0244", "creationDate" : "2022-09-07T09:56:11.556Z", "updateDate" : "2022-09-07T09:56:11.556Z", "dashboard" : "production_explore" },
{ "id" : "63186ade6c204337f56d97ca", "pids" : [ "10.5281/zenodo.6634431", "10.5281/zenodo.6385204", "10.5281/zenodo.4559725" ], "putCode" : "118582151", "orcid" : "0000-0002-3880-0244", "creationDate" : "2022-09-07T09:56:46.231Z", "updateDate" : "2022-09-07T09:56:46.231Z", "dashboard" : "production_explore" },
{ "id" : "63186ae27a767129935f495c", "pids" : [ "10.5281/zenodo.5801283", "10.5281/zenodo.3516917", "10.5281/zenodo.6616871" ], "putCode" : "118582162", "orcid" : "0000-0002-3880-0244", "creationDate" : "2022-09-07T09:56:50.660Z", "updateDate" : "2022-09-07T09:56:50.660Z", "dashboard" : "production_explore" }
];*/
this.totalOrcidResults = this.works.length;//response['total']; this.totalOrcidResults = this.works.length;//response['total'];
this.prepareOrcidQuery(); this.prepareOrcidQuery();
@ -266,7 +278,7 @@ export class MyOrcidLinksComponent {
public prepareOrcidQuery() { public prepareOrcidQuery() {
if(this.results.length >= this.currentPage) { if(Array.from(this.results.keys()).length >= this.currentPage) {
this.currentResults = this.results[this.currentPage-1]; this.currentResults = this.results[this.currentPage-1];
return; return;
} }
@ -302,11 +314,7 @@ export class MyOrcidLinksComponent {
this.disableForms = true; this.disableForms = true;
this.currentResults = []; this.currentResults = [];
this.searchUtils.totalResults = 0; this.searchUtils.totalResults = 0;
// let params: string = this.orcidQuery + this.typeQuery;
//this.subs.push(this._searchResearchResultsService.advancedSearchResults(this.resultType, parameters, page, size, sortBy, this.properties, (refine) ? this.searchPage.getRefineFieldsQuery() : null, this.searchPage.getFields(), refineFieldsFilterQuery)
this.subscriptions.push(this._searchResearchResultsService.searchForMyOrcidLinks(this.resultType, this.orcidQuery, this.typeQuery, 1, 50) this.subscriptions.push(this._searchResearchResultsService.searchForMyOrcidLinks(this.resultType, this.orcidQuery, this.typeQuery, 1, 50)
//this.subs.push(this._searchResearchResultsService.advancedSearchResults(this.resultType, parameters, page, size, sortBy, this.properties, null, this.searchPage.getFields(), refineFieldsFilterQuery)
.subscribe( .subscribe(
data => { data => {
let totalResults = data[0]; let totalResults = data[0];
@ -330,28 +338,29 @@ export class MyOrcidLinksComponent {
let resultsFound: Map<string[], number> = new Map<string[], number>(); let resultsFound: Map<string[], number> = new Map<string[], number>();
for(let work of works) { for(let work of works) {
let relatedResults = [];
this.currentResults.push({"work": work, "results" : relatedResults})
results.forEach(result => { results.forEach(result => {
let identifierValues: string[] = [].concat(...Array.from(result.identifiers.values())); let identifierValues: string[] = [].concat(...Array.from(result.identifiers.values()));
if(work['pids'].some(pid => identifierValues.includes(pid))) { if(work['pids'].some(pid => identifierValues.includes(pid))) {
let index: number = resultsFound.get(identifierValues); let index: number = resultsFound.get(identifierValues);
if(!index) { if(!index) {
this.currentResults.push(this.getResultPreview(result)); relatedResults.push(this.getResultPreview(result));
index = this.currentResults.length - 1; index = relatedResults.length - 1;
relatedResults[index].orcidPutCodes = [];
this.currentResults[index].orcidPutCodes = []; relatedResults[index].orcidCreationDates = [];
this.currentResults[index].orcidCreationDates = []; relatedResults[index].orcidUpdateDates = [];
this.currentResults[index].orcidUpdateDates = [];
} }
if (work['putCode']) { if (work['putCode']) {
this.currentResults[index].orcidPutCodes.push(work['putCode']); relatedResults[index].orcidPutCodes.push(work['putCode']);
} }
if (work['creationDate']) { if (work['creationDate']) {
this.currentResults[index].orcidCreationDates.push(work['creationDate']); relatedResults[index].orcidCreationDates.push(work['creationDate']);
} }
if (work['updateDate']) { if (work['updateDate']) {
this.currentResults[index].orcidUpdateDates.push(work['updateDate']); relatedResults[index].orcidUpdateDates.push(work['updateDate']);
} }
} }
}) })
@ -367,44 +376,6 @@ export class MyOrcidLinksComponent {
this.disableForms = false; this.disableForms = false;
} }
public resultsReturned2(results: any, totalResults, works: any[]) {
this.searchUtils.totalResults = totalResults;
for(let result of results) {
let identifierValues: string[] = [].concat(...Array.from(result.identifiers.values()));
this.currentResults.push(this.getResultPreview(result));
let filteredWorks = works.filter(work => {
return work['pids'].some(pid => identifierValues.includes(pid));
})
this.currentResults[this.currentResults.length - 1].orcidPutCodes = [];
this.currentResults[this.currentResults.length - 1].orcidCreationDates = [];
this.currentResults[this.currentResults.length - 1].orcidUpdateDates = [];
filteredWorks.forEach(work => {
if(work['putCode']) {
this.currentResults[this.currentResults.length - 1].orcidPutCodes.push(work['putCode']);
}
if(work['creationDate']) {
this.currentResults[this.currentResults.length - 1].orcidCreationDates.push(work['creationDate']);
}
if(work['updateDate']) {
this.currentResults[this.currentResults.length - 1].orcidUpdateDates.push(work['updateDate']);
}
});
}
this.results[this.currentPage-1] = this.currentResults;
this.searchUtils.status = this.errorCodes.DONE;
if (this.searchUtils.totalResults == 0) {
this.searchUtils.status = this.errorCodes.NONE;
}
this.disableForms = false;
}
public getResultPreview(result: SearchResult): ResultPreview { public getResultPreview(result: SearchResult): ResultPreview {
return ResultPreview.searchResultConvert(result, (result.entityType)?result.entityType:this.resultType); return ResultPreview.searchResultConvert(result, (result.entityType)?result.entityType:this.resultType);
} }

View File

@ -1,5 +1,5 @@
<div class="uk-margin-medium-top uk-margin"> <div class="uk-margin-medium-top uk-margin">
<no-load-paging *ngIf="totalResults > 0 && previewResults && previewResults.length > 0" [type]="openaireEntities.RESULTS" <no-load-paging *ngIf="totalResults > 0 && previewResults && previewResults.length > 0" type="Orcid links"
(pageChange)="pageChanged($event)" (pageChange)="pageChanged($event)"
[page]="currentPage" [pageSize]="resultsPerPage" [page]="currentPage" [pageSize]="resultsPerPage"
[totalResults]="totalResults"> [totalResults]="totalResults">
@ -7,23 +7,57 @@
<ul class="uk-list search-results uk-margin-medium-top"> <ul class="uk-list search-results uk-margin-medium-top">
<errorMessages [status]="[status]" [type]="'results'"></errorMessages> <errorMessages [status]="[status]" [type]="'results'"></errorMessages>
<li *ngFor="let result of previewResults"> <li *ngFor="let resultGroup of previewResults">
<div class="uk-card uk-card-default uk-padding"> <div class="uk-card uk-card-default uk-padding">
<div class="uk-grid uk-grid-divider"> <div class="uk-grid uk-grid-divider">
<div class="uk-width-expand@m uk-width-1-1 uk-first-column"> <div class="uk-width-expand@m uk-width-1-1 uk-first-column">
<result-preview [properties]="properties" [showOrcid]="false" [showOrganizations]="true" <div *ngIf="resultGroup['results'].length > 1" class="uk-alert uk-alert-warning uk-text-small">{{resultGroup['results'].length}} results found in OpenAIRE
[showSubjects]="true" [result]="result" [promoteWebsiteURL]="true" for PIDs "{{resultGroup['work']['pids'].join("\", \"")}}"
[isCard]="false"> <div>You can update your ORCID work with the most preferred result.</div>
</result-preview> </div>
<div *ngIf="resultGroup['results'].length == 0" class="uk-alert uk-alert-warning uk-text-small"> No results found in OpenAIRE
for PIDs "{{resultGroup['work']['pids'].join("\", \"")}}"
<div>You can remove the entry from your ORCID profile as well.</div>
</div>
<div *ngFor="let result of resultGroup['results']">
<div class = "uk-position-relative">
<div class = "uk-width-1-1">
<result-preview [properties]="properties" [showOrcid]="false" [showOrganizations]="true"
[showSubjects]="true" [result]="result" [promoteWebsiteURL]="true"
[isCard]="false">
</result-preview>
</div>
<div class = "uk-position-right uk-margin-large-top">
<orcid-work *ngIf="resultGroup['results'].length > 1" [resultId]="result.relcanId"
[resultTitle]="result.title"
[type]="result.resultType" [pageType]="'my_search'"
[putCodes]="result.orcidPutCodes" [givenPutCode]="true"
[identifiers]="result.identifiers"
[creationDates]="result.orcidCreationDates" [updateDates]="result.orcidUpdateDates"
[showOnlyUpdateButton]="true"
>
</orcid-work>
</div>
</div>
</div>
</div> </div>
<div class="uk-width-auto@m uk-width-1-1"> <div class="uk-width-auto@m uk-width-1-1">
<div class="uk-height-1-1 uk-padding-small uk-flex uk-flex-center uk-flex-column uk-flex-middle"> <div class="uk-height-1-1 uk-padding-small uk-flex uk-flex-center uk-flex-column uk-flex-middle">
<orcid-work [resultId]="result.relcanId" [resultTitle]="result.title" <orcid-work *ngIf="resultGroup['results'][0]" [resultId]="resultGroup['results'][0].relcanId" [resultTitle]="resultGroup['results'][0].title"
[type]="result.resultType" [pageType]="'my_search'" [type]="resultGroup['results'][0].resultType" [pageType]="'my_search'"
[putCodes]="result.orcidPutCodes" [givenPutCode]="true" [putCodes]="resultGroup['results'][0].orcidPutCodes" [givenPutCode]="true"
[identifiers]="result.identifiers" [identifiers]="resultGroup['results'][0].identifiers"
[creationDates]="result.orcidCreationDates" [updateDates]="result.orcidUpdateDates"> [creationDates]="resultGroup['results'][0].orcidCreationDates" [updateDates]="resultGroup['results'][0].orcidUpdateDates"
[showUpdateButton]="resultGroup['results'].length == 1"
>
</orcid-work>
<orcid-work *ngIf="resultGroup['results'].length ==0" [pageType]="'my_search'"
[putCodes]="[resultGroup.work['putCode']]" [givenPutCode]="true"
[identifiers]="resultGroup.work['pids']"
[creationDates]="[resultGroup.work['creationDate']]" [updateDates]="resultGroup.work['updateDates']"
[showUpdateButton]="false"
>
</orcid-work> </orcid-work>
</div> </div>
</div> </div>

View File

@ -24,7 +24,7 @@ export class searcMyOrcidResultsComponent {
@Input() properties:EnvProperties; @Input() properties:EnvProperties;
public openaireEntities = OpenaireEntities; public openaireEntities = OpenaireEntities;
@Input() previewResults:ResultPreview[]; @Input() previewResults:{"work":{},results:ResultPreview[]}[];
public urlParam: string; public urlParam: string;
public linkToAdvancedSearchPage: string; public linkToAdvancedSearchPage: string;
@ -62,11 +62,6 @@ export class searcMyOrcidResultsComponent {
} }
// ngOnChanges(changes: SimpleChanges): void {
// if (changes.results) {
// this.initialize();
// }
// }
public quote(params: string):string { public quote(params: string):string {
return '"'+params+'"'; return '"'+params+'"';
@ -75,45 +70,6 @@ export class searcMyOrcidResultsComponent {
return ResultPreview.searchResultConvert(result, (result.entityType)?result.entityType:this.type); return ResultPreview.searchResultConvert(result, (result.entityType)?result.entityType:this.type);
} }
initialize() {
this.previewResults = [];
for (let result of this.results) {
this.previewResults.push(this.getResultPreview(result));
}
if (Session.isLoggedIn() && this.results && this.results.length > 0) {
this.orcidService.getLocalWorksByPids(this.previewResults.map(
previewResult => {
if (previewResult.identifiers) {
let pidsArray: string[] = [];
for (let key of Array.from(previewResult.identifiers.keys())) {
pidsArray = pidsArray.concat(previewResult.identifiers.get(key));
}
return pidsArray;//.join();
}
})).subscribe(
works => {
for (let i = 0; i < this.previewResults.length; i++) {
if (this.previewResults[i].identifiers) {
this.previewResults[i].orcidPutCodes = [];
this.previewResults[i].orcidUpdateDates = [];
works[i].forEach(work => {
this.previewResults[i].orcidPutCodes.push(work['putCode']);
this.previewResults[i].orcidUpdateDates.push(work['creationDate']);
});
// this.previewResults[i].orcidPutCodes = works[i].map(work => work['putCode']);
// this.previewResults[i].orcidUpdateDates = works[i]
// console.debug(i, this.previewResults[i].orcidPutCodes);
}
}
}, error => {
}
);
}
}
public pageChanged($event) { public pageChanged($event) {
this.pageChange.emit($event); this.pageChange.emit($event);
HelperFunctions.scroll(); HelperFunctions.scroll();

View File

@ -20,41 +20,49 @@ declare var UIkit: any;
template: ` template: `
<ng-container *ngIf="pageType == 'landing' || pageType == 'search'"> <ng-container *ngIf="pageType == 'landing' || pageType == 'search'">
<span *ngIf="!putCodes || putCodes.length == 0" <span *ngIf="!putCodes || putCodes.length == 0"
[attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'" (click)="currentAction='add'; saveWorkPreparation();"
[class.uk-disabled]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
[class.clickable]="!showLoading && isLoggedIn && (pids || (identifiers && identifiers.size > 0))"
[ngClass]="isMobile && pageType == 'landing' ? ' uk-width-1-1' : ''"
[attr.uk-tooltip]="isMobile? 'cls: uk-invisible' : '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"> [title]="((!pids && (!identifiers || identifiers.size == 0)) || !isLoggedIn) ? ((!pids && (!identifiers || identifiers.size == 0)) ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipAdd">
<a (click)="currentAction='add'; saveWorkPreparation();" <a class="uk-flex uk-flex-middle uk-button-link"
class="uk-flex uk-flex-middle uk-button-link" [ngClass]="isMobile && !(pageType == 'landing') ? 'uk-margin-left' : ''"
[ngClass]="isMobile && !(pageType == 'landing') ? 'uk-margin-left' : 'uk-flex-center'"
[class.uk-text-bolder]="!(isMobile && pageType == 'landing')" [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))" [class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
(mouseover)="hoverEvent($event)" (mouseout)="hoverEvent($event)"> (mouseover)="hoverEvent($event)" (mouseout)="hoverEvent($event)">
<icon *ngIf="!showLoading" [class.text-orcid]="!showLoading && isLoggedIn && (pids || identifiers?.size > 0)" <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" [class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
visuallyHidden="add"></icon> name="orcid_add" [ratio]="(isMobile && pageType == 'search') ? 0.7 : 1" visuallyHidden="add"></icon>
<span *ngIf="showLoading" class="uk-icon"><loading <span *ngIf="showLoading" class="uk-icon"><loading
[top_margin]="false" [size]="'small'"></loading></span> [top_margin]="false" [size]="'small'"></loading></span>
<span [ngClass]="(isMobile && pageType == 'landing') ? 'uk-margin-small-left' : 'uk-margin-xsmall-left'">Claim</span> <span [ngClass]="(isMobile && pageType == 'landing') ? 'uk-margin-small-left' : 'uk-margin-xsmall-left'">Claim</span>
</a> </a>
<div *ngIf="isMobile && pageType == 'landing'" class="uk-margin-xsmall-top uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall"
[innerHTML]="((!pids && (!identifiers || identifiers.size == 0)) || !isLoggedIn) ? ((!pids && (!identifiers || identifiers.size == 0)) ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipAdd"></div>
</span> </span>
<span *ngIf="putCodes && putCodes.length > 0" <span *ngIf="putCodes && putCodes.length > 0"
[attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'" (click)="currentAction='delete'; deleteWorks();"
[class.uk-disabled]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
[class.clickable]="!showLoading && isLoggedIn && (pids || (identifiers && identifiers.size > 0))"
[ngClass]="isMobile && pageType == 'landing' ? ' uk-width-1-1' : ''"
[attr.uk-tooltip]="isMobile? 'cls: uk-invisible' : '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"> [title]="((!pids && (!identifiers || identifiers.size == 0)) || !isLoggedIn) ? ((!pids && (!identifiers || identifiers.size == 0)) ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipDelete">
<a (click)="currentAction='delete'; deleteWorks();" <a class="uk-flex uk-flex-middle uk-button-link"
class="uk-flex uk-flex-middle uk-button-link" [ngClass]="isMobile && !(pageType == 'landing') ? 'uk-margin-left' : ''"
[ngClass]="isMobile && !(pageType == 'landing') ? 'uk-margin-left' : 'uk-flex-center'"
[class.uk-text-bolder]="!(isMobile && pageType == 'landing')" [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))" [class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
(mouseover)="hoverEvent($event, 'delete')" (mouseout)="hoverEvent($event, 'delete')"> (mouseover)="hoverEvent($event, 'delete')" (mouseout)="hoverEvent($event, 'delete')">
<icon *ngIf="!showLoading" [class.text-orcid]="!showLoading && isLoggedIn && (pids || identifiers?.size > 0)" <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" [class.uk-text-muted]="showLoading || !isLoggedIn || (!pids && (!identifiers || identifiers.size == 0))"
visuallyHidden="delete"></icon> name="orcid_bin" [ratio]="(isMobile && pageType == 'search') ? 0.7 : 1" visuallyHidden="delete"></icon>
<span *ngIf="showLoading" class="uk-icon"><loading <span *ngIf="showLoading" class="uk-icon"><loading
[top_margin]="false" [size]="'small'"></loading></span> [top_margin]="false" [size]="'small'"></loading></span>
<span [ngClass]="(isMobile && pageType == 'landing') ? 'uk-margin-small-left' : 'uk-margin-xsmall-left'">Remove</span> <span [ngClass]="(isMobile && pageType == 'landing') ? 'uk-margin-small-left' : 'uk-margin-xsmall-left'">Remove</span>
</a> </a>
<div *ngIf="isMobile && pageType == 'landing'" class="uk-margin-xsmall-top uk-padding uk-padding-remove-vertical uk-text-meta uk-text-xsmall"
[innerHTML]="((!pids && (!identifiers || identifiers.size == 0)) || !isLoggedIn) ? ((!pids && (!identifiers || identifiers.size == 0)) ? tooltipNoPid : tooltipNoLoggedInUser) : tooltipDelete"></div>
</span> </span>
<!-- Old 'remove' code --> <!-- Old 'remove' code -->
@ -106,50 +114,53 @@ declare var UIkit: any;
<ng-container *ngIf="pageType == 'my_search'"> <ng-container *ngIf="pageType == 'my_search'">
<span class="uk-margin-bottom uk-flex uk-flex-middle uk-flex-center"> <ng-container *ngIf="!showOnlyUpdateButton">
<span>ORCID&#160;</span> <span class="uk-margin-bottom uk-flex uk-flex-middle uk-flex-center">
<img src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="" loading="lazy"> <span>ORCID&#160;</span>
<span>&#160;ACTIONS</span> <img src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="" loading="lazy">
</span> <span>&#160;ACTIONS</span>
</span>
<span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0)
? 'This work is currently deleted.'
: 'View this work from your ORCID record'">
<a (click)="currentAction='get'; getOrcidWorks()"
[class]="'uk-button uk-button-default action uk-flex uk-flex-middle '+ ((showLoading || !putCodes || putCodes.length == 0) ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='get'" name="visibility" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='get'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">View ORCID work</span>
</a>
</span>
</ng-container>
<ng-container *ngIf="showUpdateButton">
<span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0)
? 'This work is currently deleted.'
: ('Update this work to your ORCID record' + ((properties.environment == 'beta') ? '. The action will affect your real ORCID iD.' : '')
+ showUpdateDatesInTooltip())">
<a (click)="currentAction='update'; updateWorkPreparation()"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ ((showLoading || !putCodes || putCodes.length == 0) ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='update'" name="refresh" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='update'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">Update ORCID work</span>
</a>
</span>
</ng-container>
<ng-container *ngIf="!showOnlyUpdateButton">
<span *ngIf="!putCodes || putCodes.length == 0"
[attr.uk-tooltip]="tooltipAdd">
<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">Claim</span>
</a>
</span>
<span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0) <span *ngIf="putCodes && putCodes.length > 0"
? 'This work is currently deleted.'
: 'View this work from your ORCID record'">
<a (click)="currentAction='get'; getOrcidWorks()"
[class]="'uk-button uk-button-default action uk-flex uk-flex-middle '+ ((showLoading || !putCodes || putCodes.length == 0) ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='get'" name="visibility" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='get'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">View ORCID work</span>
</a>
</span>
<span [attr.uk-tooltip]="(!putCodes || putCodes.length == 0)
? 'This work is currently deleted.'
: ('Update this work to your ORCID record' + ((properties.environment == 'beta') ? '. The action will affect your real ORCID iD.' : '')
+ showUpdateDatesInTooltip())">
<a (click)="currentAction='update'; updateWorkPreparation()"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ ((showLoading || !putCodes || putCodes.length == 0) ? 'uk-disabled' : '')">
<icon *ngIf="!showLoading || currentAction!='update'" name="refresh" ratio="1" flex="true"></icon>
<span *ngIf="showLoading && currentAction=='update'" class="uk-icon icon-button"><loading [top_margin]="false"
[size]="'small'"></loading></span>
<span class="uk-margin-small-left">Update ORCID work</span>
</a>
</span>
<span *ngIf="!putCodes || putCodes.length == 0"
[attr.uk-tooltip]="tooltipAdd">
<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">Claim</span>
</a>
</span>
<span *ngIf="putCodes && putCodes.length > 0"
[attr.uk-tooltip]="tooltipDelete"> [attr.uk-tooltip]="tooltipDelete">
<a (click)="currentAction='delete'; deleteWorks();" <a (click)="currentAction='delete'; deleteWorks();"
[class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ (showLoading ? 'uk-disabled' : '')"> [class]="'uk-button uk-button-default action uk-margin-top uk-flex uk-flex-middle '+ (showLoading ? 'uk-disabled' : '')">
@ -159,6 +170,7 @@ declare var UIkit: any;
<span class="uk-margin-small-left">Remove</span> <span class="uk-margin-small-left">Remove</span>
</a> </a>
</span> </span>
</ng-container>
</ng-container> </ng-container>
<modal-alert #workModal large="true"> <modal-alert #workModal large="true">
@ -328,7 +340,10 @@ export class OrcidWorkComponent {
@Input() updateDates: string[] = []; @Input() updateDates: string[] = [];
@Input() givenPutCode: boolean = false; @Input() givenPutCode: boolean = false;
@Input() pageType: string = "search"; @Input() pageType: string = "search";
//for myorcid links page
@Input() showOnlyUpdateButton: boolean = false;
@Input() showUpdateButton: boolean = true;
public subscriptions: Subscription[] = []; public subscriptions: Subscription[] = [];
@ViewChild('workModal') workModal; @ViewChild('workModal') workModal;
// @ViewChild('saveWorkModal') saveWorkModal; // @ViewChild('saveWorkModal') saveWorkModal;

View File

@ -28,10 +28,57 @@
<schema2jsonld *ngIf="name && logoURL" [URL]="properties.domain+ properties.baseLink +'/search/find'" <schema2jsonld *ngIf="name && logoURL" [URL]="properties.domain+ properties.baseLink +'/search/find'"
[logoURL]="properties.domain + properties.baseLink+logoURL" type="search" [name]=name [logoURL]="properties.domain + properties.baseLink+logoURL" type="search" [name]=name
description="Search for {{openaireEntities.RESULTS}} ({{openaireEntities.PUBLICATIONS}}, {{openaireEntities.DATASETS}}, {{openaireEntities.SOFTWARE}}, {{openaireEntities.OTHER}}), {{openaireEntities.PROJECTS}}, {{openaireEntities.ORGANIZATIONS}}, {{openaireEntities.DATASOURCES}} in the OpenAIRE Graph. "></schema2jsonld> description="Search for {{openaireEntities.RESULTS}} ({{openaireEntities.PUBLICATIONS}}, {{openaireEntities.DATASETS}}, {{openaireEntities.SOFTWARE}}, {{openaireEntities.OTHER}}), {{openaireEntities.PROJECTS}}, {{openaireEntities.ORGANIZATIONS}}, {{openaireEntities.DATASOURCES}} in the OpenAIRE Graph. "></schema2jsonld>
<div class="uk-container-large uk-container uk-margin-top"> <div class="uk-container uk-container-large uk-margin-top uk-margin-bottom">
<div class="uk-width-1-1 uk-background-default uk-padding-small uk-padding-remove-horizontal" <div class="uk-background-default uk-padding-small uk-padding-remove-horizontal uk-padding-remove-bottom" uk-sticky="media: @m" [attr.offset]="offset">
uk-slider="finite: true" uk-sticky="media: @m" [attr.offset]="offset"> <slider-tabs type="dynamic" [flexPosition]="'center'" (activeEmitter)="entityChanged($event)">
<div class="uk-position-relative"> <slider-tab *ngIf="showPublications || showDatasets || showOrps || showSoftware"
tabId="result" [tabTemplate]="result" [active]="activeEntity == 'result'">
<ng-template #result>
<span class="uk-text-uppercase">
{{resultsName}}
<span *ngIf=" fetchPublications.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchPublications.searchUtils.totalResults | number}})</span>
</span>
</ng-template>
</slider-tab>
<slider-tab *ngIf="showProjects" tabId="projects" [tabTemplate]="projects" [active]="activeEntity == 'projects'">
<ng-template #projects>
<span class="uk-text-uppercase">
{{projectName}}
<span *ngIf="fetchProjects.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchProjects.searchUtils.totalResults | number}})</span>
</span>
</ng-template>
</slider-tab>
<slider-tab *ngIf="showDataProviders" tabId="datasources" [tabTemplate]="datasources" [active]="activeEntity == 'datasources'">
<ng-template #datasources>
<span class="uk-text-uppercase">
{{dataSourcesName}}
<span *ngIf="fetchDataproviders.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchDataproviders.searchUtils.totalResults | number}})</span>
</span>
</ng-template>
</slider-tab>
<slider-tab *ngIf="showServices" tabId="services" [tabTemplate]="services" [active]="activeEntity == 'services'">
<ng-template #services>
<span class="uk-text-uppercase">
{{servicesName}}
<span *ngIf="fetchServices.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchServices.searchUtils.totalResults | number}})</span>
</span>
</ng-template>
</slider-tab>
<slider-tab *ngIf="showOrganizations" tabId="organizations" [tabTemplate]="organizations" [active]="activeEntity == 'organizations'">
<ng-template #organizations>
<span class="uk-text-uppercase">
{{organizationsName}}
<span *ngIf="fetchOrganizations.searchUtils.totalResults!=null" class="uk-visible@m">
({{fetchOrganizations.searchUtils.totalResults | number}})</span>
</span>
</ng-template>
</slider-tab>
</slider-tabs>
<!--<div class="uk-position-relative">
<div class="uk-slider-container"> <div class="uk-slider-container">
<ul class="uk-slider-items uk-flex uk-flex-center" style="flex-wrap: nowrap !important;"> <ul class="uk-slider-items uk-flex uk-flex-center" style="flex-wrap: nowrap !important;">
<li *ngIf="showPublications || showDatasets || showOrps || showSoftware" (click)="entityChanged('result')"> <li *ngIf="showPublications || showDatasets || showOrps || showSoftware" (click)="entityChanged('result')">
@ -95,7 +142,7 @@
<a class="uk-position-center-left uk-blur-background" uk-slider-item="previous"><span uk-icon="chevron-left"></span></a> <a class="uk-position-center-left uk-blur-background" uk-slider-item="previous"><span uk-icon="chevron-left"></span></a>
<a class="uk-position-center-right uk-blur-background" uk-slider-item="next"><span uk-icon="chevron-right"></span></a> <a class="uk-position-center-right uk-blur-background" uk-slider-item="next"><span uk-icon="chevron-right"></span></a>
</div> </div>
</div> </div>-->
</div> </div>
</div> </div>

View File

@ -89,7 +89,7 @@ export class SearchAllComponent {
@Input() name; @Input() name;
@Input() customFilter: SearchCustomFilter = null; @Input() customFilter: SearchCustomFilter = null;
@Input() formPlaceholderText = "Search in Explore" @Input() formPlaceholderText = "Search"
// @Input() formPlaceholderText = "Search for "+OpenaireEntities.RESULTS+", "+OpenaireEntities.PROJECTS+", "+OpenaireEntities.DATASOURCES+" & "+OpenaireEntities.ORGANIZATIONS+" in OpenAIRE"; // @Input() formPlaceholderText = "Search for "+OpenaireEntities.RESULTS+", "+OpenaireEntities.PROJECTS+", "+OpenaireEntities.DATASOURCES+" & "+OpenaireEntities.ORGANIZATIONS+" in OpenAIRE";
@Input() searchForm: SearchForm = {class: 'search-form', dark: true} @Input() searchForm: SearchForm = {class: 'search-form', dark: true}
@Input() breadcrumbs: Breadcrumb[] = []; @Input() breadcrumbs: Breadcrumb[] = [];

View File

@ -22,13 +22,14 @@ import {SearchOrganizationsModule} from "../searchOrganizations.module";
import {SearchDataProvidersModule} from "../searchDataProviders.module"; import {SearchDataProvidersModule} from "../searchDataProviders.module";
import {PreviousRouteRecorder} from "../../utils/piwik/previousRouteRecorder.guard"; import {PreviousRouteRecorder} from "../../utils/piwik/previousRouteRecorder.guard";
import {BreadcrumbsModule} from "../../utils/breadcrumbs/breadcrumbs.module"; import {BreadcrumbsModule} from "../../utils/breadcrumbs/breadcrumbs.module";
import {SliderTabsModule} from "../../sharedComponents/tabs/slider-tabs.module";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, FormsModule, RouterModule, CommonModule, FormsModule, RouterModule,
DataProvidersServiceModule, ProjectsServiceModule, DataProvidersServiceModule, ProjectsServiceModule,
SearchResearchResultsServiceModule, OrganizationsServiceModule, SearchResearchResultsServiceModule, OrganizationsServiceModule,
SearchResultsModule, PiwikServiceModule, Schema2jsonldModule, SEOServiceModule, AdvancedSearchFormModule, SearchResearchResultsModule, SearchProjectsModule, SearchOrganizationsModule, SearchDataProvidersModule, BreadcrumbsModule SearchResultsModule, PiwikServiceModule, Schema2jsonldModule, SEOServiceModule, AdvancedSearchFormModule, SearchResearchResultsModule, SearchProjectsModule, SearchOrganizationsModule, SearchDataProvidersModule, BreadcrumbsModule, SliderTabsModule
], ],
declarations: [ declarations: [
SearchAllComponent SearchAllComponent

View File

@ -160,7 +160,9 @@ export class SearchResearchResultsComponent {
this.searchUtils.validateSize(params['size']); this.searchUtils.validateSize(params['size']);
this.searchUtils.sortBy = (params['sortBy']) ? params['sortBy'] : ''; this.searchUtils.sortBy = (params['sortBy']) ? params['sortBy'] : '';
if (this.searchUtils.sortBy && this.searchUtils.sortBy != "resultdateofacceptance,descending" && this.searchUtils.sortBy != "resultdateofacceptance,ascending") { if (this.searchUtils.sortBy && this.searchUtils.sortBy != "resultdateofacceptance,descending" && this.searchUtils.sortBy != "resultdateofacceptance,ascending"
&& this.searchUtils.sortBy != "citation_count,descending" && this.searchUtils.sortBy != "popularity,descending"
&& this.searchUtils.sortBy != "influence,descending" && this.searchUtils.sortBy != "impulse,descending") {
this.searchUtils.sortBy = ""; this.searchUtils.sortBy = "";
} }
this.selectedFields = []; this.selectedFields = [];

View File

@ -169,7 +169,7 @@
<entities-selection [simpleView]="true" [currentEntity]="entityType" <entities-selection [simpleView]="true" [currentEntity]="entityType"
(selectionChange)="simpleEntityChanged($event)" (disableSelectEmitter)="disableSelectChange($event)" (selectionChange)="simpleEntityChanged($event)" (disableSelectEmitter)="disableSelectChange($event)"
[onChangeNavigate]="true" [customFilter]="customFilter" class="uk-width-2-5"></entities-selection> [onChangeNavigate]="true" [customFilter]="customFilter" class="uk-width-2-5"></entities-selection>
<div class="uk-width-expand" input placeholder="Search in Explore" [searchable]="true" [hint]="formPlaceholderText" <div class="uk-width-expand" input [placeholder]="formPlaceholderText" [searchable]="true" [hint]="formPlaceholderText"
[(value)]="selectedFields[0].value" tooltip="true"></div> [(value)]="selectedFields[0].value" tooltip="true"></div>
<!-- <a *ngIf="isMobile" href="#mobile-filters" filters-toggle (click)="filtersClicked.emit(true)" uk-toggle>--> <!-- <a *ngIf="isMobile" href="#mobile-filters" filters-toggle (click)="filtersClicked.emit(true)" uk-toggle>-->
<!-- <icon name="filters"></icon>--> <!-- <icon name="filters"></icon>-->

View File

@ -188,8 +188,10 @@ export class AdvancedSearchFormComponent implements OnInit, OnDestroy, OnChanges
fieldIdsChanged(index: number, fieldId: string) { fieldIdsChanged(index: number, fieldId: string) {
this.selectedFields[index].name = this.fieldIdsMap[fieldId].name; this.selectedFields[index].name = this.fieldIdsMap[fieldId].name;
if(this.selectedFields[index].type !== 'keyword' || this.fieldIdsMap[fieldId].type !== 'keyword') {
this.selectedFields[index].value = "";
}
this.selectedFields[index].type = this.fieldIdsMap[fieldId].type; this.selectedFields[index].type = this.fieldIdsMap[fieldId].type;
this.selectedFields[index].value = "";
this.selectedFields[index].param = this.fieldIdsMap[fieldId].param; this.selectedFields[index].param = this.fieldIdsMap[fieldId].param;
if (this.fieldIdsMap[fieldId].type == "boolean") { if (this.fieldIdsMap[fieldId].type == "boolean") {
this.selectedFields[index].value = "true"; this.selectedFields[index].value = "true";

View File

@ -1,5 +1,6 @@
import {Component, Input, Output, EventEmitter} from '@angular/core'; import {Component, Input, Output, EventEmitter} from '@angular/core';
import {Option} from "../../sharedComponents/input/input.component"; import {Option} from "../../sharedComponents/input/input.component";
import {properties} from "../../../../environments/environment";
@Component({ @Component({
selector: 'search-sorting', selector: 'search-sorting',
@ -19,11 +20,21 @@ export class SearchSortingComponent {
@Input() entityType: string = ''; @Input() entityType: string = '';
@Output() sortByChange = new EventEmitter(); @Output() sortByChange = new EventEmitter();
public options: Option[]; public options: Option[];
private generalOptions = [ private generalOptions = properties.environment != "production" ?
{value: '', label: 'Relevance'}, [
{value: 'resultdateofacceptance,descending', label: 'Date (most recent)'}, {value: '', label: 'Relevance'},
{value: 'resultdateofacceptance,ascending', label: 'Date (least recent)'}, {value: 'resultdateofacceptance,descending', label: 'Date (most recent)'},
]; {value: 'resultdateofacceptance,ascending', label: 'Date (least recent)'},
{value: 'citation_count,descending', label: 'Citation Count'},
{value: 'popularity,descending', label: 'Popularity'},
{value: 'influence,descending', label: 'Influence'},
{value: 'impulse,descending', label: 'Impulse'}
] :
[
{value: '', label: 'Relevance'},
{value: 'resultdateofacceptance,descending', label: 'Date (most recent)'},
{value: 'resultdateofacceptance,ascending', label: 'Date (least recent)'}
];
private communityOptions = [ private communityOptions = [
{value: '', label: 'Title'}, {value: '', label: 'Title'},
{value: 'creationdate,descending', label: 'Creation Date (most recent)'}, {value: 'creationdate,descending', label: 'Creation Date (most recent)'},

View File

@ -6,7 +6,9 @@ import {Metrics} from '../utils/entities/metrics';
import{EnvProperties} from '../utils/properties/env-properties'; import{EnvProperties} from '../utils/properties/env-properties';
import {map} from "rxjs/operators"; import {map} from "rxjs/operators";
@Injectable() @Injectable({
providedIn: 'root'
})
export class MetricsService { export class MetricsService {
metrics: Metrics; metrics: Metrics;

View File

@ -135,7 +135,7 @@ export class SearchDataprovidersService {
// result.description = result.description.substring(0, this.sizeOfDescription) + "..."; // result.description = result.description.substring(0, this.sizeOfDescription) + "...";
// } // }
let typeid: string = resData['datasourcetype'].classid; let typeid: string = resData['datasourcetype'] && resData['datasourcetype'].classid;
if(typeid != "entityregistry" && typeid != "entityregistry::projects" && typeid != "entityregistry::repositories") { if(typeid != "entityregistry" && typeid != "entityregistry::projects" && typeid != "entityregistry::repositories") {
if(resData.hasOwnProperty('accessinfopackage')) { if(resData.hasOwnProperty('accessinfopackage')) {
@ -190,7 +190,7 @@ export class SearchDataprovidersService {
return subjects; return subjects;
} }
getDataproviderType(resData: any): string { getDataproviderType(resData: any): string {
if(resData['datasourcetype'].hasOwnProperty("classname")) { if(resData.hasOwnProperty('datasourcetype') && resData['datasourcetype'].hasOwnProperty("classname")) {
return resData['datasourcetype'].classname; return resData['datasourcetype'].classname;
} else { } else {
return ''; return '';

View File

@ -248,10 +248,10 @@ export class SearchProjectsService {
} }
} }
} }
if(resData.hasOwnProperty("startdate")) { if(resData.hasOwnProperty("startdate") && resData['startdate']) {
result.startYear = resData.startdate.split('-')[0]; result.startYear = resData.startdate.split('-')[0];
} }
if(resData.hasOwnProperty("enddate")) { if(resData.hasOwnProperty("enddate") && resData['enddate']) {
result.endYear = resData.enddate.split('-')[0]; result.endYear = resData.enddate.split('-')[0];
} }
// Measure // Measure

View File

@ -23,6 +23,7 @@ import {properties} from "../../../../environments/environment";
import {ClickEvent} from "../../utils/click/click-outside-or-esc.directive"; import {ClickEvent} from "../../utils/click/click-outside-or-esc.directive";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service"; import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {MobileDropdownComponent} from "../../utils/mobile-dropdown/mobile-dropdown.component"; import {MobileDropdownComponent} from "../../utils/mobile-dropdown/mobile-dropdown.component";
import {MatDatepicker} from "@angular/material/datepicker";
export type InputType = export type InputType =
'text' 'text'
@ -33,7 +34,8 @@ export type InputType =
| 'textarea' | 'textarea'
| 'select' | 'select'
| 'chips' | 'chips'
| 'year-range'; | 'year-range'
| 'date';
export interface Option { export interface Option {
icon?: string, icon?: string,
@ -75,9 +77,9 @@ declare var UIkit;
<div *ngIf="formControl" [id]="id"> <div *ngIf="formControl" [id]="id">
<div class="input-wrapper" [class.disabled]="formControl.disabled" [class.opened]="opened" <div class="input-wrapper" [class.disabled]="formControl.disabled" [class.opened]="opened"
[class.focused]="focused" [ngClass]="inputClass" [class.hint]="hint" [class.focused]="focused" [ngClass]="inputClass" [class.hint]="hint"
[class.active]="!focused && (formAsControl?.value || selectable || formAsArray?.length > 0 || getLabel(formAsControl?.value) || yearRangeActive)" [class.active]="!focused && (formAsControl?.value || selectable || type === 'date' || formAsArray?.length > 0 || getLabel(formAsControl?.value) || yearRangeActive)"
[class.danger]="(formControl.invalid && (formControl.touched || !!searchControl?.touched)) || (!!searchControl?.invalid && !!searchControl?.touched)"> [class.danger]="(formControl.invalid && (formControl.touched || !!searchControl?.touched)) || (!!searchControl?.invalid && !!searchControl?.touched)">
<div #inputBox class="input-box" [class.select]="selectable" click-outside-or-esc <div #inputBox class="input-box" [class.select]="selectable || type ==='date'" click-outside-or-esc
[class.static]="placeholderInfo?.static" (clickOutside)="click($event)"> [class.static]="placeholderInfo?.static" (clickOutside)="click($event)">
<div *ngIf="!placeholderInfo?.static && placeholderInfo?.label" class="placeholder"> <div *ngIf="!placeholderInfo?.static && placeholderInfo?.label" class="placeholder">
<label>{{placeholderInfo.label}} <sup *ngIf="required">*</sup></label> <label>{{placeholderInfo.label}} <sup *ngIf="required">*</sup></label>
@ -90,8 +92,8 @@ declare var UIkit;
[class.uk-text-truncate]="!focused"> [class.uk-text-truncate]="!focused">
</ng-template> </ng-template>
<ng-template [ngIf]="type === 'textarea'"> <ng-template [ngIf]="type === 'textarea'">
<textarea #textArea class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint" <textarea #textArea class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[rows]="rows" [formControl]="formAsControl"></textarea> [rows]="rows" [formControl]="formAsControl"></textarea>
</ng-template> </ng-template>
<ng-template [ngIf]="type === 'select'"> <ng-template [ngIf]="type === 'select'">
<ng-container *ngIf="placeholderInfo?.static"> <ng-container *ngIf="placeholderInfo?.static">
@ -163,8 +165,11 @@ declare var UIkit;
maxlength="4" (click)="activeIndex = 1;$event.preventDefault()" [formControl]="getFormByName(yearRange.to.control)"> maxlength="4" (click)="activeIndex = 1;$event.preventDefault()" [formControl]="getFormByName(yearRange.to.control)">
</div> </div>
</ng-template> </ng-template>
<div <ng-template [ngIf]="type === 'date'">
*ngIf="(formControl.disabled && disabledIcon) || icon || (selectable && selectArrow) || type === 'autocomplete' || searchable" <div *ngIf="!formAsControl.getRawValue()" class="input uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{selectADate}}</div>
<div *ngIf="formAsControl.getRawValue()" class="input uk-text-truncate" [class.uk-disabled]="formControl.disabled">{{formAsControl.getRawValue() | date: 'dd-MM-yyyy'}}</div>
</ng-template>
<div *ngIf="(formControl.disabled && disabledIcon) || icon || (selectable && selectArrow) || type === 'autocomplete' || searchable || type === 'date'"
class="uk-margin-small-left icon"> class="uk-margin-small-left icon">
<icon *ngIf="formControl.disabled && disabledIcon" [name]="disabledIcon" [flex]="true"></icon> <icon *ngIf="formControl.disabled && disabledIcon" [name]="disabledIcon" [flex]="true"></icon>
<ng-template [ngIf]="formControl.enabled"> <ng-template [ngIf]="formControl.enabled">
@ -174,8 +179,10 @@ declare var UIkit;
(click)="resetSearch($event)"> (click)="resetSearch($event)">
<icon [flex]="true" name="close"></icon> <icon [flex]="true" name="close"></icon>
</button> </button>
<button *ngIf="(!focused && type === 'autocomplete' && !selectable) || (type !== 'autocomplete' && !searchControl?.value && !!formControl?.value && (searchable || !selectable))" <button *ngIf="(!focused && type === 'autocomplete' && !selectable) ||
class="uk-close uk-icon" (click)="resetValue($event)"> (type !== 'autocomplete' && !searchControl?.value && !!formControl?.value && (searchable || !selectable)) ||
(type === 'date' && formAsControl?.value)"
class="uk-close uk-icon" (click)="resetValue($event);">
<icon [flex]="true" name="close"></icon> <icon [flex]="true" name="close"></icon>
</button> </button>
</ng-template> </ng-template>
@ -188,20 +195,23 @@ declare var UIkit;
</div> </div>
</div> </div>
</div> </div>
<div *ngIf="!mobile && type === 'date' && opened" class="uk-dropdown" #calendarBox
uk-dropdown="pos: bottom-left; mode: none; boundary-align: true;" [attr.boundary]="'#' + id" (click)="$event.stopPropagation()">
<mat-calendar [selected]="selectedDate" [startAt]="selectedDate" (selectedChange)="dateChanged($event)"></mat-calendar>
</div>
<div *ngIf="!mobile && filteredOptions && filteredOptions.length > 0 && opened" class="options uk-dropdown" #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"> uk-dropdown="pos: bottom-justify; mode: none; boundary-align: true;" [attr.boundary]="'#' + id">
<ul class="uk-nav uk-dropdown-nav"> <ul class="uk-nav uk-dropdown-nav">
<li *ngFor="let option of filteredOptions; let i=index" [class.uk-hidden]="option.hidden" <li *ngFor="let option of filteredOptions; let i=index" [class.uk-hidden]="option.hidden"
[class.uk-active]="(formControl.value === option.value) || selectedIndex === i"> [class.uk-active]="(formControl.value === option.value) || selectedIndex === i">
<a (click)="selectOption(option, $event)" <a (click)="selectOption(option, $event)"
[class]="option.disabled ? 'uk-disabled uk-text-muted' : ''"> [class]="option.disabled ? 'uk-disabled uk-text-muted' : ''">
<span <span [attr.uk-tooltip]="(tooltip)?('title: ' + (option.tooltip ? option.tooltip : option.label) + '; delay: 500; pos:bottom-left'):null">{{option.label}}</span>
[attr.uk-tooltip]="(tooltip)?('title: ' + (option.tooltip ? option.tooltip : option.label) + '; delay: 500; pos:bottom-left'):null">{{option.label}}</span>
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
<mobile-dropdown *ngIf="mobile" #mobileDropdown> <mobile-dropdown *ngIf="mobile && filteredOptions && filteredOptions.length > 0 && opened" (onClose)="focus(false)" #mobileDropdown>
<div *ngIf="placeholderInfo" class="uk-text-emphasis uk-text-bolder uk-text-center uk-padding-small uk-padding-remove-vertical uk-text-uppercase"> <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}} {{placeholderInfo.label}}
</div> </div>
@ -279,7 +289,9 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
/** Year Range Configuration */ /** Year Range Configuration */
@Input() yearRange: YearRange; @Input() yearRange: YearRange;
public activeIndex: 0 | 1 | null = null; public activeIndex: 0 | 1 | null = null;
/** Date Configuration*/
@Input() selectADate: string = 'Select a date';
public selectedDate: Date;
@Input() visibleRows: number = -1; @Input() visibleRows: number = -1;
@Input() extendEnter: () => void = null; @Input() extendEnter: () => void = null;
@Output() focusEmitter: EventEmitter<boolean> = new EventEmitter<boolean>(); @Output() focusEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
@ -299,9 +311,11 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
private subscriptions: any[] = []; private subscriptions: any[] = [];
@ViewChild('inputBox') inputBox: ElementRef; @ViewChild('inputBox') inputBox: ElementRef;
@ViewChild('optionBox') optionBox: ElementRef; @ViewChild('optionBox') optionBox: ElementRef;
@ViewChild('calendarBox') calendarBox: ElementRef;
@ViewChild('mobileDropdown') mobileDropdown: MobileDropdownComponent; @ViewChild('mobileDropdown') mobileDropdown: MobileDropdownComponent;
@ViewChild('searchInput') searchInput: ElementRef; @ViewChild('searchInput') searchInput: ElementRef;
@ViewChildren('chip') chips: QueryList<ElementRef>; @ViewChildren('chip') chips: QueryList<ElementRef>;
@ViewChild('datepicker') datepicker: MatDatepicker<any>;
@Input() @Input()
set placeholder(placeholder: string | Placeholder) { set placeholder(placeholder: string | Placeholder) {
@ -530,8 +544,10 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
?this.getFormByName(this.yearRange.from.control).errors:this.getFormByName(this.yearRange.to.control).errors)); ?this.getFormByName(this.yearRange.from.control).errors:this.getFormByName(this.yearRange.to.control).errors));
} else if(this.formAsControl) { } else if(this.formAsControl) {
return this.formAsControl.errors; return this.formAsControl.errors;
} else { } else if(this.searchControl) {
return this.searchControl.errors; return this.searchControl.errors;
} else {
return null;
} }
} }
@ -564,10 +580,13 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
} }
})); }));
} }
if (this.formAsControl?.validator) { if (this.formAsControl?.validator || this.formAsArray?.validator) {
let validator = this.formControl.validator({} as AbstractControl); let validator = this.formControl.validator({} as AbstractControl);
this.required = (validator && validator.required); this.required = (validator && validator.required);
} }
if(this.type === 'date') {
this.selectedDate = this.formAsControl.getRawValue()?new Date(this.formAsControl.getRawValue()):null;
}
this.subscriptions.push(this.formControl.valueChanges.subscribe(value => { this.subscriptions.push(this.formControl.valueChanges.subscribe(value => {
if (this.formControl.enabled) { if (this.formControl.enabled) {
if(this.type !== 'year-range') { if(this.type !== 'year-range') {
@ -587,6 +606,9 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.open(true); this.open(true);
} }
} }
if (this.type === 'date') {
this.selectedDate = value?new Date(value):null;
}
} }
if ((this.value && value && this.value !== value) || (!this.value && value) || this.value && !value) { if ((this.value && value && this.value !== value) || (!this.value && value) || this.value && !value) {
this.valueChange.emit(this.formControl.value); this.valueChange.emit(this.formControl.value);
@ -735,7 +757,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.searchInput.nativeElement.focus(); this.searchInput.nativeElement.focus();
this.activeElement.next(this.chips.last); this.activeElement.next(this.chips.last);
} }
if (this.selectArrow) { if (this.selectArrow || this.datepicker) {
this.open(!this.opened); this.open(!this.opened);
} else if (this.type !== 'autocomplete' || this.showOptionsOnEmpty || !this.formControl.value) { } else if (this.type !== 'autocomplete' || this.showOptionsOnEmpty || !this.formControl.value) {
this.open(true); this.open(true);
@ -774,6 +796,13 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
UIkit.dropdown(this.optionBox.nativeElement).hide(); UIkit.dropdown(this.optionBox.nativeElement).hide();
this.focused = false; this.focused = false;
} }
} else if(this.calendarBox) {
if (this.opened) {
UIkit.dropdown(this.calendarBox.nativeElement).show();
} else {
UIkit.dropdown(this.calendarBox.nativeElement).hide();
this.focused = false;
}
} else if(this.mobileDropdown) { } else if(this.mobileDropdown) {
if(this.opened) { if(this.opened) {
this.mobileDropdown.open(); this.mobileDropdown.open();
@ -810,5 +839,13 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.searchControl.setValue(''); this.searchControl.setValue('');
} }
} }
if(this.mobileDropdown) {
this.mobileDropdown.close();
}
}
dateChanged(event: Date) {
this.focus(false);
this.formAsControl.setValue(event.getTime());
} }
} }

View File

@ -1,10 +1,13 @@
import {NgModule} from '@angular/core'; import {NgModule} from '@angular/core';
import {InputComponent} from "./input.component"; import {InputComponent} from "./input.component";
import {SharedModule} from "../../../openaireLibrary/shared/shared.module"; import {SharedModule} from "../../shared/shared.module";
import {IconsModule} from "../../utils/icons/icons.module"; import {IconsModule} from "../../utils/icons/icons.module";
import {SafeHtmlPipeModule} from "../../utils/pipes/safeHTMLPipe.module"; import {SafeHtmlPipeModule} from "../../utils/pipes/safeHTMLPipe.module";
import {ClickModule} from "../../utils/click/click.module"; import {ClickModule} from "../../utils/click/click.module";
import {MobileDropdownModule} from "../../utils/mobile-dropdown/mobile-dropdown.module"; import {MobileDropdownModule} from "../../utils/mobile-dropdown/mobile-dropdown.module";
import {MatDatepickerModule} from "@angular/material/datepicker";
import {MatNativeDateModule} from "@angular/material/core";
import {MatInputModule} from "@angular/material/input";
@NgModule({ @NgModule({
imports: [ imports: [
@ -12,7 +15,10 @@ import {MobileDropdownModule} from "../../utils/mobile-dropdown/mobile-dropdown.
IconsModule, IconsModule,
SafeHtmlPipeModule, SafeHtmlPipeModule,
ClickModule, ClickModule,
MobileDropdownModule MobileDropdownModule,
MatDatepickerModule,
MatNativeDateModule,
MatInputModule
], ],
exports: [ exports: [
InputComponent InputComponent

View File

@ -144,7 +144,7 @@
<ng-content select="[extra-s]"></ng-content> <ng-content select="[extra-s]"></ng-content>
</ng-container> </ng-container>
</ul> </ul>
<div *ngIf="hasSearchBar" search-input [(value)]="keyword" placeholder="Search" <div *ngIf="hasSearchBar" search-input [(value)]="keyword" [placeholder]="'Search'+(portalName ? (' in '+portalName) : '')"
[searchInputClass]="'flat background small-vertical'" (searchEmitter)="goTo(canvas)" [searchInputClass]="'flat background small-vertical'" (searchEmitter)="goTo(canvas)"
class="uk-width-1-1 uk-padding-small uk-margin-medium-top"></div> class="uk-width-1-1 uk-padding-small uk-margin-medium-top"></div>
</div> </div>
@ -173,7 +173,7 @@
<ng-container *ngIf="!activeHeader.menuPosition || activeHeader.menuPosition === 'center'"> <ng-container *ngIf="!activeHeader.menuPosition || activeHeader.menuPosition === 'center'">
<ng-container *ngTemplateOutlet="mainMenu"></ng-container> <ng-container *ngTemplateOutlet="mainMenu"></ng-container>
</ng-container> </ng-container>
<div *ngIf="searchMode" #search_input search-input [(value)]="keyword" placeholder="Search" <div *ngIf="searchMode" #search_input search-input [(value)]="keyword" [placeholder]="'Search'+(portalName ? (' in '+portalName) : '')"
[searchInputClass]="'flat background small-vertical'" (searchEmitter)="goTo()" [searchInputClass]="'flat background small-vertical'" (searchEmitter)="goTo()"
class="uk-width-large@l uk-width-medium uk-width-xlarge@xl"></div> class="uk-width-large@l uk-width-medium uk-width-xlarge@xl"></div>
</div> </div>

View File

@ -70,6 +70,7 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
showEntity = {}; showEntity = {};
showPage = {}; showPage = {};
public searchMode: boolean = false; public searchMode: boolean = false;
public portalName: string = "";
public additionalMenuItems: MenuItem[] = []; public additionalMenuItems: MenuItem[] = [];
public featuredMenuItems: MenuItem[] = []; public featuredMenuItems: MenuItem[] = [];
@ -136,6 +137,9 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
//this.config.getCommunityInformation(this.properties, this.communityId).subscribe(data => { //this.config.getCommunityInformation(this.properties, this.communityId).subscribe(data => {
this.subs.push(this.config.portalAsObservable.subscribe(data => { this.subs.push(this.config.portalAsObservable.subscribe(data => {
if (data) { if (data) {
if(data.name) {
this.portalName = data.name;
}
this.showEntity = {}; this.showEntity = {};
this.showPage = {}; this.showPage = {};
if (data['entities']) { if (data['entities']) {

View File

@ -21,4 +21,5 @@ export class SliderTabComponent {
public queryParams: any = null; public queryParams: any = null;
@Input() @Input()
public customClass: string = ''; public customClass: string = '';
@Input() tabTemplate: any;
} }

View File

@ -28,34 +28,52 @@ declare var UIkit;
[ngClass]="'uk-flex-' + flexPosition + ' ' + tabsClass"> [ngClass]="'uk-flex-' + flexPosition + ' ' + tabsClass">
<ng-container *ngIf="type === 'static'"> <ng-container *ngIf="type === 'static'">
<li *ngFor="let tab of leftTabs" [ngStyle]="" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block"> <li *ngFor="let tab of leftTabs" [ngStyle]="" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block">
<a>{{tab.title}}</a> <a>
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li> </li>
<li *ngFor="let tab of rightTabs; let i=index;" [style.max-width]="(position === 'horizontal')?'50%':null" [ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''" <li *ngFor="let tab of rightTabs; let i=index;" [style.max-width]="(position === 'horizontal')?'50%':null" [ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''"
class="uk-text-capitalize uk-text-truncate uk-display-block"> class="uk-text-capitalize uk-text-truncate uk-display-block">
<a [ngClass]="tab.customClass">{{tab.title}}</a> <a [ngClass]="tab.customClass">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li> </li>
</ng-container> </ng-container>
<ng-container *ngIf="type === 'dynamic'"> <ng-container *ngIf="type === 'dynamic'">
<li *ngFor="let tab of leftTabs; let i=index;" [class.uk-active]="tab.active" [style.max-width]="(position === 'horizontal')?'50%':null"> <li *ngFor="let tab of leftTabs; let i=index;" [class.uk-active]="tab.active" [style.max-width]="(position === 'horizontal')?'50%':null">
<a [routerLink]="tab.routerLink" [queryParams]="tab.queryParams" [ngClass]="tab.customClass" <a [routerLink]="tab.routerLink" [queryParams]="tab.queryParams" [ngClass]="tab.customClass"
(click)="showActive(i)" (click)="showActive(i)"
class="uk-text-capitalize uk-text-truncate uk-display-block">{{tab.title}}</a> class="uk-text-capitalize uk-text-truncate uk-display-block">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li> </li>
<li *ngFor="let tab of rightTabs; let i=index;" [style.max-width]="(position === 'horizontal')?'50%':null" [class.uk-active]="tab.active" <li *ngFor="let tab of rightTabs; let i=index;" [style.max-width]="(position === 'horizontal')?'50%':null" [class.uk-active]="tab.active"
[ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''"> [ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''">
<a [routerLink]="tab.routerLink" [queryParams]="tab.queryParams" [ngClass]="tab.customClass" <a [routerLink]="tab.routerLink" [queryParams]="tab.queryParams" [ngClass]="tab.customClass"
(click)="showActive(i)" (click)="showActive(i)"
class="uk-text-capitalize uk-text-truncate uk-display-block">{{tab.title}}</a> class="uk-text-capitalize uk-text-truncate uk-display-block">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li> </li>
</ng-container> </ng-container>
<ng-container *ngIf="type === 'scrollable'"> <ng-container *ngIf="type === 'scrollable'">
<li *ngFor="let tab of leftTabs" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block" [class.uk-active]="tab.active"> <li *ngFor="let tab of leftTabs" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block" [class.uk-active]="tab.active">
<a routerLink="./" [fragment]="tab.id" queryParamsHandling="merge" [ngClass]="tab.customClass">{{tab.title}}</a> <a routerLink="./" [fragment]="tab.id" queryParamsHandling="merge" [ngClass]="tab.customClass">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li> </li>
<li *ngFor="let tab of rightTabs; let i=index;" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block" <li *ngFor="let tab of rightTabs; let i=index;" [style.max-width]="(position === 'horizontal')?'50%':null" class="uk-text-capitalize uk-text-truncate uk-display-block"
[ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''" [ngClass]="i === 0?'uk-flex-1 uk-flex uk-flex-right':''"
[class.uk-active]="tab.active"> [class.uk-active]="tab.active">
<a routerLink="./" [fragment]="tab.id" queryParamsHandling="merge" [ngClass]="tab.customClass">{{tab.title}}</a> <a routerLink="./" [fragment]="tab.id" queryParamsHandling="merge" [ngClass]="tab.customClass">
<span *ngIf="tab.title">{{tab.title}}</span>
<ng-container *ngTemplateOutlet="tab.tabTemplate"></ng-container>
</a>
</li> </li>
</ng-container> </ng-container>
</ul> </ul>
@ -127,6 +145,13 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
} }
ngAfterViewInit() { ngAfterViewInit() {
this.initTabs();
this.tabs.changes.subscribe(() => {
this.initTabs();
});
}
public initTabs() {
if (typeof document !== 'undefined' && this.tabs.length > 0) { if (typeof document !== 'undefined' && this.tabs.length > 0) {
setTimeout(() => { setTimeout(() => {
if (this.position === 'horizontal') { if (this.position === 'horizontal') {

View File

@ -10,108 +10,129 @@ import {properties} from "../../../../environments/environment";
@Component({ @Component({
selector: 'showAuthors', selector: 'showAuthors',
template: ` template: `
<ng-template #author_template let-author="author" let-i="i" let-italic="italic"> <ng-template #author_template let-author="author" let-i="i" let-italic="italic">
<span *ngIf="isSticky || (!author.orcid && !author.orcid_pending) || !testBrowser" style="margin-right: 5px;" <span *ngIf="isSticky || (!author.orcid && !author.orcid_pending) || !isBrowser" style="margin-right: 5px;"
[class.uk-text-italic]="italic"> [class.uk-text-italic]="italic">
{{author.fullName + ";"}} {{author.fullName + ";"}}
</span> </span>
<a *ngIf="!isSticky && (author.orcid || author.orcid_pending) && testBrowser" class="uk-flex-inline uk-flex-middle uk-link-text"> <ng-container *ngIf="!isSticky && (author.orcid || author.orcid_pending) && isBrowser">
<img *ngIf="author.orcid" src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="orcid" loading="lazy" style="width:16px; height:16px; margin-right: 3px;"> <a #toggle class="uk-flex-inline uk-flex-middle uk-link-text">
<img *ngIf="!author.orcid && author.orcid_pending" src="assets/common-assets/common/ORCIDiD_iconbw16x16.png" alt="orcid bw" loading="lazy" style="margin-right: 3px;"> <img *ngIf="author.orcid" src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="orcid"
<span style="margin-right: 5px;" [class.uk-text-italic]="italic"> loading="lazy" style="width:16px; height:16px; margin-right: 3px;">
{{author.fullName + ";"}} <img *ngIf="!author.orcid && author.orcid_pending"
</span> src="assets/common-assets/common/ORCIDiD_iconbw16x16.png" alt="orcid bw" loading="lazy"
</a> style="margin-right: 3px;">
<div *ngIf="!isSticky && (author.orcid || author.orcid_pending) && testBrowser" <span style="margin-right: 5px;" [class.uk-text-italic]="italic">
class="default-dropdown uk-margin-remove-top uk-dropdown orcid-dropdown" {{author.fullName + ";"}}
uk-dropdown="mode:click; offset: 4" style="min-width: 465px !important;"> </span>
<div class="uk-padding-small"> </a>
<h6 class="uk-margin-remove">{{author.fullName}}</h6> <div *ngIf="!isMobile" class="default-dropdown uk-margin-remove-top uk-dropdown orcid-dropdown" uk-dropdown="mode:click; offset: 4" style="min-width: 465px !important;">
<div> <ng-container *ngTemplateOutlet="dropdown"></ng-container>
<div class="uk-text-meta uk-margin-bottom">ORCID</div> </div>
<mobile-dropdown *ngIf="isMobile" [toggle]="toggle">
<div class="uk-text-meta uk-text-xsmall uk-margin-small-top uk-margin-small-bottom"> <div class="orcid-dropdown">
<img *ngIf="author.orcid" src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt="" loading="lazy">{{" "}} <ng-container *ngTemplateOutlet="dropdown"></ng-container>
<img *ngIf="!author.orcid && author.orcid_pending" src="assets/common-assets/common/ORCIDiD_iconbw16x16.png" alt="" loading="lazy">{{" "}}
<i *ngIf="author.orcid">Harvested from ORCID Public Data File</i>
<i *ngIf="!author.orcid && author.orcid_pending">Derived by OpenAIRE algorithms or harvested from 3d party repositories</i>
</div>
<div>
<div class="clipboard-wrapper uk-width-1-1 uk-flex uk-flex-middle uk-flex-center"
style="min-height: 43px; min-width: 280px;">
<input #element class="uk-padding-small uk-text-emphasis uk-width-medium uk-disabled"
[value]="properties.orcidURL+(author.orcid ? author.orcid : author.orcid_pending)"/>
<a [class]="'uk-link copy orcid_clipboard_btn orcid_clipboard_btn_auhtor_'+i"
title="Copy to clipboard" (click)="copyToClipboard(element)">
COPY
</a>
</div> </div>
<div class="uk-text-center uk-margin-small-top"> </mobile-dropdown>
<a class="uk-button uk-button-text custom-external" <ng-template #dropdown>
title="Visit author in ORCID" [href]="properties.orcidURL+(author.orcid ? author.orcid : author.orcid_pending)" target="_blank"> <div class="uk-padding-small">
VISIT AUTHOR IN ORCID <h6 class="uk-margin-remove">{{author.fullName}}</h6>
</a> <div>
</div> <div class="uk-text-meta uk-margin-bottom">ORCID</div>
</div>
</div>
<hr> <div class="uk-text-meta uk-text-xsmall uk-margin-small-top uk-margin-small-bottom">
<div class="uk-margin-top uk-text-bold uk-text-emphasis uk-text-center"> <img *ngIf="author.orcid" src="assets/common-assets/common/ORCIDiD_icon16x16.png" alt=""
{{author.fullName}} in OpenAIRE loading="lazy">{{" "}}
</div> <img *ngIf="!author.orcid && author.orcid_pending"
<div class="uk-text-center uk-margin-top uk-margin-large-left uk-margin-large-right"> src="assets/common-assets/common/ORCIDiD_iconbw16x16.png" alt="" loading="lazy">{{" "}}
<a *ngIf="properties.adminToolsPortalType !== 'eosc'" class="uk-button uk-button-primary uk-text-bold uk-padding-remove-top uk-padding-remove-bottom"
(click)="onClick()" <i *ngIf="author.orcid">Harvested from ORCID Public Data File</i>
[queryParams]="routerHelper.createQueryParams(['orcid','oc'],[(author['orcid'] ? author['orcid'] : author['orcid_pending']),'and'])" <i *ngIf="!author.orcid && author.orcid_pending">Derived by OpenAIRE algorithms or harvested
routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"> from 3d party repositories</i>
<span class="space">Search</span> </div>
</a> <div>
<a *ngIf="properties.adminToolsPortalType == 'eosc'" class="uk-button uk-button-primary uk-text-bold uk-padding-remove-top uk-padding-remove-bottom uk-light" <div class="clipboard-wrapper uk-width-1-1 uk-flex uk-flex-middle uk-flex-center"
[href]="'https://explore.openaire.eu'+properties.searchLinkToAdvancedResults+'?orcid='+(author['orcid'] ? author['orcid'] : author['orcid_pending'])+'&oc=and'" style="min-height: 43px; min-width: 280px;">
target="_blank"> <input #element class="uk-padding-small uk-text-emphasis uk-width-expand uk-disabled"
<span class="space custom-external">Search in OpenAIRE</span> [value]="properties.orcidURL+(author.orcid ? author.orcid : author.orcid_pending)"/>
</a> <button class="uk-button uk-button-link uk-margin-small-right copy orcid_clipboard_btn" [ngClass]="'orcid_clipboard_btn_auhtor_'+i"
</div> title="Copy to clipboard" (click)="copyToClipboard(element)">
</div> <icon name="content_copy" visuallyHidden="Copy to clipboard" [flex]="true"></icon>
</div> </button>
</ng-template> </div>
<div class="uk-text-center uk-margin-small-top">
<div *ngIf="authors" class="uk-height-max-medium uk-overflow-auto uk-text-small uk-text-emphasis uk-flex uk-flex-wrap"> <a class="uk-button uk-button-text custom-external"
title="Visit author in ORCID"
[href]="properties.orcidURL+(author.orcid ? author.orcid : author.orcid_pending)"
target="_blank">
VISIT AUTHOR IN ORCID
</a>
</div>
</div>
</div>
<hr>
<div class="uk-margin-top uk-text-bold uk-text-emphasis uk-text-center">
{{author.fullName}} in OpenAIRE
</div>
<div class="uk-text-center uk-margin-top uk-margin-large-left uk-margin-large-right">
<a *ngIf="properties.adminToolsPortalType !== 'eosc'"
class="uk-button uk-button-primary uk-text-bold uk-padding-remove-top uk-padding-remove-bottom"
(click)="onClick()"
[queryParams]="routerHelper.createQueryParams(['orcid','oc'],[(author['orcid'] ? author['orcid'] : author['orcid_pending']),'and'])"
routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults">
<span class="space">Search</span>
</a>
<a *ngIf="properties.adminToolsPortalType == 'eosc'"
class="uk-button uk-button-primary uk-text-bold uk-padding-remove-top uk-padding-remove-bottom uk-light"
[href]="'https://explore.openaire.eu'+properties.searchLinkToAdvancedResults+'?orcid='+(author['orcid'] ? author['orcid'] : author['orcid_pending'])+'&oc=and'"
target="_blank">
<span class="space custom-external">Search in OpenAIRE</span>
</a>
</div>
</div>
</ng-template>
</ng-container>
</ng-template>
<div *ngIf="authors"
class="uk-height-max-medium uk-overflow-auto uk-text-small uk-text-emphasis uk-flex uk-flex-wrap">
<span class="uk-text-meta uk-margin-xsmall-right"> <span class="uk-text-meta uk-margin-xsmall-right">
Authors: Authors:
</span> </span>
<ng-container *ngFor="let author of authors.slice(0, viewAll?authors.length:authorsLimit) let i=index"> <ng-container *ngFor="let author of authors.slice(0, viewAll?authors.length:authorsLimit) let i=index">
<ng-container *ngTemplateOutlet="author_template; context: { author: author, i:i, italic: true}"></ng-container> <ng-container
</ng-container> *ngTemplateOutlet="author_template; context: { author: author, i:i, italic: true}"></ng-container>
<span *ngIf="!showAll && authors && authors.length > authorsLimit" class="uk-text-meta"> </ng-container>
+{{authors.length-authorsLimit | number}} more <span *ngIf="!showAll && authors && authors.length > authorsLimit" class="uk-text-meta">
+{{authors.length - authorsLimit | number}} more
</span> </span>
<span *ngIf="showAll && authors && authors.length > authorsLimit && !viewAll"> <span *ngIf="showAll && authors && authors.length > authorsLimit && !viewAll">
<a (click)="viewAllClick();"> <a (click)="viewAllClick();" class="uk-background-muted custom-extra-entities">
+{{authors.length-authorsLimit | number}} Authors +{{authors.length - authorsLimit | number}} Authors
</a> </a>
</span> </span>
<div *ngIf="viewAll && lessBtn" class="uk-text-small"> <div *ngIf="viewAll && lessBtn" class="uk-text-small">
<a (click)="viewAll = !viewAll; lessBtn=false;">View less</a> <a (click)="viewAll = !viewAll; lessBtn=false;">View less</a>
</div>
</div> </div>
</div>
<modal-alert *ngIf="!isMobile" #authorsModal> <modal-alert *ngIf="!isMobile" #authorsModal>
<div class="uk-text-small uk-text-emphasis uk-grid uk-grid-column-collapse uk-grid-row-small" uk-grid> <div class="uk-text-small uk-text-emphasis uk-grid uk-grid-column-collapse uk-grid-row-small" uk-grid>
<ng-container *ngFor="let author of authors; let i=index"> <ng-container *ngFor="let author of authors; let i=index">
<ng-container *ngTemplateOutlet="author_template; context: { author: author, i:i}"></ng-container> <ng-container *ngTemplateOutlet="author_template; context: { author: author, i:i}"></ng-container>
</ng-container> </ng-container>
</div> </div>
</modal-alert> </modal-alert>
<fs-modal *ngIf="isMobile" #authorsModal classTitle="uk-tile-default uk-border-bottom"> <fs-modal *ngIf="isMobile" #authorsModal classTitle="uk-tile-default uk-border-bottom">
<div class="uk-text-small uk-text-emphasis uk-grid uk-grid-column-collapse uk-grid-row-small" uk-grid> <div class="uk-text-small uk-text-emphasis uk-grid uk-grid-column-collapse uk-grid-row-small" uk-grid>
<ng-container *ngFor="let author of authors; let i=index"> <ng-container *ngFor="let author of authors; let i=index">
<ng-container *ngTemplateOutlet="author_template; context: { author: author, i:i}"></ng-container> <ng-container *ngTemplateOutlet="author_template; context: { author: author, i:i}"></ng-container>
</ng-container> </ng-container>
</div> </div>
</fs-modal> </fs-modal>
` `
}) })
@ -131,11 +152,11 @@ export class ShowAuthorsComponent {
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public routerHelper: RouterHelper = new RouterHelper(); public routerHelper: RouterHelper = new RouterHelper();
testBrowser: boolean; isBrowser: boolean;
public clipboard; public clipboard;
constructor(private route: ActivatedRoute, @Inject(PLATFORM_ID) private platformId: string) { constructor(private route: ActivatedRoute, @Inject(PLATFORM_ID) private platformId: string) {
this.testBrowser = isPlatformBrowser(platformId); this.isBrowser = isPlatformBrowser(platformId);
} }
ngOnInit() {} ngOnInit() {}

View File

@ -6,10 +6,12 @@ import {RouterModule} from '@angular/router';
import {ShowAuthorsComponent} from './showAuthors.component'; import {ShowAuthorsComponent} from './showAuthors.component';
import {AlertModalModule} from "../modal/alertModal.module"; import {AlertModalModule} from "../modal/alertModal.module";
import {FullScreenModalModule} from "../modal/full-screen-modal/full-screen-modal.module"; import {FullScreenModalModule} from "../modal/full-screen-modal/full-screen-modal.module";
import {MobileDropdownModule} from "../mobile-dropdown/mobile-dropdown.module";
import {IconsModule} from "../icons/icons.module";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, FormsModule, RouterModule, AlertModalModule, FullScreenModalModule CommonModule, FormsModule, RouterModule, AlertModalModule, FullScreenModalModule, MobileDropdownModule, IconsModule
], ],
declarations: [ declarations: [
ShowAuthorsComponent ShowAuthorsComponent
@ -20,4 +22,4 @@ import {FullScreenModalModule} from "../modal/full-screen-modal/full-screen-moda
ShowAuthorsComponent ShowAuthorsComponent
] ]
}) })
export class ShowAuthorsModule { } export class ShowAuthorsModule { }

View File

@ -1,143 +1,156 @@
<a (click)="open()" <a (click)="open()"
[title]="'Send data to cloud storage'" [title]="'Send data to cloud storage'"
[attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'" [attr.uk-tooltip]="'pos: bottom; cls: uk-active uk-text-small uk-padding-small'"
class="uk-flex uk-flex-middle uk-flex-center uk-button-link uk-text-bolder"> class="uk-flex uk-flex-middle uk-button-link"
<icon flex="true" ratio="0.8" name="cloud_upload" visuallyHidden="upload"></icon> [class.uk-text-bolder]="!isMobile">
<span class="uk-margin-xsmall-left">Transfer</span> <icon flex="true" ratio="1" name="cloud_upload" visuallyHidden="upload"></icon>
</a> <span [ngClass]="isMobile ? 'uk-margin-small-left' : 'uk-margin-xsmall-left'">Transfer</span>
</a>
<!-- This is the modal --> <!-- This is the modal -->
<fs-modal #egiTransferModal classBody="uk-container-xlarge" [okButtonDisabled]="destinationPath.length == 0 || status == 'succeeded' <modal-alert #egiTransferModal classBody="uk-container-xlarge" large="true"
|| (requests > 0) || !validatePath() || !validateDestinationUrl() || (!this.downloadElements || this.downloadElements.length == 0)" [okDisabled]="!privacyAccepted || destinationPath.length == 0 || status == 'succeeded' || (requests > 0)
(okEmitter)="transfer()" (cancelEmitter)="init()"> || !validatePath() || !validateDestinationUrl() || (!this.downloadElements || this.downloadElements.length == 0)"
<div *ngIf="!accessToken" class=""> (alertOutput)="transfer()" (cancelOutput)="init()">
<div class="uk-width-1-1 uk-margin-bottom uk-text-center"> <ng-container *ngTemplateOutlet="modalContents;"></ng-container>
In order to send data to a Cloud Storage, you would need to be authenticated, please login via EGI check-in. </modal-alert>
<!-- [okButtonDisabled]="!privacyAccepted || destinationPath.length == 0 || status == 'succeeded' || (requests > 0)-->
<!-- || !validatePath() || !validateDestinationUrl() || (!this.downloadElements || this.downloadElements.length == 0)"-->
<!-- (okEmitter)="transfer()" (cancelEmitter)="init()"-->
<fs-modal #egiTransferFsModal classTitle="uk-tile-default uk-border-bottom" classBody="uk-container-xlarge"
(cancelEmitter)="init()">
<ng-container *ngTemplateOutlet="modalContents;"></ng-container>
</fs-modal>
<ng-template #modalContents>
<div *ngIf="!accessToken" class="">
<div class="uk-width-1-1 uk-margin-bottom uk-text-center">
In order to send data to a Cloud Storage, you would need to be authenticated, please login via EGI check-in.
</div>
<div class="uk-text-center">
<button *ngIf="!accessToken" class="uk-button uk-button-default" (click)="checkin()">Login
</button>
</div>
</div>
<div *ngIf="accessToken" class="">
<div class="uk-width-1-1 uk-margin-bottom uk-text-center">
You have requested to send the data corresponding to the DOI <a [href]="selectedSourceUrl" target="_blank">{{selectedSourceUrl.split(doiPrefix)[1]}}</a> to a cloud storage using the EOSC Data Transfer service
</div>
<div class="uk-grid uk-grid-small uk-child-width-1-2@m uk-grid-divider">
<!-- Source -->
<div class="uk-first-column source">
<p class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom uk-margin-top">Available DOI URLs:</p>
<div input type="select" [(value)]="selectedSourceUrl" hint="Select..." [inputClass]="'flat'"
[options]="sourceUrls" (valueChange)="this.parse()"></div>
<div *ngIf="status!='active'" class="uk-margin-top">
<div>{{this.downloadElements.length}} files found:</div>
<div class="uk-margin-small-top uk-height-max-medium uk-overflow-auto">
<ul>
<li *ngFor=" let element of this.downloadElements">{{ element.name}}
</li>
</ul>
</div>
<div *ngIf="!this.downloadElements || this.downloadElements.length == 0"> - </div>
</div>
</div> </div>
<div class="uk-text-center"> <!-- Destination -->
<button *ngIf="!accessToken" class="uk-button uk-button-default" (click)="checkin()">Login <div *ngIf="destinationOptions" class="destination" [class.uk-margin-top]="isMobile">
</button> <!-- -->
<!-- Testing:<br>-->
<!-- https://dcache-demo.desy.de:2443-->
<!-- <br>-->
<!-- /Demonstrators/EOSC-Future/EGI/-->
<!-- <br>-->
<!-- -->
<p class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom uk-margin-top">Destination storage type:</p>
<div input type="select" [(value)]="selectedDestination" hint="Select..." [inputClass]="'flat'"
[options]="destinationOptions" (valueChange)="folders = {}"></div>
<p class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom uk-margin-top">Destination system (e.g. hostname:8080):</p>
<div input [(value)]="destinationUrl" [inputClass]="'flat'"
[validators]="URLValidators" class=""></div>
<ng-container
*ngIf="selectedDestination.authType == 'password' || selectedDestination.authType == 'keys'">
<p class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom uk-margin-top">Authentication:</p>
<div class="uk-grid uk-child-width-1-2">
<div input [(value)]="destinationAuthUser" [placeholder]="'Give ' + (selectedDestination.authType ==
'password'? 'username':'access key') " [inputClass]="'flat x-small'"
class=""></div>
<div input password=true [(value)]="destinationAuthPass" [placeholder]="'Give ' + (selectedDestination.authType ==
'password'? 'password':'secret key') " [inputClass]="'flat x-small'"
class=""></div>
</div>
<!-- <div class="uk-text-xsmall">You can check our data protection policy <a class="custom-external" href="https://www.openaire.eu/data-protection-policy" target="_blank">here</a>.</div>-->
</ng-container>
<p class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom uk-margin-top">Destination path (e.g. /folder1/folder2):</p>
<div #destinationPathInput input [(value)]="destinationPath" [inputClass]="'flat'"
[validators]="pathValidators" class=""></div>
<!-- <div *ngIf="selectedDestination.hasBrowse">-->
<p *ngIf="selectedDestination.canBrowse" class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom"> or <a
[ngClass]="!validateDestinationUrl() ? 'uk-text-muted uk-disabled' : 'uk-text-primary'" [attr.disabled]="!destinationUrl"
(click)="browseFolder('/')">browse</a> to
select a folder.</p>
<div *ngIf="folders['/']" class="uk-height-max-medium uk-overflow-auto">
<ng-container *ngTemplateOutlet="folderListTmpl; context: { folder : folders['/'], folderPath: '/'}"></ng-container>
</div>
<!-- </div>-->
<ng-container *ngIf="selectedDestination.destination == 'ftp'">
<p>Comming soon!</p>
</ng-container>
<div class="uk-margin-top">
<!-- (ngModelChange)="filterChange(value.selected)"-->
<input type="checkbox" class="uk-checkbox"
[(ngModel)]="privacyAccepted"/>
<span class="uk-margin-small-left uk-text-small">*I have read and accepted the data protection policy <a class="custom-external" href="https://www.openaire.eu/data-protection-policy" target="_blank">here</a>.</span>
</div>
<div *ngIf="isMobile" class="uk-align-right uk-margin-medium-top uk-margin-bottom">
<button class="uk-button uk-button-primary"
[disabled]="!privacyAccepted || destinationPath.length == 0 || status == 'succeeded'
|| (requests > 0) || !destinationPathInput.formControl.valid || !validateDestinationUrl() || (!this.downloadElements || this.downloadElements.length == 0)"
[class.uk-disabled]="!privacyAccepted || destinationPath.length == 0 || status == 'succeeded'
|| (requests > 0) || !destinationPathInput.formControl.valid || !validateDestinationUrl() || (!this.downloadElements || this.downloadElements.length == 0)"
(click)="transfer()">
>> Transfer
</button>
</div>
</div> </div>
</div> </div>
<div *ngIf="accessToken" class=""> <!-- [class.uk-alert-success]="status && status.indexOf('error')==-1"-->
<div class="uk-width-1-1 uk-margin-bottom uk-text-center"> <!-- [class.uk-alert-error]="status && status.indexOf('error')!=-1">-->
You have requested to send the data corresponding to the DOI <a [href]="selectedSourceUrl" target="_blank">{{selectedSourceUrl.split(doiPrefix)[1]}}</a> to a cloud storage using the EOSC Data Transfer service <div id="transferAlert" *ngIf="message" class="uk-width-1-1 uk-alert uk-margin-medium-top" [ngClass]="'uk-alert-'+statusMessage" uk-alert>
</div> <div [innerHTML]="message"></div>
<div class="uk-grid uk-grid-small uk-child-width-1-2 uk-grid-divider"> <!-- <a *ngIf="status != 'succeeded' && status != 'active'" (click)="transfer()">-->
<!-- Source --> <!-- Try again!-->
<div class="uk-first-column source"> <!-- </a>-->
<p class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom uk-margin-top">Available DOI URLs:</p> <div *ngIf="requests > 0" class="uk-flex uk-flex-center uk-text-muted">
<div input type="select" [(value)]="selectedSourceUrl" hint="Select..." [inputClass]="'flat'" <div>
[options]="sourceUrls" (valueChange)="this.parse()"></div>
<div *ngIf="status!='active'" class="uk-margin-top">
<div>{{this.downloadElements.length}} files found:</div>
<div class="uk-margin-small-top uk-height-max-medium uk-overflow-auto">
<ul>
<li *ngFor=" let element of this.downloadElements">{{ element.name}}
</li>
</ul>
</div>
<div *ngIf="!this.downloadElements || this.downloadElements.length == 0"> - </div>
</div>
</div>
<!-- Destination -->
<div *ngIf="destinationOptions" class="destination">
<!-- -->
<!-- Testing:<br>-->
<!-- https://dcache-demo.desy.de:2443-->
<!-- <br>-->
<!-- /Demonstrators/EOSC-Future/EGI/-->
<!-- <br>-->
<!-- -->
<p class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom uk-margin-top">Destination storage type:</p>
<div input type="select" [(value)]="selectedDestination" hint="Select..." [inputClass]="'flat'"
[options]="destinationOptions" (valueChange)="folders = {}"></div>
<p class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom uk-margin-top">Destination system (e.g. hostname:8080):</p>
<div input [(value)]="destinationUrl" [inputClass]="'flat'"
[validators]="URLValidators" class=""></div>
<ng-container
*ngIf="selectedDestination.authType == 'password' || selectedDestination.authType == 'keys'">
<p class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom uk-margin-top">Authentication:</p>
<div class="uk-grid uk-child-width-1-2">
<div input [(value)]="destinationAuthUser" [placeholder]="'Give ' + (selectedDestination.authType ==
'password'? 'username':'access key') " [inputClass]="'flat x-small'"
class=""></div>
<div input password=true [(value)]="destinationAuthPass" [placeholder]="'Give ' + (selectedDestination.authType ==
'password'? 'password':'secret key') " [inputClass]="'flat x-small'"
class=""></div>
</div>
<!-- <div class="uk-text-xsmall">You can check our data protection policy <a class="custom-external" href="https://www.openaire.eu/data-protection-policy" target="_blank">here</a>.</div>-->
</ng-container>
<p class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom uk-margin-top">Destination path (e.g. /folder1/folder2):</p>
<div input [(value)]="destinationPath" [inputClass]="'flat'"
[validators]="pathValidators" class=""></div>
<!-- <div *ngIf="selectedDestination.hasBrowse">-->
<p *ngIf="selectedDestination.canBrowse" class="uk-text-meta uk-text-xsmall uk-margin-remove-bottom"> or <a
[ngClass]="!validateDestinationUrl() ? 'uk-text-muted uk-disabled' : 'uk-text-primary'" [attr.disabled]="!destinationUrl"
(click)="browseFolder('/')">browse</a> to
select a folder.</p>
<div *ngIf="folders['/']" class="uk-height-max-medium uk-overflow-auto">
<ng-container *ngTemplateOutlet="folderListTmpl; context: { folder : folders['/'], folderPath: '/'}"></ng-container>
</div>
<!-- </div>-->
<ng-container *ngIf="selectedDestination.destination == 'ftp'">
<p>Comming soon!</p>
</ng-container>
<div class="uk-margin-top">
<!-- (ngModelChange)="filterChange(value.selected)"-->
<input type="checkbox" class="uk-checkbox"
[(ngModel)]="privacyAccepted"/>
<span class="uk-margin-small-left uk-text-small">*I have read and accepted the data protection policy <a class="custom-external" href="https://www.openaire.eu/data-protection-policy" target="_blank">here</a>.</span>
</div>
<div class="uk-align-right uk-margin-medium-top uk-margin-bottom">
<button class="uk-button uk-button-primary"
[disabled]="!privacyAccepted || destinationPath.length == 0 || status == 'succeeded'
|| (requests > 0) || !validatePath() || !validateDestinationUrl() || (!this.downloadElements || this.downloadElements.length == 0)"
[class.uk-disabled]="!privacyAccepted || destinationPath.length == 0 || status == 'succeeded'
|| (requests > 0) || !validatePath() || !validateDestinationUrl() || (!this.downloadElements || this.downloadElements.length == 0)"
(click)="transfer()">
>> Transfer
</button>
</div>
</div>
</div>
<!-- [class.uk-alert-success]="status && status.indexOf('error')==-1"-->
<!-- [class.uk-alert-error]="status && status.indexOf('error')!=-1">-->
<div id="transferAlert" *ngIf="message" class="uk-width-1-1 uk-alert uk-margin-medium-top" [ngClass]="'uk-alert-'+statusMessage" uk-alert>
<div [innerHTML]="message"></div>
<!-- <a *ngIf="status != 'succeeded' && status != 'active'" (click)="transfer()">-->
<!-- Try again!-->
<!-- </a>-->
<div *ngIf="requests > 0" class="uk-flex uk-flex-center uk-text-muted">
<div>
<span class="uk-icon uk-spinner"> <span class="uk-icon uk-spinner">
<svg width="60" height="60" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" <svg width="60" height="60" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"
data-svg="spinner"><circle data-svg="spinner"><circle
fill="none" stroke="#000" cx="15" cy="15" r="14" style="stroke-width: 2px;"></circle></svg> fill="none" stroke="#000" cx="15" cy="15" r="14" style="stroke-width: 2px;"></circle></svg>
</span> </span>
</div>
</div> </div>
<a *ngIf="requests <= 0" class="uk-alert-close" uk-close></a>
</div> </div>
<!-- <div *ngIf="jobId || status == 'canceled'"> <a *ngIf="requests <= 0" class="uk-alert-close" uk-close></a>
<button *ngIf=" status != 'canceled'" class="uk-button uk-button-default" (click)="getStatus()">Check status</button> </div>
<button *ngIf=" status != 'canceled'" class="uk-button uk-button-default" (click)="cancel()">Cancel</button> <!-- <div *ngIf="jobId || status == 'canceled'">
<div>{{statusMessage}}</div> <button *ngIf=" status != 'canceled'" class="uk-button uk-button-default" (click)="getStatus()">Check status</button>
</div>--> <button *ngIf=" status != 'canceled'" class="uk-button uk-button-default" (click)="cancel()">Cancel</button>
<!-- <div *ngIf=" status != 'canceled'" class="uk-width-1-1 uk-text-right "--> <div>{{statusMessage}}</div>
<!-- [class.uk-invisible]="!(status == 'succeeded' || status.indexOf('error')!=-1)">--> </div>-->
<!-- <button class="uk-button uk-button-default uk-margin-top " (click)="close()">Close</button>--> <!-- <div *ngIf=" status != 'canceled'" class="uk-width-1-1 uk-text-right "-->
<!-- </div>--> <!-- [class.uk-invisible]="!(status == 'succeeded' || status.indexOf('error')!=-1)">-->
<!-- <button class="uk-button uk-button-default uk-margin-top " (click)="close()">Close</button>-->
<!-- TESTS --> <!-- </div>-->
<!-- TESTS -->
<!-- <button (click)="hasBrowse()" <!-- <button (click)="hasBrowse()"
class="uk-button uk-button-primary uk-margin-top" class="uk-button uk-button-primary uk-margin-top"
> >
@ -153,9 +166,9 @@
> >
delete folder new delete folder new
</button>--> </button>-->
<!-- End of TESTS--> <!-- End of TESTS-->
</div> </div>
</fs-modal> </ng-template>
<!-- Browse Templates --> <!-- Browse Templates -->
<ng-template #folderListTmpl let-folder="folder" let-folderPath="folderPath" > <ng-template #folderListTmpl let-folder="folder" let-folderPath="folderPath" >

View File

@ -10,6 +10,7 @@ import {delay, repeat, startWith, switchMap} from "rxjs/operators";
import {StringUtils} from "../string-utils.class"; import {StringUtils} from "../string-utils.class";
import {HelperFunctions} from "../HelperFunctions.class"; import {HelperFunctions} from "../HelperFunctions.class";
import {FullScreenModalComponent} from "../modal/full-screen-modal/full-screen-modal.component"; import {FullScreenModalComponent} from "../modal/full-screen-modal/full-screen-modal.component";
import {AlertModal} from "../modal/alert";
declare var UIkit; declare var UIkit;
@Component({ @Component({
@ -35,6 +36,7 @@ declare var UIkit;
`] `]
}) })
export class EGIDataTransferComponent { export class EGIDataTransferComponent {
@Input() isMobile: boolean = false;
subscriptions = []; subscriptions = [];
statusSub: Subscription[] = []; statusSub: Subscription[] = [];
accessToken = null; accessToken = null;
@ -55,7 +57,8 @@ export class EGIDataTransferComponent {
downloadElements = null; downloadElements = null;
@Input() isOpen = false; @Input() isOpen = false;
// @Input() selectedDestinationId = "dcache"; // @Input() selectedDestinationId = "dcache";
@ViewChild('egiTransferModal') egiTransferModal: FullScreenModalComponent; @ViewChild('egiTransferModal') egiTransferModal: AlertModal;
@ViewChild('egiTransferFsModal') egiTransferFsModal: FullScreenModalComponent;
APIURL = properties.eoscDataTransferAPI; APIURL = properties.eoscDataTransferAPI;
// status: "loading" | "success" | "errorParser" | "errorUser" | "errorTransfer" | "init" | "canceled" = "init"; // status: "loading" | "success" | "errorParser" | "errorUser" | "errorTransfer" | "init" | "canceled" = "init";
status: "unused" | "staging" | "submitted" | "active" | "succeeded" | "partial" | "failed" | "canceled" | "errorParser" | "errorUser" | "init" = "init"; status: "unused" | "staging" | "submitted" | "active" | "succeeded" | "partial" | "failed" | "canceled" | "errorParser" | "errorUser" | "init" = "init";
@ -146,20 +149,37 @@ export class EGIDataTransferComponent {
this.parse(); this.parse();
} }
this.isOpen = true; this.isOpen = true;
this.egiTransferModal.back = true;
this.egiTransferModal.cancelButton = false;
this.egiTransferModal.okButton = false;
this.egiTransferModal.okButtonText = ">> Transfer";
this.egiTransferModal.title = "EOSC Data Transfer";
this.init(); this.init();
if(typeof document !== 'undefined') {
this.egiTransferModal.open(); if(!this.isMobile) {
this.egiTransferModal.stayOpen = true;
// this.egiTransferModal.back = true;
this.egiTransferModal.cancelButton = false;
this.egiTransferModal.okButton = true;
this.egiTransferModal.okButtonText = ">> Transfer";
this.egiTransferModal.alertTitle = "EOSC Data Transfer";
if(typeof document !== 'undefined') {
this.egiTransferModal.open();
}
} else {
this.egiTransferFsModal.back = false;
this.egiTransferFsModal.cancelButton = true;
this.egiTransferFsModal.okButton = false;
// this.egiTransferFsModal.okButtonText = ">> Transfer";
this.egiTransferFsModal.title = "EOSC Data Transfer";
if(typeof document !== 'undefined') {
this.egiTransferFsModal.open();
}
} }
} }
close(){ close(){
if(this.isOpen) { if(this.isOpen) {
this.isOpen = false; this.isOpen = false;
this.egiTransferModal.cancel(); if(!this.isMobile) {
this.egiTransferModal.cancel();
} else {
this.egiTransferFsModal.cancel();
}
} }
// this.downloadElements = []; // this.downloadElements = [];
this.init(); this.init();
@ -235,7 +255,7 @@ export class EGIDataTransferComponent {
"files": [], "files": [],
"params": { "params": {
"priority": 0, "priority": 0,
"overwrite": true, "overwrite": false,
"retry": 3 "retry": 3
} }
}; };
@ -541,8 +561,9 @@ export class EGIDataTransferComponent {
} }
} }
validatePath():boolean { validatePath():boolean {
let exp1 = /^\/([A-z0-9-_+]+\/?)*$/g; // let exp1 = /^\/([A-z0-9-_+]+\/?)*$/g;
return (this.destinationPath.length > 0 && this.destinationPath.match(exp1) != null) // let exp1 = /^\/([A-z0-9-_]+[+\/]?)*$/;
return (this.destinationPath.length > 0 && this.destinationPath.startsWith("/"))
} }

View File

@ -1,23 +1,32 @@
import {Component, ElementRef, Input, ViewChild} from "@angular/core"; import {Component, ElementRef, Input, ViewChild} from "@angular/core";
import {MobileDropdownComponent} from "../mobile-dropdown/mobile-dropdown.component";
declare var UIkit; declare var UIkit;
@Component({ @Component({
selector: 'dropdown-filter', selector: 'dropdown-filter',
template: ` template: `
<button class="uk-button uk-button-default uk-flex uk-flex-middle" <button #toggle class="uk-button uk-button-default uk-flex uk-flex-middle"
[class.uk-disabled]="disabled" [disabled]="disabled"> [class.uk-disabled]="disabled" [disabled]="disabled">
<span>{{name}}<span *ngIf="count > 0">({{count}})</span></span> <span>{{name}}<span *ngIf="count > 0">({{count}})</span></span>
<icon [flex]="true" class="uk-margin-xsmall-left" [name]="'expand_' + (isOpen?'less':'more')"></icon> <icon [flex]="true" class="uk-margin-xsmall-left" [name]="'expand_' + (isOpen?'less':'more')"></icon>
</button> </button>
<div #dropdownElement class="uk-dropdown" <div *ngIf="!isMobile" #dropdownElement class="uk-dropdown"
[class.uk-height-max-large]="overflow" [class.uk-overflow-auto]="overflow" [class.uk-height-max-large]="overflow" [class.uk-overflow-auto]="overflow"
[ngStyle]="dropdownMinWidth?{'min-width.px': dropdownMinWidth}:''" [ngStyle]="dropdownMinWidth?{'min-width.px': dropdownMinWidth}:''"
[ngClass]="dropdownClass" uk-dropdown="mode: click; delay-hide: 0;"> [ngClass]="dropdownClass" uk-dropdown="mode: click; delay-hide: 0;">
<div> <div>
<ng-content></ng-content> <ng-container *ngTemplateOutlet="content"></ng-container>
</div> </div>
</div> </div>
<mobile-dropdown *ngIf="isMobile" #mobileDropdown [toggle]="toggle">
<div [ngClass]="dropdownClass">
<ng-container *ngTemplateOutlet="content"></ng-container>
</div>
</mobile-dropdown>
<ng-template #content>
<ng-content></ng-content>
</ng-template>
` `
}) })
export class DropdownFilterComponent { export class DropdownFilterComponent {
@ -33,13 +42,24 @@ export class DropdownFilterComponent {
public overflow: boolean = true; public overflow: boolean = true;
@Input() @Input()
public disabled = false; public disabled = false;
@Input()
public isMobile: boolean = false;
@ViewChild("dropdownElement") dropdownElement: ElementRef; @ViewChild("dropdownElement") dropdownElement: ElementRef;
@ViewChild("mobileDropdown") mobileDropdown: MobileDropdownComponent;
get isOpen() { get isOpen() {
return (typeof document !== 'undefined') && this.dropdownElement && UIkit.dropdown(this.dropdownElement.nativeElement).isActive(); if(this.isMobile) {
return this.mobileDropdown?.opened;
} else {
return (typeof document !== 'undefined') && this.dropdownElement && UIkit.dropdown(this.dropdownElement.nativeElement).isActive();
}
} }
closeDropdown() { closeDropdown() {
UIkit.dropdown(this.dropdownElement.nativeElement).hide(); if(this.isMobile) {
this.mobileDropdown.close();
} else {
UIkit.dropdown(this.dropdownElement.nativeElement).hide();
}
} }
} }

View File

@ -2,9 +2,10 @@ import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common"; import {CommonModule} from "@angular/common";
import {DropdownFilterComponent} from "./dropdown-filter.component"; import {DropdownFilterComponent} from "./dropdown-filter.component";
import {IconsModule} from "../icons/icons.module"; import {IconsModule} from "../icons/icons.module";
import {MobileDropdownModule} from "../mobile-dropdown/mobile-dropdown.module";
@NgModule({ @NgModule({
imports: [CommonModule, IconsModule], imports: [CommonModule, IconsModule, MobileDropdownModule],
declarations: [DropdownFilterComponent], declarations: [DropdownFilterComponent],
exports: [DropdownFilterComponent] exports: [DropdownFilterComponent]
}) })

View File

@ -186,9 +186,10 @@ export class Portal {
}; };
}; };
public static getMockCommunityInfo(pid: string, disabledEntities:string[],disabledPages:string[]): any { public static getMockCommunityInfo(pid: string, name:string, disabledEntities:string[],disabledPages:string[]): any {
let communityInfo = Object.assign({}, Portal.getmockPortalInfo()); let communityInfo = Object.assign({}, Portal.getmockPortalInfo());
communityInfo.pid = pid; communityInfo.pid = pid;
communityInfo.name = name;
for(let disabledPage of disabledPages) { for(let disabledPage of disabledPages) {
for (var i = 0; i < communityInfo.pages.length; i++) { for (var i = 0; i < communityInfo.pages.length; i++) {
if (communityInfo.pages[i].route == disabledPage) { if (communityInfo.pages[i].route == disabledPage) {

View File

@ -8,7 +8,7 @@ import {
} from "../result-preview/result-preview"; } from "../result-preview/result-preview";
export interface Id { export interface Id {
type: "pmid" | "doi" | "pmc" | "handle" | "openaire"; type: "pmid" | "doi" | "pmc" | "handle" | "openaire" | "swhid";
value: string; value: string;
trust: number trust: number
} }

View File

@ -23,6 +23,8 @@ import {EnvProperties} from "../properties/env-properties";
</div> </div>
<div *ngIf="share"> <div *ngIf="share">
<a (click)="openAddThisModal()" <a (click)="openAddThisModal()"
[title]="'Share this '+getTypeName() + ' in your social networks'"
[attr.uk-tooltip]="'pos: right; cls: uk-active uk-text-small uk-padding-small'"
class="uk-flex uk-flex-middle uk-button-link uk-text-bolder" [ngClass]="isMobile ? 'uk-margin-left uk-margin-xsmall-bottom' : 'uk-flex-center'"> class="uk-flex uk-flex-middle uk-button-link uk-text-bolder" [ngClass]="isMobile ? 'uk-margin-left uk-margin-xsmall-bottom' : 'uk-flex-center'">
<icon [flex]="true" [ratio]="0.8" name="share" visuallyHidden="share"></icon> <icon [flex]="true" [ratio]="0.8" name="share" visuallyHidden="share"></icon>
<span class="uk-margin-xsmall-left">Share</span> <span class="uk-margin-xsmall-left">Share</span>
@ -101,7 +103,6 @@ export class EntityActionsComponent implements OnInit {
public routerHelper: RouterHelper = new RouterHelper(); public routerHelper: RouterHelper = new RouterHelper();
@ViewChild('citeModal') citeModal; @ViewChild('citeModal') citeModal;
@ViewChild('embedResultsModal') embedResultsModal; @ViewChild('embedResultsModal') embedResultsModal;
@ViewChild('downloadReportModal') downloadReportModal;
@ViewChild('addThisModal') addThisModal; @ViewChild('addThisModal') addThisModal;
properties: EnvProperties = properties; properties: EnvProperties = properties;
openaireEntities = OpenaireEntities; openaireEntities = OpenaireEntities;

View File

@ -1,10 +1,11 @@
import {Component, Input, OnInit} from "@angular/core"; import {Component, ElementRef, EventEmitter, Input, OnInit, Output} from "@angular/core";
import {NavigationStart, Router} from "@angular/router";
@Component({ @Component({
selector: 'mobile-dropdown', selector: 'mobile-dropdown',
template: ` template: `
<div class="uk-dropdown-mobile" [class.uk-open]="opened"> <div class="uk-dropdown-mobile" [class.uk-open]="opened" (click)="close()">
<div class="uk-dropdown-mobile-container"> <div class="uk-dropdown-mobile-container" (click)="$event.stopPropagation()">
<a class="uk-close" (click)="close()"> <a class="uk-close" (click)="close()">
<icon name="close" [ratio]="1.2"></icon> <icon name="close" [ratio]="1.2"></icon>
</a> </a>
@ -15,22 +16,55 @@ import {Component, Input, OnInit} from "@angular/core";
</div>` </div>`
}) })
export class MobileDropdownComponent implements OnInit{ export class MobileDropdownComponent implements OnInit{
@Input() toggle: HTMLLinkElement; @Input() toggle: HTMLAnchorElement | HTMLButtonElement;
@Output() onClose: EventEmitter<void> = new EventEmitter;
public opened: boolean = false; public opened: boolean = false;
private static MOBILE_DROPDOWN_CONTAINER = 'mobile-dropdown-container';
constructor(private element: ElementRef, private router: Router) {
this.router.events.subscribe(event => {
if(event instanceof NavigationStart) {
this.element.nativeElement.remove();
}
});
}
ngOnInit() { ngOnInit() {
if(this.toggle) { if(this.toggle) {
this.toggle.onclick = (ev) => { this.toggle.onclick = (ev) => {
this.opened = !this.opened; ev.preventDefault();
ev.stopPropagation();
if(this.opened) {
this.close();
} else {
this.open();
}
} }
} }
} }
open() { open() {
this.opened = true; if(!this.opened) {
let body = document.getElementsByTagName('body')[0];
let container = document.getElementById(MobileDropdownComponent.MOBILE_DROPDOWN_CONTAINER);
if(!container) {
container = document.createElement('div');
container.setAttribute('id', MobileDropdownComponent.MOBILE_DROPDOWN_CONTAINER);
body.append(container);
}
let parent = this.element.nativeElement.parentElement;
parent.removeChild(this.element.nativeElement);
container.append(this.element.nativeElement);
this.opened = true;
body.setAttribute('style', 'overflow-y: hidden');
}
} }
close() { close() {
this.opened = false; if(this.opened) {
this.opened = false;
this.onClose.emit();
document.getElementsByTagName('body')[0].setAttribute('style', '');
}
} }
} }

View File

@ -19,10 +19,10 @@ declare var UIkit: any;
<div class="uk-modal-dialog"> <div class="uk-modal-dialog">
<div class="uk-modal-header uk-flex uk-flex-middle uk-flex-between" [ngClass]="classTitle"> <div class="uk-modal-header uk-flex uk-flex-middle uk-flex-between" [ngClass]="classTitle">
<div [class.uk-invisible]="!alertHeader"> <div [class.uk-invisible]="!alertHeader">
<h5 class="uk-margin-remove">{{alertTitle}}</h5> <h6 class="uk-margin-remove">{{alertTitle}}</h6>
</div> </div>
<button class="uk-close uk-icon uk-margin-left" (click)="cancel()"> <button class="uk-close uk-icon uk-margin-left" (click)="cancel()">
<icon name="close" ratio="1.5"></icon> <icon name="close" ratio="1.4"></icon>
</button> </button>
</div> </div>
<div #bodyElement class="uk-modal-body uk-animation-fast uk-text-left" <div #bodyElement class="uk-modal-body uk-animation-fast uk-text-left"
@ -205,6 +205,9 @@ export class AlertModal implements OnInit, AfterViewInit, OnDestroy {
open() { open() {
if(typeof UIkit !== "undefined") { if(typeof UIkit !== "undefined") {
UIkit.modal(this.element.nativeElement).show(); UIkit.modal(this.element.nativeElement).show();
if(this.overflowBody) {
this.bodyElement.nativeElement.scrollTo(0, 0);
}
} }
} }

View File

@ -25,12 +25,12 @@ declare var ResizeObserver;
<div #header class="uk-modal-header uk-flex uk-flex-middle" [ngClass]="classTitle"> <div #header class="uk-modal-header uk-flex uk-flex-middle" [ngClass]="classTitle">
<div [class.uk-invisible]="!back" class="uk-width-medium@l uk-width-auto uk-flex uk-flex-center"> <div [class.uk-invisible]="!back" class="uk-width-medium@l uk-width-auto uk-flex uk-flex-center">
<button class="uk-button uk-button-link" [class.uk-disabled]="!back" [disabled]="!back" (click)="backClicked()"> <button class="uk-button uk-button-link" [class.uk-disabled]="!back" [disabled]="!back" (click)="backClicked()">
<icon name="west" [flex]="true" [ratio]="isMobile?2:3"></icon> <icon name="west" [flex]="true" [ratio]="isMobile?1.4:2"></icon>
</button> </button>
</div> </div>
<div [class.uk-invisible]="!title" <div [class.uk-invisible]="!title"
class="uk-width-expand uk-padding-small uk-padding-remove-vertical uk-flex uk-flex-center"> class="uk-width-expand uk-padding-small uk-padding-remove-vertical uk-flex uk-flex-center">
<h4 *ngIf="isMobile" class="uk-margin-remove">{{title}}</h4> <h6 *ngIf="isMobile" class="uk-margin-remove">{{title}}</h6>
<h2 *ngIf="!isMobile" class="uk-margin-remove">{{title}}</h2> <h2 *ngIf="!isMobile" class="uk-margin-remove">{{title}}</h2>
</div> </div>
<div class="uk-width-medium@l uk-width-auto uk-flex" <div class="uk-width-medium@l uk-width-auto uk-flex"
@ -40,7 +40,7 @@ declare var ResizeObserver;
{{okButtonText}} {{okButtonText}}
</button> </button>
<button *ngIf="!okButton && cancelButton" class="uk-close uk-icon" (click)="cancel()"> <button *ngIf="!okButton && cancelButton" class="uk-close uk-icon" (click)="cancel()">
<icon name="close" ratio="2"></icon> <icon name="close" [ratio]="1.4"></icon>
</button> </button>
</div> </div>
</div> </div>
@ -142,7 +142,7 @@ export class FullScreenModalComponent implements AfterViewInit, OnDestroy {
open() { open() {
UIkit.modal(this.modal.nativeElement).show(); UIkit.modal(this.modal.nativeElement).show();
HelperFunctions.scroll(); this.body.nativeElement.scrollTo(0, 0);
} }
cancel() { cancel() {

View File

@ -13,66 +13,25 @@ declare var UIkit: any;
@Component({ @Component({
selector: 'modal-loading', selector: 'modal-loading',
template: ` template: `
<!-- uk-modal="center:true"--> <div #loading_element [class.uk-modal]="!isMobile" [class.uk-modal-full]="isMobile" [id]="id" uk-modal="container: #modal-container; bg-close:false; ">
<!-- <div [class]="(!isOpen)?'uk-modal ':'uk-modal uk-open uk-animation-fade'" [open]="!isOpen" uk-modal tabindex="-1" role="dialog" >--> <div class="uk-modal-dialog">
<div *ngIf="!isMobile" #loading_element class="uk-modal" [id]="id" uk-modal="container: #modal-container"> <div *ngIf="isMobile" #header class="uk-modal-header uk-flex uk-flex-middle" [ngClass]="classTitle">
<div class="uk-modal-dialog" role=""> <div [class.uk-invisible]="!title"
<!--div class="modal-content"--> class="uk-width-expand uk-padding-small uk-padding-remove-vertical uk-flex uk-flex-center">
<h4 class="uk-margin-remove">{{title}}</h4>
<div class="uk-modal-body"> </div>
<div > </div>
<div #body class="uk-modal-body" [class.uk-overflow-auto]="isMobile">
<div [class.uk-container]="isMobile" [class.uk-height-1-1]="isMobile">
<h4 class="text-center" >{{message}}</h4> <h4 class="text-center" >{{message}}</h4>
<!-- <div class="uk-spinner"></div>-->
<loading></loading> <loading></loading>
<ng-content></ng-content> <ng-content></ng-content>
</div> </div>
</div> </div>
</div> </div>
<!--/div-->
</div> </div>
`,
<div *ngIf="isMobile" #loading_element class="uk-modal-full" [id]="id" uk-modal="container: #modal-container">
<div class="uk-modal-dialog">
<div #header class="uk-modal-header uk-flex uk-flex-middle" [ngClass]="classTitle">
<div [class.uk-invisible]="!title"
class="uk-width-expand uk-padding-small uk-padding-remove-vertical uk-flex uk-flex-center">
<h4 class="uk-margin-remove">{{title}}</h4>
</div>
</div>
<div #body class="uk-modal-body uk-overflow-auto">
<div class="uk-container uk-height-1-1">
<h4 class="text-center">{{message}}</h4>
<loading></loading>
<ng-content></ng-content>
</div>
</div>
</div>
</div>
<!-- <div #element [class]="(!isOpen)?'uk-modal ':'uk-modal uk-animation-fade uk-open'" [open]="!isOpen" uk-modal="container: #modal-container">-->
<!-- <div class="uk-modal-dialog">-->
<!-- <div class="uk-modal-body uk-animation-fast uk-text-left">-->
<!-- <h4 class="text-center" >{{message}}</h4>-->
<!-- <div class="uk-animation-fade uk-margin-top uk-width-1-1" role="alert">-->
<!-- <span class="loading-gif uk-align-center" ></span>-->
<!-- </div>-->
<!-- <ng-content></ng-content>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!--div class="uk-modal uk-open" aria-hidden="false" style="display: block; overflow-y: scroll;">
<div class="uk-modal-dialog" tabindex="">
<div class="uk-modal-spinner"></div>
</div>
</div-->
`,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
}) })
/** /**

View File

@ -44,6 +44,7 @@ export interface EnvProperties {
cordisURL?: string; cordisURL?: string;
openDoarURL?: string; openDoarURL?: string;
r3DataURL?: string; r3DataURL?: string;
swhURL?: string;
fairSharingURL?: string, fairSharingURL?: string,
eoscMarketplaceURL?: string, eoscMarketplaceURL?: string,
sherpaURL?: string; sherpaURL?: string;

View File

@ -14,7 +14,7 @@ export class SearchFields {
// Remove Collected From Filter "collectedfrom","collectedfrom" // Remove Collected From Filter "collectedfrom","collectedfrom"
public RESULT_REFINE_FIELDS = [ public RESULT_REFINE_FIELDS = [
"resultbestaccessright", "instancetypename", (properties.environment !== 'production' ? "foslabel" : "fos"), "relfunder", "resultbestaccessright", "instancetypename", properties.environment!='production'?"foslabel":'fos', "relfunder",
"relfundinglevel0_id", "relfundinglevel1_id", "relfundinglevel2_id", "relfundinglevel0_id", "relfundinglevel1_id", "relfundinglevel2_id",
"relproject", "sdg", "country", "resultlanguagename", "resulthostingdatasource", "community"]; "relproject", "sdg", "country", "resultlanguagename", "resulthostingdatasource", "community"];

View File

@ -123,7 +123,7 @@
</div> </div>
<!-- Authors --> <!-- Authors -->
<div *ngIf="result.authors" class="uk-margin-xsmall-bottom"> <div *ngIf="result.authors" class="uk-margin-xsmall-bottom">
<showAuthors [authors]="result.authors" [authorsLimit]=4 [modal]="modal" <showAuthors [authors]="result.authors" [authorsLimit]=4 [modal]="modal" [isMobile]="isMobile"
[showAll]=true [showInline]="showInline"></showAuthors> [showAll]=true [showInline]="showInline"></showAuthors>
</div> </div>
<!-- Identifiers --> <!-- Identifiers -->
@ -214,7 +214,8 @@
<a class="uk-flex uk-flex-middle uk-link-reset"> <a class="uk-flex uk-flex-middle uk-link-reset">
<icon customClass="bip-icon-hover" [flex]="true" [ratio]="0.7" <icon customClass="bip-icon-hover" [flex]="true" [ratio]="0.7"
[name]="result.measure.bip[0].icon"></icon> [name]="result.measure.bip[0].icon"></icon>
<span class="uk-margin-xsmall-left">{{result.measure.bip[0].value}}</span> <span *ngIf="isNumber(result.measure.bip[0].value)" class="uk-margin-xsmall-left">{{formatNumber(result.measure.bip[0].value)}}</span>
<span *ngIf="!isNumber(result.measure.bip[0].value)" class="uk-margin-xsmall-left">{{result.measure.bip[0].value}}</span>
</a> </a>
<div uk-drop="pos: top-right" class="uk-card uk-card-default uk-border uk-box-no-shadow uk-padding-small"> <div uk-drop="pos: top-right" class="uk-card uk-card-default uk-border uk-box-no-shadow uk-padding-small">
<table> <table>
@ -223,7 +224,8 @@
<icon [flex]="true" [ratio]="0.7" [name]="metric.icon"></icon> <icon [flex]="true" [ratio]="0.7" [name]="metric.icon"></icon>
</td> </td>
<td class="uk-text-capitalize">{{metric.name}}</td> <td class="uk-text-capitalize">{{metric.name}}</td>
<td class="uk-text-bolder">{{metric.value}}</td> <td *ngIf="isNumber(metric.value)" class="uk-text-bolder">{{metric.value | number}}</td>
<td *ngIf="!isNumber(metric.value)" class="uk-text-bolder">{{metric.value}}</td>
</tr> </tr>
</table> </table>
<div class="uk-margin-top uk-flex uk-flex-middle uk-flex-center"> <div class="uk-margin-top uk-flex uk-flex-middle uk-flex-center">
@ -252,7 +254,7 @@
<div class="uk-margin-top uk-flex uk-flex-middle uk-flex-center"> <div class="uk-margin-top uk-flex uk-flex-middle uk-flex-center">
<span class="uk-text-uppercase">Powered by </span> <span class="uk-text-uppercase">Powered by </span>
<img class="uk-margin-xsmall-left" width="15" src="assets/common-assets/logo-small-usage-counts.png" <img class="uk-margin-xsmall-left" width="15" src="assets/common-assets/logo-small-usage-counts.png"
loading="lazy" alt="BIP!"> loading="lazy" alt="Usage counts">
</div> </div>
</div> </div>
</ng-container> </ng-container>

View File

@ -223,6 +223,10 @@ export class ResultPreviewComponent implements OnInit, OnChanges {
return formatted.number + formatted.size; return formatted.number + formatted.size;
} }
public isNumber(value): boolean {
return typeof value === 'number';
}
public getAccessLabel(accessRight) : string { public getAccessLabel(accessRight) : string {
if(accessRight) { if(accessRight) {
return (accessRight + (accessRight.toLowerCase().endsWith(" access") ? "" : " access")); return (accessRight + (accessRight.toLowerCase().endsWith(" access") ? "" : " access"));

View File

@ -149,7 +149,7 @@ export class DOI {
} }
export class Identifier { export class Identifier {
class: "doi" | "pmc" | "pmid" | "handle" | "ORCID" | "re3data" = null; class: "doi" | "pmc" | "pmid" | "handle" | "ORCID" | "re3data" | "swhid" = null;
id: string; id: string;
public static getDOIsFromString(str: string): string[] { public static getDOIsFromString(str: string): string[] {
@ -202,26 +202,28 @@ export class Identifier {
return {"class": "handle", "id": pid}; return {"class": "handle", "id": pid};
} else if (Identifier.isValidRe3Data(pid)) { } else if (Identifier.isValidRe3Data(pid)) {
return {"class": "re3data", "id": pid}; return {"class": "re3data", "id": pid};
} else if (Identifier.isValidSwhId(pid)) {
return {"class": "swhid", "id": pid};
} }
//set it as a doi, to catch the case that doi has not valid format //set it as a doi, to catch the case that doi has not valid format
return (strict?null:{"class": "doi", "id": pid}); return (strict?null:{"class": "doi", "id": pid});
} }
public static getPIDFromIdentifiers(identifiers: Map<string, string[]>): Identifier { public static getPIDFromIdentifiers(identifiers: Map<string, string[]>): Identifier {
let classes:string [] = ["doi", "handle", "pmc", "pmid", "re3data"]; let classes:string [] = ["doi", "handle", "pmc", "pmid", "re3data", "swhid"];
if(identifiers) { if(identifiers) {
for (let cl of classes){ for (let cl of classes) {
if(identifiers.get(cl)){ if (identifiers.get(cl)) {
for (let pid of identifiers.get(cl)) { for (let pid of identifiers.get(cl)) {
let identifier = Identifier.getIdentifierFromString(pid); let identifier = Identifier.getIdentifierFromString(pid);
if (identifier){ if (identifier) {
return identifier; return identifier;
}
} }
} }
}
} }
return null;
} }
return null;
} }
public static isValidDOI(str: string): boolean { public static isValidDOI(str: string): boolean {
@ -257,6 +259,12 @@ export class Identifier {
let exp = /(r3d[1-9]\d{0,8})/g; let exp = /(r3d[1-9]\d{0,8})/g;
return str.match(exp) != null; return str.match(exp) != null;
} }
public static isValidSwhId(str: string): boolean {
// let exp = /swh:1:(snp|rel|rev|dir|cnt):[0-9a-f]{40}/g;
let exp = /swh:1:snp:[0-9a-f]{40}/g;
return str.match(exp) != null;
}
} }
export class StringUtils { export class StringUtils {