Merge remote-tracking branch 'origin/develop' into plugins-functionality

This commit is contained in:
Konstantinos Triantafyllou 2024-05-30 14:47:11 +03:00
commit ead1c8f903
74 changed files with 1228 additions and 630 deletions

View File

@ -1,6 +1,7 @@
//Classes used in linking / inlinelinking when selecting an entity
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {ClaimsProperties} from "./claims.properties";
export class ClaimResult {
public source: string;
@ -38,6 +39,12 @@ export class ClaimProject {
public fundingLevel0: string;
public url: string;
}
export class ClaimOrganization {
public name: string;
// public shortName: string;
public url: string;
// public country: string;
}
export class ClaimContext {
public community: string;
@ -72,6 +79,7 @@ export class ClaimEntity {
result: ClaimResult;
project: ClaimProject;
context: ClaimContext;
organization: ClaimOrganization;
constructor() {
this.warningMessages = [];
@ -117,7 +125,12 @@ export class ClaimDBContext {
title: string;
openaireId: string;
}
export class ClaimDBOrganization {
openaireId: string;
name: string;
shortName: string;
country: string;
}
export class ClaimDBProject {
openaireId: string;
name: string;
@ -177,17 +190,18 @@ export class ShowOptions {
}
initSelectOptions(){
initSelectOptions(claimProperties:ClaimsProperties){
let options =[];
if(this.linkToEntities.indexOf('result')!=-1){
options.push({value: 'result',label: OpenaireEntities.RESULTS})
}
if(this.linkToEntities.indexOf('project')!=-1){
options.push({value: 'project',label: OpenaireEntities.PROJECTS})
options.push({value: 'project',label: claimProperties.SELECT_ENTITIES.projects})
}
if(this.linkToEntities.indexOf('context')!=-1){
options.push({value: 'context',label: OpenaireEntities.COMMUNITIES})
}
this.selectOptions = options;
console.log(options, claimProperties.SELECT_ENTITIES.projects)
}
}

View File

@ -1,69 +1,25 @@
<div class="uk-width-xlarge@l uk-width-large" [ngClass]="centerAlign ? 'uk-align-center':''">
<div class="uk-width-expand" [ngClass]="centerAlign ? 'uk-align-center':''">
<advanced-search-input (searchEmitter)="search(page,size)">
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..."
[options]="showOptions.selectOptions" class="uk-width-2-5"></div>
<div class="uk-width-expand" input type="text" [(value)]="keyword" [searchable]="true" placeholder="Entities to link"
[hint]="'Search for ' + openaireEntities.PROJECTS + '...'" tooltip="true"></div>
[options]="showOptions.selectOptions" class="uk-width-medium@xl uk-width-auto"></div>
<div *ngIf="funderOptions && funderOptions.length > 0" input type="select" [(value)]="selectedFunder" placeholder="Funder" hint="Select Funder..."
[options]="funderOptions" class="uk-width-expand" (valueChange)="funderChanged($event)"></div>
<div class="uk-width-expand" input type="text" [(value)]="keyword" [searchable]="true" placeholder="Projects to link"
[hint]="'Search for ' + openaireEntities.PROJECTS + '...'" tooltip="true" [disabled]="isNoProjectFunder"></div>
</advanced-search-input>
</div>
<div *ngIf="!showResults">
<div *ngIf=" openaireResultsStatus != errorCodes.LOADING && !isNoProjectFunder && this.selectedFunder && openaireResults.length == 0">
<div class="uk-text-center uk-text-large uk-text-meta uk-margin-large-top">No {{openaireEntities.PROJECT.toLowerCase()}} results yet... <br>Start
searching for {{openaireEntities.PROJECTS.toLowerCase()}} to add them in the Basket
</div>
</div>
<div *ngIf="showResults" class="uk-margin-top">
<div *ngIf=" openaireResultsStatus != errorCodes.LOADING && this.funderOptions.length > 1 && !this.selectedFunder">
<div class="uk-text-center uk-text-large uk-text-meta uk-margin-large-top">Select funder or search for projects to proceed
</div>
</div>
<div class="uk-margin-top">
<div class="uk-grid" uk-grid>
<div class="search-filters uk-width-1-1">
<!--<div *ngIf="countFilters()>0 && openaireResultsNum > 0" class="uk-grid uk-flex uk-flex-bottom">
<div class="uk-grid">
<h6 class="uk-text-bold">Filters</h6>
<a *ngIf="countFilters()>1" (click)="clearFilters()"
[class]="((openaireResultsStatus ==
errorCodes.LOADING)?'uk-disabled uk-link-muted':'')+' portal-link '">
Clear All
</a>
</div>
<div *ngIf="countFilters()>0" class="uk-grid uk-grid-small uk-text-small uk-margin-small-top " uk-grid>
<ng-container *ngFor="let filter of rangeFilters " >
<ng-container *ngIf = "filter.selectedFromAndToValues">
<span [title]="'Remove '+ filter.selectedFromAndToValues" (click) = "removeRangeFilter(filter) " >
<span class="selectedFilterLabel ">
<a [class]="((openaireResultsStatus ==
errorCodes.LOADING)?' uk-disabled':' ')+' uk-link-text '">
<span class=" clickable" aria-hidden="true">
<span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="close" ratio="0.8"><path fill="none" stroke="#000" stroke-width="1.6" d="M16,16 L4,4"></path><path fill="none" stroke="#000" stroke-width="1.6" d="M16,4 L4,16"></path></svg>
</span>
</span>
<span class="uk-margin-small-left">{{filter.selectedFromAndToValues}}</span>
</a>
</span>
</span>
</ng-container>
</ng-container>
<ng-container *ngFor="let filter of filters " >
<ng-container *ngIf = "filter.countSelectedValues > 0">
<span *ngFor="let value of getSelectedValues(filter); let i = index; let end = last; "
[title]="'Remove '+value.name" (click) = "removeFilter(value, filter) " >
&lt;!&ndash; if no grid on the div above, remove it and move class 'selectedFilterLabel' on top span &ndash;&gt;
<span class="selectedFilterLabel ">
<a [class]="((openaireResultsStatus ==
errorCodes.LOADING)?' uk-disabled':' ')+' uk-link-text '">
<span class=" clickable" aria-hidden="true">
<span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="close" ratio="0.8"><path fill="none" stroke="#000" stroke-width="1.6" d="M16,16 L4,4"></path><path fill="none" stroke="#000" stroke-width="1.6" d="M16,4 L4,16"></path></svg>
</span>
</span>
<span class="uk-margin-small-left" [innerHtml]="(value.name.length > 34)?value.name.substring(0,34)+'...':value.name"></span>
</a>
</span>
</span>
</ng-container>
</ng-container>
</div>
</div>-->
<!-- <ng-container *ngIf="openaireResultsNum > 0">-->
<div *ngIf="!isNoProjectFunder && openaireResultsStatus != errorCodes.LOADING && openaireResultsNum > 1 " class="search-filters uk-width-1-1">
<div class="uk-grid uk-grid-small" uk-grid>
<ng-container *ngFor="let filter of rangeFilters">
<div>
@ -104,9 +60,12 @@
role="alert">Service not available
</div>
<div *ngIf="openaireResultsStatus == errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1"
role="alert"><span class="loading-gif uk-align-center"></span></div>
role="alert">
<loading></loading>
</div>
<claim-results [localStoragePrefix]="localStoragePrefix" [results]=openaireResults
[selectedResults]=selectedProjects [basketLimit]="basketLimit"></claim-results>
<div *ngIf="isNoProjectFunder && openaireResultsStatus != errorCodes.LOADING " class="uk-alert uk-alert-default">No projects for funder <span class=" uk-text-bold">{{selectedFunder.name}}</span>. </div>
<div *ngIf="openaireResultsNum != null && openaireResultsNum > 0 && openaireResultsStatus != errorCodes.LOADING " class="uk-flex uk-flex-center ">
<paging-no-load [currentPage]="openaireResultsPage"
[totalResults]="openaireResultsNum" [term]="keyword"

View File

