Merge remote-tracking branch 'origin/master' into angular-14
This commit is contained in:
commit
17212458eb
|
@ -0,0 +1,13 @@
|
|||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule} from '@angular/router';
|
||||
|
||||
import {FosComponent} from './fos.component';
|
||||
import {PreviousRouteRecorder} from '../utils/piwik/previousRouteRecorder.guard';
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{ path: '', component: FosComponent, canDeactivate: [PreviousRouteRecorder] }
|
||||
])
|
||||
]
|
||||
})
|
||||
export class FosRoutingModule { }
|
|
@ -0,0 +1,159 @@
|
|||
<schema2jsonld *ngIf="url" [URL]="url" [name]="pageTitle" type="other" [description]="pageDescription"></schema2jsonld>
|
||||
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
|
||||
<div class="uk-padding-small uk-padding-remove-horizontal">
|
||||
<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-container uk-container-large uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-slide-bottom-medium; delay: 200">
|
||||
<div class="uk-grid uk-grid-large uk-grid-stack uk-padding-small" uk-grid>
|
||||
<div class="uk-width-3-5@m uk-width-1-1@s uk-flex uk-flex-column uk-flex-center">
|
||||
<span class="uk-align-left uk-margin-remove-bottom">
|
||||
<span uk-scrollspy-class class="uk-text-large" style="color: #EEB204">Beta</span>
|
||||
</span>
|
||||
<div style="max-width: 600px;">
|
||||
<h1 uk-scrollspy-class class="uk-h1 uk-margin-remove-top">
|
||||
<span>Fields of Science <span class="uk-text-primary">.</span></span>
|
||||
</h1>
|
||||
<div uk-scrollspy-class>
|
||||
We have integrated a Field-of-Science (FoS) taxonomy into our dataset to organize and discover research more effectively. Using the full capabilities of the OpenAIRE Research Graph (full-texts, citations, references, venues) we apply AI and bring forward any multidisciplinarity potential.
|
||||
</div>
|
||||
<div class="uk-text-meta uk-margin-top" uk-scrollspy-class>
|
||||
Our work is based on the work from our partner Athena Research Center: SciNoBo : A Hierarchical Multi-Label Classifier of Scientific Publications - <a href="https://doi.org/10.1145/3487553.3524677" target="_blank">https://doi.org/10.1145/3487553.3524677</a>
|
||||
</div>
|
||||
<!-- TODO: We need a page for the button link -->
|
||||
<!-- <div>
|
||||
<a class="uk-display-inline-block uk-text-uppercase uk-button uk-button-text uk-margin-top" uk-scrollspy-class
|
||||
routerLinkActive="router-link-active" routerLink="/">
|
||||
<span class="uk-flex uk-flex-middle">
|
||||
<span>Learn More</span>
|
||||
</span>
|
||||
</a>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-width-2-5@m uk-width-1-1@s uk-text-center" uk-scrollspy-class>
|
||||
<img src="assets/common-assets/fos/fos-hero-img.svg" loading="lazy">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="fos?.length" class="uk-container uk-container-large uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-slide-bottom-medium; delay: 200">
|
||||
<div class="uk-visible@m">
|
||||
<div uk-sticky="offset: 50;" class="uk-sticky uk-background-default uk-padding uk-padding-remove-bottom uk-padding-remove-horizontal">
|
||||
<div class="uk-flex uk-flex-right uk-margin-small-bottom">
|
||||
<div search-input [searchControl]="keywordControl" [options]="fosOptions" iconPosition="left" placeholder="Write a key word to filter the content"
|
||||
searchInputClass="border-bottom" class="uk-width-large"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container>
|
||||
<div class="uk-margin-top uk-padding-small">
|
||||
<div id="parentContainer" class="uk-grid uk-grid-large" uk-grid>
|
||||
<div class="uk-width-1-4@m uk-visible@m">
|
||||
<div class="uk-sticky" uk-sticky="bottom: !#parentContainer; offset: 200;">
|
||||
<ul *ngIf="!keyword" class="uk-tab uk-tab-left">
|
||||
<li *ngFor="let item of fos; index as i" [class.uk-active]="activeSection === item.id"
|
||||
class="uk-margin-small-bottom uk-text-capitalize">
|
||||
<a routerLink="./" [fragment]="item.id">{{item.id}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul *ngIf="keyword?.length" class="uk-tab uk-tab-left">
|
||||
<li *ngFor="let item of viewResults; index as i"
|
||||
class="uk-margin-small-bottom uk-text-capitalize" [class.uk-active]="activeSection === item.id">
|
||||
<a routerLink="./" [fragment]="item.id">{{item.id}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-width-1-1 uk-hidden@m">
|
||||
<div class="uk-sticky uk-blur-background" uk-sticky>
|
||||
<div class="uk-flex uk-flex-center uk-margin-small-bottom">
|
||||
<div search-input [searchControl]="keywordControl" [options]="fosOptions" iconPosition="left" placeholder="Write a key word to filter the content"
|
||||
searchInputClass="border-bottom" class="uk-width-large"></div>
|
||||
</div>
|
||||
<div #tabs class="uk-slider uk-position-relative" uk-slider="finite: true">
|
||||
<div class="uk-slider-container">
|
||||
<ul *ngIf="!keyword" class="uk-tab uk-flex-nowrap uk-slider-items">
|
||||
<li *ngFor="let item of fos; index as i" [class.uk-active]="activeSection === item.id && sliderInit"
|
||||
class="uk-text-capitalize">
|
||||
<a routerLink="./" [fragment]="item.id">{{item.id}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul *ngIf="keyword?.length" class="uk-tab uk-flex-nowrap uk-slider-items">
|
||||
<li *ngFor="let item of viewResults; index as i"
|
||||
class="uk-text-capitalize" [class.uk-active]="activeSection === item.id && sliderInit">
|
||||
<a routerLink="./" [fragment]="item.id">{{item.id}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<a class="uk-position-center-left uk-blur-background" uk-slider-item="previous"><span uk-icon="chevron-left"></span></a>
|
||||
<a class="uk-position-center-right uk-blur-background" uk-slider-item="next"><span uk-icon="chevron-right"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-width-expand@m">
|
||||
<ng-container *ngIf="!keyword">
|
||||
<div [id]="item.id" *ngFor="let item of fos; index as i">
|
||||
<div class="uk-text-capitalize">
|
||||
<h2 class="uk-h4 uk-margin-remove">
|
||||
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(item.id)}"
|
||||
class="uk-link-text">
|
||||
{{item.id}}
|
||||
</a>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="uk-grid uk-child-width-1-3 uk-margin-large-top uk-margin-xlarge-bottom" uk-grid="masonry: false">
|
||||
<div *ngFor="let child of item.children">
|
||||
<div class="uk-text-capitalize">
|
||||
<h3 class="uk-h6 uk-margin-small-bottom">
|
||||
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(child.id)}"
|
||||
class="uk-link-text">
|
||||
{{child.id}}
|
||||
</a>
|
||||
</h3>
|
||||
<div *ngFor="let subChild of child.children" style="margin-bottom: 5px;">
|
||||
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subChild.id)}"
|
||||
class="uk-link-text">
|
||||
{{subChild.id}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="keyword?.length">
|
||||
<div [id]="item.id" *ngFor="let item of viewResults; index as i">
|
||||
<div
|
||||
class="uk-margin-large-bottom uk-padding uk-padding-remove-top uk-padding-remove-horizontal uk-text-capitalize" [class.custom-bottom-border]="i < viewResults.length - 1">
|
||||
<h2 class="uk-h4 uk-margin-remove">
|
||||
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(item.id)}"
|
||||
class="uk-link-text" [innerHTML]="highlightKeyword(item.id)">
|
||||
</a>
|
||||
</h2>
|
||||
<div class="uk-grid uk-child-width-1-3 uk-margin-large-top uk-margin-medium-bottom" uk-grid="masonry: false">
|
||||
<div *ngFor="let subItem of item.children">
|
||||
<h3 class="uk-h6 uk-margin-small-bottom">
|
||||
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subItem.id)}"
|
||||
class="uk-link-text" [innerHTML]="highlightKeyword(subItem.id)">
|
||||
</a>
|
||||
</h3>
|
||||
<div *ngFor="let subSubItem of subItem.children" style="margin-bottom: 5px;">
|
||||
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'fos': urlEncodeAndQuote(subSubItem.id)}"
|
||||
class="uk-link-text" [innerHTML]="highlightKeyword(subSubItem.id)">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="keyword && viewResults?.length == 0">
|
||||
<div class="uk-padding-large uk-text-center">
|
||||
<h2 class="uk-h3">No results were found.</h2>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
|
@ -0,0 +1,5 @@
|
|||
@import (reference) "~src/assets/openaire-theme/less/_import-variables";
|
||||
|
||||
.custom-bottom-border {
|
||||
border-bottom: 5px solid fade(@explore-color, @global-opacity);
|
||||
}
|
|
@ -0,0 +1,220 @@
|
|||
import {HttpClient} from "@angular/common/http";
|
||||
import {ChangeDetectorRef, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from "@angular/core";
|
||||
import {Subscription} from "rxjs";
|
||||
|
||||
import {Breadcrumb} from "../utils/breadcrumbs/breadcrumbs.component";
|
||||
import {EnvProperties} from "../utils/properties/env-properties";
|
||||
import {properties} from "src/environments/environment";
|
||||
import {FormBuilder, FormControl} from "@angular/forms";
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {Meta, Title} from "@angular/platform-browser";
|
||||
import {Location} from "@angular/common";
|
||||
import {StringUtils} from "../utils/string-utils.class";
|
||||
import {SEOService} from "../sharedComponents/SEO/SEO.service";
|
||||
import {PiwikService} from "../utils/piwik/piwik.service";
|
||||
import {debounceTime, distinctUntilChanged} from "rxjs/operators";
|
||||
import Timeout = NodeJS.Timeout;
|
||||
|
||||
declare var UIkit;
|
||||
|
||||
@Component({
|
||||
selector: 'fos',
|
||||
templateUrl: 'fos.component.html',
|
||||
styleUrls: ['fos.component.less']
|
||||
})
|
||||
export class FosComponent implements OnInit, OnDestroy {
|
||||
public url: string = null;
|
||||
public pageTitle: string = "OpenAIRE | Fields of Science";
|
||||
public pageDescription: string = "We have integrated a Field-of-Science (FoS) taxonomy into our dataset to organize and discover research more effectively. Using the full capabilities of the OpenAIRE Research Graph (full-texts, citations, references, venues) we apply AI and bring forward any multidisciplinarity potential.";
|
||||
@Input() piwikSiteId = null;
|
||||
|
||||
public fos: any[] = [];
|
||||
public fosOptions: string[] = [];
|
||||
public activeSection: string;
|
||||
|
||||
public keywordControl: FormControl;
|
||||
public keyword: string;
|
||||
|
||||
public viewResults = [];
|
||||
|
||||
public result = [];
|
||||
|
||||
properties: EnvProperties = properties;
|
||||
public breadcrumbs: Breadcrumb[] = [{name: 'home', route: '/'}, {name: 'Fields of Science'}];
|
||||
|
||||
private subscriptions: Subscription[] = [];
|
||||
private observer: IntersectionObserver;
|
||||
private timeout: Timeout;
|
||||
@ViewChild('tabs') tabs: ElementRef;
|
||||
public sliderInit: boolean = false;
|
||||
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
private fb: FormBuilder,
|
||||
private location: Location,
|
||||
private route: ActivatedRoute,
|
||||
private _router: Router,
|
||||
private _meta: Meta,
|
||||
private _title: Title,
|
||||
private seoService: SEOService,
|
||||
private _piwikService: PiwikService,
|
||||
private cdr: ChangeDetectorRef
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.properties.enablePiwikTrack && (typeof document !== 'undefined')) {
|
||||
this.subscriptions.push(this._piwikService.trackView(this.properties, this.pageTitle, this.piwikSiteId).subscribe());
|
||||
}
|
||||
this.url = this.properties.domain + this.properties.baseLink + this._router.url;
|
||||
this.seoService.createLinkForCanonicalURL(this.url);
|
||||
this.updateUrl(this.url);
|
||||
this.updateTitle(this.pageTitle);
|
||||
this.updateDescription(this.pageDescription);
|
||||
this.httpClient.get(properties.domain+'/assets/common-assets/vocabulary/fos.json').subscribe(data => {
|
||||
this.fos = data['fos'];
|
||||
this.convertFosToOptions();
|
||||
if (typeof document !== 'undefined') {
|
||||
setTimeout(()=> {
|
||||
let slider = UIkit.slider(this.tabs.nativeElement);
|
||||
slider.clsActive = 'uk-slider-active';
|
||||
slider.updateActiveClasses();
|
||||
this.sliderInit = true;
|
||||
slider.slides.forEach(item => {
|
||||
item.classList.remove('uk-active');
|
||||
});
|
||||
if (this.route.snapshot.fragment) {
|
||||
this.activeSection = this.route.snapshot.fragment;
|
||||
let i = this.fos.findIndex(item => item.id == this.route.snapshot.fragment);
|
||||
slider.show(i);
|
||||
} else {
|
||||
this.activeSection = this.fos[0].id;
|
||||
}
|
||||
this.cdr.detectChanges();
|
||||
});
|
||||
}
|
||||
this.subscriptions.push(this.route.fragment.subscribe(fragment => {
|
||||
if(fragment) {
|
||||
this.activeSection = fragment;
|
||||
if(this.tabs) {
|
||||
let slider = UIkit.slider(this.tabs.nativeElement);
|
||||
let i = this.fos.findIndex(item => item.id == fragment);
|
||||
slider.show(i);
|
||||
}
|
||||
} else {
|
||||
this.activeSection = this.fos[0].id;
|
||||
}
|
||||
}));
|
||||
this.keywordControl = this.fb.control('');
|
||||
this.subscriptions.push(this.keywordControl.valueChanges.pipe(debounceTime(500), distinctUntilChanged()).subscribe(value => {
|
||||
this.keyword = value;
|
||||
this.findMatches(this.keyword);
|
||||
if (typeof document !== 'undefined') {
|
||||
setTimeout(() => {
|
||||
this.setObserver();
|
||||
});
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnDestroy() {
|
||||
for (let sub of this.subscriptions) {
|
||||
sub.unsubscribe();
|
||||
}
|
||||
if(this.observer) {
|
||||
this.observer.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private setObserver() {
|
||||
if(this.observer) {
|
||||
this.observer.disconnect();
|
||||
}
|
||||
this.observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if(entry.isIntersecting) {
|
||||
if(this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
this.timeout = setTimeout(() => {
|
||||
this._router.navigate(['./'], {fragment: entry.target.id, relativeTo: this.route, state: {disableScroll: true}});
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
}, {threshold: 0.25, rootMargin: '-100px'});
|
||||
this.fos.forEach(fos => {
|
||||
let element = document.getElementById(fos.id);
|
||||
if(element) {
|
||||
this.observer.observe(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
convertFosToOptions() {
|
||||
this.fosOptions = [];
|
||||
this.fos.forEach(fos => {
|
||||
this.fosOptions.push(fos.id);
|
||||
if(fos.children) {
|
||||
fos.children.forEach(child => {
|
||||
this.fosOptions.push(child.id);
|
||||
if(child.children) {
|
||||
child.children.forEach(child2 => {
|
||||
this.fosOptions.push(child2.id);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
findMatches(value: string) {
|
||||
this.viewResults = JSON.parse(JSON.stringify(this.fos));
|
||||
let matchLevel1: boolean = false;
|
||||
let matchLevel2: boolean = false;
|
||||
// 1st level search
|
||||
if(this.viewResults.length) {
|
||||
this.viewResults = this.viewResults.filter(item => {
|
||||
matchLevel1 = !!item.id.includes(value?.toLowerCase());
|
||||
// // 2nd level search
|
||||
if(item.children?.length && !matchLevel1) {
|
||||
item.children = item.children.filter(subItem => {
|
||||
matchLevel2 = !!subItem.id.includes(value?.toLowerCase());
|
||||
// 3rd level search
|
||||
if(subItem.children?.length && !matchLevel2) {
|
||||
subItem.children = subItem.children.filter(subSubItem => subSubItem.id.includes(value?.toLowerCase()));
|
||||
}
|
||||
return subItem.children?.length > 0 || matchLevel2;
|
||||
});
|
||||
}
|
||||
return item.children?.length > 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
highlightKeyword(name) {
|
||||
if(name.includes(this.keyword.toLowerCase())) {
|
||||
return name.replace(new RegExp(this.keyword, "gi"), (matchedValue) => `<mark class="highlighted">${matchedValue}</mark>`);
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public urlEncodeAndQuote(str: string): string {
|
||||
return StringUtils.quote(StringUtils.URIEncode(str));
|
||||
}
|
||||
|
||||
private updateUrl(url: string) {
|
||||
this._meta.updateTag({content: url}, "property='og:url'");
|
||||
}
|
||||
|
||||
private updateTitle(title: string) {
|
||||
var _title = ((title.length > 50) ? title.substring(0, 50) : title);
|
||||
this._title.setTitle(_title);
|
||||
this._meta.updateTag({content: _title}, "property='og:title'");
|
||||
}
|
||||
|
||||
private updateDescription(description: string) {
|
||||
this._meta.updateTag({content: description}, "name='description'");
|
||||
this._meta.updateTag({content: description}, "property='og:description'");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import {CommonModule} from "@angular/common";
|
||||
import {NgModule} from "@angular/core";
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {PreviousRouteRecorder} from "../utils/piwik/previousRouteRecorder.guard";
|
||||
import {IconsModule} from "../utils/icons/icons.module";
|
||||
import {BreadcrumbsModule} from "../utils/breadcrumbs/breadcrumbs.module";
|
||||
import {Schema2jsonldModule} from "../sharedComponents/schema2jsonld/schema2jsonld.module";
|
||||
import {SearchInputModule} from "../sharedComponents/search-input/search-input.module";
|
||||
import {SEOServiceModule} from "../sharedComponents/SEO/SEOService.module";
|
||||
import {PiwikService} from "../utils/piwik/piwik.service";
|
||||
|
||||
import {FosRoutingModule} from './fos-routing.module';
|
||||
import {FosComponent} from './fos.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule, FormsModule, RouterModule,
|
||||
FosRoutingModule, BreadcrumbsModule, IconsModule,
|
||||
SearchInputModule, Schema2jsonldModule, SEOServiceModule
|
||||
],
|
||||
declarations: [
|
||||
FosComponent
|
||||
],
|
||||
providers: [
|
||||
PreviousRouteRecorder, PiwikService
|
||||
],
|
||||
exports: [
|
||||
FosComponent
|
||||
]
|
||||
})
|
||||
export class FosModule {
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule} from '@angular/router';
|
||||
|
||||
import {SdgComponent} from './sdg.component';
|
||||
import {PreviousRouteRecorder} from '../utils/piwik/previousRouteRecorder.guard';
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{ path: '', component: SdgComponent, canDeactivate: [PreviousRouteRecorder] }
|
||||
])
|
||||
]
|
||||
})
|
||||
export class SdgRoutingModule { }
|
|
@ -0,0 +1,72 @@
|
|||
<schema2jsonld *ngIf="url" [URL]="url" [name]="pageTitle" type="other" [description]="pageDescription"></schema2jsonld>
|
||||
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
|
||||
<div class="uk-padding-small uk-padding-remove-horizontal">
|
||||
<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-container uk-container-large uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-slide-bottom-medium; delay: 200">
|
||||
<div class="uk-grid uk-grid-large uk-grid-stack uk-padding-small" uk-grid>
|
||||
<div class="uk-width-3-5@m uk-width-1-1@s uk-flex uk-flex-column uk-flex-center">
|
||||
<span class="uk-align-left uk-margin-remove-bottom">
|
||||
<span uk-scrollspy-class class="uk-text-large" style="color: #EEB204">Beta</span>
|
||||
</span>
|
||||
<h1 uk-scrollspy-class class="uk-h1 uk-width-4-5@m uk-margin-remove-top">
|
||||
<span>Science for UN Sustainable Development Goals<span class="custom-sdg-dot"></span></span>
|
||||
</h1>
|
||||
<h2 uk-scrollspy-class class="uk-h5 uk-margin-remove-top">
|
||||
Laying the foundation for new approaches and solutions.
|
||||
</h2>
|
||||
<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.
|
||||
</div>
|
||||
<div>
|
||||
<!-- TODO: need a page for the description of the algorithm - to get us there from the learn more btn -->
|
||||
<!-- <a class="uk-display-inline-block uk-text-uppercase uk-button uk-button-text uk-margin-top" uk-scrollspy-class
|
||||
routerLinkActive="router-link-active" routerLink="/">
|
||||
<span class="uk-flex uk-flex-middle">
|
||||
<span>Learn More</span>
|
||||
</span>
|
||||
</a> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-width-2-5@m uk-width-1-1@s uk-text-center uk-position-relative" uk-scrollspy-class>
|
||||
<img src="assets/common-assets/sdg/sdg-hero-img.svg" loading="lazy">
|
||||
<div class="uk-position-bottom-left uk-card uk-card-default uk-padding">
|
||||
<img src="assets/common-assets/sdg/sdg-badge.png" loading="lazy" style="max-width: 215px">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-container uk-container-large uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-slide-bottom-medium; delay: 200">
|
||||
<div *ngIf="loading">
|
||||
<loading></loading>
|
||||
</div>
|
||||
<div *ngIf="!loading">
|
||||
<div *ngIf="displayedSdgs && displayedSdgs.length" class="uk-padding-small uk-margin-auto@m uk-grid uk-child-width-1-4@xl uk-child-width-1-4@l uk-child-width-1-3@m uk-child-width-1-2@s" uk-grid>
|
||||
<div *ngFor="let sdg of displayedSdgs">
|
||||
<a [routerLink]="properties.searchLinkToResults" [queryParams]="{'sdg': urlEncodeAndQuote(sdg.id)}"
|
||||
class="uk-link-reset">
|
||||
<div class="uk-card uk-card-default uk-card-hover" [class]="'sdg-card sdg-' + sdg.code">
|
||||
<div class="uk-height-1-1 uk-flex uk-flex-column uk-flex-between">
|
||||
<div class="uk-flex uk-flex-middle uk-light uk-padding-small uk-padding-remove-bottom">
|
||||
<div class="uk-text-bold uk-h4 uk-margin-remove">
|
||||
{{sdg.code}}
|
||||
</div>
|
||||
<div class="uk-text-bold uk-text-uppercase uk-text-small uk-margin-small-left">
|
||||
<span [innerHTML]="sdg.html"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-text-center">
|
||||
<img [src]="'assets/common-assets/sdg/icons/g' + sdg.code + '.png'" alt="">
|
||||
</div>
|
||||
<div class="uk-text-center uk-padding-small uk-background-default" style="border-radius: 0 0 4px 4px;">
|
||||
<span class="uk-text-large uk-text-bold uk-margin-small-bottom">{{sdg.number == null ? '0' : sdg.number | number}}</span>
|
||||
<p class="uk-text-small uk-text-uppercase uk-margin-remove">{{openaireEntities.RESULTS}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,30 @@
|
|||
@import (reference) "~src/assets/openaire-theme/less/_import-variables";
|
||||
|
||||
@sdgs: #E6233D, #DF9F00, #19A220, #D70023, #FF0B00, #00BFE8, #FFC300, #B10240, #FF5D00,
|
||||
#F50D86, #FF8A00, #CA8A03, #2B772B, #0098DF, #00B91C, #0069A2, #1C336A;
|
||||
|
||||
custom-sdg-dot:after {
|
||||
content: "";
|
||||
background-image: url("~src/assets/common-assets/sdg/sdg-dot-img.svg");
|
||||
display: inline-block;
|
||||
background-size: 100% 100%;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.sdg-card {
|
||||
width: 265px;
|
||||
height: 255px;
|
||||
|
||||
img {
|
||||
height: @global-control-height;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
each(@sdgs, {
|
||||
&.sdg-@{index} {
|
||||
background-color: @value !important;
|
||||
}
|
||||
})
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
import {HttpClient} from "@angular/common/http";
|
||||
import {Component, Input, OnDestroy, OnInit} from "@angular/core";
|
||||
import {Subscription} from "rxjs";
|
||||
import {Breadcrumb} from "../utils/breadcrumbs/breadcrumbs.component";
|
||||
import {EnvProperties} from "../utils/properties/env-properties";
|
||||
import {properties} from "src/environments/environment";
|
||||
import {RefineFieldResultsService} from "../services/refineFieldResults.service";
|
||||
import {OpenaireEntities} from "../utils/properties/searchFields";
|
||||
import {StringUtils} from "../utils/string-utils.class";
|
||||
import {Router} from '@angular/router';
|
||||
import {Meta, Title} from "@angular/platform-browser";
|
||||
import {SEOService} from "../sharedComponents/SEO/SEO.service";
|
||||
import {PiwikService} from "../utils/piwik/piwik.service";
|
||||
|
||||
@Component({
|
||||
selector: 'sdg',
|
||||
templateUrl: 'sdg.component.html',
|
||||
styleUrls: ['sdg.component.less']
|
||||
})
|
||||
export class SdgComponent implements OnInit, OnDestroy {
|
||||
public url: string = null;
|
||||
public pageTitle: string = "OpenAIRE | Sustainable Development Goals";
|
||||
public pageDescription: string = "Laying the foundation for new approaches and solutions. 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.";
|
||||
@Input() piwikSiteId = null;
|
||||
|
||||
private sdgs: any = [];
|
||||
private sdgsResearchOutcomes: any = [];
|
||||
public displayedSdgs: any = [];
|
||||
|
||||
public loading: boolean;
|
||||
properties: EnvProperties = properties;
|
||||
openaireEntities = OpenaireEntities;
|
||||
@Input() customFilter = null;
|
||||
public breadcrumbs: Breadcrumb[] = [{name: 'home', route: '/'}, {name: 'Sustainable Development Goals'}];
|
||||
|
||||
subscriptions: Subscription[] = [];
|
||||
|
||||
constructor(
|
||||
private httpClient: HttpClient, private refineFieldResultsService: RefineFieldResultsService,
|
||||
private _router: Router,
|
||||
private _meta: Meta,
|
||||
private _title: Title,
|
||||
private seoService: SEOService,
|
||||
private _piwikService: PiwikService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.loading = true;
|
||||
if (this.properties.enablePiwikTrack && (typeof document !== 'undefined')) {
|
||||
this.subscriptions.push(this._piwikService.trackView(this.properties, this.pageTitle, this.piwikSiteId).subscribe());
|
||||
}
|
||||
this.url = this.properties.domain + this.properties.baseLink + this._router.url;
|
||||
this.seoService.createLinkForCanonicalURL(this.url);
|
||||
this.updateUrl(this.url);
|
||||
this.updateTitle(this.pageTitle);
|
||||
this.updateDescription(this.pageDescription);
|
||||
this.httpClient.get(properties.domain+'/assets/common-assets/vocabulary/sdg.json').subscribe(data => {
|
||||
this.sdgs = data['sdg'];
|
||||
});
|
||||
let refineParams = null;
|
||||
if(this.customFilter) {
|
||||
let refineValue = StringUtils.URIEncode(this.customFilter.queryFieldName + " exact " + StringUtils.quote((this.customFilter.valueId)));
|
||||
refineParams = '&fq=' + refineValue;
|
||||
}
|
||||
this.refineFieldResultsService.getRefineFieldsResultsByEntityName(['sdg'], 'result', this.properties, refineParams).subscribe(data => {
|
||||
this.sdgsResearchOutcomes = data[1][0].values;
|
||||
let merged =[];
|
||||
for(let i=0; i<this.sdgs.length; i++){
|
||||
merged.push({
|
||||
...this.sdgs[i],
|
||||
...(this.sdgsResearchOutcomes.find((innerItem) => innerItem.id === this.sdgs[i].id))
|
||||
});
|
||||
}
|
||||
this.displayedSdgs = merged;
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnDestroy() {
|
||||
for (let sub of this.subscriptions) {
|
||||
sub.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
public urlEncodeAndQuote(str: string): string {
|
||||
return StringUtils.quote(StringUtils.URIEncode(str));
|
||||
}
|
||||
|
||||
private updateUrl(url: string) {
|
||||
this._meta.updateTag({content: url}, "property='og:url'");
|
||||
}
|
||||
|
||||
private updateTitle(title: string) {
|
||||
var _title = ((title.length > 50) ? title.substring(0, 50) : title);
|
||||
this._title.setTitle(_title);
|
||||
this._meta.updateTag({content: _title}, "property='og:title'");
|
||||
}
|
||||
|
||||
private updateDescription(description: string) {
|
||||
this._meta.updateTag({content: description}, "name='description'");
|
||||
this._meta.updateTag({content: description}, "property='og:description'");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import {CommonModule} from "@angular/common";
|
||||
import {NgModule} from "@angular/core";
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {PreviousRouteRecorder} from "../utils/piwik/previousRouteRecorder.guard";
|
||||
import {BreadcrumbsModule} from "../utils/breadcrumbs/breadcrumbs.module";
|
||||
import {RefineFieldResultsServiceModule} from "../services/refineFieldResultsService.module";
|
||||
import {LoadingModule} from "../utils/loading/loading.module";
|
||||
import {Schema2jsonldModule} from "../sharedComponents/schema2jsonld/schema2jsonld.module";
|
||||
import {SEOServiceModule} from "../sharedComponents/SEO/SEOService.module";
|
||||
import {PiwikService} from "../utils/piwik/piwik.service";
|
||||
|
||||
import {SdgRoutingModule} from './sdg-routing.module';
|
||||
import {SdgComponent} from './sdg.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule, FormsModule, RouterModule,
|
||||
SdgRoutingModule, BreadcrumbsModule, RefineFieldResultsServiceModule,
|
||||
LoadingModule, Schema2jsonldModule, SEOServiceModule
|
||||
],
|
||||
declarations: [
|
||||
SdgComponent
|
||||
],
|
||||
providers: [
|
||||
PreviousRouteRecorder, PiwikService
|
||||
],
|
||||
exports: [
|
||||
SdgComponent
|
||||
]
|
||||
})
|
||||
export class SdgModule {
|
||||
|
||||
}
|
|
@ -315,6 +315,7 @@ export class SearchResearchResultsService {
|
|||
}
|
||||
|
||||
result['id'] = Array.isArray(data) ? data[i]['result']['header']['dri:objIdentifier'] : data['result']['header']['dri:objIdentifier'];
|
||||
result['objId'] = result['id'];
|
||||
let canId = ParsingFunctions.parseRelCanonicalId(Array.isArray(data) ? data[i] : data, "result");
|
||||
if (canId) {
|
||||
result['id'] = canId;
|
||||
|
|
|
@ -4,6 +4,7 @@ export class SearchResult {
|
|||
title: ResultTitle;
|
||||
id: string;
|
||||
relcanId: string;
|
||||
objId: string;
|
||||
DOIs: string[]=[];
|
||||
identifiers: Map<string, string[]>;
|
||||
measure: Array<string>;
|
||||
|
|
|
@ -346,7 +346,7 @@
|
|||
Popularity: Citation-based measure reflecting the current impact.
|
||||
</div>
|
||||
<div>
|
||||
<a title="Link to Bip!Finder" class="uk-float-right" target="_blank" href="https://bip.imis.athena-innovation.gr/site/details?id={{result.id}}">
|
||||
<a title="Link to Bip!Finder" class="uk-float-right" target="_blank" href="https://bip.imis.athena-innovation.gr/site/details?id={{result.objId}}">
|
||||
View more details
|
||||
</a>
|
||||
</div>
|
||||
|
@ -385,7 +385,7 @@
|
|||
Influence: Citation-based measure reflecting the total impact.
|
||||
</div>
|
||||
<div>
|
||||
<a title="Link to Bip!Finder" class=" uk-float-right" target="_blank" href="https://bip.imis.athena-innovation.gr/site/details?id={{result.id}}">
|
||||
<a title="Link to Bip!Finder" class=" uk-float-right" target="_blank" href="https://bip.imis.athena-innovation.gr/site/details?id={{result.objId}}">
|
||||
View more details
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -72,6 +72,7 @@ export interface Organization {
|
|||
}
|
||||
|
||||
export class ResultPreview {
|
||||
objId: string;
|
||||
relcanId: string;
|
||||
id: string;
|
||||
title: string;
|
||||
|
@ -146,6 +147,7 @@ export class ResultPreview {
|
|||
let resultPreview: ResultPreview = new ResultPreview();
|
||||
resultPreview.id = result.id;
|
||||
resultPreview.relcanId = result.relcanId;
|
||||
resultPreview.objId = result.objId;
|
||||
resultPreview.title = result.title.name;
|
||||
resultPreview.accessMode = result.title.accessMode;
|
||||
// resultPreview.sc39 = result.title.sc39;
|
||||
|
|
Loading…
Reference in New Issue