Merge remote-tracking branch 'origin/angular-14' into data-transfer-v2

This commit is contained in:
Konstantina Galouni 2023-01-04 13:36:54 +02:00
commit 161052d97c
113 changed files with 2015 additions and 1765 deletions

View File

@ -7,7 +7,7 @@ import {properties} from "../../../../../environments/environment";
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class ContextsService { export class ContextsService {
private communitiesSubject: BehaviorSubject<any> = new BehaviorSubject(null); private communitiesSubject: BehaviorSubject<any> = new BehaviorSubject(null);
private promise: Promise<any>; private promise: Promise<void>;
private sub: Subscription = null; private sub: Subscription = null;
constructor(private http: HttpClient=null ) { constructor(private http: HttpClient=null ) {
@ -34,7 +34,7 @@ export class ContextsService {
public initCommunities() { public initCommunities() {
let url = properties.contextsAPI + 's/'; let url = properties.contextsAPI + 's/';
this.promise = new Promise<any>((resolve => { this.promise = new Promise<void>((resolve => {
this.sub = this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) this.sub = this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => this.parseCommunities(res, true) )) .pipe(map(res => this.parseCommunities(res, true) ))
.subscribe( .subscribe(

View File

@ -2,8 +2,10 @@ import {throwError as observableThrowError} from 'rxjs';
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
import {ClaimEntity, ClaimResult} from '../claimHelper.class'; import {ClaimEntity, ClaimResult} from '../claimHelper.class';
import {map} from "rxjs/operators"; import {map, timeout} from "rxjs/operators";
import {EnvProperties} from "../../../utils/properties/env-properties"; import {EnvProperties} from "../../../utils/properties/env-properties";
import {properties} from "../../../../../environments/environment";
import {StringUtils} from "../../../utils/string-utils.class";
@Injectable() @Injectable()
export class SearchCrossrefService { export class SearchCrossrefService {
@ -20,7 +22,9 @@ export class SearchCrossrefService {
} }
searchCrossrefByDOIs(DOIs: string[], properties: EnvProperties, parse: boolean = false): any { searchCrossrefByDOIs(DOIs: string[], properties: EnvProperties, parse: boolean = false, file: boolean = false): any {
let timeoutTime: number = properties.environment == "production" ? 6000 : 12000;
// let timeoutTimeForFile: number = 60000;
var doisParams = ""; var doisParams = "";
for (var i = 0; i < DOIs.length; i++) { for (var i = 0; i < DOIs.length; i++) {
@ -28,11 +32,21 @@ export class SearchCrossrefService {
} }
let url = properties.searchCrossrefAPIURL + '?filter=' + doisParams; let url = properties.searchCrossrefAPIURL + '?filter=' + doisParams;
return this.http.get(url) return this.http.get(url)
//.map(request => <any> request.json().message) // .pipe(timeout(file ? timeoutTimeForFile : (timeoutTime)))
.pipe(timeout(timeoutTime))
.pipe(map(request => request['message'])) .pipe(map(request => request['message']))
.pipe(map(request => [request["total-results"], parse ? this.parse(request['items']) : request])) .pipe(map(request => [request["total-results"], parse ? this.parse(request['items']) : request]))
//.catch(this.handleError);
} }
searchCrossrefByDOI(DOI: string): any {
let timeoutTimeForFile: number = 20000;
let url = properties.searchCrossrefAPIURL + '/' + StringUtils.URIEncode(DOI);
return this.http.get(url)
.pipe(timeout(timeoutTimeForFile))
.pipe(map(request => request['message']))
.pipe(map(request => this.parse(request)))
}
searchCrossrefByMultipleDOIs(dois: string[], properties: EnvProperties, parse: boolean = false): any { searchCrossrefByMultipleDOIs(dois: string[], properties: EnvProperties, parse: boolean = false): any {
let url = properties.searchCrossrefAPIURL + '?filter=doi:'; let url = properties.searchCrossrefAPIURL + '?filter=doi:';
for (var i = 0; i < dois.length; i++) { for (var i = 0; i < dois.length; i++) {
@ -56,8 +70,11 @@ export class SearchCrossrefService {
parse(response): ClaimEntity[] { parse(response): ClaimEntity[] {
const results: ClaimEntity[] = []; const results: ClaimEntity[] = [];
for (let i = 0; i < response.length; i++) { let length = Array.isArray(response) ? response.length : 1;
const item = response[i];
for (let i = 0; i < length; i++) {
const item = Array.isArray(response) ? response[i] : response;
const entity: ClaimEntity = new ClaimEntity(); const entity: ClaimEntity = new ClaimEntity();
entity.result = new ClaimResult(); entity.result = new ClaimResult();
entity.result.publisher = null; entity.result.publisher = null;

View File

@ -3,7 +3,7 @@ import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
import {EnvProperties} from '../../../utils/properties/env-properties'; import {EnvProperties} from '../../../utils/properties/env-properties';
import {ClaimEntity, ClaimResult} from '../claimHelper.class'; import {ClaimEntity, ClaimResult} from '../claimHelper.class';
import {catchError, map} from 'rxjs/operators'; import {catchError, map, timeout} from 'rxjs/operators';
import {properties} from "../../../../../environments/environment"; import {properties} from "../../../../../environments/environment";
@ -21,10 +21,14 @@ export class SearchDataciteService {
//.catch(this.handleError); //.catch(this.handleError);
} }
getDataciteResultByDOI(doi: string, properties: EnvProperties, parse: boolean = false): any { getDataciteResultByDOI(doi: string, properties: EnvProperties, parse: boolean = false, file: boolean = false): any {
let timeoutTime: number = properties.environment == "production" ? 6000 : 12000;
let timeoutTimeForFile: number = 20000;
let url = properties.searchDataciteAPIURL + '/' + doi; let url = properties.searchDataciteAPIURL + '/' + doi;
let key = url; let key = url;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url) return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(timeout(file ? timeoutTimeForFile : (timeoutTime)))
.pipe(map(request => (parse ? SearchDataciteService.parse([request["data"]])[0] : request)), catchError(err => of(null))); .pipe(map(request => (parse ? SearchDataciteService.parse([request["data"]])[0] : request)), catchError(err => of(null)));
} }

View File

@ -21,9 +21,11 @@ declare var UIkit: any;
<div> <div>
<!--div class="uk-text-lead">Upload a DOI csv file <helper div="link-result-bulk" tooltip=true ></helper></div> <!--div class="uk-text-lead">Upload a DOI csv file <helper div="link-result-bulk" tooltip=true ></helper></div>
<label for="exampleInputFile">Select a file: </label--> <label for="exampleInputFile">Select a file: </label-->
<div class="js-upload uk-float-left" uk-form-custom> <div class="uk-float-left">
<span class="js-upload" uk-form-custom>
<input id="exampleInputFile" class="uk-width-medium" type="file" (change)="fileChangeEvent($event)"/> <input id="exampleInputFile" class="uk-width-medium" type="file" (change)="fileChangeEvent($event)"/>
<span class="uk-link " style="text-decoration: underline;">Upload a DOI's CSV file </span> <span class="uk-link " style="text-decoration: underline;">Upload a DOI's CSV file </span>
</span>
<!--button class="uk-button portal-button" type="button" tabindex="-1" [class.disabled]="!enableUpload" ><span class="uk-margin-small-right uk-icon" > <!--button class="uk-button portal-button" type="button" tabindex="-1" [class.disabled]="!enableUpload" ><span class="uk-margin-small-right uk-icon" >
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <polyline fill="none" stroke="#000" points="5 8 9.5 3.5 14 8 "></polyline> <rect x="3" y="17" width="13" height="1"></rect> <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <polyline fill="none" stroke="#000" points="5 8 9.5 3.5 14 8 "></polyline> <rect x="3" y="17" width="13" height="1"></rect>
<line fill="none" stroke="#000" x1="9.5" y1="15" x2="9.5" y2="4"></line></svg></span> Select</button--> <line fill="none" stroke="#000" x1="9.5" y1="15" x2="9.5" y2="4"></line></svg></span> Select</button-->
@ -107,17 +109,16 @@ export class BulkClaimComponent {
exceedsLimit = false; exceedsLimit = false;
@Input() basketLimit ; @Input() basketLimit ;
tooltip = ` tooltip = `
<div class="uk-padding-small uk-padding-remove-right uk-padding-remove-left"> <div>
<div > <div class="uk-margin-bottom">Up to 100 DOIs</div>
<div><span class="uk-text-bold">CSV format:</span> <br>&quot;DOI&quot;,&quot;ACCESS_MODE&quot;,&quot;DATE&quot;</div> <div><span class="uk-text-bold">CSV format:</span> <br>&quot;DOI&quot;,&quot;ACCESS_MODE&quot;,&quot;DATE&quot;</div>
<br> <br>
<div class=" uk-text-small"> <div class="uk-text-small">
<div>- DOI is required</div> <div>- DOI is required</div>
<div>- Access mode: <br> OPEN, CLOSED, EMBARGO</div> <div>- Access mode: <br> OPEN, CLOSED, EMBARGO</div>
<div>- Embargo end date:<br> YYYY-MM-DD </div> <div>- Embargo end date:<br> YYYY-MM-DD </div>
</div> </div>
</div> </div>`;
</div>`;
constructor(private _searchCrossrefService: SearchCrossrefService, private _searchDataciteService: SearchDataciteService) { constructor(private _searchCrossrefService: SearchCrossrefService, private _searchDataciteService: SearchDataciteService) {
this.filesToUpload = []; this.filesToUpload = [];
} }
@ -226,7 +227,7 @@ export class BulkClaimComponent {
} }
makeFileRequest(url: string, params: Array<string>, files: Array<File>) { makeFileRequest(url: string, params: Array<string>, files: Array<File>) {
return new Promise((resolve, reject) => { return new Promise<void>((resolve, reject) => {
const formData: any = new FormData(); const formData: any = new FormData();
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
@ -247,11 +248,12 @@ export class BulkClaimComponent {
} }
fetchResult(id: string, accessMode: string, date: string, row: number) { fetchResult(id: string, accessMode: string, date: string, row: number) {
this.subscriptions.push(this._searchCrossrefService.searchCrossrefByDOIs([id], this.properties, true).subscribe( // this.subscriptions.push(this._searchCrossrefService.searchCrossrefByDOIs([id], this.properties, true, true).subscribe(
this.subscriptions.push(this._searchCrossrefService.searchCrossrefByDOI(id).subscribe(
data => { data => {
const result:ClaimEntity = data[1][0]; if (data.length > 0) {
if (data[1].length > 0) { const result:ClaimEntity = data[0];
this.foundIds.push(id); this.foundIds.push(id);
result.result.accessRights = accessMode; result.result.accessRights = accessMode;
result.result.embargoEndDate = date; result.result.embargoEndDate = date;

View File

@ -11,7 +11,7 @@ export class CommunityService {
public community: BehaviorSubject<CommunityInfo> = new BehaviorSubject(null); public community: BehaviorSubject<CommunityInfo> = new BehaviorSubject(null);
public communityId: string = null; public communityId: string = null;
private promise: Promise<boolean> = null; private promise: Promise<void> = null;
private subs = []; private subs = [];
constructor(private http: HttpClient) {} constructor(private http: HttpClient) {}
@ -40,7 +40,7 @@ export class CommunityService {
getCommunity(communityId: string, refresh = false) { getCommunity(communityId: string, refresh = false) {
if (this.communityId !== communityId || !this.community.value || refresh) { if (this.communityId !== communityId || !this.community.value || refresh) {
this.communityId = communityId; this.communityId = communityId;
this.promise = new Promise<any>((resolve, reject) => { this.promise = new Promise<void>((resolve, reject) => {
this.subs.push(this.getCommunityInfo(communityId).subscribe(community => { this.subs.push(this.getCommunityInfo(communityId).subscribe(community => {
this.community.next(community); this.community.next(community);
resolve(); resolve();

View File

@ -8,7 +8,7 @@ export class ConnectHelper {
if(properties.environment == "development" && if(properties.environment == "development" &&
(properties.adminToolsPortalType == "connect" || properties.adminToolsPortalType == "community" (properties.adminToolsPortalType == "connect" || properties.adminToolsPortalType == "community"
|| properties.adminToolsPortalType == "aggregator" || properties.adminToolsPortalType == "eosc")) { || properties.adminToolsPortalType == "aggregator" || properties.adminToolsPortalType == "eosc")) {
domain = "canada.explore.openaire.eu"; //for testing domain = "test.openaire.eu"; //for testing
} }
domain = domain.indexOf("//") != -1? domain.split("//")[1]:domain; //remove https:// prefix domain = domain.indexOf("//") != -1? domain.split("//")[1]:domain; //remove https:// prefix
if (domain.indexOf('eosc-portal.eu') != -1) { if (domain.indexOf('eosc-portal.eu') != -1) {

View File

@ -1,9 +1,8 @@
<div page-content> <div page-content>
<div header> <div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info"> <div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<img src="assets/common-assets/placeholder.png" class="uk-margin-right">
<div> <div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Classes</div> <div class="uk-text-background uk-text-bold uk-text-small">Manage Classes</div>
<h1 class="uk-h6 uk-margin-remove">Super Admin</h1> <h1 class="uk-h6 uk-margin-remove">Super Admin</h1>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router"; import {ActivatedRoute, Router} from "@angular/router";
import {HelpContentService} from "../../services/help-content.service"; import {HelpContentService} from "../../services/help-content.service";
import {FormArray, FormBuilder, FormGroup, Validators} from "@angular/forms"; import {UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators} from "@angular/forms";
import {CheckDivId, DivId} from "../../utils/entities/adminTool/divId"; import {CheckDivId, DivId} from "../../utils/entities/adminTool/divId";
import {Page} from "../../utils/entities/adminTool/page"; import {Page} from "../../utils/entities/adminTool/page";
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
@ -25,15 +25,15 @@ export class DivIdsComponent implements OnInit {
private selectedDivIds: string[] = []; private selectedDivIds: string[] = [];
public checkboxes: CheckDivId[] = []; public checkboxes: CheckDivId[] = [];
public divIds: DivId[] = []; public divIds: DivId[] = [];
public classForm: FormGroup; public classForm: UntypedFormGroup;
public pagesCtrl: FormArray; public pagesCtrl: UntypedFormArray;
private searchText: RegExp = new RegExp(''); private searchText: RegExp = new RegExp('');
public keyword: string = ""; public keyword: string = "";
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public formPages: Page[] = []; public formPages: Page[] = [];
public showLoading: boolean = true; public showLoading: boolean = true;
public filterForm: FormGroup; public filterForm: UntypedFormGroup;
private subscriptions: any[] = []; private subscriptions: any[] = [];
public allPages: Option[] = []; public allPages: Option[] = [];
selectedCommunityPid = null; selectedCommunityPid = null;
@ -42,7 +42,7 @@ export class DivIdsComponent implements OnInit {
constructor(private element: ElementRef, private route: ActivatedRoute, private _router: Router, constructor(private element: ElementRef, private route: ActivatedRoute, private _router: Router,
private title: Title, private title: Title,
private _helpContentService: HelpContentService, private _fb: FormBuilder, private _helpContentService: HelpContentService, private _fb: UntypedFormBuilder,
private _clearCacheService: ClearCacheService) { private _clearCacheService: ClearCacheService) {
} }

View File

@ -49,7 +49,11 @@
<button class="uk-button uk-button-link uk-text-normal"><icon name="info" type="outlined" [flex]="true"></icon></button> <button class="uk-button uk-button-link uk-text-normal"><icon name="info" type="outlined" [flex]="true"></icon></button>
<div class="uk-dropdown uk-text-normal uk-width-medium uk-padding-small" uk-dropdown> <div class="uk-dropdown uk-text-normal uk-width-medium uk-padding-small" uk-dropdown>
OpenAIRE style guide is based on <a href="https://getuikit.com/docs/introduction" target="_blank" class="uk-link custom-external">UIKit</a>. OpenAIRE style guide is based on <a href="https://getuikit.com/docs/introduction" target="_blank" class="uk-link custom-external">UIKit</a>.
You can find some usage examples <a routerLink="/theme" [queryParams]="parentClass?{parentClass: parentClass}:null" target="_blank" class="uk-link custom-external">here</a> You can find some usage examples
<a *ngIf="properties.dashboard == 'monitor'" routerLink="/theme" [queryParams]="parentClass?{parentClass: parentClass}:null"
target="_blank" class="uk-link custom-external">here</a>
<a *ngIf="properties.dashboard == 'connect'" [href] ="'https://'+(properties.environment == 'beta' ? 'beta.' : '')+this.portal+'.openaire.eu/theme'"
target="_blank" class="uk-link custom-external">here</a>
in order to style your content. in order to style your content.
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import {Component, OnInit} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {Page} from '../../utils/entities/adminTool/page'; import {Page} from '../../utils/entities/adminTool/page';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
@ -16,7 +16,7 @@ import {ClearCacheService} from "../../services/clear-cache.service";
}) })
export class ClassContentFormComponent implements OnInit { export class ClassContentFormComponent implements OnInit {
myForm: FormGroup; myForm: UntypedFormGroup;
portal: string; portal: string;
parentClass: string; parentClass: string;
pageId: string; pageId: string;
@ -28,7 +28,7 @@ export class ClassContentFormComponent implements OnInit {
private subs: Subscription[] = []; private subs: Subscription[] = [];
public pageHelpContent: DivHelpContent; public pageHelpContent: DivHelpContent;
constructor(private route: ActivatedRoute, private _router: Router, private _fb: FormBuilder, constructor(private route: ActivatedRoute, private _router: Router, private _fb: UntypedFormBuilder,
private _helpContentService: HelpContentService, private _clearCacheService: ClearCacheService) { private _helpContentService: HelpContentService, private _clearCacheService: ClearCacheService) {
} }

View File

@ -1,5 +1,5 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {FormBuilder, FormControl, FormGroup} from '@angular/forms'; import {UntypedFormBuilder, UntypedFormControl, UntypedFormGroup} from '@angular/forms';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import {PageHelpContentFilterOptions} from '../../utils/entities/adminTool/page-help-content'; import {PageHelpContentFilterOptions} from '../../utils/entities/adminTool/page-help-content';
@ -26,7 +26,7 @@ export class ClassHelpContentsComponent implements OnInit {
private selectedPageContents: string[] = []; private selectedPageContents: string[] = [];
public checkboxes: CheckDivHelpContent[] = []; public checkboxes: CheckDivHelpContent[] = [];
public divHelpContents: DivHelpContent[] = []; public divHelpContents: DivHelpContent[] = [];
public formGroup: FormGroup; public formGroup: UntypedFormGroup;
public pages: Page[]; public pages: Page[];
public checkboxAll: boolean = false; public checkboxAll: boolean = false;
public filters: PageHelpContentFilterOptions = {id: '', active: null, text: new RegExp('')}; public filters: PageHelpContentFilterOptions = {id: '', active: null, text: new RegExp('')};
@ -39,11 +39,11 @@ export class ClassHelpContentsComponent implements OnInit {
public page: Page; public page: Page;
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public showLoading: boolean = true; public showLoading: boolean = true;
public filterForm: FormControl; public filterForm: UntypedFormControl;
private subscriptions: any[] = []; private subscriptions: any[] = [];
constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router, constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router,
private _helpService: HelpContentService, private _fb: FormBuilder, private sanitizer: DomSanitizer, private _helpService: HelpContentService, private _fb: UntypedFormBuilder, private sanitizer: DomSanitizer,
private _clearCacheService: ClearCacheService) { private _clearCacheService: ClearCacheService) {
} }

View File

@ -1,11 +1,8 @@
<div page-content> <div page-content>
<div header> <div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info"> <div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<ng-container *ngIf="showLogo">
<img [src]="entity | logoUrl" class="uk-margin-right uk-blend-multiply">
</ng-container>
<div> <div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Entities</div> <div class="uk-text-background uk-text-bold uk-text-small">Manage Entities</div>
<h1 class="uk-h6 uk-margin-remove">{{name?name:'Super Admin'}}</h1> <h1 class="uk-h6 uk-margin-remove">{{name?name:'Super Admin'}}</h1>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {CheckEntity, Entity} from '../../utils/entities/adminTool/entity'; import {CheckEntity, Entity} from '../../utils/entities/adminTool/entity';
import {Portal} from '../../utils/entities/adminTool/portal'; import {Portal} from '../../utils/entities/adminTool/portal';
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
@ -34,7 +34,7 @@ export class EntitiesComponent implements OnInit {
public entities: Entity[] = []; public entities: Entity[] = [];
public entityForm: FormGroup; public entityForm: UntypedFormGroup;
private searchText: RegExp = new RegExp(''); private searchText: RegExp = new RegExp('');
public keyword = ''; public keyword = '';
@ -52,14 +52,14 @@ export class EntitiesComponent implements OnInit {
public showLoading = true; public showLoading = true;
public isPortalAdministrator = null; public isPortalAdministrator = null;
public filterForm: FormGroup; public filterForm: UntypedFormGroup;
private subscriptions: any[] = []; private subscriptions: any[] = [];
private index: number; private index: number;
constructor(private element: ElementRef, private route: ActivatedRoute, constructor(private element: ElementRef, private route: ActivatedRoute,
private _router: Router, private title: Title, private _router: Router, private title: Title,
private _helpContentService: HelpContentService, private _helpContentService: HelpContentService,
private userManagementService: UserManagementService, private _fb: FormBuilder, private userManagementService: UserManagementService, private _fb: UntypedFormBuilder,
private communityService: CommunityService, private communityService: CommunityService,
private stakeholderService: StakeholderService, private stakeholderService: StakeholderService,
private _clearCacheService: ClearCacheService) { private _clearCacheService: ClearCacheService) {

View File

@ -53,7 +53,11 @@
<button class="uk-button uk-button-link uk-text-normal"><icon name="info" type="outlined" [flex]="true"></icon></button> <button class="uk-button uk-button-link uk-text-normal"><icon name="info" type="outlined" [flex]="true"></icon></button>
<div class="uk-dropdown uk-text-normal uk-width-medium uk-padding-small" uk-dropdown> <div class="uk-dropdown uk-text-normal uk-width-medium uk-padding-small" uk-dropdown>
OpenAIRE style guide is based on <a href="https://getuikit.com/docs/introduction" target="_blank" class="uk-link custom-external">UIKit</a>. OpenAIRE style guide is based on <a href="https://getuikit.com/docs/introduction" target="_blank" class="uk-link custom-external">UIKit</a>.
You can find some usage examples <a routerLink="/theme" [queryParams]="parentClass?{parentClass: parentClass}:null" target="_blank" class="uk-link custom-external">here</a> You can find some usage examples
<a *ngIf="properties.dashboard == 'monitor'" routerLink="/theme" [queryParams]="parentClass?{parentClass: parentClass}:null"
target="_blank" class="uk-link custom-external">here</a>
<a *ngIf="properties.dashboard == 'connect'" [href] ="'https://'+(properties.environment == 'beta' ? 'beta.' : '')+this.portal+'.openaire.eu/theme'"
target="_blank" class="uk-link custom-external">here</a>
in order to style your content. in order to style your content.
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import {Component, OnInit} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {Page} from '../../utils/entities/adminTool/page'; import {Page} from '../../utils/entities/adminTool/page';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
@ -17,7 +17,7 @@ import {NotificationHandler} from "../../utils/notification-handler";
}) })
export class PageContentFormComponent implements OnInit { export class PageContentFormComponent implements OnInit {
myForm: FormGroup; myForm: UntypedFormGroup;
portal: string; portal: string;
parentClass: string; parentClass: string;
pageId: string; pageId: string;
@ -30,7 +30,7 @@ export class PageContentFormComponent implements OnInit {
private subs: Subscription[] = []; private subs: Subscription[] = [];
public pageHelpContent: PageHelpContent; public pageHelpContent: PageHelpContent;
constructor(private route: ActivatedRoute, private _router: Router, private _fb: FormBuilder, constructor(private route: ActivatedRoute, private _router: Router, private _fb: UntypedFormBuilder,
private _helpContentService: HelpContentService, private _clearCacheService: ClearCacheService) { private _helpContentService: HelpContentService, private _clearCacheService: ClearCacheService) {
} }

View File

@ -1,5 +1,5 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {FormBuilder, FormControl, FormGroup} from '@angular/forms'; import {UntypedFormBuilder, UntypedFormControl, UntypedFormGroup} from '@angular/forms';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import { import {
@ -27,7 +27,7 @@ export class PageHelpContentsComponent implements OnInit {
private selectedPageContents: string[] = []; private selectedPageContents: string[] = [];
public checkboxes: CheckPageHelpContent[] = []; public checkboxes: CheckPageHelpContent[] = [];
public pageHelpContents: PageHelpContent[] = []; public pageHelpContents: PageHelpContent[] = [];
public formGroup: FormGroup; public formGroup: UntypedFormGroup;
public pages: Page[]; public pages: Page[];
public checkboxAll: boolean = false; public checkboxAll: boolean = false;
public filters: PageHelpContentFilterOptions = {id: '', active: null, text: new RegExp('')}; public filters: PageHelpContentFilterOptions = {id: '', active: null, text: new RegExp('')};
@ -40,13 +40,13 @@ export class PageHelpContentsComponent implements OnInit {
public page: Page; public page: Page;
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public showLoading: boolean = true; public showLoading: boolean = true;
public filterForm: FormControl; public filterForm: UntypedFormControl;
private subscriptions: any[] = []; private subscriptions: any[] = [];
public selectedKeyword: string; public selectedKeyword: string;
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent; @ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router, constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router,
private _helpService: HelpContentService, private _fb: FormBuilder, private sanitizer: DomSanitizer, private _helpService: HelpContentService, private _fb: UntypedFormBuilder, private sanitizer: DomSanitizer,
private _clearCacheService: ClearCacheService) { private _clearCacheService: ClearCacheService) {
} }

View File

@ -159,19 +159,41 @@
</div> </div>
</div> </div>
<div *ngIf="displayMenuItems && displayMenuItems.length > 0" class="uk-width-1-4@m"> <div *ngIf="displayMenuItems && displayMenuItems.length > 0" class="uk-width-1-4@m">
<h6>Menu settings</h6> <h6>Menu visibility</h6>
<div class="uk-margin-small-bottom"> <div class="uk-margin-small-bottom">
<label (click)="toggleMenu(true, selectedMenuType == 'normalMenu'? false : true )"> <label (click)="toggleMenu(true, selectedMenuType == 'normalMenu'? false : true )">
<input class="uk-radio" type="radio" name="menu" [checked]="(selectedMenuType == 'normalMenu' && showNormalMenu) || (selectedMenuType == 'customMenu' && showFeaturedMenu)"> <input class="uk-radio" type="radio" name="menu" [checked]="(selectedMenuType == 'normalMenu' && showNormalMenu) || (selectedMenuType == 'customMenu' && showFeaturedMenu)">
<span class="uk-margin-small-left">Show menu</span> <span class="uk-margin-small-left">Visible</span>
</label> </label>
</div> </div>
<div> <div>
<label (click)="toggleMenu(false, selectedMenuType == 'normalMenu'? false : true )"> <label (click)="toggleMenu(false, selectedMenuType == 'normalMenu'? false : true )">
<input class="uk-radio" type="radio" name="menu" [checked]="(selectedMenuType == 'normalMenu' && !showNormalMenu) || (selectedMenuType == 'customMenu' && !showFeaturedMenu)"> <input class="uk-radio" type="radio" name="menu" [checked]="(selectedMenuType == 'normalMenu' && !showNormalMenu) || (selectedMenuType == 'customMenu' && !showFeaturedMenu)">
<span class="uk-margin-small-left">Hide menu</span> <span class="uk-margin-small-left">Hidden</span>
</label> </label>
</div> </div>
<h6 class="uk-margin-medium-top">Menu alignment</h6>
<div *ngIf="selectedMenuType == 'customMenu'">
<div>
<label (click)="alignMenu('LEFT')">
<input class="uk-radio" type="radio" name="menuAlign" [checked]="(featuredAlignment == 'LEFT')">
<span class="uk-margin-small-left">Left</span>
</label>
</div>
<div>
<label (click)="alignMenu('CENTER')">
<input class="uk-radio" type="radio" name="menuAlign" [checked]="(featuredAlignment == 'CENTER')">
<span class="uk-margin-small-left">Center</span>
</label>
</div>
<div>
<label (click)="alignMenu('RIGHT')">
<input class="uk-radio" type="radio" name="menuAlign" [checked]="(featuredAlignment == 'RIGHT')">
<span class="uk-margin-small-left">Right</span>
</label>
</div>
</div>
</div> </div>
</div> </div>
<div *ngIf="displayMenuItems && displayMenuItems.length == 0" <div *ngIf="displayMenuItems && displayMenuItems.length == 0"
@ -206,6 +228,25 @@
<div *ngIf="pageStatus != null && !pageStatus.get(menuItemForm.get('route').value) && menuItemForm.get('route').dirty" class="uk-text-center"> <div *ngIf="pageStatus != null && !pageStatus.get(menuItemForm.get('route').value) && menuItemForm.get('route').dirty" class="uk-text-center">
<span class="uk-text-warning">The item is not used because the required page is disabled</span> <span class="uk-text-warning">The item is not used because the required page is disabled</span>
</div> </div>
<!-- <div *ngIf="selectedMenuType == 'customMenu'" class="uk-text-center uk-margin-top">Or <a (click)="newPageWindow()">create a new one</a></div>-->
<!-- <div *ngIf="newPageWindowOpen" class="uk-card uk-card-default uk-card-body uk-margin-top">-->
<!-- <div>-->
<!-- <button (click)="newPageWindow()" class="uk-close uk-icon uk-float-right" uk-close></button>-->
<!-- <h6 class="uk-text-bold uk-margin-remove-top">Create New Page</h6>-->
<!-- </div>-->
<!-- <form *ngIf="pageForm" [formGroup]="pageForm" class="uk grid uk-child-width-1-1" uk-grid>-->
<!-- <div input [formInput]="pageForm.get('name')" type="text" label="Name"-->
<!-- placeholder="Name"></div>-->
<!-- <div input [formInput]="pageForm.get('route')" type="text"-->
<!-- placeholder="Route"></div>-->
<!-- <div class="uk-flex uk-flex-right">-->
<!-- <button [disabled]="!(pageForm.get('name').value && pageForm.get('route').value)"-->
<!-- class="uk-button uk-button-secondary outlined" (click)="createPage()">Create Page-->
<!-- </button>-->
<!-- </div>-->
<!-- </form>-->
<!-- </div>-->
</div> </div>
<!-- <div class="uk-flex" *ngIf="isPortalAdministrator"> <!-- <div class="uk-flex" *ngIf="isPortalAdministrator">
<div class="uk-form-label uk-margin-small-right">Featured</div> <div class="uk-form-label uk-margin-small-right">Featured</div>

View File

@ -11,7 +11,7 @@ import {properties} from "../../../../environments/environment";
import {StringUtils} from "../../utils/string-utils.class"; import {StringUtils} from "../../utils/string-utils.class";
import {Title} from "@angular/platform-browser"; import {Title} from "@angular/platform-browser";
import {AlertModal} from '../../utils/modal/alert'; import {AlertModal} from '../../utils/modal/alert';
import {MenuItemExtended} from '../../sharedComponents/menu'; import {MenuAlignment, MenuItemExtended} from '../../sharedComponents/menu';
import {SearchInputComponent} from '../../sharedComponents/search-input/search-input.component'; import {SearchInputComponent} from '../../sharedComponents/search-input/search-input.component';
import {Option} from '../../sharedComponents/input/input.component'; import {Option} from '../../sharedComponents/input/input.component';
import {CommunityInfo} from '../../connect/community/communityInfo'; import {CommunityInfo} from '../../connect/community/communityInfo';
@ -22,6 +22,9 @@ import {ClearCacheService} from '../../services/clear-cache.service';
import {TransitionGroupComponent} from '../../utils/transition-group/transition-group.component'; import {TransitionGroupComponent} from '../../utils/transition-group/transition-group.component';
import {HelperFunctions} from '../../utils/HelperFunctions.class'; import {HelperFunctions} from '../../utils/HelperFunctions.class';
import {NotificationHandler} from '../../utils/notification-handler'; import {NotificationHandler} from '../../utils/notification-handler';
// import {Page} from "../../utils/entities/adminTool/page";
declare var UIkit;
@Component({ @Component({
selector: 'menuSelector', selector: 'menuSelector',
@ -38,6 +41,8 @@ export class MenuComponent implements OnInit {
private index: number; private index: number;
// public newPageWindowOpen: boolean = false;
public menuItemForm: FormGroup; public menuItemForm: FormGroup;
public pageForm: FormGroup; public pageForm: FormGroup;
public menuTypes = [ public menuTypes = [
@ -57,6 +62,7 @@ export class MenuComponent implements OnInit {
public showNormalMenu: boolean = false; public showNormalMenu: boolean = false;
public showFeaturedMenu: boolean = false; public showFeaturedMenu: boolean = false;
public featuredAlignment: string = MenuAlignment.CENTER.valueOf();
public communities: Portal[] = []; public communities: Portal[] = [];
public portal: string; public portal: string;
@ -150,6 +156,7 @@ export class MenuComponent implements OnInit {
this.normalMenuItems = data.menuItems; this.normalMenuItems = data.menuItems;
this.showFeaturedMenu = data.isFeaturedMenuEnabled; this.showFeaturedMenu = data.isFeaturedMenuEnabled;
this.showNormalMenu = data.isMenuEnabled; this.showNormalMenu = data.isMenuEnabled;
this.featuredAlignment = data.featuredAlignment.valueOf();
this.getPages(); this.getPages();
this.getParentOptions(); this.getParentOptions();
this.showLoading = false; this.showLoading = false;
@ -416,9 +423,72 @@ export class MenuComponent implements OnInit {
} }
this._clearCacheService.clearCache("Menu toggled"); this._clearCacheService.clearCache("Menu toggled");
this._clearCacheService.purgeBrowserCache("Menu toggled", this.portal); this._clearCacheService.purgeBrowserCache("Menu toggled", this.portal);
NotificationHandler.rise("Menu has been <b>successfully toggled to be "+(status?"visible":"hidden")+"</b>");
}, error => { }, error => {
this.handleError("System error toggling menu", error); this.handleError("System error toggling menu", error);
}) })
); );
} }
public alignMenu(alignment: string) {
this.subscriptions.push(
this._helpContentService.alignMenu(MenuAlignment[alignment], this.portal).subscribe(() => {
this.featuredAlignment = alignment;
this._clearCacheService.clearCache("Menu aligned");
this._clearCacheService.purgeBrowserCache("Menu aligned", this.portal);
NotificationHandler.rise("Menu has been <b>successfully "+alignment.toLowerCase()+" aligned</b>");
}, error => {
this.handleError("System error aligning menu to the "+alignment.toLowerCase(), error);
})
);
}
// public newPageWindow() {
// this.newPageWindowOpen = !this.newPageWindowOpen;
// this.pageForm = this._fb.group({
// _id: this._fb.control(null),
// route: this._fb.control('/featured/', [Validators.required, StringUtils.validRoute(this.allPages, 'value'), this.validCustomRoute()]),
// name: this._fb.control('', Validators.required),
// isEnabled: this._fb.control(true),
// portalType: this._fb.control(this.properties.adminToolsPortalType, Validators.required),
// portalPid: this._fb.control(this.portal),
// top: this._fb.control(true),
// bottom: this._fb.control(false),
// left: this._fb.control(false),
// right: this._fb.control(false),
// type: this._fb.control('html', Validators.required),
// entities: this._fb.control([''])
// });
// }
//
// public validCustomRoute(): ValidatorFn {
// return (control: AbstractControl): ValidationErrors | null => {
// if (control.value) {
// if (!control.value.startsWith("/featured")) {
// return {error: 'Custom route should start with /featured'}
// }
// }
// }
// }
//
// public createPage() {
// if(!this.pageForm.value.route.startsWith('/featured')) {
// this.pageForm.value.route = '/featured/'.concat(this.pageForm.value.route);
// }
//
// this.showLoading = true;
// this.subscriptions.push(
// this._helpContentService.savePage(<Page>this.pageForm.value, this.properties.adminToolsAPIURL).subscribe(
// page => {
// this.allPages.push({value: page.route, label: page.name});
// NotificationHandler.rise('Page <b>' + page.name + '</b> has been <b>successfully created</b>');
// this.newPageWindowOpen = !this.newPageWindowOpen;
// this.menuItemForm.get('route').setValue(page.route);
// this.menuItemForm.get('route').markAsDirty();
// this.showLoading = false;
// },
// error => this.handleError('System error creating page', error)
// )
// );
// }
} }

View File

@ -1,11 +1,8 @@
<div page-content> <div page-content>
<div header> <div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info"> <div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<ng-container *ngIf="showLogo">
<img [src]="entity | logoUrl" class="uk-margin-right uk-blend-multiply">
</ng-container>
<div> <div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Pages</div> <div class="uk-text-background uk-text-bold uk-text-small">Manage Pages</div>
<h1 class="uk-h6 uk-margin-remove">{{name ? name : 'Super Admin'}}</h1> <h1 class="uk-h6 uk-margin-remove">{{name ? name : 'Super Admin'}}</h1>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; import {UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {CheckPage, Page} from '../../utils/entities/adminTool/page'; import {CheckPage, Page} from '../../utils/entities/adminTool/page';
import {Entity} from '../../utils/entities/adminTool/entity'; import {Entity} from '../../utils/entities/adminTool/entity';
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
@ -38,7 +38,7 @@ export class PagesComponent implements OnInit {
//public errorMessage: string; //public errorMessage: string;
public pageForm: FormGroup; public pageForm: UntypedFormGroup;
private searchText: RegExp = new RegExp(''); private searchText: RegExp = new RegExp('');
public keyword: string = ''; public keyword: string = '';
@ -53,7 +53,7 @@ export class PagesComponent implements OnInit {
public showLoading: boolean = true; public showLoading: boolean = true;
public isPortalAdministrator = null; public isPortalAdministrator = null;
public filterForm: FormGroup; public filterForm: UntypedFormGroup;
public typeOptions = [{label: 'Search', value: 'search'}, { public typeOptions = [{label: 'Search', value: 'search'}, {
label: 'Share', label: 'Share',
value: 'share' value: 'share'
@ -61,7 +61,7 @@ export class PagesComponent implements OnInit {
label: 'Link', label: 'Link',
value: 'link' value: 'link'
}, {label: 'Other', value: 'other'}]; }, {label: 'Other', value: 'other'}];
public entitiesCtrl: FormArray; public entitiesCtrl: UntypedFormArray;
allEntities: Option[] = []; allEntities: Option[] = [];
private subscriptions: any[] = []; private subscriptions: any[] = [];
public portalUtils: PortalUtils = new PortalUtils(); public portalUtils: PortalUtils = new PortalUtils();
@ -72,7 +72,7 @@ export class PagesComponent implements OnInit {
constructor(private element: ElementRef, private route: ActivatedRoute, constructor(private element: ElementRef, private route: ActivatedRoute,
private title: Title, private title: Title,
private _router: Router, private _helpContentService: HelpContentService, private _router: Router, private _helpContentService: HelpContentService,
private userManagementService: UserManagementService, private _fb: FormBuilder, private userManagementService: UserManagementService, private _fb: UntypedFormBuilder,
private communityService: CommunityService, private communityService: CommunityService,
private stakeholderService: StakeholderService, private stakeholderService: StakeholderService,
private _clearCacheService: ClearCacheService) { private _clearCacheService: ClearCacheService) {

View File

@ -1,9 +1,8 @@
<div page-content> <div page-content>
<div header> <div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info"> <div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<img src="assets/common-assets/placeholder.png" class="uk-margin-right">
<div> <div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Portals</div> <div class="uk-text-background uk-text-bold uk-text-small">Manage Portals</div>
<h1 class="uk-h6 uk-margin-remove">Super Admin</h1> <h1 class="uk-h6 uk-margin-remove">Super Admin</h1>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
import {HelperFunctions} from "../../utils/HelperFunctions.class"; import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {Subscriber} from "rxjs"; import {Subscriber} from "rxjs";
@ -27,8 +27,8 @@ export class PortalsComponent implements OnInit {
public checkboxes: CheckPortal[] = []; public checkboxes: CheckPortal[] = [];
public portals: Portal[] = []; public portals: Portal[] = [];
public portalForm: FormGroup; public portalForm: UntypedFormGroup;
public filterForm: FormGroup; public filterForm: UntypedFormGroup;
private subscriptions: any[] = []; private subscriptions: any[] = [];
private searchText: RegExp = new RegExp(''); private searchText: RegExp = new RegExp('');
@ -42,7 +42,7 @@ export class PortalsComponent implements OnInit {
constructor(private element: ElementRef, private route: ActivatedRoute, constructor(private element: ElementRef, private route: ActivatedRoute,
private title: Title, private title: Title,
private _router: Router, private _helpContentService: HelpContentService, private _fb: FormBuilder, private _router: Router, private _helpContentService: HelpContentService, private _fb: UntypedFormBuilder,
private _clearCacheService: ClearCacheService) { private _clearCacheService: ClearCacheService) {
} }

View File

@ -2,10 +2,10 @@ import {
AfterViewInit, AfterViewInit,
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ElementRef, ElementRef, Inject,
Input, Input,
OnDestroy, OnDestroy,
OnInit, OnInit, PLATFORM_ID,
ViewChild ViewChild
} from "@angular/core"; } from "@angular/core";
import {LayoutService} from "../sidebar/layout.service"; import {LayoutService} from "../sidebar/layout.service";
@ -18,8 +18,8 @@ declare var ResizeObserver;
selector: '[page-content]', selector: '[page-content]',
template: ` template: `
<div id="page_content"> <div id="page_content">
<div id="page_content_sticky_footer" #sticky_footer class="uk-blur-background" <div [class.uk-hidden]="!isBrowser" id="page_content_sticky_footer" #sticky_footer class="uk-tile-default uk-blur-background"
[attr.uk-sticky]="'bottom: true;'" [attr.offset]="footer_offset"> [attr.uk-sticky]="'bottom: true'" [attr.offset]="footer_offset">
<div class="uk-container uk-container-large"> <div class="uk-container uk-container-large">
<div class="uk-padding-small uk-padding-remove-vertical"> <div class="uk-padding-small uk-padding-remove-vertical">
<ng-content select="[sticky_footer]"></ng-content> <ng-content select="[sticky_footer]"></ng-content>
@ -30,19 +30,23 @@ declare var ResizeObserver;
[attr.uk-sticky]="(headerSticky && shouldSticky)?'media: @m':null" [attr.offset]="offset" [attr.uk-sticky]="(headerSticky && shouldSticky)?'media: @m':null" [attr.offset]="offset"
[attr.style]="'margin-top: '+(footer_height? '-'+footer_height+'px': '0')"> [attr.style]="'margin-top: '+(footer_height? '-'+footer_height+'px': '0')">
<div class="uk-container uk-container-large"> <div class="uk-container uk-container-large">
<div class="uk-padding-small uk-padding-remove-vertical"> <div class="uk-padding-small uk-padding-remove-vertical uk-padding-remove-right">
<div class="header">
<ng-content select="[header]"></ng-content> <ng-content select="[header]"></ng-content>
</div> </div>
</div> </div>
</div> </div>
</div>
<div id="page_content_actions" #actions class="uk-blur-background" <div id="page_content_actions" #actions class="uk-blur-background"
[attr.uk-sticky]="(!headerSticky && shouldSticky)?'media: @m':null" [attr.offset]="offset"> [attr.uk-sticky]="(!headerSticky && shouldSticky)?'media: @m':null" [attr.offset]="offset">
<div class="uk-container uk-container-large"> <div class="uk-container uk-container-large">
<div class="uk-padding-small uk-padding-remove-vertical"> <div class="uk-padding-small uk-padding-remove-vertical uk-padding-remove-right">
<div class="actions">
<ng-content select="[actions]"></ng-content> <ng-content select="[actions]"></ng-content>
</div> </div>
</div> </div>
</div> </div>
</div>
<div id="page_content_inner" class="uk-container uk-container-large"> <div id="page_content_inner" class="uk-container uk-container-large">
<div class="uk-padding-small uk-padding-remove-vertical"> <div class="uk-padding-small uk-padding-remove-vertical">
<ng-content select="[inner]"></ng-content> <ng-content select="[inner]"></ng-content>
@ -70,7 +74,8 @@ export class PageContentComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild("sticky_footer") sticky_footer; @ViewChild("sticky_footer") sticky_footer;
subscriptions = []; subscriptions = [];
constructor(private layoutService: LayoutService, private cdr: ChangeDetectorRef) { constructor(private layoutService: LayoutService, private cdr: ChangeDetectorRef,
@Inject(PLATFORM_ID) private platformId) {
} }
ngOnInit() { ngOnInit() {
@ -79,6 +84,10 @@ export class PageContentComponent implements OnInit, AfterViewInit, OnDestroy {
} }
} }
get isBrowser() {
return this.platformId === 'browser';
}
get isStickyActive() { get isStickyActive() {
if (this.header && this.actions && this.shouldSticky) { if (this.header && this.actions && this.shouldSticky) {
let sticky = this.headerSticky ? this.header.nativeElement : this.actions.nativeElement; let sticky = this.headerSticky ? this.header.nativeElement : this.actions.nativeElement;

View File

@ -2,12 +2,15 @@ import {Injectable} from "@angular/core";
import {BehaviorSubject, Observable, Subscriber} from "rxjs"; import {BehaviorSubject, Observable, Subscriber} from "rxjs";
import {ActivationStart, Router} from "@angular/router"; import {ActivationStart, Router} from "@angular/router";
declare var ResizeObserver;
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class LayoutService { export class LayoutService {
public static HEADER_HEIGHT = '65px'; public static HEADER_HEIGHT = '65px';
private deviceBreakpoint: number;
/** /**
* Set this to true when sidebar items are ready. * Set this to true when sidebar items are ready.
@ -28,6 +31,10 @@ export class LayoutService {
* Add hasAdminMenu: true on data of route config, if global sidebar should be used. * Add hasAdminMenu: true on data of route config, if global sidebar should be used.
*/ */
private hasAdminMenuSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); private hasAdminMenuSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
/**
* Add hasInternalSidebar: true on data of route config, if internal sidebar should be used.
*/
private hasInternalSidebarSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
/** /**
* Add isFrontPage: true on data of route config, if current route is for front page. * Add isFrontPage: true on data of route config, if current route is for front page.
*/ */
@ -51,21 +58,42 @@ export class LayoutService {
* Be sure that replaceHeader exists. * Be sure that replaceHeader exists.
*/ */
private replaceHeaderSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); private replaceHeaderSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
private observer: IntersectionObserver; /** Check if the current device is mobile or tablet */
sub: any; private isMobileSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
private subscriptions: any[] = [];
ngOnDestroy() { ngOnDestroy() {
this.clearSubscriptions(); this.clearSubscriptions();
} }
clearSubscriptions() { clearSubscriptions() {
if (this.sub instanceof Subscriber) { this.subscriptions.forEach(subscription => {
this.sub.unsubscribe(); if (subscription instanceof Subscriber) {
subscription.unsubscribe();
} else if(subscription instanceof ResizeObserver) {
subscription.disconnect();
}
})
}
setObserver() {
if(typeof ResizeObserver !== "undefined" && typeof document !== "undefined") {
this.deviceBreakpoint = Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--uk-breakpoint-m').replace('px', '')) + 1;
let resizeObs = new ResizeObserver(entries => {
entries.forEach(entry => {
this.isMobileSubject.next(entry.target.clientWidth < this.deviceBreakpoint);
})
});
this.subscriptions.push(resizeObs);
resizeObs.observe(document.documentElement);
} }
} }
constructor(private router: Router) { constructor(private router: Router) {
this.sub = this.router.events.subscribe(event => { if(typeof window !== 'undefined') {
this.isMobileSubject.next(window.innerWidth < this.deviceBreakpoint);
}
this.subscriptions.push(this.router.events.subscribe(event => {
if (event instanceof ActivationStart) { if (event instanceof ActivationStart) {
this.setReplaceHeader(false); this.setReplaceHeader(false);
let data = event.snapshot.data; let data = event.snapshot.data;
@ -93,6 +121,12 @@ export class LayoutService {
} else { } else {
this.setHasAdminMenu(false); this.setHasAdminMenu(false);
} }
if (data['hasInternalSidebar'] !== undefined &&
data['hasInternalSidebar'] === true) {
this.setHasInternalSidebar(true);
} else {
this.setHasInternalSidebar(false);
}
if (data['isFrontPage'] !== undefined && if (data['isFrontPage'] !== undefined &&
data['isFrontPage'] === true) { data['isFrontPage'] === true) {
this.setFrontPage(true); this.setFrontPage(true);
@ -118,7 +152,8 @@ export class LayoutService {
this.setActiveMenuItem(''); this.setActiveMenuItem('');
} }
} }
}); }));
this.setObserver();
} }
get open(): boolean { get open(): boolean {
@ -145,7 +180,6 @@ export class LayoutService {
this.hasHeaderSubject.next(value); this.hasHeaderSubject.next(value);
} }
get hasAdminMenu(): Observable<boolean> { get hasAdminMenu(): Observable<boolean> {
return this.hasAdminMenuSubject.asObservable(); return this.hasAdminMenuSubject.asObservable();
} }
@ -154,6 +188,14 @@ export class LayoutService {
this.hasAdminMenuSubject.next(value); this.hasAdminMenuSubject.next(value);
} }
get hasInternalSidebar(): Observable<boolean> {
return this.hasInternalSidebarSubject.asObservable();
}
setHasInternalSidebar(value: boolean) {
this.hasInternalSidebarSubject.next(value);
}
get isFrontPage(): Observable<boolean> { get isFrontPage(): Observable<boolean> {
return this.isFrontPageSubject.asObservable(); return this.isFrontPageSubject.asObservable();
} }
@ -166,6 +208,10 @@ export class LayoutService {
return this.replaceHeaderSubject.asObservable(); return this.replaceHeaderSubject.asObservable();
} }
get replaceHeaderValue(): boolean {
return this.replaceHeaderSubject.getValue();
}
setReplaceHeader(value: boolean) { setReplaceHeader(value: boolean) {
this.replaceHeaderSubject.next(value); this.replaceHeaderSubject.next(value);
} }
@ -193,4 +239,12 @@ export class LayoutService {
setActiveMenuItem(value: string) { setActiveMenuItem(value: string) {
this.activeMenuItemSubject.next(value); this.activeMenuItemSubject.next(value);
} }
get isMobile(): Observable<boolean> {
return this.isMobileSubject.asObservable();
}
get isMobileValue(): boolean {
return this.isMobileSubject.getValue();
}
} }

View File

@ -1,21 +1,28 @@
<aside id="sidebar_main"> <aside id="sidebar_main">
<div id="sidebar_content"> <div id="sidebar_content">
<div *ngIf="items.length > 0" class="menu_section uk-margin-xlarge-top" style="min-height: 30vh"> <div *ngIf="items.length > 0" class="menu_section uk-margin-large-top" style="min-height: 30vh">
<ul class="uk-list uk-nav uk-nav-default" uk-nav> <ul #nav class="uk-list uk-nav uk-nav-default uk-nav-parent-icon" uk-nav="duration: 400">
<ng-template ngFor [ngForOf]="items" let-item let-i="index"> <ng-template ngFor [ngForOf]="items" let-item>
<li [class.uk-active]="isTheActiveMenuItem(item)" <li [class.uk-active]="isTheActiveMenuItem(item)"
[class.uk-open]="isTheActiveMenuItem(item)" [class.uk-parent]="item.items.length > 0">
[class.uk-parent]="item.items.length > 1"> <a [routerLink]="getItemRoute(item)" [title]="item.title"
<a *ngIf="item.items.length <= 1" [routerLink]="(item.route)?item.route:null" [queryParams]="item.route?item.params:null" [queryParamsHandling]="item.route?queryParamsHandling:null">
[title]="item.title"
[queryParams]=item.params [queryParamsHandling]="queryParamsHandling">
<div class="uk-flex uk-flex-middle uk-flex-center"> <div class="uk-flex uk-flex-middle uk-flex-center">
<div *ngIf="item.icon" class="uk-width-auto"> <div *ngIf="item.icon && (item.icon.svg || item.icon.name)" class="uk-width-auto">
<icon class="menu-icon" [customClass]="item.icon.class" [name]="item.icon.name" [svg]="item.icon.svg" [flex]="true"></icon> <icon class="menu-icon" [customClass]="item.icon.class" [name]="item.icon.name" ratio="0.9" [svg]="item.icon.svg" [flex]="true"></icon>
</div> </div>
<span *ngIf="open || !item.icon" [class.uk-text-small]="!open" class="uk-width-expand uk-text-truncate uk-margin-small-left">{{item.title}}</span> <span *ngIf="open || !item.icon" [class.uk-text-small]="!open" class="uk-width-expand uk-text-truncate uk-margin-small-left">{{item.title}}</span>
<span *ngIf="item.items?.length > 0"></span>
</div> </div>
</a> </a>
<ul *ngIf="item.items?.length > 0 && (isBrowser || isTheActiveMenuItem(item))" class="uk-nav-sub">
<li *ngFor="let subItem of item.items"
[class.uk-active]="isTheActiveMenuItem(item, subItem)">
<a [routerLink]="subItem.route?subItem.route:null" [queryParams]="subItem.route?subItem.params:null"
[queryParamsHandling]="subItem.route?queryParamsHandling:null" [title]="subItem.title">
<span class="uk-text-truncate">{{subItem.title}}</span></a>
</li>
</ul>
</li> </li>
</ng-template> </ng-template>
</ul> </ul>

View File

@ -1,27 +1,41 @@
import {Component, Input, OnInit} from '@angular/core'; import {AfterViewInit, Component, ElementRef, Inject, Input, PLATFORM_ID, ViewChild} from '@angular/core';
import {MenuItem} from "../../../sharedComponents/menu"; import {MenuItem} from "../../../sharedComponents/menu";
import {ActivatedRoute, QueryParamsHandling, Router} from "@angular/router"; import {ActivatedRoute, Router} from "@angular/router";
import {DomSanitizer} from "@angular/platform-browser"; import {DomSanitizer} from "@angular/platform-browser";
import {properties} from "../../../../../environments/environment"; import {properties} from "../../../../../environments/environment";
import {LayoutService} from "./layout.service"; import {LayoutService} from "./layout.service";
declare var UIkit;
@Component({ @Component({
selector: 'dashboard-sidebar', selector: 'dashboard-sidebar',
templateUrl: 'sideBar.component.html' templateUrl: 'sideBar.component.html'
}) })
export class SideBarComponent implements OnInit { export class SideBarComponent implements AfterViewInit {
@Input() items: MenuItem[] = []; @Input() items: MenuItem[] = [];
@Input() activeItem: string = ''; @Input() activeItem: string = '';
@Input() activeSubItem: string = ''; @Input() activeSubItem: string = '';
@Input() specialMenuItem: MenuItem = null; @Input() specialMenuItem: MenuItem = null;
@Input() queryParamsHandling; @Input() queryParamsHandling;
properties; @ViewChild("nav") nav: ElementRef
public properties = properties;
constructor(private route: ActivatedRoute, private router: Router, private sanitizer: DomSanitizer, private layoutService: LayoutService) { constructor(private route: ActivatedRoute, private router: Router,
this.properties = properties; private sanitizer: DomSanitizer, private layoutService: LayoutService,
@Inject(PLATFORM_ID) private platformId) {}
ngAfterViewInit() {
if(this.nav && typeof UIkit !== "undefined") {
setTimeout(() => {
if(this.items[this.activeIndex]?.items?.length > 0) {
UIkit.nav(this.nav.nativeElement).toggle(this.activeIndex, true);
}
});
}
} }
ngOnInit(): void { get isBrowser() {
return this.platformId === 'browser';
} }
get currentRoute() { get currentRoute() {
@ -35,6 +49,15 @@ export class SideBarComponent implements OnInit {
return this.items?this.items.findIndex(item => this.isTheActiveMenuItem(item)):0; return this.items?this.items.findIndex(item => this.isTheActiveMenuItem(item)):0;
} }
getItemRoute(item: MenuItem) {
if(this.activeSubItem && item.items.length > 0) {
let subItem = item.items.find(subItem => subItem._id === this.activeSubItem);
return subItem?subItem.route:(item.route?item.route:null);
} else {
return item.route?item.route:null;
}
}
isTheActiveMenuItem(item: MenuItem, subItem: MenuItem = null): boolean { isTheActiveMenuItem(item: MenuItem, subItem: MenuItem = null): boolean {
if (this.activeItem || this.activeSubItem) { if (this.activeItem || this.activeSubItem) {
return (!subItem && this.activeItem === item._id) || return (!subItem && this.activeItem === item._id) ||

View File

@ -1,5 +1,5 @@
import {Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild} from '@angular/core'; import {Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild} from '@angular/core';
import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms'; import {UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators} from '@angular/forms';
import {AlertModal} from "../../../utils/modal/alert"; import {AlertModal} from "../../../utils/modal/alert";
import {UserRegistryService} from "../../../services/user-registry.service"; import {UserRegistryService} from "../../../services/user-registry.service";
import {EnvProperties} from "../../../utils/properties/env-properties"; import {EnvProperties} from "../../../utils/properties/env-properties";
@ -46,16 +46,16 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
public loadActive: boolean = true; public loadActive: boolean = true;
public loadPending: boolean = true; public loadPending: boolean = true;
public selectedUser: string = null; public selectedUser: string = null;
public invited: FormControl; public invited: UntypedFormControl;
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public exists: boolean = true; public exists: boolean = true;
public roleFb: FormGroup; public roleFb: UntypedFormGroup;
/** Paging */ /** Paging */
activePage: number = 1; activePage: number = 1;
pendingPage: number = 1; pendingPage: number = 1;
pageSize: number = 10; pageSize: number = 10;
/** Search */ /** Search */
filterForm: FormGroup; filterForm: UntypedFormGroup;
@ViewChild('inviteModal') inviteModal: AlertModal; @ViewChild('inviteModal') inviteModal: AlertModal;
@ViewChild('deleteModal') deleteModal: AlertModal; @ViewChild('deleteModal') deleteModal: AlertModal;
@ViewChild('deletePendingModal') deletePendingModal: AlertModal; @ViewChild('deletePendingModal') deletePendingModal: AlertModal;
@ -65,7 +65,7 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges {
private userManagementService: UserManagementService, private userManagementService: UserManagementService,
private notificationService: NotificationService, private notificationService: NotificationService,
private router: Router, private router: Router,
private fb: FormBuilder) { private fb: UntypedFormBuilder) {
} }
ngOnInit() { ngOnInit() {

View File

@ -1,19 +1,23 @@
import { Injectable, Inject, PLATFORM_ID } from '@angular/core'; import {Injectable, Inject, PLATFORM_ID, Optional} from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http'; import {HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse, HttpHeaders} from '@angular/common/http';
import { Observable, of } from 'rxjs'; import {Observable, of} from 'rxjs';
import { tap } from 'rxjs/operators'; import {tap} from 'rxjs/operators';
import { TransferState, makeStateKey, StateKey } from '@angular/platform-browser'; import {TransferState, makeStateKey, StateKey} from '@angular/platform-browser';
import { isPlatformServer } from '@angular/common'; import {isPlatformServer} from '@angular/common';
import {properties} from "../../environments/environment"; import {properties} from "../../environments/environment";
import {REQUEST} from "./utils/tokens";
import * as Xhr2 from 'xhr2';
Xhr2.prototype._restrictedHeaders = {};
@Injectable() @Injectable()
export class HttpInterceptorService implements HttpInterceptor { export class HttpInterceptorService implements HttpInterceptor {
private static HTTP_WHITELIST = [ properties.monitorServiceAPIURL + '/stakeholder' ]; private static HTTP_WHITELIST = [];
constructor(private transferState: TransferState, @Inject(PLATFORM_ID) private platformId: any) {} constructor(private transferState: TransferState, @Inject(PLATFORM_ID) private platformId: any, @Optional() @Inject(REQUEST) protected req: any) {
}
public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (request.method !== 'GET' || this.isService(request, HttpInterceptorService.HTTP_WHITELIST)) { if (request.method !== 'GET' || this.isService(request, HttpInterceptorService.HTTP_WHITELIST)) {
return next.handle(request); return next.handle(request);
} }
@ -31,7 +35,14 @@ export class HttpInterceptorService implements HttpInterceptor {
return of(response); return of(response);
} else { } else {
if (isPlatformServer(this.platformId)) { if (isPlatformServer(this.platformId)) {
return next.handle(request).pipe(tap((event) => { let headers = new HttpHeaders();
if(request.withCredentials) {
headers = headers.set('Cookie', this.req.get('Cookie'));
}
const authReq = request.clone({
headers: headers
});
return next.handle(authReq).pipe(tap((event) => {
//console.info("server add: ", key); //console.info("server add: ", key);
this.transferState.set(key, (<HttpResponse<any>>event).body); this.transferState.set(key, (<HttpResponse<any>>event).body);
})); }));
@ -41,8 +52,8 @@ export class HttpInterceptorService implements HttpInterceptor {
} }
} }
isService(req: HttpRequest<any>, service: string | string[]):boolean { isService(req: HttpRequest<any>, service: string | string[]): boolean {
if(Array.isArray(service)) { if (Array.isArray(service)) {
return !!service.find(element => req.url.indexOf(element) !== -1); return !!service.find(element => req.url.indexOf(element) !== -1);
} else { } else {
return req.url.indexOf(service) !== -1; return req.url.indexOf(service) !== -1;

View File

@ -68,8 +68,8 @@ export class DataProviderComponent {
// Statistics tab variables // Statistics tab variables
public statsClicked: boolean = false; public statsClicked: boolean = false;
@ViewChild('statisticsModal') statisticsModal; // @ViewChild('statisticsModal') statisticsModal;
@ViewChild('relatedDatasourcesModal') relatedDatasourcesModal; // @ViewChild('relatedDatasourcesModal') relatedDatasourcesModal;
@ViewChild('addThisModal') addThisModal @ViewChild('addThisModal') addThisModal
// Variables for publications, research data, projects, datasources, related datasources tabs // Variables for publications, research data, projects, datasources, related datasources tabs
@ -672,21 +672,21 @@ export class DataProviderComponent {
return !(this.totalViews != null && this.totalDownloads != null && this.pageViews != null) || this.totalViews > 0 || this.totalDownloads > 0 || this.pageViews > 0; return !(this.totalViews != null && this.totalDownloads != null && this.pageViews != null) || this.totalViews > 0 || this.totalDownloads > 0 || this.pageViews > 0;
} }
public openStatistics() { // public openStatistics() {
this.statsClicked = true; // this.statsClicked = true;
this.statisticsModal.cancelButton = false; // this.statisticsModal.cancelButton = false;
this.statisticsModal.okButton = false; // this.statisticsModal.okButton = false;
this.statisticsModal.alertTitle = "Statistics of"; // this.statisticsModal.alertTitle = "Statistics of";
this.statisticsModal.open(); // this.statisticsModal.open();
} // }
//
public openRelatedDatasources() { // public openRelatedDatasources() {
this.searchRelatedDatasources(1, 0); // this.searchRelatedDatasources(1, 0);
this.relatedDatasourcesModal.cancelButton = false; // this.relatedDatasourcesModal.cancelButton = false;
this.relatedDatasourcesModal.okButton = false; // this.relatedDatasourcesModal.okButton = false;
this.relatedDatasourcesModal.alertTitle = "Related "+this.openaireEntities.DATASOURCES+" of"; // this.relatedDatasourcesModal.alertTitle = "Related "+this.openaireEntities.DATASOURCES+" of";
this.relatedDatasourcesModal.open(); // this.relatedDatasourcesModal.open();
} // }
public openAddThisModal() { public openAddThisModal() {
this.addThisModal.cancelButton = false; this.addThisModal.cancelButton = false;

View File

@ -6,7 +6,7 @@ import{EnvProperties} from '../../utils/properties/env-properties';
import {map} from "rxjs/operators"; import {map} from "rxjs/operators";
import {ParsingFunctions} from "../landing-utils/parsingFunctions.class"; import {ParsingFunctions} from "../landing-utils/parsingFunctions.class";
import {OpenaireEntities} from "../../utils/properties/searchFields"; import {OpenaireEntities} from "../../utils/properties/searchFields";
import {Identifier} from "../../utils/string-utils.class"; import {Identifier, StringUtils} from "../../utils/string-utils.class";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
@ -138,8 +138,14 @@ export class DataProviderService {
this.dataProviderInfo.relcanId = ParsingFunctions.parseRelCanonicalId(this.dataProviderInfo.record, "datasource"); this.dataProviderInfo.relcanId = ParsingFunctions.parseRelCanonicalId(this.dataProviderInfo.record, "datasource");
if(data[0] != null) { if(data[0] != null) {
this.dataProviderInfo.title = {"name": (data[0].englishname)?data[0].englishname: data[0].officialname, "url": data[0].websiteurl}; this.dataProviderInfo.title = {"name": "", "url": data[0].websiteurl};
this.dataProviderInfo.officialName = data[0].officialname; if(data[0].officialname) {
this.dataProviderInfo.title.name = StringUtils.HTMLToString(String(data[0].officialname));
this.dataProviderInfo.officialName = StringUtils.HTMLToString(String(data[0].officialname));
}
if(data[0].englishname) {
this.dataProviderInfo.title.name = StringUtils.HTMLToString(String(data[0].englishname));
}
var pattern = /.{12}::.+/; var pattern = /.{12}::.+/;
var originalIds =(data[0].originalId)?data[0].originalId:""; var originalIds =(data[0].originalId)?data[0].originalId:"";

View File

@ -11,7 +11,7 @@ import {
} from "@angular/core"; } from "@angular/core";
import {ResultLandingInfo} from "../../utils/entities/resultLandingInfo"; import {ResultLandingInfo} from "../../utils/entities/resultLandingInfo";
import {EnvProperties} from "../../utils/properties/env-properties"; import {EnvProperties} from "../../utils/properties/env-properties";
import {FormArray, FormBuilder, FormGroup, Validators} from "@angular/forms"; import {UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators} from "@angular/forms";
import {AlertModal} from "../../utils/modal/alert"; import {AlertModal} from "../../utils/modal/alert";
import {HelperFunctions} from "../../utils/HelperFunctions.class"; import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {OrganizationInfo} from "../../utils/entities/organizationInfo"; import {OrganizationInfo} from "../../utils/entities/organizationInfo";
@ -43,12 +43,12 @@ export class FeedbackComponent implements OnInit, OnChanges {
public sending: boolean = false; public sending: boolean = false;
public sent: boolean = false; public sent: boolean = false;
public error: boolean = false; public error: boolean = false;
public form: FormGroup; public form: UntypedFormGroup;
public url: string = null; public url: string = null;
public recipients: string[] = []; public recipients: string[] = [];
subscriptions = []; subscriptions = [];
constructor(private fb: FormBuilder, constructor(private fb: UntypedFormBuilder,
private emailService: EmailService) { private emailService: EmailService) {
} }
@ -94,7 +94,7 @@ export class FeedbackComponent implements OnInit, OnChanges {
} }
public addIssue() { public addIssue() {
let issue: FormGroup = this.fb.group({ let issue: UntypedFormGroup = this.fb.group({
field: this.fb.control(this.preSelectedField, Validators.required), field: this.fb.control(this.preSelectedField, Validators.required),
report: this.fb.control('', Validators.required) report: this.fb.control('', Validators.required)
}); });
@ -105,8 +105,8 @@ export class FeedbackComponent implements OnInit, OnChanges {
this.issues.removeAt(index); this.issues.removeAt(index);
} }
public get issues(): FormArray { public get issues(): UntypedFormArray {
return <FormArray>this.form.get('issues'); return <UntypedFormArray>this.form.get('issues');
} }
changeShowForm(value: boolean) { changeShowForm(value: boolean) {

View File

@ -49,7 +49,7 @@ import {AlertModal} from "../../../utils/modal/alert";
class="uk-text-primary">Under curation</span> class="uk-text-primary">Under curation</span>
</span> </span>
</div> </div>
<div [class]="isSticky ? 'uk-margon-bottom' : 'uk-margin-medium-bottom'"> <div [class]="isSticky ? 'uk-margin-bottom' : 'uk-margin-medium-bottom'">
<showTitle [titleName]="title" classNames="uk-margin-remove-bottom"></showTitle> <showTitle [titleName]="title" classNames="uk-margin-remove-bottom"></showTitle>
<div *ngIf="subTitle"> <div *ngIf="subTitle">
<span class="uk-text-meta uk-text-small" [innerHTML]="subTitle"></span> <span class="uk-text-meta uk-text-small" [innerHTML]="subTitle"></span>

View File

@ -10,7 +10,7 @@ import {StringUtils} from "../../utils/string-utils.class";
export class ParsingFunctions { export class ParsingFunctions {
public eoscSubjects = [ public eoscSubjects = [
{label: 'EOSC::Jupyter Notebook', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'marketplace.eosc-portal.eu/services?tag=EOSC%3A%3AJupyter+Notebook', value: 'Jupyter Notebook'}, {label: 'EOSC::Jupyter Notebook', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'marketplace.eosc-portal.eu/services?tag=EOSC%3A%3AJupyter+Notebook', value: 'Jupyter Notebook'},
{label: 'EOSC::RO-crate', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'marketplace.eosc-portal.eu/services?tag=EOSC%3A%3ARO-crate', value: 'RO-crate'}, {label: 'EOSC::RO-crate', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'marketplace.eosc-portal.eu/datasources/eosc.psnc.6f0470e3bb9203ec3a7553f3a72a7a1f?q=ROHub', value: 'RO-crate'},
{label: 'EOSC::Galaxy Workflow', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'marketplace.eosc-portal.eu/services?tag=EOSC%3A%3AGalaxy+Workflow', value: 'Galaxy Workflow'}, {label: 'EOSC::Galaxy Workflow', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'marketplace.eosc-portal.eu/services?tag=EOSC%3A%3AGalaxy+Workflow', value: 'Galaxy Workflow'},
{label: 'EOSC::Twitter Data', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'marketplace.eosc-portal.eu/services?tag=EOSC%3A%3ATwitter+Data', value: 'Twitter Data'} {label: 'EOSC::Twitter Data', link: 'https://' + (properties.environment != 'production'?'beta.':'') + 'marketplace.eosc-portal.eu/services?tag=EOSC%3A%3ATwitter+Data', value: 'Twitter Data'}
] ]
@ -802,7 +802,7 @@ export class ParsingFunctions {
if(stripHTML) { if(stripHTML) {
return abstracts.join(' '); return abstracts.join(' ');
} else { } else {
return abstracts.length > 0 ? ('<p>' + abstracts.join('</p><p>') + '</p>') : abstracts.join(' '); return abstracts.length > 0 ? ('<p>' + abstracts.join('</p> <p>') + '</p>') : abstracts.join(' ');
} }
} }
} }

View File

@ -70,8 +70,8 @@ export class OrganizationComponent {
public activeTab: string = ""; public activeTab: string = "";
@ViewChild('downloadReportsModal') downloadReportsModal; @ViewChild('downloadReportsModal') downloadReportsModal;
@ViewChild('downloadReportModal') downloadReportModal; // @ViewChild('downloadReportModal') downloadReportModal;
@ViewChild('downloadFunderReportModal') downloadFunderReportModal; // @ViewChild('downloadFunderReportModal') downloadFunderReportModal;
@ViewChild('addThisModal') addThisModal; @ViewChild('addThisModal') addThisModal;
@ViewChild(ModalLoading) loading: ModalLoading; @ViewChild(ModalLoading) loading: ModalLoading;
@ -118,7 +118,7 @@ export class OrganizationComponent {
public feedbackFields: string [] = ['Name', 'Country', 'Other']; public feedbackFields: string [] = ['Name', 'Country', 'Other'];
@ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference; @ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference;
@ViewChild('projectsModal') projectsModal; // @ViewChild('projectsModal') projectsModal;
public deleteByInferenceOpened: boolean = false; public deleteByInferenceOpened: boolean = false;

View File

@ -80,8 +80,8 @@ export class ProjectComponent {
// Active tab variable for responsiveness // Active tab variable for responsiveness
public activeTab: string = ""; public activeTab: string = "";
@ViewChild('statisticsModal') statisticsModal; // @ViewChild('statisticsModal') statisticsModal;
@ViewChild('linkProjectModal') linkProjectModal; // @ViewChild('linkProjectModal') linkProjectModal;
@ViewChild('embedResultsModal') embedResultsModal; @ViewChild('embedResultsModal') embedResultsModal;
@ViewChild('downloadReportModal') downloadReportModal; @ViewChild('downloadReportModal') downloadReportModal;
@ViewChild('addThisModal') addThisModal @ViewChild('addThisModal') addThisModal

View File

@ -9,6 +9,7 @@ import{EnvProperties} from '../../utils/properties/env-properties';
import { ParsingFunctions } from '../landing-utils/parsingFunctions.class'; import { ParsingFunctions } from '../landing-utils/parsingFunctions.class';
import {map} from "rxjs/operators"; import {map} from "rxjs/operators";
import {StringUtils} from "../../utils/string-utils.class";
@Injectable() @Injectable()
export class ProjectService { export class ProjectService {
@ -123,7 +124,11 @@ export class ProjectService {
// ['result']['metadata']['oaf:entity']['oaf:project'] // ['result']['metadata']['oaf:entity']['oaf:project']
if(data[0] != null) { if(data[0] != null) {
this.projectInfo.acronym = data[0].acronym; this.projectInfo.acronym = data[0].acronym;
this.projectInfo.title = Array.isArray(data[0]['title']) ? data[0].title[0] : data[0].title; if(data[0]['title']) {
this.projectInfo.title = Array.isArray(data[0]['title']) ? StringUtils.HTMLToString(String(data[0].title[0])) : StringUtils.HTMLToString(String(data[0].title));
} else {
this.projectInfo.title = "";
}
this.projectInfo.funding.code = data[0].code; this.projectInfo.funding.code = data[0].code;
if(data[0].startdate) { if(data[0].startdate) {
let date: number = Date.parse(data[0].startdate); let date: number = Date.parse(data[0].startdate);

View File

@ -49,7 +49,7 @@ export class DeletedByInferenceService {
result.dateofacceptance = data.dateofacceptance; result.dateofacceptance = data.dateofacceptance;
result.embargoEndDate = data.embargoenddate; result.embargoEndDate = data.embargoenddate;
result.description = this.parsingFunctions.parseDescription(data.description); result.description = this.parsingFunctions.parseDescription(data.description, true);
if(data['bestaccessright'] && data['bestaccessright'].hasOwnProperty("classname")) { if(data['bestaccessright'] && data['bestaccessright'].hasOwnProperty("classname")) {
result.accessMode = data['bestaccessright'].classname; result.accessMode = data['bestaccessright'].classname;

View File

@ -53,7 +53,7 @@
</a> </a>
</li> </li>
<!-- ORCID --> <!-- ORCID -->
<li *ngIf="properties.adminToolsPortalType == 'explore' || properties.adminToolsPortalType == 'community'" <li *ngIf="properties.adminToolsPortalType == 'explore' || properties.adminToolsPortalType == 'community' || properties.adminToolsPortalType == 'aggregator'"
class="uk-text-center"> class="uk-text-center">
<orcid-work [resultId]="id" [resultTitle]="resultLandingInfo.title" [resultLandingInfo]="resultLandingInfo" <orcid-work [resultId]="id" [resultTitle]="resultLandingInfo.title" [resultLandingInfo]="resultLandingInfo"
[pids]="pidsArrayString" [pageType]="'landing'"> [pids]="pidsArrayString" [pageType]="'landing'">
@ -149,7 +149,7 @@
</a> </a>
</div> </div>
<!-- ORCID --> <!-- ORCID -->
<div *ngIf="properties.adminToolsPortalType == 'explore' || properties.adminToolsPortalType == 'community'" <div *ngIf="properties.adminToolsPortalType == 'explore' || properties.adminToolsPortalType == 'community' || properties.adminToolsPortalType == 'aggregator'"
class="uk-margin-small-right"> class="uk-margin-small-right">
<orcid-work [resultId]="id" [resultTitle]="resultLandingInfo.title" [resultLandingInfo]="resultLandingInfo" <orcid-work [resultId]="id" [resultTitle]="resultLandingInfo.title" [resultLandingInfo]="resultLandingInfo"
[pids]="pidsArrayString" [pageType]="'landing'"> [pids]="pidsArrayString" [pageType]="'landing'">
@ -446,32 +446,23 @@
<ng-template #right_column> <ng-template #right_column>
<div class="uk-margin-medium-top uk-list uk-list-large uk-padding uk-padding-remove-vertical" [class.uk-list-divider]="!viewAll"> <div class="uk-margin-medium-top uk-list uk-list-large uk-padding uk-padding-remove-vertical" [class.uk-list-divider]="!viewAll">
<!-- EOSC Services--> <!-- EOSC Services-->
<!-- 1 link --> <div *ngIf="resultLandingInfo.eoscSubjects?.length > 0 && properties.adminToolsPortalType == 'eosc'
<div *ngIf="resultLandingInfo.eoscSubjects?.length == 1 && properties.adminToolsPortalType == 'eosc'
&& (!viewAll || viewAll=='egiNotebook')"> && (!viewAll || viewAll=='egiNotebook')">
<a class="uk-link-text uk-text-bold custom-external" <div class="uk-flex uk-flex-between uk-flex-middle uk-margin-small-bottom">
target="_blank" [href]="resultLandingInfo.eoscSubjects[0].link"> <span class="uk-text-light-grey uk-text-nowrap uk-margin-small-right">Compatible EOSC Services</span>
</div>
<div class="uk-margin-small-bottom uk-flex">
<img src="assets/common-assets/eosc-logo.png" <img src="assets/common-assets/eosc-logo.png"
loading="lazy" alt="eosc_logo" style="width:27px; height:27px"> loading="lazy" alt="eosc_logo" style="width:27px; height:27px">
<span class="uk-margin-small-left uk-text-uppercase"><u>Check compatible EOSC services</u></span> <div class="uk-margin-small-left uk-flex uk-flex-column uk-flex-center">
</a> <div *ngFor="let subject of resultLandingInfo.eoscSubjects; let i=index" class="uk-text-truncate">
</div> <a [href]="subject.link" target="_blank" class="custom-external">{{subject.value}}</a>
<!-- more than 1 links -->
<div *ngIf="resultLandingInfo.eoscSubjects?.length > 1 && properties.adminToolsPortalType == 'eosc'
&& (!viewAll || viewAll=='egiNotebook')">
<a class="uk-link-text uk-text-bold">
<img src="assets/common-assets/eosc-logo.png"
loading="lazy" alt="eosc_logo" style="width:27px; height:27px">
<span class="uk-margin-small-left uk-text-uppercase"><u>Check compatible EOSC services</u></span>
</a>
<div class="uk-dropdown" uk-dropdown="pos: bottom-right; offset: 10; delay-hide: 0; mode:click">
<ul class="uk-nav uk-dropdown-nav">
<li *ngFor="let item of resultLandingInfo.eoscSubjects">
<a [href]="item.link" target="_blank" class="custom-external">{{item.value}}</a>
</li>
</ul>
</div> </div>
</div> </div>
</div>
</div>
<div *ngIf="resultLandingInfo.sdg && resultLandingInfo.sdg.length > 0 && (!viewAll || viewAll=='sdg')"> <div *ngIf="resultLandingInfo.sdg && resultLandingInfo.sdg.length > 0 && (!viewAll || viewAll=='sdg')">
<sdg [subjects]="resultLandingInfo.sdg" (viewAllClicked)="viewAll=$event" (feedbackClicked)="feedbackClicked('Sustainable Development Goals (SDGs)')"></sdg> <sdg [subjects]="resultLandingInfo.sdg" (viewAllClicked)="viewAll=$event" (feedbackClicked)="feedbackClicked('Sustainable Development Goals (SDGs)')"></sdg>
</div> </div>

View File

@ -37,11 +37,11 @@ export class ResultLandingComponent {
@Input() piwikSiteId = properties.piwikSiteId; @Input() piwikSiteId = properties.piwikSiteId;
@Input() communityId = null; @Input() communityId = null;
enermapsId; enermapsId;
@ViewChild('linkModal') linkModal; // @ViewChild('linkModal') linkModal;
@ViewChild('citeModal') citeModal; @ViewChild('citeModal') citeModal;
@ViewChild('addThisModal') addThisModal; @ViewChild('addThisModal') addThisModal;
@ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference; @ViewChild('AlertModalDeletedByInference') alertModalDeletedByInference;
@ViewChild('relationModal') relationModal; // @ViewChild('relationModal') relationModal;
public deleteByInferenceOpened: boolean = false; public deleteByInferenceOpened: boolean = false;
@Input() public resultFromInput: boolean = false; @Input() public resultFromInput: boolean = false;
@Input() public resultLandingInfo: ResultLandingInfo; @Input() public resultLandingInfo: ResultLandingInfo;
@ -118,7 +118,7 @@ export class ResultLandingComponent {
public isLoggedIn: boolean = false; public isLoggedIn: boolean = false;
public pid: string; public pid: string;
@ViewChild("annotation") annotation: AnnotationComponent; // @ViewChild("annotation") annotation: AnnotationComponent;
public contextsWithLink: any; public contextsWithLink: any;
public relatedClassFilters: Option[]=[{"label": "All relations", "value": ""}]; public relatedClassFilters: Option[]=[{"label": "All relations", "value": ""}];
@ -743,12 +743,12 @@ export class ResultLandingComponent {
} }
} }
public openLinkModal() { // public openLinkModal() {
this.linkModal.cancelButton = false; // this.linkModal.cancelButton = false;
this.linkModal.okButton = false; // this.linkModal.okButton = false;
this.linkModal.alertTitle = "Link this " + this.getTypeName() + " to"; // this.linkModal.alertTitle = "Link this " + this.getTypeName() + " to";
this.linkModal.open(); // this.linkModal.open();
} // }
public openCiteModal() { public openCiteModal() {
this.citeThisClicked = true; this.citeThisClicked = true;
@ -800,11 +800,14 @@ export class ResultLandingComponent {
); );
// console.log("rich content " + allow) // console.log("rich content " + allow)
//spam words to exclude - need to be in lower case //spam words to exclude - need to be in lower case
let title_authors_words = ["movie","hd","film","kimetsu", "1080p","4k","call of duty", "mobile hack", "tubydi", "电影","電影","download ebook","download [ebook]","düşük hapı", "düşük hapi"];
let title_authors_words = ["movie","hd","film","kimetsu", "1080p","4k","call of duty", "mobile hack", "tubydi", "电影","電影","download ebook","download [ebook]","düşük hapı", "düşük hapi",
"protocolo raikov", "top gun maverick streaming vf", "expensive candy full movie", "sigma game download", "阿凡達2線上看", "lack adam torrent magnet",
"원피스 필름 레드 다시보기", "원피스 필름 레드 자막 다시보기", "gtatogel", "gta to gel"];
let abstract_words = ["operacao-feliz-natal.blogspot.com", "moviedouban.site", "hack-expert-solution.link"]; let abstract_words = ["operacao-feliz-natal.blogspot.com", "moviedouban.site", "hack-expert-solution.link"];
allow = allow && !( allow = allow && !(
(this.hasKeyword(resultLandingInfo.title,title_authors_words) || (resultLandingInfo.authors && this.hasKeyword(resultLandingInfo.authors.map(o => o.fullName).join(" "),title_authors_words)) (this.hasKeyword(resultLandingInfo.title,title_authors_words) || (resultLandingInfo.authors && this.hasKeyword(resultLandingInfo.authors.map(o => o.fullName).join(" "),title_authors_words))
|| (resultLandingInfo.description && resultLandingInfo.description[0] && this.hasKeyword(resultLandingInfo.description[0],abstract_words)) || (resultLandingInfo.description && this.hasKeyword(resultLandingInfo.description,abstract_words))
) && ) &&
((resultLandingInfo.publisher && resultLandingInfo.publisher.toLowerCase() == "zenodo") || ((resultLandingInfo.publisher && resultLandingInfo.publisher.toLowerCase() == "zenodo") ||
(resultLandingInfo.hostedBy_collectedFrom && resultLandingInfo.hostedBy_collectedFrom.filter(value => { (resultLandingInfo.hostedBy_collectedFrom && resultLandingInfo.hostedBy_collectedFrom.filter(value => {
@ -816,7 +819,7 @@ export class ResultLandingComponent {
let common_abstract = ["international audience","n/a","peer reviewed","national audience","info:eu-repo/semantics/published","-",".","graphical abstract","met lit. opg","international audience; no abstract",'<jats:p>.</jats:p>',"politics","info:eu-repo/semantics/publishedversion","copia digital. madrid : ministerio de educación, cultura y deporte, 2016",'<jats:p />',"peer-reviewed","copia digital. madrid : ministerio de educación, cultura y deporte. subdirección general de coordinación bibliotecaria, 2015","<jats:p>-</jats:p>","imperial users only","yüksek lisans"]; let common_abstract = ["international audience","n/a","peer reviewed","national audience","info:eu-repo/semantics/published","-",".","graphical abstract","met lit. opg","international audience; no abstract",'<jats:p>.</jats:p>',"politics","info:eu-repo/semantics/publishedversion","copia digital. madrid : ministerio de educación, cultura y deporte, 2016",'<jats:p />',"peer-reviewed","copia digital. madrid : ministerio de educación, cultura y deporte. subdirección general de coordinación bibliotecaria, 2015","<jats:p>-</jats:p>","imperial users only","yüksek lisans"];
let common_authors = ["[s.n.]","null &na;","nn","(:unap)","(:null)","null anonymous","anonymous"]; let common_authors = ["[s.n.]","null &na;","nn","(:unap)","(:null)","null anonymous","anonymous"];
allow = allow && !( allow = allow && !(
this.isKeyword(resultLandingInfo.title,common_titles) || (resultLandingInfo.description && resultLandingInfo.description[0] && this.isKeyword(resultLandingInfo.description[0],common_abstract)) || this.isKeyword(resultLandingInfo.title,common_titles) || (resultLandingInfo.description && this.isKeyword(resultLandingInfo.description,common_abstract)) ||
(resultLandingInfo.authors && this.hasKeyword("_"+resultLandingInfo.authors.map(o => o.fullName).join("_")+"_",common_authors, "_")) (resultLandingInfo.authors && this.hasKeyword("_"+resultLandingInfo.authors.map(o => o.fullName).join("_")+"_",common_authors, "_"))
); );
// console.log("common content " + allow) // console.log("common content " + allow)

View File

@ -153,10 +153,10 @@ export class ResultLandingService {
for(let i=0; i<data[1].length; i++) { for(let i=0; i<data[1].length; i++) {
if(data[1][i] && data[1][i].content) { if(data[1][i] && data[1][i].content) {
if(!this.resultLandingInfo.title || data[1][i].classid == "main title") { if(!this.resultLandingInfo.title || data[1][i].classid == "main title") {
this.resultLandingInfo.title = String(data[1][i].content); this.resultLandingInfo.title = StringUtils.HTMLToString(String(data[1][i].content));
} }
if(!this.resultLandingInfo.subtitle && data[1][i].classid === 'subtitle') { if(!this.resultLandingInfo.subtitle && data[1][i].classid === 'subtitle') {
this.resultLandingInfo.subtitle = String(data[1][i].content); this.resultLandingInfo.subtitle = StringUtils.HTMLToString(String(data[1][i].content));
} }
// if(data[1][i].classid == "main title") { // if(data[1][i].classid == "main title") {
// break; // break;
@ -171,7 +171,7 @@ export class ResultLandingService {
} }
// this.resultLandingInfo.title = (data[1][0] && data[1][0].content) ? String(data[1][0].content) : ""; // this.resultLandingInfo.title = (data[1][0] && data[1][0].content) ? String(data[1][0].content) : "";
} else { } else {
this.resultLandingInfo.title = (data[1] && data[1].content) ? String(data[1].content) : ""; this.resultLandingInfo.title = (data[1] && data[1].content) ? StringUtils.HTMLToString(String(data[1].content)) : "";
} }
} }

View File

@ -5,9 +5,7 @@
</div> </div>
<div *ngIf="!loading" class="uk-grid" uk-grid> <div *ngIf="!loading" class="uk-grid" uk-grid>
<div class="tm-main uk-width-1-1@s uk-width-1-1@m uk-width-1-1@l uk-row-first "> <div class="tm-main uk-width-1-1@s uk-width-1-1@m uk-width-1-1@l uk-row-first ">
<div *ngIf="!server" class="uk-container uk-container-small uk-position-relative"> <div *ngIf="!server" class="uk-container uk-container-small uk-position-relative">
<div *ngIf="loggedIn && !errorCode" class=""> <div *ngIf="loggedIn && !errorCode" class="">
<div class="uk-h2 uk-text-center">User Information</div> <div class="uk-h2 uk-text-center">User Information</div>
<div> <div>
@ -19,13 +17,13 @@
<div *ngIf="user.role.length > 1"> <div *ngIf="user.role.length > 1">
<span class="uk-text-muted"> Roles </span> <span> {{getTheRolesFormatted(user.role)}} </span> <span class="uk-text-muted"> Roles </span> <span> {{getTheRolesFormatted(user.role)}} </span>
</div> </div>
<div class="uk-margin-top " *ngIf="user.role.length > 1"> <div class="uk-margin-top" *ngIf="user.role.length > 1">
<a class="uk-button uk-button-primary" href="https://aai.openaire.eu/roles/index.php" <a *ngIf="isCurator" class="uk-button uk-button-primary" href="https://aai.openaire.eu/roles/index.php"
target="_blank">Manage your roles</a> {{" "}} target="_blank">Manage your roles</a> {{" "}}
<a *ngIf="user && isUserManager()" class="uk-button uk-button-primary" <a *ngIf="isUserManager" class="uk-button uk-button-primary uk-margin-top"
href="https://aai.openaire.eu/roles/admin.php" href="https://aai.openaire.eu/roles/admin.php"
target="_blank">Manage role requests</a>{{" "}} target="_blank">Manage role requests</a>{{" "}}
<a *ngIf="user && isUserManager()" class="uk-button uk-button-primary" <a *ngIf="isUserManager" class="uk-button uk-button-primary uk-margin-top"
href="https://aai.openaire.eu/registry" href="https://aai.openaire.eu/registry"
target="_blank">Manage users</a> target="_blank">Manage users</a>
</div> </div>
@ -33,25 +31,6 @@
<!-- <button (click)="logout()" class=" uk-button uk-button-default">Log out</button> --> <!-- <button (click)="logout()" class=" uk-button uk-button-default">Log out</button> -->
</div> </div>
<!--form *ngIf="!loggedIn" class=" ">
<h3>Welcome to OpenAIRE's Discover Portal</h3>
<p>This service uses the same ldap sign-in as the OpenAIRE services so you can use the same
credentials.</p>
<p>Login in. To see it in action.</p>
<div class="uk-margin">
<input class="uk-input uk-form-width-medium" placeholder="Username" type="text" name="username" [(ngModel)]="username">
</div>
<div class="uk-margin">
<input placeholder="Password" class="uk-input uk-form-width-medium" type="password" name="password" [(ngModel)]="password">
</div>
<div class="uk-margin">
<button (click)="login()" class=" uk-button uk-button-primary">Login</button>
</div>
</form-->
<div *ngIf="errorCode == '1' || (!loggedIn && errorCode != '3' && errorCode != '6')" class="uk-alert uk-alert-warning"> <div *ngIf="errorCode == '1' || (!loggedIn && errorCode != '3' && errorCode != '6')" class="uk-alert uk-alert-warning">
The requested page requires authentication. The requested page requires authentication.
<span *ngIf="!loggedIn">Please <a class="uk-link" (click)="logIn()"> sign in</a> to continue. <span *ngIf="!loggedIn">Please <a class="uk-link" (click)="logIn()"> sign in</a> to continue.
@ -68,10 +47,7 @@
<div *ngIf="errorCode == '5'" class="uk-alert uk-alert-warning"> <div *ngIf="errorCode == '5'" class="uk-alert uk-alert-warning">
There is no research community selected. There is no research community selected.
</div> </div>
<div *ngIf="!loggedIn && errorMessage.length > 0" class="uk-alert uk-alert-danger">{{errorMessage}}</div> <div *ngIf="!loggedIn && errorMessage.length > 0" class="uk-alert uk-alert-danger">{{errorMessage}}</div>
</div> </div>
</div> </div>
</div> </div>

View File

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

View File

@ -9,10 +9,10 @@ import {UserManagementService} from "../services/user-management.service";
@Component({ @Component({
selector: 'user-mini', selector: 'user-mini',
template: ` template: `
<ul *ngIf="!mobileView" class="uk-navbar-nav"> <ul class="uk-navbar-nav">
<li class="uk-parent"> <li>
<a *ngIf="!loggedIn" (click)="logIn()">Sign in</a> <a *ngIf="!loggedIn && !mobileView" (click)="logIn()">Sign in</a>
<ng-container *ngIf="loggedIn"> <ng-container *ngIf="loggedIn && !mobileView">
<a class="login uk-icon"> <a class="login uk-icon">
<svg height="60" width="60"> <svg height="60" width="60">
<circle cx="30" cy="30" r="20" stroke-width="2"></circle> <circle cx="30" cy="30" r="20" stroke-width="2"></circle>
@ -37,21 +37,36 @@ import {UserManagementService} from "../services/user-management.service";
</ul> </ul>
</div> </div>
</ng-container> </ng-container>
</li> <a *ngIf="!loggedIn && mobileView" (click)="logIn()">
</ul> <icon name="login" ratio="1.5" [flex]="true"></icon>
<ul *ngIf="mobileView" class="uk-nav uk-nav-default"> </a>
<li> <a *ngIf="loggedIn && mobileView" href="#account" class="login uk-icon" uk-toggle>
<span *ngIf="loggedIn" class="uk-flex uk-flex-middle"> <svg height="30" width="30">
<span>{{user.fullname + " "}}</span> <circle cx="15" cy="15" r="15" stroke-width="2"></circle>
<span class="uk-margin-small-right uk-icon"><svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <text x="50%" y="50%" text-anchor="middle" dy=".35em" font-size="14">
<circle fill="none" stroke="#000" stroke-width="1.1" cx="9.9" cy="6.4" r="4.4"></circle> {{firstLetters ? firstLetters : 'AN'}}
<path fill="none" stroke="#000" stroke-width="1.1" </text>
d="M1.5,19 C2.3,14.5 5.8,11.2 10,11.2 C14.2,11.2 17.7,14.6 18.5,19.2"></path>
</svg> </svg>
</span> </a>
</span> <div *ngIf="loggedIn" id="account" class="uk-offcanvas" uk-offcanvas="flip: true; overlay: true">
<a *ngIf="!loggedIn" (click)="logIn()">Sign in</a> <div class="uk-offcanvas-bar uk-padding-remove-horizontal">
<ul *ngIf="loggedIn" class="uk-nav-sub"> <button class="uk-offcanvas-close uk-icon uk-close">
<icon name="close" ratio="1.5" visuallyHidden="close menu"></icon>
</button>
<div class="uk-padding uk-flex uk-flex-middle">
<div class="login">
<svg height="60" width="60" style="max-width: 60px; height: 60px;">
<circle cx="30" cy="30" r="20" stroke-width="2"></circle>
<text x="50%" y="50%" text-anchor="middle" dy=".4em" font-size="16">
{{firstLetters ? firstLetters : 'AN'}}
</text>
</svg>
</div>
<h5 class="uk-margin-small-left uk-margin-remove-bottom uk-margin-remove-top uk-text-truncate">
{{user.fullname}}
</h5>
</div>
<ul class="uk-nav uk-nav-primary uk-list uk-margin-top uk-nav-parent-icon" uk-nav>
<ng-container *ngFor="let item of userMenuItems "> <ng-container *ngFor="let item of userMenuItems ">
<li *ngIf="item.needsAuthorization && isAuthorized || !item.needsAuthorization"> <li *ngIf="item.needsAuthorization && isAuthorized || !item.needsAuthorization">
<a *ngIf="item.route" [routerLink]="item.route" (click)="closeCanvas()">{{item.title}}</a> <a *ngIf="item.route" [routerLink]="item.route" (click)="closeCanvas()">{{item.title}}</a>
@ -62,6 +77,8 @@ import {UserManagementService} from "../services/user-management.service";
<li *ngIf="userMenuItems.length > 0" class="uk-nav-divider"></li> <li *ngIf="userMenuItems.length > 0" class="uk-nav-divider"></li>
<li><a (click)="logOut()">Log out</a></li> <li><a (click)="logOut()">Log out</a></li>
</ul> </ul>
</div>
</div>
</li> </li>
</ul> </ul>
` `

View File

@ -4,10 +4,13 @@ import { FormsModule } from '@angular/forms';
import { RouterModule } from "@angular/router"; import { RouterModule } from "@angular/router";
import {UserMiniComponent} from "./userMini.component"; import {UserMiniComponent} from "./userMini.component";
import {IconsModule} from "../utils/icons/icons.module";
import {IconsService} from "../utils/icons/icons.service";
import {login} from "../utils/icons/icons";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, FormsModule, RouterModule CommonModule, FormsModule, RouterModule, IconsModule
], ],
declarations: [ declarations: [
UserMiniComponent UserMiniComponent
@ -18,4 +21,7 @@ import {UserMiniComponent} from "./userMini.component";
] ]
}) })
export class UserMiniModule { export class UserMiniModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([login])
}
} }

View File

@ -1,4 +1,6 @@
@media only screen and (min-width: 640px) { @import "~src/assets/openaire-theme/less/_import-variables";
@media only screen and (min-width: @breakpoint-small) {
.how .first > div:first-child { .how .first > div:first-child {
position: relative; position: relative;
} }
@ -157,7 +159,7 @@
} }
} }
@media only screen and (max-width: 639px) { @media only screen and (max-width: @breakpoint-xsmall-max) {
.how .first { .how .first {
position: relative; position: relative;
padding-bottom: 30%; padding-bottom: 30%;

View File

@ -9,6 +9,7 @@ import {Subscriber} from "rxjs";
@Component({ @Component({
selector: 'indicator-themes-page', selector: 'indicator-themes-page',
template: ` template: `
<div class="uk-visible@m">
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom"> <div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
<div class="uk-padding-small uk-padding-remove-horizontal"> <div class="uk-padding-small uk-padding-remove-horizontal">
<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs> <breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
@ -18,10 +19,10 @@ import {Subscriber} from "rxjs";
<h1>Indicator Themes<span class="uk-text-primary">.</span></h1> <h1>Indicator Themes<span class="uk-text-primary">.</span></h1>
<div class="uk-section"> <div class="uk-section">
<div class="uk-grid uk-grid-large uk-flex-middle" uk-grid> <div class="uk-grid uk-grid-large uk-flex-middle" uk-grid>
<div class="uk-width-3-5@m uk-width-1-1"> <div class="uk-width-3-5">
<img src="assets/common-assets/monitor-assets/indicator-themes-circle.png"> <img src="assets/common-assets/monitor-assets/indicator-themes-circle.png">
</div> </div>
<div class="uk-width-expand@m uk-width-1-1"> <div class="uk-width-expand">
<div> <div>
<h5>Indicator themes that we are covering in the Monitor dashboards.</h5> <h5>Indicator themes that we are covering in the Monitor dashboards.</h5>
<p> <p>
@ -38,6 +39,29 @@ import {Subscriber} from "rxjs";
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="uk-hidden@m">
<div class="uk-section uk-container uk-container-large">
<h1 class="uk-heading-small uk-text-center uk-padding-small uk-padding-remove-vertical">Indicator Themes<span class="uk-text-primary">.</span></h1>
<div class="uk-text-center uk-margin-large-top">
<div class="uk-padding-small uk-padding-remove-vertical">
<img src="assets/common-assets/monitor-assets/indicator-themes-circle.png">
</div>
<div>
<h5 class="uk-margin-large-top uk-margin-large-bottom">Indicator themes that we are covering in the Monitor dashboards.</h5>
<p>
This is the current set of indicator themes we cover. Well keep enriching it as new requests and data are coming into the <a href="https://graph.openaire.eu" class="text-graph" target="_blank">OpenAIRE Research Graph</a>. We are at your disposal, should you have any recommendations!
</p>
<p>
Check out the indicator pages (for <a [routerLink]="['../funder']" [relativeTo]="route">funders</a>,
<a [routerLink]="['../organization']" [relativeTo]="route">research institutions</a> and
<a [routerLink]="['../ri']" [relativeTo]="route">research initiatives</a>)
for the specific indicators for each type of dashboard, and the <a [routerLink]="['../../methodology']" [relativeTo]="route">methodology and terminology</a> page on how we produce the metrics.
</p>
</div>
</div>
</div>
</div>
` `
}) })
export class IndicatorThemesComponent implements OnInit, OnDestroy { export class IndicatorThemesComponent implements OnInit, OnDestroy {

View File

@ -11,7 +11,7 @@ import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
@Component({ @Component({
selector: 'indicators-page', selector: 'indicators-page',
template: ` template: `
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom"> <div class="uk-visible@m uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
<div class="uk-padding-small uk-padding-remove-horizontal"> <div class="uk-padding-small uk-padding-remove-horizontal">
<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs> <breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
</div> </div>

View File

@ -11,6 +11,7 @@ import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
@Component({ @Component({
selector: 'methodological-approach', selector: 'methodological-approach',
template: ` template: `
<div class="uk-visible@m">
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom"> <div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
<div class="uk-padding-small uk-padding-remove-horizontal"> <div class="uk-padding-small uk-padding-remove-horizontal">
<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs> <breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
@ -18,9 +19,9 @@ import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
</div> </div>
<div class="uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-fade; delay: 250"> <div class="uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-fade; delay: 250">
<div id="how" class="uk-container uk-container-large"> <div id="how" class="uk-container uk-container-large">
<h2 class="uk-h1" uk-scrollspy-class> <h1 class="uk-h1" uk-scrollspy-class>
Inclusion, transparency, <br> quality, state of the art <br> technology<span class="uk-text-primary">.</span> Inclusion, transparency, <br> quality, state of the art <br> technology<span class="uk-text-primary">.</span>
</h2> </h1>
<div class="uk-padding uk-padding-remove-vertical"> <div class="uk-padding uk-padding-remove-vertical">
<div class="uk-margin-large-top uk-card uk-card-default uk-card-body" uk-scrollspy-class> <div class="uk-margin-large-top uk-card uk-card-default uk-card-body" uk-scrollspy-class>
<p class="uk-margin-top">Our methodological approach is based on the following operational quality <p class="uk-margin-top">Our methodological approach is based on the following operational quality
@ -88,6 +89,72 @@ import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="uk-hidden@m">
<div class="uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-fade; delay: 250">
<div class="uk-container uk-container-large">
<h1 class="uk-heading-small uk-text-center uk-padding-small uk-padding-remove-vertical" uk-scrollspy-class>
Inclusion, transparency, <br> quality, state of the art <br> technology<span class="uk-text-primary">.</span>
</h1>
<div class="uk-margin-xlarge-top" uk-scrollspy-class>
<p>Our <span class="uk-text-primary">methodological approach</span> is based on the following operational quality
<span class="uk-text-primary">criteria</span>:</p>
<ul>
<li class="uk-margin-small-bottom"><span class="uk-text-bold">Openness and transparency:</span> Methodological assumptions are openly and
clearly presented.
</li>
<li class="uk-margin-small-bottom"><span class="uk-text-bold">Coverage and accuracy:</span> As detailed in <a
href="https://graph.openaire.eu/" target="_blank">graph.openaire.eu</a>
multiple data sources are ingested in the OpenAIRE research graph for coverage to the fullest extent
possible, in order to provide meaningful indicators.
</li>
<li class="uk-margin-small-bottom"><span class="uk-text-bold">Clarity and replicability:</span> We describe our construction methodology in
detail, so that
it can be verified and used by the scholarly communication community to create ongoing updates to our
proposed statistics and indicators.
</li>
<li class="uk-margin-small-bottom"><span class="uk-text-bold">Readiness and timeliness:</span> The methodology is built around
well-established open databases
and already tested knowledge extraction technologies - natural language processing (NLP)/machine-learning
(ML) - using operational
workflows in OpenAIRE to warrant timely results.
</li>
<li><span class="uk-text-bold">Trust and robustness:</span> Our methodology also strives to be reliable,
robust, and aligned
to other assessment methods so that it can be operationalized, used and reused, in conjunction with other
assessment methods.
</li>
</ul>
<div class="uk-text-small uk-text-italic uk-text-muted">The text above is modified from <a
href="https://op.europa.eu/en/publication-detail/-/publication/56cc104f-0ebb-11ec-b771-01aa75ed71a1"
target="_blank">this report</a> (DOI: 10.2777/268348).
</div>
</div>
<div class="uk-margin-xlarge-top uk-padding-large">
<img src="assets/common-assets/common/graph-nodes.svg" alt="OpenAIRE Research Graph" loading="lazy">
</div>
<div class="uk-margin-top uk-margin-large-bottom">
<span class="uk-text-large text-graph">Completeness, inclusion, transparency and replicability</span>
<h2 class="uk-margin-small-top uk-margin-remove-bottom">How?</h2>
<h2 class="uk-margin-remove-top uk-padding uk-padding-remove-vertical uk-padding-remove-left">Its about open data and collaboration<span class="text-graph">.</span></h2>
<ul class="uk-list uk-list-bullet uk-margin-large-top">
<li class="uk-flex uk-flex-column uk-margin-medium-bottom">
<span class="uk-text-large uk-margin-small-bottom">Built on the <span class="uk-text-bold">OpenAire Research Graph</span></span>
<span>Linked scholarly information from open initiatives around the world. Beyond publications.</span>
</li>
<li class="uk-flex uk-flex-column uk-margin-medium-bottom">
<span class="uk-text-large uk-margin-small-bottom">Based on <span class="uk-text-bold">Open Science principles</span></span>
<span>Open data sources, Open APIs, well documented metrics and indicators.</span>
</li>
<li class="uk-flex uk-flex-column">
<span class="uk-text-large uk-margin-small-bottom">Relevance for the <span class="uk-text-bold">Community</span></span>
<span>Indicators development and visualizations to meet community requirements.</span>
</li>
</ul>
</div>
</div>
</div>
</div>
<!-- <div class="uk-section uk-section-large uk-container uk-container-large"> <!-- <div class="uk-section uk-section-large uk-container uk-container-large">
TODO: Graph scheme TODO: Graph scheme
</div> --> </div> -->

View File

@ -19,6 +19,7 @@ import {HelperModule} from "../../utils/helper/helper.module";
{ {
path: '', path: '',
redirectTo: 'terminology', redirectTo: 'terminology',
pathMatch: 'full',
canDeactivate: [PreviousRouteRecorder] canDeactivate: [PreviousRouteRecorder]
}, },
{ {

View File

@ -3,8 +3,10 @@ import {
AfterViewInit, AfterViewInit,
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
Inject,
OnDestroy, OnDestroy,
OnInit, OnInit,
PLATFORM_ID,
ViewChild ViewChild
} from "@angular/core"; } from "@angular/core";
import {Subscription} from "rxjs"; import {Subscription} from "rxjs";
@ -15,6 +17,8 @@ import {SEOService} from "../../sharedComponents/SEO/SEO.service";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component"; import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
import {HelperService} from "../../utils/helper/helper.service"; import {HelperService} from "../../utils/helper/helper.service";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {isPlatformServer} from "@angular/common";
declare var ResizeObserver; declare var ResizeObserver;
@ -22,28 +26,31 @@ declare var ResizeObserver;
@Component({ @Component({
selector: 'terminology', selector: 'terminology',
template: ` template: `
<div id="graph_element" #graph_element class="uk-blur-background" uk-sticky="bottom: true;" [attr.offset]="graph_offset"> <div *ngIf="!isMobile" class="uk-visible@m">
<div class="uk-container uk-container-large uk-margin-small-top uk-margin-small-bottom">
<icon name="graph" customClass="text-graph"></icon>
<span class="uk-margin-small-left uk-text-meta">More information for </span>
<a href="https://graph.openaire.eu" class="text-graph">OpenAIRE Research Graph</a>
<span class="uk-text-meta">.</span>
</div>
</div>
<div class="uk-background-muted"> <div class="uk-background-muted">
<div class="uk-container uk-container-large uk-section uk-section-small"> <div class="uk-container uk-container-large uk-section uk-section-small">
<div class="uk-padding-small uk-padding-remove-horizontal"> <div class="uk-padding-small uk-padding-remove-horizontal">
<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs> <breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
</div> </div>
<div class="uk-text-center" uk-scrollspy-class> <div class="uk-text-center" uk-scrollspy-class>
<h1 class="uk-margin-medium-top uk-margin-medium-bottom">Terminology and <br> construction<span class="uk-text-primary">.</span></h1> <h1 class="uk-margin-medium-top uk-margin-medium-bottom">Terminology and <br> construction<span
class="uk-text-primary">.</span></h1>
</div> </div>
</div> </div>
</div> </div>
<div *ngIf="divContents" class="uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-fade; delay: 250"> <div *ngIf="divContents" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-fade; delay: 250">
<div id="graph_element" #graph_element class="uk-blur-background" uk-sticky="bottom: true"
[attr.offset]="graph_offset">
<div class="uk-container uk-container-large uk-margin-small-top uk-margin-small-bottom">
<icon name="graph" customClass="text-graph"></icon>
<span class="uk-margin-small-left uk-text-meta">More information for </span>
<a href="https://graph.openaire.eu" target="_blank" class="text-graph">OpenAIRE Research Graph</a>
<span class="uk-text-meta">.</span>
</div>
</div>
<div class="uk-section uk-container uk-container-large" uk-scrollspy-class> <div class="uk-section uk-container uk-container-large" uk-scrollspy-class>
<div id="parentContainer" class="uk-grid uk-grid-large" uk-grid> <div id="parentContainer" class="uk-grid uk-grid-large" uk-grid>
<div class="uk-width-1-4@m uk-visible@m"> <div class="uk-width-1-4 uk-margin-top">
<div class="uk-sticky" uk-sticky="bottom: !#parentContainer; offset: 100;"> <div class="uk-sticky" uk-sticky="bottom: !#parentContainer; offset: 100;">
<slider-tabs type="scrollable" position="left"> <slider-tabs type="scrollable" position="left">
<slider-tab tabId="entities" tabTitle="1. Entities"></slider-tab> <slider-tab tabId="entities" tabTitle="1. Entities"></slider-tab>
@ -52,180 +59,59 @@ declare var ResizeObserver;
</slider-tabs> </slider-tabs>
</div> </div>
</div> </div>
<div class="uk-width-1-1 uk-hidden@m"> <div class="uk-width-expand uk-margin-top">
<div class="uk-sticky uk-background-default" uk-sticky>
<slider-tabs type="scrollable" position="horizontal">
<slider-tab tabId="entities" tabTitle="1. Entities"></slider-tab>
<slider-tab tabId="inherited-and-inferred-attributes" tabTitle="2. Inherited and Inferred Attributes"></slider-tab>
<slider-tab tabId="constructed-attributes" tabTitle="3. Constructed Attributes"></slider-tab>
</slider-tabs>
</div>
</div>
<div class="uk-width-expand@m">
<div id="entities" class="uk-margin-large-bottom"> <div id="entities" class="uk-margin-large-bottom">
<helper [texts]="divContents.entities"></helper> <helper [texts]="divContents['entities']"></helper>
</div> </div>
<div id="inherited-and-inferred-attributes" class="uk-margin-large-bottom"> <div id="inherited-and-inferred-attributes" class="uk-margin-large-bottom">
<!-- Helptext below here -->
<helper [texts]="divContents['inherited-and-inferred-attributes']"></helper> <helper [texts]="divContents['inherited-and-inferred-attributes']"></helper>
</div> </div>
<div id="constructed-attributes" class="uk-margin-large-bottom"> <div id="constructed-attributes" class="uk-margin-large-bottom">
<helper [texts]="divContents['constructed-attributes']"></helper> <helper [texts]="divContents['constructed-attributes']"></helper>
</div>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="isMobile || isServer" class="uk-hidden@m">
<div class="uk-background-muted">
<div class="uk-container uk-container-large">
<div class="uk-text-center" uk-scrollspy-class>
<h1 class="uk-heading-small uk-margin-medium-top uk-margin-medium-bottom">Terminology and <br> construction<span
class="uk-text-primary">.</span></h1>
</div>
</div>
</div>
<div *ngIf="divContents" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-fade; delay: 250">
<div id="graph_element" #graph_element class="uk-blur-background" uk-sticky="bottom: true"
[attr.offset]="graph_offset">
<div class="uk-container uk-container-large uk-margin-small-top uk-margin-small-bottom uk-text-xsmall uk-text-right">
<icon name="graph" customClass="text-graph"></icon>
<span class="uk-margin-small-left uk-text-meta">More information for </span>
<a href="https://graph.openaire.eu" target="_blank" class="text-graph">OpenAIRE Research Graph</a>
<span class="uk-text-meta">.</span>
</div>
</div>
<div> <div>
<h4>3. Constructed Attributes</h4> <div class="uk-sticky uk-background-default uk-padding uk-padding-remove-horizontal" uk-sticky>
<div class="uk-margin-medium-top"> <slider-tabs type="scrollable" position="horizontal">
All attributes in this tab are constructed by us, with the methodology presented below. <slider-tab tabId="entities_m" tabTitle="1. Entities"></slider-tab>
</div> <slider-tab tabId="inherited-and-inferred-attributes_m"
<dl class="uk-description-list uk-description-list-divider uk-margin-medium-top"> tabTitle="2. Inherited and Inferred Attributes"></slider-tab>
<div class="uk-grid" uk-grid> <slider-tab tabId="constructed-attributes_m" tabTitle="3. Constructed Attributes"></slider-tab>
<dt class="uk-width-1-3@m uk-width-1-1">Attribute</dt> </slider-tabs>
<dd class="uk-width-1-3@m uk-width-1-1 uk-text-bold">Definition</dd>
<dd class="uk-width-1-3@m uk-width-1-1 uk-text-bold">How we build it</dd>
</div>
<hr>
<div class=" uk-text-bold uk-text-primary">
Journal Business Models
</div>
<hr>
<div class="uk-grid " uk-grid>
<dt class="uk-width-1-3@m uk-width-1-1">Fully Open Access (OA)</dt>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>A journal that publishes only in open access.</p>
</dd>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>We follow <a target="_blank" href="https://support.unpaywall.org/support/solutions/articles/44001792752-how-do-we-decide-if-a-given-journal-is-fully-oa-">Unpaywalls approach</a> on defining fully Open Access journals and publishers and we construct the lists of the latter using Unpaywall data.</p>
<p>In brief, a journal is fully Open Access if one or more of the following occur: </p>
<ol>
<li>It is in the Directory of Open Access Journals (DOAJ)</li>
<li>It has a known fully OA Publisher (curated list).</li>
<li>It only publishes OA articles.</li>
</ol>
</dd>
</div>
<hr>
<div class="uk-grid " uk-grid>
<dt class="uk-width-1-3@m uk-width-1-1">Subscription</dt>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>A journal that charges for access to its articles.</p>
</dd>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>Journals without any open access articles.</p>
</dd>
</div>
<hr>
<div class="uk-grid " uk-grid>
<dt class="uk-width-1-3@m uk-width-1-1">Hybrid</dt>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>A subscription journal where some of its articles are open access.</p>
</dd>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>Journals with open access articles that are not fully OA journals.</p>
</dd>
</div>
<hr>
<div class="uk-grid " uk-grid>
<dt class="uk-width-1-3@m uk-width-1-1">Transformative</dt>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>"A Transformative Journal is a subscription/hybrid journal that is actively committed to
transitioning to a fully Open Access journal.</p>
<p>In addition, a Transformative Journal must:</p>
<ul>
<li>gradually increase the share of Open Access content; and</li>
<li>offset subscription income from payments for publishing services (to avoid double payments)."
</li>
</ul>
<p>Source: <a href="https://www.coalition-s.org/transformative-journals-faq/" target="_blank">Plan S initiative</a></p>
</dd>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>
We identify Transformative Journals by ISSN matching with the publicly available <a href="https://journalcheckertool.org/transformative-journals/" target="_blank">Transformative Journals data</a> from Plan S initiative.
</p>
</dd>
</div>
<hr>
<div class=" uk-text-bold uk-text-primary">
Journal APC Business Models
</div>
<hr>
<div class="uk-grid " uk-grid>
<dt class="uk-width-1-3@m uk-width-1-1">Diamond OA</dt>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>A fully OA journal that does not charge article processing charges (APCs).</p>
<p>In other words, fully OA journals are either diamond, or charge APCs.</p>
</dd>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>
We obtain APC data from DOAJ using <a href="https://doaj.org/docs/public-data-dump/" target="_blank">DOAJs Public Data Dump</a> (an exportable version of the journal metadata). We used it to determine whether a particular fully OA journal charges APCs.
</p>
</dd>
</div>
<hr>
<div class=" uk-text-bold uk-text-primary">
Routes to Open Access (OA)
</div>
<hr>
<div class="uk-grid " uk-grid>
<dt class="uk-width-1-3@m uk-width-1-1">Green OA</dt>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>An open access scientific publication deposited in a repository</p>
</dd>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>As in definition</p>
</dd>
</div>
<hr>
<div class="uk-grid " uk-grid>
<dt class="uk-width-1-3@m uk-width-1-1">Gold OA</dt>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>A scientific publication published in a fully OA journal.</p>
</dd>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>We define fully OA journals above.</p>
</dd>
</div>
<hr>
<div class="uk-grid " uk-grid>
<dt class="uk-width-1-3@m uk-width-1-1">Hybrid OA</dt>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>An open access scientific publication published in a hybrid journal with an open license.</p>
</dd>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>We define hybrid journals above.</p>
<p>At this point we consider only CC licenses open. We are currently working on cleaning non-CC
licenses as well to identify other open ones.</p>
<p>In principle, this means that we may be underestimating the number of hybrid OA articles and
overestimating the number of bronze.</p>
</dd>
</div>
<hr>
<div class="uk-grid " uk-grid>
<dt class="uk-width-1-3@m uk-width-1-1">Bronze OA</dt>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>An open access scientific publication published in a hybrid journal without an open license.</p>
</dd>
<dd class="uk-width-1-3@m uk-width-1-1">
</dd>
</div>
<hr>
<div class=" uk-text-bold uk-text-primary">
Miscellaneous
</div>
<hr>
<div class="uk-grid " uk-grid>
<dt class="uk-width-1-3@m uk-width-1-1">Downloads</dt>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>The number of downloads of a publications full text in a specific time frame, from a given set of
data sources.</p>
</dd>
<dd class="uk-width-1-3@m uk-width-1-1">
<p>We utilize the usage data for the downloads from <a href="https://www.openaire.eu/guides-usage-counts" target="_blank">OpenAIREs Usage Counts service</a> that harvests it from a set of
datasources. The time range of available downloads varies for each datasource.</p>
</dd>
</div>
</dl>
</div> </div>
</div> </div>
<div class="uk-container uk-container-large uk-section uk-section-small uk-text-break">
<div id="entities_m" class="uk-margin-xlarge-bottom">
<helper [texts]="divContents['entities']"></helper>
</div>
<div id="inherited-and-inferred-attributes_m" class="uk-margin-xlarge-bottom">
<helper [texts]="divContents['inherited-and-inferred-attributes']"></helper>
</div>
<div id="constructed-attributes_m" class="uk-margin-xlarge-bottom">
<helper [texts]="divContents['constructed-attributes']"></helper>
</div> </div>
</div> </div>
</div> </div>
@ -244,6 +130,8 @@ export class TerminologyComponent implements OnInit, OnDestroy, AfterViewInit, A
public activeSection: string; public activeSection: string;
public properties = properties; public properties = properties;
public divContents: any; public divContents: any;
isMobile: boolean = false;
isServer: boolean;
constructor(private seoService: SEOService, constructor(private seoService: SEOService,
private meta: Meta, private meta: Meta,
@ -251,7 +139,10 @@ export class TerminologyComponent implements OnInit, OnDestroy, AfterViewInit, A
private route: ActivatedRoute, private route: ActivatedRoute,
private title: Title, private title: Title,
private cdr: ChangeDetectorRef, private cdr: ChangeDetectorRef,
private helper: HelperService) { private helper: HelperService,
private layoutService: LayoutService,
@Inject(PLATFORM_ID) private platform: any) {
this.isServer = isPlatformServer(this.platform);
} }
ngOnInit() { ngOnInit() {
@ -269,6 +160,10 @@ export class TerminologyComponent implements OnInit, OnDestroy, AfterViewInit, A
this.activeSection = 'entities'; this.activeSection = 'entities';
} }
})); }));
this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
this.cdr.detectChanges();
});
this.getDivContents(); this.getDivContents();
} }
@ -295,7 +190,7 @@ export class TerminologyComponent implements OnInit, OnDestroy, AfterViewInit, A
} }
private getDivContents() { private getDivContents() {
this.subscriptions.push(this.helper.getDivHelpContents(this.properties, 'monitor', this.router.url).subscribe(contents => { this.subscriptions.push(this.helper.getDivHelpContents(this.properties, 'monitor', '/methodology/terminology').subscribe(contents => {
this.divContents = contents; this.divContents = contents;
})); }));
} }

View File

@ -40,7 +40,7 @@ export class ResourcesService {
"", "", false, [], null, {})); "", "", false, [], null, {}));
items.push(ResourcesService.setLink(new MenuItem("indicator-themes", "Indicator Themes", items.push(ResourcesService.setLink(new MenuItem("indicator-themes", "Indicator Themes",
"", "", false, [], null, {}, null, null, null, null, '_self'), prefix + "/indicators/themes", portal)); "", "", false, [], null, {}, null, null, null, null, '_self'), prefix + "/indicators/themes", portal));
let promise = new Promise(resolve => { let promise = new Promise<void>(resolve => {
this.isPagesEnabled().subscribe(status => { this.isPagesEnabled().subscribe(status => {
ResourcesService.types.forEach((type, index) => { ResourcesService.types.forEach((type, index) => {
if (status[index]) { if (status[index]) {

View File

@ -23,7 +23,7 @@ export interface Reorder {
export class StakeholderService { export class StakeholderService {
private stakeholderSubject: BehaviorSubject<Stakeholder> = null; private stakeholderSubject: BehaviorSubject<Stakeholder> = null;
private promise: Promise<any>; private promise: Promise<void>;
private sub; private sub;
constructor(private http: HttpClient, private route: ActivatedRoute) { constructor(private http: HttpClient, private route: ActivatedRoute) {
@ -46,7 +46,7 @@ export class StakeholderService {
getStakeholder(alias: string): Observable<Stakeholder> { getStakeholder(alias: string): Observable<Stakeholder> {
if (!this.stakeholderSubject.value || this.stakeholderSubject.value.alias !== alias) { if (!this.stakeholderSubject.value || this.stakeholderSubject.value.alias !== alias) {
this.promise = new Promise<any>((resolve, reject) => { this.promise = new Promise<void>((resolve, reject) => {
this.sub = this.http.get<Stakeholder>(properties.monitorServiceAPIURL + '/stakeholder/' + encodeURIComponent(alias), CustomOptions.registryOptions()).pipe(map(stakeholder => { this.sub = this.http.get<Stakeholder>(properties.monitorServiceAPIURL + '/stakeholder/' + encodeURIComponent(alias), CustomOptions.registryOptions()).pipe(map(stakeholder => {
return this.formalize(this.checkIsUpload(stakeholder)); return this.formalize(this.checkIsUpload(stakeholder));
})).subscribe(stakeholder => { })).subscribe(stakeholder => {

View File

@ -1,5 +1,5 @@
import {ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation} from "@angular/core"; import {ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation} from "@angular/core";
import {FormArray, FormBuilder, FormGroup} from "@angular/forms"; import {UntypedFormArray, UntypedFormBuilder, UntypedFormGroup} from "@angular/forms";
import {Role, User} from "../../login/utils/helper.class"; import {Role, User} from "../../login/utils/helper.class";
import {UserManagementService} from "../../services/user-management.service"; import {UserManagementService} from "../../services/user-management.service";
import {Subscription} from "rxjs"; import {Subscription} from "rxjs";
@ -47,7 +47,7 @@ import {NotificationHandler} from "../../utils/notification-handler";
export class NotifyFormComponent implements OnInit, OnDestroy { export class NotifyFormComponent implements OnInit, OnDestroy {
@Input() @Input()
public label: string = 'Notify Managers'; public label: string = 'Notify Managers';
public form: FormGroup; public form: UntypedFormGroup;
@Input() @Input()
public availableGroups: Option[] = null; public availableGroups: Option[] = null;
public groups: Option[] = []; public groups: Option[] = [];
@ -60,7 +60,7 @@ export class NotifyFormComponent implements OnInit, OnDestroy {
private subscriptions: any[] = []; private subscriptions: any[] = [];
public sending: boolean = false; public sending: boolean = false;
constructor(private fb: FormBuilder, constructor(private fb: UntypedFormBuilder,
private cdr: ChangeDetectorRef, private cdr: ChangeDetectorRef,
private userManagementService: UserManagementService, private userManagementService: UserManagementService,
private notificationService: NotificationService) { private notificationService: NotificationService) {
@ -157,8 +157,8 @@ export class NotifyFormComponent implements OnInit, OnDestroy {
return groups; return groups;
} }
get groupsAsFromArray(): FormArray { get groupsAsFromArray(): UntypedFormArray {
return this.form.get('groups')?(<FormArray>this.form.get('groups')):null; return this.form.get('groups')?(<UntypedFormArray>this.form.get('groups')):null;
} }
get message(): string { get message(): string {

View File

@ -302,9 +302,9 @@ export class OrcidWorkComponent {
public subscriptions: Subscription[] = []; public subscriptions: Subscription[] = [];
@ViewChild('workModal') workModal; @ViewChild('workModal') workModal;
@ViewChild('saveWorkModal') saveWorkModal; // @ViewChild('saveWorkModal') saveWorkModal;
@ViewChild('grantModal') grantModal; @ViewChild('grantModal') grantModal;
@ViewChild('messageModal') messageModal; // @ViewChild('messageModal') messageModal;
@ViewChild('propagationModal') propagationModal; @ViewChild('propagationModal') propagationModal;
public requestGrant: boolean = false; public requestGrant: boolean = false;
@ -723,16 +723,16 @@ export class OrcidWorkComponent {
this.workModal.cancel(); this.workModal.cancel();
} }
openMessageModal(title: string) { // openMessageModal(title: string) {
this.messageModal.cancelButton = false; // this.messageModal.cancelButton = false;
this.messageModal.okButton = false; // this.messageModal.okButton = false;
this.messageModal.alertTitle = title; // this.messageModal.alertTitle = title;
this.messageModal.open(); // this.messageModal.open();
} // }
//
closeMessageModal() { // closeMessageModal() {
this.messageModal.cancel(); // this.messageModal.cancel();
} // }
openPropagationModal(title: string) { openPropagationModal(title: string) {
this.propagationModal.cancelButton = true; this.propagationModal.cancelButton = true;

View File

@ -91,7 +91,7 @@ export class OrcidComponent {
this.message = "<div>Thank you for connecting your ORCID iD with OpenAIRE!</div>" + this.message = "<div>Thank you for connecting your ORCID iD with OpenAIRE!</div>" +
"<div class='uk-margin-small-top'>This window will automatically close and you will be ready to link OpenAIRE research results with your ORCID iD.</div>"; "<div class='uk-margin-small-top'>This window will automatically close and you will be ready to link OpenAIRE research results with your ORCID iD.</div>";
if(window && window.opener) { if(window && window.opener) {
window.opener.postMessage("success"); window.opener.postMessage("success", "*");
window.close(); window.close();
} }
setTimeout(() => { setTimeout(() => {

View File

@ -1,5 +1,6 @@
import {ResultLandingInfo} from "../utils/entities/resultLandingInfo"; import {ResultLandingInfo} from "../utils/entities/resultLandingInfo";
import {ResultPreview} from "../utils/result-preview/result-preview"; import {ResultPreview} from "../utils/result-preview/result-preview";
import {StringUtils} from "../utils/string-utils.class";
export class WorkV3_0 { export class WorkV3_0 {
// automatically filled by orcid? // automatically filled by orcid?
@ -107,7 +108,8 @@ export class WorkV3_0 {
} }
if(resultLandingInfo.description && resultLandingInfo.description.length < description_limit) { if(resultLandingInfo.description && resultLandingInfo.description.length < description_limit) {
work['short-description'] = resultLandingInfo.description.length > 0 ? resultLandingInfo.description[0] : ""; resultLandingInfo.description = StringUtils.HTMLToString(resultLandingInfo.description);
work['short-description'] = resultLandingInfo.description.substring(0, description_limit-1);
} }
// citation (Citation, optional), // citation (Citation, optional),

View File

@ -4,8 +4,8 @@ import {ActivatedRoute, Router} from "@angular/router";
import {UserManagementService} from "../services/user-management.service"; import {UserManagementService} from "../services/user-management.service";
import {UserRegistryService} from "../services/user-registry.service"; import {UserRegistryService} from "../services/user-registry.service";
import {LoginErrorCodes} from "../login/utils/guardHelper.class"; import {LoginErrorCodes} from "../login/utils/guardHelper.class";
import {Subscriber} from "rxjs"; import {Subscriber, Subscription} from "rxjs";
import {FormBuilder, FormControl, Validators} from "@angular/forms"; import {UntypedFormBuilder, UntypedFormControl, Validators} from "@angular/forms";
import {AlertModal} from "../utils/modal/alert"; import {AlertModal} from "../utils/modal/alert";
import {properties} from "../../../environments/environment"; import {properties} from "../../../environments/environment";
import {EmailService} from "../utils/email/email.service"; import {EmailService} from "../utils/email/email.service";
@ -62,13 +62,18 @@ import {Composer} from "../utils/email/composer";
</modal-alert> </modal-alert>
<modal-alert #errorModal (alertOutput)="cancel()" [overflowBody]="false"> <modal-alert #errorModal (alertOutput)="cancel()" [overflowBody]="false">
<div> <div>
We are unable to process the request because the link is invalid, or it has expired. We are unable to process the request. What happened?
<ul class="uk-margin-top uk-list uk-list-circle uk-list-primary">
<li>You are logged in with a different email, than the one you have received the invitation.
Check <a [routerLink]="[userInfoLinkPrefix + '/user-info']" (click)="errorModal.cancel()">here</a> the email of your account.</li>
<li>The invitation has been canceled.</li>
<li>The URL is invalid.</li>
</ul>
</div> </div>
</modal-alert> </modal-alert>
` `
}) })
export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewInit { export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewInit {
@Input() @Input()
public id: string; public id: string;
@Input() @Input()
@ -77,10 +82,13 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
public name: string; public name: string;
@Input() @Input()
public service: "connect" | "monitor" = "monitor"; public service: "connect" | "monitor" = "monitor";
@Input()
public userInfoLinkPrefix = '';
public user: User; public user: User;
public verification: any; public verification: any;
public code: FormControl; public code: UntypedFormControl;
private subs: any[] = []; private subscriptions: any[] = [];
private paramsSubscription: Subscription;
@ViewChild('managerModal') managerModal: AlertModal; @ViewChild('managerModal') managerModal: AlertModal;
@ViewChild('memberModal') memberModal: AlertModal; @ViewChild('memberModal') memberModal: AlertModal;
@ViewChild('errorModal') errorModal: AlertModal; @ViewChild('errorModal') errorModal: AlertModal;
@ -90,7 +98,7 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
constructor(private route: ActivatedRoute, constructor(private route: ActivatedRoute,
private router: Router, private router: Router,
private fb: FormBuilder, private fb: UntypedFormBuilder,
private emailService: EmailService, private emailService: EmailService,
private userManagementService: UserManagementService, private userManagementService: UserManagementService,
private userRegistryService: UserRegistryService) { private userRegistryService: UserRegistryService) {
@ -101,12 +109,15 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
} }
ngAfterViewInit() { ngAfterViewInit() {
this.subs.push(this.route.queryParams.subscribe(params => { this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
if (params && params['verify']) {
this.subs.push(this.userManagementService.getUserInfo().subscribe(user => {
this.user = user; this.user = user;
if (this.paramsSubscription instanceof Subscription) {
this.paramsSubscription.unsubscribe();
}
this.paramsSubscription = this.route.queryParams.subscribe(params => {
if (params && params['verify']) {
if (this.user) { if (this.user) {
this.subs.push(this.userRegistryService.getInvitation(params['verify']).subscribe(verification => { this.subscriptions.push(this.userRegistryService.getInvitation(params['verify']).subscribe(verification => {
this.verification = verification; this.verification = verification;
if (this.user.email === this.verification.email.toLowerCase() && this.id === this.verification.entity && this.type === this.verification.type) { if (this.user.email === this.verification.email.toLowerCase() && this.id === this.verification.entity && this.type === this.verification.type) {
if (this.verification.verificationType === 'manager') { if (this.verification.verificationType === 'manager') {
@ -123,22 +134,26 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
this.openErrorModal(); this.openErrorModal();
})); }));
} else { } else {
this.router.navigate(['/user-info'], { this.router.navigate(['user-info'], {
queryParams: { queryParams: {
'errorCode': LoginErrorCodes.NOT_LOGIN, 'errorCode': LoginErrorCodes.NOT_LOGIN,
'redirectUrl': this.router.url 'redirectUrl': this.router.url
} },
relativeTo: this.route
}); });
} }
}));
} }
});
})); }));
} }
ngOnDestroy() { ngOnDestroy() {
this.subs.forEach(value => { if (this.paramsSubscription instanceof Subscription) {
if (value instanceof Subscriber) { this.paramsSubscription.unsubscribe();
value.unsubscribe(); }
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
} }
}); });
} }
@ -168,13 +183,13 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
this.error = null; this.error = null;
this.errorModal.cancelButton = false; this.errorModal.cancelButton = false;
this.errorModal.okButtonText = 'Ok'; this.errorModal.okButtonText = 'Ok';
this.errorModal.alertTitle = 'Invalid request'; this.errorModal.alertTitle = 'Invalid URL';
this.errorModal.open(); this.errorModal.open();
} }
public verifyManager() { public verifyManager() {
this.loading = true; this.loading = true;
this.subs.push(this.userRegistryService.verify(this.verification.id, this.code.value).subscribe(() => { this.subscriptions.push(this.userRegistryService.verify(this.verification.id, this.code.value).subscribe(() => {
this.managerModal.cancel(); this.managerModal.cancel();
this.error = null; this.error = null;
this.userManagementService.updateUserInfo(() => { this.userManagementService.updateUserInfo(() => {
@ -182,9 +197,9 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
this.loading = false; this.loading = false;
this.router.navigate(['/admin/' + this.verification.entity]); this.router.navigate(['/admin/' + this.verification.entity]);
} else { } else {
this.subs.push(this.emailService.notifyManagers(this.id, 'manager', this.subscriptions.push(this.emailService.notifyManagers(this.id, 'manager',
Composer.composeEmailToInformOldManagersForTheNewOnes(this.name, this.id)).subscribe(() => { Composer.composeEmailToInformOldManagersForTheNewOnes(this.name, this.id)).subscribe(() => {
this.subs.push(this.emailService.notifyNewManager(Composer.composeEmailForNewManager(this.id, this.name)).subscribe( this.subscriptions.push(this.emailService.notifyNewManager(Composer.composeEmailForNewManager(this.id, this.name)).subscribe(
() => { () => {
this.loading = false; this.loading = false;
window.location.href = properties.adminPortalURL + '/' + this.verification.entity; window.location.href = properties.adminPortalURL + '/' + this.verification.entity;
@ -211,7 +226,7 @@ export class RoleVerificationComponent implements OnInit, OnDestroy, AfterViewIn
public verifyMember() { public verifyMember() {
this.loading = true; this.loading = true;
if (!this.isMember) { if (!this.isMember) {
this.subs.push(this.userRegistryService.verify(this.verification.id, this.code.value, "member").subscribe(() => { this.subscriptions.push(this.userRegistryService.verify(this.verification.id, this.code.value, "member").subscribe(() => {
this.loading = false; this.loading = false;
this.error = null; this.error = null;
this.userManagementService.updateUserInfo(() => { this.userManagementService.updateUserInfo(() => {

View File

@ -6,9 +6,10 @@ import {ReactiveFormsModule} from "@angular/forms";
import {LoadingModule} from "../utils/loading/loading.module"; import {LoadingModule} from "../utils/loading/loading.module";
import {InputModule} from "../sharedComponents/input/input.module"; import {InputModule} from "../sharedComponents/input/input.module";
import {EmailService} from "../utils/email/email.service"; import {EmailService} from "../utils/email/email.service";
import {RouterModule} from "@angular/router";
@NgModule({ @NgModule({
imports: [CommonModule, AlertModalModule, ReactiveFormsModule, LoadingModule, InputModule], imports: [CommonModule, AlertModalModule, ReactiveFormsModule, LoadingModule, InputModule, RouterModule],
declarations: [RoleVerificationComponent], declarations: [RoleVerificationComponent],
exports: [RoleVerificationComponent], exports: [RoleVerificationComponent],
providers: [EmailService] providers: [EmailService]

View File

@ -18,6 +18,10 @@
</h2> </h2>
<div class="uk-width-3-4@m" uk-scrollspy-class> <div class="uk-width-3-4@m" uk-scrollspy-class>
We have developed a classification scheme for UN Sustainable Development Goals, to view contributions of research towards complex challenges for humanity such as climate change, biodiversity loss, pollution and poverty reduction. We have developed a classification scheme for UN Sustainable Development Goals, to view contributions of research towards complex challenges for humanity such as climate change, biodiversity loss, pollution and poverty reduction.
<div class="uk-text-meta uk-margin-top">
For more information please visit <a href="https://www.openaire.eu/openaire-explore-introducing-sdgs-and-fos" target="_blank">https://www.openaire.eu/openaire-explore-introducing-sdgs-and-fos</a>
</div>
</div> </div>
<div> <div>
<!-- TODO: need a page for the description of the algorithm - to get us there from the learn more btn --> <!-- TODO: need a page for the description of the algorithm - to get us there from the learn more btn -->

View File

@ -1,4 +1,4 @@
<div class="uk-background-norepeat uk-background-bottom-center uk-padding-remove-bottom uk-section uk-section-small" [ngClass]="searchForm.class"> <div class="uk-background-norepeat uk-background-bottom-center uk-padding-remove-bottom" [ngClass]="searchForm.class">
<div class="uk-width-1-1"> <div class="uk-width-1-1">
<div *ngIf="breadcrumbs.length > 0" class="uk-container uk-container-large" [class.uk-light]="searchForm.dark"> <div *ngIf="breadcrumbs.length > 0" class="uk-container uk-container-large" [class.uk-light]="searchForm.dark">
<div class="uk-padding-small uk-padding-remove-horizontal uk-padding-remove-bottom"> <div class="uk-padding-small uk-padding-remove-horizontal uk-padding-remove-bottom">
@ -9,7 +9,7 @@
<div class="uk-container uk-container-large uk-section uk-section-small uk-margin-bottom" id="searchForm"> <div class="uk-container uk-container-large uk-section uk-section-small uk-margin-bottom" id="searchForm">
<div class="uk-grid uk-flex uk-flex-middle uk-flex-center" uk-grid> <div class="uk-grid uk-flex uk-flex-middle uk-flex-center" uk-grid>
<div class="uk-width-1-1 uk-width-auto@m"><div id="searchImage"></div></div> <div class="uk-width-1-1 uk-width-auto@m"><div id="searchImage"></div></div>
<advanced-search-form class="uk-width-expand uk-padding uk-padding-remove-vertical" <advanced-search-form class="uk-width-expand uk-padding-remove-vertical"
entityType="all" entityType="all"
(queryChange)="keywordChanged($event)" (queryChange)="keywordChanged($event)"
[isDisabled]="disableForms" [isDisabled]="disableForms"

View File

@ -97,7 +97,7 @@ export class SearchResearchResultsComponent {
@Input() stickyForm:boolean = false; @Input() stickyForm:boolean = false;
private timeoutId; private timeoutId;
private promise: Promise<boolean> = null; private promise: Promise<void> = null;
private publicCommunities = null; private publicCommunities = null;
@Input() usedBy: string = "search"; @Input() usedBy: string = "search";
@ -194,7 +194,7 @@ export class SearchResearchResultsComponent {
} }
public getPublicCommunities() { public getPublicCommunities() {
this.promise = new Promise<any>(resolve => { this.promise = new Promise<void>(resolve => {
this._contextService.getPublicCommunitiesByState().subscribe( this._contextService.getPublicCommunitiesByState().subscribe(
data => { data => {
if(this.publicCommunities == null) { if(this.publicCommunities == null) {
@ -210,7 +210,7 @@ export class SearchResearchResultsComponent {
} }
racePromiseWithTimeout() { racePromiseWithTimeout() {
const timeoutPromise = new Promise((_, reject) => { const timeoutPromise = new Promise<void>((_, reject) => {
this.timeoutId = setTimeout(() => { this.timeoutId = setTimeout(() => {
this.publicCommunities = []; this.publicCommunities = [];
reject(new Error('Request timed out')); reject(new Error('Request timed out'));

View File

@ -19,14 +19,14 @@
<button type="submit" class="uk-hidden"></button> <button type="submit" class="uk-hidden"></button>
<div class="uk-grid uk-grid-small uk-grid-divider uk-flex-between" uk-grid> <div class="uk-grid uk-grid-small uk-grid-divider uk-flex-between" uk-grid>
<div class="uk-width-expand"> <div class="uk-width-expand">
<div class="uk-padding-small uk-padding-remove-left uk-overflow-auto" style="height: 200px; overflow-x: hidden; direction: rtl; scrollbar-gutter: stable;"> <div #container class="uk-padding-small uk-padding-remove-left uk-overflow-auto" style="height: 150px; overflow-x: hidden; direction: rtl; scrollbar-gutter: stable;">
<div style="direction: ltr;"> <div style="direction: ltr;">
<table class="uk-table uk-text-small uk-table-responsive uk-table-small uk-margin-remove"> <table class="uk-table uk-text-small uk-table-responsive uk-table-small uk-margin-remove">
<tr> <tr>
<td class="uk-text-bold uk-text-uppercase uk-width-1-3">Searching Fields</td> <td class="uk-text-bold uk-text-uppercase uk-width-1-3">Searching Fields</td>
<td class="uk-text-bold uk-text-uppercase uk-width-2-5">Terms</td> <td class="uk-text-bold uk-text-uppercase uk-width-2-5">Terms</td>
</tr> </tr>
<tr *ngFor="let selectedField of selectedFields; let i = index"> <tr *ngFor="let selectedField of selectedFields; let i = index;">
<td> <td>
<div class="uk-grid uk-flex-middle uk-child-width-1-2@m uk-child-width-1-1"> <div class="uk-grid uk-flex-middle uk-child-width-1-2@m uk-child-width-1-1">
<div input [(value)]="selectedField.id" inputClass="border-bottom" <div input [(value)]="selectedField.id" inputClass="border-bottom"
@ -46,8 +46,6 @@
placeholder="Type keywords..." placeholder="Type keywords..."
[(ngModel)]="selectedField.value" name="value[{{i}}]"> [(ngModel)]="selectedField.value" name="value[{{i}}]">
</div> </div>
</td> </td>
<td *ngIf="selectedField.type == 'date'"> <td *ngIf="selectedField.type == 'date'">
<date-filter [dateValue]=selectedField.dateValue [validDateFrom]=validDateFrom class="uk-width-expand" <date-filter [dateValue]=selectedField.dateValue [validDateFrom]=validDateFrom class="uk-width-expand"
@ -147,19 +145,19 @@
</ng-container> </ng-container>
<div *ngIf="simpleView" class="uk-flex uk-flex-center uk-flex-wrap"> <div *ngIf="simpleView" class="uk-flex uk-flex-center uk-flex-wrap">
<div class="uk-width-xlarge@l uk-width-large"> <div class="uk-width-xlarge@l uk-width-large">
<div class="uk-margin-small-bottom uk-text-small uk-flex uk-flex-right" [class.uk-light]="dark" *ngIf="showSwitchSearchLink"> <div class="uk-text-small uk-flex uk-flex-right" [class.uk-light]="dark" *ngIf="showSwitchSearchLink">
<a *ngIf ="this.entityType !='all' && this.entityType == this.selectedEntity && advancedSearchLink" <a *ngIf ="this.entityType !='all' && this.entityType == this.selectedEntity && advancedSearchLink"
[routerLink]="advancedSearchLink" [queryParams]="advancedSearchLinkParameters" [routerLink]="advancedSearchLink" [queryParams]="advancedSearchLinkParameters" class="uk-margin-small-bottom"
[ngClass]="(isDisabled)?'uk-disabled uk-link-muted':null">Advanced search [ngClass]="(isDisabled)?'uk-disabled uk-link-muted':null">Advanced search
</a> </a>
<a *ngIf =" this.entityType !='all' && this.entityType != this.selectedEntity && selectedEntityAdvancedUrl " <a *ngIf =" this.entityType !='all' && this.entityType != this.selectedEntity && selectedEntityAdvancedUrl "
[routerLink]="selectedEntityAdvancedUrl" [routerLink]="selectedEntityAdvancedUrl"
[queryParams]="{q:this.selectedFields[0].value,op:'and'}" [queryParams]="{q:this.selectedFields[0].value,op:'and'}" class="uk-margin-small-bottom"
[ngClass]="(isDisabled)?'uk-disabled uk-link-muted':null">Advanced search [ngClass]="(isDisabled)?'uk-disabled uk-link-muted':null">Advanced search
</a> </a>
<a *ngIf =" this.entityType =='all'" <a *ngIf =" this.entityType =='all'"
[routerLink]="properties.searchLinkToAdvancedResults" [routerLink]="properties.searchLinkToAdvancedResults"
[queryParams]="advancedSearchLinkParameters" [queryParams]="advancedSearchLinkParameters" class="uk-margin-small-bottom"
[ngClass]="(isDisabled)?'uk-disabled uk-link-muted':null">Advanced search [ngClass]="(isDisabled)?'uk-disabled uk-link-muted':null">Advanced search
</a> </a>
</div> </div>
@ -173,10 +171,18 @@
[(value)]="selectedFields[0].value" tooltip="true"></div> [(value)]="selectedFields[0].value" tooltip="true"></div>
</advanced-search-input> </advanced-search-input>
<div *ngIf="selectedFields[0] && disableSelect" search-input [disabled]="isDisabled" [(value)]="selectedFields[0].value" <div *ngIf="selectedFields[0] && disableSelect" search-input [disabled]="isDisabled" [(value)]="selectedFields[0].value"
[placeholder]="formPlaceholderText" (searchEmitter)="simpleKeywordChanged()"></div> [placeholder]="formPlaceholderText" (searchEmitter)="simpleKeywordChanged()" [iconPosition]="isMobile?'left':'right'">
<a *ngIf="isMobile" href="#mobile-filters" filters-toggle (click)="filtersClicked.emit(true)" uk-toggle>
<icon name="filters"></icon>
</a>
</div>
</ng-container> </ng-container>
<div *ngIf="selectedFields[0] && !entitiesSelection" search-input [disabled]="isDisabled" [(value)]="selectedFields[0].value" <div *ngIf="selectedFields[0] && !entitiesSelection" search-input [disabled]="isDisabled" [(value)]="selectedFields[0].value"
[placeholder]="formPlaceholderText" (searchEmitter)="simpleKeywordChanged()"></div> [placeholder]="formPlaceholderText" (searchEmitter)="simpleKeywordChanged()" [iconPosition]="isMobile?'left':'right'">
<a *ngIf="isMobile" href="#mobile-filters" filters-toggle (click)="filtersClicked.emit(true)" uk-toggle>
<icon name="filters"></icon>
</a>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -7,7 +7,7 @@ import {
OnDestroy, OnDestroy,
OnInit, OnInit,
Output, Output,
SimpleChanges SimpleChanges, ViewChild
} from '@angular/core'; } from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
@ -25,6 +25,7 @@ import {Option} from "../../sharedComponents/input/input.component";
templateUrl: 'advancedSearchForm.component.html' templateUrl: 'advancedSearchForm.component.html'
}) })
export class AdvancedSearchFormComponent implements OnInit, OnDestroy, OnChanges { export class AdvancedSearchFormComponent implements OnInit, OnDestroy, OnChanges {
@ViewChild("container") container;
@Input() entityType; @Input() entityType;
@Input() fieldIds: string[]; @Input() fieldIds: string[];
@Input() fieldIdsMap; @Input() fieldIdsMap;
@ -40,6 +41,7 @@ export class AdvancedSearchFormComponent implements OnInit, OnDestroy, OnChanges
@Output() queryChange = new EventEmitter(); @Output() queryChange = new EventEmitter();
@Input() resultTypes; @Input() resultTypes;
@Input() quickFilter: { filter: Filter, selected: boolean, filterId: string, value: string }; @Input() quickFilter: { filter: Filter, selected: boolean, filterId: string, value: string };
@Input() isMobile: boolean = false;
public disableSelect: boolean = false; public disableSelect: boolean = false;
validDateFrom: boolean = true; validDateFrom: boolean = true;
validDateTo: boolean = true; validDateTo: boolean = true;
@ -59,6 +61,7 @@ export class AdvancedSearchFormComponent implements OnInit, OnDestroy, OnChanges
selectedEntityAdvancedUrl; selectedEntityAdvancedUrl;
@Input() entitiesSelection: boolean; @Input() entitiesSelection: boolean;
@Input() showSwitchSearchLink: boolean = true; @Input() showSwitchSearchLink: boolean = true;
@Output() filtersClicked: EventEmitter<boolean> = new EventEmitter<boolean>();
sub; sub;
constructor(private route: ActivatedRoute, private router: Router, private cdr: ChangeDetectorRef) {} constructor(private route: ActivatedRoute, private router: Router, private cdr: ChangeDetectorRef) {}
@ -158,6 +161,8 @@ export class AdvancedSearchFormComponent implements OnInit, OnDestroy, OnChanges
this.selectedFields.push(new AdvancedField(this.newFieldId, this.fieldIdsMap[this.newFieldId].param, this.fieldIdsMap[this.newFieldId].name, type, "", "and")); this.selectedFields.push(new AdvancedField(this.newFieldId, this.fieldIdsMap[this.newFieldId].param, this.fieldIdsMap[this.newFieldId].name, type, "", "and"));
} }
this.cdr.detectChanges();
this.container.nativeElement.scrollTo({top: this.container.nativeElement.scrollHeight, behavior: 'smooth'});
} }
removeField(index: number) { removeField(index: number) {

View File

@ -10,26 +10,30 @@ import {DateFilterModule} from './dateFilter.module';
import {SearchFormModule} from './searchForm.module'; import {SearchFormModule} from './searchForm.module';
import {QuickSelectionsModule} from "./quick-selections.module"; import {QuickSelectionsModule} from "./quick-selections.module";
import {EntitiesSelectionModule} from "./entitiesSelection.module"; import {EntitiesSelectionModule} from "./entitiesSelection.module";
import { MatSelectModule } from "@angular/material/select"; import {MatSelectModule} from "@angular/material/select";
import {IconsModule} from "../../utils/icons/icons.module"; import {IconsModule} from "../../utils/icons/icons.module";
import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module"; import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module";
import {AdvancedSearchInputModule} from "../../sharedComponents/advanced-search-input/advanced-search-input.module"; import {AdvancedSearchInputModule} from "../../sharedComponents/advanced-search-input/advanced-search-input.module";
import {InputModule} from "../../sharedComponents/input/input.module"; import {InputModule} from "../../sharedComponents/input/input.module";
import {IconsService} from "../../utils/icons/icons.service";
import {filters} from "../../utils/icons/icons";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, FormsModule, RouterModule, EntitiesAutocompleteModule, StaticAutocompleteModule, DateFilterModule, SearchFormModule, QuickSelectionsModule, EntitiesSelectionModule, MatSelectModule, IconsModule, SearchInputModule, AdvancedSearchInputModule, InputModule CommonModule, FormsModule, RouterModule, EntitiesAutocompleteModule, StaticAutocompleteModule, DateFilterModule,
SearchFormModule, QuickSelectionsModule, EntitiesSelectionModule, MatSelectModule, IconsModule, SearchInputModule, AdvancedSearchInputModule, InputModule
], ],
declarations: [ declarations: [
AdvancedSearchFormComponent, AdvancedSearchFormComponent,
],
providers:[
], ],
exports: [ exports: [
AdvancedSearchFormComponent AdvancedSearchFormComponent
] ]
}) })
export class AdvancedSearchFormModule { } export class AdvancedSearchFormModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([filters]);
}
}

View File

@ -1,7 +1,7 @@
import {Component, Input} from '@angular/core'; import {Component, Input} from '@angular/core';
import {DateValue} from './searchHelperClasses.class'; import {DateValue} from './searchHelperClasses.class';
import {FormControl} from "@angular/forms"; import {UntypedFormControl} from "@angular/forms";
import { MatDatepickerInputEvent } from "@angular/material/datepicker"; import { MatDatepickerInputEvent } from "@angular/material/datepicker";
@Component({ @Component({
@ -61,8 +61,8 @@ ngOnInit() {
this.updateDefaultRangeDates(this.dateValue.from,this.dateValue.to); this.updateDefaultRangeDates(this.dateValue.from,this.dateValue.to);
} }
updateDefaultRangeDates(df:Date,dt:Date){ updateDefaultRangeDates(df:Date,dt:Date){
this.fromDate = new FormControl(df); this.fromDate = new UntypedFormControl(df);
this.toDate = new FormControl(dt); this.toDate = new UntypedFormControl(dt);
} }
typeChanged(type:string){ typeChanged(type:string){

View File

@ -3,7 +3,7 @@
<div class="uk-slider filters-slider" uk-slider="finite: true"> <div class="uk-slider filters-slider" uk-slider="finite: true">
<div [class.uk-invisible]="list.children.length === 0" class="uk-position-relative"> <div [class.uk-invisible]="list.children.length === 0" class="uk-position-relative">
<div class="uk-slider-container"> <div class="uk-slider-container">
<ul #list class="uk-slider-items uk-grid uk-grid-small uk-margin-small-right uk-flex-nowrap"> <ul #list class="uk-slider-items uk-grid uk-grid-small uk-margin-small-right uk-flex-nowrap" style="padding-bottom: 1px">
<ng-container *ngIf="customFilter && ((customFilterEnabled && <ng-container *ngIf="customFilter && ((customFilterEnabled &&
refineFields.indexOf(customFilter.queryFieldName) == refineFields.indexOf(customFilter.queryFieldName) ==
-1) ||customFilter.isHiddenFilter)"> -1) ||customFilter.isHiddenFilter)">
@ -113,18 +113,44 @@
</ul> </ul>
</div> </div>
</ng-template> </ng-template>
<!-- TODO - Clean up --> <ng-template #sorting let-mobile="mobile">
<div *ngIf="!includeOnlyResultsAndFilter" [class]="usedBy != 'deposit' && usedBy != 'orcid' && (!customFilter || customFilter.queryFieldName != 'communityId') ? <div *ngIf="searchUtils.totalResults > 10 || sort || searchUtils.totalResults > searchUtils.size ||
(!loadPaging && oldTotalResults > searchUtils.size && searchUtils.status == errorCodes.LOADING)"
class="uk-grid uk-flex-middle uk-child-width-1-1 uk-child-width-1-2@m" uk-grid>
<div>
<div class="uk-grid uk-flex-middle uk-grid-column-collapse" uk-grid>
<div *ngIf="searchUtils.totalResults > 10 && !mobile" class="uk-width-small uk-margin-right">
<div input type="select" placeholder="Results per page" inputClass="flat x-small"
[options]="pageOptions" [(value)]="searchUtils.size" [disabled]="disabled"
(valueChange)="sizeChanged($event)"></div>
</div>
<search-sorting *ngIf="sort && searchUtils.totalResults > 0"
[entityType]="entityType" [sortBy]="searchUtils.sortBy"
(sortByChange)="sortByChanged($event)"
[isDisabled]="disabled">
</search-sorting>
</div>
</div>
<search-paging *ngIf="!mobile" [type]="type" [loadPaging]="loadPaging" [oldTotalResults]="oldTotalResults"
[searchUtils]="searchUtils" [results]="results" [baseUrl]="searchUtils.baseUrl"
[parameterNames]="parameterNames" [parameterValues]="parameterValues"
[isDisabled]="disabled">
</search-paging>
</div>
</ng-template>
<ng-template #main let-mobile="mobile">
<!-- TODO - Clean up -->
<div *ngIf="!includeOnlyResultsAndFilter" [class]="usedBy != 'deposit' && usedBy != 'orcid' && (!customFilter || customFilter.queryFieldName != 'communityId') ?
(stickyForm?'':' ') : (stickyForm?'':' ') :
(+ (stickyForm?'':' uk-section') +' uk-padding-remove-bottom uk-padding-remove-top ' + (+ (stickyForm?'':' uk-section') +' uk-padding-remove-bottom uk-padding-remove-top ' +
((usedBy == 'deposit' || usedBy == 'orcid') ? ' uk-padding-remove-top ' : ' '))" ((usedBy == 'deposit' || usedBy == 'orcid') ? ' uk-padding-remove-top ' : ' '))"
[attr.uk-sticky]="(stickyForm?'{animation:false;offset:100;top:90;cls-active:uk-active uk-sticky-below;cls-inactive:uk-sticky '+ [attr.uk-sticky]="((stickyForm || mobile)?'{offset:100;top:90;cls-active:uk-active uk-sticky-below;cls-inactive:uk-sticky '+
(usedBy != 'deposit' && usedBy != 'orcid' && (!customFilter || customFilter.queryFieldName != 'communityId') ? (usedBy != 'deposit' && usedBy != 'orcid' && (!customFilter || customFilter.queryFieldName != 'communityId') ?
' uk-position-relative ' :(' uk-section ' ))+'}':null)"> ' uk-position-relative ' :(' uk-section ' ))+'}':null)">
<div class="uk-background-norepeat uk-background-bottom-center uk-padding-remove-bottom uk-section uk-section-small" [ngClass]="searchForm.class"> <div class="uk-background-norepeat uk-background-bottom-center" [ngClass]="searchForm.class">
<div class="uk-width-1-1"> <div class="uk-width-1-1">
<div *ngIf="showBreadcrumb" class="uk-container uk-container-large" [class.uk-light]="searchForm.dark"> <div *ngIf="showBreadcrumb && !mobile" class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom" [class.uk-light]="searchForm.dark">
<div class="uk-padding-small uk-padding-remove-horizontal"> <div class="uk-margin-top">
<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs> <breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
</div> </div>
</div> </div>
@ -132,7 +158,7 @@
<div class="uk-container uk-section uk-section-small uk-margin-bottom" id="searchForm"> <div class="uk-container uk-section uk-section-small uk-margin-bottom" id="searchForm">
<div class="uk-grid uk-flex uk-flex-middle uk-flex-center" uk-grid> <div class="uk-grid uk-flex uk-flex-middle uk-flex-center" uk-grid>
<div [class]="'uk-width-1-1'+(simpleView?' uk-width-auto@m' : '')"><div id="searchImage"></div></div> <div [class]="'uk-width-1-1'+(simpleView?' uk-width-auto@m' : '')"><div id="searchImage"></div></div>
<advanced-search-form class="uk-width-expand uk-padding uk-padding-remove-vertical" <advanced-search-form class="uk-width-expand uk-padding-remove-vertical"
[entityType]="entityType" [entityType]="entityType"
[fieldIds]="fieldIds" [fieldIds]="fieldIds"
[fieldIdsMap]="fieldIdsMap" [fieldIdsMap]="fieldIdsMap"
@ -143,9 +169,9 @@
[simpleSearchLink]="simpleSearchLink" [simpleSearchLink]="simpleSearchLink"
[advancedSearchLink]="advancedSearchLink" [advancedSearchLink]="advancedSearchLink"
[advancedSearchLinkParameters]="this.routerHelper.createQueryParams(this.parameterNames, this.parameterValues)" [advancedSearchLinkParameters]="this.routerHelper.createQueryParams(this.parameterNames, this.parameterValues)"
[simpleView]="simpleView" [formPlaceholderText]="formPlaceholderText" [simpleView]="simpleView" [formPlaceholderText]="formPlaceholderText" [isMobile]="mobile"
[resultTypes]="resultTypes" [quickFilter]="quickFilter" [entitiesSelection]="entitiesSelection" [resultTypes]="resultTypes" [quickFilter]="quickFilter" [entitiesSelection]="entitiesSelection"
[showSwitchSearchLink]="showSwitchSearchLink" [customFilter]="customFilter" [showSwitchSearchLink]="showSwitchSearchLink" [customFilter]="customFilter" (filtersClicked)="showOffCanvas = $event"
> >
</advanced-search-form> </advanced-search-form>
</div> </div>
@ -153,16 +179,16 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<schema2jsonld *ngIf="url" [URL]="url" type="search" [name]=pageTitleWithFilters <schema2jsonld *ngIf="url" [URL]="url" type="search" [name]=pageTitleWithFilters
[searchAction]=false [description]="metaDescription"></schema2jsonld> [searchAction]=false [description]="metaDescription"></schema2jsonld>
<div id="tm-main" [class.uk-margin-medium-top]="!includeOnlyResultsAndFilter" [class.uk-margin-top]="stickyForm"> <div id="tm-main" [class.uk-margin-medium-top]="!includeOnlyResultsAndFilter && properties.adminToolsPortalType != 'eosc'" [class.uk-margin-top]="stickyForm">
<ng-template #loading> <ng-template #loading>
<loading [ngClass]="'uk-height-medium uk-display-block uk-margin-xlarge-top'"></loading> <loading class="uk-height-medium uk-display-block uk-margin-xlarge-top"></loading>
</ng-template> </ng-template>
<ng-template [ngIf]="searchUtils.refineStatus != errorCodes.LOADING || existingFiltersWithValues !== 0" [ngIfElse]="loading"> <ng-template [ngIf]="searchUtils.refineStatus != errorCodes.LOADING || existingFiltersWithValues !== 0" [ngIfElse]="loading">
<div class="uk-container uk-container-large"> <div class="uk-container uk-container-large">
<div> <div [class.uk-margin-top]="properties.adminToolsPortalType == 'eosc'" >
<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0" <helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
[texts]="pageContents['top']"></helper> [texts]="pageContents['top']"></helper>
<div *ngIf="resultTypes" class="uk-flex uk-flex-center uk-padding-small uk-padding-remove-vertical uk-background-muted uk-border-rounded"> <div *ngIf="resultTypes" class="uk-flex uk-flex-center uk-padding-small uk-padding-remove-vertical uk-background-muted uk-border-rounded">
@ -171,39 +197,24 @@
</quick-selections> </quick-selections>
</div> </div>
<div [class]="showRefine? 'uk-width-4-5@m uk-width-4-5@l uk-width-1-1@s' :'uk-width-1-1'"> <div [class]="showRefine? 'uk-width-4-5@m uk-width-4-5@l uk-width-1-1@s' :'uk-width-1-1'">
<div *ngIf="showRefine" class="uk-hidden@m uk-margin-top"> <div *ngIf="showRefine && mobile">
<a href="#mobile-filters" uk-toggle (click)="showOffCanvas=true;"> <div #mobileFilters id="mobile-filters" uk-offcanvas="overlay: true">
<span class="uk-icon uk-margin-small-right uk-margin-small-left"> <div class="uk-offcanvas-bar uk-padding-remove-horizontal">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
data-svg="settings">
<ellipse fill="none" stroke="#000" cx="6.11" cy="3.55" rx="2.11" ry="2.15"></ellipse>
<ellipse fill="none" stroke="#000" cx="6.11" cy="15.55" rx="2.11" ry="2.15"></ellipse>
<circle fill="none" stroke="#000" cx="13.15" cy="9.55" r="2.15"></circle>
<rect x="1" y="3" width="3" height="1"></rect>
<rect x="10" y="3" width="8" height="1"></rect>
<rect x="1" y="9" width="8" height="1"></rect>
<rect x="15" y="9" width="3" height="1"></rect>
<rect x="1" y="15" width="3" height="1"></rect>
<rect x="10" y="15" width="8" height="1"></rect>
</svg>
</span>
<span>Filters <span
*ngIf="(selectedRangeFilters+selectedFilters) > 0">
({{(selectedRangeFilters + selectedFilters)}})</span>
</span>
</a>
<div #mobileFilters id="mobile-filters" uk-offcanvas="overlay: true" style="z-index:10000;">
<div class="uk-offcanvas-bar">
<a class="uk-offcanvas-close uk-icon uk-close" (click)="showOffCanvas=false"> <a class="uk-offcanvas-close uk-icon uk-close" (click)="showOffCanvas=false">
<icon name="close" ratio="1.5" visuallyHidden="close filters"></icon> <icon name="close" ratio="1.5" visuallyHidden="close filters"></icon>
</a> </a>
<div *ngIf="showOffCanvas"> <div *ngIf="showOffCanvas" class="uk-padding-small uk-padding-remove-vertical">
<div class="uk-margin-medium-top">
<ng-container *ngTemplateOutlet="sorting; context: {mobile: mobile}"></ng-container>
</div>
<div class="uk-margin-medium-top">
<ng-container *ngTemplateOutlet="filters_column; context: {}"></ng-container> <ng-container *ngTemplateOutlet="filters_column; context: {}"></ng-container>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
<div *ngIf="includeOnlyResultsAndFilter && showSwitchSearchLink && advancedSearchLink" class="uk-margin-medium-top uk-margin-medium-bottom"> <div *ngIf="includeOnlyResultsAndFilter && showSwitchSearchLink && advancedSearchLink" class="uk-margin-medium-top uk-margin-medium-bottom">
<a routerLinkActive="router-link-active" <a routerLinkActive="router-link-active"
[routerLink]="advancedSearchLink" style="z-index:1;" [routerLink]="advancedSearchLink" style="z-index:1;"
@ -212,17 +223,17 @@
search search
</a> </a>
</div> </div>
<div class="uk-grid uk-margin-large-top uk-margin-large-bottom" uk-grid> </div>
<div *ngIf="showRefine && (results.length > 0 </div>
|| (searchUtils.refineStatus == errorCodes.LOADING && searchUtils.status != errorCodes.LOADING) <div class="uk-container" [class.uk-container-large]="!mobile" [class.uk-container-expand]="mobile" [class.uk-padding-remove-horizontal]="mobile">
|| (!hideFilters && <div class="uk-grid uk-margin-large-bottom" [class.uk-margin-top]="!mobile" uk-grid>
(existingFiltersWithValues > 0 || (selectedRangeFilters + selectedFilters + selectedTypesNum) > 0) <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">
class="uk-width-1-4@m search-filters uk-visible@m">
<ng-container *ngTemplateOutlet="filters_column; context: {}"></ng-container> <ng-container *ngTemplateOutlet="filters_column; context: {}"></ng-container>
</div> </div>
<div class="uk-width-expand@m uk-with-1-1@s"> <div class="uk-width-expand@m uk-with-1-1@s">
<div [class.uk-padding-small]="mobile" class="uk-padding-remove-vertical">
<!-- Results only for Custom Filter? --> <!-- Results only for Custom Filter? -->
<div *ngIf="customFilter && !customFilter.isHiddenFilter && <div *ngIf="customFilter && !customFilter.isHiddenFilter &&
customFilter.selected == false && customFilter.promptToAddFilter" customFilter.selected == false && customFilter.promptToAddFilter"
@ -241,7 +252,7 @@
[href]="openaireLink+this.routerHelper.createQueryParamsString(this.parameterNames, this.parameterValues)" [href]="openaireLink+this.routerHelper.createQueryParamsString(this.parameterNames, this.parameterValues)"
target="_blank"> OpenAIRE - Explore</a>. target="_blank"> OpenAIRE - Explore</a>.
</div> </div>
<div class="uk-flex uk-flex-between uk-flex-middle uk-flex-wrap uk-margin-bottom"> <div class="uk-flex uk-flex-between uk-flex-middle uk-flex-wrap">
<!-- Total results, number of pages --> <!-- Total results, number of pages -->
<h6 class="uk-margin-remove"> <h6 class="uk-margin-remove">
<ng-container *ngIf="results && searchUtils.totalResults > 0"> <ng-container *ngIf="results && searchUtils.totalResults > 0">
@ -267,35 +278,18 @@
</search-download> </search-download>
</div> </div>
</div> </div>
<div *ngIf="(searchUtils.status !== errorCodes.LOADING || !loadPaging)"> <div *ngIf="(searchUtils.status !== errorCodes.LOADING || !loadPaging) && !mobile" class="uk-margin-top">
<ng-container *ngTemplateOutlet="selected_filters_pills;"></ng-container> <ng-container *ngTemplateOutlet="selected_filters_pills;"></ng-container>
</div> </div>
<div *ngIf="searchUtils.totalResults > 10 || sort || searchUtils.totalResults > searchUtils.size || <div *ngIf="!mobile" class="uk-margin-medium-topuk-margin-medium-top">
(!loadPaging && oldTotalResults > searchUtils.size && searchUtils.status == errorCodes.LOADING)" <ng-container *ngTemplateOutlet="sorting; context: {mobile: mobile}"></ng-container>
class="uk-grid uk-flex-middle uk-child-width-1-1 uk-child-width-1-2@m uk-margin-medium-top" uk-grid>
<div>
<div class="uk-flex uk-flex-middle">
<div *ngIf="searchUtils.totalResults > 10" class="uk-width-small uk-margin-right">
<div input type="select" placeholder="Results per page" inputClass="flat x-small"
[options]="pageOptions" [(value)]="searchUtils.size" [disabled]="disabled"
(valueChange)="sizeChanged($event)"></div>
</div> </div>
<search-sorting *ngIf="sort && searchUtils.totalResults > 0" <div [class]="searchUtils.page > pagingLimit ? 'search-results' : ''"
[entityType]="entityType" [sortBy]="searchUtils.sortBy" *ngIf="(searchUtils.page >= pagingLimit) && (searchUtils.totalResults > searchUtils.size*pagingLimit)">
(sortByChange)="sortByChanged($event)" <p class="uk-alert uk-alert-warning" uk-alert>For more results please try a new, more specific query</p>
[isDisabled]="disabled">
</search-sorting>
</div> </div>
</div> </div>
<search-paging [type]="type" [loadPaging]="loadPaging" [oldTotalResults]="oldTotalResults" <div *ngIf="(searchUtils.page <= pagingLimit) || (searchUtils.totalResults <= searchUtils.size*pagingLimit)" class="uk-margin">
[searchUtils]="searchUtils" [results]="results" [baseUrl]="searchUtils.baseUrl"
[parameterNames]="parameterNames" [parameterValues]="parameterValues"
[isDisabled]="disabled">
</search-paging>
</div>
<div
*ngIf="(searchUtils.page <= pagingLimit) || (searchUtils.totalResults <= searchUtils.size*pagingLimit)"
class="uk-margin">
<search-result *ngIf="( entityType !='community' && entityType != 'stakeholder') && usedBy == 'search'" <search-result *ngIf="( entityType !='community' && entityType != 'stakeholder') && usedBy == 'search'"
[results]="results" [results]="results"
[status]=searchUtils.status [status]=searchUtils.status
@ -320,19 +314,16 @@
[results]="results" [results]="results"
[status]="searchUtils.status" [status]="searchUtils.status"
[type]="entityType" [type]="entityType"
[showType]="entityType == 'stakeholder'" [showType]="entityType == 'stakeholder'" [isMobile]="mobile"
[showLoading]="true" [properties]=properties> [showLoading]="true" [properties]=properties>
</portal-search-result> </portal-search-result>
</div> </div>
<div [class]="searchUtils.page > pagingLimit ? 'search-results' : ''" <div [class.uk-padding-small]="mobile" class="uk-padding-remove-vertical">
*ngIf="(searchUtils.page >= pagingLimit) && (searchUtils.totalResults > searchUtils.size*pagingLimit)">
<p class="uk-alert uk-alert-warning" uk-alert>For more results please try a new, more specific query</p>
</div>
<div class="uk-margin-medium-top"> <div class="uk-margin-medium-top">
<search-paging [type]="type" [loadPaging]="loadPaging" [oldTotalResults]="oldTotalResults" <search-paging [type]="type" [loadPaging]="loadPaging" [oldTotalResults]="oldTotalResults"
[searchUtils]="searchUtils" [results]="results" [baseUrl]="searchUtils.baseUrl" [searchUtils]="searchUtils" [results]="results" [baseUrl]="searchUtils.baseUrl"
[parameterNames]="parameterNames" [parameterValues]="parameterValues" [parameterNames]="parameterNames" [parameterValues]="parameterValues"
[isDisabled]="disabled"> [isDisabled]="disabled" [isMobile]="mobile">
</search-paging> </search-paging>
</div> </div>
<div *ngIf="showIndexInfo && searchUtils.status !== errorCodes.LOADING" class="uk-margin-large-top uk-grid uk-child-width-1-2 uk-text-small"> <div *ngIf="showIndexInfo && searchUtils.status !== errorCodes.LOADING" class="uk-margin-large-top uk-grid uk-child-width-1-2 uk-text-small">
@ -353,11 +344,18 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0" <helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0"
[texts]="pageContents['bottom']"></helper> [texts]="pageContents['bottom']"></helper>
</div> </div>
</div> </div>
</div>
</ng-template> </ng-template>
</div>
</ng-template>
<div *ngIf="!isMobile" class="uk-visible@m">
<ng-container *ngTemplateOutlet="main; context: {mobile: false}"></ng-container>
</div>
<div *ngIf="isMobile || isServer" class="uk-hidden@m">
<ng-container *ngTemplateOutlet="main; context: {mobile: true}"></ng-container>
</div> </div>
<modal-alert #removeCustomFilter (alertOutput)="closeCustomFilterModal()"></modal-alert> <modal-alert #removeCustomFilter (alertOutput)="closeCustomFilterModal()"></modal-alert>

View File

@ -1,15 +1,15 @@
import { import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ElementRef, ElementRef, Inject,
Input, Input,
OnChanges, OnChanges,
OnDestroy, OnDestroy,
OnInit, OnInit, PLATFORM_ID,
SimpleChanges, SimpleChanges,
ViewChild ViewChild
} from '@angular/core'; } from '@angular/core';
import {Location} from '@angular/common'; import {isPlatformServer, Location} from '@angular/common';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser'; import {Meta, Title} from '@angular/platform-browser';
@ -35,6 +35,8 @@ import {AlertModal} from "../../utils/modal/alert";
import {Subscriber} from "rxjs"; import {Subscriber} from "rxjs";
import {IndexInfoService} from "../../utils/indexInfo.service"; import {IndexInfoService} from "../../utils/indexInfo.service";
import {Background} from "../../utils/background-utils"; import {Background} from "../../utils/background-utils";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {Platform} from "@angular/cdk/platform";
export interface SearchForm extends Background {} export interface SearchForm extends Background {}
@ -147,13 +149,8 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
currentFilterToRemove; currentFilterToRemove;
public indexUpdateDate: Date; public indexUpdateDate: Date;
showOffCanvas:boolean = false; showOffCanvas:boolean = false;
// public resultsPerPageOptions = [ isMobile: boolean = false;
// {label: '5', value: '5'}, isServer: boolean;
// {label: '10', value: '10'},
// {label: '20', value: '20'},
// {label: '50', value: '50'},
// ];
constructor(private route: ActivatedRoute, constructor(private route: ActivatedRoute,
private location: Location, private location: Location,
@ -163,7 +160,10 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
private router: Router, private router: Router,
private seoService: SEOService, private seoService: SEOService,
private helper: HelperService, private helper: HelperService,
private layoutService: LayoutService,
@Inject(PLATFORM_ID) private platform: any,
private cdr: ChangeDetectorRef, private indexInfoService: IndexInfoService) { private cdr: ChangeDetectorRef, private indexInfoService: IndexInfoService) {
this.isServer = isPlatformServer(this.platform);
} }
ngOnInit() { ngOnInit() {
@ -178,6 +178,10 @@ export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
if (typeof document !== 'undefined' && this.isPiwikEnabled && !this.includeOnlyResultsAndFilter && this.piwikSiteId) { if (typeof document !== 'undefined' && this.isPiwikEnabled && !this.includeOnlyResultsAndFilter && this.piwikSiteId) {
this.subscriptions.push(this._piwikService.trackView(this.properties, this.pageTitle, this.piwikSiteId).subscribe()); this.subscriptions.push(this._piwikService.trackView(this.properties, this.pageTitle, this.piwikSiteId).subscribe());
} }
this.layoutService.isMobile.subscribe(isMobile => {
this.isMobile = isMobile;
this.cdr.detectChanges();
});
this.route.queryParams.subscribe(params => { this.route.queryParams.subscribe(params => {
if (params['page'] && params['page'] != 1) { if (params['page'] && params['page'] != 1) {
HelperFunctions.scrollToId("searchForm"); HelperFunctions.scrollToId("searchForm");

View File

@ -1,71 +1,40 @@
<ul class="uk-list uk-list-xlarge" [class]="'uk-list uk-margin ' + custom_class" <ul class="uk-list uk-list-large uk-margin" [class.uk-list-xlarge]="!isMobile" [ngClass]="custom_class"
uk-height-match="target: .uk-card-default; row: false"> uk-height-match="target: .uk-card-default; row: false">
<errorMessages [status]="[status]" [type]="'results'"></errorMessages> <errorMessages [status]="[status]" [type]="'results'"></errorMessages>
<li *ngFor="let result of results"> <li *ngFor="let result of results">
<div class="uk-card uk-card-default uk-card-body uk-position-relative uk-flex uk-flex-column uk-flex-center" <div class="uk-card uk-card-default uk-card-body uk-position-relative uk-flex uk-flex-column uk-flex-center"
[ngClass]="result.type" [class.uk-disabled]="!hasPermission(result)"> [ngClass]="result.type" [class.uk-disabled]="!hasPermission(result)">
<div> <div *ngIf="type === 'community' && result.isSubscribed" [class.uk-position-top-left]="!isMobile" [class.uk-position-top-right]="isMobile" class="uk-text-background uk-text-center uk-padding-small uk-text-uppercase uk-text-bold">
<div *ngIf="type === 'community' && result.isSubscribed"
class="uk-text-background uk-text-center uk-position-top-left uk-padding-small uk-text-uppercase uk-text-bold">
<span>Member</span> <span>Member</span>
</div> </div>
<div *ngIf="type === 'community' && result.status === 'manager'" <div [ngClass]="isMobile?'uk-flex uk-flex-middle uk-margin-bottom':'uk-position-top-right uk-margin-top uk-margin-right uk-flex uk-flex-column uk-flex-middle'">
class="uk-position-top-right uk-margin-top uk-margin-right uk-flex uk-flex-column uk-flex-middle"> <div *ngIf="type === 'community' && result.status === 'manager'">
<icon [name]="visibilityIcon.get('RESTRICTED')" ratio="1.2" [flex]="true"></icon> <icon [name]="visibilityIcon.get('RESTRICTED')" [ratio]="isMobile?0.8:1.2" [flex]="true"></icon>
<span class="uk-text-small uk-text-capitalize">restricted</span> <span class="uk-text-small uk-text-capitalize" [class.uk-text-xsmall]="isMobile" [class.uk-margin-xsmall-left]="isMobile">restricted</span>
</div>
<div *ngIf="type === 'community' && result.status === 'hidden'"
class="uk-position-top-right uk-margin-top uk-margin-right uk-flex uk-flex-column uk-flex-middle">
<icon [name]="visibilityIcon.get('PRIVATE')" ratio="1.2" [flex]="true"></icon>
<span class="uk-text-small uk-text-capitalize">private</span>
</div>
<div *ngIf="result.visibility && result.visibility !== 'PUBLIC'"
class="uk-position-top-right uk-margin-top uk-margin-right uk-flex uk-flex-column uk-flex-middle">
<icon [name]="visibilityIcon.get(result.visibility)" ratio="1.2" [flex]="true"></icon>
<span class="uk-text-small uk-text-capitalize">{{result.visibility.toLowerCase()}}</span>
</div> </div>
<ng-container *ngIf="type === 'community' && result.status === 'hidden'">
<icon [name]="visibilityIcon.get('PRIVATE')" [ratio]="isMobile?0.8:1.2" [flex]="true"></icon>
<span class="uk-text-small uk-text-capitalize" [class.uk-text-xsmall]="isMobile" [class.uk-margin-xsmall-left]="isMobile">private</span>
</ng-container>
<ng-container *ngIf="result.visibility && result.visibility !== 'PUBLIC'">
<icon [name]="visibilityIcon.get(result.visibility)" [ratio]="isMobile?0.8:1.2" [flex]="true"></icon>
<span class="uk-text-small uk-text-capitalize" [class.uk-text-xsmall]="isMobile" [class.uk-margin-xsmall-left]="isMobile">{{result.visibility.toLowerCase()}}</span>
</ng-container>
</div> </div>
<div class="uk-grid uk-flex uk-flex-middle uk-margin-medium-right" uk-grid> <div class="uk-grid uk-flex uk-flex-middle uk-margin-medium-right" uk-grid>
<a *ngIf="directLink && hasPermission(result)"
[href]="(type === 'community')?getCommunityPageUrl(result):getStakeholderPageUrl(result)"
target="_blank" class="uk-width-1-5@s">
<ng-container *ngTemplateOutlet="resultPreview; context: {result: result}"></ng-container>
</a>
<a *ngIf="!directLink && hasPermission(result)"
class="uk-width-1-5@s uk-width-1-1"
(click)="confirmModalOpen(result)">
<ng-container *ngTemplateOutlet="resultPreview; context: {result: result}"></ng-container>
</a>
<div *ngIf="!hasPermission(result)" class="uk-width-1-5@s">
<ng-container *ngTemplateOutlet="resultPreview; context: {result: result}"></ng-container>
</div>
<div class="uk-width-expand"> <div class="uk-width-expand">
<h5 [class.uk-h5]="!isMobile" [class.uk-h6]="isMobile">
<div *ngIf="type === 'community'" [title]="result.shortTitle" class="uk-margin-bottom"> <div *ngIf="type === 'community'" [title]="result.shortTitle" class="uk-margin-bottom">
<a *ngIf="directLink && hasPermission(result)" [href]="getCommunityPageUrl(result)" <a *ngIf="directLink && hasPermission(result)" [href]="getCommunityPageUrl(result)" class="uk-link-heading uk-text-truncate uk-display-inline-block" target="_blank">{{(result.title) ? result.title : result.shortTitle}}</a>
class="uk-h5 uk-link-heading" target="_blank"> <a *ngIf="!directLink && hasPermission(result)" (click)="confirmModalOpen(result)" class="uk-link-heading uk-text-truncate uk-display-inline-block">{{(result.title) ? result.title : result.shortTitle}}</a>
{{(result.title) ? result.title : result.shortTitle}} <div *ngIf="!hasPermission(result)" class="uk-text-truncate uk-display-inline-block">{{(result.title) ? result.title : result.shortTitle}}</div>
</a>
<a *ngIf="!directLink && hasPermission(result)" (click)="confirmModalOpen(result)"
class="uk-h5 uk-link-heading">
{{(result.title) ? result.title : result.shortTitle}}
</a>
<h5 *ngIf="!hasPermission(result)">
{{(result.title) ? result.title : result.shortTitle}}
</h5>
</div> </div>
<div *ngIf="type === 'stakeholder'" [title]="result.index_shortName" class="uk-margin-bottom"> <div *ngIf="type === 'stakeholder'" [title]="result.index_shortName" class="uk-margin-bottom">
<a *ngIf="directLink && hasPermission(result)" [href]="getStakeholderPageUrl(result)" <a *ngIf="directLink && hasPermission(result)" [href]="getStakeholderPageUrl(result)" class="uk-link-heading uk-text-truncate uk-display-inline-block" target="_blank">{{(result.name) ? result.name : result.index_shortName}}</a>
class="uk-h5 uk-link-heading" target="_blank"> <a *ngIf="!directLink && hasPermission(result)" (click)="confirmModalOpen(result)" class="uk-link-heading uk-text-truncate uk-display-inline-block">{{(result.name) ? result.name : result.index_shortName}}</a>
{{(result.name) ? result.name : result.index_shortName}} <div *ngIf="!hasPermission(result)" class="uk-text-truncate uk-display-inline-block">{{(result.name) ? result.name : result.index_shortName}}</div>
</a>
<a *ngIf="!directLink && hasPermission(result)" (click)="confirmModalOpen(result)"
class="uk-h5 uk-link-heading">
{{(result.name) ? result.name : result.index_shortName}}
</a>
<h5 *ngIf="!hasPermission(result)">
{{(result.name) ? result.name : result.index_shortName}}
</h5>
</div> </div>
</h5>
<div class="uk-text-small"> <div class="uk-text-small">
<div *ngIf="result.date || result.creationDate" class="uk-flex uk-flex-middle uk-margin-small-bottom"> <div *ngIf="result.date || result.creationDate" class="uk-flex uk-flex-middle uk-margin-small-bottom">
<span class="uk-text-meta">Creation Date: </span> <span class="uk-text-meta">Creation Date: </span>
@ -78,10 +47,21 @@
<span class="uk-margin-small-left uk-text-capitalize">{{mapType(result.type)}}</span> <span class="uk-margin-small-left uk-text-capitalize">{{mapType(result.type)}}</span>
</div> </div>
</div> </div>
<div *ngIf="result.description" class="uk-margin-top uk-text-small multi-line-ellipsis lines-3"> <div *ngIf="result.description && !isMobile" class="uk-margin-top uk-text-small multi-line-ellipsis lines-3">
<p class="uk-text-meta" [innerHTML]="result.description"></p> <p class="uk-text-meta" [innerHTML]="result.description"></p>
</div> </div>
</div> </div>
<div class="uk-width-1-5@m uk-width-1-3 uk-flex-first@m">
<a *ngIf="directLink && hasPermission(result)" [href]="(type === 'community')?getCommunityPageUrl(result):getStakeholderPageUrl(result)" target="_blank">
<ng-container *ngTemplateOutlet="resultPreview; context: {result: result}"></ng-container>
</a>
<a *ngIf="!directLink && hasPermission(result)" (click)="confirmModalOpen(result)">
<ng-container *ngTemplateOutlet="resultPreview; context: {result: result}"></ng-container>
</a>
<div *ngIf="!hasPermission(result)">
<ng-container *ngTemplateOutlet="resultPreview; context: {result: result}"></ng-container>
</div>
</div>
</div> </div>
<div *ngIf="result.isManager" class="uk-flex uk-flex-right uk-margin-top"> <div *ngIf="result.isManager" class="uk-flex uk-flex-right uk-margin-top">
<manage [communityId]="result.communityId" [alias]="result.alias"></manage> <manage [communityId]="result.communityId" [alias]="result.alias"></manage>

View File

@ -1,14 +1,16 @@
@import (reference) "~src/assets/openaire-theme/less/color.less"; @import (reference) "~src/assets/openaire-theme/less/color.less";
@import (reference) "~src/assets/openaire-theme/less/_import-variables.less";
.setType(@color) { .setType(@color, @position: left) {
border-left: 4px solid fade(@color, 30%); border-@{position}: 4px solid fade(@color, 30%);
& .type { & .type {
color: @color; color: @color;
} }
} }
.uk-card { @media(min-width: @breakpoint-medium) {
.uk-card {
&.funder { &.funder {
.setType(@funder-color); .setType(@funder-color);
} }
@ -20,4 +22,21 @@
&.organization { &.organization {
.setType(@organization-color); .setType(@organization-color);
} }
}
}
@media(max-width: @breakpoint-small-max) {
.uk-card {
&.funder {
.setType(@funder-color, bottom);
}
&.ri {
.setType(@ri-color, bottom);
}
&.organization {
.setType(@organization-color, bottom);
}
}
} }

View File

@ -22,6 +22,7 @@ export class PortalSearchResultComponent implements OnInit{
@Input() showLoading: boolean = false; @Input() showLoading: boolean = false;
@Input() custom_class: string = "search-results"; @Input() custom_class: string = "search-results";
@Input() properties: EnvProperties; @Input() properties: EnvProperties;
@Input() isMobile: boolean = false;
@ViewChild('AlertModal') modal; @ViewChild('AlertModal') modal;
visibilityIcon: Map<Visibility, string> = new Map<Visibility, string> ([ visibilityIcon: Map<Visibility, string> = new Map<Visibility, string> ([
["PRIVATE", 'incognito'], ["PRIVATE", 'incognito'],

View File

@ -1,5 +1,5 @@
import {ChangeDetectorRef, Component, EventEmitter, Input, Output} from '@angular/core'; import {ChangeDetectorRef, Component, EventEmitter, Input, Output} from '@angular/core';
import {FormBuilder} from "@angular/forms"; import {UntypedFormBuilder} from "@angular/forms";
import {Filter} from "./searchHelperClasses.class"; import {Filter} from "./searchHelperClasses.class";
import {EnvProperties} from "../../utils/properties/env-properties"; import {EnvProperties} from "../../utils/properties/env-properties";
import {ConfigurationService} from "../../utils/configuration/configuration.service"; import {ConfigurationService} from "../../utils/configuration/configuration.service";
@ -48,7 +48,7 @@ export class QuickSelectionsComponent {
subs: Subscription[] = []; subs: Subscription[] = [];
constructor(private _fb: FormBuilder, private config: ConfigurationService, private _router: Router, private route: ActivatedRoute, private cdr:ChangeDetectorRef) { constructor(private _fb: UntypedFormBuilder, private config: ConfigurationService, private _router: Router, private route: ActivatedRoute, private cdr:ChangeDetectorRef) {
} }
changed() { changed() {

View File

@ -4,13 +4,13 @@ import {ErrorCodes} from '../../utils/properties/errorCodes';
@Component({ @Component({
selector: 'search-paging', selector: 'search-paging',
template: ` template: `
<paging *ngIf="results && searchUtils.totalResults > searchUtils.size" <paging *ngIf="results && searchUtils.totalResults > searchUtils.size" [position]="isMobile?'center':'right'"
[currentPage]="searchUtils.page" [totalResults]="searchUtils.totalResults" [baseUrl]="baseUrl" [currentPage]="searchUtils.page" [totalResults]="searchUtils.totalResults" [baseUrl]="baseUrl"
[size]="searchUtils.size" [parameterNames]="parameterNames" [parameterValues]="parameterValues" [size]="searchUtils.size" [parameterNames]="parameterNames" [parameterValues]="parameterValues"
[isDisabled]="isDisabled"> [isDisabled]="isDisabled">
</paging> </paging>
<paging *ngIf="!loadPaging && oldTotalResults > searchUtils.size && searchUtils.status == errorCodes.LOADING" <paging *ngIf="!loadPaging && oldTotalResults > searchUtils.size && searchUtils.status == errorCodes.LOADING"
[currentPage]="searchUtils.page" [totalResults]="oldTotalResults" [baseUrl]="baseUrl" [currentPage]="searchUtils.page" [totalResults]="oldTotalResults" [baseUrl]="baseUrl" [position]="isMobile?'center':'right'"
[size]="searchUtils.size" [parameterNames]="parameterNames" [parameterValues]="parameterValues" [size]="searchUtils.size" [parameterNames]="parameterNames" [parameterValues]="parameterValues"
[isDisabled]="isDisabled"> [isDisabled]="isDisabled">
</paging> </paging>
@ -26,6 +26,7 @@ export class SearchPagingComponent {
@Input() parameterValues: string[]; @Input() parameterValues: string[];
@Input() loadPaging: boolean = true; @Input() loadPaging: boolean = true;
@Input() oldTotalResults: number = 0; @Input() oldTotalResults: number = 0;
@Input() isMobile: boolean = false;
public totalResults: number = 0; public totalResults: number = 0;
public errorCodes: ErrorCodes = new ErrorCodes(); public errorCodes: ErrorCodes = new ErrorCodes();

View File

@ -40,7 +40,7 @@ export class SearchResultComponent implements OnInit, OnChanges {
this.previewResults.push(this.getResultPreview(result)); this.previewResults.push(this.getResultPreview(result));
} }
if((properties.adminToolsPortalType == "explore" || properties.adminToolsPortalType == "community") if((properties.adminToolsPortalType == "explore" || properties.adminToolsPortalType == "community" || properties.adminToolsPortalType == "aggregator")
&& Session.isLoggedIn() && this.results && this.results.length > 0 && Session.isLoggedIn() && this.results && this.results.length > 0
&& (this.type == "result" || this.type == "publication" || this.type == "dataset" || this.type == "software" || this.type == "other") && (this.type == "result" || this.type == "publication" || this.type == "dataset" || this.type == "software" || this.type == "other")
) { ) {

View File

@ -14,7 +14,7 @@ export class CustomizationService {
const isArray = obj instanceof Array; const isArray = obj instanceof Array;
for (let k in obj) { for (let k in obj) {
if (obj[k] === null || obj[k] === '') { if (obj[k] === null || obj[k] === '') {
isArray ? obj.splice(k, 1) : delete obj[k]; isArray ? obj.splice(Number.parseInt(k), 1) : delete obj[k];
} else if (typeof obj[k] === 'object') { } else if (typeof obj[k] === 'object') {
CustomizationService.removeNulls(obj[k]); CustomizationService.removeNulls(obj[k]);
} }

View File

@ -350,6 +350,11 @@ export class HelpContentService {
.pipe(catchError(this.handleError)); .pipe(catchError(this.handleError));
} }
alignMenu(alignment: string, portalPid: string) {
return this.http.post<Menu>(properties.adminToolsAPIURL + properties.adminToolsPortalType + "/" + portalPid + "/menu/align?alignment=" + alignment, {}, CustomOptions.getAuthOptionsWithBody())
.pipe(catchError(this.handleError));
}
// unused // unused
getCommunities( helpContentUrl:string) { getCommunities( helpContentUrl:string) {

View File

@ -77,7 +77,7 @@ export class RefineFieldResultsService {
}else if(entityType == "person"){ }else if(entityType == "person"){
suffix="people/"; suffix="people/";
}else if(entityType == "result"){ }else if(entityType == "result"){
suffix="publications/"; suffix="results/";
} }
return suffix; return suffix;
} }

View File

@ -13,19 +13,11 @@ export class ReportsService {
//On the service: //On the service:
downloadCSVFile(url: string){ downloadCSVFile(url: string){
//var headers = new Headers(); return this.http.get(url, {responseType: 'text'}).pipe(map(res => new Blob([res], { type: 'text/csv' })));
//headers.append('responseType', 'arraybuffer');
return this.http.get(url, {responseType: 'text'})
.pipe(
timeout(10000),
map(res => new Blob([res], { type: 'text/csv' })));
} }
getCSVResponse(url: string){ getCSVResponse(url: string){
//var headers = new Headers();
//headers.append('responseType', 'arraybuffer');
return this.http.get(url, {responseType: 'text'}) return this.http.get(url, {responseType: 'text'})
.pipe(timeout(10000));
//.pipe(map(res => res));
} }
/** /**

View File

@ -106,8 +106,14 @@ export class SearchDataprovidersService {
result['title'] = {"name": '', "accessMode": ''}; result['title'] = {"name": '', "accessMode": ''};
result['title'].name = resData.officialname; if(resData.officialname) {
result['englishname'] = resData.englishname; result['title'].name = StringUtils.HTMLToString(String(resData.officialname));
}
if(resData.englishname) {
result['englishname'] = StringUtils.HTMLToString(String(resData.englishname));
} else {
result['englishname'] = "";
}
//result['title'].url = OpenaireProperties.getsearchLinkToDataProvider(); //result['title'].url = OpenaireProperties.getsearchLinkToDataProvider();
//result['title'].url += Array.isArray(data) ? data[i]['result']['header']['dri:objIdentifier'] : data['result']['header']['dri:objIdentifier']; //result['title'].url += Array.isArray(data) ? data[i]['result']['header']['dri:objIdentifier'] : data['result']['header']['dri:objIdentifier'];
@ -125,9 +131,9 @@ export class SearchDataprovidersService {
let abstracts = this.parsingFunctions.parseDescription(resData.description, true); let abstracts = this.parsingFunctions.parseDescription(resData.description, true);
result.description = abstracts; result.description = abstracts;
if (result.description && result.description.length > this.sizeOfDescription) { // if (result.description && result.description.length > this.sizeOfDescription) {
result.description = result.description.substring(0, this.sizeOfDescription) + "..."; // result.description = result.description.substring(0, this.sizeOfDescription) + "...";
} // }
let typeid: string = resData['datasourcetype'].classid; let typeid: string = resData['datasourcetype'].classid;
if(typeid != "entityregistry" && typeid != "entityregistry::projects" && typeid != "entityregistry::repositories") { if(typeid != "entityregistry" && typeid != "entityregistry::projects" && typeid != "entityregistry::repositories") {

View File

@ -94,9 +94,11 @@ export class SearchOrganizationsService {
result['title'] = {"name": '', "accessMode": ''}; result['title'] = {"name": '', "accessMode": ''};
result['title'].name = resData.legalshortname; if(resData.legalshortname) {
result['title'].name = StringUtils.HTMLToString(String(resData.legalshortname));
}
if(!result['title'].name || result['title'].name == '') { if(!result['title'].name || result['title'].name == '') {
result['title'].name = resData.legalname; result['title'].name = StringUtils.HTMLToString(String(resData.legalname));
} }
//result['title'].url = OpenaireProperties.getsearchLinkToOrganization(); //result['title'].url = OpenaireProperties.getsearchLinkToOrganization();

View File

@ -135,10 +135,14 @@ export class SearchProjectsService {
// if(resData['acronym'] != undefined && resData['acronym'] != "") { // if(resData['acronym'] != undefined && resData['acronym'] != "") {
// result['title'].name = resData['acronym'] + " - "; // result['title'].name = resData['acronym'] + " - ";
// } // }
if(Array.isArray(resData['title'])) { if(resData['title']) {
result['title'].name += resData['title'][0]; if (Array.isArray(resData['title'])) {
result['title'].name += StringUtils.HTMLToString(String(resData['title'][0]));
} else { } else {
result['title'].name += resData['title']; result['title'].name += StringUtils.HTMLToString(String(resData['title']));
}
} else {
result['title'].name = "";
} }
// if(result['title'].name != '') { // if(result['title'].name != '') {
@ -160,9 +164,9 @@ export class SearchProjectsService {
let abstracts = this.parsingFunctions.parseDescription(resData.summary, true); let abstracts = this.parsingFunctions.parseDescription(resData.summary, true);
result.description = abstracts; result.description = abstracts;
if (result.description && result.description.length > this.sizeOfDescription) { // if (result.description && result.description.length > this.sizeOfDescription) {
result.description = result.description.substring(0, this.sizeOfDescription) + "..."; // result.description = result.description.substring(0, this.sizeOfDescription) + "...";
} // }
if(resData['rels'].hasOwnProperty("rel")) { if(resData['rels'].hasOwnProperty("rel")) {
let relLength = Array.isArray(resData['rels']['rel']) ? resData['rels']['rel'].length : 1; let relLength = Array.isArray(resData['rels']['rel']) ? resData['rels']['rel'].length : 1;

View File

@ -205,7 +205,17 @@ export class SearchResearchResultsService {
for (let i = 0; i < resData['measure'].length; i++) { for (let i = 0; i < resData['measure'].length; i++) {
if (resData['measure'][i].id == 'influence') { if (resData['measure'][i].id == 'influence') {
result.measure[1] = resData['measure'][i].class; result.measure[1] = resData['measure'][i].class;
if (resData['measure'][i].class == 'A') { if (resData['measure'][i].class == 'C1') {
result.measure[3] = 'Top 0.01% in';
} else if (resData['measure'][i].class == 'C2') {
result.measure[3] = 'Top 0.1% in';
} else if (resData['measure'][i].class == 'C3') {
result.measure[3] = 'Top 1% in';
} else if (resData['measure'][i].class == 'C4') {
result.measure[3] = 'Top 10% in';
} else if (resData['measure'][i].class == 'C5') {
result.measure[3] = 'Average/low';
} else if (resData['measure'][i].class == 'A') {
result.measure[3] = 'Exceptional'; result.measure[3] = 'Exceptional';
} else if (resData['measure'][i].class == 'B') { } else if (resData['measure'][i].class == 'B') {
result.measure[3] = 'Substantial'; result.measure[3] = 'Substantial';
@ -215,7 +225,17 @@ export class SearchResearchResultsService {
} }
if (resData['measure'][i].id == 'popularity') { if (resData['measure'][i].id == 'popularity') {
result.measure[0] = resData['measure'][i].class; result.measure[0] = resData['measure'][i].class;
if (resData['measure'][i].class == 'A') { if (resData['measure'][i].class == 'C1') {
result.measure[2] = 'Top 0.01% in';
} else if (resData['measure'][i].class == 'C2') {
result.measure[2] = 'Top 0.1% in';
} else if (resData['measure'][i].class == 'C3') {
result.measure[2] = 'Top 1% in';
} else if (resData['measure'][i].class == 'C4') {
result.measure[2] = 'Top 10% in';
} else if (resData['measure'][i].class == 'C5') {
result.measure[2] = 'Average/low';
} else if (resData['measure'][i].class == 'A') {
result.measure[2] = 'Exceptional'; result.measure[2] = 'Exceptional';
} else if (resData['measure'][i].class == 'B') { } else if (resData['measure'][i].class == 'B') {
result.measure[2] = 'Substantial'; result.measure[2] = 'Substantial';
@ -299,7 +319,7 @@ export class SearchResearchResultsService {
for (let i = 0; i < resData['title'].length; i++) { for (let i = 0; i < resData['title'].length; i++) {
if (resData['title'][i] && resData['title'][i].content) { if (resData['title'][i] && resData['title'][i].content) {
if (!result.title.name || resData['title'][i].classid == "main title") { if (!result.title.name || resData['title'][i].classid == "main title") {
result['title'].name = String(resData['title'][i].content); result['title'].name = StringUtils.HTMLToString(String(resData['title'][i].content));
} }
if (resData['title'][i].classid == "main title") { if (resData['title'][i].classid == "main title") {
break; break;
@ -311,7 +331,7 @@ export class SearchResearchResultsService {
} }
// result['title'].name = (resData['title'][0] && resData['title'][0].content) ? String(resData['title'][0].content) : ""; // result['title'].name = (resData['title'][0] && resData['title'][0].content) ? String(resData['title'][0].content) : "";
} else { } else {
result['title'].name = (resData['title'] && resData['title'].content) ? String(resData['title'].content) : ""; result['title'].name = (resData['title'] && resData['title'].content) ? StringUtils.HTMLToString(String(resData['title'].content)) : "";
} }
result['id'] = Array.isArray(data) ? data[i]['result']['header']['dri:objIdentifier'] : data['result']['header']['dri:objIdentifier']; result['id'] = Array.isArray(data) ? data[i]['result']['header']['dri:objIdentifier'] : data['result']['header']['dri:objIdentifier'];
@ -373,9 +393,9 @@ export class SearchResearchResultsService {
let abstracts = this.parsingFunctions.parseDescription(resData.description, true); let abstracts = this.parsingFunctions.parseDescription(resData.description, true);
result.description = abstracts; result.description = abstracts;
if (result.description && result.description.length > this.sizeOfDescription) { // if (result.description && result.description.length > this.sizeOfDescription) {
result.description = result.description.substring(0, this.sizeOfDescription) + "..."; // result.description = result.description.substring(0, this.sizeOfDescription) + "...";
} // }
if (resData.embargoenddate && resData.embargoenddate != '') { if (resData.embargoenddate && resData.embargoenddate != '') {
result.embargoEndDate = Dates.getDate(resData.embargoenddate); result.embargoEndDate = Dates.getDate(resData.embargoenddate);

View File

@ -1,9 +1,8 @@
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
import {BehaviorSubject, from, Observable} from "rxjs"; import {Observable} from "rxjs";
import {COOKIE, Session, User} from "../login/utils/helper.class"; import {Session, User} from "../login/utils/helper.class";
import {map} from "rxjs/operators"; import {map} from "rxjs/operators";
import {NavigationEnd, Router} from "@angular/router";
import {properties} from "../../../environments/environment"; import {properties} from "../../../environments/environment";
import {StringUtils} from "../utils/string-utils.class"; import {StringUtils} from "../utils/string-utils.class";
import {CustomOptions} from "./servicesUtils/customOptions.class"; import {CustomOptions} from "./servicesUtils/customOptions.class";

View File

@ -1,24 +1,38 @@
<ng-template #grant>
<div class="uk-margin-small-top">
<img style="max-width: 42px;" [src]="assetsPath + 'common/commission.jpg'" alt="flag black white low" width="50px" loading="lazy">
</div>
<div class="uk-margin-left">
<helper *ngIf="divContents && divContents['footer']?.length > 0"
[texts]="divContents['footer']"></helper>
<div *ngIf="properties.footerGrantText">
<span class="uk-text-xsmall" [innerHtml]="properties.footerGrantText"></span>
</div>
</div>
</ng-template>
<ng-container *ngIf="shortView;else longView"> <ng-container *ngIf="shortView;else longView">
<div *ngIf="properties.footerGrantText || (divContents && divContents['footer']?.length > 0)" <div *ngIf="properties.footerGrantText || (divContents && divContents['footer']?.length > 0)"
class="uk-padding uk-flex uk-flex-middle"> class="uk-padding uk-flex uk-flex-middle">
<div *ngIf="showCommision" class="uk-width-1-2 uk-margin-left"> <div *ngIf="showCommision" class="uk-width-1-2 uk-margin-left">
<div class="uk-flex uk-flex-middle"> <div class="uk-flex uk-flex-middle@m uk-flex-top">
<div> <div>
<img style="margin-right: 8px; float: left;" <img style="max-width: 42px;"
[src]="assetsPath + 'common/commission.jpg'" [src]="assetsPath + 'common/commission.jpg'"
alt="flag black white low" width="50px" height="33px" loading="lazy"> alt="flag black white low" width="50px" loading="lazy">
</div> </div>
<div class="uk-margin-left"> <div class="uk-margin-left">
<helper *ngIf="divContents && divContents['footer']?.length > 0" <helper *ngIf="divContents && divContents['footer']?.length > 0"
[texts]="divContents['footer']"></helper> [texts]="divContents['footer']"></helper>
<div class="uk-visible@m"> <div class="uk-visible@m">
<div *ngIf="properties.footerGrantText" class=""> <div *ngIf="properties.footerGrantText" class="">
<span style="font-size: 12px; line-height: 0.7!important;" [innerHtml]="properties.footerGrantText"></span> <span style="font-size: 12px; line-height: 0.7!important;"
[innerHtml]="properties.footerGrantText"></span>
</div> </div>
</div> </div>
<div class="uk-text-center uk-hidden@m"> <div class="uk-text-center uk-hidden@m">
<div *ngIf="properties.footerGrantText" class=""> <div *ngIf="properties.footerGrantText" class="">
<span style="font-size: 12px; line-height: 0.7!important;" [innerHtml]="properties.footerGrantText"></span> <span style="font-size: 12px; line-height: 0.7!important;"
[innerHtml]="properties.footerGrantText"></span>
</div> </div>
</div> </div>
</div> </div>
@ -33,92 +47,46 @@
</div> </div>
</ng-container> </ng-container>
<ng-template #longView> <ng-template #longView>
<div [class]="sectionClass + ' uk-section uk-padding-remove-bottom'"> <div class="uk-visible@m">
<div [class]="'uk-container ' +(centered?'uk-container-small':'uk-container-expand') "> <div [ngClass]="background">
<!-- <div class="uk-container uk-container-expand uk-margin-small">--> <div class="uk-section uk-padding-remove-bottom">
<div [class]="(centered?'':'uk-grid uk-grid-collapse ') "> <div class="uk-container" [class.uk-container-expand]="!centered" [class.uk-container-small]="centered">
<div id="footer#3" <div class="uk-grid" [class.uk-flex-center]="centered" uk-grid>
[class]="'uk-first-column uk-flex uk-flex-middle ' + <div *ngIf="properties.footerGrantText || (divContents && divContents['footer']?.length > 0)"
(centered?'uk-grid uk-margin-remove-right':'uk-margin-large-right ' + class="uk-width-1-1" [class.uk-width-1-3@m]="!centered"
(properties.footerGrantText || (divContents && divContents['footer']?.length > 0) ? 'uk-width-1-3@m' : '')) + [attr.uk-grid]="centered?'':null" [class.uk-grid]="centered">
(centered && showMenuItems ? '' : ' uk-flex-column')"> <div *ngIf="showOpenaire" class="uk-text-center uk-margin-bottom uk-width-1-1"
<ng-container *ngIf="properties.footerGrantText || (divContents && divContents['footer']?.length > 0)"> [class.uk-width-1-4@m]="centered">
<div *ngIf="showOpenaire"
[class]="(centered?'uk-width-1-1 uk-width-1-4@m uk-text-center ':'') +
(centered && showMenuItems ? '' : 'uk-margin-bottom')">
<!-- <img [src]="assetsPath + 'common/Logo_Horizontal_'+(darkBackground?'white':'dark')+'_small.png'" -->
<img [src]="assetsPath + 'common/Logo_Horizontal.png'" <img [src]="assetsPath + 'common/Logo_Horizontal.png'"
width="140px" width="140px"
height="50px" class="el-image" alt="OpenAIRE" loading="lazy"> height="50px" class="el-image" alt="OpenAIRE" loading="lazy">
</div> </div>
<div *ngIf="showCommision" id="footer#5" <div *ngIf="showCommision" class="uk-width-expand">
[class]="'uk-text-left '+(centered?' uk-margin uk-width-expand':' uk-margin-left')"> <div class="uk-flex uk-flex-top uk-flex-center">
<!-- [src]="assetsPath + 'common/commission'+(this.darkBackground?'.jpg':'-dark.png')"--> <ng-container *ngTemplateOutlet="grant"></ng-container>
<!-- <div *ngIf="!grantAdvance" class="uk-margin">-->
<!-- <img style="margin-right: 8px; float: left;"-->
<!-- [src]="assetsPath + 'common/commission'+(this.darkBackground?'.jpg':'-dark.png')"-->
<!-- alt="flag black white low" width="50" height="33">-->
<!-- <span style="font-size: 8pt; line-height: 0.7!important;" [innerHtml] = "grantConenctText"></span>-->
<!-- </div>-->
<!-- <div class="uk-margin">-->
<!-- <img style="margin-right: 8px; float: left;" [src]="assetsPath + 'common/commission'+(this.darkBackground?'.jpg':'-dark.png')" alt="flag black white low" width="50" height="33">-->
<!-- <span style="font-size: 8pt; line-height: 0.7!important;" [innerHtml] = "grantAdvanceText"></span>-->
<!-- </div>-->
<div class="uk-flex uk-flex-middle">
<div>
<img style="margin-right: 8px; float: left;"
[src]="assetsPath + 'common/commission.jpg'"
alt="flag black white low" width="50px" height="33px" loading="lazy">
</div>
<div class="uk-margin-left">
<helper *ngIf="divContents && divContents['footer']?.length > 0"
[texts]="divContents['footer']"></helper>
<div *ngIf="properties.footerGrantText" class="">
<span style="font-size: 12px; line-height: 0.7!important;" [innerHtml]="properties.footerGrantText"></span>
</div> </div>
</div> </div>
</div> </div>
<!--img [src]="assetsPath + 'common/commission.jpg'" sizes="(min-width: 50px) 50px" data-width="427" data-height="285" class="el-image" alt="European Commission"--> <div [class.uk-hidden]="centered" class="uk-grid uk-width-expand" uk-grid>
</div> <div *ngIf="showMenuItems" class="uk-width-expand">
<!--<div *ngIf="showSocialButtons" id="footer#6" class="newsletter uk-margin uk-margin-remove-bottom uk-text-left@s uk-text-center uk-panel"> <div class="uk-text-right uk-text-center">
<ul class="uk-nav uk-nav-default" uk-nav>
<a target="_blank" href="https://www.openaire.eu/newsletter/listing" class="el-link newsletter"> <ng-container *ngFor="let item of menuItems">
<h6 class="el-title uk-margin"> <li *ngIf="isEnabled(item.routeRequired, showPage)">
Newsletter <a *ngIf="item.route.length > 0" routerLink="{{item.route}}"
<span class="el-image uk-icon"> [queryParams]=item.params>{{item.title}}</a>
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <a *ngIf="item.route.length == 0 && item.url.length > 0" href="{{item.url}}"
<circle cx="3.12" cy="16.8" r="1.85"></circle> target="_blank">{{item.title}}</a>
<path fill="none" stroke="#000" stroke-width="1.1" d="M1.5,8.2 C1.78,8.18 2.06,8.16 2.35,8.16 C7.57,8.16 11.81,12.37 11.81,17.57 C11.81,17.89 11.79,18.19 11.76,18.5"></path>
<path fill="none" stroke="#000" stroke-width="1.1" d="M1.5,2.52 C1.78,2.51 2.06,2.5 2.35,2.5 C10.72,2.5 17.5,9.24 17.5,17.57 C17.5,17.89 17.49,18.19 17.47,18.5"></path>
</svg>
</span>
</h5>
</a>
</div>-->
</ng-container>
</div>
<div [class]="(!centered?'uk-grid uk-width-expand':'')">
<div *ngIf="showMenuItems" [class]="'uk-width-expand@m '+ (darkBackground?'uk-light':'')">
<div id="footer#7" class="uk-text-right@m uk-text-center">
<ul [class]="(centered?'uk-flex-center':'')
+' uk-subnav uk-margin-remove-bottom uk-subnav-divider'" uk-margin="">
<ng-container *ngFor="let submenu of menuItems">
<li class="el-item" *ngIf="isEnabled(submenu.routeRequired, showPage)">
<a *ngIf="submenu.route.length > 0" routerLink="{{submenu.route}}"
[queryParams]=submenu.params>{{submenu.title}}</a>
<a *ngIf="submenu.route.length == 0 && submenu.url.length > 0" href="{{submenu.url}}"
target="_blank">{{submenu.title}}</a>
</li> </li>
</ng-container> </ng-container>
</ul> </ul>
</div> </div>
</div> </div>
<div *ngIf="!showMenuItems" id="footer#9" class="uk-width-expand@s uk-visible@m"> <ng-container *ngIf="!showMenuItems">
<div id="footer#10" class="uk-width-medium uk-text-left@s uk-text-center uk-panel"> <div class="uk-width-1-3">
<h6 class="el-title uk-h6">Dashboards</h6> <div>
<ul class="uk-nav uk-nav-default uk-nav-parent-icon uk-nav-accordion" uk-nav=""> <h6>Dashboards</h6>
<ul class="uk-nav uk-nav-default" uk-nav>
<li><a <li><a
[href]="'https://'+(properties.environment =='beta' || properties.environment =='development'?'beta.':'')+'explore.openaire.eu'" [href]="'https://'+(properties.environment =='beta' || properties.environment =='development'?'beta.':'')+'explore.openaire.eu'"
target="_blank">Explore</a></li> target="_blank">Explore</a></li>
@ -135,11 +103,10 @@
</ul> </ul>
</div> </div>
</div> </div>
<div *ngIf="!showMenuItems" id="footer#11" class="uk-width-expand@s uk-visible@m"> <div class="uk-width-1-3">
<div id="footer#12" class="uk-width-medium uk-text-left@s uk-text-center uk-panel"> <div>
<h6>Support</h6> <h6>Support</h6>
<ul class="uk-nav uk-nav-default uk-nav-parent-icon uk-nav-accordion" uk-nav=""> <ul class="uk-nav uk-nav-default" uk-nav>
<li><a target="_blank" href="https://www.openaire.eu/contact-noads">NOADs</a></li> <li><a target="_blank" href="https://www.openaire.eu/contact-noads">NOADs</a></li>
<li><a target="_blank" href="https://www.openaire.eu/guides">Guides</a></li> <li><a target="_blank" href="https://www.openaire.eu/guides">Guides</a></li>
<li><a target="_blank" href="https://www.openaire.eu/faqs">FAQs</a></li> <li><a target="_blank" href="https://www.openaire.eu/faqs">FAQs</a></li>
@ -148,10 +115,10 @@
</ul> </ul>
</div> </div>
</div> </div>
<div *ngIf="!showMenuItems" id="footer#13" class="uk-width-expand@s uk-visible@m"> <div class="uk-width-1-3">
<div id="footer#14" class="uk-width-medium uk-text-left@s uk-text-center uk-panel"> <div class="">
<h6>Updates</h6> <h6>Updates</h6>
<ul class="uk-nav uk-nav-default uk-nav-parent-icon uk-nav-accordion" uk-nav=""> <ul class="uk-nav uk-nav-default" uk-nav>
<li><a target="_blank" href="https://www.openaire.eu/news/">News</a></li> <li><a target="_blank" href="https://www.openaire.eu/news/">News</a></li>
<li><a target="_blank" href="https://www.openaire.eu/events">Events</a></li> <li><a target="_blank" href="https://www.openaire.eu/events">Events</a></li>
<li><a target="_blank" href="https://www.openaire.eu/blogs/magazine">Blogs</a></li> <li><a target="_blank" href="https://www.openaire.eu/blogs/magazine">Blogs</a></li>
@ -160,161 +127,154 @@
</ul> </ul>
</div> </div>
</div> </div>
</ng-container>
</div> </div>
<div *ngIf="showSocialButtons" class="uk-margin-medium uk-text-center uk-width-1-1"> <div *ngIf="showSocialButtons" class="uk-margin-medium-top uk-margin-medium-bottom uk-width-1-1">
<div [class]="(centered?'uk-flex-center':'uk-flex-left ') + <div class="uk-flex uk-flex-middle uk-flex-wrap" [class.uk-flex-center]="centered">
' uk-flex-middle uk-child-width-auto uk-grid-small uk-grid'" uk-grid> <div class="uk-grid uk-grid-small uk-width-auto@m uk-child-width-auto" uk-grid>
<div> <div>
<a href="https://www.twitter.com/OpenAIRE_eu" target="_blank" <a href="https://www.twitter.com/OpenAIRE_eu" target="_blank"
class="uk-icon-button" style="background-color: #55ACEE;"> class="uk-icon-button uk-icon uk-icon-button-small twitter">
<svg width="20" height="20" fill="#fff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <icon name="twitter" [flex]="true" visuallyHidden="twitter"></icon>
<path
d="M19,4.74 C18.339,5.029 17.626,5.229 16.881,5.32 C17.644,4.86 18.227,4.139 18.503,3.28 C17.79,3.7 17.001,4.009 16.159,4.17 C15.485,3.45 14.526,3 13.464,3 C11.423,3 9.771,4.66 9.771,6.7 C9.771,6.99 9.804,7.269 9.868,7.539 C6.795,7.38 4.076,5.919 2.254,3.679 C1.936,4.219 1.754,4.86 1.754,5.539 C1.754,6.82 2.405,7.95 3.397,8.61 C2.79,8.589 2.22,8.429 1.723,8.149 L1.723,8.189 C1.723,9.978 2.997,11.478 4.686,11.82 C4.376,11.899 4.049,11.939 3.713,11.939 C3.475,11.939 3.245,11.919 3.018,11.88 C3.49,13.349 4.852,14.419 6.469,14.449 C5.205,15.429 3.612,16.019 1.882,16.019 C1.583,16.019 1.29,16.009 1,15.969 C2.635,17.019 4.576,17.629 6.662,17.629 C13.454,17.629 17.17,12 17.17,7.129 C17.17,6.969 17.166,6.809 17.157,6.649 C17.879,6.129 18.504,5.478 19,4.74"></path>
</svg>
<span class="visually-hidden">twitter</span>
</a> </a>
</div> </div>
<div> <div>
<a href="https://www.facebook.com/groups/openaire/" target="_blank" <a href="https://www.facebook.com/groups/openaire/" target="_blank"
class="uk-icon-button" style="background-color: #3A5998;"> class="uk-icon-button uk-icon-button-small facebook">
<svg width="20" height="20" fill="#fff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <icon name="facebook" [flex]="true" visuallyHidden="facebook"></icon>
<path
d="M11,10h2.6l0.4-3H11V5.3c0-0.9,0.2-1.5,1.5-1.5H14V1.1c-0.3,0-1-0.1-2.1-0.1C9.6,1,8,2.4,8,5v2H5.5v3H8v8h3V10z"></path>
</svg>
<span class="visually-hidden">facebook</span>
</a> </a>
</div> </div>
<div> <div>
<a href="https://www.linkedin.com/groups/3893548/" target="_blank" <a href="https://www.linkedin.com/groups/3893548/" target="_blank"
class="uk-icon-button" style="background-color: #1F88BE;"> class="uk-icon-button uk-icon-button-small linkedin">
<svg width="20" height="20" fill="#fff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <icon name="linkedin" [flex]="true" visuallyHidden="linkedin"></icon>
<path
d="M5.77,17.89 L5.77,7.17 L2.21,7.17 L2.21,17.89 L5.77,17.89 L5.77,17.89 Z M3.99,5.71 C5.23,5.71 6.01,4.89 6.01,3.86 C5.99,2.8 5.24,2 4.02,2 C2.8,2 2,2.8 2,3.85 C2,4.88 2.77,5.7 3.97,5.7 L3.99,5.7 L3.99,5.71 L3.99,5.71 Z"></path>
<path
d="M7.75,17.89 L11.31,17.89 L11.31,11.9 C11.31,11.58 11.33,11.26 11.43,11.03 C11.69,10.39 12.27,9.73 13.26,9.73 C14.55,9.73 15.06,10.71 15.06,12.15 L15.06,17.89 L18.62,17.89 L18.62,11.74 C18.62,8.45 16.86,6.92 14.52,6.92 C12.6,6.92 11.75,7.99 11.28,8.73 L11.3,8.73 L11.3,7.17 L7.75,7.17 C7.79,8.17 7.75,17.89 7.75,17.89 L7.75,17.89 L7.75,17.89 Z"></path>
</svg>
<span class="visually-hidden">linkedin</span>
</a> </a>
</div> </div>
<div> <div>
<a href="https://www.slideshare.net/OpenAIRE_eu" target="_blank" <a href="https://www.slideshare.net/OpenAIRE_eu" target="_blank"
class="uk-icon-button" style="background-color: #002E3C;"> class="uk-icon-button uk-icon-button-small slideshare">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <icon name="slideshare" [flex]="true" visuallyHidden="slideshare"></icon>
<line fill="#fff" stroke="#fff" stroke-width="1.1" x1="13.4" y1="14" x2="6.3" y2="10.7"></line>
<line fill="#fff" stroke="#fff" stroke-width="1.1" x1="13.5" y1="5.5" x2="6.5" y2="8.8"></line>
<circle fill="#fff" stroke="#fff" stroke-width="1.1" cx="15.5" cy="4.6" r="2.3"></circle>
<circle fill="#fff" stroke="#fff" stroke-width="1.1" cx="15.5" cy="14.8" r="2.3"></circle>
<circle fill="#fff" stroke="#fff" stroke-width="1.1" cx="4.5" cy="9.8" r="2.3"></circle>
</svg>
<span class="visually-hidden">slideshare</span>
</a> </a>
</div> </div>
<div> <div>
<a href="https://www.youtube.com/channel/UChFYqizc-S6asNjQSoWuwjw" target="_blank" <a href="https://www.youtube.com/channel/UChFYqizc-S6asNjQSoWuwjw" target="_blank"
class="uk-icon-button" style="background-color: #FF0312;"> class="uk-icon-button uk-icon-button-small youtube">
<svg width="20" height="20" fill="#fff" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <icon name="youtube" [flex]="true" visuallyHidden="youtube"></icon>
<path
d="M15,4.1c1,0.1,2.3,0,3,0.8c0.8,0.8,0.9,2.1,0.9,3.1C19,9.2,19,10.9,19,12c-0.1,1.1,0,2.4-0.5,3.4c-0.5,1.1-1.4,1.5-2.5,1.6 c-1.2,0.1-8.6,0.1-11,0c-1.1-0.1-2.4-0.1-3.2-1c-0.7-0.8-0.7-2-0.8-3C1,11.8,1,10.1,1,8.9c0-1.1,0-2.4,0.5-3.4C2,4.5,3,4.3,4.1,4.2 C5.3,4.1,12.6,4,15,4.1z M8,7.5v6l5.5-3L8,7.5z"></path>
</svg>
<span class="visually-hidden">youtube</span>
</a> </a>
</div> </div>
<div class="uk-margin-large-left"> </div>
<a target="_blank" href="https://www.openaire.eu/newsletters"> <div class="uk-margin-large-left uk-width-auto">
<span class="uk-flex uk-flex-middle"> <a target="_blank" class="uk-flex uk-flex-middle uk-link-text" href="https://www.openaire.eu/newsletters">
<span class="uk-text-large uk-text-bold">Newsletter</span> <span class="uk-text-large uk-text-bold">Newsletter</span>
<span class="uk-icon uk-margin-small-left"> <icon name="newsletter" class="uk-margin-small-left" [flex]="true"></icon>
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<circle cx="3.12" cy="16.8" r="1.85"></circle>
<path fill="none" stroke="#000" stroke-width="3"
d="M1.5,8.2 C1.78,8.18 2.06,8.16 2.35,8.16 C7.57,8.16 11.81,12.37 11.81,17.57 C11.81,17.89 11.79,18.19 11.76,18.5"></path>
<path fill="none" stroke="#000" stroke-width="3"
d="M1.5,2.52 C1.78,2.51 2.06,2.5 2.35,2.5 C10.72,2.5 17.5,9.24 17.5,17.57 C17.5,17.89 17.49,18.19 17.47,18.5"></path>
</svg>
</span>
</span>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
<!-- </div>-->
</div> </div>
</div> </div>
</div> </div>
<div [class]="sectionClass + ' uk-section uk-section-xsmall'"> <div class="uk-section uk-section-xsmall uk-container uk-container-large uk-position-relative">
<div class="uk-container uk-container-expand"> <div class="uk-grid uk-flex-center uk-text-xsmall uk-text-emphasis" uk-grid>
<div class="uk-grid-margin uk-grid" uk-grid=""> <div class=" uk-flex uk-flex-top">
<div class="uk-width-small@m uk-first-column"> <a href="https://creativecommons.org/licenses/by/4.0/" rel="license" class="uk-link-reset">
</div> <icon name="cc" [preserveColor]="true" visuallyHidden="Creative-Commons"></icon>
<div class="uk-width-expand@m"> <icon name="by" [preserveColor]="true" visuallyHidden="Licence" class="uk-margin-xsmall-left"></icon>
<div id="footer#22" class=" uk-text-small uk-margin uk-margin-remove-bottom uk-text-center@m uk-text-center ">
<a href="http://creativecommons.org/licenses/by/4.0/" rel="license" class="license">
<svg *ngIf="darkBackground" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="24"
height="24" class=" uk-svg">
<title></title>
<g data-name="Creative Commons" id="Creative_Commons">
<circle cx="12" cy="12" r="11.5"
style="fill:none;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round"></circle>
<path d="M10.87,10a3.5,3.5,0,1,0,0,4"
style="fill:none;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round"></path>
<path d="M18.87,10a3.5,3.5,0,1,0,0,4"
style="fill:none;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round"></path>
</g>
</svg>
&nbsp;<svg *ngIf="!darkBackground" xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24">
<path id="creative-commons"
d="M9.7,14.675a1.311,1.311,0,0,1-1.15-.557,2.511,2.511,0,0,1-.391-1.477q0-2.032,1.541-2.034a1.36,1.36,0,0,1,.666.205,1.569,1.569,0,0,1,.605.718l1.541-.8A3.222,3.222,0,0,0,9.457,9.067a3.249,3.249,0,0,0-2.412.964,3.548,3.548,0,0,0-.957,2.61,3.562,3.562,0,0,0,.945,2.63,3.362,3.362,0,0,0,2.485.942,3.367,3.367,0,0,0,1.766-.481,3.408,3.408,0,0,0,1.254-1.326l-1.419-.718a1.44,1.44,0,0,1-1.416.987Zm6.634,0a1.312,1.312,0,0,1-1.15-.557,2.511,2.511,0,0,1-.391-1.477q0-2.032,1.541-2.034a1.389,1.389,0,0,1,.686.205,1.577,1.577,0,0,1,.608.718l1.519-.8a3.181,3.181,0,0,0-3.04-1.663,3.253,3.253,0,0,0-2.412.964,3.546,3.546,0,0,0-.955,2.61,3.576,3.576,0,0,0,.934,2.63,3.349,3.349,0,0,0,2.5.942,3.328,3.328,0,0,0,1.745-.481,3.54,3.54,0,0,0,1.274-1.326l-1.438-.718a1.441,1.441,0,0,1-1.416.987ZM21.156,4.12A11.61,11.61,0,0,0,12.624.64a11.436,11.436,0,0,0-8.44,3.48A11.738,11.738,0,0,0,.641,12.64,11.537,11.537,0,0,0,4.185,21.1a11.532,11.532,0,0,0,8.44,3.541,11.856,11.856,0,0,0,8.592-3.57,11.389,11.389,0,0,0,3.424-8.431,11.583,11.583,0,0,0-3.484-8.52Zm-1.5,15.391a9.631,9.631,0,0,1-7,2.94,9.479,9.479,0,0,1-6.938-2.911A9.422,9.422,0,0,1,2.8,12.64,9.57,9.57,0,0,1,5.747,5.68,9.3,9.3,0,0,1,12.655,2.8a9.4,9.4,0,0,1,6.94,2.88,9.411,9.411,0,0,1,2.884,6.96,9.157,9.157,0,0,1-2.823,6.87Z"
transform="translate(-0.641 -0.64)"/>
</svg>
{{' '}}
<svg *ngIf="darkBackground" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="24"
height="24" class=" uk-svg">
<title></title>
<g id="Attribution">
<g data-name="<Group>" id="_Group_">
<circle cx="12" cy="5" data-name="<Path>" id="_Path_" r="1.5"
style="fill:none;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round"></circle>
<path
d="M12,8a5,5,0,0,0-3.07.71,1,1,0,0,0-.43.83V15H10v5.5h4V15h1.5V9.54a1,1,0,0,0-.43-.83A5,5,0,0,0,12,8Z"
data-name="<Path>" id="_Path_2"
style="fill:none;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round"></path>
</g>
<circle cx="12" cy="12" r="11.5"
style="fill:none;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round"></circle>
</g>
</svg>
<svg *ngIf="!darkBackground" xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24">
<g id="Group_756" data-name="Group 756" transform="translate(0)">
<path id="Path_2324" data-name="Path 2324"
d="M18.325,11.98a.775.775,0,0,0-.775-.775H12.641a.775.775,0,0,0-.775.775v4.909h1.369V22.7h3.719V16.889h1.37V11.98Z"
transform="translate(-3.095 -2.951)"/>
<path id="Path_2325" data-name="Path 2325"
d="M17.209,7.759A1.679,1.679,0,1,1,15.53,6.08,1.679,1.679,0,0,1,17.209,7.759Z"
transform="translate(-3.529 -1.83)"/>
<path id="Path_2326" data-name="Path 2326"
d="M12.624.64A11.439,11.439,0,0,0,4.183,4.12,11.736,11.736,0,0,0,.639,12.64,11.537,11.537,0,0,0,4.183,21.1a11.531,11.531,0,0,0,8.441,3.54,11.851,11.851,0,0,0,8.591-3.57,11.383,11.383,0,0,0,3.424-8.43,11.582,11.582,0,0,0-3.484-8.52,11.612,11.612,0,0,0-8.53-3.48Zm.03,2.159a9.4,9.4,0,0,1,6.939,2.88,9.414,9.414,0,0,1,2.883,6.96,9.156,9.156,0,0,1-2.823,6.87,9.63,9.63,0,0,1-7,2.94,9.48,9.48,0,0,1-6.939-2.91A9.425,9.425,0,0,1,2.8,12.64,9.573,9.573,0,0,1,5.746,5.68,9.3,9.3,0,0,1,12.654,2.8Z"
transform="translate(-0.639 -0.64)"/>
</g>
</svg>
<span class="visually-hidden">license</span>
</a> </a>
&nbsp;Unless otherwise indicated, all materials created by OpenAIRE are licenced under&nbsp;<a <span class="uk-margin-small-left uk-width-expand">Unless otherwise indicated, all materials created by OpenAIRE are licenced under</span>
href="http://creativecommons.org/licenses/by/4.0/" rel="license">CC ATTRIBUTION 4.0 INTERNATIONAL <a class="uk-link-text uk-margin-medium-left" href="http://creativecommons.org/licenses/by/4.0/" rel="license"><u>CC ATTRIBUTION 4.0 INTERNATIONALLICENSE</u></a>
LICENSE</a>.
</div> </div>
</div> </div>
<div class="uk-width-small@m"> <div class="uk-position-bottom-right uk-margin-bottom uk-margin-large-right">
<div class="uk-margin uk-margin-remove-top uk-margin-remove-bottom uk-text-right@m uk-text-center"> <a href="#" class="uk-totop uk-display-block" uk-scroll>
<a href="#" uk-totop="" uk-scroll="" class="uk-totop uk-icon"> <icon name="expand_less" ratio="1.5" [flex]="true" visuallyHidden="toTop"></icon>
<span class="visually-hidden">To top</span>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="uk-hidden@m">
<div [ngClass]="background">
<div class="uk-section uk-padding-remove-bottom">
<div class="uk-container" [class.uk-container-expand]="!centered" [class.uk-container-small]="centered">
<div class="uk-grid" [class.uk-flex-center]="centered" uk-grid>
<div *ngIf="properties.footerGrantText || (divContents && divContents['footer']?.length > 0)"
class="uk-width-1-1" [attr.uk-grid]="centered?'':null" [class.uk-grid]="centered">
<div *ngIf="showOpenaire" class="uk-text-center uk-margin-bottom uk-width-1-1">
<img [src]="assetsPath + 'common/Logo_Horizontal.png'"
width="140px"
height="50px" class="el-image" alt="OpenAIRE" loading="lazy">
</div>
<div *ngIf="showCommision" class="uk-width-expand">
<div class="uk-flex uk-flex-top uk-flex-center">
<ng-container *ngTemplateOutlet="grant"></ng-container>
</div>
</div>
</div>
<div *ngIf="showSocialButtons" class="uk-margin-medium-top uk-margin-medium-bottom uk-width-1-1">
<div class="uk-flex uk-flex-middle uk-flex-center uk-flex-wrap">
<div class="uk-grid uk-grid-small uk-flex-center uk-width-1-1 uk-child-width-auto" uk-grid>
<div>
<a href="https://www.twitter.com/OpenAIRE_eu" target="_blank"
class="uk-icon-button uk-icon uk-icon-button-small twitter">
<icon name="twitter" [flex]="true" visuallyHidden="twitter"></icon>
</a>
</div>
<div>
<a href="https://www.facebook.com/groups/openaire/" target="_blank"
class="uk-icon-button uk-icon-button-small facebook">
<icon name="facebook" [flex]="true" visuallyHidden="facebook"></icon>
</a>
</div>
<div>
<a href="https://www.linkedin.com/groups/3893548/" target="_blank"
class="uk-icon-button uk-icon-button-small linkedin">
<icon name="linkedin" [flex]="true" visuallyHidden="linkedin"></icon>
</a>
</div>
<div>
<a href="https://www.slideshare.net/OpenAIRE_eu" target="_blank"
class="uk-icon-button uk-icon-button-small slideshare">
<icon name="slideshare" [flex]="true" visuallyHidden="slideshare"></icon>
</a>
</div>
<div>
<a href="https://www.youtube.com/channel/UChFYqizc-S6asNjQSoWuwjw" target="_blank"
class="uk-icon-button uk-icon-button-small youtube">
<icon name="youtube" [flex]="true" visuallyHidden="youtube"></icon>
</a>
</div>
</div>
<div class="uk-margin-medium-top uk-width-auto">
<a target="_blank" class="uk-flex uk-flex-middle uk-link-text" href="https://www.openaire.eu/newsletters">
<span class="uk-text-large uk-text-bold">Newsletter</span>
<icon name="newsletter" class="uk-margin-small-left" [flex]="true"></icon>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-section uk-section-xsmall uk-container uk-container-large uk-position-relative">
<div class="uk-grid uk-flex-center uk-text-xsmall uk-text-emphasis" uk-grid>
<div class=" uk-flex uk-flex-top">
<a href="https://creativecommons.org/licenses/by/4.0/" rel="license" class="uk-link-reset">
<icon name="cc" [preserveColor]="true" visuallyHidden="Creative-Commons"></icon>
<icon name="by" [preserveColor]="true" visuallyHidden="Licence" class="uk-margin-xsmall-left"></icon>
</a>
<span class="uk-margin-small-left uk-width-expand">Unless otherwise indicated, all materials created by OpenAIRE are licenced under</span>
</div>
<div class="uk-width-1-1 uk-text-center">
<a class="uk-link-text" href="http://creativecommons.org/licenses/by/4.0/" rel="license"><u>CC ATTRIBUTION 4.0 INTERNATIONALLICENSE</u></a>
</div>
</div>
<div class="uk-margin-top uk-flex uk-flex-center">
<a href="#" class="uk-totop" uk-scroll>
<icon name="expand_less" ratio="1.5" [flex]="true" visuallyHidden="toTop"></icon>
</a>
</div>
</div>
</div>
</div> </div>
</ng-template> </ng-template>

View File

@ -1,8 +1,8 @@
import { Component, Input } from '@angular/core'; import {Component, Input} from '@angular/core';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import 'rxjs'; import 'rxjs';
import{MenuItem} from './menu'; import {MenuItem} from './menu';
import { ConfigurationService } from '../utils/configuration/configuration.service'; import {ConfigurationService} from '../utils/configuration/configuration.service';
import {EnvProperties} from "../utils/properties/env-properties"; import {EnvProperties} from "../utils/properties/env-properties";
import {Subscription} from "rxjs"; import {Subscription} from "rxjs";
import {properties} from '../../../environments/environment'; import {properties} from '../../../environments/environment';
@ -13,46 +13,36 @@ import {HelperService} from "../utils/helper/helper.service";
templateUrl: 'bottom.component.html' templateUrl: 'bottom.component.html'
}) })
export class BottomComponent { export class BottomComponent {
@Input() showSocialButtons: boolean = true;
@Input() showOpenaire: boolean = true;
@Input() showMenuItems: boolean = false;
@Input() showCommision: boolean = true;
@Input() assetsPath: string = 'assets/common-assets/';
@Input() menuItems: MenuItem [];
@Input() communityId;
showPage = {};
@Input() grantAdvance: boolean = true;
@Input() properties: EnvProperties = properties;
@Input() centered: boolean = false;
@Input() shortView: boolean = false;
@Input() background: string = "uk-tile-default";
subs: Subscription[] = [];
public divContents = null;
@Input() showSocialButtons:boolean = true; constructor(private config: ConfigurationService, private route: ActivatedRoute,
@Input() showOpenaire:boolean = true;
@Input() showMenuItems:boolean = false;
@Input() showCommision:boolean = true;
@Input() assetsPath:string ='assets/common-assets/';
@Input() menuItems:MenuItem [];
@Input() communityId;
// @Input() environment:string = "beta";
showPage ={};
@Input() grantAdvance:boolean = true;
// grantAdvanceText = "OpenAIRE-Advance receives funding from the European Union's Horizon 2020 Research and Innovation programme under Grant Agreement No. 777541.";
// grantConenctText = "OpenAIRE-Connect receives funding from the European Union's Horizon 2020 Research and Innovation programme under grant agreement No. 731011 and No. 777541.";
@Input() properties:EnvProperties = properties;
@Input() darkBackground:boolean=true;
@Input() centered:boolean=false;
@Input() shortView: boolean = false;
sectionClass= "uk-tile-default";
subs: Subscription[] = [];
public divContents = null;
constructor(private config: ConfigurationService, private route: ActivatedRoute,
private helper: HelperService) { private helper: HelperService) {
} }
ngOnInit() { ngOnInit() {
if(!properties.footerGrantText) { if (!properties.footerGrantText) {
this.getDivContents(); this.getDivContents();
} }
if(!this.darkBackground){
this.sectionClass= " footer-light-background";
}
this.subs.push(this.route.queryParams.subscribe(params => { this.subs.push(this.route.queryParams.subscribe(params => {
if(this.showMenuItems){ if (this.showMenuItems) {
if( this.properties.adminToolsAPIURL && this.communityId ){ if (this.properties.adminToolsAPIURL && this.communityId) {
//this.subs.push(this.config.getCommunityInformation(this.properties, this.communityId ).subscribe(data => { //this.subs.push(this.config.getCommunityInformation(this.properties, this.communityId ).subscribe(data => {
this.subs.push(this.config.communityInformationState.subscribe(data => { this.subs.push(this.config.communityInformationState.subscribe(data => {
if(data) { if (data) {
for (var i = 0; i < data['pages'].length; i++) { for (var i = 0; i < data['pages'].length; i++) {
this.showPage[data['pages'][i]["route"]] = data['pages'][i]["isEnabled"]; this.showPage[data['pages'][i]["route"]] = data['pages'][i]["isEnabled"];
@ -71,14 +61,14 @@ constructor(private config: ConfigurationService, private route: ActivatedRoute
} }
} }
isEnabled(required, enabled){ isEnabled(required, enabled) {
if(!required ){ if (!required) {
return true; return true;
} }
for(let requiredEntity of required){ for (let requiredEntity of required) {
// console.log("R "+requiredEntity +" E " + enabled[requiredEntity]) // console.log("R "+requiredEntity +" E " + enabled[requiredEntity])
if(typeof enabled[requiredEntity] === "undefined" || enabled[requiredEntity] == false){ if (typeof enabled[requiredEntity] === "undefined" || enabled[requiredEntity] == false) {
return false; return false;
} }
} }
@ -87,7 +77,7 @@ constructor(private config: ConfigurationService, private route: ActivatedRoute
private getDivContents() { private getDivContents() {
let communityId = this.communityId; let communityId = this.communityId;
if(!communityId) { if (!communityId) {
communityId = properties.adminToolsCommunity; communityId = properties.adminToolsCommunity;
} }
this.subs.push(this.helper.getDivHelpContents(this.properties, communityId, "/").subscribe(contents => { this.subs.push(this.helper.getDivHelpContents(this.properties, communityId, "/").subscribe(contents => {

View File

@ -1,22 +1,25 @@
import { NgModule } from '@angular/core'; import {NgModule} from '@angular/core';
import { CommonModule } from '@angular/common'; import {CommonModule} from '@angular/common';
import { FormsModule } from '@angular/forms'; import {FormsModule} from '@angular/forms';
import { RouterModule } from "@angular/router"; import {RouterModule} from "@angular/router";
import {BottomComponent} from './bottom.component'; import {BottomComponent} from './bottom.component';
import {HelperModule} from "../utils/helper/helper.module"; import {HelperModule} from "../utils/helper/helper.module";
import {IconsModule} from "../utils/icons/icons.module";
import {IconsService} from "../utils/icons/icons.service";
import {by, cc, facebook, linkedin, newsletter, slideshare, twitter, youtube} from "../utils/icons/icons";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, FormsModule, RouterModule, HelperModule CommonModule, FormsModule, RouterModule, HelperModule, IconsModule
], ],
declarations: [ declarations: [
BottomComponent BottomComponent
], ],
exports: [BottomComponent]
exports: [
BottomComponent
]
}) })
export class BottomModule{ } export class BottomModule{
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([by, cc, twitter, facebook, linkedin, slideshare, youtube, newsletter]);
}
}

View File

@ -13,7 +13,7 @@ import {
SimpleChanges, SimpleChanges,
ViewChild ViewChild
} from "@angular/core"; } from "@angular/core";
import {AbstractControl, FormArray, FormControl, ValidatorFn} from "@angular/forms"; import {AbstractControl, UntypedFormArray, UntypedFormControl, ValidatorFn} from "@angular/forms";
import {HelperFunctions} from "../../utils/HelperFunctions.class"; import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {Subscription} from "rxjs"; import {Subscription} from "rxjs";
import {EnvProperties} from "../../utils/properties/env-properties"; import {EnvProperties} from "../../utils/properties/env-properties";
@ -60,7 +60,7 @@ declare var UIkit;
<label>{{placeholderInfo.label}} <sup *ngIf="required">*</sup></label> <label>{{placeholderInfo.label}} <sup *ngIf="required">*</sup></label>
</div> </div>
<div class="uk-flex" [class.uk-flex-middle]="type !== 'textarea'" <div class="uk-flex" [class.uk-flex-middle]="type !== 'textarea'"
[attr.uk-tooltip]="(tooltip && !focused && type !== 'chips' && type !== 'textarea')?('title: ' + getTooltip(formControl.value ? (formControl.value) : (placeholderInfo?.static?placeholderInfo.label:hint)) + '; delay: 500; pos: bottom-left'):null"> [attr.uk-tooltip]="(tooltip && !focused && type !== 'chips' && type !== 'textarea' && (formControl.value || hint || placeholderInfo?.label))?('title: ' + (formControl.value ?getTooltip(formControl.value):(hint?hint:placeholderInfo?.label)) + '; delay: 500; pos: bottom-left'):null">
<ng-template [ngIf]="type === 'text' || type === 'URL' || type === 'logoURL'"> <ng-template [ngIf]="type === 'text' || type === 'URL' || type === 'logoURL'">
<input #input class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint" <input #input class="input" [attr.placeholder]="placeholderInfo?.static?placeholderInfo.label:hint"
[formControl]="formAsControl" [class.uk-text-truncate]="!focused"> [formControl]="formAsControl" [class.uk-text-truncate]="!focused">
@ -217,7 +217,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
@Input() noValueSelected: string = 'No option selected'; @Input() noValueSelected: string = 'No option selected';
/** Chips && Autocomplete*/ /** Chips && Autocomplete*/
public filteredOptions: Option[] = []; public filteredOptions: Option[] = [];
public searchControl: FormControl; public searchControl: UntypedFormControl;
/** Use modifier's class(es) to change view of your Input */ /** Use modifier's class(es) to change view of your Input */
@Input() inputClass: string = 'inner'; @Input() inputClass: string = 'inner';
/** Icon on the input */ /** Icon on the input */
@ -332,12 +332,12 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.id = 'input-' + InputComponent.INPUT_COUNTER; this.id = 'input-' + InputComponent.INPUT_COUNTER;
if (!this.formControl) { if (!this.formControl) {
if (Array.isArray(this.value)) { if (Array.isArray(this.value)) {
this.formControl = new FormArray([]); this.formControl = new UntypedFormArray([]);
this.value.forEach(value => { this.value.forEach(value => {
this.formAsArray.push(new FormControl(value, this.validators)); this.formAsArray.push(new UntypedFormControl(value, this.validators));
}); });
} else { } else {
this.formControl = new FormControl(this.value); this.formControl = new UntypedFormControl(this.value);
this.formControl.setValidators(this.validators); this.formControl.setValidators(this.validators);
} }
if (this.disabled) { if (this.disabled) {
@ -372,16 +372,16 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.unsubscribe(); this.unsubscribe();
} }
get formAsControl(): FormControl { get formAsControl(): UntypedFormControl {
if (this.formControl instanceof FormControl) { if (this.formControl instanceof UntypedFormControl) {
return this.formControl; return this.formControl;
} else { } else {
return null; return null;
} }
} }
get formAsArray(): FormArray { get formAsArray(): UntypedFormArray {
if (this.formControl instanceof FormArray) { if (this.formControl instanceof UntypedFormArray) {
return this.formControl; return this.formControl;
} else { } else {
return null; return null;
@ -401,7 +401,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
} }
if (this.type === 'chips' || this.type === 'autocomplete') { if (this.type === 'chips' || this.type === 'autocomplete') {
if (!this.searchControl) { if (!this.searchControl) {
this.searchControl = new FormControl('', this.validators); this.searchControl = new UntypedFormControl('', this.validators);
} }
this.subscriptions.push(this.searchControl.valueChanges.subscribe(value => { this.subscriptions.push(this.searchControl.valueChanges.subscribe(value => {
this.filteredOptions = this.filter(value); this.filteredOptions = this.filter(value);
@ -488,7 +488,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
if (event && event.stopPropagation) { if (event && event.stopPropagation) {
event.stopPropagation(); event.stopPropagation();
} }
this.formAsArray.push(new FormControl(this.searchControl.value, this.validators)); this.formAsArray.push(new UntypedFormControl(this.searchControl.value, this.validators));
this.formAsArray.markAsDirty(); this.formAsArray.markAsDirty();
} }
this.searchControl.setValue(''); this.searchControl.setValue('');
@ -573,7 +573,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
if (this.formAsControl) { if (this.formAsControl) {
this.formAsControl.setValue(option.value); this.formAsControl.setValue(option.value);
} else if (this.formAsArray) { } else if (this.formAsArray) {
this.formAsArray.push(new FormControl(option.value)); this.formAsArray.push(new UntypedFormControl(option.value));
this.formAsArray.markAsDirty(); this.formAsArray.markAsDirty();
event.stopPropagation(); event.stopPropagation();
this.focus(true); this.focus(true);

View File

@ -76,6 +76,7 @@ export class Menu {
portalPid: string; portalPid: string;
isFeaturedMenuEnabled: boolean; isFeaturedMenuEnabled: boolean;
isMenuEnabled: boolean; isMenuEnabled: boolean;
featuredAlignment: MenuAlignment;
featuredMenuItems: MenuItemExtended[] = []; featuredMenuItems: MenuItemExtended[] = [];
menuItems: MenuItemExtended[] = []; menuItems: MenuItemExtended[] = [];
} }
@ -83,3 +84,5 @@ export class Menu {
export class SideMenuItem extends MenuItem { export class SideMenuItem extends MenuItem {
ukIcon: string = ''; ukIcon: string = '';
} }
export enum MenuAlignment {LEFT="LEFT", CENTER="CENTER", RIGHT="RIGHT"}

View File

@ -1,5 +1,5 @@
<div *ngIf="showMenu && activeHeader"> <div *ngIf="showMenu && activeHeader">
<div class="uk-hidden@l"> <div id="main-menu-small" class="uk-hidden@m">
<nav class="uk-navbar-container uk-navbar" uk-navbar="delay-hide: 400"> <nav class="uk-navbar-container uk-navbar" uk-navbar="delay-hide: 400">
<div <div
*ngIf="(properties.environment =='beta' || properties.environment =='development') && showLogo && activeHeader.badge"> *ngIf="(properties.environment =='beta' || properties.environment =='development') && showLogo && activeHeader.badge">
@ -7,8 +7,8 @@
[src]="'assets/common-assets/'+(properties.environment =='beta'?'beta_flag.svg':'prototype_flag.svg')" [src]="'assets/common-assets/'+(properties.environment =='beta'?'beta_flag.svg':'prototype_flag.svg')"
alt="BETA" style="height: 60px; width: 60px;"> alt="BETA" style="height: 60px; width: 60px;">
</div> </div>
<div *ngIf="!onlyTop || userMenu" class="uk-navbar-left"> <div *ngIf="!onlyTop || userMenu" class="uk-navbar-left" [class.uk-light]='activeHeader.darkBg'>
<a *ngIf="!offCanvasFlip" class="uk-navbar-toggle" href="#tm-mobile" uk-toggle="" style="z-index:1000;"> <a class="uk-navbar-toggle" href="#tm-mobile" uk-toggle>
<div uk-navbar-toggle-icon="" class="uk-navbar-toggle-icon uk-icon custom-navbar-toggle-icon"></div> <div uk-navbar-toggle-icon="" class="uk-navbar-toggle-icon uk-icon custom-navbar-toggle-icon"></div>
<span class="visually-hidden">toggle menu</span> <span class="visually-hidden">toggle menu</span>
</a> </a>
@ -16,42 +16,43 @@
<div class="uk-navbar-center"> <div class="uk-navbar-center">
<ng-container *ngTemplateOutlet="header_template; context: {mobile: true}"></ng-container> <ng-container *ngTemplateOutlet="header_template; context: {mobile: true}"></ng-container>
</div> </div>
<div *ngIf="!onlyTop || userMenu" class="uk-navbar-right"> <div *ngIf="!onlyTop || userMenu" class="uk-navbar-right" [class.uk-light]='activeHeader.darkBg'>
<a *ngIf="offCanvasFlip" class="uk-navbar-toggle" href="#tm-mobile" uk-toggle=""> <ng-container *ngIf="userMenu">
<div uk-navbar-toggle-icon="" class="uk-navbar-toggle-icon uk-icon custom-navbar-toggle-icon"></div> <user-mini [user]="user" mobileView=true (closeCanvasEmitter)="closeCanvas(canvas)"
</a> [userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl
[logOutUrl]=properties.logoutUrl [cookieDomain]=properties.cookieDomain></user-mini>
</ng-container>
</div> </div>
</nav> </nav>
<div #canvas id="tm-mobile" [attr.uk-offcanvas]="(offCanvasFlip?'flip:'+(offCanvasFlip + ';'):'') + 'overlay: true'" <div #canvas id="tm-mobile" [attr.uk-offcanvas]="'overlay: true'"
class="uk-offcanvas"> class="uk-offcanvas">
<div class="uk-offcanvas-bar"> <div class="uk-offcanvas-bar uk-padding-remove-horizontal">
<a class="uk-offcanvas-close uk-icon uk-close"> <button class="uk-offcanvas-close uk-icon uk-close">
<icon name="close" ratio="1.5" visuallyHidden="close menu"></icon> <icon name="close" ratio="1.5" visuallyHidden="close menu"></icon>
</a> </button>
<div class="uk-padding"> <ul class="uk-nav uk-nav-primary uk-list uk-list-large uk-margin-top uk-nav-parent-icon" uk-nav>
<ul class="uk-nav uk-nav-default">
<ng-container *ngIf="!onlyTop"> <ng-container *ngIf="!onlyTop">
<ng-container *ngFor="let menu of menuItems">
<li *ngIf="showHomeMenuItem && currentRoute.route !== '/'"> <li *ngIf="showHomeMenuItem && currentRoute.route !== '/'">
<a routerLink="/" (click)="closeCanvas(canvas)">Home</a> <a routerLink="/" (click)="closeCanvas(canvas)">Home</a>
</li> </li>
<li [class.uk-active]="isTheActiveMenu(menu)" <ng-container *ngFor="let menu of menuItems">
<li [class.uk-active]="isTheActiveMenu(menu)" [class.uk-parent]="menu.items.length > 0" [ngClass]="menu.customClass"
*ngIf="isAtleastOneEnabled(menu.entitiesRequired,showEntity) && isAtleastOneEnabled(menu.routeRequired, showPage)"> *ngIf="isAtleastOneEnabled(menu.entitiesRequired,showEntity) && isAtleastOneEnabled(menu.routeRequired, showPage)">
<!--a routerLink="{{menu.rootItem.route}}" [queryParams]=menu.rootItem.params class="uk-offcanvas-close custom-offcanvas-close">{{menu.rootItem.title}}</a--> <!--a routerLink="{{menu.rootItem.route}}" [queryParams]=menu.rootItem.params class="uk-offcanvas-close custom-offcanvas-close">{{menu.rootItem.title}}</a-->
<a *ngIf="menu.route.length > 0 && (isEnabled([menu.route], showPage) || !menu.routeRequired)" <a *ngIf="menu.route && (isEnabled([menu.route], showPage) || !menu.routeRequired)"
routerLink="{{menu.route}}" (click)="closeCanvas(canvas)" routerLink="{{menu.route}}" (click)="menu.items.length === 0?closeCanvas(canvas):null"
[queryParams]="menu.params" [queryParams]="menu.params"
[fragment]="menu.fragment">{{menu.title}}</a> [fragment]="menu.fragment">{{menu.title}}</a>
<a *ngIf="menu.route.length == 0 && menu.url.length > 0" <a *ngIf="!menu.route && menu.url"
href="{{menu.url}}" (click)="closeCanvas(canvas)" [class.custom-external]="menu.target != '_self'" href="{{menu.url}}" (click)="menu.items.length === 0?closeCanvas(canvas):null" [class.custom-external]="menu.target != '_self'"
target="{{menu.target}}">{{menu.title}}</a> target="{{menu.target}}">{{menu.title}}</a>
<a *ngIf="(menu.route.length == 0 && menu.url.length == 0) || <a *ngIf="(!menu.route && !menu.url) ||
(menu.route.length >0 && menu.routeRequired && !isEnabled([menu.route], showPage) (menu.route && menu.routeRequired && !isEnabled([menu.route], showPage)
&& isAtleastOneEnabled(menu.routeRequired, showPage))" && isAtleastOneEnabled(menu.routeRequired, showPage))"
(click)="closeCanvas(canvas)">{{menu.title}}</a> (click)="menu.items.length === 0?closeCanvas(canvas):null">{{menu.title}}</a>
<ul class="uk-nav-sub"> <ul *ngIf="menu.items.length > 0" class="uk-nav-sub">
<ng-container *ngFor="let submenu of menu.items"> <ng-container *ngFor="let submenu of menu.items">
<li [class.uk-active]="isTheActiveMenu(submenu)" <li [class.uk-active]="isTheActiveMenu(submenu)" [ngClass]="submenu.customClass"
*ngIf="isEnabled(submenu.entitiesRequired,showEntity) && isEnabled(submenu.routeRequired, showPage) && (submenu.route.length > 0 || submenu.url.length > 0)" *ngIf="isEnabled(submenu.entitiesRequired,showEntity) && isEnabled(submenu.routeRequired, showPage) && (submenu.route.length > 0 || submenu.url.length > 0)"
[class.uk-parent]="submenu.items && submenu.items.length > 0"> [class.uk-parent]="submenu.items && submenu.items.length > 0">
<a *ngIf="submenu.route.length > 0" (click)="closeCanvas(canvas)" <a *ngIf="submenu.route.length > 0" (click)="closeCanvas(canvas)"
@ -62,7 +63,7 @@
target="{{submenu.target}}">{{submenu.title}}</a> target="{{submenu.target}}">{{submenu.title}}</a>
<ul *ngIf="submenu.items && submenu.items.length > 0" class="uk-nav-sub"> <ul *ngIf="submenu.items && submenu.items.length > 0" class="uk-nav-sub">
<ng-container *ngFor="let subsubmenu of submenu.items"> <ng-container *ngFor="let subsubmenu of submenu.items">
<li [class.uk-active]="isTheActiveMenu(subsubmenu)"> <li [class.uk-active]="isTheActiveMenu(subsubmenu)" [ngClass]="subsubmenu.customClass">
<a *ngIf="subsubmenu.route.length > 0" <a *ngIf="subsubmenu.route.length > 0"
routerLink="{{subsubmenu.route}}" [queryParams]="subsubmenu.params" routerLink="{{subsubmenu.route}}" [queryParams]="subsubmenu.params"
[fragment]="subsubmenu.fragment" (click)="closeCanvas(canvas)">{{subsubmenu.title}}</a> [fragment]="subsubmenu.fragment" (click)="closeCanvas(canvas)">{{subsubmenu.title}}</a>
@ -77,21 +78,75 @@
class="uk-nav-header">{{submenu.title}}</li> class="uk-nav-header">{{submenu.title}}</li>
</ng-container> </ng-container>
</ul> </ul>
<ul *ngIf="menu.route === '/' && isFeaturedMenuEnabled && featuredMenuItems?.length > 0" class="uk-nav-sub">
<li [class.uk-active]="isTheActiveMenu(item)" *ngFor="let item of featuredMenuItems" [ngClass]="item.customClass">
<a *ngIf="item.type == 'internal' && item.route && isEnabled([item.route], showPage)"
routerLink="{{item.route}}"
[queryParams]="item.params"
[fragment]="item.fragment"
(click)="closeCanvas(canvas)">
{{item.title}}
</a>
<a *ngIf="item.type == 'external' && item.url"
href="{{item.url}}" class="custom-external"
target="_blank"
(click)="closeCanvas(canvas)">
{{item.title}}
</a>
</li>
</ul>
</li>
</ng-container>
<ng-container *ngIf="isMenuEnabled && additionalMenuItems?.length > 0">
<ng-container *ngFor="let menu of additionalMenuItems">
<li [class.uk-active]="isTheActiveMenu(menu)" [class.uk-parent]="menu.items.length > 0" [ngClass]="menu.customClass">
<a *ngIf="menu.type == 'internal' && menu.route && isEnabled([menu.route], showPage)"
routerLink="{{menu.route}}"
[queryParams]="menu.params"
[fragment]="menu.fragment"
(click)="menu.items.length === 0?closeCanvas(canvas):null">
{{menu.title}}
</a>
<a *ngIf="menu.type == 'external' && menu.url"
href="{{menu.url}}"
target="_blank" class="custom-external"
(click)="menu.items.length === 0?closeCanvas(canvas):null">
{{menu.title}}
</a>
<a *ngIf="menu.type == 'noAction'">
{{menu.title}}
</a>
<ul class="uk-nav-sub">
<ng-container *ngIf="menu.items?.length">
<ng-container *ngFor="let submenu of menu.items">
<li [class.uk-active]="isTheActiveMenu(submenu)" [ngClass]="submenu.customClass">
<a *ngIf="submenu.type == 'internal' && submenu.route && isEnabled([submenu.route], showPage)"
routerLink="{{submenu.route}}"
[queryParams]="submenu.params"
[fragment]="submenu.fragment"
(click)="menu.items.length === 0?closeCanvas(canvas):null">
{{submenu.title}}
</a>
<a *ngIf="submenu.type == 'external' && submenu.url"
href="{{submenu.url}}"
target="_blank" class="custom-external"
(click)="menu.items.length === 0?closeCanvas(canvas):null">
{{submenu.title}}
</a>
</li> </li>
</ng-container> </ng-container>
</ng-container> </ng-container>
</ul> </ul>
<ng-container *ngIf="userMenu"> </li>
<user-mini [user]="user" mobileView=true (closeCanvasEmitter)="closeCanvas(canvas)" </ng-container>
[userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl </ng-container>
[logOutUrl]=properties.logoutUrl [cookieDomain]=properties.cookieDomain></user-mini>
<ng-content select="[extra-s]"></ng-content> <ng-content select="[extra-s]"></ng-content>
</ng-container> </ng-container>
</ul>
</div> </div>
</div> </div>
</div> </div>
</div> <div id="main-menu" class="uk-visible@m">
<div id="main-menu" class="uk-visible@l">
<div *ngIf="activeHeader" [class.uk-light]='activeHeader.darkBg'> <div *ngIf="activeHeader" [class.uk-light]='activeHeader.darkBg'>
<div class="uk-navbar-container" uk-sticky="media@m"> <div class="uk-navbar-container" uk-sticky="media@m">
<div *ngIf="(properties.environment =='beta' || properties.environment =='development') && showLogo && activeHeader.badge"> <div *ngIf="(properties.environment =='beta' || properties.environment =='development') && showLogo && activeHeader.badge">
@ -122,15 +177,17 @@
<user-mini *ngIf="userMenu" [user]="user" <user-mini *ngIf="userMenu" [user]="user"
[userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl [logOutUrl]=properties.logoutUrl [userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl [logOutUrl]=properties.logoutUrl
[cookieDomain]=properties.cookieDomain></user-mini> [cookieDomain]=properties.cookieDomain></user-mini>
<div class="uk-visible@l">
<ng-content select="[extra-m]"></ng-content> <ng-content select="[extra-m]"></ng-content>
</div> </div>
</div>
<ng-template #mainMenu> <ng-template #mainMenu>
<ul class="uk-navbar-nav" [class.uk-margin-right]="!userMenu"> <ul class="uk-navbar-nav" [class.uk-margin-right]="!userMenu">
<li class="uk-parent" *ngIf="showHomeMenuItem && currentRoute.route !== '/'"> <li class="uk-parent" *ngIf="showHomeMenuItem && currentRoute.route !== '/'">
<a routerLink="/">Home</a> <a routerLink="/">Home</a>
</li> </li>
<ng-container *ngFor="let menu of menuItems"> <ng-container *ngFor="let menu of menuItems">
<li class="uk-parent" [class.uk-active]="isTheActiveMenu(menu)" <li class="uk-parent" [class.uk-active]="isTheActiveMenu(menu)" [ngClass]="menu.customClass"
*ngIf="isAtleastOneEnabled(menu.entitiesRequired,showEntity) && isAtleastOneEnabled(menu.routeRequired, showPage)"> *ngIf="isAtleastOneEnabled(menu.entitiesRequired,showEntity) && isAtleastOneEnabled(menu.routeRequired, showPage)">
<!--a routerLink="{{menu.rootItem.route}}" [queryParams]=menu.rootItem.params class="" aria-expanded="false">{{menu.rootItem.title}}</a--> <!--a routerLink="{{menu.rootItem.route}}" [queryParams]=menu.rootItem.params class="" aria-expanded="false">{{menu.rootItem.title}}</a-->
<a *ngIf="menu.route.length > 0 && (isEnabled([menu.route], showPage) || !menu.routeRequired )" <a *ngIf="menu.route.length > 0 && (isEnabled([menu.route], showPage) || !menu.routeRequired )"
@ -149,7 +206,7 @@
<li *ngIf="isEnabled(submenu.entitiesRequired,showEntity) && <li *ngIf="isEnabled(submenu.entitiesRequired,showEntity) &&
isEnabled(submenu.routeRequired, showPage) && (submenu.route.length > 0 || isEnabled(submenu.routeRequired, showPage) && (submenu.route.length > 0 ||
submenu.url.length > 0)" [class.uk-active]="isTheActiveMenu(submenu)" submenu.url.length > 0)" [class.uk-active]="isTheActiveMenu(submenu)"
[class.uk-parent]="submenu.items && submenu.items.length > 0"> [class.uk-parent]="submenu.items && submenu.items.length > 0" [ngClass]="submenu.customClass">
<a *ngIf="submenu.route.length > 0" <a *ngIf="submenu.route.length > 0"
routerLink="{{submenu.route}}" [queryParams]="submenu.params" routerLink="{{submenu.route}}" [queryParams]="submenu.params"
[fragment]="submenu.fragment">{{submenu.title}}</a> [fragment]="submenu.fragment">{{submenu.title}}</a>
@ -158,7 +215,7 @@
target="{{submenu.target}}">{{submenu.title}}</a> target="{{submenu.target}}">{{submenu.title}}</a>
<ul *ngIf="submenu.items && submenu.items.length > 0" class="uk-nav-sub"> <ul *ngIf="submenu.items && submenu.items.length > 0" class="uk-nav-sub">
<ng-container *ngFor="let subsubmenu of submenu.items"> <ng-container *ngFor="let subsubmenu of submenu.items">
<li [class.uk-active]="isTheActiveMenu(subsubmenu)"> <li [class.uk-active]="isTheActiveMenu(subsubmenu)" [ngClass]="subsubmenu.customClass">
<a *ngIf="subsubmenu.route.length > 0" <a *ngIf="subsubmenu.route.length > 0"
routerLink="{{subsubmenu.route}}" [queryParams]="subsubmenu.params" routerLink="{{subsubmenu.route}}" [queryParams]="subsubmenu.params"
[fragment]="subsubmenu.fragment">{{subsubmenu.title}}</a> [fragment]="subsubmenu.fragment">{{subsubmenu.title}}</a>
@ -176,25 +233,20 @@
</div> </div>
</li> </li>
</ng-container> </ng-container>
<!-- Custom menu items -->
<!-- TODO: Add to mobile menu as well! -->
<ng-container *ngIf="isMenuEnabled && additionalMenuItems?.length > 0"> <ng-container *ngIf="isMenuEnabled && additionalMenuItems?.length > 0">
<ng-container *ngFor="let menu of additionalMenuItems"> <ng-container *ngFor="let menu of additionalMenuItems">
<li class="uk-parent" [class.uk-active]="isTheActiveMenu(menu)"> <li class="uk-parent" [class.uk-active]="isTheActiveMenu(menu)" [ngClass]="menu.customClass">
<!-- INTERNAL ROOT-->
<a *ngIf="menu.type == 'internal' && menu.route && isEnabled([menu.route], showPage)" <a *ngIf="menu.type == 'internal' && menu.route && isEnabled([menu.route], showPage)"
routerLink="{{menu.route}}" routerLink="{{menu.route}}"
[queryParams]="menu.params" [queryParams]="menu.params"
[fragment]="menu.fragment"> [fragment]="menu.fragment">
{{menu.title}} {{menu.title}}
</a> </a>
<!-- EXTERNAL ROOT-->
<a *ngIf="menu.type == 'external' && menu.url" <a *ngIf="menu.type == 'external' && menu.url"
href="{{menu.url}}" href="{{menu.url}}"
target="_blank" class="custom-external"> target="_blank" class="custom-external">
{{menu.title}} {{menu.title}}
</a> </a>
<!-- NO ACTION ROOT-->
<a *ngIf="menu.type == 'noAction'"> <a *ngIf="menu.type == 'noAction'">
{{menu.title}} {{menu.title}}
</a> </a>
@ -204,15 +256,13 @@
<div class="uk-first-column uk-height-max-medium uk-overflow-auto"> <div class="uk-first-column uk-height-max-medium uk-overflow-auto">
<ul class="uk-nav uk-navbar-dropdown-nav"> <ul class="uk-nav uk-navbar-dropdown-nav">
<ng-container *ngFor="let submenu of menu.items"> <ng-container *ngFor="let submenu of menu.items">
<li [class.uk-active]="isTheActiveMenu(submenu)"> <li [class.uk-active]="isTheActiveMenu(submenu)" [ngClass]="submenu.customClass">
<!-- INTERNAL CHILD -->
<a *ngIf="submenu.type == 'internal' && submenu.route && isEnabled([submenu.route], showPage)" <a *ngIf="submenu.type == 'internal' && submenu.route && isEnabled([submenu.route], showPage)"
routerLink="{{submenu.route}}" routerLink="{{submenu.route}}"
[queryParams]="submenu.params" [queryParams]="submenu.params"
[fragment]="submenu.fragment"> [fragment]="submenu.fragment">
{{submenu.title}} {{submenu.title}}
</a> </a>
<!-- EXTERNAL CHILD -->
<a *ngIf="submenu.type == 'external' && submenu.url" <a *ngIf="submenu.type == 'external' && submenu.url"
href="{{submenu.url}}" href="{{submenu.url}}"
target="_blank" class="custom-external"> target="_blank" class="custom-external">
@ -239,10 +289,10 @@
<div class="uk-background-primary uk-light"> <div class="uk-background-primary uk-light">
<div class="uk-container uk-container-expand"> <div class="uk-container uk-container-expand">
<div class="uk-navbar" uk-navbar="delay-hide: 400"> <div class="uk-navbar" uk-navbar="delay-hide: 400">
<div class="uk-navbar-right"> <div [ngClass]="'uk-navbar-'+featuredAlignment.toLowerCase()">
<ul class="uk-navbar-nav"> <ul class="uk-navbar-nav">
<ng-container *ngFor="let item of featuredMenuItems"> <ng-container *ngFor="let item of featuredMenuItems">
<li [class.uk-active]="isTheActiveMenu(item)"> <li [class.uk-active]="isTheActiveMenu(item)" [ngClass]="item.customClass">
<a *ngIf="item.type == 'internal' && item.route && isEnabled([item.route], showPage)" <a *ngIf="item.type == 'internal' && item.route && isEnabled([item.route], showPage)"
routerLink="{{item.route}}" routerLink="{{item.route}}"
[queryParams]="item.params" [queryParams]="item.params"

View File

@ -1,8 +1,8 @@
import {Component, Input, OnDestroy, OnInit} from '@angular/core'; import {ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {Session, User} from '../login/utils/helper.class'; import {Session, User} from '../login/utils/helper.class';
import {ConfigurationService} from '../utils/configuration/configuration.service'; import {ConfigurationService} from '../utils/configuration/configuration.service';
import {MenuItem} from './menu'; import {MenuAlignment, MenuItem} from './menu';
import {EnvProperties} from '../utils/properties/env-properties'; import {EnvProperties} from '../utils/properties/env-properties';
import {Subscription} from 'rxjs'; import {Subscription} from 'rxjs';
import {HelpContentService} from '../services/help-content.service'; import {HelpContentService} from '../services/help-content.service';
@ -29,7 +29,7 @@ export interface Header {
selector: 'navbar', selector: 'navbar',
templateUrl: 'navigationBar.component.html' templateUrl: 'navigationBar.component.html'
}) })
export class NavigationBarComponent implements OnInit, OnDestroy { export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
@Input() portal: string = 'connect'; @Input() portal: string = 'connect';
@Input() onlyTop: boolean = false; @Input() onlyTop: boolean = false;
@Input() logoPath: string = 'assets/common-assets/'; @Input() logoPath: string = 'assets/common-assets/';
@ -48,7 +48,6 @@ export class NavigationBarComponent implements OnInit, OnDestroy {
@Input() searchRoute: string = '/search/find'; @Input() searchRoute: string = '/search/find';
@Input() searchPlaceHolder: string = 'Search for research results'; @Input() searchPlaceHolder: string = 'Search for research results';
@Input() showLogo: boolean = true; @Input() showLogo: boolean = true;
@Input() offCanvasFlip: boolean = false;
replaceHeader: boolean = false; replaceHeader: boolean = false;
public activeHeader: Header; public activeHeader: Header;
keyword: string = ''; keyword: string = '';
@ -61,6 +60,7 @@ export class NavigationBarComponent implements OnInit, OnDestroy {
public featuredMenuItems: MenuItem[] = []; public featuredMenuItems: MenuItem[] = [];
public isMenuEnabled: boolean = false; public isMenuEnabled: boolean = false;
public isFeaturedMenuEnabled: boolean = false; public isFeaturedMenuEnabled: boolean = false;
public featuredAlignment: string = MenuAlignment.CENTER.valueOf();
constructor(private router: Router, constructor(private router: Router,
private route: ActivatedRoute, private route: ActivatedRoute,
@ -78,6 +78,12 @@ export class NavigationBarComponent implements OnInit, OnDestroy {
} }
} }
ngOnChanges(changes: SimpleChanges) {
if(changes.header) {
this.setHeader(this.layoutService.replaceHeaderValue);
}
}
closeCanvas(element) { closeCanvas(element) {
UIkit.offcanvas(element).hide(); UIkit.offcanvas(element).hide();
} }
@ -126,6 +132,7 @@ export class NavigationBarComponent implements OnInit, OnDestroy {
data => { data => {
this.isMenuEnabled = data.isMenuEnabled; this.isMenuEnabled = data.isMenuEnabled;
this.isFeaturedMenuEnabled = data.isFeaturedMenuEnabled; this.isFeaturedMenuEnabled = data.isFeaturedMenuEnabled;
this.featuredAlignment = data.featuredAlignment;
this.featuredMenuItems = data.featuredMenuItems; this.featuredMenuItems = data.featuredMenuItems;
this.additionalMenuItems = data.menuItems; this.additionalMenuItems = data.menuItems;
}, },
@ -134,9 +141,13 @@ export class NavigationBarComponent implements OnInit, OnDestroy {
); );
} }
this.subs.push(this.layoutService.replaceHeader.subscribe(replaceHeader => { this.subs.push(this.layoutService.replaceHeader.subscribe(replaceHeader => {
this.setHeader(replaceHeader);
}));
}
setHeader(replaceHeader: boolean) {
this.replaceHeader = this.header.replaceHeader && replaceHeader; this.replaceHeader = this.header.replaceHeader && replaceHeader;
this.activeHeader = this.replaceHeader?this.header.replaceHeader:this.header; this.activeHeader = this.replaceHeader?this.header.replaceHeader:this.header;
}));
} }
isEnabled(required, enabled) { isEnabled(required, enabled) {

View File

@ -7,8 +7,8 @@ import {properties} from '../../../../environments/environment';
import {NumberSize, NumberUtils} from '../../utils/number-utils.class'; import {NumberSize, NumberUtils} from '../../utils/number-utils.class';
import {BehaviorSubject, Observable, Subscription, zip} from 'rxjs'; import {BehaviorSubject, Observable, Subscription, zip} from 'rxjs';
import {RouterHelper} from "../../utils/routerHelper.class"; import {RouterHelper} from "../../utils/routerHelper.class";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {OpenaireEntities} from "../../utils/properties/searchFields"; import {OpenaireEntities} from "../../utils/properties/searchFields";
import {SearchOrganizationsService} from '../../services/searchOrganizations.service';
export interface Numbers { export interface Numbers {
publicationsSize?: NumberSize; publicationsSize?: NumberSize;
@ -23,152 +23,57 @@ export interface Numbers {
organizationsSize?: NumberSize; organizationsSize?: NumberSize;
} }
type Entity = 'publication' | 'dataset' | 'software' | 'other' | 'project' | 'datasource' | 'organization';
interface Link {
link: string,
params?: any
}
@Component({ @Component({
selector: 'numbers', selector: 'numbers',
template: ` template: `
<div *ngIf="!loading && numbers"> <div *ngIf="showContentWithNumbers" class="uk-margin-top" style="max-width: 600px;" uk-scrollspy-class>
<div class="uk-container uk-section uk-padding-remove-bottom uk-text-center"> <div>
<div class="uk-grid uk-grid-large uk-child-width-1-3@m" uk-grid> A comprehensive and open dataset of research information covering
<div *ngIf="numbers.fundersSize"> <span *ngIf="hasPublications" class="uk-text-bold">{{numbers.publicationsSize.number|number}}<span class="uk-text-lowercase">{{numbers.publicationsSize.size}}</span> {{openaireEntities.PUBLICATIONS.toLowerCase()}}</span>
<h3 *ngIf="links.get('project')"> <ng-container *ngIf="(hasPublications && (hasDatasets || hasSoftware || (hasDatasources || hasProjects || hasOrganizations)))">, </ng-container>
<a *ngIf="externalLink" [href]="links.get('project').link" target="_blank" class="uk-text-bold number uk-link-text uk-button-link"> <span *ngIf="hasDatasets" class="uk-text-bold">{{numbers.datasetsSize.number|number}}<span class="uk-text-lowercase">{{numbers.datasetsSize.size}}</span> {{openaireEntities.DATASETS.toLowerCase()}}</span>
{{numbers.fundersSize.number|number}}<span class="number-size">{{numbers.fundersSize.size}}</span> <ng-container *ngIf="(hasDatasets && (hasSoftware || (hasDatasources || hasProjects || hasOrganizations)))">, </ng-container>
</a> <span *ngIf="hasSoftware" class="uk-text-bold">{{numbers.softwareSize.number|number}}<span class="uk-text-lowercase">{{numbers.softwareSize.size}}</span> {{openaireEntities.SOFTWARE.toLowerCase()}} items</span>
<a *ngIf="!externalLink" [routerLink]="links.get('project').link" <ng-container *ngIf="(hasSoftware && (hasDatasources || hasProjects || hasOrganizations))">, </ng-container>
[queryParams]="links.get('project').params" class="uk-text-bold number uk-link-text uk-button-link"> <ng-container *ngIf="((hasPublications || hasDatasets || hasSoftware) && (hasDatasources))"> from </ng-container>
{{numbers.fundersSize.number|number}}<span class="number-size">{{numbers.fundersSize.size}}</span> <span *ngIf="hasDatasources" class="uk-text-bold">{{numbers.datasourcesSize.number|number}}<span class="uk-text-lowercase">{{numbers.datasourcesSize.size}}</span> {{openaireEntities.DATASOURCES.toLowerCase()}}</span>
</a> <ng-container *ngIf="(hasDatasources) && ((hasProjects) || hasOrganizations)">, linked to </ng-container>
</h3> <span *ngIf="hasProjects" class="uk-text-bold">{{numbers.projectsSize.number|number}}<span class="uk-text-lowercase">{{numbers.projectsSize.size}}</span> grants</span>
<span class="uk-text-uppercase uk-text-large">Funders</span> <ng-container *ngIf="hasProjects && hasOrganizations"> and </ng-container>
<span *ngIf="hasOrganizations" class="uk-text-bold">{{numbers.organizationsSize.number|number}}<span class="uk-text-lowercase">{{numbers.organizationsSize.size}}</span> {{openaireEntities.ORGANIZATIONS.toLowerCase()}}</span>.
</div> </div>
<div *ngIf="numbers.datasourcesSize"> <div class="uk-text-primary">All linked together through citations and semantics.</div>
<h3>
<a *ngIf="externalLink" [href]="links.get('datasource').link" target="_blank" class="uk-text-bold number uk-link-text uk-button-link">
{{numbers.datasourcesSize.number|number}}<span
class="number-size">{{numbers.datasourcesSize.size}}</span>
</a>
<a *ngIf="!externalLink" [routerLink]="links.get('datasource').link"
[queryParams]="links.get('datasource').params" class="uk-text-bold number uk-link-text uk-button-link">
{{numbers.datasourcesSize.number|number}}<span
class="number-size">{{numbers.datasourcesSize.size}}</span>
</a>
</h3>
<span class="uk-text-uppercase uk-text-large">{{openaireEntities.DATASOURCES}}</span>
</div>
<div *ngIf="numbers.projectsSize">
<h3>
<a *ngIf="externalLink" [href]="links.get('project').link" target="_blank" class="uk-text-bold number uk-link-text uk-button-link">
{{numbers.projectsSize.number|number}}<span class="number-size">{{numbers.projectsSize.size}}</span>
</a>
<a *ngIf="!externalLink" [routerLink]="links.get('project').link"
[queryParams]="links.get('project').params" class="uk-text-bold number uk-link-text uk-button-link">
{{numbers.projectsSize.number|number}}<span class="number-size">{{numbers.projectsSize.size}}</span>
</a>
</h3>
<span class="uk-text-uppercase uk-text-large">{{openaireEntities.PROJECTS}}</span>
</div>
</div>
</div>
<div class="uk-section uk-margin-top" [ngClass]="backgroundClass">
<div class="uk-container">
<div class="uk-grid uk-flex-center uk-margin-auto-left@m uk-margin-auto-right@m uk-grid-large" uk-grid>
<div *ngIf="numbers.publicationsSize" class="uk-width-1-2@m uk-flex uk-flex-center">
<div class="number-width uk-width-medium uk-flex uk-flex-column">
<a *ngIf="externalLink" [href]="links.get('publication').link" target="_blank"
class="number uk-text-bold uk-margin-bottom uk-text-center uk-text-left@m uk-link-text uk-button-link">{{numbers.publicationsSize.count|number}}</a>
<a *ngIf="!externalLink" [routerLink]="links.get('publication').link"
[queryParams]="links.get('publication').params"
class="number uk-text-bold uk-margin-bottom uk-text-center uk-text-left@m uk-link-text uk-button-link">{{numbers.publicationsSize.count|number}}</a>
<div class="uk-text-uppercase uk-flex uk-flex-middle uk-flex-center uk-flex-left@m">
<icon name="book" ratio="1.5" [flex]="true" class="uk-margin-right" [customClass]="colorClass"></icon>
<span>{{openaireEntities.PUBLICATIONS}}</span>
</div>
</div>
</div>
<div *ngIf="numbers.datasetsSize" class="uk-width-1-2@m uk-flex uk-flex-center">
<div class="number-width uk-width-medium uk-flex uk-flex-column">
<a *ngIf="externalLink" [href]="links.get('dataset').link" target="_blank"
class="number uk-text-bold uk-margin-bottom uk-text-center uk-text-left@m uk-link-text uk-button-link">{{numbers.datasetsSize.count|number}}</a>
<a *ngIf="!externalLink" [routerLink]="links.get('dataset').link"
[queryParams]="links.get('dataset').params"
class="number uk-text-bold uk-margin-bottom uk-text-center uk-text-left@m uk-link-text uk-button-link">{{numbers.datasetsSize.count|number}}</a>
<div class="uk-text-uppercase uk-flex uk-flex-middle uk-flex-center uk-flex-left@m">
<icon name="database" ratio="1.5" [flex]="true" class="uk-margin-right"
[customClass]="colorClass"></icon>
<span>{{openaireEntities.DATASETS}}</span>
</div>
</div>
</div>
<div *ngIf="numbers.softwareSize" class="uk-width-1-2@m uk-flex uk-flex-center">
<div class="number-width uk-width-medium uk-flex uk-flex-column">
<a *ngIf="externalLink" [href]="links.get('software').link" target="_blank"
class="number uk-text-bold uk-margin-bottom uk-text-center uk-text-left@m uk-link-text uk-button-link">{{numbers.softwareSize.count|number}}</a>
<a *ngIf="!externalLink" [routerLink]="links.get('software').link"
[queryParams]="links.get('software').params"
class="number uk-text-bold uk-margin-bottom uk-text-center uk-text-left@m uk-link-text uk-button-link">{{numbers.softwareSize.count|number}}</a>
<div class="uk-text-uppercase uk-flex uk-flex-middle uk-flex-center uk-flex-left@m">
<icon name="cog" ratio="1.5" [flex]="true" class="uk-margin-right" [customClass]="colorClass"></icon>
<span>{{openaireEntities.SOFTWARE}}</span>
</div>
</div>
</div>
<div *ngIf="numbers.otherSize" class="uk-width-1-2@m uk-flex uk-flex-center">
<div class="number-width uk-width-medium uk-flex uk-flex-column">
<a *ngIf="externalLink" [href]="links.get('other').link" target="_blank"
class="number uk-text-bold uk-margin-bottom uk-text-center uk-text-left@m uk-link-text uk-button-link">{{numbers.otherSize.count|number}}</a>
<a *ngIf="!externalLink" [routerLink]="links.get('other').link"
[queryParams]="links.get('other').params"
class="number uk-text-bold uk-margin-bottom uk-text-center uk-text-left@m uk-link-text uk-button-link">{{numbers.otherSize.count|number}}</a>
<div class="uk-text-uppercase uk-flex uk-flex-middle uk-flex-center uk-flex-left@m">
<icon name="earth" ratio="1.5" [flex]="true" class="uk-margin-right"
[customClass]="colorClass"></icon>
<span>{{openaireEntities.OTHER}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="loading" class="uk-container uk-section uk-text-center" style="min-height: 400px">
<loading [color]="colorClass"></loading>
</div> </div>
`, `,
}) })
export class NumbersComponent implements OnInit, OnDestroy { export class NumbersComponent implements OnInit, OnDestroy {
@Input() colorClass = 'uk-text-primary';
@Input() backgroundClass = null;
/** Add a value if you want to apply refine query*/ /** Add a value if you want to apply refine query*/
@Input() refineValue = null; @Input() refineValue = null;
/** True: Default initialization /** True: Default initialization
* False: Call init method to initialize numbers */ * False: Call init method to initialize numbers */
@Input() defaultInit = true; @Input() defaultInit = true;
/** Add an external link for numbers link */
@Input() externalLink;
/** When numbers have been initialized this emitter will emitted */ /** When numbers have been initialized this emitter will emitted */
@Output() results: EventEmitter<Numbers> = new EventEmitter<Numbers>(); @Output() results: EventEmitter<Numbers> = new EventEmitter<Numbers>();
showPublications: boolean = true;
showDatasets: boolean = true;
showSoftware: boolean = true;
showOrp: boolean = true;
showOrganizations: boolean = true;
showProjects: boolean = true;
showDataProviders: boolean = true;
numbersLimit: number = 100;
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public openaireEntities = OpenaireEntities; public openaireEntities = OpenaireEntities;
public routerHelper: RouterHelper = new RouterHelper(); public routerHelper: RouterHelper = new RouterHelper();
public numbers: Numbers = {}; public numbers: Numbers = {};
public loading: boolean = true;
public links: Map<Entity, Link> = new Map<Entity, Link>();
private params: Map<Entity, {}> = new Map<Entity, {}>();
private emptySubject: BehaviorSubject<number> = new BehaviorSubject<number>(0); private emptySubject: BehaviorSubject<number> = new BehaviorSubject<number>(0);
private subs: any[] = []; private subs: any[] = [];
constructor(private searchResearchResultsService: SearchResearchResultsService, constructor(private searchResearchResultsService: SearchResearchResultsService,
private searchDataprovidersService: SearchDataprovidersService, private searchDataprovidersService: SearchDataprovidersService,
private refineFieldResultsService: RefineFieldResultsService) { private refineFieldResultsService: RefineFieldResultsService,
this.links = new Map<Entity, Link>(); private _searchOrganizationsService: SearchOrganizationsService) {
this.params = new Map<Entity, {}>();
this.emptySubject = new BehaviorSubject<number>(0); this.emptySubject = new BehaviorSubject<number>(0);
} }
@ -176,81 +81,10 @@ export class NumbersComponent implements OnInit, OnDestroy {
if (this.defaultInit) { if (this.defaultInit) {
this.init(); this.init();
} }
this.setLinks();
}
setParams() {
this.params.set('publication', {type: 'publications'});
this.params.set('dataset', {type: 'datasets'});
this.params.set('software', {type: 'software'});
this.params.set('other', {type: 'other'});
this.params.set('project', {});
this.params.set('datasource', {});
if (this.refineValue) {
this.params.forEach((value) => {
value['fq'] = this.refineValue;
});
}
}
setLinks() {
this.setParams();
if (this.externalLink) {
this.links.set('publication', {
link: this.externalLink + properties.searchLinkToResults +
this.routerHelper.createQueryParamsString(Object.keys(this.params.get('publication')), HelperFunctions.getValues(this.params.get('publication')))
});
this.links.set('dataset', {
link: this.externalLink + properties.searchLinkToResults +
this.routerHelper.createQueryParamsString(Object.keys(this.params.get('dataset')), HelperFunctions.getValues(this.params.get('dataset')))
});
this.links.set('software', {
link: this.externalLink + properties.searchLinkToResults +
this.routerHelper.createQueryParamsString(Object.keys(this.params.get('software')), HelperFunctions.getValues(this.params.get('software')))
});
this.links.set('other', {
link: this.externalLink + properties.searchLinkToResults +
this.routerHelper.createQueryParamsString(Object.keys(this.params.get('other')), HelperFunctions.getValues(this.params.get('other')))
});
this.links.set('project', {
link: this.externalLink + properties.searchLinkToProjects +
this.routerHelper.createQueryParamsString(Object.keys(this.params.get('project')), HelperFunctions.getValues(this.params.get('project')))
});
this.links.set('datasource', {
link: this.externalLink + properties.searchLinkToDataProviders +
this.routerHelper.createQueryParamsString(Object.keys(this.params.get('datasource')), HelperFunctions.getValues(this.params.get('datasource')))
});
} else {
this.links.set('publication', {
link: properties.searchLinkToResults,
params: this.routerHelper.createQueryParams(Object.keys(this.params.get('publication')), HelperFunctions.getValues(this.params.get('publication')))
});
this.links.set('dataset', {
link: properties.searchLinkToResults,
params: this.routerHelper.createQueryParams(Object.keys(this.params.get('dataset')), HelperFunctions.getValues(this.params.get('dataset')))
});
this.links.set('software', {
link: properties.searchLinkToResults,
params: this.routerHelper.createQueryParams(Object.keys(this.params.get('software')), HelperFunctions.getValues(this.params.get('software')))
});
this.links.set('other', {
link: properties.searchLinkToResults,
params: this.routerHelper.createQueryParams(Object.keys(this.params.get('other')), HelperFunctions.getValues(this.params.get('other')))
});
this.links.set('project', {
link: properties.searchLinkToProjects,
params: this.routerHelper.createQueryParams(Object.keys(this.params.get('project')), HelperFunctions.getValues(this.params.get('project')))
});
this.links.set('datasource', {
link: properties.searchLinkToDataProviders,
params: this.routerHelper.createQueryParams(Object.keys(this.params.get('datasource')), HelperFunctions.getValues(this.params.get('datasource')))
});
}
} }
init(getDatasetsLinked = false, getSoftwareLinked = false, getPublications = true, getDatasets = true, init(getDatasetsLinked = false, getSoftwareLinked = false, getPublications = true, getDatasets = true,
getSoftware = true, getOther = true, getProjects = true, getDataProviders = true, refineValue: string = null) { getSoftware = true, getOther = true, getProjects = true, getDataProviders = true, getOrganizations = true, refineValue: string = null) {
this.loading = true;
if (refineValue) { if (refineValue) {
this.refineValue = refineValue; this.refineValue = refineValue;
} }
@ -263,7 +97,8 @@ export class NumbersComponent implements OnInit, OnDestroy {
(getSoftwareLinked) ? this.searchResearchResultsService.numOfSearchResultsLinkedToPub("software", this.properties) : this.empty, (getSoftwareLinked) ? this.searchResearchResultsService.numOfSearchResultsLinkedToPub("software", this.properties) : this.empty,
(getOther) ? this.searchResearchResultsService.numOfSearchResults('other', '', this.properties, refineParams) : this.empty, (getOther) ? this.searchResearchResultsService.numOfSearchResults('other', '', this.properties, refineParams) : this.empty,
(getProjects) ? this.refineFieldResultsService.getRefineFieldsResultsByEntityName(['funder'], 'project', this.properties, refineParams) : this.empty, (getProjects) ? this.refineFieldResultsService.getRefineFieldsResultsByEntityName(['funder'], 'project', this.properties, refineParams) : this.empty,
(getDataProviders) ? this.searchDataprovidersService.numOfSearchDataproviders('', this.properties, refineParams) : this.empty (getDataProviders) ? this.searchDataprovidersService.numOfSearchDataproviders('', this.properties, refineParams) : this.empty,
(getOrganizations) ? this._searchOrganizationsService.numOfSearchOrganizations2('', this.properties, refineParams) : this.empty
).subscribe((data: any[]) => { ).subscribe((data: any[]) => {
if (data[0] && data[0] > 0) { if (data[0] && data[0] > 0) {
this.numbers.publicationsSize = NumberUtils.roundNumber(data[0]); this.numbers.publicationsSize = NumberUtils.roundNumber(data[0]);
@ -291,12 +126,13 @@ export class NumbersComponent implements OnInit, OnDestroy {
} }
if (data[7] && data[7] > 0) { if (data[7] && data[7] > 0) {
this.numbers.datasourcesSize = NumberUtils.roundNumber(data[7]); this.numbers.datasourcesSize = NumberUtils.roundNumber(data[7]);
}
if (data[8] && data[8] > 0) {
this.numbers.organizationsSize = NumberUtils.roundNumber(data[8]);
} }
this.results.emit(this.numbers); this.results.emit(this.numbers);
this.loading = false;
}, err => { }, err => {
this.handleError('Error getting numbers', err); this.handleError('Error getting numbers', err);
this.loading = false;
})); }));
} }
@ -314,5 +150,35 @@ export class NumbersComponent implements OnInit, OnDestroy {
private handleError(message: string, error) { private handleError(message: string, error) {
console.error('Numbers: ' + message, error); console.error('Numbers: ' + message, error);
}
public get showContentWithNumbers() {
if (this.numbers && (this.hasPublications || this.hasDatasets || this.hasSoftware || this.hasDatasources || this.hasProjects || this.hasOrganizations)) {
return true;
}
}
public get hasPublications() {
return this.showPublications && this.numbers.publicationsSize && this.numbers.publicationsSize.count >= this.numbersLimit;
}
public get hasDatasets() {
return this.showDatasets && this.numbers.datasetsSize && this.numbers.datasetsSize.count >= this.numbersLimit;
}
public get hasSoftware() {
return this.showSoftware && this.numbers.softwareSize && this.numbers.softwareSize.count >= this.numbersLimit;
}
public get hasDatasources() {
return this.showDataProviders && this.numbers.datasourcesSize && this.numbers.datasourcesSize.count >= this.numbersLimit;
}
public get hasProjects() {
return this.showProjects && this.numbers.projectsSize && this.numbers.projectsSize.count >= this.numbersLimit;
}
public get hasOrganizations() {
return this.showOrganizations && this.numbers.organizationsSize && this.numbers.organizationsSize.count >= this.numbersLimit;
} }
} }

View File

@ -117,8 +117,8 @@ export class JsonldDocumentSerializerService {
} }
serializeDescription(doc, buffer){ serializeDescription(doc, buffer){
if(doc.description && doc.description[0]) { if(doc.description) {
buffer["description"] = doc.description[0]; buffer["description"] = doc.description;
} }
} }
serializeIdentifier(doc, buffer){ serializeIdentifier(doc, buffer){

View File

@ -22,7 +22,7 @@ import {ClickEvent} from "../../utils/click/click-outside-or-esc.directive";
[class.collapsed]="hidden" [ngClass]="searchInputClass"> [class.collapsed]="hidden" [ngClass]="searchInputClass">
<div class="uk-flex uk-flex-middle"> <div class="uk-flex uk-flex-middle">
<div class="uk-width-expand"> <div class="uk-width-expand">
<div #input [class.uk-hidden]="hidden" input [formInput]="searchControl" inputClass="search" [disabledIcon]="null" <div #input [class.uk-hidden]="hidden" input [formInput]="searchControl" [inputClass]="'search'+(iconPosition === 'left'?' icon-left':'')" [disabledIcon]="null"
[placeholder]="{label: placeholder, static: true}" [value]="value" (valueChange)="valueChange.emit($event)" [placeholder]="{label: placeholder, static: true}" [value]="value" (valueChange)="valueChange.emit($event)"
[disabled]="disabled" [showOptionsOnEmpty]="false" [type]="(options.length > 0?'autocomplete_soft':'text')" [options]="options"></div> [disabled]="disabled" [showOptionsOnEmpty]="false" [type]="(options.length > 0?'autocomplete_soft':'text')" [options]="options"></div>
</div> </div>
@ -36,6 +36,9 @@ import {ClickEvent} from "../../utils/click/click-outside-or-esc.directive";
<icon name="search" [flex]="true" ratio="1.3"></icon> <icon name="search" [flex]="true" ratio="1.3"></icon>
</div> </div>
</div> </div>
<div class="uk-width-auto filters-toggle">
<ng-content select="[filters-toggle]"></ng-content>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -40,8 +40,7 @@ declare var UIkit;
</div> </div>
<a *ngIf="position === 'horizontal'" class="uk-position-center-left uk-blur-background" uk-slider-item="previous"><span <a *ngIf="position === 'horizontal'" class="uk-position-center-left uk-blur-background" uk-slider-item="previous"><span
uk-icon="chevron-left"></span></a> uk-icon="chevron-left"></span></a>
<a *ngIf="position === 'horizontal'" class="uk-position-center-right uk-blur-background" <a *ngIf="position === 'horizontal'" class="uk-position-center-right uk-blur-background" uk-slider-item="next"><span
uk-slider-item="next"><span
uk-icon="chevron-right"></span></a> uk-icon="chevron-right"></span></a>
</div> </div>
`, `,

View File

@ -9,7 +9,9 @@ export const DEFAULT_TIMEOUT = new InjectionToken<number>('defaultTimeout');
@Injectable() @Injectable()
export class TimeoutInterceptor implements HttpInterceptor { export class TimeoutInterceptor implements HttpInterceptor {
private static TIMEOUT_WHITELIST = [properties.csvAPIURL, properties.registryUrl, properties.claimsAPIURL]; // timeout inside services for: properties.searchCrossrefAPIURL, properties.searchDataciteAPIURL
private static TIMEOUT_WHITELIST = [properties.csvAPIURL, properties.registryUrl, properties.claimsAPIURL,
properties.searchCrossrefAPIURL, properties.searchDataciteAPIURL];
constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout: number, @Inject(PLATFORM_ID) private platformId: any) { constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout: number, @Inject(PLATFORM_ID) private platformId: any) {
} }

View File

@ -1,3 +1,5 @@
import {UrlMatcher, UrlSegment} from "@angular/router";
export class HelperFunctions { export class HelperFunctions {
public static scroll() { public static scroll() {
@ -107,4 +109,37 @@ export class HelperFunctions {
public static swap(array: any[], from, to) { public static swap(array: any[], from, to) {
array.splice(to, 0, array.splice(from, 1)[0]); array.splice(to, 0, array.splice(from, 1)[0]);
} }
public static routingMatcher:((paths: string[]) => UrlMatcher) = (paths: string[]) => {
return (segments) => {
const matchingPathIndex = paths.findIndex((path, index) => {
const pathSegments = path.split("/");
return segments.every((segment, i) =>
pathSegments.length > i && (
pathSegments[i].startsWith(":") ? true : segment.path.toLowerCase() === pathSegments[i].toLowerCase()));
});
if (matchingPathIndex >= 0) {
const matchingPath = paths[matchingPathIndex];
const consumed: UrlSegment[] = [];
const params = {};
matchingPath.split("/").forEach((path, i) => {
consumed.push(segments[i]);
if (path.startsWith(":")) {
const param = path.substring(1);
params[param] = segments[i];
}
});
return {
consumed: consumed,
posParams: params
};
}
return null;
};
};
} }

View File

@ -11,7 +11,7 @@ import {properties} from "../../../../environments/environment";
export class ConfigurationService { export class ConfigurationService {
private communityInformation: BehaviorSubject<Portal> = new BehaviorSubject(null); private communityInformation: BehaviorSubject<Portal> = new BehaviorSubject(null);
private sub: Subscription = null; private sub: Subscription = null;
private promise: Promise<boolean> = null; private promise: Promise<void> = null;
constructor(private http: HttpClient) { constructor(private http: HttpClient) {
} }
@ -36,7 +36,7 @@ export class ConfigurationService {
} }
public initStaticCommunityInformation(communityInformation: Portal) { public initStaticCommunityInformation(communityInformation: Portal) {
this.promise = new Promise<any>((resolve => { this.promise = new Promise<void>((resolve => {
this.communityInformation.next(communityInformation); this.communityInformation.next(communityInformation);
resolve(); resolve();
})); }));
@ -45,7 +45,7 @@ export class ConfigurationService {
public initCommunityInformation(properties: EnvProperties, community: string) { public initCommunityInformation(properties: EnvProperties, community: string) {
if (community == null) return; if (community == null) return;
let url = properties.adminToolsAPIURL + "/" + properties.adminToolsPortalType + "/" + community + "/full"; let url = properties.adminToolsAPIURL + "/" + properties.adminToolsPortalType + "/" + community + "/full";
this.promise = new Promise<any>((resolve => { this.promise = new Promise<void>((resolve => {
this.sub = this.http.get<Portal>((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url).subscribe( this.sub = this.http.get<Portal>((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url).subscribe(
(communityInformation: Portal) => { (communityInformation: Portal) => {
this.communityInformation.next(communityInformation); this.communityInformation.next(communityInformation);

View File

@ -6,6 +6,7 @@ export class Curator {
affiliations: Affiliation[]; affiliations: Affiliation[];
photo: string; photo: string;
bio: string; bio: string;
visible: boolean = true;
} }
export class Affiliation { export class Affiliation {

View File

@ -54,6 +54,38 @@ import {Component} from "@angular/core";
<icon name="mining"></icon> <icon name="mining"></icon>
<div class="uk-text-bold uk-margin-small-top">mining</div> <div class="uk-text-bold uk-margin-small-top">mining</div>
</div> </div>
<div class="uk-text-center">
<icon name="by"></icon>
<div class="uk-text-bold uk-margin-small-top">by</div>
</div>
<div class="uk-text-center">
<icon name="cc"></icon>
<div class="uk-text-bold uk-margin-small-top">cc</div>
</div>
<div class="uk-text-center">
<icon name="twitter"></icon>
<div class="uk-text-bold uk-margin-small-top">twitter</div>
</div>
<div class="uk-text-center">
<icon name="facebook"></icon>
<div class="uk-text-bold uk-margin-small-top">facebook</div>
</div>
<div class="uk-text-center">
<icon name="linkedin"></icon>
<div class="uk-text-bold uk-margin-small-top">linkedin</div>
</div>
<div class="uk-text-center">
<icon name="slideshare"></icon>
<div class="uk-text-bold uk-margin-small-top">slideshare</div>
</div>
<div class="uk-text-center">
<icon name="youtube"></icon>
<div class="uk-text-bold uk-margin-small-top">youtube</div>
</div>
<div class="uk-text-center">
<icon name="newsletter"></icon>
<div class="uk-text-bold uk-margin-small-top">newsletter</div>
</div>
</div> </div>
<div class="uk-margin-medium-top"> <div class="uk-margin-medium-top">
<h4 class="uk-text-bold">Usage</h4> <h4 class="uk-text-bold">Usage</h4>

View File

@ -15,7 +15,9 @@ import {
orcid_add, orcid_add,
orcid_bin, orcid_bin,
quotes, quotes,
restricted restricted,
by,
cc, twitter, facebook, linkedin, slideshare, youtube, newsletter
} from "../icons"; } from "../icons";
@NgModule({ @NgModule({
@ -27,6 +29,6 @@ import {
}) })
export class IconsPreviewModule { export class IconsPreviewModule {
constructor(private iconsService: IconsService) { constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([book, database, cog, earth, incognito, restricted, graph, filters, orcid_add, orcid_bin, link, quotes, mining]) this.iconsService.registerIcons([book, database, cog, earth, incognito, restricted, graph, filters, orcid_add, orcid_bin, link, quotes, mining, by, cc, twitter, facebook, linkedin, slideshare, youtube, newsletter])
} }
} }

View File

@ -46,7 +46,7 @@ export interface StopRule {
@Component({ @Component({
selector: 'icon', selector: 'icon',
template: ` template: `
<span #icon *ngIf="svg" class="uk-icon" [class.uk-preserve]="gradient" [class.uk-flex]="flex" [ngClass]="customClass" [ngStyle]="style" [innerHTML]="svg | safeHtml"></span> <span #icon *ngIf="svg" class="uk-icon" [class.uk-preserve]="gradient || preserveColor" [class.uk-flex]="flex" [ngClass]="customClass" [ngStyle]="style" [innerHTML]="svg | safeHtml"></span>
<span *ngIf="!svg && iconName" [class.uk-flex]="flex" [ngClass]="customClass" [class.uk-display-inline-block]="!flex"> <span *ngIf="!svg && iconName" [class.uk-flex]="flex" [ngClass]="customClass" [class.uk-display-inline-block]="!flex">
<span class="material-icons" [ngClass]="type" [ngStyle]="style">{{iconName}}</span> <span class="material-icons" [ngClass]="type" [ngStyle]="style">{{iconName}}</span>
</span> </span>
@ -125,6 +125,8 @@ export class IconsComponent implements AfterViewInit, OnChanges {
public stopRules: StopRule[]= [{class: 'start', offset: 0}, {class: 'end', offset: 100}]; public stopRules: StopRule[]= [{class: 'start', offset: 0}, {class: 'end', offset: 100}];
@ViewChild("icon") @ViewChild("icon")
public icon: ElementRef; public icon: ElementRef;
@Input()
public preserveColor: boolean = false;
constructor(private iconsService: IconsService, constructor(private iconsService: IconsService,
private cdr: ChangeDetectorRef) {} private cdr: ChangeDetectorRef) {}

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