@ -1,4 +1,4 @@
import {Component, ElementRef, EventEmitter, Input, Output} from '@angular/core';
import {Component, ElementRef, EventEmitter, Input, Output, ViewChild} from '@angular/core';
import {SearchProjectsService} from '../../services/searchProjects.service';
import {ProjectService} from '../../landingPages/project/project.service';
import {ClaimEntity, ClaimProject} from './claimHelper.class';
@ -10,6 +10,7 @@ import {RangeFilter} from "../../utils/rangeFilter/rangeFilterHelperClasses.clas
import {OpenaireEntities, SearchFields} from "../../utils/properties/searchFields";
import {NewSearchPageComponent} from "../../searchPages/searchUtils/newSearchPage.component";
import {Subscriber} from "rxjs";
import { properties } from 'src/environments/environment';
declare var UIkit:any;
@ -26,12 +27,11 @@ export class ClaimProjectsSearchFormComponent {
public elementRef;
@Output() projectSelected = new EventEmitter();
@Input() public properties:EnvProperties;
public properties:EnvProperties = properties;
@Input() public inlineClaim:boolean=false;
@Input() localStoragePrefix:string = "";
@Input() basketLimit;
@Input() showOptions;
public errorCodes:ErrorCodes = new ErrorCodes();
public projects:string[];
public warningMessage = "";
@ -53,29 +53,63 @@ export class ClaimProjectsSearchFormComponent {
public rangeFields:string[][] = this.searchFields.PROJECT_RANGE_FIELDS;
openaireEntities = OpenaireEntities;
sub;
selectedFunder = null;
funderOptions = [];
isNoProjectFunder = false;
constructor(private _service: ProjectService, private _projectService: SearchProjectsService, myElement: ElementRef) {
this.elementRef = myElement;
this.rangeFilters = RangeFilter.parse(this.rangeFields,"project");
this.rangeFilters = RangeFilter.parse(this.rangeFields,"project");
this.getFunders();
}
ngOnDestroy() {
if (this.sub instanceof Subscriber) {
this.sub.unsubscribe();
}
}
getFunders(){
this.openaireResultsStatus = this.errorCodes.LOADING;
this.showResults = true;
this.sub = this._projectService.advancedSearchProjects("", 1, 0, this.properties,
this.refineFieldsQuery, this.refineFields, "&type=projects&sf=funder").subscribe(
data => {
let option = {value : null, label: "No funder selected"};
this.funderOptions.push(option);
for(let v of data[2][0].values){
let option = {value : v, label: v.name};
this.funderOptions.push(option);
}
this.openaireResultsStatus = this.errorCodes.DONE;
}, error =>{
this.openaireResultsStatus = this.errorCodes.ERROR;
})
}
funderChanged(value){
this.keyword = ""
this.selectedFunder = value;
this.isNoProjectFunder = this.selectedFunder && this.selectedFunder.number == 1;
this.openaireResults = [];
if(this.isNoProjectFunder){
this.showResults = true;
this.search(1,1);
}else{
this.openaireResults = [];
}
}
search(page,size) {
if (this.keyword.length == 0) {
/* if (this.keyword.length == 0) {
this.showResults = false;
return;
}
}*/
this.showResults = true;
this.openaireResults = [];
this.openaireResultsStatus = this.errorCodes.LOADING;
this.prevFilters = this.filters;
//searchProjects (params: string, refineParams:string, page: number, size: number, refineFields:string[] , properties:EnvProperties ):any {
this.sub = this._projectService.advancedSearchProjects(this.createOpenaireQueryParams(), page, size, this.properties, (page == 1) ? this.refineFieldsQuery : null, (page == 1) ? this.refineFields : [], this.createOpenaireRefineQuery()).subscribe(
this.sub = this._projectService.advancedSearchProjects(this.createOpenaireQueryParams(), page, size, this.properties, this.createOpenaireRefineQuery(), [], null).subscribe(
// this.sub = this._projectService.searchProjects(this.createOpenaireQueryParams(),(page==1)? this.refineFieldsQuery:null, page, size, (page==1)?this.refineFields:[], this.properties).subscribe(
data => {
if (data != null) {
@ -91,6 +125,9 @@ export class ClaimProjectsSearchFormComponent {
this.openaireResultsStatus = this.errorCodes.NONE;
this.filters = this.checkSelectedFilters([], this.prevFilters);
}
/* if(this.isNoProjectFunder && this.claimResultsComponent){
this.claimResultsComponent.add(this.openaireResults[0])
}*/
} else {
this.openaireResultsStatus = this.errorCodes.ERROR;
}
@ -102,83 +139,20 @@ export class ClaimProjectsSearchFormComponent {
}
);
}
// select(entity){
// if(this.selectedProjects.length > 50){
// UIkit.notification({
// message : 'Your basket exceeds the number of allowed projects (50)',
// status : 'warning',
// timeout : 1500,
// pos : 'top-center'
// });
// return;
// }
// this.query = "";
// // this.searchTermStream.next(this.query); //clear
// entity = entity.value;
// // var project: ClaimProject = new ClaimProject();
// // project.funderId = entity.funderId;
// // project.funderName = entity.funderName;
// // project.id = entity.id;
// // project.projectName = entity.projectName;
// // project.projectAcronym = entity.projectAcronym;
// // project.startDate = entity.startDate;
// // project.endDate = entity.endDate;
// // project.code = entity.code;
// // project.jurisdiction = entity.jurisdiction;
// // project.fundingLevel0 = entity.fundingLevel0;
//
//
// var index:number =this.selectedProjects.indexOf(entity);
// var found:boolean = false;
// this.warningMessage = "";
//
// for (var _i = 0; _i < this.selectedProjects.length; _i++) {
// let project = this.selectedProjects[_i];
// if(entity.id == project.id){
// found=true;
// this.warningMessage = "Project already in your basket";
// }
// }
//
// if (!found) {
// this.selectedProjects.push(entity);
// if(this.selectedProjects != null){
// localStorage.setItem(this.localStoragePrefix + "projects", JSON.stringify(this.selectedProjects));
// }
// this.projectSelected.emit({
// value: true
// });
//
// }
// }
/* static showItem(item):string{
return ((item.field[1]['@value'])?item.field[1]['@value']+" - ":"" ) + item.field[3]['@value'];
}*/
remove(item){
remove(item){
let index:number =this.selectedProjects.indexOf(item);
if (index > -1) {
this.selectedProjects.splice(index, 1);
}
}
/* handleClick(event){
var clickedComponent = event.target;
var inside = false;
do {
if (clickedComponent === this.elementRef.nativeElement) {
inside = true;
}
clickedComponent = clickedComponent.parentNode;
} while (clickedComponent);
}*/
static openaire2ClaimEntity(items, properties:EnvProperties){
static openaire2ClaimEntity(items, properties:EnvProperties){
const projects: ClaimEntity[] = [];
for(const item of items){
const entity: ClaimEntity = new ClaimEntity();
entity.project = new ClaimProject();
entity.project.funderId = item.funderId;
entity.project.funderShortname = item.funderShortname?item.funderShortname:(entity.project.funderId.split("::")[1]);
entity.project.funderShortname = item.funderShortname?item.funderShortname:(entity.project.funderId?entity.project.funderId.split("::")[1]:"");
entity.project.funderName = item.funderName;
entity.id = item.id;
entity.project.url = (item.code !="unidentified") ? properties.searchLinkToProject + entity.id : null;
@ -214,12 +188,6 @@ export class ClaimProjectsSearchFormComponent {
}
createOpenaireRefineQuery(): string {
/*if(this.startYear.length > 0 ){
query+='&fq=projectstartyear exact \"'+this.startYear+'\"'
}
if(this.endYear.length > 0 ){
query+='&fq=projectendyear exact \"'+this.endYear+'\"'
}*/
let allFqs = "";
for (let filter of this.filters) {
if (filter.countSelectedValues > 0) {
@ -237,6 +205,12 @@ export class ClaimProjectsSearchFormComponent {
}
}
}
if(this.selectedFunder){
allFqs += "&fq=" + StringUtils.URIEncode( "funder exact " + (StringUtils.quote(this.selectedFunder.id)));
}
if(!this.isNoProjectFunder || !this.selectedFunder){
allFqs += '&fq=(projectcode<>"unidentified")'
}
for (let i = 0; i < this.rangeFilters.length; i++) {
let filter = this.rangeFilters[i];
//selectedFromValue, selectedToValue, equalityOp, equalityOpFrom, equalityOpTo, filterOp ){

View File

@ -17,14 +17,15 @@ import {RangeFilterModule} from "../../utils/rangeFilter/rangeFilter.module";
import {AdvancedSearchInputModule} from "../../sharedComponents/advanced-search-input/advanced-search-input.module";
import {InputModule} from "../../sharedComponents/input/input.module";
import {DropdownFilterModule} from "../../utils/dropdown-filter/dropdown-filter.module";
import {LoadingModule} from "../../utils/loading/loading.module";
@NgModule({
imports: [
SharedModule, CommonModule,
// LoadingModalModule,
ProjectServiceModule, ProjectsServiceModule, EntitiesAutocompleteModule, HelperModule,
PagingModule, SearchFilterModule, ClaimResultsModule, RangeFilterModule, AdvancedSearchInputModule, InputModule, DropdownFilterModule
],
imports: [
SharedModule, CommonModule,
// LoadingModalModule,
ProjectServiceModule, ProjectsServiceModule, EntitiesAutocompleteModule, HelperModule,
PagingModule, SearchFilterModule, ClaimResultsModule, RangeFilterModule, AdvancedSearchInputModule, InputModule, DropdownFilterModule, LoadingModule
],
providers:[
],
declarations: [

View File

@ -51,7 +51,9 @@
</div>
</div>
<div *ngIf="crossrefStatus === errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1"
role="alert"><span class="loading-gif uk-align-center"></span></div>
role="alert">
<loading></loading>
</div>
<div>
<claim-results [localStoragePrefix]=localStoragePrefix [results]=crossrefResults
@ -114,7 +116,7 @@
<div *ngIf="openaireResultsStatus === errorCodes.LOADING"
class="uk-animation-fade uk-margin-top uk-width-1-1"
role="alert"><span class="loading-gif uk-align-center">Loading...</span></div>
role="alert"><loading></loading></div>
<claim-results [localStoragePrefix]=localStoragePrefix
[results]=openaireResults [selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results>
<div class="uk-flex uk-flex-center" *ngIf=" openaireResultsStatus != errorCodes.LOADING && openaireResultsNum != null && openaireResultsNum > 0" >
@ -177,7 +179,7 @@
</div>
</div>
<div *ngIf="orcidStatus == errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1" role="alert">
<span class="loading-gif uk-align-center"></span></div>
<loading></loading></div>
</div>
</div>
<div *ngIf="activeTab == 'datacite'" id="datacite" class="uk-animation-fade">
@ -190,7 +192,7 @@
<div class="uk-margin-top">
<div *ngIf="dataciteStatus == errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1"
role="alert"><span class="loading-gif uk-align-center"></span></div>
role="alert"><loading></loading></div>
<div>
<claim-results [localStoragePrefix]=localStoragePrefix *ngIf="dataciteResults.length > 0 "
[results]=dataciteResults [selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results>

View File

@ -22,10 +22,11 @@ import {AdvancedSearchInputModule} from "../../sharedComponents/advanced-search-
import {InputModule} from "../../sharedComponents/input/input.module";
import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module";
import {DropdownFilterModule} from "../../utils/dropdown-filter/dropdown-filter.module";
import {LoadingModule} from "../../utils/loading/loading.module";
@NgModule({
imports: [SharedModule, CommonModule, SearchResearchResultsServiceModule, PagingModule, SearchCrossrefServiceModule,
SearchDataciteServiceModule, HelperModule, SearchFilterModule, ClaimResultsModule, MatSelectModule, QuickSelectionsModule, RangeFilterModule, ClaimProjectsSearchFormModule, AdvancedSearchInputModule, InputModule, SearchInputModule, DropdownFilterModule],
SearchDataciteServiceModule, HelperModule, SearchFilterModule, ClaimResultsModule, MatSelectModule, QuickSelectionsModule, RangeFilterModule, ClaimProjectsSearchFormModule, AdvancedSearchInputModule, InputModule, SearchInputModule, DropdownFilterModule, LoadingModule],
providers:[
SearchOrcidService
],

View File

@ -0,0 +1,23 @@
export class ClaimsProperties{
ALLOW_ORGANIZATION_LINKING:boolean = false;
SELECT_ENTITIES = {
projects:"Funding"
}
INLINE_ENTITY = {
show: true,
guideText : null
}
BASKET ={
source_title: "Source",
target_title: "Link source to"
}
METADATA_PREVIEW ={
source_title: "Source",
target_title: "Link to",
edit_source_title: "Edit",
edit_target_title: "Edit",
edit_target_icon: "edit"
}
}

View File

@ -1,25 +1,27 @@
<schema2jsonld *ngIf="url" [URL]="url" [name]="pageTitle" type="other"></schema2jsonld>
<div class="uk-grid">
<div class="uk-width-expand uk-position-relative">
<div class="uk-width-expand uk-position-relative uk-margin-small-top">
<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
[texts]="pageContents['top']"></helper>
<div *ngIf="filterForm" [id]="actions?'page_content_actions':null" [class.uk-blur-background]="actions" [attr.uk-sticky]="(actions)?'media: @m':null" [attr.offset]="offset">
<div [class.uk-padding-small]="actions" class="uk-padding-remove-vertical">
<div class="uk-section-xsmall">
<div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle">
<div search-input [disabled]="loading" [searchControl]="filterForm.controls.keyword" searchInputClass="outer"
placeholder="Search links" class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"
(searchEmitter)="changeKeyword()" [expandable]="true"></div>
</div>
</div>
</div>
</div>
<div [class.uk-padding]="actions" class="uk-padding-remove-vertical">
<div class="uk-margin-medium-top">
<div class="uk-margin-small-top">
<results-and-pages [type]="resultsNum !== 1?'Links':'Link'" [page]="page" [pageSize]="size" [hasSearch]="true" [searchTerm]="keyword"
[totalResults]="resultsNum" customClasses="uk-margin-remove"></results-and-pages>
</div>
<div class="uk-grid uk-flex-middle uk-margin-medium-top" uk-grid>
<div class="uk-grid uk-flex-middle uk-margin-small-top" uk-grid>
<div *ngIf="fetchBy != 'User' && properties.environment == 'development'" >
<input [(ngModel)]="mine" [checked]="mine" (ngModelChange)="goTo(1)" type="checkbox" class="uk-checkbox"> Mine
</div>
<div>
<dropdown-filter #dropdownFilter dropdownClass="uk-width-medium uk-padding-small"
name="Type of Entity" [disabled]="loading" [count]="entities.length">
@ -43,6 +45,7 @@
type="select" [options]="sortOptions">
</div>
</div>
<div class="uk-width-expand@l uk-width-1-1 uk-flex uk-flex-right@m uk-flex-center">
<paging-no-load [currentPage]="page" [totalResults]="resultsNum" [size]="size"
[loading]="false" (pageChange)="pageChange($event)"></paging-no-load>

View File

@ -40,7 +40,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
page: number = 1;
size: number = 50;
keyword: string; // the keyword string to give to the request as parameter
types = ["All", "Project", "Context", "Result", "User"];
types = ["All", "Project", "Context", "Result", "User", "Organization"];
loading: boolean = false;
@Input() fetchBy: string;
@Input() fetchId: string;
@ -53,6 +53,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
public filterForm: FormGroup;
public entities: string[] = [];
selected = [];
mine = false;
allOptions: Option[] = [
{label: OpenaireEntities.PUBLICATIONS, value: "publication"},
@ -133,6 +134,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
this.fetchId = this.fetchId ? this.fetchId : '';
}
let page = (params['page'] === undefined) ? 1 : +params['page'];
this.mine = (params['mine'] == 'true' ? true:false);
this.keyword = (params['keyword'] ? params['keyword'] : "");
this.filterForm.get('keyword').setValue(this.keyword);
this.page = (page <= 0) ? 1 : page;
@ -186,6 +188,16 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
this.handleErrors(err, "Error getting claims for project with id: " + this.fetchId);
}
);
} else if (this.fetchBy == "Organization") {
this.subResults = this._claimService.getClaimsByOrganization(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL, this.mine).subscribe(
data => {
this.manageAPIData(data);
this.loading = false;
},
err => {
this.handleErrors(err, "Error getting claims for project with id: " + this.fetchId);
}
);
} else if (this.fetchBy == "User") {
this.subResults = this._claimService.getClaimsByUser(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
data => {
@ -209,7 +221,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
}
);
} else if (this.fetchBy == "Context") {
this.subResults = this._claimService.getClaimsBycontext(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
this.subResults = this._claimService.getClaimsBycontext(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL, this.mine).subscribe(
data => {
this.manageAPIData(data);
this.loading = false;
@ -220,7 +232,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
}
);
} else {
this.subResults = this._claimService.getClaims(this.size, this.page, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
this.subResults = this._claimService.getClaims(this.size, this.page, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL, this.mine).subscribe(
data => {
this.manageAPIData(data);
this.loading = false;
@ -259,15 +271,8 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
types += (types.length > 0 ? ',' : '') + type;
}
params += (this.entities.length > 0) ? (params.length > 0 ? '&' : '') + "types=" + types : "";
if (this.isAdmin) {
params += (this.fetchBy == 'All' ? "" : (params.length > 0 ? '&' : '') + "fetchBy=" + this.fetchBy);
params += (this.fetchId == '' ? "" : (params.length > 0 ? '&' : '') + "fetchId=" + this.fetchId);
}
params += (this.filterForm.get("sort").value.sort == 'date' && this.filterForm.get("sort").value.descending ? "" : (params.length > 0 ? '&' : '') + "sort=" + this.filterForm.get("sort").value.sort + "-" + this.filterForm.get("sort").value.descending);
params += (this.keyword == '' ? "" : (params.length > 0 ? '&' : '') + "keyword=" + this.keyword);
if (this.communityId != null) {
params += "&communityId=" + this.communityId;
}
return params;
}

View File

@ -1,6 +1,6 @@
import {Component, Input} from '@angular/core';
import {EnvProperties} from '../../../utils/properties/env-properties';
import {ClaimDBContext, ClaimDBProject, ClaimDBResult} from "../claimHelper.class";
import {ClaimDBContext, ClaimDBOrganization, ClaimDBProject, ClaimDBResult} from "../claimHelper.class";
import {OpenaireEntities} from "../../../utils/properties/searchFields";
import {StringUtils} from "../../../utils/string-utils.class";
@ -26,6 +26,10 @@ import {StringUtils} from "../../../utils/string-utils.class";
<project-title [project]="entity" [searchLink]=properties.searchLinkToProject
[externalPortalUrl]=externalPortalUrl></project-title>
</div>
<div *ngIf="type == 'organization'" [attr.uk-tooptip]="getEntityName(type)">
<span class="uk-text-meta uk-text-small uk-margin-small-right uk-text-nowrap">Link to:</span>
<organization-title [organization]="entity"></organization-title>
</div>
<div *ngIf="type == 'context'">
<span class="uk-text-meta uk-text-small uk-margin-small-right uk-text-nowrap">Link to:</span>
<h6 class="uk-h6 uk-margin-remove">
@ -36,7 +40,7 @@ import {StringUtils} from "../../../utils/string-utils.class";
})
export class ClaimEntityFormatter {
@Input() entity: ClaimDBResult | ClaimDBContext | ClaimDBProject;
@Input() entity: ClaimDBResult | ClaimDBContext | ClaimDBProject | ClaimDBOrganization;
@Input() type: string;
@Input() properties: EnvProperties;
@Input() externalPortalUrl: string = null;

View File

@ -5,18 +5,19 @@ import { RouterModule } from '@angular/router';
import {ProjectTitleFormatter} from './projectTitleFormatter.component';
import {PublicationTitleFormatter} from './publicationTitleFormatter.component';
import {ClaimEntityFormatter} from './claimEntityFormatter.component';
import {OrganizationTitleFormatterComponent} from "./organizationTitleFormatter.component";
@NgModule({
imports: [
CommonModule, RouterModule
],
declarations: [
ProjectTitleFormatter, PublicationTitleFormatter, ClaimEntityFormatter
ProjectTitleFormatter, PublicationTitleFormatter, ClaimEntityFormatter, OrganizationTitleFormatterComponent
],
providers: [ ],
exports: [
ProjectTitleFormatter, PublicationTitleFormatter, ClaimEntityFormatter
ProjectTitleFormatter, PublicationTitleFormatter, ClaimEntityFormatter, OrganizationTitleFormatterComponent
]
})

View File

@ -0,0 +1,18 @@
import {Component, Input} from '@angular/core';
@Component({
selector: 'organization-title',
template: `
<h6 *ngIf="organization" class="uk-margin-remove multi-line-ellipsis lines-2">
<p class="uk-margin-remove">
{{(organization.shortName ? ('[' + organization.shortName + '] ') : '')}}{{organization.name}}
</p>
</h6>
`
})
export class OrganizationTitleFormatterComponent {
@Input() organization: any;
public url: string;
}

View File

@ -10,10 +10,10 @@ import {properties} from "../../../../../environments/environment";
<ng-container>
<h6 class="uk-margin-remove multi-line-ellipsis lines-2">
<p class="uk-margin-remove">
<a *ngIf="externalPortalUrl" [href]="externalPortalUrl + projectUrl + '?projectId='+project['openaireId']" class="uk-link uk-link-heading">
<a *ngIf="externalPortalUrl" [href]="externalPortalUrl + projectUrl + '?projectId='+project['openaireId']" class="uk-link uk-link-heading" [class.uk-disabled]="project.name == 'unidentified'">
{{(project['acronym'] ? ('[' + project['acronym'] + '] ') : '')}}{{project['name']}}
</a>
<a *ngIf="!externalPortalUrl" [routerLink]="projectUrl" [queryParams]="routerHelper.createQueryParam('projectId',project['openaireId'])" class="uk-link uk-link-heading">
<a *ngIf="!externalPortalUrl" [routerLink]="projectUrl" [queryParams]="routerHelper.createQueryParam('projectId',project['openaireId'])" class="uk-link uk-link-heading" [class.uk-disabled]="project.name == 'unidentified'">
{{(project['acronym'] ? ('[' + project['acronym'] + '] ') : '')}}{{project['name']}}
</a>
</p>

View File

@ -12,8 +12,8 @@ export class ClaimsService {
private getClaimRequest(size : number, page : number, url :string, fromCache:boolean):any {
return this.http.get(url, CustomOptions.getAuthOptionsWithBody());
}
getClaims( size : number, page : number, keyword:string, sortby: string, descending: boolean, types: string, apiUrl:string):any {
let url = apiUrl +"claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types);
getClaims( size : number, page : number, keyword:string, sortby: string, descending: boolean, types: string, apiUrl:string, mine:boolean):any {
let url = apiUrl +"claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types) + (mine?"&mine=true":"") + (mine?"&mine=true":"");
return this.getClaimRequest(size,page,url,true);
}
@ -23,7 +23,7 @@ export class ClaimsService {
return this.getClaimRequest(size,page,url,false);
}
getClaimsBycontext( size : number, page : number, contextId:string, keyword:string, sortby: string, descending: boolean, types: string , apiUrl:string):any {
getClaimsBycontext( size : number, page : number, contextId:string, keyword:string, sortby: string, descending: boolean, types: string , apiUrl:string, mine:boolean):any {
//console.info('ClaimsService: getClaims for context : '+contextId);
let url = apiUrl +"contexts/"+contextId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types);
return this.getClaimRequest(size,page,url,true);
@ -40,6 +40,10 @@ export class ClaimsService {
let url = apiUrl +"projects/"+projectId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types);
return this.getClaimRequest(size,page,url,true);
}
getClaimsByOrganization( size : number, page : number, organizationId:string, keyword:string, sortby: string, descending: boolean, types: string, apiUrl:string, mine:boolean):any {
let url = apiUrl +"organizations/"+organizationId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types) + (mine?"&mine=true":"");
return this.getClaimRequest(size,page,url,true);
}
deleteClaimById(claimId:string , apiUrl:string):any{
//console.warn('Trying to delete claim with id : '+claimId);

View File

@ -1,6 +1,6 @@
<linking-generic *ngIf="validInput" [localStoragePrefix]="localStoragePrefix" [results]="results" [sources]="sources"
[communityId]="communityId" [inlineEntity]="inlineEntity" [showOptions]="showOptions"
pageTitle="Direct Linking">
pageTitle="Direct Linking" [claimsProperties]="claimsProperties">
</linking-generic>
<div *ngIf="validInput== false" id="tm-main" class=" uk-section uk-padding-remove-top tm-middle">

View File

@ -1,7 +1,7 @@
import {Component, Input, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {EnvProperties} from '../../utils/properties/env-properties';
import {ClaimEntity, ClaimProject, ShowOptions} from '../claim-utils/claimHelper.class';
import {ClaimEntity, ClaimOrganization, ClaimProject, ShowOptions} from '../claim-utils/claimHelper.class';
import {EntitiesSearchService} from '../../utils/entitiesAutoComplete/entitySearch.service';
import {SearchResearchResultsService} from '../../services/searchResearchResults.service';
import {LinkingGenericComponent} from "../linking/linkingGeneric.component";
@ -11,6 +11,7 @@ import {properties} from "../../../../environments/environment";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {StringUtils} from "../../utils/string-utils.class";
import {ClaimProjectsSearchFormComponent} from "../claim-utils/claimProjectSearchForm.component";
import {ClaimsProperties} from "../claim-utils/claims.properties";
@Component({
@ -24,18 +25,20 @@ export class DirectLinkingComponent {
// linkType: string = "project"; // link type (selected in home page) : project, context, software, etc
/* url Parameters for inline linking */
id: string = null; //entity id
@Input() id: string = null; //entity id
type: string = null; // entity type (publication or dataset)
// linkTo: string = null; // entity type (project or context or entity)
// linkToEntities: string[] = [];
showOptions:ShowOptions = new ShowOptions();
validEntityTypes = ["dataset", "publication", "software", "other", "project", "context"];
validEntityTypes = ["dataset", "publication", "software", "other", "project", "context", "organization"];
sources: ClaimEntity[] = [];
inlineEntity: ClaimEntity = null;
validInput: boolean = null;//'true;
properties: EnvProperties;
@Input() communityId: string = null;
localStoragePrefix: string = "";
@Input() organizationClaim: boolean = false;
@Input() claimsProperties:ClaimsProperties = new ClaimsProperties();
constructor(private _router: Router, private route: ActivatedRoute,private entitySearch:EntitiesSearchService,
private _searchResearchResultsService: SearchResearchResultsService) {}
subscriptions = [];
@ -48,11 +51,18 @@ export class DirectLinkingComponent {
}
ngOnInit() {
this.properties = properties;
/* if(!this.claimsProperties){
this.claimsProperties = new ClaimsProperties();
}*/
this.subscriptions.push(this.route.queryParams.subscribe(params => {
this.id = params['id'];
this.type = params['type'];
this.showOptions.linkTo = params['linkTo'];
if(this.organizationClaim){
this.type = "organization";
this.showOptions.linkTo = "result";
}else {
this.id = params['id'];
this.type = params['type'];
this.showOptions.linkTo = params['linkTo'];
}
if (this.type != null && this.showOptions.linkTo != null) {
this.type = (this.validEntityTypes.indexOf(this.type) != -1) ? this.type : 'publication';
this.showOptions.linkTo = (this.validEntityTypes.indexOf(this.showOptions.linkTo) != -1 || this.showOptions.linkTo == "result") ? this.showOptions.linkTo : 'project';
@ -68,6 +78,8 @@ export class DirectLinkingComponent {
if (this.type == "project") {
// this.linkType = "project";
this.getProjectById(this.id);
} else if (this.type == "organization") {
this.getOrganizationById(this.id);
} else if (this.type == "publication") {
this.getResearchResultById("publication", this.id);
} else if (this.type == "dataset") {
@ -81,7 +93,7 @@ export class DirectLinkingComponent {
}
//set which entities it is allowed to link to.
// add first the
if(this.type == "project"){
if(this.type == "project" || this.type == "organization"){
this.showOptions.linkToEntities = ["result"];
this.showOptions.linkTo = "result";
}else{
@ -95,24 +107,27 @@ export class DirectLinkingComponent {
this.showOptions.linkToEntities = ["result","project","context" ];
}
}
} else {
this.validInput = this.isValidInput(null);
}
} else {
this.validInput = this.isValidInput(null);
}));
}
}));
}
isValidInput(result: ClaimEntity) {
if (result == null) {
return false;
} else if (this.type == "project" && this.showOptions.linkTo != "result") {
} else if (this.type == "organization" && !this.claimsProperties.ALLOW_ORGANIZATION_LINKING) {
return false;
} else if ((this.type == "project" || this.type == "organization") && this.showOptions.linkTo != "result") {
return false;
} else if (["dataset", "publication", "software", "other"].indexOf(this.type) != -1 && (["project", "context", "result"].indexOf(this.showOptions.linkTo) == -1)) {
return false;
} else if (["project", "dataset", "publication", "software", "other"].indexOf(this.type) == -1) {
} else if (["project", "dataset", "publication", "software", "other", "organization"].indexOf(this.type) == -1) {
return false;
} else {
return true;
@ -130,6 +145,17 @@ export class DirectLinkingComponent {
this.handleError("Error getting project by id: " + id, err);
}));
}
getOrganizationById(id: string) {
this.subscriptions.push(this.entitySearch.fetchByType(id,"organization", this.properties).subscribe(
data => {
this.createClaimEntity(data, "organization");
},
err => {
this.validInput = this.isValidInput(null);
//console.log("An error occured")
this.handleError("Error getting project by id: " + id, err);
}));
}
getResearchResultById(resultType: string, id: string) {
this.subscriptions.push(this._searchResearchResultsService.searchById(resultType, id, this.properties).subscribe(data => {
@ -162,7 +188,17 @@ export class DirectLinkingComponent {
entity.project.jurisdiction = project.jurisdiction;
entity.project.startDate = project.startDate;
this.inlineEntity = entity;
}else{
}else if(type =="organization"){
let organization = data[0];
let entity:ClaimEntity = new ClaimEntity();
entity.id = organization.id;
entity.type = "organization";
entity.title = organization.label;
entity.organization = new ClaimOrganization();
// entity.organization.url = properties.searchLinkToOrganization + entity.id;
entity.organization.name = organization.label;
this.inlineEntity = entity;
}else{
results = ClaimResultSearchFormComponent.openaire2ClaimResults(data, this.properties);
}

View File

@ -176,7 +176,7 @@ export class ClaimInsertComponent {
"id": entity.id,
"record": ClaimInsertComponent.createDirectClaim(entity, this.sources, idSuffix)
});
} else if (this.inlineEntity) {
} else if (this.inlineEntity && this.inlineEntity.type != "organization") {
directclaims.push({
"id": entity.id,
"record": ClaimInsertComponent.createDirectClaim(entity, [this.inlineEntity], idSuffix)
@ -193,6 +193,8 @@ export class ClaimInsertComponent {
claims.push(ClaimInsertComponent.createContextClaim(result, entity, user.email, dashboard, idSuffix));
} else if (entity.project) {
claims.push(ClaimInsertComponent.createProjectClaim(result, entity, user.email, dashboard, idSuffix));
/* } else if (entity.organization) {
claims.push(ClaimInsertComponent.createOrganizationClaim(result, entity, user.email, dashboard, idSuffix));*/
}
this.infoToLog.push([ result.title?result.title: result.id, entity.title?entity.title:entity.id]);
@ -212,6 +214,10 @@ export class ClaimInsertComponent {
if (entity.result) {
claims.push(ClaimInsertComponent.createProjectClaim(entity, this.inlineEntity, user.email, dashboard, idSuffix));
}
} else if (this.inlineEntity.organization) {
if (entity.result) {
claims.push(ClaimInsertComponent.createOrganizationClaim(entity, this.inlineEntity, user.email, dashboard, idSuffix));
}
}
}
@ -385,8 +391,13 @@ export class ClaimInsertComponent {
localStorage.removeItem(this.localStoragePrefix + "results");
localStorage.removeItem(this.localStoragePrefix + "claimsJob");
localStorage.removeItem(this.localStoragePrefix + "feedRecordsJob");
this._router.navigate([this.properties.myClaimsLink], {queryParams: this.params});
if(this.properties.myClaimsLink && this.properties.myClaimsLink.indexOf(".") == -1) {
this._router.navigate([this.properties.myClaimsLink], {queryParams: this.params});
}else if(this.properties.myClaimsLink && this.properties.myClaimsLink.indexOf(".") != -1) {
this._router.navigate([this.properties.myClaimsLink], {relativeTo: this.route});
}else{
this._router.navigate(["/"]);
}
}
}
@ -426,6 +437,23 @@ export class ClaimInsertComponent {
idSuffix : idSuffix
};
}
private static createOrganizationClaim(resultEntity: ClaimEntity, organizationEntity: ClaimEntity, user: any, dashboard:string, idSuffix:string): ClaimRecord2Insert {
return {
claimedBy: user,
sourceId: organizationEntity.id,
sourceType: "organization",
sourceCollectedFrom: "openaire",
sourceAccessRights: "OPEN",
sourceEmbargoEndDate: "",
targetId: resultEntity.id,
targetType: resultEntity.type,
targetCollectedFrom: resultEntity.result.source,
targetAccessRights: resultEntity.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
claimedInDashboard : dashboard,
idSuffix : idSuffix
};
}
private static createResultClaim(inlineResult: ClaimEntity, resultEntity: ClaimEntity, user: string, dashboard:string, idSuffix:string): ClaimRecord2Insert {

View File

@ -67,18 +67,19 @@
[results]="results" [sources]="sources"
[localStoragePrefix]="localStoragePrefix" [inlineEntity]="inlineEntity"
[showOptions]="showOptions" [properties]=properties [pageContents]="pageContents"
[defaultColors]="!communityId" [communityId]="communityId"
[defaultColors]="!communityId" [communityId]="communityId" [claimsProperties]="claimsProperties"
>
</metadata-preview>
<div id="tm-main" class="uk-section uk-padding-remove-top" *ngIf="showOptions.show != 'claim'">
<div>
<schema2jsonld *ngIf="url" [URL]="url" name="Link your {{openaireEntities.RESULTS}}" type="other"></schema2jsonld>
<div class="uk-container uk-container-large">
<div *ngIf="properties" class="uk-section uk-padding-remove-top">
<div *ngIf="properties && claimsProperties" class="uk-section uk-padding-remove-top">
<div class="uk-container uk-container-large">
<div class="uk-grid basketContainer" *ngIf="showOptions.show!='claim'" uk-grid>
<div class="uk-width-2-3@m uk-position-z-index uk-flex-first@m uk-flex-last uk-margin-medium-top">
<h2 *ngIf="inlineEntity" class="uk-text-center">Link source to</h2>
<h2 *ngIf="inlineEntity && claimsProperties.INLINE_ENTITY.show" class="uk-text-center">Link source to</h2>
<div *ngIf="inlineEntity && claimsProperties.INLINE_ENTITY.guideText" class="uk-text-center">{{claimsProperties.INLINE_ENTITY.guideText}}</div>
<div *ngIf="showOptions.show=='source'">
<claim-result-search-form [selectedResults]="sources" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'"
@ -115,16 +116,16 @@
<div class="uk-card-body uk-padding-small">
<div>
<ng-container *ngIf="inlineEntity">
<div class="uk-margin-small-bottom">
<div class="uk-text-emphasis uk-text-bolder">Source</div>
<div *ngIf="claimsProperties.INLINE_ENTITY.show" class="uk-margin-small-bottom">
<div class="uk-text-emphasis uk-text-bolder">{{claimsProperties.BASKET.source_title}}</div>
<claim-selected-results [results]="[inlineEntity]"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="false" type="source">
</claim-selected-results>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal"><hr class="uk-margin-remove"/></div>
<div *ngIf="claimsProperties.INLINE_ENTITY.show" class="uk-padding-small uk-padding-remove-horizontal"><hr class="uk-margin-remove"/></div>
<div class="uk-margin-small-top">
<div class="uk-text-emphasis uk-text-bolder">Link source to <span *ngIf="results.length> 0">({{(results.length) | number}})</span></div>
<div class="uk-text-emphasis uk-text-bolder">{{claimsProperties.BASKET.target_title}} <span *ngIf="results.length> 0">({{(results.length) | number}})</span></div>
<ng-container *ngTemplateOutlet="destinations_basket"></ng-container>
</div>
</ng-container>

View File

@ -18,6 +18,7 @@ import {RouterHelper} from "../../utils/routerHelper.class";
import { Location } from '@angular/common';
import {LoginErrorCodes} from "../../login/utils/guardHelper.class";
import {UserManagementService} from "../../services/user-management.service";
import {ClaimsProperties} from "../claim-utils/claims.properties";
@Component({
selector: 'linking-generic',
@ -41,7 +42,7 @@ export class LinkingGenericComponent {
// show linkToEntities /values: result, project, context
@Input() sources:ClaimEntity[] =[];
properties:EnvProperties;
properties:EnvProperties = properties;
public openaireEntities = OpenaireEntities;
@Input() localStoragePrefix:string = "linking_";
url=null;
@ -49,7 +50,7 @@ export class LinkingGenericComponent {
public pageContents = null;
@Input() breadcrumbs: Breadcrumb[] = [];
public routerHelper: RouterHelper = new RouterHelper();
@Input() claimsProperties:ClaimsProperties = new ClaimsProperties();
constructor (private _router: Router, private route: ActivatedRoute, private entitySearch:EntitiesSearchService,
private _meta: Meta, private _title: Title, private _piwikService:PiwikService,
private seoService: SEOService, private helper: HelperService, private cdr: ChangeDetectorRef,
@ -58,6 +59,9 @@ export class LinkingGenericComponent {
subscriptions = [];
ngOnInit() {
/* if(!this.claimsProperties){
this.claimsProperties = new ClaimsProperties();
}*/
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
if (!user) {
this.saveStateAndRedirectLogin();
@ -68,14 +72,13 @@ export class LinkingGenericComponent {
this.breadcrumbs.push({name: "Link", route: null});
}
this.showOptions.show = 'source';
this.showOptions.initSelectOptions();
this.showOptions.initSelectOptions(this.claimsProperties);
if(this.inlineEntity){
this.showOptions.showLinkTo();
// this.showOptions.basketShowLinksTo = true;
this.showOptions.show = this.showOptions.linkTo;
}
this.properties = properties;
this.url = this.properties.domain + this.properties.baseLink+this._router.url;
var description = "Linking is a functionality provided by OpenAIRE, in order to link research results with a project, a research community or other research results.";

View File

@ -3,13 +3,21 @@ import {SharedModule} from '../../../../openaireLibrary/shared/shared.module';
import {ClaimEntityTitleComponent} from "./ClaimEntityTitle.component";
import {ClaimEntityResultMetadataComponent} from "./ClaimEntityResultMetadata.component";
import {ClaimEntityProjectMetadataComponent} from "./ClaimEntityProjectMetadata.component";
import {IconsService} from "../../../utils/icons/icons.service";
import {coins} from "../../../utils/icons/icons";
import {IconsModule} from "../../../utils/icons/icons.module";
@NgModule({
imports: [
SharedModule
SharedModule,
IconsModule
],
declarations: [
ClaimEntityTitleComponent, ClaimEntityResultMetadataComponent, ClaimEntityProjectMetadataComponent
], exports:[ ClaimEntityTitleComponent, ClaimEntityResultMetadataComponent, ClaimEntityProjectMetadataComponent]
})
export class ClaimEntitiesMetadataModule { }
export class ClaimEntitiesMetadataModule {
constructor(private _iconsService:IconsService) {
this._iconsService.registerIcons([coins])
}
}

View File

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

View File

@ -5,16 +5,18 @@ import {ClaimEntity} from '../../claim-utils/claimHelper.class';
selector: 'claim-title',
template: `
<div class="uk-grid uk-flex uk-flex-middle">
<span *ngIf="showIcon" class="uk-flex">
<span *ngIf="entity.result" class="material-icons uk-text-small uk-text-meta">
insert_drive_file
</span>
<span *ngIf="entity.project" class="material-icons uk-text-small uk-text-meta">
assignment_turned_in
</span>
<span *ngIf="entity.type=='community'" class="material-icons uk-text-small uk-text-meta" style="margin-right: 2px;">
people
</span>
<span *ngIf="showIcon" class="uk-flex uk-margin-xsmall-right">
<icon *ngIf="entity.result" class=" uk-text-small uk-text-meta" name="insert_drive_file">
</icon>
<icon *ngIf="entity.project && entity.project.code !='unidentified'" class=" uk-text-small uk-text-meta" name="assignment_turned_in">
</icon>
<icon *ngIf="entity.project && entity.project.code =='unidentified'" class="uk-text-small uk-text-meta" name="coins" [ratio]="1.4">
</icon>
<icon *ngIf="entity.organization" class=" uk-text-small uk-text-meta" name="account_balance">
</icon>
<icon *ngIf="entity.type=='community'" class=" uk-text-small uk-text-meta" style="margin-right: 2px;" name="people">
</icon>
</span>
<div class="uk-width-expand multi-line-ellipsis lines-3" style="word-break: break-word;"
[class.uk-padding-remove-left]="showIcon" [class.uk-text-truncate]="shortVersion">
@ -27,7 +29,15 @@ import {ClaimEntity} from '../../claim-utils/claimHelper.class';
<span *ngIf="(entity.result && !entity.result.url)">
{{entity.title ? sliceString(entity.title) : '[No title available]'}}
</span>
<span *ngIf="entity.type=='project' && entity.project">
<span *ngIf="entity.type=='project' && entity.project && entity.project.code =='unidentified'">
<span *ngIf="!shortVersion">
{{(entity.project.funderShortname ? '[' + entity.project.funderShortname + '] ' : '') + entity.project.funderName}}
</span>
<span *ngIf="shortVersion">
{{sliceString(entity.project.funderName)}}
</span>
</span>
<span *ngIf="entity.type=='project' && entity.project && entity.project.code!='unidentified'">
<a *ngIf="entity.project && entity.project.url" target="_blank" [href]="entity.project.url"
class="uk-link uk-text-decoration-none uk-width-expand">
<span *ngIf="!shortVersion">
@ -46,6 +56,9 @@ import {ClaimEntity} from '../../claim-utils/claimHelper.class';
</span>
</span>
</span>
<span *ngIf="entity.type=='organization' && entity.organization">
{{sliceString(entity.title)}}
</span>
<span *ngIf="entity.type=='community' && entity.context">
<span *ngIf=" entity.context.community != entity.context.concept.label">
{{entity.context.community }} > {{entity.context.category}} >

View File

@ -6,15 +6,14 @@
<div class="uk-width-expand">
<div class="uk-card uk-card-default">
<div class="uk-card-body">
<div class="uk-grid uk-grid-divider uk-child-width-1-2@m uk-child-width-1-1@s" uk-grid>
<div class="uk-grid uk-grid-divider uk-child-width-1-1@s" uk-grid [class.uk-child-width-1-2@m] = "claimsProperties.INLINE_ENTITY.show" >
<!-- Sources-->
<div>
<div *ngIf="claimsProperties.INLINE_ENTITY.show">
<div class=" uk-margin uk-animation-toggle">
<span class="uk-h6 "> SOURCES ({{sources.length + (inlineEntity ? 1 : 0) | number}})
<span class="uk-h6 "> {{claimsProperties.METADATA_PREVIEW.source_title}} ({{sources.length + (inlineEntity ? 1 : 0) | number}})
</span>
<a *ngIf="!inlineEntity" class="uk-float-right uk-text-small" (click)="showOptions.showSource() "> <span
uk-icon="pencil" class="uk-margin-xsmall-right"></span>Edit
sources</a>
uk-icon="pencil" class="uk-margin-xsmall-right"></span>{{claimsProperties.METADATA_PREVIEW.edit_source_title}}</a>
</div>
<ul *ngIf="inlineEntity" class="uk-list uk-animation-fade uk-list-divider">
<li>
@ -153,13 +152,15 @@
</div>
<!-- Results-->
<div class=" ">
<div class=" uk-margin ">
<span class=" uk-h6 "> LINK TO ({{results.length | number}})</span>
<div class=" uk-margin uk-grid">
<span class=" uk-h6 uk-width-expand"> {{claimsProperties.METADATA_PREVIEW.target_title}} ({{results.length | number}})</span>
<div class="uk-width-auto uk-flex">
<a class="uk-float-right uk-text-small" (click)="showOptions.showLinkTo()"> <span
uk-icon="pencil" class="uk-margin-xsmall-right"></span>Edit
entities</a>
<icon [name]="claimsProperties.METADATA_PREVIEW.edit_target_icon" [flex]="true"></icon>
<a class=" uk-margin-left-xsmall uk-text-small" (click)="showOptions.showLinkTo()">
{{claimsProperties.METADATA_PREVIEW.edit_target_title}}</a>
</div>
</div>
<div *ngIf="results.length == 0">
<div class="uk-alert dangerBorder no-selected-message uk-text-center">

View File

@ -4,6 +4,7 @@ import {ClaimEntity, ClaimsErrorMessage, Message, ShowOptions} from '../../claim
import {EnvProperties} from "../../../utils/properties/env-properties";
import {Dates} from "../../../utils/string-utils.class";
import {HelperFunctions} from "../../../utils/HelperFunctions.class";
import {ClaimsProperties} from "../../claim-utils/claims.properties";
@Component({
selector: 'metadata-preview',
@ -28,6 +29,7 @@ export class MetadataPreviewComponent {
@ViewChild(AlertModal) alertApplyAll;
@Input() localStoragePrefix: string = "";
@Input() communityId:string= null;
@Input() claimsProperties:ClaimsProperties;
errors:ClaimsErrorMessage[] = [];
warnings:Message[] = [];
public commonAccessRights = "OPEN"; // for access rights- changes when user apply a change to every entity

View File

@ -11,16 +11,17 @@ import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import {HelperModule} from "../../../utils/helper/helper.module";
import {SelectedPublicationsModule} from "./selectedResults.module";
import {IconsModule} from "../../../utils/icons/icons.module";
@NgModule({
imports: [
SharedModule,
AlertModalModule,
ClaimEntitiesMetadataModule,
InsertClaimsModule,
MatDatepickerModule, MatNativeDateModule, MatFormFieldModule, MatInputModule, MatSelectModule,
HelperModule, SelectedPublicationsModule
],
imports: [
SharedModule,
AlertModalModule,
ClaimEntitiesMetadataModule,
InsertClaimsModule,
MatDatepickerModule, MatNativeDateModule, MatFormFieldModule, MatInputModule, MatSelectModule,
HelperModule, SelectedPublicationsModule, IconsModule
],
declarations: [MetadataPreviewComponent],
exports:[MetadataPreviewComponent]
})

View File

@ -370,8 +370,10 @@ export class MenuComponent implements OnInit {
}
public valueChange() {
this.elements.disable();
this.cdr.detectChanges();
this.elements.init();
this.elements.enable();
}
public get displayMenuItems() {

View File

@ -8,16 +8,16 @@
<div class="uk-flex uk-flex-left@m uk-flex-center uk-width-expand">
<ul class="uk-subnav uk-subnav-pill">
<li [class.uk-active]="showCurrent" (click)="showCurrent = true">
<a class="uk-text-capitalize">{{stakeholderUtils.roles[role]}}s</a>
<a class="uk-text-capitalize">{{roleUtils.roles[role]}}s</a>
</li>
<li [class.uk-active]="!showCurrent" (click)="showCurrent = false">
<a>Pending {{stakeholderUtils.roles[role]}}s</a>
<a>Pending {{roleUtils.roles[role]}}s</a>
</li>
</ul>
</div>
<div class="uk-width-expand@m uk-width-1-1 uk-grid uk-flex-right@m uk-flex-center uk-flex-middle" uk-grid>
<div *ngIf="showCurrent" [disabled]="loadActive" search-input class="uk-width-expand@l uk-width-1-1"
[searchControl]="filterForm.get('active')" [expandable]="true" [placeholder]="'Search ' + stakeholderUtils.roles[role] + 's'" searchInputClass="outer">
[searchControl]="filterForm.get('active')" [expandable]="true" [placeholder]="'Search ' + roleUtils.roles[role] + 's'" searchInputClass="outer">
</div>
<div *ngIf="!showCurrent" [disabled]="loadPending" search-input class="uk-width-expand@l uk-width-1-1"
[searchControl]="filterForm.get('pending')" [expandable]="true" [placeholder]="'Search invitations'" searchInputClass="outer">
@ -27,7 +27,7 @@
[attr.uk-tooltip]="inviteDisableMessage" [class.uk-disabled]="loadPending || loadPending"
[disabled]="loadActive || loadPending || !!inviteDisableMessage" (click)="openInviteModal()">
<icon name="person_add" [flex]="true" type="filled"></icon>
<span class="uk-margin-small-left uk-text-bold uk-text-uppercase">Invite {{stakeholderUtils.roles[role]}}</span>
<span class="uk-margin-small-left uk-text-bold uk-text-uppercase">Invite {{roleUtils.roles[role]}}</span>
</button>
<button *ngIf="!exists && isCurator" class="uk-button uk-button-default uk-flex uk-flex-middle"
(click)="openCreateRoleModal()">
@ -47,16 +47,16 @@
<div *ngIf="!loadActive && !loadPending">
<div *ngIf="(showCurrent && showActive.length == 0) || (!showCurrent && showPending.length == 0)"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div *ngIf="showCurrent">No {{stakeholderUtils.roles[role]}}s found</div>
<div *ngIf="!showCurrent">No pending {{stakeholderUtils.roles[role]}} invitations found</div>
<div *ngIf="showCurrent">No {{roleUtils.roles[role]}}s found</div>
<div *ngIf="!showCurrent">No pending {{roleUtils.roles[role]}} invitations found</div>
</div>
<div *ngIf="(showCurrent && showActive.length > 0) || (!showCurrent && showPending.length > 0)">
<no-load-paging *ngIf="showCurrent" [type]="(showActive.length > 1)?(stakeholderUtils.roles[role] + 's'):role"
<no-load-paging *ngIf="showCurrent" [type]="(showActive.length > 1)?(roleUtils.roles[role] + 's'):role"
(pageChange)="updateActivePage($event)"
[page]="activePage" [pageSize]="pageSize"
[totalResults]="showActive.length">
</no-load-paging>
<no-load-paging *ngIf="!showCurrent" [type]="stakeholderUtils.roles[role] + ' ' + (showPending.length > 1?'invitations':'invitation')"
<no-load-paging *ngIf="!showCurrent" [type]="roleUtils.roles[role] + ' ' + (showPending.length > 1?'invitations':'invitation')"
(pageChange)="updatePendingPage($event)"
[page]="pendingPage" [pageSize]="pageSize"
[totalResults]="showPending.length">
@ -109,12 +109,12 @@
</modal-alert>
<modal-alert #deleteModal [overflowBody]="false" (alertOutput)="deleteActive()" classTitle="uk-background-primary uk-light">
<div *ngIf="selectedUser">
Are you sure you want to remove <span class="uk-text-bold">{{selectedUser}}</span> from {{stakeholderUtils.roles[role]}}s?
Are you sure you want to remove <span class="uk-text-bold">{{selectedUser}}</span> from {{roleUtils.roles[role]}}s?
</div>
</modal-alert>
<modal-alert #deletePendingModal [overflowBody]="false" (alertOutput)="deletePending()" classTitle="uk-background-primary uk-light">
<div *ngIf="selectedUser">
Are you sure you want to cancel {{stakeholderUtils.roles[role]}} invitation of <span class="uk-text-bold">{{selectedUser}}</span>?
Are you sure you want to cancel {{roleUtils.roles[role]}} invitation of <span class="uk-text-bold">{{selectedUser}}</span>?
</div>
</modal-alert>
<modal-alert #createRoleModal [overflowBody]="false" (alertOutput)="createGroup()" classTitle="uk-background-primary uk-light"

View File

@ -13,7 +13,7 @@ import {AlertModal} from "../../../utils/modal/alert";
import {UserRegistryService} from "../../../services/user-registry.service";
import {EnvProperties} from "../../../utils/properties/env-properties";
import {properties} from "../../../../../environments/environment";
import {Role, Session, User} from "../../../login/utils/helper.class";
import {Role, RoleUtils, Session, User} from "../../../login/utils/helper.class";
import {UserManagementService} from "../../../services/user-management.service";
import {Router} from "@angular/router";
import {StringUtils} from "../../../utils/string-utils.class";
@ -44,7 +44,9 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
@Input()
public id: string;
@Input()
public type: string;
set type(type: string) {
this._type = Role.mapType(type);
}
@Input()
public name: string;
@Input()
@ -90,6 +92,8 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
@ViewChild('deletePendingModal') deletePendingModal: AlertModal;
@ViewChild('createRoleModal') createRoleModal: AlertModal;
public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public roleUtils: RoleUtils = new RoleUtils();
private _type: string;
constructor(private userRegistryService: UserRegistryService,
private userManagementService: UserManagementService,
@ -143,7 +147,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
updateLists() {
this.loadActive = true;
this.loadPending = true;
this.subs.push(this.userRegistryService.getActive(this.type, this.id, this.role, true).subscribe(users => {
this.subs.push(this.userRegistryService.getActive(this._type, this.id, this.role, true).subscribe(users => {
this.active = users;
this.filterActiveBySearch(this.filterForm.value.active);
this.loadActive = false;
@ -156,7 +160,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
}
this.loadActive = false;
}));
this.subs.push(this.userRegistryService.getPending(this.type, this.id, this.role, true).subscribe(users => {
this.subs.push(this.userRegistryService.getPending(this._type, this.id, this.role, true).subscribe(users => {
this.pending = users;
this.filterPendingBySearch(this.filterForm.value.pending);
this.loadPending = false;
@ -185,7 +189,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
openDeleteModal(item: any) {
if (this.showCurrent) {
this.selectedUser = item.email;
this.deleteModal.alertTitle = 'Delete ' + this.stakeholderUtils.roles[this.role];
this.deleteModal.alertTitle = 'Delete ' + this.roleUtils.roles[this.role];
this.deleteModal.open();
} else {
this.selectedUser = item;
@ -195,7 +199,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
}
openInviteModal() {
this.inviteModal.alertTitle = 'Invite ' + this.stakeholderUtils.roles[this.role];
this.inviteModal.alertTitle = 'Invite ' + this.roleUtils.roles[this.role];
this.inviteModal.okButtonLeft = false;
this.inviteModal.okButtonText = 'Send';
this.emailsForm = this.fb.array([], Validators.required);
@ -208,8 +212,8 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
this.createRoleModal.okButtonLeft = false;
this.createRoleModal.okButtonText = 'Create';
this.roleFb = this.fb.group({
name: this.fb.control(Role.roleName(this.type, this.id), Validators.required),
description: this.fb.control(Role.roleName(this.type, this.id), Validators.required)
name: this.fb.control(Role.roleName(this._type, this.id), Validators.required),
description: this.fb.control(Role.roleName(this._type, this.id), Validators.required)
});
setTimeout(() => {
this.roleFb.get('name').disable();
@ -220,7 +224,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
deleteActive() {
this.loadActive = true;
this.subs.push(this.userRegistryService.remove(this.type, this.id, this.selectedUser, this.role).subscribe(() => {
this.subs.push(this.userRegistryService.remove(this._type, this.id, this.selectedUser, this.role).subscribe(() => {
this.active = this.active.filter(user => user.email != this.selectedUser);
if (this.currentActivePage.length === 0) {
this.activePage = 1;
@ -239,13 +243,13 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
deletePending() {
this.loadPending = true;
this.subs.push(this.userRegistryService.cancelInvitation(this.type, this.id, this.selectedUser, this.role).subscribe(() => {
this.subs.push(this.userRegistryService.cancelInvitation(this._type, this.id, this.selectedUser, this.role).subscribe(() => {
this.pending = this.pending.filter(user => user != this.selectedUser);
this.filterPendingBySearch(this.filterForm.value.pending);
if (this.currentPendingPage.length === 0) {
this.pendingPage = 1;
}
NotificationHandler.rise(StringUtils.capitalize(this.stakeholderUtils.roles[this.role]) + ' invitation to ' + this.selectedUser + ' has been <b>canceled</b>');
NotificationHandler.rise(StringUtils.capitalize(this.roleUtils.roles[this.role]) + ' invitation to ' + this.selectedUser + ' has been <b>canceled</b>');
this.loadPending = false;
}, error => {
NotificationHandler.rise('An error has occurred. Please try again later', 'danger');
@ -266,7 +270,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
let current = null;
let invitations = (<Array<any>>this.emailsForm.value).map(email => {
current = email;
return this.userRegistryService.invite(this.type, this.id, {
return this.userRegistryService.invite(this._type, this.id, {
link: this.link,
email: this.emailComposer(this.name, email, this.role)
}, this.role).pipe(catchError(error => {
@ -294,7 +298,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
}
} else {
NotificationHandler.rise('An error has occurred while sending the invitation mail to ' +
response.email + '.Check if the user is already a ' + this.stakeholderUtils.roles[this.role] + ' or try again later', 'danger');
response.email + '.Check if the user is already a ' + this.roleUtils.roles[this.role] + ' or try again later', 'danger');
return of(null);
}
});
@ -309,12 +313,12 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
createGroup() {
this.loadActive = true;
this.loadPending = true;
this.userRegistryService.createRole(this.type, this.id).subscribe(() => {
this.userRegistryService.createRole(this._type, this.id).subscribe(() => {
NotificationHandler.rise('Group has been <b> successfully created</b>');
this.updateLists();
}, error => {
if(error.status === 409) {
NotificationHandler.rise('Group already exists. You can try to invite a ' + this.stakeholderUtils.roles[this.role] + ' instead.', 'warning');
NotificationHandler.rise('Group already exists. You can try to invite a ' + this.roleUtils.roles[this.role] + ' instead.', 'warning');
this.updateLists();
} else {
NotificationHandler.rise('An error has occurred. Please try again later', 'danger');
@ -337,11 +341,11 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
}
public get isManager(): boolean {
return this.isCurator || !!Session.isManager(this.type, this.id, this.user);
return this.isCurator || !!Session.isManager(this._type, this.id, this.user);
}
public get isCurator(): boolean {
return this.isPortalAdmin || !!Session.isCurator(this.type, this.user);
return this.isPortalAdmin || !!Session.isCurator(this._type, this.user);
}
public get isPortalAdmin(): boolean {

View File

@ -36,9 +36,11 @@
</div>
</div>
</div>
<div *ngIf="fos?.length" class="uk-container uk-container-large uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-slide-bottom-medium; delay: 200">
<div *ngIf="fos?.length" id="levels" class="uk-container uk-container-large uk-section"
uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-slide-bottom-medium; delay: 200">
<div class="uk-visible@m">
<div uk-sticky="offset: 50;" class="uk-sticky uk-background-default uk-padding uk-padding-remove-bottom uk-padding-remove-horizontal">
<div id="keyword_search" uk-sticky="offset: 50;" class="uk-sticky uk-background-default uk-padding uk-padding-remove-bottom uk-padding-remove-horizontal">
<div class="uk-flex uk-flex-right uk-margin-small-bottom">
<div search-input [searchControl]="keywordControl" [options]="fosOptions" iconPosition="left" placeholder="Write a key word to filter the content"
searchInputClass="border-bottom" class="uk-width-large"></div>
@ -53,11 +55,29 @@
<ul *ngIf="!keyword" class="uk-tab uk-tab-left">
<li *ngFor="let item of fos; index as i" [class.uk-active]="activeSection === item.id"
class="uk-margin-small-bottom uk-text-capitalize">
<a routerLink="./" [fragment]="item.id">{{item.id}}</a>
<a (click)="selectedParentLevels=[]" routerLink="./" [fragment]="item.id">
<div>
{{item.id}}
<ng-container *ngIf="selectedParentLevels.length > 0 && selectedParentLevels[0].id==item.id">
<div class="uk-margin-left uk-margin-xsmall-top">
<span class="uk-flex uk-flex-middle">
<icon [flex]="true" ratio="1" name="subdirectory_arrow_right"></icon>
{{selectedParentLevels[1].id}}
</span>
<div class="uk-margin-left uk-margin-xsmall-top">
<span class="uk-flex uk-flex-middle">
<icon [flex]="true" ratio="1" name="subdirectory_arrow_right"></icon>
{{selectedParentLevels[2].label}}
</span>
</div>
</div>
</ng-container>
</div>
</a>
</li>
</ul>
<ul *ngIf="keyword?.length" class="uk-tab uk-tab-left">
<li *ngFor="let item of viewResults; index as i"
<li *ngFor="let item of viewResults; index as i"
class="uk-margin-small-bottom uk-text-capitalize" [class.uk-active]="activeSection === item.id">
<a routerLink="./" [fragment]="item.id">{{item.id}}</a>
</li>
@ -91,7 +111,34 @@
</div>
</div>
<div class="uk-width-expand@m">
<ng-container *ngIf="!keyword">
<div *ngIf="!keyword && selectedParentLevels.length > 0" [id]="selectedParentLevels[0].id+'||'+selectedParentLevels[1].code+'||'+selectedParentLevels[2].code">
<a (click)="backClicked();"
class="uk-button-link uk-flex uk-flex-middle uk-margin-bottom">
<icon name="arrow_back" visuallyHidden="back" flex="true" ratio="1"></icon>
<span class="uk-margin-small-left">Back</span>
</a>
<div>
<h2 class="uk-h4 uk-text-capitalize uk-margin-remove">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(selectedParentLevels[2])"
class="uk-link-text">
{{selectedParentLevels[2].label}}
</a>
</h2>
<div class="uk-grid uk-child-width-1-3 uk-margin-large-top uk-margin-xlarge-bottom" uk-grid="masonry: false">
<div *ngFor="let level4 of selectedParentLevels[2].children">
<div class="uk-text-capitalize">
<h3 class="uk-h6 uk-margin-small-bottom">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(level4)"
class="uk-link-text">
{{level4.label}}
</a>
</h3>
</div>
</div>
</div>
</div>
</div>
<ng-container *ngIf="!keyword && selectedParentLevels.length == 0">
<div [id]="item.id" *ngFor="let item of fos; index as i">
<div class="uk-text-capitalize">
<h2 class="uk-h4 uk-margin-remove">
@ -110,12 +157,51 @@
{{child.id}}
</a>
</h3>
<div *ngFor="let subChild of child.children" style="margin-bottom: 5px;">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(subChild)"
class="uk-link-text">
{{searchFieldsHelper.getFosParameter() == 'foslabel' ? subChild.label : subChild.id}}
</a>
</div>
<!-- class="parent uk-transition-toggle" tabindex="0"-->
<div *ngFor="let subChild of child.children; let i=index" style="margin-bottom: 7px;"
class="uk-flex uk-flex-middle uk-flex-between uk-transition-toggle" tabindex="0">
<!-- <span class="uk-flex uk-flex-between">-->
<a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(subChild)"
class="uk-link-text uk-width-expand">
{{searchFieldsHelper.getFosParameter() == 'foslabel' ? subChild.label : subChild.id}}
</a>
<span *ngIf="properties.environment == 'development' && subChild.children?.length > 0" (click)="moreClicked(item, child, subChild)"
class="uk-transition-fade uk-width-auto uk-flex uk-flex-middle uk-margin-left label4 uk-text-small uk-text-meta">
<!-- <a class="view-more-less-link uk-link-text uk-text-lowercase">-->
<!-- +{{subChild.children.length}} more-->
<!--&lt;!&ndash; <icon [flex]="true" ratio="1" name="chevron_right"></icon>&ndash;&gt;-->
<!-- </a>-->
<icon [flex]="true" ratio="0.7" name="subdirectory_arrow_right"></icon>
<a class="uk-link-text uk-text-lowercase">
more
</a>
</span>
<!-- <div *ngIf="subChild.children?.length > 0" (click)="selectedParentLevels=[item, child, subChild]"-->
<!-- class="uk-flex uk-flex-middle uk-margin-left label4 uk-text-small uk-text-meta">-->
<!-- <a class="uk-link-text">{{subChild.children.length}} Subcategories</a>-->
<!-- <icon [flex]="true" ratio="1" name="chevron_right"></icon>-->
<!-- </div>-->
<!-- <span *ngIf="subChild?.children?.length > 0" (click)="fosAccordions.set(subChild.id, !fosAccordions.get(subChild.id))" class="uk-accordion-title uk-padding-remove"></span>-->
<!-- </span>-->
<!-- <div *ngIf="fosAccordions.get(subChild.id)" class="uk-margin-left">-->
<!-- <div *ngFor="let level4 of subChild.children" style="margin-bottom: 7px;">-->
<!-- <a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(level4)"-->
<!-- class="label4 uk-text-small uk-text-meta">-->
<!-- {{searchFieldsHelper.getFosParameter() == 'foslabel' ? level4.label : level4.id}}-->
<!-- </a>-->
<!-- </div>-->
<!-- </div>-->
<!-- uk-transition-slide-top-->
<!-- <div *ngIf="subChild.children?.length > 0" class="uk-transition-slide-top">-->
<!-- <div class="child">-->
<!-- <a class="uk-link uk-margin-left">{{subChild.children.length}} Subcategories ></a>-->
<!-- </div>-->
<!-- </div>-->
</div>
</div>
</div>
</div>
@ -137,10 +223,16 @@
class="uk-link-text" [innerHTML]="highlightKeyword(subItem.id)">
</a>
</h3>
<div *ngFor="let subSubItem of subItem.children" style="margin-bottom: 5px;">
<div *ngFor="let subSubItem of subItem.children" style="margin-bottom: 7px;">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(subSubItem)"
class="uk-link-text" [innerHTML]="highlightKeyword(searchFieldsHelper.getFosParameter() == 'foslabel' ? subSubItem.label : subSubItem.id)">
</a>
<div *ngFor="let level4 of subSubItem?.children" class="uk-margin-left">
<a [routerLink]="properties.searchLinkToResults" [queryParams]="buildFosQueryParam(level4)"
class="uk-text-small uk-text-meta uk-margin-xsmall-bottom" [innerHTML]="highlightKeyword(searchFieldsHelper.getFosParameter() == 'foslabel' ? level4.label : level4.id)">
</a>
</div>
</div>
</div>
</div>

View File

@ -16,6 +16,7 @@ import {debounceTime, distinctUntilChanged} from "rxjs/operators";
import Timeout = NodeJS.Timeout;
import {ISVocabulariesService} from "../utils/staticAutoComplete/ISVocabularies.service";
import {SearchFields} from "../utils/properties/searchFields";
import {HelperFunctions} from "../utils/HelperFunctions.class";
declare var UIkit;
@ -28,6 +29,8 @@ export class FosComponent implements OnInit, OnDestroy {
public url: string = null;
public pageTitle: string = "OpenAIRE | Fields of Science";
public pageDescription: string = "We have integrated a Field-of-Science (FoS) taxonomy into our dataset to organize and discover research more effectively. Using the full capabilities of the OpenAIRE Graph (full-texts, citations, references, venues) we apply AI and bring forward any multidisciplinarity potential.";
public scrollPos = 0;
public selectedParentLevels = [];
public fos: any[] = [];
public fosOptions: string[] = [];
public activeSection: string;
@ -82,21 +85,43 @@ export class FosComponent implements OnInit, OnDestroy {
item.classList.remove('uk-active');
});
if (this.route.snapshot.fragment) {
this.activeSection = this.route.snapshot.fragment;
let i = this.fos.findIndex(item => item.id == this.route.snapshot.fragment);
slider.show(i);
let splitFragment = this.route.snapshot.fragment.split("||");
this.activeSection = this.route.snapshot.fragment.split("||")[0];
let i = this.fos.findIndex(item => (item.id == this.route.snapshot.fragment || this.route.snapshot.fragment.startsWith(item.id+"||")));
if(i <0 || i>this.fos.length-1) {
this._router.navigate(['./'], {fragment: "", relativeTo: this.route, state: {disableScroll: true}});
} else {
if (splitFragment.length > 1) {
let level1 = this.fos[i];
let level2 = null;
let level3 = null;
if (level1.children) {
level2 = level1.children.find(item => item.code == splitFragment[1]);
if (level2 && level2.children) {
level3 = level2.children.find(item => item.code == splitFragment[2]);
this.selectedParentLevels = [this.fos[i], level2, level3];
}
}
if(!level2 || !level3) {
this._router.navigate(['./'], {fragment: level1.id, relativeTo: this.route, state: {disableScroll: true}});
}
} else {
slider.show(i);
}
}
} else {
this.activeSection = this.fos[0].id;
}
this.cdr.detectChanges();
});
}
this.subscriptions.push(this.route.fragment.subscribe(fragment => {
if(fragment) {
this.activeSection = fragment;
this.activeSection = fragment.split("||")[0];
if(this.tabs) {
let slider = UIkit.slider(this.tabs.nativeElement);
let i = this.fos.findIndex(item => item.id == fragment);
let i = this.fos.findIndex(item => (item.id == fragment || fragment.startsWith(item.id+"||")));
slider.show(i);
}
} else {
@ -105,13 +130,16 @@ export class FosComponent implements OnInit, OnDestroy {
}));
this.keywordControl = this.fb.control('');
this.subscriptions.push(this.keywordControl.valueChanges.pipe(debounceTime(500), distinctUntilChanged()).subscribe(value => {
this.keyword = value;
this.findMatches(this.keyword);
if (typeof IntersectionObserver !== 'undefined') {
setTimeout(() => {
this.setObserver();
});
}
if(this.keyword !== undefined || value) {
this.selectedParentLevels = [];
}
this.keyword = value;
this.findMatches(this.keyword);
if (typeof IntersectionObserver !== 'undefined') {
setTimeout(() => {
this.setObserver();
});
}
}));
});
}
@ -154,11 +182,16 @@ export class FosComponent implements OnInit, OnDestroy {
this.fos.forEach(fos => {
this.fosOptions.push(fos.id);
if(fos.children) {
fos.children.forEach(child => {
this.fosOptions.push(child.id);
if(child.children) {
child.children.forEach(child2 => {
this.fosOptions.push(child2.id);
fos.children.forEach(l2 => {
this.fosOptions.push(l2.id);
if(l2.children) {
l2.children.forEach(l3 => {
this.fosOptions.push(l3.id);
if(l3.children) {
l3.children.forEach(l4 => {
this.fosOptions.push(l4.id);
})
}
});
}
});
@ -170,19 +203,29 @@ export class FosComponent implements OnInit, OnDestroy {
this.viewResults = JSON.parse(JSON.stringify(this.fos));
let matchLevel1: boolean = false;
let matchLevel2: boolean = false;
let matchLevel3: boolean = false;
// 1st level search
if(this.viewResults.length) {
this.viewResults = this.viewResults.filter(item => {
matchLevel1 = !!item.id.includes(value?.toLowerCase());
// // 2nd level search
// 2nd level search
if(item.children?.length && !matchLevel1) {
item.children = item.children.filter(subItem => {
matchLevel2 = !!subItem.id.includes(value?.toLowerCase());
// 3rd level search
if(subItem.children?.length && !matchLevel2) {
subItem.children = subItem.children.filter(subSubItem => subSubItem.id.includes(value?.toLowerCase()));
subItem.children = subItem.children.filter(subSubItem => {
matchLevel3 = subSubItem.id.includes(value?.toLowerCase());
// 4th level search
if(subSubItem.children?.length && !matchLevel3) {
subSubItem.children = subSubItem.children.filter(level4Item => {
return level4Item.id.toLowerCase().includes(value?.toLowerCase())
});
}
return subSubItem.children?.length > 0 || matchLevel3;
});
}
return subItem.children?.length > 0 || matchLevel2;
return subItem.children?.length > 0;
});
}
return item.children?.length > 0;
@ -191,7 +234,7 @@ export class FosComponent implements OnInit, OnDestroy {
}
highlightKeyword(name) {
if(name.includes(this.keyword.toLowerCase())) {
if(name.toLowerCase().includes(this.keyword.toLowerCase())) {
return name.replace(new RegExp(this.keyword, "gi"), (matchedValue) => `<mark class="highlighted">${matchedValue}</mark>`);
} else {
return name;
@ -221,4 +264,41 @@ export class FosComponent implements OnInit, OnDestroy {
// return {'foslabel': this.urlEncodeAndQuote(fos.id+"||"+fos.label)};
return (this.searchFieldsHelper.getFosParameter() == 'foslabel' ? ({'foslabel': this.urlEncodeAndQuote(fos.id+"||"+fos.label)}) : ({'fos': this.urlEncodeAndQuote(fos.id)}));
}
public backClicked() {
let id = this.selectedParentLevels[0].id;
this.selectedParentLevels=[];
this.cdr.detectChanges();
if(this.scrollPos) {
HelperFunctions.scrollTo(0, this.scrollPos);
this._router.navigate(['./'], {fragment: id, relativeTo: this.route, state: {disableScroll: true}});
} else {
this._router.navigate(['./'], {
fragment: id,
relativeTo: this.route,
state: {disableScroll: false, behavior: 'auto'}
});
}
this.cdr.detectChanges();
if (typeof IntersectionObserver !== 'undefined') {
setTimeout(() => {
this.setObserver();
}, 200);
}
}
public moreClicked(level1, level2, level3) {
this.scrollPos = window.scrollY;
if(this.observer) {
this.observer.disconnect();
}
this.selectedParentLevels=[level1, level2, level3];
this.cdr.detectChanges();
this._router.navigate(['./'],
{fragment: this.selectedParentLevels[0].id+"||"+this.selectedParentLevels[1].code+"||"+this.selectedParentLevels[2].code,
relativeTo: this.route, state: {disableScroll: false, behavior: 'auto'}});
}
}

View File

@ -17,8 +17,8 @@ import {OpenaireEntities} from "../../utils/properties/searchFields";
</errorMessages>
<div *ngIf="fetchResults.searchUtils.status == errorCodes.DONE && !loading" class="uk-text-small">
<div class="uk-text-meta uk-margin-medium-bottom">
*Only top 100 {{openaireEntities.DATASOURCES}} that host {{openaireEntities.RESULTS}} which are also available via the Federated Research Data Repository are shown.
<div *ngIf="results.length > 90" class="uk-text-meta uk-margin-medium-bottom">
*Only top 100 {{openaireEntities.DATASOURCES}} that host {{openaireEntities.RESULTS}} which are also available via {{collectedFromName}} are shown.
</div>
<results-and-pages *ngIf="results.length >pageSize" [type]="openaireEntities.DATASOURCES"
[page]="page" [pageSize]="pageSize"

View File

@ -33,8 +33,9 @@ import {RouterHelper} from "../../utils/routerHelper.class";
</a>
</div>
<div *ngIf="properties.environment != 'production' && isMobile && (usedBy == 'landing') && availableOn[0].fulltext" class="uk-width-1-1"><hr></div><div *ngIf="availableOn[0].downloadUrl" [ngClass]="isMobile ? 'uk-width-1-1' : ''">
<div class="uk-flex uk-flex-middle" [ngClass]="isMobile ? ((usedBy == 'landing') ? 'uk-padding-small uk-padding-remove-horizontal' : '') : ''">
<div *ngIf="isMobile && (usedBy == 'landing') && availableOn[0].fulltext" class="uk-width-1-1"><hr></div>
<div *ngIf="availableOn[0].downloadUrl" [ngClass]="isMobile ? 'uk-width-1-1' : ''">
<div class="uk-flex uk-flex-middle" [ngClass]="isMobile ? ((usedBy == 'landing') ? 'uk-padding-small uk-padding-remove-horizontal' : '') : ''">
<span [class]="'uk-margin-xsmall-right ' + (availableOn[0].accessRightIcon == 'open_access' ? 'open-access' : 'closed-access')"
uk-tooltip [title]="getAccessLabel(availableOn[0].accessRight)">
<icon [name]="availableOn[0].accessRightIcon" [flex]="true" [ratio]="(isMobile && usedBy == 'landing') ? 1 : 0.8"></icon>

View File

@ -159,7 +159,7 @@ import {RouterHelper} from "../../utils/routerHelper.class";
<span>{{showInline ? projectNames.join(', ') : projectNames.slice(0, projectsLimit).join(', ')}}</span>
<span *ngIf="projects.length > projectsLimit">
<a *ngIf="!showInline" (click)="viewAllProjectsClick();" class="uk-background-muted custom-extra-entities">
+{{projects.length - projectsLimit | number}} projects
+{{projects.length - projectsLimit | number}}{{projects.length == 1000 ? ' more' : ''}} projects
</a>
<a *ngIf="showInline && lessBtn" (click)="showInline = !showInline; lessBtn = false;"
class="uk-background-muted custom-extra-entities">
@ -173,7 +173,7 @@ import {RouterHelper} from "../../utils/routerHelper.class";
<span>{{showInline ? organizationNames.join(', ') : organizationNames.slice(0, organizationsLimit).join(', ')}}</span>
<span *ngIf="organizations.length > organizationsLimit">
<a *ngIf="!showInline" (click)="viewAllPartnersClick();" class="uk-background-muted custom-extra-entities">
+{{organizations.length - organizationsLimit | number}} partners
+{{organizations.length - organizationsLimit | number}}{{organizations.length == 1000 ? ' more' : ''}} partners
</a>
<a *ngIf="showInline && lessBtn" (click)="showInline = !showInline; lessBtn = false;"
class="uk-background-muted custom-extra-entities">
@ -197,6 +197,7 @@ import {RouterHelper} from "../../utils/routerHelper.class";
<modal-alert *ngIf="!isMobile" #partnersModal>
<div *ngIf="organizations?.length == 1000" class="uk-text-meta uk-margin-medium-bottom">Only 1000 Partners<span *ngIf="resultTitle"> of {{resultTitle}}</span> are shown here.</div>
<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">
@ -207,6 +208,7 @@ import {RouterHelper} from "../../utils/routerHelper.class";
</modal-alert>
<modal-alert *ngIf="!isMobile" #projectsModal>
<div *ngIf="projects?.length == 1000" class="uk-text-meta uk-margin-medium-bottom">Only 1000 {{openaireEntities.PROJECTS}}<span *ngIf="resultTitle"> of {{resultTitle}}</span> are shown here.</div>
<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">
@ -223,6 +225,7 @@ import {RouterHelper} from "../../utils/routerHelper.class";
styleUrls: ['entity-metadata.component.less']
})
export class EntityMetadataComponent {
@Input() resultTitle: string = null;
@Input() isMobile: boolean = false;
@Input() entityType: string;
@Input() types: string[];

View File

@ -39,7 +39,7 @@ export class ParsingFunctions {
let fundedByProject: Project = {
"id": "", "acronym": "", "title": "",
"funderShortname": "", "funderName": "",
"funderShortname": "", "funderName": "", "funderJurisdiction": "",
"funding": "", "code": "", "provenanceAction": "", "validated": false
};
@ -61,8 +61,7 @@ export class ParsingFunctions {
}
if (relation.hasOwnProperty("funding")) {
let funding: { "funderName": string, "funderShortname": string, "stream": string };
funding = this.parseFundingTrees(relation.funding);
let funding = this.parseFundingTrees(relation.funding);
if (funding.funderName) {
fundedByProject['funderName'] = funding.funderName;
@ -70,6 +69,9 @@ export class ParsingFunctions {
if (funding.funderShortname) {
fundedByProject['funderShortname'] = funding.funderShortname;
}
if(funding.funderJurisdiction) {
fundedByProject['funderJurisdiction'] = funding.funderJurisdiction;
}
if (funding.stream) {
fundedByProject['funding'] = funding.stream;
}
@ -79,10 +81,11 @@ export class ParsingFunctions {
}
// publication & research data : for fundedByProjects | project landing : for funding
public parseFundingTrees(fundingTree: any): { "funderName": string, "funderShortname": string, "stream": string } {
let funding: { "funderName": string, "funderShortname": string, "stream": string } = {
public parseFundingTrees(fundingTree: any): any {
let funding: { "funderName": string, "funderShortname": string, "funderJurisdiction": string, "stream": string } = {
"funderName": "",
"funderShortname": "",
"funderJurisdiction": "",
"stream": ""
};
let length = Array.isArray(fundingTree) ? fundingTree.length : 1;
@ -93,6 +96,7 @@ export class ParsingFunctions {
if (fundingData.hasOwnProperty("funder")) {
funding.funderShortname = fundingData['funder'].shortname;
funding.funderName = fundingData['funder'].name;
funding.funderJurisdiction = fundingData['funder'].jurisdiction;
}
funding.stream = this.addFundingLevel0(fundingData, funding.stream);
@ -581,7 +585,7 @@ export class ParsingFunctions {
return eoscSubjectsFound;
}
// publication & dataset landing : for subjects and otherSubjects and classifiedSubjects
parseAllSubjects(_subjects: any, vocabulary: any): [string[], Map<string, string[]>, Map<string, string[]>, string[], string[],] {
// let eoscSubjectsFound = [];
@ -590,12 +594,12 @@ export class ParsingFunctions {
let classifiedSubjects: Map<string, string[]>;
let fos: string[];
let sdg: string[];
let setOfEoscSubjects: Set<string> = new Set();
let subject;
let length = Array.isArray(_subjects) ? _subjects.length : 1;
for (let i = 0; i < length; i++) {
subject = Array.isArray(_subjects) ? _subjects[i] : _subjects;
if (subject.classid != "") {
@ -628,7 +632,7 @@ export class ParsingFunctions {
if (classifiedSubjects == undefined) {
classifiedSubjects = new Map<string, string[]>();
}
let content: string = subject.content + "";
// let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, eoscSubjectsFound, subject, content);
// let found: boolean = checkAndAddEoscSubjectResp["found"];
@ -639,7 +643,11 @@ export class ParsingFunctions {
if (!classifiedSubjects.has(subject.classname)) {
classifiedSubjects.set(subject.classname, new Array<string>());
}
classifiedSubjects.get(subject.classname).push(content);
if(properties.environment == "production") {
classifiedSubjects.get(subject.classname).push(content);
} else {
classifiedSubjects.get(subject.classname).push(subject.classid + ": " + content);
}
// }
}
} else {
@ -659,6 +667,17 @@ export class ParsingFunctions {
}
}
}
if(properties.environment != "production" && classifiedSubjects != null) {
if (subjects == undefined) {
subjects = new Array<string>();
}
for (let classified of classifiedSubjects.keys()) {
subjects = subjects.concat(classifiedSubjects.get(classified));
}
classifiedSubjects = null;
}
return [subjects, otherSubjects, classifiedSubjects, fos, sdg];
}

View File

@ -116,7 +116,8 @@ export class ProjectsInModalComponent {
}
if (filterLimits.length > 0) {
//this.filterQuery+=' and '+filter.filterId + ' exact '+ filterLimits + ' ';
this.filterQuery += ' and ( ' + filterLimits + ' ) ';
// this.filterQuery += ' and ( ' + filterLimits + ' ) ';
this.filterQuery += '( ' + filterLimits + ' ) ';
}
}

View File

@ -488,7 +488,7 @@ export class OrganizationComponent {
let filename: string = 'funder-project-' + this.contentFileName + '-report';
this.subscriptions.push(this._searchProjectsService.getProjectsForOrganizations(this.organizationId, ' and (funder exact "' + this.encodeURI(this.funderId) + '" ) ', 1, this.funderCount, [], this.properties).subscribe(
this.subscriptions.push(this._searchProjectsService.getProjectsForOrganizations(this.organizationId, '(funder exact "' + this.encodeURI(this.funderId) + '" ) ', 1, this.funderCount, [], this.properties).subscribe(
data => {
projects = data[1];
for (let index = 0; index < projects.length; index++) {

View File

@ -28,7 +28,7 @@ import {HelperFunctions} from "../../../utils/HelperFunctions.class";
<li *ngFor="let result of results.slice((page-1)*pageSize, page*pageSize)">
<result-preview [modal]="modal" [properties]="properties" [hasLink]="false" [result]="getResultPreview(result)"
[showOrcid]="false" [prevPath]="prevPath" [showInline]="true"
[isDeletedByInferenceModal]="true"></result-preview>
[isDeletedByInferenceModal]="true" [isMobile]="isMobile"></result-preview>
</li>
</ul>
<no-load-paging *ngIf="results.length > pageSize" [type]="type"
@ -40,6 +40,7 @@ import {HelperFunctions} from "../../../utils/HelperFunctions.class";
`
})
export class DeletedByInferenceComponent {
@Input() isMobile: boolean = false;
@Input() prevPath: string = "";
public results: ResultLandingInfo[] = [];
@Input() id: string;

View File

@ -2,7 +2,9 @@
<schema2jsonld *ngIf="resultLandingInfo && resultLandingInfo.record"
[data]=resultLandingInfo.record [URL]="canonicalUrl"
[searchActionRoute]="properties.searchLinkToResults"></schema2jsonld>
<div *ngIf="resultLandingInfo && !resultLandingInfo.belongsTo" [innerHTML]="resultLandingInfo.message"
class="uk-alert uk-alert-warning uk-position-fixed uk-position-bottom-center uk-text-small" style="z-index: 1000;">
</div>
<!-- Desktop view -->
<div *ngIf="!isMobile" id="tm-main" class="landing uk-section uk-padding-remove tm-middle">
<div class="tm-main">
@ -1169,19 +1171,27 @@
<deletedByInference *ngIf="type == 'publication' && deleteByInferenceOpened"
[id]="resultLandingInfo.record['result']['header']['dri:objIdentifier']"
[ids]="resultLandingInfo.deletedByInferenceIds"
[resultType]="type" [type]="openaireEntities.PUBLICATIONS"></deletedByInference>
[resultType]="type" [type]="openaireEntities.PUBLICATIONS"
[isMobile]="isMobile"
[modal]="alertModalDeletedByInferenceFS"></deletedByInference>
<deletedByInference *ngIf="type == 'dataset' && deleteByInferenceOpened"
[id]="resultLandingInfo.record['result']['header']['dri:objIdentifier']"
[ids]="resultLandingInfo.deletedByInferenceIds"
[resultType]="'dataset'" [type]="openaireEntities.DATASETS"></deletedByInference>
[resultType]="'dataset'" [type]="openaireEntities.DATASETS"
[isMobile]="isMobile"
[modal]="alertModalDeletedByInferenceFS"></deletedByInference>
<deletedByInference *ngIf="type == 'software' && deleteByInferenceOpened"
[id]="resultLandingInfo.record['result']['header']['dri:objIdentifier']"
[ids]="resultLandingInfo.deletedByInferenceIds"
[resultType]="type" [type]="openaireEntities.SOFTWARE"></deletedByInference>
[resultType]="type" [type]="openaireEntities.SOFTWARE"
[isMobile]="isMobile"
[modal]="alertModalDeletedByInferenceFS"></deletedByInference>
<deletedByInference *ngIf="type == 'orp' && deleteByInferenceOpened"
[id]="resultLandingInfo.record['result']['header']['dri:objIdentifier']"
[ids]="resultLandingInfo.deletedByInferenceIds"
[resultType]="'other'" [type]="openaireEntities.OTHER"></deletedByInference>
[resultType]="'other'" [type]="openaireEntities.OTHER"
[isMobile]="isMobile"
[modal]="alertModalDeletedByInferenceFS"></deletedByInference>
</fs-modal>
<fs-modal *ngIf="resultLandingInfo" #citeFsModal classTitle="uk-tile-default uk-border-bottom">
@ -1192,4 +1202,4 @@
<fs-modal *ngIf="resultLandingInfo" #addThisFsModal classTitle="uk-tile-default uk-border-bottom" classBody="uk-flex uk-flex-center uk-flex-middle">
<addThis *ngIf="addThisClicked"></addThis>
</fs-modal>
</ng-container>
</ng-container>

View File

@ -1,4 +1,4 @@
import {ChangeDetectorRef, Component, ElementRef, Input, ViewChild} from '@angular/core';
import {ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, Output, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser';
@ -43,6 +43,7 @@ export class ResultLandingComponent {
@Input() type: string = "publication";
@Input() communityId = null;
@Output() result: EventEmitter<ResultLandingInfo> = new EventEmitter<ResultLandingInfo>();
enermapsId;
// @ViewChild('linkModal') linkModal;
@ViewChild('citeModal') citeModal;
@ -514,6 +515,9 @@ export class ResultLandingComponent {
this.resultLandingInfo = data;
this.id = this.resultLandingInfo.objIdentifier;
let typeId = this.identifier?.id?'pid':'id';
let id = this.identifier?.id?this.identifier.id:this.id;
this.resultLandingInfo.setBelongsTo(typeId, id);
//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.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';
@ -591,7 +595,6 @@ export class ResultLandingComponent {
this.setActiveTab();
this.cdr.detectChanges();
if (contexts) {
if (this.communityId && this.communityId == "enermaps" && properties.enermapsURL) {
this.enermapsId = ParsingFunctions.getEnermapsConceptId(contexts);

View File

@ -221,6 +221,11 @@ export class COOKIE {
}
}
class Roles {
manager = 'manager';
member = 'member';
}
export class Role {
public static GROUP = '';
public static PORTAL_ADMIN = 'PORTAL_ADMINISTRATOR';
@ -228,6 +233,7 @@ export class Role {
public static ANONYMOUS_USER = 'ROLE_ANONYMOUS';
public static USER_MANAGER = 'USER_MANAGER';
public static CURATOR_CLAIM = 'CURATOR_CLAIM';
public static ROLES: Roles = new Roles();
public static roleName(type: string, id: string) {
return this.GROUP + this.mapType(type) + '.' + id;
@ -285,3 +291,10 @@ export class Role {
return this.mapType(type, false).toUpperCase() + "_" + id.toUpperCase();
}
}
export class RoleUtils {
get roles() {
return Role.ROLES;
}
}

View File

@ -181,19 +181,6 @@
class="uk-text-center uk-text-bold uk-margin-small-bottom">
{{ indicator.name }}
</div>
<div *ngIf="indicator.indicatorPaths.length > 1" class="uk-margin-medium-bottom">
<ul class="uk-subnav uk-subnav-pill uk-subnav-small">
<li *ngFor="let indicatorPath of indicator.indicatorPaths; let i=index"
class="uk-flex uk-margin-small-top"
[class.uk-active]="(!indicator.activePath && i == 0) || indicator.activePath === i">
<a (click)="indicator.activePath = i">
<span>
{{ indicatorPath.parameters.title ? indicatorPath.parameters.title : '--' }}
</span>
</a>
</li>
</ul>
</div>
<iframe *ngIf="!properties.disableFrameLoad && getActiveIndicatorPath(indicator) && getActiveIndicatorPath(indicator).source !=='image' &&
safeUrls.get(indicatorUtils.getFullUrl(stakeholder, getActiveIndicatorPath(indicator)))"
allowfullscreen="true" mozallowfullscreen="true"
@ -213,6 +200,13 @@
[ngClass]="'uk-height-' + (indicator.height?indicator.height.toLowerCase():'medium')"
[src]="getActiveIndicatorPath(indicator).url">
</div>
<slider-tabs *ngIf="indicator.indicatorPaths.length > 1" [type]="'dynamic'" [flexPosition]="'right'" (activeEmitter)="indicator.activePath = $event"
tabsClass="uk-subnav uk-subnav-pill uk-subnav-small" containerClass="uk-margin-top uk-margin-bottom" [border]="false">
<slider-tab *ngFor="let indicatorPath of indicator.indicatorPaths; let i=index"
[tabTitle]="indicatorPath.parameters.tab ? indicatorPath.parameters.tab : indicatorPath.parameters.title"
[tabId]="i" [active]="(!indicator.activePath && i == 0) || indicator.activePath == i">
</slider-tab>
</slider-tabs>
</div>
</div>
</div>
@ -483,7 +477,7 @@
class="uk-visible-toggle uk-flex uk-margin-small-top" transition-group-item
[class.uk-active]="(!indicator.activePath && i == 0) || indicator.activePath === i">
<a (click)="activeChartIndicatorPath(i)">
<span>{{ getParameter(i, 'title')?.get('value')?.value ? getParameter(i, 'title').get('value').value : 'No title yet' }}</span>
<span>{{ getParameter(i, 'tab')?.get('value')?.value ? getParameter(i, 'tab').get('value').value : 'No title yet' }}</span>
</a>
<span *ngIf="!indicator.defaultId && chartIndicatorPaths.length > 1"
class="uk-flex uk-flex-column uk-flex-center uk-margin-small-left"
@ -548,6 +542,9 @@
</div>
<div class="uk-width-1-1" formArrayName="parameters">
<div class="uk-grid" uk-grid>
<div *ngIf="stakeholderUtils.hasMultiChartIndicatorPaths && getParameter(i, 'tab')" input class="uk-width-1-1"
[formInput]="getParameter(i, 'tab').get('value')"
placeholder="Tab Title"></div>
<div *ngIf="getParameter(i, 'title')" input class="uk-width-1-1"
[formInput]="getParameter(i, 'title').get('value')"
placeholder="Chart Title"></div>

View File

@ -668,6 +668,9 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple
if(!indicatorPath.parameters.statsProfile) {
indicatorPath.parameters.statsProfile = null;
}
if(!indicatorPath.parameters.tab) {
indicatorPath.parameters.tab = indicatorPath.parameters.title;
}
Object.keys(indicatorPath.parameters).forEach(key => {
if (this.indicatorUtils.ignoredParameters.indexOf(key) === -1) {
if (this.indicatorUtils.parametersValidators.has(key)) {

View File

@ -222,10 +222,6 @@
[queryParams]="{view: 'RESTRICTED'}"
(click)="hide(element)">Restricted view</a>
</li>
<!--<li class="disabled"><a class="uk-disabled uk-text-muted"
uk-tooltip="Note: available only in administration dashboard"
(click)="hide(element)">Private view</a>
</li>-->
</ul>
</div>
</div>

View File

@ -242,18 +242,30 @@ export class TopicComponent extends StakeholderBaseComponent implements OnInit,
}
topicChanged(callback: Function, save: boolean = false) {
if(this.topics && save) {
this.topics.disable();
}
if(this.categories) {
this.categories.disable();
}
if(this.subCategories) {
this.subCategories.disable();
}
if(callback) {
callback();
}
this.cdr.detectChanges();
if(this.topics && save) {
this.topics.init();
this.topics.enable();
}
if(this.categories) {
this.categories.init();
this.categories.enable();
}
if(this.subCategories) {
this.subCategories.init();
this.subCategories.enable();
}
}
@ -378,15 +390,23 @@ export class TopicComponent extends StakeholderBaseComponent implements OnInit,
}
categoryChanged(callback: Function, save: boolean = false) {
if(this.categories && save) {
this.categories.disable();
}
if(this.subCategories) {
this.subCategories.disable();
}
if(callback) {
callback();
}
this.cdr.detectChanges();
if(this.categories && save) {
this.categories.init();
this.categories.enable();
}
if(this.subCategories) {
this.subCategories.init();
this.subCategories.enable();
}
}
@ -512,12 +532,16 @@ export class TopicComponent extends StakeholderBaseComponent implements OnInit,
}
subCategoryChanged(callback: Function, save: boolean = false) {
if(this.subCategories && save) {
this.subCategories.disable();
}
if(callback) {
callback();
}
this.cdr.detectChanges();
if(this.subCategories && save) {
this.subCategories.init();
this.subCategories.enable();
}
}

View File

@ -7,21 +7,14 @@ import {
IndicatorPathType,
IndicatorType,
SourceType,
Stakeholder, SubCategory,
Topic,
Stakeholder,
Visibility,
} from "../../monitor/entities/stakeholder";
import {AbstractControl, ValidatorFn, Validators} from "@angular/forms";
import {Option} from "../../sharedComponents/input/input.component";
import {Session} from "../../login/utils/helper.class";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {properties} from "src/environments/environment";
class Roles {
manager = 'manager';
member = 'member';
}
class Entities {
stakeholder = 'Dashboard';
funder = 'Funder';
@ -41,8 +34,13 @@ class Entities {
researchers = 'Researchers';
}
export interface OAIndicator {
numerator: IndicatorPath;
denominator: IndicatorPath;
}
export class StakeholderConfiguration {
public static ROLES: Roles = new Roles();
public static ENTITIES: Entities = new Entities();
public static TYPES: Option[] = [
{value: 'funder', label: StakeholderConfiguration.ENTITIES.funder},
@ -63,13 +61,10 @@ export class StakeholderConfiguration {
public static CACHE_INDICATORS: boolean = true;
public static NUMBER_MULTI_INDICATOR_PATHS = false;
public static CHART_MULTI_INDICATOR_PATHS = true;
public static openAccess: Map<string, OAIndicator> = new Map();
}
export class StakeholderUtils {
get roles() {
return StakeholderConfiguration.ROLES;
}
get entities() {
return StakeholderConfiguration.ENTITIES;
}
@ -102,6 +97,10 @@ export class StakeholderUtils {
return StakeholderConfiguration.CHART_MULTI_INDICATOR_PATHS;
}
get openAccess(): Map<string, OAIndicator> {
return StakeholderConfiguration.openAccess;
}
visibilityIcon: Map<Visibility, string> = new Map<Visibility, string>(this.visibilities.map(option => [option.value, option.icon]));
defaultValue(options: Option[]) {
@ -988,6 +987,7 @@ export class IndicatorUtils {
obj[this.getDescriptionObjectName(obj)]["options"]["title"] = ChartHelper.prefix + "title" + ChartHelper.suffix;
}
indicatorPath.parameters["title"] = title ? title : "";
indicatorPath.parameters["tab"] = title ? title : "";
}
private extractSubTitle(obj, indicatorPath: IndicatorPath) {

View File

@ -0,0 +1,113 @@
import {ChangeDetectorRef, Directive, OnInit} from "@angular/core";
import {StakeholderBaseComponent} from "../../monitor-admin/utils/stakeholder-base.component";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {StakeholderType} from "../entities/stakeholder";
import {Option} from "../../sharedComponents/input/input.component";
import {FormBuilder, FormControl} from "@angular/forms";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {debounceTime, distinctUntilChanged} from "rxjs/operators";
@Directive()
export class BrowseStakeholderBaseComponent<T> extends StakeholderBaseComponent implements OnInit {
openaireEntities = OpenaireEntities;
stakeholderType: StakeholderType;
stakeholders: T[] = [];
filteredStakeholders: T[] = [];
showLoading: boolean = true;
isMobile: boolean = false;
gridView: boolean = true;
sortOptions: Option[] = [
{value: 'alphAsc', label: 'Alphabetically Asc. (A-Z)'},
{value: 'alphDsc', label: 'Alphabetically Dsc. (Z-A)'},
];
pageOptions: number[] = [10, 20, 30, 40];
sortBy: string = null;
currentPage: number = 1;
pageSize: number = 10;
parameters = {};
keywordControl: FormControl;
hasPublications: boolean = true;
/* Services */
protected layoutService: LayoutService;
protected cdr: ChangeDetectorRef;
protected fb: FormBuilder;
constructor() {
super();
}
ngOnInit() {
this.keywordControl = this.fb.control(this._route.snapshot.queryParams.keyword);
this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
this.cdr.detectChanges();
}));
this.stakeholderType = this._route.snapshot.data.type;
if (!this.stakeholderType) {
this.navigateToError();
}
this.init();
this.subscriptions.push(this.keywordControl.valueChanges.pipe(debounceTime(200), distinctUntilChanged()).subscribe(value => {
this.filtering(value);
if (value?.length > 0) {
this.parameters['keyword'] = value;
} else {
delete this.parameters['keyword']
}
this._router.navigate([], {queryParams: this.parameters});
}));
}
init() {
this.stakeholders = [];
this.filteredStakeholders = [];
}
protected filtering(value) {
if (!value) {
this.filteredStakeholders = this.stakeholders;
} else {
this.filteredStakeholders = this.stakeholders.filter(item => (item['name'] && item['name'].toLowerCase().includes(value.toLowerCase())) || (item['alias'] && item['alias'].toLowerCase().includes(value.toLowerCase())));
}
this.afterStakeholdersInitialized();
this.currentPage = 1;
}
sortByChanged() {
switch (this.sortBy) {
case 'alphAsc':
this.stakeholders = this.stakeholders.sort((a, b) => a['name'].localeCompare(b['name']));
break;
case 'alphDsc':
this.stakeholders = this.stakeholders.sort((a, b) => b['name'].localeCompare(a['name']));
break;
default:
break;
}
}
sizeChanged($event) {
this.pageSize = $event;
this.currentPage = 1;
this.afterStakeholdersInitialized();
}
updateCurrentPage($event) {
this.currentPage = $event.value;
HelperFunctions.scrollToId('target');
this.afterStakeholdersInitialized();
}
get typeAsLabel() {
return this.stakeholderUtils.types.find(type => type.value === this.stakeholderType).label;
}
afterStakeholdersInitialized() {
// this is a method that will be overriden from the components extending this base component, if needed
this.showLoading = false;
}
}

View File

@ -207,7 +207,7 @@ export class IndicatorPath {
type: IndicatorPathType;
source: SourceType;
url: string;
safeResourceUrl: SafeResourceUrl; // initialize on front end
safeResourceUrl?: SafeResourceUrl; // initialize on front end
jsonPath: string[];
chartObject: string;
parameters: any;

View File

@ -1,5 +1,5 @@
import {AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, ViewChild} from "@angular/core";
import {Role, User} from "../login/utils/helper.class";
import {Role, RoleUtils, User} from "../login/utils/helper.class";
import {ActivatedRoute, Router} from "@angular/router";
import {UserManagementService} from "../services/user-management.service";
import {UserRegistryService} from "../services/user-registry.service";
@ -21,7 +21,7 @@ import {StringUtils} from "../utils/string-utils.class";
<modal-alert #managerModal [overflowBody]="false" (alertOutput)="verifyManager()" (cancelOutput)="cancel()"
[okDisabled]="code.invalid || loading">
<div>
You have been invited to join <span class="uk-text-bold">{{name}}</span> {{(dashboard)}} Dashboard as a {{stakeholderUtils.roles.manager}}.
You have been invited to join <span class="uk-text-bold">{{name}}</span> {{(dashboard)}} Dashboard as a {{roleUtils.roles.manager}}.
<span class="uk-text-primary">Fill</span> in the <span class="uk-text-primary">verification code</span>, sent to
your email, to accept the invitation request.
</div>
@ -38,7 +38,7 @@ import {StringUtils} from "../utils/string-utils.class";
(alertOutput)="verifyMember()" [okDisabled]="(code.invalid || loading)">
<div>
<div>
You have been invited to join <span class="uk-text-bold">{{name}}</span> {{(dashboard)}} Dashboard as a {{stakeholderUtils.roles.member}}.
You have been invited to join <span class="uk-text-bold">{{name}}</span> {{(dashboard)}} Dashboard as a {{roleUtils.roles.member}}.
<span class="uk-text-primary">Fill</span> in the <span class="uk-text-primary">verification code</span>, sent
to your email, to accept the invitation request.
</div>
@ -73,7 +73,7 @@ export class RoleVerificationComponent extends BaseComponent implements OnInit,
public id: string;
@Input()
set type(type: string) {
this._type = Role.GROUP + type;
this._type = Role.GROUP + Role.mapType(type);
}
@Input()
public name: string;
@ -98,6 +98,7 @@ export class RoleVerificationComponent extends BaseComponent implements OnInit,
public error: string = null;
public loading: boolean = false;
public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
public roleUtils: RoleUtils = new RoleUtils();
constructor(protected _route: ActivatedRoute,
protected _router: Router,
@ -173,7 +174,7 @@ export class RoleVerificationComponent extends BaseComponent implements OnInit,
this.managerModal.okButtonText = 'Accept';
this.managerModal.stayOpen = true;
this.managerModal.cancelButtonText = 'Cancel';
this.managerModal.alertTitle = StringUtils.capitalize(this.stakeholderUtils.roles.manager) + ' Invitation';
this.managerModal.alertTitle = StringUtils.capitalize(this.roleUtils.roles.manager) + ' Invitation';
this.managerModal.open();
}
@ -184,7 +185,7 @@ export class RoleVerificationComponent extends BaseComponent implements OnInit,
this.memberModal.okButtonLeft = false;
this.memberModal.stayOpen = true;
this.memberModal.cancelButtonText = 'Cancel';
this.memberModal.alertTitle = StringUtils.capitalize(this.stakeholderUtils.roles.member) + ' Invitation';
this.memberModal.alertTitle = StringUtils.capitalize(this.roleUtils.roles.member) + ' Invitation';
this.cdr.detectChanges();
this.memberModal.open();
}

View File

@ -33,6 +33,7 @@ import {RefineFieldResultsService} from "../services/refineFieldResults.service"
[includeOnlyResultsAndFilter]="includeOnlyResultsAndFilter"
[searchForm]="searchForm"
[sort]="false"
[showRefine]="refineFields?.length > 0"
[filters]="filters"
[simpleView]="simpleView" formPlaceholderText="Search by organization name..."
[showSwitchSearchLink]="showSwitchSearchLink"

View File

@ -5,7 +5,7 @@
<ng-container *ngFor="let customFilter of customFilters">
<ng-container *ngIf="customFilter.isHiddenFilter">
<li class="uk-flex uk-flex-middle">
<span class="uk-text-capitalize uk-label uk-label-small uk-label-search-filter uk-text-truncate target1">
<span class="uk-text-capitalize uk-label uk-label-small uk-label-secondary uk-text-truncate target1">
{{customFilter.valueName}}
</span>
</li>
@ -15,7 +15,7 @@
<ng-container *ngFor="let type of resultTypes.values; let i = index;">
<ng-container *ngIf="type.selected">
<li class="">
<span class="uk-text-capitalize uk-label uk-label-small uk-label-search-filter uk-flex uk-flex-middle target2">
<span class="uk-text-capitalize uk-label uk-label-small uk-label-secondary uk-flex uk-flex-middle target2">
<span class="uk-margin-small-right uk-width-expand uk-text-truncate">{{type.name}}</span>
<button [class.uk-disabled]="disabled" (click)="removeResultType(type.id)" class="uk-close uk-icon" [disabled]="disabled">
<icon name="close" flex="true" ratio="0.7"></icon>
@ -29,7 +29,7 @@
<ng-container *ngFor="let filter of rangeFilters ">
<ng-container *ngIf="filter.selectedFromAndToValues">
<li class="">
<span class="uk-text-capitalize uk-label uk-label-small uk-label-search-filter uk-flex uk-flex-middle target3">
<span class="uk-text-capitalize uk-label uk-label-small uk-label-secondary uk-flex uk-flex-middle target3">
<span class="uk-margin-small-right uk-width-expand uk-text-truncate">{{filter.selectedFromAndToValues}}</span>
<button [class.uk-disabled]="disabled" (click)="removeRangeFilter(filter)" class="uk-close uk-icon" [disabled]="disabled">
<icon name="close" flex="true" ratio="0.7"></icon>
@ -44,7 +44,7 @@
<ng-container *ngFor="let value of getSelectedValues(filter); let i = index; let end = last; ">
<li *ngIf="!customFilter || (customFilter.isHiddenFilter && customFilter.valueId != value.id)"
class="">
<span class="uk-text-capitalize uk-label uk-label-small uk-label-search-filter uk-flex uk-flex-middle target4">
<span class="uk-text-capitalize uk-label uk-label-small uk-label-secondary uk-flex uk-flex-middle target4">
<span
class="uk-margin-small-right uk-width-expand uk-text-truncate">
<ng-container *ngIf="filter.type && (filter.type == 'boolean' || filter.type == 'triplet') else noboolean">
@ -73,7 +73,7 @@
<ng-container *ngIf="filter.countSelectedValues > 0">
<ng-container *ngFor="let value of getSelectedValues(filter); let i = index; let end = last; ">
<li *ngIf="!customFilters || (customFilters[0].isHiddenFilter && customFilters[0].valueId != value.id)">
<span class="uk-text-capitalize uk-label uk-label-small uk-label-search-filter uk-flex uk-flex-middle target5">
<span class="uk-text-capitalize uk-label uk-label-small uk-label-secondary uk-flex uk-flex-middle target5">
<span class="uk-margin-small-right uk-width-expand uk-text-truncate">
<ng-container *ngIf="filter.type && (filter.type == 'boolean' || filter.type == 'triplet') else noboolean">
<span>{{filter.title}}:
@ -288,8 +288,14 @@
</div>
<div class="uk-container uk-margin-top" [class.uk-container-large]="!mobile" [class.uk-container-expand]="mobile" [class.uk-padding-remove-horizontal]="mobile">
<div class="uk-grid uk-margin-large-bottom" [class.uk-margin-top]="!mobile" uk-grid>
<div *ngIf="!mobile && showRefine && (searchUtils.refineStatus == errorCodes.DONE && ((orderedFilters && orderedFilters.length > 0) || (staticFilters && staticFilters.length > 0)
|| (rangeFilters && rangeFilters.length > 0) || (filters && filters.length > 0)))
<!-- <div *ngIf="!mobile && showRefine -->
<!-- && (searchUtils.refineStatus == errorCodes.DONE && ((orderedFilters && orderedFilters.length > 0) || (staticFilters && staticFilters.length > 0)-->
<!-- || (rangeFilters && rangeFilters.length > 0) || (filters && filters.length > 0)))-->
<!-- && (results.length > 0 || (searchUtils.refineStatus == errorCodes.LOADING && searchUtils.status != errorCodes.LOADING) || (!hideFilters &&-->
<!-- (existingFiltersWithValues > 0 || (selectedRangeFilters + selectedFilters + selectedTypesNum) > 0))) "-->
<!-- class="uk-width-1-4@m search-filters">-->
<!-- </div>-->
<div *ngIf="!mobile && showRefine
&& (results.length > 0 || (searchUtils.refineStatus == errorCodes.LOADING && searchUtils.status != errorCodes.LOADING) || (!hideFilters &&
(existingFiltersWithValues > 0 || (selectedRangeFilters + selectedFilters + selectedTypesNum) > 0))) "
class="uk-width-1-4@m search-filters">

View File

@ -78,7 +78,7 @@ export class SearchResultComponent implements OnInit, OnChanges {
// console.debug(i, this.previewResults[i].orcidPutCodes);
}
}
// this.previewResults = JSON.parse(JSON.stringify(this.previewResults, this.replacer), this.reviver);
this.previewResults = JSON.parse(JSON.stringify(this.previewResults, this.replacer), this.reviver);
}, error => {
}

View File

@ -95,7 +95,7 @@ export class OrganizationService {
}
}
if(organization['pid'] && properties.environment != "production") {
if(organization['pid']) {
this.organizationInfo.identifiers = this.parsingFunctions.parseIdentifiers(organization['pid']);
}
}

View File

@ -100,13 +100,16 @@ export class SearchOrganizationsService {
result['title'] = {"name": '', "accessMode": ''};
if(resData.legalshortname) {
result['title'].name = StringUtils.HTMLToString(String(resData.legalshortname));
}
if(!result['title'].name || result['title'].name == '') {
if(resData.legalname) {
result['title'].name = StringUtils.HTMLToString(String(resData.legalname));
} else {
result['title'].name = "";
}
if(resData.legalshortname) {
result['acronym'] = StringUtils.HTMLToString(String(resData.legalshortname));
}
//result['title'].url = OpenaireProperties.getsearchLinkToOrganization();
//result['title'].url += Array.isArray(data) ? data[i]['result']['header']['dri:objIdentifier'] : data['result']['header']['dri:objIdentifier'];
result['id'] = Array.isArray(data) ? data[i]['result']['header']['dri:objIdentifier'] : data['result']['header']['dri:objIdentifier'];
@ -175,7 +178,7 @@ export class SearchOrganizationsService {
result.country = resData.country.classname;
}
if(resData['pid'] && properties.environment != "production") {
if(resData['pid']) {
result.identifiers = this.parsingFunctions.parseIdentifiers(resData['pid']);
}

View File

@ -34,14 +34,15 @@ export class SearchProjectsService {
}
getProjectsforDataProvider (datasourceId: string, page: number, size: number, properties:EnvProperties ):any {
let url = properties.searchResourcesAPIURL;
var basicQuery = "(oaftype exact project) "
var basicQuery = "(oaftype exact project) ";
var filterQuery = "&fq=(projectcode<>\"unidentified\")";
url += "?query=";
if(datasourceId!= null && datasourceId != '' ) {
url +=" ( "+basicQuery+ " ) " +" and (collectedfromdatasourceid exact \"" + datasourceId + "\" or resulthostingdatasourceid exact \""+ datasourceId + "\")";
}else{
url +=" ( "+basicQuery+ " ) ";
}
url += filterQuery;
url += "&page="+(page-1)+"&size="+size;
url += "&format=json";
@ -53,6 +54,7 @@ export class SearchProjectsService {
// &type=projects
let url = properties.searchAPIURLLAst+"resources2/?format=json";
// var basicQuery = "(oaftype exact project) "
var basicQuery = "&fq=(projectcode<>\"unidentified\")";
// url += "?query=";
if(params!= null && params != '' ) {
url +="&query=(" + params + ")";
@ -66,6 +68,8 @@ export class SearchProjectsService {
if(refineQuery) {
url += "&" + refineQuery;
}
// url += "&fq="+basicQuery;
url += basicQuery;
url += "&page="+(page-1)+"&size="+size;
url += minRef ? "&minRef=true" : "";
@ -80,11 +84,15 @@ export class SearchProjectsService {
let url = properties.searchResourcesAPIURL;
var basicQuery = "(oaftype exact project) "
url += "?query=";
if(filterquery!= null && filterquery != '' ) {
url +="( ( "+basicQuery+ " ) and (relorganizationid exact \"" + organizationId + "\")"+" " + filterquery + ")";
}else{
// if(filterquery!= null && filterquery != '' ) {
// url +="( ( "+basicQuery+ " ) and (relorganizationid exact \"" + organizationId + "\")"+" " + filterquery + ")";
// }else{
url +=" (( "+basicQuery+ " ) " +" and (relorganizationid exact \"" + organizationId + "\"))";
// }
if(filterquery) {
url += "&fq=" + filterquery;
}
url += "&fq=(projectcode<>\"unidentified\")";
if(refineFields!= null && refineFields.length > 0 ) {
url +="&refine=true";
for(let i=0; i< refineFields.length ; i++ ){
@ -304,6 +312,8 @@ export class SearchProjectsService {
if(refineParams!= null && refineParams != '' ) {
url += refineParams;
}
url += "&fq=(projectcode<>\"unidentified\")";
return this.http.get((properties.useCache)? (properties.cacheUrl+encodeURIComponent(url)): url)
.pipe(map(res => res['meta']['total']));
}

View File

@ -0,0 +1,7 @@
import {ActivatedRouteSnapshot, BaseRouteReuseStrategy} from "@angular/router";
export class CustomRouteReuseStrategy extends BaseRouteReuseStrategy {
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.routeConfig === curr.routeConfig || (!!future.routeConfig?.component && future.routeConfig?.component === curr.routeConfig?.component)
}
}

View File

@ -58,15 +58,22 @@ export class AdvancedSearchInputComponent implements AfterContentInit, OnDestroy
}
ngAfterContentInit() {
this.inputs.forEach(input => {
input.inputClass = 'advanced-search';
input.selectArrow = null;
this.init();
this.inputs.changes.subscribe(input => {
this.init();
});
}
ngOnDestroy() {
}
init() {
this.inputs.forEach(input => {
input.inputClass = 'advanced-search';
input.selectArrow = null;
});
}
focusNext(input: InputComponent | EntitiesSelectionComponent, event: any = null) {
if(!event || !event.init) {
setTimeout(() => {

View File

@ -101,7 +101,7 @@
<li><a
[href]="'https://'+(properties.environment =='beta' || properties.environment =='development'?'beta.':'')+'monitor.openaire.eu'"
target="_blank">Monitor</a></li>
<li><a href="https://graph.openaire.eu/develop/" target="_blank">Develop</a></li>
<li><a href="'https://'+(properties.environment =='beta' || properties.environment =='development'?'beta.':'')+'develop.openaire.eu" target="_blank">Develop</a></li>
</ul>
</div>
</div>

View File

@ -829,7 +829,6 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
resetValue(event: any) {
event.stopPropagation();
console.log(1)
this.formControl.setValue('');
this.focus(true, event);
}

View File

@ -9,7 +9,7 @@ export class SliderTabComponent {
@Input("tabTitle")
public title: string;
@Input("tabId")
public id: string;
public id: string | number;
@Input()
public active: boolean = false;
@Input()

View File

@ -143,7 +143,7 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
/**
* Notify regarding new active element
* */
@Output() activeEmitter: EventEmitter<string> = new EventEmitter<string>();
@Output() activeEmitter: EventEmitter<string | number> = new EventEmitter<number>();
private activeIndex: number = 0;
private subscriptions: any[] = [];
private observer: IntersectionObserver;
@ -235,7 +235,7 @@ export class SliderTabsComponent implements AfterViewInit, OnDestroy {
});
}, {threshold: 0.1});
this.tabs.forEach(tab => {
let element = document.getElementById(tab.id);
let element = document.getElementById(tab.id.toString());
if (element) {
this.observer.observe(element);
}

View File

@ -19,7 +19,7 @@ import {properties} from "../../../../environments/environment";
@Component({
selector: 'showAuthors',
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" let-modal="modal">
<span *ngIf="isSticky || (!author.orcid && !author.orcid_pending) || !isBrowser" style="margin-right: 5px;"
[class.uk-text-italic]="italic">
{{author.fullName + ";"}}
@ -36,7 +36,7 @@ import {properties} from "../../../../environments/environment";
</span>
</a>
<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;" [attr.container]="!modal ? '#modal-container' : true">
uk-dropdown="mode:click; offset: 4; pos: bottom-right" style="min-width: 465px !important;" [attr.container]="'#modal-container'">
<ng-container *ngTemplateOutlet="dropdown"></ng-container>
</div>
<mobile-dropdown *ngIf="isMobile" [toggle]="toggle">
@ -112,7 +112,7 @@ import {properties} from "../../../../environments/environment";
</span>
<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>
*ngTemplateOutlet="author_template; context: { author: author, i:i, italic: true, modal: modal}"></ng-container>
</ng-container>
<span *ngIf="!showAll && authors && authors.length > authorsLimit" class="uk-text-meta">
+{{authors.length - authorsLimit | number}} more
@ -127,18 +127,18 @@ import {properties} from "../../../../environments/environment";
</div>
</div>
<modal-alert *ngIf="!isMobile" #authorsModal>
<modal-alert *ngIf="!isMobile && showAll && authors && authors.length > authorsLimit" #authorsModal>
<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 *ngTemplateOutlet="author_template; context: { author: author, i:i}"></ng-container>
<ng-container *ngTemplateOutlet="author_template; context: { author: author, i:i, modal: authorsModal}"></ng-container>
</ng-container>
</div>
</modal-alert>
<fs-modal *ngIf="isMobile" #authorsModal classTitle="uk-tile-default uk-border-bottom">
<fs-modal *ngIf="isMobile && showAll && authors && authors.length > authorsLimit" #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>
<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, modal: authorsModal}"></ng-container>
</ng-container>
</div>
</fs-modal>
@ -170,10 +170,24 @@ export class ShowAuthorsComponent {
ngOnInit() {}
ngOnDestroy() {
if(typeof document !== 'undefined') {
let modal_container = document.getElementById("modal-container");
modal_container.childNodes.forEach(c=> {
if (c['className'] && c['className'].includes("orcid-dropdown")) {
modal_container.removeChild(c);
}
});
}
}
public onClick() {
if (this.modal) {
this.modal.cancel();
}
if(this.authorsModal) {
this.authorsModal.cancel();
}
}
public viewAllClick() {

View File

@ -1,7 +1,7 @@
import {Email} from "./email";
import {Body} from "./body";
import {properties} from "../../../../environments/environment";
import {User} from "../../login/utils/helper.class";
import {Role, User} from "../../login/utils/helper.class";
import {StakeholderConfiguration} from "../../monitor-admin/utils/indicator-utils";
export class Composer {
@ -33,7 +33,7 @@ export class Composer {
email.subject = this.subjectPrefix + communityName + ": Welcome new manager";
email.body = "<div style='font-size:" + this.noteBodySize + "'><p>Welcome to OpenAIRE Connect!</p>"
+ "<p>You are receiving this e-mail as you were assigned as manager of the <a href='https://beta."
+ "<p>You are receiving this e-mail as you were assigned as " + Role.ROLES['manager'] + " of the <a href='https://beta."
+ communityId + ".openaire.eu/'>" + communityName + "</a> gateway. "
+ "In order to access the administration section of your community you must first login using one of the available options. "
+ "<br>The administrative rights are associated with the e-mail address that was used to send you this message."
@ -108,6 +108,20 @@ export class Composer {
return email;
}
public static composeEmailForDevelopPersonalInfo(user: User): Email {
let email: Email = new Email();
email.subject = "Welcome to The OpenAIRE API mailing list";
email.body = "<div style='font-size:" + this.noteBodySize + "'>"
+ "<p>Dear " + user.fullname + ",</p>"
+ "<p>As a user of the OpenAIRE APIs, you are a member of the openaire-api mailing list. " +
" We will use this list to inform you of relevant news and updates. If you wish to unsubscribe, " +
" please send an email to the list admin at <a href='mailto:gbikas@openaire.eu'>gbikas@openaire.eu</a> " +
" and <a href='mailto:stefania.amodeo@openaire.eu'>stefania.amodeo@openaire.eu</a>.</p>"
+ "<p>The OpenAIRE Graph team</p>";
email.recipients = [user.email];
return email;
}
public static composeEmailForDevelop(contactForm: any, admins: any, user: User): Email {
let email: Email = new Email();
email.subject = "OpenAIRE - Develop [" + properties.environment.toUpperCase() + "]";
@ -315,9 +329,9 @@ export class Composer {
'<p>The verification code is <b>((__code__))</b>.</p>' +
'<p>By logging in and using the service you accept and agree to the <a href="' + pdppLink + '" target="_blank">OpenAIRE personal data protection policy</a>.</p>' +
(role === "manager"?
'<p>As a manager of the OpenAIRE Monitor Dashboard, you will have access to the administration part of the dashboard, ' +
'<p>As a ' + Role.ROLES[role] + ' of the OpenAIRE Monitor Dashboard, you will have access to the administration part of the dashboard, ' +
'where you will be able to customize and manage the profile of the ' + name + '.</p>':
'<p>As a member of the OpenAIRE Monitor Dashboard, you will have access to the restricted access areas of the profile for the ' + name + '.') +
'<p>As a ' + Role.ROLES[role] + ' of the OpenAIRE Monitor Dashboard, you will have access to the restricted access areas of the profile for the ' + name + '.') +
'<p>Please contact us at <a href="mailto:' + properties.helpdeskEmail+'">' + properties.helpdeskEmail +
'</a> if you have any questions or concerns.</p>' +
'<p>Kind Regards<br>The OpenAIRE Team</p>' +
@ -336,13 +350,13 @@ export class Composer {
email.subject = 'National Open Access Monitor Ireland | ' + name;
email.recipient = recipient;
email.body = '<p>Dear user,</p>' +
'<p>You have been invited to be a ' + StakeholderConfiguration.ROLES[role] +' of the for the National Open Access Monitor, Ireland dashboard for the ' + name + '.</p>' +
'<p>You have been invited to be a ' + Role.ROLES[role] +' of the for the National Open Access Monitor, Ireland dashboard for the ' + name + '.</p>' +
'<p>Click <a href="((__link__))" target="_blank">this URL</a> and use the verification code below to accept the invitation.</p>' +
'<p>The verification code is <b>((__code__))</b>.</p>' +
'<p>At your first sign in you will be asked to accept and consent to the "OpenAIRE Personal Data Protection Policy and Consent Form" to be able to use the service.</p>' +
(role === "manager"?
'<p>As a ' + StakeholderConfiguration.ROLES[role] + ' of the National Open Access Monitor, Ireland, you will have access to the administration part of the dashboard, where you will be able to also invite other users to become ' + StakeholderConfiguration.ROLES['member'] + 's.</p>':
'<p>As a ' + StakeholderConfiguration.ROLES[role] + ' of the National Open Access Monitor, Ireland, you will have access to the sandbox of the profile for the ' + name + '.') +
'<p>As a ' + Role.ROLES[role] + ' of the National Open Access Monitor, Ireland, you will have access to the administration part of the dashboard, where you will be able to also invite other users to become ' + Role.ROLES['member'] + 's.</p>':
'<p>As a ' + Role.ROLES[role] + ' of the National Open Access Monitor, Ireland, you will have access to the sandbox of the profile for the ' + name + '.') +
'<p>Please contact us at <a href="mailto:' + properties.helpdeskEmail+'">' + properties.helpdeskEmail +
'</a> if you have any questions or concerns.</p>' +
'<p>Kind Regards<br>The OpenAIRE Team</p>' +
@ -365,9 +379,9 @@ export class Composer {
'<p>Click <a href="((__link__))" target="_blank">this URL</a> and use the verification code below to accept the invitation.</p>' +
'<p>The verification code is <b>((__code__))</b>.</p>' +
(role === 'manager'?
'<p>As a manager of the OpenAIRE Research Community Dashboard, you will have access to the administration part of the dashboard, ' +
'<p>As a ' + Role.ROLES[role] + ' of the OpenAIRE Research Community Dashboard, you will have access to the administration part of the dashboard, ' +
'where you will be able to customize and manage the content of the ' + name + '.</p>':
'<p>As a member of the OpenAIRE Research Community Dashboard, you will have access to the community dashboard and link research results with projects, communities and other research projects.</p>') +
'<p>As a ' + Role.ROLES[role] + ' of the OpenAIRE Research Community Dashboard, you will have access to the community dashboard and link research results with projects, communities and other research projects.</p>') +
'<p>Please contact us at <a href="mailto:' + properties.helpdeskEmail+'">' + properties.helpdeskEmail +
'</a> if you have any questions or concerns.</p>' +
'<p>Kind Regards<br>The OpenAIRE Team</p>' +

View File

@ -1,202 +1,205 @@
import {properties} from "../../../../environments/environment";
import {Measure} from "./resultLandingInfo";
import {BelongsTo, Measure} from "./resultLandingInfo";
export class DataproviderProvenance {
provenance: Map<string, {"urlPrefix": string, "name": string}>;
provenance: Map<string, { "urlPrefix": string, "name": string }>;
constructor() {
this.provenance = new Map();
this.provenance.set("opendoar____::", {"urlPrefix": properties.openDoarURL, "name": "OpenDOAR"});//, "idRegexPrefix": ""});
this.provenance.set("re3data_____::", {"urlPrefix": properties.r3DataURL, "name": "re3data.org"});
this.provenance.set("fairsharing_::", {"urlPrefix": properties.fairSharingURL, "name": "FAIRsharing"});
this.provenance.set("eosc________::", {"urlPrefix": properties.eoscMarketplaceURL, "name": "EOSC Service Catalogue"});
this.provenance.set("eosc________::", {
"urlPrefix": properties.eoscMarketplaceURL,
"name": "EOSC Service Catalogue"
});
}
}
export class DataProviderInfo {
relcanId;
objIdentifier: string;
record;
title: { "name": string, "url": string };
officialName: string;
type: string;
registry: boolean;
compatibility: { "info": string, "name": string, "id": string };
oaiPmhURL: string;
openDoarId: string;
r3DataId: string;
provenance: Map<string, {"url": string[]}>;
originalId: string;
countries: string[];
journal: {"journal": "", "issn": string, "lissn": string, "eissn": string};
description: string;
subjects: string[];
jurisdiction: string;
thematic: boolean;
contentpolicy: string;
identifiers: Map<string, string[]>; //key is the classname
relcanId;
objIdentifier: string;
record;
title: { "name": string, "url": string };
officialName: string;
type: string;
registry: boolean;
compatibility: { "info": string, "name": string, "id": string };
oaiPmhURL: string;
openDoarId: string;
r3DataId: string;
provenance: Map<string, { "url": string[] }>;
originalId: string;
countries: string[];
journal: { "journal": "", "issn": string, "lissn": string, "eissn": string };
description: string;
subjects: string[];
jurisdiction: string;
thematic: boolean;
contentpolicy: string;
identifiers: Map<string, string[]>; //key is the classname
fundedContent: string; // search query
measure: Measure;
//collected from datasource api
// aggregationStatus: {"fundedContent": string, "indexRecords": string, "fulltexts": string, "lastUpdateDate": string};
aggregationStatus: {"fulltexts": string};
aggregationStatus: { "fulltexts": string };
tabs: {"name": string, "content": string}[];
tabs2: string[] =[];
tabsInTypes = {
"publicationsTab": new Set<string>(
[ "aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"infospace",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"scholarcomminfra",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"orprepository"
]),
"datasetsTab": new Set<string>(
[ "aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"infospace",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"scholarcomminfra",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"orprepository"
]),
"statisticsTab": new Set<string>(
[ "aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"orprepository"
]),
// "organizationsTab": new Set<string>(
// [ "entityregistry::projects",
// "entityregistry::repositories"
// ]),
"projectsTab": new Set<string>(["entityregistry::projects"]),
"datasourcesTab": new Set<string>(["entityregistry::repositories"]),
"relatedDatasourcesTab": new Set<string>(
[ "aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"aggregator::pubsrepository::institutional",
"aggregator::datarepository"
]),
"softwareTab": new Set<string>(
[
"aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"infospace",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"scholarcomminfra",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"softwarerepository",
"aggregator::softwarerepository",
"orprepository"
]),
"orpsTab": new Set<string>(
[
"aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"infospace",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"scholarcomminfra",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"softwarerepository",
"aggregator::softwarerepository",
"orprepository"
]),
"metricsTab": new Set<string>(
[ "aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"infospace",
"pubsrepository::institutional",
"pubsrepository::journal",
"websource",
"pubsrepository::unknown",
"scholarcomminfra",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"softwarerepository",
"aggregator::softwarerepository",
"orprepository"
])
tabs: { "name": string, "content": string }[];
tabs2: string[] = [];
tabsInTypes = {
"publicationsTab": new Set<string>(
["aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"infospace",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"scholarcomminfra",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"orprepository"
]),
"datasetsTab": new Set<string>(
["aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"infospace",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"scholarcomminfra",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"orprepository"
]),
"statisticsTab": new Set<string>(
["aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"orprepository"
]),
// "organizationsTab": new Set<string>(
// [ "entityregistry::projects",
// "entityregistry::repositories"
// ]),
"projectsTab": new Set<string>(["entityregistry::projects"]),
"datasourcesTab": new Set<string>(["entityregistry::repositories"]),
"relatedDatasourcesTab": new Set<string>(
["aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"aggregator::pubsrepository::institutional",
"aggregator::datarepository"
]),
"softwareTab": new Set<string>(
[
"aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"infospace",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"scholarcomminfra",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"softwarerepository",
"aggregator::softwarerepository",
"orprepository"
]),
"orpsTab": new Set<string>(
[
"aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"infospace",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"scholarcomminfra",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"softwarerepository",
"aggregator::softwarerepository",
"orprepository"
]),
"metricsTab": new Set<string>(
["aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"crissystem",
"datarepository::unknown",
"infospace",
"pubsrepository::institutional",
"pubsrepository::journal",
"websource",
"pubsrepository::unknown",
"scholarcomminfra",
"pubsrepository::thematic",
"pubscatalogue::unknown",
"softwarerepository",
"aggregator::softwarerepository",
"orprepository"
])
};
};
resultsBy: string;
resultTypes = {
"collectedFrom": new Set<string>(
[ "aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"entityregistry::projects",
"entityregistry::repositories",
"infospace",
"scholarcomminfra",
"pubscatalogue::unknown",
"aggregator::softwarerepository"
]),
"hostedBy": new Set<string>(
[ "crissystem",
"datarepository::unknown",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"pubsrepository::thematic",
"softwarerepository",
"orprepository"
])
};
resultsBy: string;
resultTypes = {
"collectedFrom": new Set<string>(
["aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"entityregistry::projects",
"entityregistry::repositories",
"infospace",
"scholarcomminfra",
"pubscatalogue::unknown",
"aggregator::softwarerepository"
]),
"hostedBy": new Set<string>(
["crissystem",
"datarepository::unknown",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"pubsrepository::thematic",
"softwarerepository",
"orprepository"
])
};
organizations: {"acronym": string, "name": string, "id": string}[] = [];
//publications: any;
//datasets: any;
statistics: any;
//projects: any;
datasources: any;
organizations: { "acronym": string, "name": string, "id": string }[] = [];
//publications: any;
//datasets: any;
statistics: any;
//projects: any;
datasources: any;
//relatedDatasources: Map<string, {"name": string, "countPublications": string, "countDatasets": string, "countSoftware": string, "countOrps": string}>;
relatedDatasources: {"id": string, "name": string, "count": number}[] = [];
//relatedDatasources: Map<string, {"name": string, "countPublications": string, "countDatasets": string, "countSoftware": string, "countOrps": string}>;
relatedDatasources: { "id": string, "name": string, "count": number }[] = [];
}

View File

@ -1,3 +1,5 @@
import {BelongsTo} from "./resultLandingInfo";
export interface OrganizationProject {
name: string;
id: string;

View File

@ -1,4 +1,5 @@
import {Measure} from "./resultLandingInfo";
import {BelongsTo, Measure} from "./resultLandingInfo";
import {StringUtils} from "../string-utils.class";
export class ProjectInfo {
id:string;
@ -23,4 +24,14 @@ export class ProjectInfo {
totalDatasets: number;
publicationsStatus: any;
measure: Measure;
belongsTo: boolean = true;
message: string;
setBelongsTo(id: string) {
this.belongsTo = !BelongsTo.project || BelongsTo.project.fields.findIndex(field => BelongsTo.check(this, field)) != -1;
this.message = !this.belongsTo?BelongsTo.project.message:null;
if(this.message) {
this.message = this.message.replace('((id))', id);
}
}
}

View File

@ -6,6 +6,9 @@ import {
Project,
RelationResult
} from "../result-preview/result-preview";
import {isArray} from "rxjs/internal-compatibility";
import {OpenaireEntities} from "../properties/searchFields";
import {StringUtils} from "../string-utils.class";
export interface Id {
type: "pmid" | "doi" | "pmc" | "handle" | "openaire" | "swhid";
@ -30,18 +33,6 @@ export interface Context {
}
export interface Measure {
// /** @deprecated*/
// downloads?: string;
// /** @deprecated*/
// views?: string;
// /** @deprecated*/
// influence?: string;
// /** @deprecated*/
// popularity?: string;
// /** @deprecated*/
// citations?: string;
// /** @deprecated*/
// impulse?: string;
bip?: Metric[]
counts?: Metric[]
countsPerDatasource?: MetricPerDatasource[];
@ -61,12 +52,46 @@ export interface Metric {
value: any
}
class Field {
path: string[];
value: string;
}
export class BelongsTo {
public static result: BelongsTo = null;
public static project: BelongsTo = null;
public static organization: BelongsTo = null;
public static datasource: BelongsTo = null;
fields: Field[];
message: string;
public static check(element: any, field: Field): boolean {
if (field) {
field = Object.assign({}, field);
let json: any = element;
if (field.path.length > 0) {
if (Array.isArray(json)) {
return json.findIndex(value => BelongsTo.check(value, field)) != -1;
} else {
json = json[field.path[0]];
field.path = field.path.slice(1);
return BelongsTo.check(json, field);
}
}
console.log(json, field.value)
return json == field.value;
}
return false;
}
}
export class ResultLandingInfo {
relcanId;
objIdentifier: string;
// PUBLICATION, DATASET, SOFTWARE, ORP
record;
resultType: "publication"|"dataset"|"other"|"software";
resultType: "publication" | "dataset" | "other" | "software";
// PUBLICATION, DATASET, SOFTWARE, ORP, DELETED_BY_INFERENCE
title: string;
accessMode: string;
@ -79,26 +104,26 @@ export class ResultLandingInfo {
languages: string[];
countries: string[];
description: string;
hostedBy_collectedFrom: HostedByCollectedFrom[];
// PUBLICATION, DATASET, SOFTWARE, ORP
fundedByProjects: Project[];
underCurationMessage: boolean;
publisher: string;
journal: Journal;
subjects: string[];
otherSubjects: Map<string, string[]>;
classifiedSubjects: Map<string, string[]>; //<class of subject, subjects>
fos: {"id": string, "label": string}[] = [];
fos: { "id": string, "label": string }[] = [];
sdg: string[];
eoscSubjects: any[];
oaRoutes: OARoutes;
publiclyFunded: boolean;
// // percentage is for trust
// relatedResearchResults: RelationResult[];
// // percentage is for similarity
@ -159,22 +184,35 @@ export class ResultLandingInfo {
relatedClassFilters: Set<string> = new Set();
contexts: Context[];
deletedByInferenceIds: string[];
// PUBLICATION, DATASET, ORP
references: Reference[];
// PUBLICATION
bioentities: Map<string, Map<string, string>>; //<site name, <>>
organizations: Organization[];
openCitations: { "url": string, "title": string, "year": string, "doi": string, "authors": string[] }[];
// DATASET
subtitle: string;
// SOFTWARE
programmingLanguages: string[];
measure: Measure;
measure: Measure;
belongsTo: boolean = true;
message: string;
setBelongsTo(typeId: string, id: string) {
this.belongsTo = !BelongsTo.result || BelongsTo.result.fields.findIndex(field => BelongsTo.check(this, field)) != -1;
this.message = !this.belongsTo ? BelongsTo.result.message : null;
if (this.message) {
this.message = this.message.replace('((result))', StringUtils.getEntityName(this.resultType));
this.message = this.message.replace('((type_id))', typeId);
this.message = this.message.replace('((id))', id);
}
}
}

View File

@ -148,7 +148,7 @@ private fetch (link,id,oafEntityType,type, properties:EnvProperties ){
if(keyword!= null && keyword != '' ) {
if(type=="project") {
//name, title, acronym, grantid
url += "fq="+'(projectcode_nt="'+keyword+'" ) or (fundershortname='+'"'+keyword+ '"'+') or (projectacronym="'+keyword+'" ) or (projecttitle="'+keyword+'")';
url += "fq="+'(projectcode_nt="'+keyword+'" ) or (fundershortname='+'"'+keyword+ '"'+') or (projectacronym="'+keyword+'" ) or (projecttitle="'+keyword+'")&fq=(projectcode<>"unidentified")';
} else if(type=="organization") {
//name fields
url += "fq="+'(organizationlegalname="'+keyword+'" ) or (organizationlegalshortname='+'"'+keyword+ '")';

View File

@ -161,3 +161,8 @@ export const unknown_access: Icon = {
name: 'unknown_access',
data: '<svg xmlns="http://www.w3.org/2000/svg" width="373.336" height="490.004" viewBox="0 0 373.336 490.004"><g id="noun-lock-question-mark-250128" transform="translate(-163.328 -34.992)"><path id="Path_119172" data-name="Path 119172" d="M490,198.33H466.668V151.662a116.67,116.67,0,0,0-233.34,0V198.33H210A46.8,46.8,0,0,0,163.328,245v233.33A46.8,46.8,0,0,0,210,525H490a46.8,46.8,0,0,0,46.668-46.668V245A46.8,46.8,0,0,0,490,198.33ZM365.55,469.78H334.441V438.671H365.55ZM397.441,350l-14,14c-10.891,11.668-17.891,20.223-17.891,43.555H334.441v-7.777a61.712,61.712,0,0,1,17.891-43.555l19.445-19.445A30.98,30.98,0,1,0,318.891,315H287.782a62.223,62.223,0,0,1,124.446,0,49.983,49.983,0,0,1-14.785,35Zm24.887-151.67H277.668V151.662c0-39.668,32.668-72.332,72.332-72.332S422.332,112,422.332,151.662Z"/></g></svg>'
}
export const coins: Icon = {
name: 'coins',
data: '<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 315.47 315.47"><g id="Layer_1-2"><g><g><ellipse class="" cx="116.85" cy="98.6" rx="63.94" ry="37.92"/><ellipse class="" cx="199.59" cy="167.66" rx="63.94" ry="37.92"/><path class="cls-3" d="M260.39,185.84c1.25-1.88,2.51-3.76,3.13-5.95-.31,13.48,1.25,14.42-.94,21.63-5.01,17.24-38.86,29.77-64.25,29.15-21.63-.31-39.18-2.82-54.85-15.98-4.39-3.76-9.4-7.52-9.72-12.85,0-10.03,0-11.6,.31-23.82,10.34,38.86,102.8,41.37,126.31,7.84Z"/><path class="cls-3" d="M262.58,209.66c.94,8.78-1.57,13.79-1.88,20.06-.94,14.73-35.1,24.76-61.43,25.07-31.34,.31-63.62-12.22-64.25-24.76-.63-11.28,0-5.33-.94-20.06,21.31,32.28,105.31,31.97,128.5-.31Z"/><path class="cls-3" d="M116.85,140.71c38.55,.31,57.67-17.86,61.74-25.07,1.88-3.45-.31,12.85-.94,13.16-14.1,4.07-31.03,10.03-40.43,21.94-2.82,3.45-3.76,7.52-5.01,12.54,0,.31-13.48-.31-14.42-.31-28.21,0-61.12-13.48-65.82-35.73-.63-4.39,0-8.15,0-17.55,10.03,19.75,36.67,30.71,64.88,31.03Z"/><path class="cls-3" d="M116.85,166.72c5.01,.31,15.04,0,15.04,0-.94,8.78-.63,12.85-1.25,23.19,0,.31-71.15,3.76-78.67-33.85-.63-4.07,0-7.84,0-17.55,15.67,21.31,42.94,27.27,64.88,28.21Z"/><path class="cls-3" d="M130.01,194.3s.94,12.54,.63,21.94c0,.31-68.95,1.88-78.04-27.58l-.63-21.31c16.92,23.51,52.65,27.58,78.04,26.95Z"/></g></g></g></svg>'
}

View File

@ -56,6 +56,7 @@ export class MobileDropdownComponent implements OnInit{
parent.removeChild(this.element.nativeElement);
container.append(this.element.nativeElement);
this.opened = true;
this.cdr.markForCheck();
body.setAttribute('style', 'overflow-y: hidden');
}
}

View File

@ -77,7 +77,8 @@
</div>
<!-- Metadata -->
<div class="uk-margin-xsmall-top">
<entity-metadata [entityType]="type" [types]="result.types" [startYear]="result.startYear?.toString()"
<entity-metadata [resultTitle]="result?.title"
[entityType]="type" [types]="result.types" [startYear]="result.startYear?.toString()"
[endYear]="result.endYear?.toString()"
[year]="result.year?.toString()"
[openAccessMandatePublications]="result.openAccessMandatePublications"
@ -218,7 +219,7 @@
<div *ngIf="result.oaRoutes" class="uk-first-column">
<!-- class="metrics uk-text-xsmall uk-width-auto uk-flex uk-flex-middle uk-flex-right uk-text-meta">-->
<a class="uk-flex uk-flex-middle uk-link-reset">
<span #badge class="access-route-badge" [ngClass]="'dots-' + badge.children.length.toString()">
<span #badge class="access-route-badge" [ngClass]="'dots-' + countDots">
<span *ngIf="result.oaRoutes.green" class="dot green"></span>
<span *ngIf="result.oaRoutes.oaColor" class="dot" [ngClass]="result.oaRoutes.oaColor"></span>
<span *ngIf="result.oaRoutes.isInDiamondJournal" class="dot diamond"></span>

View File

@ -13,7 +13,7 @@ import {NumberUtils} from '../number-utils.class';
selector: 'result-preview',
templateUrl: 'result-preview.component.html',
styleUrls: ['result-preview.component.less'],
// changeDetection: ChangeDetectionStrategy.OnPush
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ResultPreviewComponent implements OnInit, OnChanges {
@Input() prevPath: string = "";

View File

@ -43,6 +43,7 @@ export interface Project {
title: string;
funderShortname: string;
funderName: string;
funderJurisdiction?: string
funding?: string;
code: string;
validated?: boolean;

View File

@ -24,6 +24,7 @@ export class SmoothScroll {
} else if (event instanceof NavigationEnd) {
let headerOffset = (this.layoutService.isMobileValue?0:Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--header-height'))) + 35;
if(!this.router.getCurrentNavigation().extras?.state?.disableScroll) {
let behavior = this.router.getCurrentNavigation().extras?.state?.behavior ? this.router.getCurrentNavigation().extras?.state?.behavior : "smooth";
if (this.interval) {
clearInterval(this.interval);
}
@ -48,7 +49,7 @@ export class SmoothScroll {
} else {
clearInterval(interval);
const y = element.getBoundingClientRect().top + window.scrollY + yOffset;
window.scrollTo({top: y, behavior: 'smooth'});
window.scrollTo({top: y, behavior: behavior});
}
}, 50);
}
@ -58,7 +59,7 @@ export class SmoothScroll {
}, 100);
} else {
setTimeout( () => {
window.scrollTo({top: 0, behavior: 'smooth'});
window.scrollTo({top: 0, behavior: behavior});
}, 0);
}
}
@ -76,4 +77,4 @@ export class SmoothScroll {
clearInterval(this.interval);
}
}
}
}

View File

@ -30,13 +30,14 @@ export class TransitionGroupComponent implements AfterViewInit, OnDestroy {
@Input()
public id: string;
public size: number;
private disabled: boolean = false;
private subscription: Subscription;
constructor(public element: ElementRef) {}
ngAfterViewInit() {
this.subscription = this.items.changes.subscribe(items => {
if(items.length === this.size) {
if(items.length === this.size && !this.disabled) {
items.forEach(item => item.prevPos = item.newPos || item.prevPos);
items.forEach(this.runCallback);
this.refreshPosition('newPos');
@ -126,17 +127,17 @@ export class TransitionGroupComponent implements AfterViewInit, OnDestroy {
/**
* Enable transition
* @deprecated
*
* */
enable() {
console.debug('Deprecated')
this.disabled = false;
}
/**
* Disable transition
* @deprecated
*
* */
disable() {
console.debug('Deprecated')
this.disabled = true;
}
}