[Library|Trunk]

JSONLD:
-Home page: 
-Add description in Website with search action
-In every search page add description based on the filters
-In (project, content provider, organization) landing add description if available otherwise use the title
-In project add id in funder entity

Autocomplete: create event emitter to update entity or refine result label (used in jsonld)

	


git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-services-library/trunk/ng-openaire-library/src/app@59152 d315682c-612b-4755-9ff5-7f18f6832af3
This commit is contained in:
argiro.kokogiannaki 2020-07-21 12:41:08 +00:00
parent 048e3b99b5
commit 3828670514
11 changed files with 117 additions and 35 deletions

View File

@ -23,7 +23,7 @@ import {Breadcrumb} from "../utils/breadcrumbs/breadcrumbs.component";
</div> </div>
<div class="uk-container uk-container-large uk-margin-medium-top"> <div class="uk-container uk-container-large uk-margin-medium-top">
<div class="uk-grid-divider" uk-grid> <div class="uk-grid-divider uk-grid" uk-grid>
<div class="uk-width-1-2@m uk-width-1-1@s"> <div class="uk-width-1-2@m uk-width-1-1@s">
<!-- <p class="uk-margin-auto uk-text-large">How to <span class="uk-text-bold">deposit</span> your research...</p>--> <!-- <p class="uk-margin-auto uk-text-large">How to <span class="uk-text-bold">deposit</span> your research...</p>-->
<span class="uk-grid"> <span class="uk-grid">
@ -136,7 +136,7 @@ import {Breadcrumb} from "../utils/breadcrumbs/breadcrumbs.component";
</div> </div>
</div> </div>
<div class=""> <div class="">
<schema2jsonld *ngIf="url" [URL]="url" [name]="title" type="other"></schema2jsonld> <schema2jsonld *ngIf="url" [URL]="url" [name]="title" type="other" description=" Find the appropriate repository to deposit your research products of any type (publication, data, software, other) or to include in your data management plan. Search and browse for OpenAIRE compliant repositories registered in OpenDOAR and re3data. "></schema2jsonld>
<div class="uk-section tm-middle uk-container uk-container-large uk-margin-small-top uk-padding-remove-top uk-padding-remove-bottom "> <div class="uk-section tm-middle uk-container uk-container-large uk-margin-small-top uk-padding-remove-top uk-padding-remove-bottom ">
<div class="uk-container uk-container-large uk-margin-bottom uk-margin-medium-top"> <div class="uk-container uk-container-large uk-margin-bottom uk-margin-medium-top">
<div class="uk-grid uk-padding"> <div class="uk-grid uk-padding">

View File

@ -31,7 +31,8 @@
</div> </div>
</div> </div>
<schema2jsonld *ngIf="name && logoURL" [URL]="properties.baseLink+'/search/find'" <schema2jsonld *ngIf="name && logoURL" [URL]="properties.baseLink+'/search/find'"
[logoURL]="properties.baseLink+logoURL" type="search" [name]=name></schema2jsonld> [logoURL]="properties.baseLink+logoURL" type="search" [name]=name
description="Search for research outcomes (publications, datasets, software, other research products), projects, organizations, content providers in the OpenAIRE Research Graph. "></schema2jsonld>
<div class="uk-container-large uk-container"> <div class="uk-container-large uk-container">
<ul class=" portalTabs uk-tab uk-width-1-1 " uk-tab="animation: uk-animation-fade"> <ul class=" portalTabs uk-tab uk-width-1-1 " uk-tab="animation: uk-animation-fade">

View File

