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) => `${matchedValue}`); } 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'"); } }