Project

General

Profile

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, 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 && user"
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/advanced/research-outcomes"
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 user;
91
  public visibleAnnotations: number;
92
  public loading: boolean = false;
93
  public submitted: boolean = false;
94
  @Output()
95
  public userEmitter: EventEmitter<User> = new EventEmitter<User>();
96
  @Output()
97
  public pidEmitter: EventEmitter<string> = new EventEmitter<string>();
98
  @ViewChild('iframe') iframe: ElementRef;
99
  @ViewChild('form') form: ElementRef;
100
  private subscriptions: any[] = [];
101
  
102
  constructor(private annotationService: AnnotationService,
103
              private userManagementService: UserManagementService) {
104
  }
105
  
106
  @HostListener('window:message', ['$event'])
107
  public onChange(event) {
108
    if (this.properties.b2noteAPIURL.includes(event.origin)) {
109
      if (event.data === "B2NOTE loaded") {
110
        let token = COOKIE.getCookie('AccessToken');
111
        this.iframe.nativeElement.contentWindow.postMessage({token: token}, this.properties.b2noteAPIURL);
112
      } else {
113
        this.getAnnotations();
114
      }
115
    }
116
  }
117
  
118
  ngOnInit(): void {
119
    this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
120
      this.user = user;
121
      this.userEmitter.emit(this.user);
122
    }));
123
    this.visibleAnnotations = this.annotationSize;
124
    if (typeof window !== "undefined") {
125
      let id = this.id;
126
      this.url = window.location.href;
127
      if (this.landingInfo.deletedByInferenceIds) {
128
        id = this.landingInfo.deletedByInferenceIds[0];
129
        this.url = this.url.replace(this.id, id);
130
      }
131
      if (this.landingInfo.identifiers && this.landingInfo.identifiers.size > 0) {
132
        if (this.landingInfo.identifiers.get('doi')) {
133
          this.pid = this.landingInfo.identifiers.get('doi')[0];
134
        } else {
135
          const key: string = this.landingInfo.identifiers.keys().next().value;
136
          if (key) {
137
            this.pid = this.landingInfo.identifiers.get(key)[0];
138
          }
139
        }
140
      }
141
      if (this.pid) {
142
        this.getAnnotations();
143
      }
144
      this.pidEmitter.emit(this.pid);
145
    }
146
  }
147
  
148
  public get enabled(): boolean {
149
    return this.pid && this.user;
150
  }
151
  
152
  private clearSubscriptions() {
153
    this.subscriptions.forEach(subscription => {
154
      if (subscription instanceof Subscriber) {
155
        subscription.unsubscribe();
156
      }
157
    });
158
    this.subscriptions = [];
159
  }
160
  
161
  private getAnnotations() {
162
    if (!this.annotations || this.annotations.length === 0) {
163
      this.loading = true;
164
    }
165
    this.subscriptions.push(this.annotationService.getAllAnnotations(this.pid).subscribe(annotations => {
166
      this.annotations.forEach((annotation, index) => {
167
        if (!annotations.find(element => element.type === annotation.type && element.text === annotation.text)) {
168
          this.annotations.splice(index, 1);
169
        }
170
      });
171
      annotations.forEach(annotation => {
172
        if (!this.annotations.find(element => element.type === annotation.type && element.text === annotation.text)) {
173
          annotation.targetSize = 3;
174
          this.annotationService.getAnnotationTargets(annotation.text, annotation.type).subscribe(targets => {
175
            annotation.targets = targets.filter(target => target.id !== this.pid);
176
            /*for(let i = 0; i < 10; i++) {
177
              annotation.targets.push(targets[0]);
178
            }*/
179
          });
180
          this.annotations.push(annotation);
181
        }
182
      });
183
      this.annotations = this.sort(this.annotations);
184
      this.loading = false;
185
    }, error => {
186
      this.loading = false;
187
    }));
188
  }
189
  
190
  public sort(annotations: Annotation[]): Annotation[] {
191
    return annotations.sort((a, b) => {
192
      if (a.type === b.type) {
193
        return 1;
194
      } else if (a.type === 'semantic') {
195
        return -1;
196
      } else if (b.type === 'semantic') {
197
        return 1;
198
      } else if (a.type === 'keyword') {
199
        return -1;
200
      } else if (b.type === 'keyword') {
201
        return 1;
202
      }
203
    });
204
  }
205
  
206
  public searchPid(pid: string): { [k: string]: any; } {
207
    return {
208
      f0: 'pid',
209
      fv0: pid,
210
      qf: false
211
    }
212
  }
213
  
214
  ngOnDestroy() {
215
    this.clearSubscriptions();
216
  }
217
  
218
  toggleAnnotation(event) {
219
    if (this.visible) {
220
      event.preventDefault();
221
    } else if(!this.submitted) {
222
      this.form.nativeElement.submit();
223
      this.submitted = true;
224
    }
225
    this.visible = !this.visible;
226
  }
227
  
228
  open(i: number) {
229
    this.annotations.forEach((annotation, index) => {
230
      if (index != i) {
231
        annotation.targetSize = 3;
232
      } else {
233
        annotation.targetSize = annotation.targets.length
234
      }
235
    });
236
  }
237
}
(1-1/4)