Skip to content

Commit

Permalink
added the popup #16
Browse files Browse the repository at this point in the history
  • Loading branch information
tmushayahama committed May 6, 2020
1 parent dd9b8e1 commit d328fd9
Show file tree
Hide file tree
Showing 14 changed files with 466 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/@noctua.editor/index.ts
@@ -0,0 +1 @@
export * from './noctua-editor.module';
145 changes: 145 additions & 0 deletions src/@noctua.editor/inline-reference/inline-reference.service.ts
@@ -0,0 +1,145 @@
import { Injectable, Inject, Injector, ElementRef, ComponentRef, ViewChild } from '@angular/core';
import {
Overlay,
OverlayRef,
OverlayConfig,
OriginConnectionPosition,
OverlayConnectionPosition,
PositionStrategy
} from '@angular/cdk/overlay';
import { ComponentPortal, PortalInjector } from '@angular/cdk/portal';
import { ReferenceDropdownOverlayRef } from './reference-dropdown/reference-dropdown-ref';
import { referenceDropdownData } from './reference-dropdown/reference-dropdown.tokens';

import { NoctuaReferenceDropdownComponent } from './reference-dropdown/reference-dropdown.component';

export interface SearchCriiteria {
gp: string;
url: string;
}

export interface ReferenceDropdownDialogConfig {
panelClass?: string;
hasBackdrop?: boolean;
backdropClass?: string;
positionStrategy?: PositionStrategy;
width?: string;
data?: any;
}

const DEFAULT_CONFIG: ReferenceDropdownDialogConfig = {
hasBackdrop: true,
backdropClass: 'dark-backdrop',
panelClass: 'tm-file-preview-dialog-panel',
// width: '600px',
data: null
};

@Injectable({
providedIn: 'root'
})
export class InlineReferenceService {

constructor(
private injector: Injector,
private overlay: Overlay) { }


open(elementToConnectTo: ElementRef, config: ReferenceDropdownDialogConfig = {}) {
const dialogConfig = { ...DEFAULT_CONFIG, ...config };

dialogConfig['positionStrategy'] = this._getPosition(elementToConnectTo);
// dialogConfig['width'] = '420px';
const originRect = elementToConnectTo.nativeElement;
const overlayRef = this.createOverlay(dialogConfig);
const dialogRef = new ReferenceDropdownOverlayRef(overlayRef);
const overlayComponent = this.attachDialogContainer(overlayRef, dialogConfig, dialogRef);

overlayRef.backdropClick().subscribe(_ => dialogRef.close());

return dialogRef;
}

close(data): void {
// this.overlayRef.dispose();
}

private createInjector(config: ReferenceDropdownDialogConfig, dialogRef: ReferenceDropdownOverlayRef): PortalInjector {
const injectionTokens = new WeakMap();

injectionTokens.set(ReferenceDropdownOverlayRef, dialogRef);
injectionTokens.set(referenceDropdownData, config.data);

return new PortalInjector(this.injector, injectionTokens);
}

private attachDialogContainer(overlayRef: OverlayRef, config: ReferenceDropdownDialogConfig, dialogRef: ReferenceDropdownOverlayRef) {
const injector = this.createInjector(config, dialogRef);

const containerPortal = new ComponentPortal(NoctuaReferenceDropdownComponent, null, injector);
const containerRef: ComponentRef<NoctuaReferenceDropdownComponent> = overlayRef.attach(containerPortal);

return containerRef.instance;
}

private createOverlay(config: ReferenceDropdownDialogConfig) {
const overlayConfig = this.getOverlayConfig(config);

return this.overlay.create(overlayConfig);
}

private getOverlayConfig(config: ReferenceDropdownDialogConfig): OverlayConfig {
const overlayConfig = new OverlayConfig({
hasBackdrop: config.hasBackdrop,
backdropClass: config.backdropClass,
width: config.width,
panelClass: config.panelClass,
scrollStrategy: this.overlay.scrollStrategies.block(),
positionStrategy: config.positionStrategy
});

return overlayConfig;
}

private _getPosition(elementToConnectTo: ElementRef) {
const origin = {
topLeft: { originX: 'start', originY: 'top' } as OriginConnectionPosition,
topRight: { originX: 'end', originY: 'top' } as OriginConnectionPosition,
bottomLeft: { originX: 'start', originY: 'bottom' } as OriginConnectionPosition,
bottomRight: { originX: 'end', originY: 'bottom' } as OriginConnectionPosition,
topCenter: { originX: 'center', originY: 'top' } as OriginConnectionPosition,
bottomCenter: { originX: 'center', originY: 'bottom' } as OriginConnectionPosition
};

const overlay = {
topLeft: { overlayX: 'start', overlayY: 'top' } as OverlayConnectionPosition,
topRight: { overlayX: 'end', overlayY: 'top' } as OverlayConnectionPosition,
bottomLeft: { overlayX: 'start', overlayY: 'bottom' } as OverlayConnectionPosition,
bottomRight: { overlayX: 'end', overlayY: 'bottom' } as OverlayConnectionPosition,
topCenter: { overlayX: 'center', overlayY: 'top' } as OverlayConnectionPosition,
bottomCenter: { overlayX: 'center', overlayY: 'bottom' } as OverlayConnectionPosition
};

return this.overlay.position()
.flexibleConnectedTo(elementToConnectTo)
.withFlexibleDimensions(true)
.withPush(true)
.withPositions([{
overlayX: 'end',
overlayY: 'top',
originX: 'end',
originY: 'bottom'
}]);
//.withOffsetY(1)
//.withDirection('ltr')
//.withFallbackPosition(origin.bottomRight, overlay.topRight)
//.withFallbackPosition(origin.topLeft, overlay.bottomLeft)
//.withFallbackPosition(origin.topRight, overlay.bottomRight)
// .withFallbackPosition(origin.topCenter, overlay.bottomCenter)
// .withFallbackPosition(origin.bottomCenter, overlay.topCenter)
}

getLink() {

}
}
@@ -0,0 +1,10 @@
import { OverlayRef } from '@angular/cdk/overlay';