@ -63,7 +63,8 @@
[selectedValue]=selectedField.value [showSelected]=true [selectedValue]=selectedField.value [showSelected]=true
[placeHolderMessage]="'Search for '+selectedField.name" [title]="selectedField.name" [placeHolderMessage]="'Search for '+selectedField.name" [title]="selectedField.name"
[multipleSelections]=false (selectedValueChanged)="valueChanged($event,i)" [multipleSelections]=false (selectedValueChanged)="valueChanged($event,i)"
(listUpdated)="listUpdated($event,selectedField.id)"></static-autocomplete> (listUpdated)="listUpdated($event,selectedField.id)"
(updateValueLabel)="updatedValueLabel($event, i)"></static-autocomplete>
</td> </td>
<td *ngIf="selectedField.type == 'entity'"> <td *ngIf="selectedField.type == 'entity'">
<entities-autocomplete [properties]=properties [fieldId]=selectedField.id [entityType]=selectedField.param <entities-autocomplete [properties]=properties [fieldId]=selectedField.id [entityType]=selectedField.param
@ -71,7 +72,7 @@
[placeHolderMessage]="'Search for '+selectedField.name" [title]="selectedField.name" [placeHolderMessage]="'Search for '+selectedField.name" [title]="selectedField.name"
[multipleSelections]=false [multipleSelections]=false
(selectedValueChanged)="valueChanged($event,i)" (selectedValueChanged)="valueChanged($event,i)"
(listUpdated)="listUpdated($event,selectedField.id)"> (updateValueLabel)="updatedValueLabel($event, i)">
</entities-autocomplete> </entities-autocomplete>
</td> </td>
@ -98,14 +99,15 @@
<td class=" "> <td class=" ">
<span type="button" class="uk-icon-button portal-button-reverse clickable " <span type="button" class="uk-icon-button portal-button-reverse clickable "
(click)="removeField(i)"> (click)="removeField(i)">
<span uk-icon="minus"> </span> <span class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg" data-svg="minus"><rect height="1" width="18" y="9" x="1"></rect></svg></span>
</span> </span>
<div *ngIf="i == selectedFields.length-1 " class="uk-margin-small-top"> <div *ngIf="i == selectedFields.length-1 " class="uk-margin-small-top">
<span type="button" <span type="button"
class="uk-icon-button portal-button clickable " class="uk-icon-button portal-button clickable "
(click)="addField()"> (click)="addField()">
<span uk-icon="plus"> <span class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20"
</span> xmlns="http://www.w3.org/2000/svg" data-svg="plus"><rect x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17" height="1"></rect></svg></span>
</span> </span>
</div> </div>
</td> </td>

View File

