diff --git a/claims/claim-utils/displayClaims/displayClaims.component.ts b/claims/claim-utils/displayClaims/displayClaims.component.ts index 6405ceca..cfdea924 100644 --- a/claims/claim-utils/displayClaims/displayClaims.component.ts +++ b/claims/claim-utils/displayClaims/displayClaims.component.ts @@ -34,7 +34,7 @@ private seoService: SEOService) { }); this.sub = this.route.queryParams.subscribe(params => { - this.seoService.createLinkForCanonicalURL(false); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url, false); if( this.myClaims){ this.fetchBy = "User"; diff --git a/claims/directLinking/directLinking.component.ts b/claims/directLinking/directLinking.component.ts index 99969942..ca1df929 100644 --- a/claims/directLinking/directLinking.component.ts +++ b/claims/directLinking/directLinking.component.ts @@ -51,7 +51,6 @@ export class DirectLinkingComponent { this._meta.updateTag({content:title},"property='og:title'"); this._title.setTitle(title); - this.seoService.createLinkForCanonicalURL(false); } ngOnInit() { @@ -59,6 +58,7 @@ export class DirectLinkingComponent { .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; this.url = data.envSpecific.baseLink+this._router.url; + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url, false); }); diff --git a/claims/linking/linkingGeneric.component.ts b/claims/linking/linkingGeneric.component.ts index e1b38c4e..e31cb1dd 100644 --- a/claims/linking/linkingGeneric.component.ts +++ b/claims/linking/linkingGeneric.component.ts @@ -53,7 +53,6 @@ export class LinkingGenericComponent { var title = "OpenAIRE | Linking"; this._meta.updateTag({content:title},"property='og:title'"); this._title.setTitle(title); - this.seoService.createLinkForCanonicalURL(false); } @@ -62,6 +61,7 @@ export class LinkingGenericComponent { .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; this.url = data.envSpecific.baseLink+this._router.url; + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url, false); }); if( typeof localStorage !== 'undefined') { diff --git a/deposit/datasets/depositBySubjectResult.component.ts b/deposit/datasets/depositBySubjectResult.component.ts index 23443ce4..6f3f61e0 100644 --- a/deposit/datasets/depositBySubjectResult.component.ts +++ b/deposit/datasets/depositBySubjectResult.component.ts @@ -70,7 +70,7 @@ export class DepositBySubjectResultComponent { this.updateTitle(title); this.updateDescription(description); - this.seoService.createLinkForCanonicalURL(false); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url, false); } diff --git a/deposit/deposit.component.ts b/deposit/deposit.component.ts index a4ac92ba..25999438 100644 --- a/deposit/deposit.component.ts +++ b/deposit/deposit.component.ts @@ -51,7 +51,7 @@ export class DepositComponent { var title = "Deposit "+this.requestFor; var description = "Openaire, repositories, open access, content provider, compatibility, organization, deposit "+ this.requestFor; - this.seoService.createLinkForCanonicalURL(false); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url, false); this.updateTitle(title); this.updateDescription(description); } diff --git a/deposit/depositResult.component.ts b/deposit/depositResult.component.ts index 41a22c1a..2bf953f2 100644 --- a/deposit/depositResult.component.ts +++ b/deposit/depositResult.component.ts @@ -189,7 +189,6 @@ export class DepositResultComponent { var description = "Deposit "+this.requestFor; var title = "Openaire, repositories, open access, content provider, compatibility, organization, deposit "+ this.requestFor; - this.seoService.createLinkForCanonicalURL(false); this.updateTitle(title); this.updateDescription(description); @@ -199,6 +198,7 @@ export class DepositResultComponent { this.route.data .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url, false); this.updateUrl(data.envSpecific.baseLink+this._router.url); this.url = data.envSpecific.baseLink+this._router.url; diff --git a/landingPages/dataProvider/dataProvider.component.ts b/landingPages/dataProvider/dataProvider.component.ts index abbe7f2f..54e91a79 100644 --- a/landingPages/dataProvider/dataProvider.component.ts +++ b/landingPages/dataProvider/dataProvider.component.ts @@ -131,12 +131,12 @@ export class DataProviderComponent { .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; this.updateUrl(data.envSpecific.baseLink+this._router.url); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url); }); this.sub = this.route.queryParams.subscribe(data => { this.updateTitle("Content provider"); this.updateDescription(""); - this.seoService.createLinkForCanonicalURL(); this.datasourceId = data['datasourceId']; if(this.datasourceId){ this.getDataProviderInfo(this.datasourceId); diff --git a/landingPages/dataset/dataset.component.ts b/landingPages/dataset/dataset.component.ts index ec87a119..89ff9819 100644 --- a/landingPages/dataset/dataset.component.ts +++ b/landingPages/dataset/dataset.component.ts @@ -69,13 +69,13 @@ export class DatasetComponent { .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; this.updateUrl(data.envSpecific.baseLink+this._router.url); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url); }); this.sub = this.route.queryParams.subscribe(params => { this.datasetInfo = null; this.updateTitle("Dataset"); this.updateDescription(""); - this.seoService.createLinkForCanonicalURL(); this.datasetId = params['datasetId']; console.info("Id is :"+this.datasetId); @@ -133,7 +133,7 @@ export class DatasetComponent { */ if(this.datasetInfo.title){ this.updateTitle(this.datasetInfo.title); - this.updateDescription((this.datasetInfo.description?(this.datasetInfo.description):(","+this.datasetInfo.title))); + this.updateDescription((this.datasetInfo.description?(this.datasetInfo.description):(","+this.datasetInfo.title))); } if(this.properties.enablePiwikTrack && (typeof document !== 'undefined')){ this.piwiksub = this._piwikService.trackView(this.properties, this.datasetInfo.title/*.name*/, this.piwikSiteId).subscribe(); diff --git a/landingPages/htmlProjectReport/htmlProjectReport.component.ts b/landingPages/htmlProjectReport/htmlProjectReport.component.ts index 4c43c16c..2211b660 100644 --- a/landingPages/htmlProjectReport/htmlProjectReport.component.ts +++ b/landingPages/htmlProjectReport/htmlProjectReport.component.ts @@ -79,6 +79,7 @@ export class HtmlProjectReportComponent{ .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; this.updateUrl(data.envSpecific.baseLink+this._router.url); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url); }); this.sub = this.route.queryParams.subscribe(params => { @@ -106,7 +107,7 @@ export class HtmlProjectReportComponent{ var description = "project, project "+ this.resultsType +" report, funding, open access, publications, research data, software, other research products"; this.updateTitle(title); this.updateDescription(description); - this.seoService.createLinkForCanonicalURL(); + } else { this.showLoading = false; diff --git a/landingPages/organization/organization.component.ts b/landingPages/organization/organization.component.ts index 95288ba2..039eceec 100644 --- a/landingPages/organization/organization.component.ts +++ b/landingPages/organization/organization.component.ts @@ -124,14 +124,13 @@ export class OrganizationComponent { .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; this.updateUrl(data.envSpecific.baseLink+this._router.url); - + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url); }); console.info('organization init'); this.sub = this.route.queryParams.subscribe(params => { this.organizationInfo=null; this.updateTitle("Organization"); this.updateDescription(""); - this.seoService.createLinkForCanonicalURL(); this.projectsClicked = false; this.organizationId = params['organizationId']; diff --git a/landingPages/orp/orp.component.ts b/landingPages/orp/orp.component.ts index aa7952ab..faa0c66c 100644 --- a/landingPages/orp/orp.component.ts +++ b/landingPages/orp/orp.component.ts @@ -69,13 +69,13 @@ export class OrpComponent { .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; this.updateUrl(data.envSpecific.baseLink+this._router.url); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url); }); this.sub = this.route.queryParams.subscribe(params => { this.orpInfo = null; this.updateTitle("Other Research Product"); this.updateDescription(""); - this.seoService.createLinkForCanonicalURL(); this.orpId = params['orpId']; console.info("Id is :"+this.orpId); diff --git a/landingPages/project/project.component.ts b/landingPages/project/project.component.ts index f858a577..c75ae479 100644 --- a/landingPages/project/project.component.ts +++ b/landingPages/project/project.component.ts @@ -135,9 +135,8 @@ properties:EnvProperties; var description = ""; this.updateTitle(title); - this.updateDescription(description); - this.seoService.createLinkForCanonicalURL(); - + this.updateDescription(description); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url); this.projectId = params['projectId']; var grantId = params['grantId']; var funder = params['funder']; diff --git a/landingPages/publication/publication.component.ts b/landingPages/publication/publication.component.ts index 96277c34..086bc7c7 100644 --- a/landingPages/publication/publication.component.ts +++ b/landingPages/publication/publication.component.ts @@ -91,8 +91,7 @@ export class PublicationComponent { this.publicationInfo = null; this.updateTitle("Publication"); this.updateDescription(""); - this.seoService.createLinkForCanonicalURL(); - + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url); this.articleId = data['articleId']; console.info("Article id is :"+this.articleId); diff --git a/landingPages/software/software.component.ts b/landingPages/software/software.component.ts index 616c08da..cfa2cc2e 100644 --- a/landingPages/software/software.component.ts +++ b/landingPages/software/software.component.ts @@ -68,14 +68,14 @@ export class SoftwareComponent { .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; this.updateUrl(data.envSpecific.baseLink+this._router.url); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url); }); this.sub = this.route.queryParams.subscribe(params => { this.softwareInfo = null; this.updateTitle("Software"); this.updateDescription("Software, search, open access"); - this.seoService.createLinkForCanonicalURL(); - + this.softwareId = params['softwareId']; console.info("Id is :"+this.softwareId); diff --git a/searchPages/find/search.component.ts b/searchPages/find/search.component.ts index f84a04e0..975551a1 100644 --- a/searchPages/find/search.component.ts +++ b/searchPages/find/search.component.ts @@ -145,7 +145,7 @@ public subPub;public subData; public subSoftware; public subOrps; public subProj this._meta.updateTag({content:description},"property='og:description'"); this._meta.updateTag({content:title},"property='og:title'"); this._meta.updateTag({content:url},"property='og:url'"); - this.seoService.createLinkForCanonicalURL(false); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this._router.url,false); if(this.properties.enablePiwikTrack && (typeof document !== 'undefined')){ this.piwiksub = this._piwikService.trackView(this.properties, "OpenAIRE |Search publications, research data, projects...", this.piwikSiteId).subscribe(); diff --git a/searchPages/searchUtils/advancedSearchPage.component.ts b/searchPages/searchUtils/advancedSearchPage.component.ts index ce9929d4..9d4be096 100644 --- a/searchPages/searchUtils/advancedSearchPage.component.ts +++ b/searchPages/searchUtils/advancedSearchPage.component.ts @@ -94,7 +94,7 @@ export class AdvancedSearchPageComponent { this.searchUtils.baseUrl = "/" + this.searchUtils.baseUrl; this.updateBaseUrlWithParameters(); - this.seoService.createLinkForCanonicalURL(false); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this.router.url,false); } diff --git a/searchPages/searchUtils/searchPage.component.ts b/searchPages/searchUtils/searchPage.component.ts index 19d92800..4fc1742d 100644 --- a/searchPages/searchUtils/searchPage.component.ts +++ b/searchPages/searchUtils/searchPage.component.ts @@ -105,7 +105,7 @@ export class SearchPageComponent { this.updateTitle(this.pageTitle); var description = "Openaire, search, repositories, open access, type, content provider, funder, project, " + this.type + "," +this.pageTitle; this.updateDescription(description); - this.seoService.createLinkForCanonicalURL(false); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this.router.url,false); } ngAfterViewChecked(){ diff --git a/searchPages/searchUtils/searchPageTableView.component.ts b/searchPages/searchUtils/searchPageTableView.component.ts index 82b7ad54..ae94217e 100644 --- a/searchPages/searchUtils/searchPageTableView.component.ts +++ b/searchPages/searchUtils/searchPageTableView.component.ts @@ -3,7 +3,7 @@ import {ViewChild, Output} from '@angular/core'; import {EventEmitter, ViewEncapsulation} from '@angular/core'; import {OnInit, AfterViewInit} from '@angular/core'; import {Location} from '@angular/common'; -import {ActivatedRoute} from '@angular/router'; +import {ActivatedRoute, Router} from '@angular/router'; import {Title, Meta} from '@angular/platform-browser'; import {Observable} from 'rxjs/Observable'; @@ -79,6 +79,7 @@ export class SearchPageTableViewComponent implements OnInit, AfterViewInit { properties:EnvProperties; url = null; constructor (private route: ActivatedRoute, + private router: Router, private location: Location, private _meta: Meta, private _title: Title, @@ -108,7 +109,7 @@ export class SearchPageTableViewComponent implements OnInit, AfterViewInit { this.updateTitle(this.pageTitle); var description = "Openaire, search, repositories, open access, type, content provider, funder, project, " + this.type + "," +this.pageTitle; this.updateDescription(description); - this.seoService.createLinkForCanonicalURL(false); + this.seoService.createLinkForCanonicalURL(this.properties.baseLink+this.router.url,false); } diff --git a/sharedComponents/SEO/SEO.service.ts b/sharedComponents/SEO/SEO.service.ts index d7ea2d7a..db3b3eb6 100644 --- a/sharedComponents/SEO/SEO.service.ts +++ b/sharedComponents/SEO/SEO.service.ts @@ -1,30 +1,25 @@ import { Injectable, Inject } from '@angular/core'; import { DOCUMENT } from '@angular/common'; +import { Optional, RendererFactory2, ViewEncapsulation } from '@angular/core'; -// @Injectable({ -// providedIn: 'root' -// }) @Injectable() export class SEOService { - constructor( @Inject(DOCUMENT) private doc) { + constructor( @Inject(DOCUMENT) private doc, + private rendererFactory: RendererFactory2, + @Inject(DOCUMENT) private document) { } - createLinkForCanonicalURL(addParameters:boolean=true) { - var url = ""; - if(this.doc ){ + createLinkForCanonicalURL(url:string, addParameters:boolean=true) { + if(this.doc && (typeof this.doc.getElementById === "function" || typeof this.doc.createElement === "function") ){ if(addParameters || !this.doc.URL || this.doc.URL.indexOf("?") == -1){ url = this.doc.URL; }else{ url = this.doc.URL.substring(0,this.doc.URL.indexOf("?")); } - console.log("createLinkForCanonicalURL"); - if (typeof this.doc.getElementById === "function") { let currentLink: HTMLLinkElement = this.doc.getElementById("relcan"); if(currentLink ){ currentLink.setAttribute('href', url); - console.log("update canonical url:" + url); - return ; } } @@ -33,12 +28,109 @@ export class SEOService { link.setAttribute('id', 'relcan'); link.setAttribute('rel', 'canonical'); this.doc.head.appendChild(link); - console.log("create new canonical url:" + url); - link.setAttribute('href', url); } - } + }else{ + try { + const renderer = this.rendererFactory.createRenderer(this.document, { + id: '-1', + encapsulation: ViewEncapsulation.None, + styles: [], + data: {} + }); + + const link = renderer.createElement('link'); + const head = this.document.head; + + if (head === null) { + throw new Error(' not found within DOCUMENT.'); + } + renderer.setAttribute(link, "rel", "canonical"); + renderer.setAttribute(link, "href", (addParameters)?url:this.doc.URL.split("?")[0]); + renderer.setAttribute(link, "id", "relcan"); + // [TODO]: get them to update the existing one (if it exists) ? + renderer.appendChild(head, link); + } catch (e) { + console.error('Error within linkService : ', e); + } + } + } } + +/* + * -- LinkService -- [Temporary] + * @MarkPieszak + * + * Similar to Meta service but made to handle creation for SEO purposes + * -- NOTE: Soon there will be an overall DocumentService within Angular that handles Meta/Link everything + */ +// +// import { Injectable, Optional, RendererFactory2, ViewEncapsulation, Inject } from '@angular/core'; +// import { DOCUMENT } from '@angular/platform-browser'; +// +// @Injectable() +// export class LinkService { +// +// constructor( +// private rendererFactory: RendererFactory2, +// @Inject(DOCUMENT) private document +// ) { +// } + + /** + * Inject the State into the bottom of the + */ +// addTag(tag: LinkDefinition, forceCreation?: boolean) { +// +// try { +// const renderer = this.rendererFactory.createRenderer(this.document, { +// id: '-1', +// encapsulation: ViewEncapsulation.None, +// styles: [], +// data: {} +// }); +// +// const link = renderer.createElement('link'); +// const head = this.document.head; +// const selector = this._parseSelector(tag); +// +// if (head === null) { +// throw new Error(' not found within DOCUMENT.'); +// } +// +// Object.keys(tag).forEach((prop: string) => { +// return renderer.setAttribute(link, prop, tag[prop]); +// }); +// +// // [TODO]: get them to update the existing one (if it exists) ? +// renderer.appendChild(head, link); +// +// } catch (e) { +// console.error('Error within linkService : ', e); +// } +// } +// +// private _parseSelector(tag: LinkDefinition): string { +// // Possibly re-work this +// const attr: string = tag.rel ? 'rel' : 'hreflang'; +// return `${attr}="${tag[attr]}"`; +// } +// } + +export declare type LinkDefinition = { + charset?: string; + crossorigin?: string; + href?: string; + hreflang?: string; + media?: string; + rel?: string; + rev?: string; + sizes?: string; + target?: string; + type?: string; +} & { + [prop: string]: string; + };