[develop | DONE | FIXED] remove b2note (annotation component) and all its references

This commit is contained in:
Alex Martzios 2024-01-11 12:49:57 +02:00
parent 6f13ab475a
commit c2312e297e
6 changed files with 1 additions and 377 deletions

View File

@ -1,225 +0,0 @@
import {
Component,
ElementRef,
EventEmitter,
HostListener,
Input,
OnDestroy,
OnInit,
Output,
ViewChild
} from "@angular/core";
import {Annotation, AnnotationService} from "./annotation.service";
import {ResultLandingInfo} from "../../utils/entities/resultLandingInfo";
import {EnvProperties} from "../../utils/properties/env-properties";
import {properties} from "../../../../environments/environment";
import {UserManagementService} from "../../services/user-management.service";
import {COOKIE, Session, User} from "../../login/utils/helper.class";
import {Subscriber} from "rxjs";
@Component({
selector: 'b2note',
template: `
<div *ngIf="annotations && annotations.length > 0" class="sideInfoTitle uk-margin-small-bottom">Annotations</div>
<div class="b2note">
<form #form ngNoForm *ngIf="pid && isLoggedIn"
[action]="properties.b2noteAPIURL + 'widget'"
method="post"
target="b2note_iframe"
class="uk-padding-small uk-padding-remove-vertical">
<!--URL of the annotated record-->
<input
type="hidden"
name="recordurl_tofeed"
[value]="url">
<!--PID of the annotated record-->
<input
type="hidden"
name="pid_tofeed"
[value]="pid">
</form>
<loading *ngIf="loading" class="uk-margin-medium-top"></loading>
<ul *ngIf="annotations && !loading" class="uk-list uk-list-divider">
<li *ngFor="let annotation of annotations.slice(0, visibleAnnotations); let i=index" uk-grid
class="uk-flex uk-flex-top uk-margin-remove-left">
<div [ngClass]="annotation.type" class="type">{{annotation.type}}</div>
<div [class.uk-width-1-3]="annotation.targets"
[class.uk-width-1-6@s]="annotation.targets">{{annotation.text}}</div>
<ul class="uk-width-expand uk-list uk-margin-remove-top" *ngIf="annotation.targets">
<li *ngFor="let target of annotation.targets.slice(0, annotation.targetSize)">
<a *ngIf="target.url" [href]="target.url" target="_blank">{{target.id}}</a>
<a *ngIf="!target.url" routerLink="/search/result"
[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>
</ul>
</li>
</ul>
<div *ngIf="visibleAnnotations < annotations.length" class="uk-margin-medium-top uk-text-center">
<button class="uk-button uk-button-primary"
(click)="visibleAnnotations = (visibleAnnotations + annotationSize)">Load More
</button>
</div>
</div>
<div [class.uk-hidden]="!visible">
<div class="widget-container" cdkDrag>
<button type="button" class="close" aria-label="Close" (click)="toggleAnnotation($event)">
<span aria-hidden="true">×</span>
</button>
<iframe #iframe id="b2note_iframe" name="b2note_iframe" class="b2note-iframe">
</iframe>
</div>
</div>`,
styleUrls: ['annotation.css']
})
export class AnnotationComponent implements OnInit, OnDestroy {
@Input()
public landingInfo: ResultLandingInfo = null;
@Input()
public id: string = null;
public properties: EnvProperties = properties;
public url: string = null;
public pid: string = null;
public keywords: string[] = [];
public visible: boolean = false;
public annotations: Annotation[] = [];
public annotationSize: number = 10;
public isLoggedIn: boolean = Session.isLoggedIn();
public visibleAnnotations: number;
public loading: boolean = false;
public submitted: boolean = false;
@Output()
public pidEmitter: EventEmitter<string> = new EventEmitter<string>();
@ViewChild('iframe') iframe: ElementRef;
@ViewChild('form') form: ElementRef;
private subscriptions: any[] = [];
constructor(private annotationService: AnnotationService) {
}
@HostListener('window:message', ['$event'])
public onChange(event) {
if (this.properties.b2noteAPIURL.includes(event.origin)) {
if (event.data === "B2NOTE loaded") {
let token = COOKIE.getCookie('AccessToken');
this.iframe.nativeElement.contentWindow.postMessage({token: token}, this.properties.b2noteAPIURL);
} else {
this.getAnnotations();
}
}
}
ngOnInit(): void {
this.visibleAnnotations = this.annotationSize;
if (typeof window !== "undefined") {
let id = this.id;
this.url = window.location.href;
if (this.landingInfo.deletedByInferenceIds) {
id = this.landingInfo.deletedByInferenceIds[0];
this.url = this.url.replace(this.id, id);
}
if (this.landingInfo.identifiers && this.landingInfo.identifiers.size > 0) {
if (this.landingInfo.identifiers.get('doi')) {
this.pid = this.landingInfo.identifiers.get('doi')[0];
} else {
const key: string = this.landingInfo.identifiers.keys().next().value;
if (key) {
this.pid = this.landingInfo.identifiers.get(key)[0];
}
}
}
if (this.pid) {
this.getAnnotations();
}
this.pidEmitter.emit(this.pid);
}
}
public get enabled(): boolean {
return this.pid && this.isLoggedIn;
}
private clearSubscriptions() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
this.subscriptions = [];
}
private getAnnotations() {
if (!this.annotations || this.annotations.length === 0) {
this.loading = true;
}
this.subscriptions.push(this.annotationService.getAllAnnotations(this.pid).subscribe(annotations => {
this.annotations.forEach((annotation, index) => {
if (!annotations.find(element => element.type === annotation.type && element.text === annotation.text)) {
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.getAnnotationTargets(annotation.text, annotation.type).subscribe(targets => {
annotation.targets = targets.filter(target => target.id !== this.pid);
});
this.annotations.push(annotation);
}
});
this.annotations = this.sort(this.annotations);
this.loading = false;
}, error => {
this.loading = false;
}));
}
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 {
pid: pid
}
}
ngOnDestroy() {
this.clearSubscriptions();
}
toggleAnnotation(event) {
if (this.visible) {
event.preventDefault();
} else if(!this.submitted) {
this.form.nativeElement.submit();
this.submitted = true;
}
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

@ -1,41 +0,0 @@
.widget-container {
position: fixed;
left: 50%;
top: 50%;
z-index: 1000;
padding: 19px;
margin-left: -167px;
margin-top: -311px;
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2),
0 2px 2px 0 rgba(0, 0, 0, 0.14),
0 1px 5px 0 rgba(0, 0, 0, 0.12);
border: 1px solid #e3e3e3;
border-radius: 4px;
outline: 0;
min-height: 20px;
background-color: #f5f5f5;
cursor: move;
}
.widget-container:hover, .widget-container:active{
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14),
0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.close {
float: right;
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
font-size: 21px;
font-weight: bold;
opacity: 0.2;
}
.b2note-iframe {
width: 100%;
height: 600px;
border: 1px solid #dddddd;
}