@ -150,6 +150,9 @@ export class AdvancedSearchFormComponent {
valueChanged($event,index:number){ valueChanged($event,index:number){
this.selectedFields[index].value = $event.value; this.selectedFields[index].value = $event.value;
} }
updatedValueLabel($event,index:number){
this.selectedFields[index].valueLabel = $event.value;
}
listUpdated($event,fieldId:number){ listUpdated($event,fieldId:number){
this.fieldList[fieldId] = $event.value; this.fieldList[fieldId] = $event.value;
} }

View File

@ -178,7 +178,7 @@
</div> </div>
</div> </div>
<schema2jsonld *ngIf="!includeOnlyResultsAndFilter && url" [URL]="url" type="search" [name]=pageTitle <schema2jsonld *ngIf="!includeOnlyResultsAndFilter && url" [URL]="url" type="search" [name]=pageTitle
[searchAction]=false></schema2jsonld> [searchAction]=false [description]="metaDescription" ></schema2jsonld>
<div id="tm-main" class=" tm-middle"> <div id="tm-main" class=" tm-middle">

View File

@ -57,7 +57,7 @@ export class NewSearchPageComponent {
@Input() rangeFilters: RangeFilter[] = []; @Input() rangeFilters: RangeFilter[] = [];
@Input() rangeFields: string[][] = []; @Input() rangeFields: string[][] = [];
@Input() refineFields = []; @Input() refineFields = [];
@Input() filters = []; @Input() filters:Filter[] = [];
selectedFilters: number = 0; selectedFilters: number = 0;
selectedRangeFilters: number = 0; selectedRangeFilters: number = 0;
private searchFieldsHelper: SearchFields = new SearchFields(); private searchFieldsHelper: SearchFields = new SearchFields();
@ -101,7 +101,7 @@ export class NewSearchPageComponent {
public errorCodes: ErrorCodes = new ErrorCodes(); public errorCodes: ErrorCodes = new ErrorCodes();
breadcrumbs:Breadcrumb[] = []; breadcrumbs:Breadcrumb[] = [];
url = null; url = null;
metaDescription = "";
@Input() entitiesSelection:boolean = true; @Input() entitiesSelection:boolean = true;
@Input() showAdvancedSearchLink:boolean = true; @Input() showAdvancedSearchLink:boolean = true;
@ -128,10 +128,8 @@ export class NewSearchPageComponent {
this.resultsPerPage = data.envSpecific.resultsPerPage; this.resultsPerPage = data.envSpecific.resultsPerPage;
this.csvLimit = data.envSpecific.csvLimit; this.csvLimit = data.envSpecific.csvLimit;
this.isPiwikEnabled = data.envSpecific.enablePiwikTrack; this.isPiwikEnabled = data.envSpecific.enablePiwikTrack;
if (typeof window !== 'undefined') { this.updateUrl(data.envSpecific.baseLink +this.router.url);
this.updateUrl(data.envSpecific.baseLink + location.pathname); this.url = data.envSpecific.baseLink + this.router.url;
this.url = data.envSpecific.baseLink + location.pathname
}
if (typeof document !== 'undefined' && this.isPiwikEnabled) { if (typeof document !== 'undefined' && this.isPiwikEnabled) {
this.piwiksub = this._piwikService.trackView(this.properties, this.pageTitle, this.piwikSiteId).subscribe(); this.piwiksub = this._piwikService.trackView(this.properties, this.pageTitle, this.piwikSiteId).subscribe();
} }
@ -142,10 +140,10 @@ export class NewSearchPageComponent {
} }
this.customFilterEnabled = params['cf'] && params['cf'] == "true"; this.customFilterEnabled = params['cf'] && params['cf'] == "true";
}); });
var description = "Openaire, search, repositories, open access, type, content provider, funder, project, " + this.pageTitle; this.metaDescription = this.pageTitle;
this.updateTitle(this.pageTitle); this.updateTitle(this.pageTitle);
this.updateDescription(description); this.updateDescription();
this.searchUtils.baseUrl = "/" + this.searchUtils.baseUrl; this.searchUtils.baseUrl = "/" + this.searchUtils.baseUrl;
this.seoService.createLinkForCanonicalURL(this.properties.baseLink + this.router.url, false); this.seoService.createLinkForCanonicalURL(this.properties.baseLink + this.router.url, false);
@ -179,9 +177,43 @@ export class NewSearchPageComponent {
} }
} }
updateDescription(description: string) { updateDescription() {
this._meta.updateTag({content: description}, "name='description'"); this.metaDescription = "Search results for ";
this._meta.updateTag({content: description}, "property='og:description'"); if(this.resultTypes){
let array = [];
for(let type of this.resultTypeOptions){
if(this.resultTypes[type.id]== true){
array.push(type.name);
}
}
if(array.length == 0){
this.metaDescription += "research outcomes ";
}else{
this.metaDescription += array.join(", ") + " ";
}
}else{
this.metaDescription = this.pageTitle + " ";
}
let filterArray = [];
for(let filter of this.filters){
if(filter.countSelectedValues> 0){
for(let value of filter.values){
if(value.selected) {
filterArray.push(value.name);
}
}
}
}
for(let field of this.selectedFields){
if((field.type == "entity" || field.type == "refine") && field.valueLabel.length > 0 && filterArray.indexOf(field.valueLabel)==-1){
filterArray.push(field.valueLabel)
}else if(!(field.type == "entity" || field.type == "refine") && field.value.length > 0 && filterArray.indexOf(field.value)==-1) {
filterArray.push(field.value);
}
}
this.metaDescription+= (filterArray.length > 0?" filtered for: ":"") + filterArray.join(", ") + " ";
this._meta.updateTag({content: this.metaDescription}, "name='description'");
this._meta.updateTag({content: this.metaDescription}, "property='og:description'");
} }
updateTitle(title: string) { updateTitle(title: string) {
@ -375,6 +407,7 @@ export class NewSearchPageComponent {
} }
} }
this.filterFilterValues(this.filters); this.filterFilterValues(this.filters);
this.updateDescription();
return filters; return filters;
} }

