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, 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
}
(1-1/4)