[Library | Trunk]: Annotations add list of related annotations resources

git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-services-library/trunk/ng-openaire-library/src/app@59962 d315682c-612b-4755-9ff5-7f18f6832af3
This commit is contained in:
k.triantafyllou 2020-11-25 16:09:36 +00:00
parent fd31ff1556
commit 3dfe33b5c7
8 changed files with 176 additions and 96 deletions

View File

@ -22,11 +22,6 @@ import {Subscriber} from "rxjs";
type="hidden" type="hidden"
name="recordurl_tofeed" name="recordurl_tofeed"
[value]="url"> [value]="url">
<!--URL of the record contents for downloading-->
<input
type="hidden"
name="subject_tofeed"
[value]="pid">
<!--PID of the annotated record--> <!--PID of the annotated record-->
<input <input
type="hidden" type="hidden"
@ -51,15 +46,18 @@ import {Subscriber} from "rxjs";
</div> </div>
<div *ngIf="loading" class="loading-gif uk-margin-medium-top"></div> <div *ngIf="loading" class="loading-gif uk-margin-medium-top"></div>
<ul *ngIf="annotations && !loading" class="uk-list uk-list-divider"> <ul *ngIf="annotations && !loading" class="uk-list uk-list-divider">
<li *ngFor="let annotation of annotations.slice(0, visibleAnnotations)" uk-grid <li *ngFor="let annotation of annotations.slice(0, visibleAnnotations); let i=index" uk-grid
class="uk-flex uk-flex-top uk-margin-remove-left"> class="uk-flex uk-flex-top uk-margin-remove-left">
<div [ngClass]="annotation.type" class="uk-width-auto">{{annotation.type}}</div> <div [ngClass]="annotation.type" class="type">{{annotation.type}}</div>
<div [class.uk-width-1-3]="annotation.urls" [class.uk-width-1-6@s]="annotation.urls">{{annotation.text}}</div> <div [class.uk-width-1-3]="annotation.targets"
<ul class="uk-width-expand uk-list uk-margin-remove-top" *ngIf="annotation.urls"> [class.uk-width-1-6@s]="annotation.targets">{{annotation.text}}</div>
<li *ngFor="let url of annotation.urls.slice(0, annotation.urlSize)"><a [href]="url" <ul class="uk-width-expand uk-list uk-margin-remove-top" *ngIf="annotation.targets">
target="_blank">{{url}}</a></li> <li *ngFor="let target of annotation.targets.slice(0, annotation.targetSize)">
<li *ngIf="annotation.urlSize < annotation.urls.length"><a <a *ngIf="target.url" [href]="target.url" target="_blank">{{target.id}}</a>
(click)="annotation.urlSize = annotation.urls.length">+ {{annotation.urls.length - annotation.urlSize}} <a *ngIf="!target.url" routerLink="/search/advanced/research-outcomes" [queryParams]="searchPid(target.id)">{{target.id}}</a>
</li>
<li *ngIf="annotation.targetSize < annotation.targets.length"><a
(click)="open(i)">+ {{annotation.targets.length - annotation.targetSize}}
more</a></li> more</a></li>
</ul> </ul>
</li> </li>
@ -72,11 +70,9 @@ import {Subscriber} from "rxjs";
</div> </div>
<div [class.uk-hidden]="!visible"> <div [class.uk-hidden]="!visible">
<div class="widget-container" cdkDrag> <div class="widget-container" cdkDrag>
<!--Close button, should be bound to hide the widget-->
<button type="button" class="close" aria-label="Close" (click)="toggleAnnotation($event)"> <button type="button" class="close" aria-label="Close" (click)="toggleAnnotation($event)">
<span aria-hidden="true">×</span> <span aria-hidden="true">×</span>
</button> </button>
<!--The glorious iframe with the running app!-->
<iframe #iframe id="b2note_iframe" name="b2note_iframe" class="b2note-iframe"> <iframe #iframe id="b2note_iframe" name="b2note_iframe" class="b2note-iframe">
</iframe> </iframe>
</div> </div>
@ -156,26 +152,80 @@ export class AnnotationComponent implements OnInit, OnDestroy {
} }
private getAnnotations() { private getAnnotations() {
if(!this.annotations || this.annotations.length === 0) { if (!this.annotations || this.annotations.length === 0) {
this.loading = true; this.loading = true;
} }
this.subscriptions.push(this.annotationService.getAllAnnotations(this.properties, this.pid).subscribe(annotations => { this.subscriptions.push(this.annotationService.getAllAnnotations(this.pid).subscribe(annotations => {
this.annotations = annotations; this.annotations.forEach((annotation, index) => {
this.annotations.forEach(annotation => { if (!annotations.find(element => element.type === annotation.type && element.text === annotation.text)) {
annotation.urlSize = 3; this.annotations.splice(index, 1);
}
}); });
annotations.forEach(annotation => {
if (!this.annotations.find(element => element.type === annotation.type && element.text === annotation.text)) {
annotation.targetSize = 3;
this.annotationService.getAnnotationsTargets(annotation.text, annotation.type).subscribe(targets => {
annotation.targets = targets.filter(target => target.id !== this.pid);
/*for(let i = 0; i < 10; i++) {
annotation.targets.push(targets[0]);
}*/
});
this.annotations.push(annotation);
}
});
this.annotations = this.sort(this.annotations);
this.loading = false;
}, error => {
this.loading = false; this.loading = false;
})); }));
} }
ngOnDestroy(): void { public sort(annotations: Annotation[]): Annotation[] {
return annotations.sort((a, b) => {
if (a.type === b.type) {
return 1;
} else if (a.type === 'semantic') {
return -1;
} else if (b.type === 'semantic') {
return 1;
} else if (a.type === 'keyword') {
return -1;
} else if (b.type === 'keyword') {
return 1;
}
});
}
public searchPid(pid: string): { [k: string]: any;} {
return {
f0: 'pid',
fv0: pid,
qf: false
}
}
ngOnDestroy()
:
void {
this.clearSubscriptions(); this.clearSubscriptions();
} }
public toggleAnnotation(event) { public
toggleAnnotation(event) {
if (this.visible) { if (this.visible) {
event.preventDefault(); event.preventDefault();
} }
this.visible = !this.visible; this.visible = !this.visible;
} }
open(i: number) {
this.annotations.forEach((annotation, index) => {
if(index != i) {
annotation.targetSize = 3;
} else {
annotation.targetSize = annotation.targets.length
}
});
}
} }