View File

@ -25,6 +25,7 @@ export class AdvancedField{
public name: string; // public name: string; //
public type: string = "keyword"; //keyword, static or dynamic public type: string = "keyword"; //keyword, static or dynamic
public value: string = ''; public value: string = '';
public valueLabel: string = '';
public operatorId: string; public operatorId: string;
public operatorName: string =""; public operatorName: string ="";
public valid: boolean = true; public valid: boolean = true;

View File

@ -1,4 +1,4 @@
import {Component, Input} from '@angular/core'; import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core';
import {OpenAireJsonldConverterService} from './service/open-aire-jsonld-converter.service'; import {OpenAireJsonldConverterService} from './service/open-aire-jsonld-converter.service';
import {JsonldDocumentSerializerService} from './service/jsonld-document-serializer.service'; import {JsonldDocumentSerializerService} from './service/jsonld-document-serializer.service';
@ -8,7 +8,7 @@ import {JsonldDocumentSerializerService} from './service/jsonld-document-seriali
<ngx-json-ld [json]="json"></ngx-json-ld> <ngx-json-ld [json]="json"></ngx-json-ld>
` `
}) })
export class Schema2jsonldComponent { export class Schema2jsonldComponent implements OnInit, OnChanges {
@Input() data; // for project, organization, datasource @Input() data; // for project, organization, datasource
@Input() URL; @Input() URL;
@Input() logoURL; // for home, search @Input() logoURL; // for home, search
@ -23,14 +23,22 @@ export class Schema2jsonldComponent {
private documentSerializer: JsonldDocumentSerializerService) { private documentSerializer: JsonldDocumentSerializerService) {
} }
ngOnChanges(changes: SimpleChanges): void {
if (changes.description) {
this.createJson();
}
}
ngOnInit() { ngOnInit() {
this.createJson();
}
createJson(){
var docOvject; var docOvject;
if (this.type == 'project') { if (this.type == 'project') {
docOvject = this.documentParser.convertProject(this.data, this.URL, this.otherURL); docOvject = this.documentParser.convertProject(this.data, this.URL);
this.json = this.documentSerializer.serializeOrganization(docOvject); this.json = this.documentSerializer.serializeOrganization(docOvject);
} else if (this.type == 'organization') { } else if (this.type == 'organization') {
docOvject = this.documentParser.convertOrganization(this.data, this.URL); docOvject = this.documentParser.convertOrganization(this.data, this.URL, this.description);
this.json = this.documentSerializer.serializeOrganization(docOvject); this.json = this.documentSerializer.serializeOrganization(docOvject);
} else if (this.type == 'datasource') { } else if (this.type == 'datasource') {
docOvject = this.documentParser.convertDatasource(this.data, this.URL, this.otherURL); docOvject = this.documentParser.convertDatasource(this.data, this.URL, this.otherURL);

View File

@ -36,6 +36,9 @@ export class OpenAireJsonldConverterService {
searchPage["name"] = name; searchPage["name"] = name;
searchPage["url"] = properties.baseLink+"/search/find/"; searchPage["url"] = properties.baseLink+"/search/find/";
searchPage["logo"] = logoURL; searchPage["logo"] = logoURL;
if(description){
searchPage["description"] = description;
}
const action ={}; const action ={};
action["@type"]= "SearchAction"; action["@type"]= "SearchAction";
action["@id"]= properties.baseLink+"/#search-action"; action["@id"]= properties.baseLink+"/#search-action";
@ -53,7 +56,10 @@ export class OpenAireJsonldConverterService {
buffer["url"] = URL; buffer["url"] = URL;
if(description){ if(description){
buffer["description"] = description; buffer["description"] = description;
} buffer["@id"] = URL; }else{
buffer["description"] = name;
}
buffer["@id"] = URL;
return buffer; return buffer;
} }
createSearchPage(name, URL, logoURL, searchAction:boolean = true, description:string = null): any { createSearchPage(name, URL, logoURL, searchAction:boolean = true, description:string = null): any {
@ -88,7 +94,7 @@ export class OpenAireJsonldConverterService {
doc.issn = this.getISSN(result); doc.issn = this.getISSN(result);
doc.description = this.getDescription(result); doc.description = this.getDescription(result);
doc.identifier = this.getIdentifier(result); doc.identifier = this.getIdentifier(result);
doc.id = URL doc.id = URL;
doc.url = URL; doc.url = URL;
doc.sameAs = this.getSameAs(result); doc.sameAs = this.getSameAs(result);
doc.creator = this.getCreator(result); doc.creator = this.getCreator(result);
@ -99,40 +105,50 @@ export class OpenAireJsonldConverterService {
return doc; return doc;
} }
convertProject(project: any, URL, otherUrl): Organization { convertProject(project: any, URL): Organization {
const doc = new Organization(); const doc = new Organization();
doc.title = (project.title)?project.title:project.acronym; doc.title = (project.title)?project.title:project.acronym;
doc.identifier = new Array<Identifier>(); doc.identifier = new Array<Identifier>();
doc.identifier.push({id:project.funding.code, schema: "grantid"}); doc.identifier.push({id:project.funding.code, schema: "grantid"});
var funder = new Organization(); let funder = new Organization();
funder.title = project.funding.funderShortName; funder.id = properties.baseLink+"#funder-"+project.funding.funderShortName;
funder.title = project.funding.funderName;
doc.funder = funder; doc.funder = funder;
doc.url = URL; doc.url = URL;
doc.id = URL;
doc["description"] = [];
doc["description"].push((project.title)?project.title:project.acronym);
doc.sameAs =[project.url]; doc.sameAs =[project.url];
return doc; return doc;
} }
convertOrganization(organization: any, URL): Organization { convertOrganization(organization: any, URL, description:string = null): Organization {
const doc = new Organization(); const doc = new Organization();
doc.title = organization.title.name ; doc.title = organization.title.name ;
doc.legalName = organization.name; doc.legalName = organization.name;
doc.areaServed = organization.country; doc.areaServed = organization.country;
doc.url = URL; doc.url = URL;
doc.id = URL;
doc["description"] = [];
doc["description"].push(((organization.title.name?organization.title.name:"") + " - " + (organization.name?organization.name:"")));
return doc; return doc;
} }
convertDatasource(datasource: any, URL, otherUrl): Organization { convertDatasource(datasource: any, URL, otherUrl): Organization {
const doc = new Organization(); const doc = new Organization();
doc.title = datasource.title.name; doc.title = datasource.title.name?datasource.title.name:datasource.officialName;
//doc.identifier = datasource.contractNum; //doc.identifier = datasource.contractNum;
doc.legalName = datasource.officialName; doc.legalName = datasource.officialName;
if(datasource.countries && datasource.countries.length > 0){ if(datasource.countries && datasource.countries.length > 0){
doc.areaServed = datasource.countries[0]; doc.areaServed = datasource.countries[0];
} }
doc.url = URL; doc.url = URL;
doc.id = URL;
doc["description"] = [];
doc["description"].push(datasource.description?datasource.description:datasource.title.name?datasource.title.name:datasource.officialName);
if(datasource.oaiPmhURL || otherUrl || datasource.title.url){ if(datasource.oaiPmhURL || otherUrl || datasource.title.url){
doc.sameAs = []; doc.sameAs = [];
if(otherUrl){ if(otherUrl){

View File

@ -56,6 +56,7 @@ export class EntitiesAutocompleteComponent {
@Input() title = "Autocomplete"; @Input() title = "Autocomplete";
@Output() addItem = new EventEmitter(); // when selected list changes update parent component @Output() addItem = new EventEmitter(); // when selected list changes update parent component
@Output() selectedValueChanged = new EventEmitter(); // when changed a method for filtering will be called @Output() selectedValueChanged = new EventEmitter(); // when changed a method for filtering will be called
@Output() updateValueLabel = new EventEmitter(); //when the value is id sends an event to update the value (for meta tags)
@Input() public list = []; // the entries resulted after filtering function @Input() public list = []; // the entries resulted after filtering function
@Input() public selected = []; // the entries selected from user @Input() public selected = []; // the entries selected from user
@Input() public keywordlimit = 3; // the minimum length of keyword @Input() public keywordlimit = 3; // the minimum length of keyword
@ -181,6 +182,9 @@ export class EntitiesAutocompleteComponent {
this.selectedValueChanged.emit({ this.selectedValueChanged.emit({
value: this.selectedValue value: this.selectedValue
}); });
this.updateValueLabel.emit({
value:""
});
} }
@ -213,6 +217,9 @@ export class EntitiesAutocompleteComponent {
this.selectedValueChanged.emit({ this.selectedValueChanged.emit({
value: this.selectedValue value: this.selectedValue
}); });
this.updateValueLabel.emit({
value:this.showItem(item)
});
this.focus=false; this.focus=false;
} }
@ -267,6 +274,9 @@ export class EntitiesAutocompleteComponent {
this.sub = this._search.fetchByType(this.selectedValue,this.entityType, this.properties).subscribe( this.sub = this._search.fetchByType(this.selectedValue,this.entityType, this.properties).subscribe(
data => { data => {
this.selected.push( data[0]); this.selected.push( data[0]);
this.updateValueLabel.emit({
value:this.showItem(this.selected[0])
});
this.showInput = false; this.showInput = false;
}, },
err => { err => {

View File

@ -46,6 +46,7 @@ export class StaticAutoCompleteComponent implements OnChanges{
@Input() title = "Autocomplete"; @Input() title = "Autocomplete";
@Output() addItem = new EventEmitter(); // when selected list changes update parent component @Output() addItem = new EventEmitter(); // when selected list changes update parent component
@Output() selectedValueChanged = new EventEmitter(); // when changed a method for filtering will be called @Output() selectedValueChanged = new EventEmitter(); // when changed a method for filtering will be called
@Output() updateValueLabel = new EventEmitter(); //when the value is id sends an event to update the value (for meta tags)
@Output() listUpdated = new EventEmitter(); // when changed a method for filtering will be called @Output() listUpdated = new EventEmitter(); // when changed a method for filtering will be called
@Input() public list = []; // the entries resulted after filtering function @Input() public list = []; // the entries resulted after filtering function
@Input() public filtered = []; // the entries resulted after filtering function @Input() public filtered = []; // the entries resulted after filtering function
@ -197,7 +198,9 @@ export class StaticAutoCompleteComponent implements OnChanges{
this.selectedValueChanged.emit({ this.selectedValueChanged.emit({
value: this.selectedValue value: this.selectedValue
}); });
this.updateValueLabel.emit({
value:""
});
} }
} }
@ -229,7 +232,9 @@ export class StaticAutoCompleteComponent implements OnChanges{
this.selectedValueChanged.emit({ this.selectedValueChanged.emit({
value: this.selectedValue value: this.selectedValue
}); });
this.updateValueLabel.emit({
value:this.showItem(item)
});
} }
} }
@ -279,6 +284,9 @@ export class StaticAutoCompleteComponent implements OnChanges{
this.selectedValue = this.list[i].label; this.selectedValue = this.list[i].label;
this.selected.push(this.list[i]); this.selected.push(this.list[i]);
this.showInput = false; this.showInput = false;
this.updateValueLabel.emit({
value:this.showItem(this.list[i])
});
return; return;
} }