export class ReferenceDropdownOverlayRef {

constructor(private overlayRef: OverlayRef) { }

close(): void {
this.overlayRef.dispose();
}
}
@@ -0,0 +1,35 @@
<form [formGroup]="evidenceDBForm" novalidate class="pl-8 pr-8 w-100-p" fxLayout="column" fxLayoutAlign="start stretch">
<div class="w-100-p" fxLayout="row" fxLayoutAlign="start center">
<mat-form-field appearance="outline" fxFlex="100px" class="noc-sm mr-12">
<mat-select placeholder="" formControlName="db">
<mat-option *ngFor="let evidenceDB of noctuaFormConfigService.evidenceDBs.options" [value]="evidenceDB">
{{evidenceDB.label}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline" fxFlex="" class="noc-sm w-100-p">
<input matInput formControlName="accession" type="text" placeholder="Accession" autocomplete="off">
</mat-form-field>
<button mat-icon-button (click)="close()">
<mat-icon>cancel</mat-icon>
</button>
<button mat-icon-button (click)="save()">
<mat-icon>check_circle</mat-icon>
</button>
</div>
<div class="w-100-p" fxLayout="row" fxLayoutAlign="start center">
<div *ngIf="article" class="noc-article-info" fxLayout="column" fxLayoutAlign="start stretch">
<div class="noc-article-title w-100-p">
<a (click)="$event.stopPropagation()" href="{{article.link}}" target="_blank">
{{article.title}}
</a>
</div>
<div class="noc-article-author w-100-p">
<mat-icon class="s-16 mr-4">person</mat-icon> <span>{{article.author}}</span>
</div>
<div class="noc-article-date w-100-p">
<mat-icon class="s-16 mr-4">date_range</mat-icon> <span>{{article.date}}</span>
</div>
</div>
</div>
</form>
@@ -0,0 +1,32 @@
@import "src/@noctua/scss/noctua";
@import "src/@noctua.common/scss/noctua.common";

:host {
padding-top: 8px;
width: 100%;
@include deep-width(400px);
@include mat-elevation(4);

background-color: #fbf9de;

.noc-edit-field {
@include deep-width(300px);
}

.noc-article-info {
padding: 12px 5px;

.noc-article-title {
font-size: 12px;
max-height: 60px;
overflow: hidden;
}

.noc-article-author {
max-height: 60px;
overflow: hidden;
}

.noc-article-date {}
}
}
@@ -0,0 +1,125 @@
import { Component, Inject, OnInit, OnDestroy } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';

import {
NoctuaFormConfigService,
NoctuaAnnotonFormService,
AnnotonError,
noctuaFormConfig,
Article,
NoctuaLookupService
} from 'noctua-form-base';

import { referenceDropdownData } from './reference-dropdown.tokens';
import { ReferenceDropdownOverlayRef } from './reference-dropdown-ref';
//import { NoctuaFormDialogService } from 'app/main/apps/noctua-form';
import { SparqlService } from '@noctua.sparql/services/sparql/sparql.service';

@Component({
selector: 'noc-reference-dropdown',
templateUrl: './reference-dropdown.component.html',
styleUrls: ['./reference-dropdown.component.scss']
})

export class NoctuaReferenceDropdownComponent implements OnInit, OnDestroy {
evidenceDBForm: FormGroup;
formControl: FormControl;
article: Article;

private _unsubscribeAll: Subject<any>;

constructor(public dialogRef: ReferenceDropdownOverlayRef,
@Inject(referenceDropdownData) public data: any,
private noctuaLookupService: NoctuaLookupService,
// private noctuaFormDialogService: NoctuaFormDialogService,
public noctuaFormConfigService: NoctuaFormConfigService,
public noctuaAnnotonFormService: NoctuaAnnotonFormService,
) {
this._unsubscribeAll = new Subject();
this.formControl = data.formControl;
}

ngOnInit(): void {
this.evidenceDBForm = this._createEvidenceDBForm();
this._onValueChange();
}

clearValues() {

}

save() {
const self = this;
const db = this.evidenceDBForm.value.db;
const accession = this.evidenceDBForm.value.accession;
const errors = [];
let canSave = true;

if (accession.trim() === '') {
const error = new AnnotonError('error', 1, `${db.name} accession is required`);
errors.push(error);
// self.noctuaFormDialogService.openAnnotonErrorsDialog(errors);
canSave = false;
}

if (canSave) {
this.formControl.setValue(db.name + ':' + accession.trim());
this.close();
}
}

cancelEvidenceDb() {
this.evidenceDBForm.controls['accession'].setValue('');
}

private _createEvidenceDBForm() {
return new FormGroup({
db: new FormControl(this.noctuaFormConfigService.evidenceDBs.selected),
accession: new FormControl('',
[
Validators.required,
])
});
}

private _onValueChange() {
const self = this;

self.evidenceDBForm.valueChanges.pipe(
takeUntil(this._unsubscribeAll),
distinctUntilChanged(),
debounceTime(400)
).subscribe(data => {
self.article = null;
self._updateArticle(data);
});
}

close() {
this.dialogRef.close();
}

private _updateArticle(value) {
const self = this;

if (value.db.name === noctuaFormConfig.evidenceDB.options.pmid.name && value.accession) {
const pmid = value.accession.trim();

if (pmid === '') {
return;
}
this.noctuaLookupService.getPubmedInfo(pmid).pipe(
takeUntil(this._unsubscribeAll))
.subscribe((article: Article) => {
self.article = article;
});
}
}

ngOnDestroy(): void {
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}
@@ -0,0 +1,3 @@
import { InjectionToken } from '@angular/core';

export const referenceDropdownData = new InjectionToken<any>('referenceDropdownData');
9 changes: 9 additions & 0 deletions src/@noctua.editor/models/editor-category.ts
@@ -0,0 +1,9 @@
export enum EditorCategory {
relationship = 'relationship',
term = 'term',
evidence = 'evidence',
reference = 'reference',
with = 'with',
evidenceAll = 'evidenceAll',
all = 'all'
}
27 changes: 27 additions & 0 deletions src/@noctua.editor/noctua-editor.module.ts
@@ -0,0 +1,27 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NoctuaSharedModule } from '@noctua/shared.module';
import { NoctuaReferenceDropdownComponent } from './inline-reference/reference-dropdown/reference-dropdown.component';

@NgModule({
declarations: [
NoctuaReferenceDropdownComponent,
],
imports: [
CommonModule,
RouterModule,
FormsModule,
ReactiveFormsModule,
NoctuaSharedModule
],
exports: [
NoctuaReferenceDropdownComponent,
],
entryComponents: [
NoctuaReferenceDropdownComponent,
]
})
export class NoctuaEditorModule {
}

0 comments on commit d328fd9

Please sign in to comment.