[Library|Trunk]

SEO changes:
- ignore quick filter in search pages. don't add qf=true, the filter is NOT applied by default.
- add page in the canonical url
- keep order of params to have the same url in canonical no matter the order of the filters
- add prev/ next links

TimeOut interceptor: set it 3000 for server and 6000 for client



git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-services-library/trunk/ng-openaire-library/src/app@61019 d315682c-612b-4755-9ff5-7f18f6832af3
This commit is contained in:
argiro.kokogiannaki 2021-05-19 07:39:08 +00:00
parent 2e5ba2141a
commit eee822bdeb
5 changed files with 195 additions and 105 deletions

View File

@ -166,7 +166,7 @@ export class NewSearchPageComponent {
this.basicMetaDescription.push(this.pageTitle)
}
}
console.log("title " + this.pageTitle, this.basicMetaDescription)
// console.log("title " + this.pageTitle, this.basicMetaDescription)
this.updateMeta(this.pageTitle);
});
this.searchUtils.baseUrl = "/" + this.searchUtils.baseUrl;
@ -231,7 +231,7 @@ export class NewSearchPageComponent {
if(value.selected) {
filterArray.push(filterName + '"' + value.name + '"');
filtervalues.push(value.name);
filterURL += ((filterName.length == 0) ? ',' : '') + StringUtils.URIEncode('"' + value.id + '"' );
filterURL += ((filterName.length == 0) ? ',' : '') + StringUtils.URIEncode( '"' + StringUtils.URIEncode( value.id ) + '"');
filterName = "";
}
@ -244,8 +244,15 @@ export class NewSearchPageComponent {
this._meta.updateTag({content: this.metaDescription}, "name='description'");
this._meta.updateTag({content: this.metaDescription}, "property='og:description'");
this.updateTitle(title, (nonCanonicalizedPage ? filtervalues.join(" | ") + " | ": ""));
this.url = this.properties.domain + this.properties.baseLink + this.router.url.split('?')[0] + (nonCanonicalizedPage ? filterURL : "");
this.seoService.createLinkForCanonicalURL(this.url, true);
filterURL = (nonCanonicalizedPage ? filterURL : "");
this.url = this.properties.domain + this.properties.baseLink + this.router.url.split('?')[0] + filterURL;
this.seoService.createLinkForCanonicalURL(this.url + (this.searchUtils.page !=1?(filterURL.length > 0?'&':'?')+'page='+this.searchUtils.page:''), true);
this.seoService.createLinkForNextURL(this.url + (filterURL.length > 0 ? '&' : '?') + 'page=' + (this.searchUtils.page + 1), true);
if(this.searchUtils.page != 1) {
this.seoService.createLinkForPrevURL(this.url + (this.searchUtils.page !=2?(filterURL.length > 0?'&':'?')+'page='+(this.searchUtils.page - 1):'') , true);
}else{
this.seoService.removeLinkForPrevURL();
}
}
updateTitle(title: string, filters:string) {
@ -277,9 +284,9 @@ export class NewSearchPageComponent {
this.rangeFilters[i].selectedToValue = null;
}
this.selectedRangeFilters = 0;
if (this.quickFilter) {
this.removeValueFromQuickFilter();
}
// if (this.quickFilter) {
// this.removeValueFromQuickFilter();
// }
if(this.resultTypes) {
this.resultTypes.values = [];
}
@ -427,23 +434,23 @@ export class NewSearchPageComponent {
if(this.customFilter){
this.customFilter.selected = this.customFilter.queryFieldName == filter.filterId && values.indexOf(StringUtils.quote(this.customFilter.valueId)) != -1;
}
} else if (this.quickFilter && this.quickFilter.filterId == filter.filterId && this.quickFilter.selected) {
for (let filterValue of filter.values) {
if (filterValue.id == this.quickFilter.value) {
filterValue.selected = true;
filter.countSelectedValues++;
} else {
filterValue.selected = false;
}
}
// } else if (this.quickFilter && this.quickFilter.filterId == filter.filterId && this.quickFilter.selected) {
// for (let filterValue of filter.values) {
// if (filterValue.id == this.quickFilter.value) {
// filterValue.selected = true;
// filter.countSelectedValues++;
// } else {
// filterValue.selected = false;
// }
// }
} else {
for (let filterValue of filter.values) {
filterValue.selected = false;
}
}
if (this.quickFilter && filter.filterId == this.quickFilter.filterId) {
this.quickFilter.filter = filter;
}
// if (this.quickFilter && filter.filterId == this.quickFilter.filterId) {
// this.quickFilter.filter = filter;
// }
}
if (this.parameterNames.indexOf("cf") != -1 && this.parameterValues[this.parameterNames.indexOf("cf")] == "true") {
this.customFilter.selected = true;
@ -610,9 +617,9 @@ export class NewSearchPageComponent {
if(filter.filterType == "radio"){
filter.radioValue = "";
}
if (this.quickFilter && this.quickFilter.filterId == filter.filterId) {
this.removeValueFromQuickFilter();
}
// if (this.quickFilter && this.quickFilter.filterId == filter.filterId) {
// this.removeValueFromQuickFilter();
// }
this.goTo(1);
}
public openRemoveCustomFilterModal() {
@ -648,9 +655,9 @@ export class NewSearchPageComponent {
}
filterChanged($event) {
if (this.quickFilter && this.quickFilter.filter) {
/* if (this.quickFilter && this.quickFilter.filter) {
this.removeValueFromQuickFilter();
}
}*/
this.goTo(1);
}
@ -658,7 +665,7 @@ export class NewSearchPageComponent {
/**
* if there is a change in the values of the quick filter, this function has to be run, to also update the quickFilter
*/
removeValueFromQuickFilter() {
/* removeValueFromQuickFilter() {
if (this.quickFilter.filter.countSelectedValues == 0) {
this.quickFilter.selected = false;
} else {
@ -668,7 +675,7 @@ export class NewSearchPageComponent {
}
this.quickFilter.selected = (isQuickEnabled && this.quickFilter.filter.countSelectedValues == 1);
}
}
}*/
/**
* Set selected the value of the custom filter.
@ -1031,7 +1038,7 @@ export class NewSearchPageComponent {
allFqs += "&fq=" + StringUtils.URIEncode(this.customFilter.queryFieldName + " exact " + StringUtils.quote((this.customFilter.valueId)));
}
if (this.quickFilter && this.entityType == "result") {
/* if (this.quickFilter && this.entityType == "result") {
if((URLparams[this.quickFilter.filterId] == undefined && URLparams["qf"] == undefined) || URLparams["qf"] == "true"
|| ((URLparams[this.quickFilter.filterId] != undefined && StringUtils.URIDecode(URLparams[this.quickFilter.filterId]).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1).indexOf(StringUtils.quote(this.quickFilter.value)) != -1))) {
this.quickFilter.selected = true;
@ -1043,7 +1050,7 @@ export class NewSearchPageComponent {
// ||( URLparams[this.quickFilter.filterId] == undefined && URLparams["qf"] == "true")) {
allFqs += "&fq=resultbestaccessright exact " + StringUtils.quote(this.quickFilter.value);
}
}
}*/
if (this.entityType == "result") {
if (URLparams["type"]) {
@ -1264,9 +1271,11 @@ public static createRangeFilterQuery(rangeField,selectedFromValue, selectedToVal
this.parameterValues.splice(0, this.parameterValues.length);
for (var i = 0; i < this.selectedFields.length; i++) {
//default operator is and
this.parameterNames.push("f"+i);
this.parameterValues.push(this.selectedFields[i].id + (this.selectedFields[i].operatorId!='and'?(","+this.selectedFields[i].operatorId):''));
this.parameterNames.push("fv"+i);
if((this.selectedFields[i].value && this.selectedFields[i].value.length > 0) || this.selectedFields[i].type == "date") {
this.parameterNames.push("f" + i);
this.parameterValues.push(this.selectedFields[i].id + (this.selectedFields[i].operatorId != 'and' ? ("," + this.selectedFields[i].operatorId) : ''));
this.parameterNames.push("fv" + i);
}
if (this.selectedFields[i].type == "date") {
if (this.selectedFields[i].dateValue.type == "range") {
@ -1275,29 +1284,48 @@ public static createRangeFilterQuery(rangeField,selectedFromValue, selectedToVal
this.parameterValues.push(StringUtils.URIEncode(this.selectedFields[i].dateValue.type));
}
} else {
} else if(this.selectedFields[i].value && this.selectedFields[i].value.length > 0) {
// console.log(this.selectedFields[i].value +" " + StringUtils.URIEncode(this.selectedFields[i].value))
this.parameterValues.push(StringUtils.URIEncode(this.selectedFields[i].value));
}
}
if (includePage) {
if (includePage && this.searchUtils.page != 1) {
this.parameterNames.push("page");
this.parameterValues.push("" + this.searchUtils.page);
}
//if (this.searchUtils.size != this.resultsPerPage) {
if (this.resultsPerPageChanged) {
if (this.resultsPerPageChanged && this.searchUtils.size != this.resultsPerPageChanged) {
this.parameterNames.push("size");
//this.parameterValues.push("" + this.searchUtils.size);
this.parameterValues.push("" + this.resultsPerPageChanged);
}
//if (this.sort && this.searchUtils.sortBy) {
if (this.sort && this.sortByChanged) {
if (this.sort && this.sortedByChanged && this.sortedByChanged.length > 0) {
this.parameterNames.push("sortBy");
//this.parameterValues.push(this.searchUtils.sortBy);
this.parameterValues.push(this.sortedByChanged);
}
if (this.resultTypes && (this.entityType == 'publication' || this.entityType == 'dataset' || this.entityType == 'software' || this.entityType == 'other' || this.entityType == "result")) {
let values = [];
for(let value of this.resultTypes.values){
if(value.selected) {
values.push(value.id);
}
}
this.selectedTypesNum = 0;
if (values.length > 0 && values.length != 4) {
this.parameterNames.push("type");
this.parameterValues.push(values.join(","));
this.selectedTypesNum = values.length;
}
//
/* if(this.quickFilter) {
this.parameterNames.push("qf");
this.parameterValues.push("" + this.quickFilter.selected);
}*/
}
for (let filter of filters) {
var filterLimits = "";
if (filter.countSelectedValues > 0) {
@ -1337,24 +1365,7 @@ public static createRangeFilterQuery(rangeField,selectedFromValue, selectedToVal
this.parameterValues.push(this.searchUtils.keyword);
}
if (this.resultTypes && (this.entityType == 'publication' || this.entityType == 'dataset' || this.entityType == 'software' || this.entityType == 'other' || this.entityType == "result")) {
let values = [];
for(let value of this.resultTypes.values){
if(value.selected) {
values.push(value.id);
}
}
this.selectedTypesNum = 0;
if (values.length > 0 && values.length != 4) {
this.parameterNames.push("type");
this.parameterValues.push(values.join(","));
this.selectedTypesNum = values.length;
}
if(this.quickFilter) {
this.parameterNames.push("qf");
this.parameterValues.push("" + this.quickFilter.selected);
}
}
if(this.customFilterEnabled){
this.parameterNames.push("cf");
this.parameterValues.push("true");
@ -1404,7 +1415,7 @@ public static createRangeFilterQuery(rangeField,selectedFromValue, selectedToVal
}
}
if (this.quickFilter) {
/* if (this.quickFilter) {
if (this.entityType == "result" && (URLparams[this.quickFilter.filterId] == undefined) && (URLparams["qf"] == undefined || URLparams["qf"] == "true")) {
let filter = new Filter();
filter.title = fields.getFieldName(this.quickFilter.filterId, this.entityType);
@ -1419,7 +1430,7 @@ public static createRangeFilterQuery(rangeField,selectedFromValue, selectedToVal
filter.countSelectedValues = 1;
filters.push(filter)
}
}
}*/
if ((this.entityType == 'publication' || this.entityType == 'dataset' || this.entityType == 'software' || this.entityType == 'other' || this.entityType == "result")) {
this.resultTypes = {values:[],filterId:"type", countSelectedValues: 0, filterType: 'checkbox', originalFilterId: "", valueIsExact: true, title: "Result Types",filterOperator:"or"};
if (URLparams["type"]) {

View File

@ -10,6 +10,7 @@ import {
import { Filter, Value} from './searchHelperClasses.class';
import {ActivatedRoute, Router} from "@angular/router";
import 'rxjs/add/operator/filter';
import {SearchFields} from "../../utils/properties/searchFields";
@Component({
selector: 'search-filter',
templateUrl: 'searchFilter.component.html'
@ -33,6 +34,7 @@ export class SearchFilterComponent implements OnInit, OnChanges{
keyword = "";
sortBy = "name";
queryParams = {};
paramPosition = 0;
@Input() actionRoute:boolean = false;
@Input() quickFilter: { filter: Filter, selected: boolean, filterId: string, value: string };
sub;
@ -48,6 +50,7 @@ export class SearchFilterComponent implements OnInit, OnChanges{
ngOnInit() {
this.sub = this.route.queryParams.subscribe(params => {
this.queryParams = Object.assign({}, params);
this.paramPosition = SearchFields.getParameterOrder(this.filter.filterId, this.getEntries(params));
});
this.filter.values = this.filter.values.filter(value => !value.name.toLowerCase().includes('unknown') && !value.name.toLowerCase().includes('not available'));
if(this.filter.filterType == "radio"){
@ -243,12 +246,12 @@ export class SearchFilterComponent implements OnInit, OnChanges{
}
getParams(filter:Filter, value:Value){
let params = Object.assign({}, this.queryParams);
let qf=false;
/* let qf=false;
if(this.quickFilter && this.quickFilter.filterId == filter.filterId && this.quickFilter.selected && value.id == this.quickFilter.value){
params['qf']="false";
qf=true;
}
if(params[filter.filterId] && this.checkIfValueIndexOf(params[filter.filterId].split(','),value.id)==-1 && !qf) {
}*/
if(params[filter.filterId] && this.checkIfValueIndexOf(params[filter.filterId].split(','),value.id)==-1 /*&& !qf*/) {
//has other values of this filter --> add this value
params[filter.filterId] = params[filter.filterId] + ',' + '"' + encodeURIComponent(value.id) + '"';
}else if(params[filter.filterId] && this.checkIfValueIndexOf(params[filter.filterId].split(','),value.id)!=-1) {
@ -260,9 +263,13 @@ export class SearchFilterComponent implements OnInit, OnChanges{
if(values.length == 0){
delete params[filter.filterId];
}
} else if(!qf){
} else /*if(!qf)*/{
//has no filter, no value --> add the value
params[filter.filterId] = '"' + encodeURIComponent(value.id) + '"' ;
//check the order
let keyValues = this.getEntries(params);
keyValues.splice(this.paramPosition,0, [filter.filterId,'"' + encodeURIComponent(value.id) + '"']); // insert key value at paramPosition.
params = keyValues.reduce((o, key) => Object.assign(o, {[key[0]]:key[1]}), {});
// params[filter.filterId] = '"' + encodeURIComponent(value.id) + '"' ;
}
delete params['page'];
return params;
@ -277,4 +284,17 @@ export class SearchFilterComponent implements OnInit, OnChanges{
}
return -1;
}
getEntries(obj) {
if (!Object.entries) {
var ownProps = Object.keys(obj),
i = ownProps.length,
resArray = new Array(i); // preallocate the Array
while (i--)
resArray[i] = [ownProps[i], obj[ownProps[i]]];
return resArray;
}else{
return Object.entries(obj);
}
}
}

View File

@ -9,52 +9,88 @@ export class SEOService {
@Inject(DOCUMENT) private document) {
}
createLinkForCanonicalURL(url:string, addParameters:boolean=true) {
if(this.doc && (typeof this.doc.getElementById === "function" || typeof this.doc.createElement === "function") ){
if(!addParameters && url && url.indexOf("?") != -1){
url = url.substring(0,url.indexOf("?"));
}
if (typeof this.doc.getElementById === "function") {
let currentLink: HTMLLinkElement = this.doc.getElementById("relcan");
if(currentLink ){
currentLink.setAttribute('href', url);
return ;
}
createLinkForCanonicalURL(url:string, addParameters:boolean=true) {
this.createLink(url,"relcan", "canonical", addParameters)
}
createLinkForCanonicalSearchURL(url:string, addParameters:boolean=true, ) {
this.createLink(url,"relcan", "canonical", addParameters);
this.createLink(url,"relnext", "next", addParameters)
this.createLink(url,"relprev", "prev", addParameters)
}
createLinkForNextURL(url:string, addParameters:boolean=true) {
this.createLink(url,"relnext", "next", addParameters)
}
createLinkForPrevURL(url:string, addParameters:boolean=true) {
this.createLink(url,"relprev", "prev", addParameters)
}
createLink(url:string, id:string, relname:string, addParameters:boolean=true) {
if(this.doc && (typeof this.doc.getElementById === "function" || typeof this.doc.createElement === "function") ){
if(!addParameters && url && url.indexOf("?") != -1){
url = url.substring(0,url.indexOf("?"));
}
if (typeof this.doc.getElementById === "function") {
let currentLink: HTMLLinkElement = this.doc.getElementById(id);
if(currentLink ){
currentLink.setAttribute('href', url);
return ;
}
if (typeof this.doc.createElement === "function") {
let link: HTMLLinkElement = this.doc.createElement('link');
link.setAttribute('id', 'relcan');
link.setAttribute('rel', 'canonical');
this.doc.head.appendChild(link);
link.setAttribute('href', url);
}
if (typeof this.doc.createElement === "function") {
let link: HTMLLinkElement = this.doc.createElement('link');
link.setAttribute('id', id);
link.setAttribute('rel', relname);
this.doc.head.appendChild(link);
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('<head> not found within DOCUMENT.');
}
renderer.setAttribute(link, "rel", relname);
renderer.setAttribute(link, "href", (addParameters)?url:url.split("?")[0]);
renderer.setAttribute(link, "id", id);
// [TODO]: get them to update the existing one (if it exists) ?
renderer.appendChild(head, link);
} catch (e) {
console.error('Error within linkService : ', e);
}
}
}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('<head> not found within DOCUMENT.');
}
renderer.setAttribute(link, "rel", "canonical");
renderer.setAttribute(link, "href", (addParameters)?url: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);
}
removeLinkForNextURL() {
this.removeLink("relnext", "next");
}
removeLinkForPrevURL() {
this.removeLink("relprev", "prev");
}
removeLink( id:string, relname:string) {
if(this.doc && (typeof this.doc.getElementById === "function" || typeof this.doc.createElement === "function") ){
if (typeof this.doc.getElementById === "function") {
let currentLink: HTMLLinkElement = this.doc.getElementById(id);
if(currentLink ){
currentLink.setAttribute('href', "");
currentLink.setAttribute('rel', "");
return ;
}
}
}
}
}
}

View File

@ -1,13 +1,14 @@
import { Inject, Injectable, InjectionToken } from '@angular/core';
import {Inject, Injectable, InjectionToken, PLATFORM_ID} from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
import { timeout } from 'rxjs/operators';
import {isPlatformServer} from "@angular/common";
export const DEFAULT_TIMEOUT = new InjectionToken<number>('defaultTimeout');
@Injectable()
export class TimeoutInterceptor implements HttpInterceptor {
constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout: number) {
constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout: number, @Inject(PLATFORM_ID) private platformId: any) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
@ -15,9 +16,8 @@ export class TimeoutInterceptor implements HttpInterceptor {
return next.handle(req);
}
const timeoutValue = req.headers.get('timeout') || this.defaultTimeout;
const timeoutValue = isPlatformServer(this.platformId)?3000:6000;//req.headers.get('timeout') || this.defaultTimeout;
const timeoutValueNumeric = Number(timeoutValue);
return next.handle(req).pipe(timeout(timeoutValueNumeric));
}
}

View File

@ -678,7 +678,30 @@ export class SearchFields {
return "UNDEFINED";
}
}
public static getParameterOrder(fieldId: string, params): number {
let fields = [];
let searchFields = new SearchFields();
if (searchFields.RESULT_REFINE_FIELDS.indexOf(fieldId) !=-1) {
fields = searchFields.RESULT_REFINE_FIELDS;
} else if (searchFields.PROJECT_REFINE_FIELDS.indexOf(fieldId) !=-1) {
fields = searchFields.PROJECT_REFINE_FIELDS
} else if (searchFields.ORGANIZATION_REFINE_FIELDS.indexOf(fieldId) !=-1) {
fields = searchFields.ORGANIZATION_REFINE_FIELDS;
} else if (searchFields.DATASOURCE_REFINE_FIELDS.indexOf(fieldId) !=-1) {
fields = searchFields.DATASOURCE_REFINE_FIELDS;
}
let index = fields.indexOf(fieldId);
let paramIndex = 0;
if(index != -1){
for(let keyValue of params){
if(fields.indexOf(keyValue[0])>index){
break;
}
paramIndex++
}
}
return paramIndex;
}
/*
AND
Funder: relfunder, relfundinglevel0_id, relfundinglevel1_id, relfundinglevel2_id