View File

@ -2,7 +2,7 @@
position: fixed; position: fixed;
left: 50%; left: 50%;
top: 50%; top: 50%;
z-index: 5; z-index: 1000;
padding: 19px; padding: 19px;
margin-left: -167px; margin-left: -167px;
margin-top: -311px; margin-top: -311px;

View File

@ -2,9 +2,10 @@ import {NgModule} from "@angular/core";
import {AnnotationComponent} from "./annotation.component"; import {AnnotationComponent} from "./annotation.component";
import {CommonModule} from "@angular/common"; import {CommonModule} from "@angular/common";
import {DragDropModule} from "@angular/cdk/drag-drop"; import {DragDropModule} from "@angular/cdk/drag-drop";
import {RouterModule} from "@angular/router";
@NgModule({ @NgModule({
imports: [CommonModule, DragDropModule], imports: [CommonModule, DragDropModule, RouterModule],
declarations: [AnnotationComponent], declarations: [AnnotationComponent],
exports: [AnnotationComponent] exports: [AnnotationComponent]
}) })

View File

@ -3,79 +3,108 @@ import {HttpClient} from "@angular/common/http";
import {Observable} from "rxjs"; import {Observable} from "rxjs";
import {EnvProperties} from "../../utils/properties/env-properties"; import {EnvProperties} from "../../utils/properties/env-properties";
import {map} from "rxjs/operators"; import {map} from "rxjs/operators";
import {properties} from "../../../../environments/environment";
export interface AnnotationTarget {
id: string;
url: string;
}
export interface Annotation { export interface Annotation {
text: string; text: string;
type: 'semantic' | 'keyword' | 'comment'; type: 'semantic' | 'keyword' | 'comment';
urls?: string[]; targets?: AnnotationTarget[];
urlSize?: number; targetSize?: number;
} }
@Injectable({ @Injectable({
providedIn: "root" providedIn: "root"
}) })
export class AnnotationService { export class AnnotationService {
api = 'api/'; api = 'api/';
constructor(private http: HttpClient) { constructor(private http: HttpClient) {
} }
getAllAnnotations(properties: EnvProperties, source: string): Observable<Annotation[]> { getAllAnnotations(source: string): Observable<Annotation[]> {
let url = properties.b2noteAPIURL + this.api + 'annotations?type[]=semantic&type[]=keyword&type[]=comment&format=json-ld&download=false&target-source=' + encodeURIComponent(source); let url = properties.b2noteAPIURL + this.api + 'annotations?target-id=' + encodeURIComponent(source);
return this.http.get<Annotation[]>(url).pipe(map((response: any[]) => { return this.http.get<Annotation[]>(url).pipe(map((response: any[]) => {
return this.parseAnnotations(response); return this.parseAnnotations(response);
})); }));
} }
private parseAnnotations(response: any[]): Annotation[] { getAnnotationsTargets(value: string, type: 'semantic' | 'keyword' | 'comment'): Observable<AnnotationTarget[]> {
let annotations: Annotation[] = []; let url = properties.b2noteAPIURL + this.api + 'annotations?value=' + encodeURIComponent(value);
if(response && response.length > 0) { return this.http.get<AnnotationTarget[]>(url).pipe(map((response: any[]) => {
response.forEach(value => { return this.parseAnnotationTargets(response, type);
let body = value.body; }));
if(body.type === 'TextualBody') { }
if(body.purpose === 'tagging') {
annotations.push({ private parseAnnotations(response: any[]): Annotation[] {
text: body.value, let annotations: Annotation[] = [];
type: "keyword" if (response && response.length > 0) {
}); response.forEach(value => {
} else { if (value.visibility === 'public') {
annotations.push({ let body = value.body;
text: body.value, if (body.type === 'TextualBody') {
type: "comment" if (body.purpose === 'tagging') {
}); annotations.push({
} text: body.value,
} else { type: "keyword"
let items = body.items; });
let urls: string[] = []; } else {
let text: string = null; annotations.push({
items.forEach(item => { text: body.value,
if(item.type === 'SpecificResource') { type: "comment"
urls.push(item.source); });
} else if(item.type === 'TextualBody') {
text = item.value;
}
});
annotations.push({
text: text,
type: "semantic",
urls: urls
});
}
});
}
return annotations.sort((a, b) => {
if(a.type === b.type) {
return 0;
} else if (a.type === 'semantic') {
return -1;
} else if(b.type === 'semantic') {
return 1;
} else if(a.type === 'keyword') {
return -1;
} else if(b.type === 'keyword') {
return 1;
} }
}); } else {
let items = body.items;
let text: string = null;
items.forEach(item => {
if (item.type === 'TextualBody') {
text = item.value;
}
});
annotations.push({
text: text,
type: "semantic"
});
}
}
});
} }
return annotations;
}
private parseAnnotationTargets(response: any[], type: 'semantic' | 'keyword' | 'comment'): AnnotationTarget[] {
let targets: AnnotationTarget[] = [];
if (response && response.length > 0) {
response.forEach(value => {
if (value.visibility === 'public') {
let body = value.body;
if (body.type === 'TextualBody') {
if (body.purpose === 'tagging' && type === 'keyword') {
targets.push({
id: value.target.id,
url: value.target.source
});
} else if(type === 'comment'){
targets.push({
id: value.target.id,
url: value.target.source
});
}
} else if(type === 'semantic'){
targets.push({
id: value.target.id,
url: value.target.source
});
}
}
});
}
return targets;
}
} }