View File

@ -1,13 +0,0 @@
import {NgModule} from "@angular/core";
import {AnnotationComponent} from "./annotation.component";
import {CommonModule} from "@angular/common";
import {DragDropModule} from "@angular/cdk/drag-drop";
import {RouterModule} from "@angular/router";
import {LoadingModule} from "../../utils/loading/loading.module";
@NgModule({
imports: [CommonModule, DragDropModule, RouterModule, LoadingModule],
declarations: [AnnotationComponent],
exports: [AnnotationComponent]
})
export class AnnotationModule {}

View File

@ -1,95 +0,0 @@
import {Injectable} from "@angular/core";
import {HttpClient} from "@angular/common/http";
import {Observable} from "rxjs";
import {EnvProperties} from "../../utils/properties/env-properties";
import {map} from "rxjs/operators";
import {properties} from "../../../../environments/environment";
export interface AnnotationTarget {
id: string;
url: string;
}
export interface Annotation {
text: string;
type: 'semantic' | 'keyword' | 'comment';
targets?: AnnotationTarget[];
targetSize?: number;
}
@Injectable({
providedIn: "root"
})
export class AnnotationService {
api = 'api/';
constructor(private http: HttpClient) {
}
getAllAnnotations(source: string): Observable<Annotation[]> {
let url = properties.b2noteAPIURL + this.api + 'annotations?target-id[]=' + encodeURIComponent(source);
return this.http.get<Annotation[]>(url).pipe(map((response: any[]) => {
return this.parseAnnotations(response);
}));
}
getAnnotationTargets(value: string, type: 'semantic' | 'keyword' | 'comment'): Observable<AnnotationTarget[]> {
let url = properties.b2noteAPIURL + this.api + 'annotations?value=' + encodeURIComponent(value) + '&type[]=' + type;
return this.http.get<AnnotationTarget[]>(url).pipe(map((response: any[]) => {
return this.parseAnnotationTargets(response);
}));
}
private parseAnnotations(response: any[]): Annotation[] {
let annotations: Annotation[] = [];
if (response && response.length > 0) {
response.forEach(value => {
if (value.visibility === 'public') {
let body = value.body;
if (body.type === 'TextualBody') {
if (body.purpose === 'tagging') {
annotations.push({
text: body.value,
type: "keyword"
});
} else {
annotations.push({
text: body.value,
type: "comment"
});
}
} 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[]): AnnotationTarget[] {
let targets: AnnotationTarget[] = [];
if (response && response.length > 0) {
response.forEach(value => {
if (value.visibility === 'public') {
targets.push({
id: value.target.id,
url: value.target.source
});
}
});
}
return targets;
}
}

View File

@ -134,7 +134,6 @@ export class ResultLandingComponent {
public isLoggedIn: boolean = false;
public pid: string;
// @ViewChild("annotation") annotation: AnnotationComponent;
public contextsWithLink: any;
public relatedClassFilters: Option[]=[{"label": "All relations", "value": ""}];

View File

@ -20,7 +20,6 @@ import {ShowAuthorsModule} from "../../utils/authors/showAuthors.module";
import {HelperModule} from "../../utils/helper/helper.module";
import {ResultLandingUtilsModule} from "../landing-utils/resultLandingUtils.module";
import {AlertModalModule} from "../../utils/modal/alertModal.module";
import {AnnotationModule} from "../annotation/annotation.module";
import {LandingHeaderModule} from "../landing-utils/landing-header/landing-header.module";
import {NoLoadPaging} from "../../searchPages/searchUtils/no-load-paging.module";
import {ResultPreviewModule} from "../../utils/result-preview/result-preview.module";
@ -45,7 +44,7 @@ import {EntityActionsModule} from "../../utils/entity-actions/entity-actions.mod
CiteThisModule, PagingModule, IFrameModule,
AltMetricsModule, Schema2jsonldModule, SEOServiceModule,
DeletedByInferenceModule, ShowAuthorsModule, HelperModule, ResultLandingUtilsModule, AlertModalModule,
AnnotationModule, LandingHeaderModule, NoLoadPaging, ResultPreviewModule, FeedbackModule, TabsModule, LoadingModule,
LandingHeaderModule, NoLoadPaging, ResultPreviewModule, FeedbackModule, TabsModule, LoadingModule,
OrcidModule, IconsModule, InputModule, EGIDataTransferModule, RecaptchaModule,
SdgFosSuggestModule, FullScreenModalModule, SafeHtmlPipeModule, EntityActionsModule
],