1
|
import {
|
2
|
Component,
|
3
|
ElementRef,
|
4
|
EventEmitter,
|
5
|
HostListener,
|
6
|
Input,
|
7
|
OnDestroy,
|
8
|
OnInit,
|
9
|
Output,
|
10
|
ViewChild
|
11
|
} from "@angular/core";
|
12
|
import {Annotation, AnnotationService} from "./annotation.service";
|
13
|
import {ResultLandingInfo} from "../../utils/entities/resultLandingInfo";
|
14
|
import {EnvProperties} from "../../utils/properties/env-properties";
|
15
|
import {properties} from "../../../../environments/environment";
|
16
|
import {UserManagementService} from "../../services/user-management.service";
|
17
|
import {COOKIE, Session, User} from "../../login/utils/helper.class";
|
18
|
import {Subscriber} from "rxjs";
|
19
|
|
20
|
@Component({
|
21
|
selector: 'b2note',
|
22
|
template: `
|
23
|
<div *ngIf="annotations && annotations.length > 0" class="sideInfoTitle uk-margin-small-bottom">Annotations</div>
|
24
|
<div class="b2note">
|
25
|
<form #form ngNoForm *ngIf="pid && isLoggedIn"
|
26
|
[action]="properties.b2noteAPIURL + 'widget'"
|
27
|
method="post"
|
28
|
target="b2note_iframe"
|
29
|
class="uk-padding-small uk-padding-remove-vertical">
|
30
|
<!--URL of the annotated record-->
|
31
|
<input
|
32
|
type="hidden"
|
33
|
name="recordurl_tofeed"
|
34
|
[value]="url">
|
35
|
<!--PID of the annotated record-->
|
36
|
<input
|
37
|
type="hidden"
|
38
|
name="pid_tofeed"
|
39
|
[value]="pid">
|
40
|
</form>
|
41
|
<loading *ngIf="loading" class="uk-margin-medium-top"></loading>
|
42
|
<ul *ngIf="annotations && !loading" class="uk-list uk-list-divider">
|
43
|
<li *ngFor="let annotation of annotations.slice(0, visibleAnnotations); let i=index" uk-grid
|
44
|
class="uk-flex uk-flex-top uk-margin-remove-left">
|
45
|
<div [ngClass]="annotation.type" class="type">{{annotation.type}}</div>
|
46
|
<div [class.uk-width-1-3]="annotation.targets"
|
47
|
[class.uk-width-1-6@s]="annotation.targets">{{annotation.text}}</div>
|
48
|
<ul class="uk-width-expand uk-list uk-margin-remove-top" *ngIf="annotation.targets">
|
49
|
<li *ngFor="let target of annotation.targets.slice(0, annotation.targetSize)">
|
50
|
<a *ngIf="target.url" [href]="target.url" target="_blank">{{target.id}}</a>
|
51
|
<a *ngIf="!target.url" routerLink="/search/result"
|
52
|
[queryParams]="searchPid(target.id)">{{target.id}}</a>
|
53
|
</li>
|
54
|
<li *ngIf="annotation.targetSize < annotation.targets.length"><a
|
55
|
(click)="open(i)">+ {{annotation.targets.length - annotation.targetSize}}
|
56
|
more</a></li>
|
57
|
</ul>
|
58
|
</li>
|
59
|
</ul>
|
60
|
<div *ngIf="visibleAnnotations < annotations.length" class="uk-margin-medium-top uk-text-center">
|
61
|
<button class="uk-button uk-button-primary"
|
62
|
(click)="visibleAnnotations = (visibleAnnotations + annotationSize)">Load More
|
63
|
</button>
|
64
|
</div>
|
65
|
</div>
|
66
|
<div [class.uk-hidden]="!visible">
|
67
|
<div class="widget-container" cdkDrag>
|
68
|
<button type="button" class="close" aria-label="Close" (click)="toggleAnnotation($event)">
|
69
|
<span aria-hidden="true">×</span>
|
70
|
</button>
|
71
|
<iframe #iframe id="b2note_iframe" name="b2note_iframe" class="b2note-iframe">
|
72
|
</iframe>
|
73
|
</div>
|
74
|
</div>`,
|
75
|
styleUrls: ['annotation.css']
|
76
|
})
|
77
|
export class AnnotationComponent implements OnInit, OnDestroy {
|
78
|
|
79
|
@Input()
|
80
|
public landingInfo: ResultLandingInfo = null;
|
81
|
@Input()
|
82
|
public id: string = null;
|
83
|
public properties: EnvProperties = properties;
|
84
|
public url: string = null;
|
85
|
public pid: string = null;
|
86
|
public keywords: string[] = [];
|
87
|
public visible: boolean = false;
|
88
|
public annotations: Annotation[] = [];
|
89
|
public annotationSize: number = 10;
|
90
|
public isLoggedIn: boolean = Session.isLoggedIn();
|
91
|
public visibleAnnotations: number;
|
92
|
public loading: boolean = false;
|
93
|
public submitted: boolean = false;
|
94
|
@Output()
|
95
|
public pidEmitter: EventEmitter<string> = new EventEmitter<string>();
|
96
|
@ViewChild('iframe') iframe: ElementRef;
|
97
|
@ViewChild('form') form: ElementRef;
|
98
|
private subscriptions: any[] = [];
|
99
|
|
100
|
constructor(private annotationService: AnnotationService) {
|
101
|
}
|
102
|
|
103
|
@HostListener('window:message', ['$event'])
|
104
|
public onChange(event) {
|
105
|
if (this.properties.b2noteAPIURL.includes(event.origin)) {
|
106
|
if (event.data === "B2NOTE loaded") {
|
107
|
let token = COOKIE.getCookie('AccessToken');
|
108
|
this.iframe.nativeElement.contentWindow.postMessage({token: token}, this.properties.b2noteAPIURL);
|
109
|
} else {
|
110
|
this.getAnnotations();
|
111
|
}
|
112
|
}
|
113
|
}
|
114
|
|
115
|
ngOnInit(): void {
|
116
|
this.visibleAnnotations = this.annotationSize;
|
117
|
if (typeof window !== "undefined") {
|
118
|
let id = this.id;
|
119
|
this.url = window.location.href;
|
120
|
if (this.landingInfo.deletedByInferenceIds) {
|
121
|
id = this.landingInfo.deletedByInferenceIds[0];
|
122
|
this.url = this.url.replace(this.id, id);
|
123
|
}
|
124
|
if (this.landingInfo.identifiers && this.landingInfo.identifiers.size > 0) {
|
125
|
if (this.landingInfo.identifiers.get('doi')) {
|
126
|
this.pid = this.landingInfo.identifiers.get('doi')[0];
|
127
|
} else {
|
128
|
const key: string = this.landingInfo.identifiers.keys().next().value;
|
129
|
if (key) {
|
130
|
this.pid = this.landingInfo.identifiers.get(key)[0];
|
131
|
}
|
132
|
}
|
133
|
}
|
134
|
if (this.pid) {
|
135
|
this.getAnnotations();
|
136
|
}
|
137
|
this.pidEmitter.emit(this.pid);
|
138
|
}
|
139
|
}
|
140
|
|
141
|
public get enabled(): boolean {
|
142
|
return this.pid && this.isLoggedIn;
|
143
|
}
|
144
|
|
145
|
private clearSubscriptions() {
|
146
|
this.subscriptions.forEach(subscription => {
|
147
|
if (subscription instanceof Subscriber) {
|
148
|
subscription.unsubscribe();
|
149
|
}
|
150
|
});
|
151
|
this.subscriptions = [];
|
152
|
}
|
153
|
|
154
|
private getAnnotations() {
|
155
|
if (!this.annotations || this.annotations.length === 0) {
|
156
|
this.loading = true;
|
157
|
}
|
158
|
this.subscriptions.push(this.annotationService.getAllAnnotations(this.pid).subscribe(annotations => {
|
159
|
this.annotations.forEach((annotation, index) => {
|
160
|
if (!annotations.find(element => element.type === annotation.type && element.text === annotation.text)) {
|
161
|
this.annotations.splice(index, 1);
|
162
|
}
|
163
|
});
|
164
|
annotations.forEach(annotation => {
|
165
|
if (!this.annotations.find(element => element.type === annotation.type && element.text === annotation.text)) {
|
166
|
annotation.targetSize = 3;
|
167
|
this.annotationService.getAnnotationTargets(annotation.text, annotation.type).subscribe(targets => {
|
168
|
annotation.targets = targets.filter(target => target.id !== this.pid);
|
169
|
});
|
170
|
this.annotations.push(annotation);
|
171
|
}
|
172
|
});
|
173
|
this.annotations = this.sort(this.annotations);
|
174
|
this.loading = false;
|
175
|
}, error => {
|
176
|
this.loading = false;
|
177
|
}));
|
178
|
}
|
179
|
|
180
|
public sort(annotations: Annotation[]): Annotation[] {
|
181
|
return annotations.sort((a, b) => {
|
182
|
if (a.type === b.type) {
|
183
|
return 1;
|
184
|
} else if (a.type === 'semantic') {
|
185
|
return -1;
|
186
|
} else if (b.type === 'semantic') {
|
187
|
return 1;
|
188
|
} else if (a.type === 'keyword') {
|
189
|
return -1;
|
190
|
} else if (b.type === 'keyword') {
|
191
|
return 1;
|
192
|
}
|
193
|
});
|
194
|
}
|
195
|
|
196
|
public searchPid(pid: string): { [k: string]: any; } {
|
197
|
return {
|
198
|
pid: pid
|
199
|
}
|
200
|
}
|
201
|
|
202
|
ngOnDestroy() {
|
203
|
this.clearSubscriptions();
|
204
|
}
|
205
|
|
206
|
toggleAnnotation(event) {
|
207
|
if (this.visible) {
|
208
|
event.preventDefault();
|
209
|
} else if(!this.submitted) {
|
210
|
this.form.nativeElement.submit();
|
211
|
this.submitted = true;
|
212
|
}
|
213
|
this.visible = !this.visible;
|
214
|
}
|
215
|
|
216
|
open(i: number) {
|
217
|
this.annotations.forEach((annotation, index) => {
|
218
|
if (index != i) {
|
219
|
annotation.targetSize = 3;
|
220
|
} else {
|
221
|
annotation.targetSize = annotation.targets.length
|
222
|
}
|
223
|
});
|
224
|
}
|
225
|
}
|