View File

@ -75,7 +75,7 @@
<!-- Metrics --> <!-- Metrics -->
<li *ngIf="hasMetrics" class="uk-margin-medium-top"> <li *ngIf="hasMetrics" class="uk-margin-medium-top">
<div class="uk-text-center uk-flex uk-flex-middle uk-flex-center"> <div class="uk-text-center uk-flex uk-flex-middle uk-flex-center">
<div> <div [class.uk-hidden]="!(totalViews && totalDownloads && pageViews)">
<metrics [pageViews]="pageViews" <metrics [pageViews]="pageViews"
[id]="datasourceId" [entityType]="'datasources'" [entity]="'Content Provider'" [id]="datasourceId" [entityType]="'datasources'" [entity]="'Content Provider'"
[viewsFrameUrl]="viewsFrameUrl" [downloadsFrameUrl]="downloadsFrameUrl" [viewsFrameUrl]="viewsFrameUrl" [downloadsFrameUrl]="downloadsFrameUrl"

View File

@ -386,7 +386,7 @@
<!-- Metrics --> <!-- Metrics -->
<li *ngIf="hasMetrics" class="uk-margin-medium-top"> <li *ngIf="hasMetrics" class="uk-margin-medium-top">
<div class="uk-text-center uk-flex uk-flex-middle uk-flex-center"> <div class="uk-text-center uk-flex uk-flex-middle uk-flex-center">
<div> <div [class.uk-hidden]="!(totalViews && totalDownloads && pageViews)">
<metrics [pageViews]="pageViews" <metrics [pageViews]="pageViews"
[id]="projectId" [entityType]="'projects'" [entity]="'project'" [id]="projectId" [entityType]="'projects'" [entity]="'project'"
[viewsFrameUrl]="viewsFrameUrl" [downloadsFrameUrl]="downloadsFrameUrl" [viewsFrameUrl]="viewsFrameUrl" [downloadsFrameUrl]="downloadsFrameUrl"

