2022-11-03 11:15:13 +01:00
import { HttpClient } from "@angular/common/http" ;
2022-11-03 14:55:10 +01:00
import { ChangeDetectorRef , Component , ElementRef , Input , OnDestroy , OnInit , ViewChild } from "@angular/core" ;
2022-11-03 11:15:13 +01:00
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." ;
2022-11-03 14:55:10 +01:00
@Input ( ) piwikSiteId = null ;
2022-11-03 11:15:13 +01:00
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' ) ) {
2022-11-03 14:55:10 +01:00
this . subscriptions . push ( this . _piwikService . trackView ( this . properties , this . pageTitle , this . piwikSiteId ) . subscribe ( ) ) ;
2022-11-03 11:15:13 +01:00
}
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'" ) ;
}
}