View File

@ -44,9 +44,9 @@ export class ProjectComponent {
public metricsClicked: boolean; public metricsClicked: boolean;
public viewsFrameUrl: string; public viewsFrameUrl: string;
public downloadsFrameUrl: string; public downloadsFrameUrl: string;
private totalViews: number; public totalViews: number;
private totalDownloads: number; public totalDownloads: number;
private pageViews: number; public pageViews: number;
// Statistics tab variables // Statistics tab variables
public statsClicked: boolean; public statsClicked: boolean;

View File

@ -104,7 +104,7 @@
<li *ngIf="hasAltMetrics || hasMetrics" class="uk-margin-medium-top"> <li *ngIf="hasAltMetrics || hasMetrics" class="uk-margin-medium-top">
<div uk-grid <div uk-grid
class="uk-child-width-1-3 uk-text-center uk-flex uk-flex-middle uk-flex-center uk-padding-remove-left"> class="uk-child-width-1-3 uk-text-center uk-flex uk-flex-middle uk-flex-center uk-padding-remove-left">
<div *ngIf="hasMetrics"> <div *ngIf="hasMetrics" [class.uk-hidden]="!(totalViews && totalDownloads && pageViews)">
<metrics [pageViews]="pageViews" <metrics [pageViews]="pageViews"
[id]="id" [entityType]="'results'" [entity]="title" [id]="id" [entityType]="'results'" [entity]="title"
[viewsFrameUrl]="viewsFrameUrl" [downloadsFrameUrl]="downloadsFrameUrl" [viewsFrameUrl]="viewsFrameUrl" [downloadsFrameUrl]="downloadsFrameUrl"