diff --git a/src/app/core/config/config.model.ts b/src/app/core/config/config.model.ts index 723c03750..350dd0ef3 100644 --- a/src/app/core/config/config.model.ts +++ b/src/app/core/config/config.model.ts @@ -81,6 +81,7 @@ export interface Config { disableKetcher?: boolean; useApprovalAPI?: boolean; dummyWhoami?: Auth; + enableStructureFeatures?: boolean; } export interface StagingAreaSettings { diff --git a/src/app/core/structure-editor/structure-editor-implementation.model.ts b/src/app/core/structure-editor/structure-editor-implementation.model.ts index a52292c9e..6202b3613 100644 --- a/src/app/core/structure-editor/structure-editor-implementation.model.ts +++ b/src/app/core/structure-editor/structure-editor-implementation.model.ts @@ -96,8 +96,7 @@ export class EditorImplementation implements Editor { getSmiles(): Observable { if (this.ketcher != null) { - return from(this.ketcher.getSmiles()).pipe(switchMap(data => { - return data;})); + return from(this.ketcher.getSmiles()); } else if (this.jsdraw != null) { return new Observable(observer => { observer.next(this.jsdraw.getSmiles()); @@ -144,6 +143,7 @@ export class EditorImplementation implements Editor { setMolecule(molfile: string): void { if (this.ketcher && this.ketcher != null) { this.ketcher.setMolecule(molfile); + this.ketcher.setMolecule(molfile); } else if (this.jsdraw && this.jsdraw != null) { // from simple tests, this should push the current molecule down // on the undo stack. diff --git a/src/app/core/structure-editor/structure-editor.component.ts b/src/app/core/structure-editor/structure-editor.component.ts index 0d504a880..1e583c618 100644 --- a/src/app/core/structure-editor/structure-editor.component.ts +++ b/src/app/core/structure-editor/structure-editor.component.ts @@ -83,7 +83,7 @@ export class StructureEditorComponent implements OnInit, AfterViewInit, OnDestro window.removeEventListener('drop', this.preventDrag); window.removeEventListener('dragover', this.preventDrag); window.removeEventListener('paste', this.checkPaste); - (this.myCanvas.nativeElement).removeEventListener('click', this.click); + (this.myCanvas.nativeElement).removeEventListener('click', this.listener); delete this.ketcher; let parentElement = document.getElementById('ketcherwrapper'); let childElement = document.getElementById('root'); @@ -118,14 +118,14 @@ export class StructureEditorComponent implements OnInit, AfterViewInit, OnDestro } listener = () => { - /* var elmR=document.getElementById("root"); + var elmR=document.getElementById("root"); if(this.structureEditor==="ketcher"){ if( elmR && elmR.querySelector(":focus-within")){ this.getSketcher().activated=true; }else{ this.getSketcher().activated=false; } - }*/ + } } private preventDrag = (event: DragEvent) => { @@ -135,8 +135,8 @@ export class StructureEditorComponent implements OnInit, AfterViewInit, OnDestro // override JSDraw for Molvec paste event. Using the JSDraw menu copy function seems to ignore this at first checkPaste = (event: ClipboardEvent ) => { - - if ((this.jsdraw || this.ketcher ) && this.getSketcher().activated) { + console.log('check paste'); + if ((this.jsdraw || this.ketcher )&& this.getSketcher().activated) { event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); @@ -156,7 +156,7 @@ export class StructureEditorComponent implements OnInit, AfterViewInit, OnDestro ngOnInit() { // window.addEventListener('keyup',this.listener); - // window.addEventListener('click',this.listener); + window.addEventListener('click',this.listener); this.overlayContainer = this.overlayContainerService.getContainerElement(); @@ -346,7 +346,6 @@ export class StructureEditorComponent implements OnInit, AfterViewInit, OnDestro this.ketcher.getMolfile().then(result => { let mfile = [null]; mfile[0]= result; - // this.getSketcher().setFile(mfile[0], "mol"); this.getSketcher().setFile(mfile[0], "mol"); }) } @@ -398,13 +397,38 @@ export class StructureEditorComponent implements OnInit, AfterViewInit, OnDestro sendToMolvec(img: string) { this.canvasMessage = ''; this.loadingService.setLoading(true); + console.log('sending to molvec'); + console.log(img); this.structureService.molvec(img).subscribe(response => { const mol = response.molfile; - if (this.ketcher) { - // this.ketcher.setMolecule(mol); + console.log(response); + if (this.ketcher && this.structureEditor === 'ketcher') { + this.ketcher.setMolecule(mol); + setTimeout(() => { + this.editor.setMolecule(mol); + }, 100); + this.loadedMolfile.emit(mol); + + this.loadingService.setLoading(false); + this.structureService.molvec(img).subscribe(resp => { + setTimeout(() => { + this.editor.setMolecule(resp.molfile); + this.ketcher.setMolecule(mol); + }, 100); + }, error => { + this.canvasMessage = 'Structure not detectable'; + this.loadingService.setLoading(false); + }); + } - this.loadedMolfile.emit(mol); - this.loadingService.setLoading(false); + else { + console.log('not ketcher'); + this.jsdraw.setMolfile(mol); + this.loadingService.setLoading(false); + this.loadedMolfile.emit(mol); + + } + }, error => { this.canvasMessage = 'Structure not detectable'; this.loadingService.setLoading(false); @@ -450,6 +474,7 @@ export class StructureEditorComponent implements OnInit, AfterViewInit, OnDestro if (items[i].type.indexOf('image') !== -1) { event.preventDefault(); event.stopPropagation(); + this.canvasMessage = ''; valid = true; send.type = 'image'; const reader = new FileReader(); @@ -465,13 +490,30 @@ export class StructureEditorComponent implements OnInit, AfterViewInit, OnDestro } else if (items[i].type === 'text/plain') { const text = event.clipboardData.getData('text/plain'); if (text.indexOf(' { + if (response.structure && response.structure.molfile) { - this.ketcher.setMolecule(response.structure.molfile); + + this.editor.setMolecule(response.structure.molfile); + this.loadedMolfile.emit(response.structure.molfile); + + if(response.structure.smiles === '') { + this.canvasMessage = 'empty or invalid structure pasted'; + } + } else { + this.canvasMessage = 'Structure text not recognized'; } + this.loadingService.setLoading(false); + + },error =>{ + this.loadingService.setLoading(false); + this.canvasMessage = 'empty or invalid structure pasted'; }); } } diff --git a/src/app/core/structure/structure-post-response.model.ts b/src/app/core/structure/structure-post-response.model.ts index 394801649..9b8e08b9c 100644 --- a/src/app/core/structure/structure-post-response.model.ts +++ b/src/app/core/structure/structure-post-response.model.ts @@ -8,6 +8,7 @@ export interface InterpretStructureResponse { structure: SubstanceStructure; moieties: Array; structuralUnits: Array; + featureList?: Array; } export interface ResolverResponse { diff --git a/src/app/core/substance-form/structure/substance-form-structure-card.component.html b/src/app/core/substance-form/structure/substance-form-structure-card.component.html index 5e7f9b789..2ed0c293e 100644 --- a/src/app/core/substance-form/structure/substance-form-structure-card.component.html +++ b/src/app/core/substance-form/structure/substance-form-structure-card.component.html @@ -1,13 +1,34 @@
- +
{{userMessage}}
+
+
+ + + Structure Features + + + + + + + + + + + + +
Feature{{element.key}}Value{{element.value}}
+
+
+
diff --git a/src/app/core/substance-form/structure/substance-form-structure-card.component.scss b/src/app/core/substance-form/structure/substance-form-structure-card.component.scss index f26adf203..ff3deeb27 100644 --- a/src/app/core/substance-form/structure/substance-form-structure-card.component.scss +++ b/src/app/core/substance-form/structure/substance-form-structure-card.component.scss @@ -43,6 +43,25 @@ } } + .feature-table { + display:block; + margin: auto; + width: 85%; + } + + .feature-expansion { + width:100%; + justify-content: center; + } + + .full-width { + width: 100%; + } + + tr.mat-row, tr.mat-footer-row { + height: 32px; +} + .SUCCESS { color: var(--success-green-color); background-color: var(--success-green-bg-color); diff --git a/src/app/core/substance-form/structure/substance-form-structure-card.component.ts b/src/app/core/substance-form/structure/substance-form-structure-card.component.ts index c7fbb0efe..de03874fb 100644 --- a/src/app/core/substance-form/structure/substance-form-structure-card.component.ts +++ b/src/app/core/substance-form/structure/substance-form-structure-card.component.ts @@ -18,6 +18,9 @@ import { SubstanceFormStructuralUnitsService } from '../structural-units/substan import { SubstanceFormStructureService } from './substance-form-structure.service'; import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; import { StructureEditorComponent } from '@gsrs-core/structure-editor'; +import { take } from 'rxjs/operators'; +import { ConfigService } from '@gsrs-core/config'; +import { MatTableDataSource } from '@angular/material/table'; @Component({ selector: 'app-substance-form-structure-card', @@ -32,10 +35,15 @@ export class SubstanceFormStructureCardComponent extends SubstanceFormBase imple substanceType: string; smiles: string; mol: string; + features: Array; isInitializing = true; private overlayContainer: HTMLElement; structureErrorsArray: Array; subscriptions: Array = []; + privateFeatures: any; + enableStructureFeatures = true; + sortedFeatures = new MatTableDataSource(); + displayedColumns = ['key', 'value']; @ViewChild(StructureEditorComponent) structureEditorComponent!: StructureEditorComponent; constructor( @@ -49,7 +57,8 @@ export class SubstanceFormStructureCardComponent extends SubstanceFormBase imple private substanceService: SubstanceService, private substanceFormStructuralUnitsService: SubstanceFormStructuralUnitsService, private activatedRoute: ActivatedRoute, - private router: Router + private router: Router, + private configService: ConfigService ) { super(); } @@ -155,12 +164,37 @@ export class SubstanceFormStructureCardComponent extends SubstanceFormBase imple this.structureService.interpretStructure(molfile).subscribe(response => { this.processStructurePostResponse(response); this.structure.molfile = molfile; + this.smiles = response.structure.smiles; }); } } processStructurePostResponse(structurePostResponse?: InterpretStructureResponse): void { if (structurePostResponse && structurePostResponse.structure) { + if (structurePostResponse.featureList && structurePostResponse.featureList.length > 0) { + let temp = []; + Object.keys(structurePostResponse.featureList[0]).forEach(key => { + let label = key; + if(key === 'categoryScore'){ + label = 'Category Score'; + } + if(key === 'sumOfScores'){ + label = 'Sum Of Scores'; + } + temp.push({'key': label,'value': structurePostResponse.featureList[0][key] }); + }); + let customSort = (array: any[]): any[] => { + return array.sort((a, b) => { + if (a.key === 'Category Score') return -1; + if (b.key === 'Category Score') return 1; + if (a.key === 'Sum Of Scores') return a.key === 'Category Score' ? 1 : -1; + if (b.key === 'Sum Of Scores') return b.key === 'Category Score' ? -1 : 1; + return a.key.localeCompare(b.key); + }); + }; + this.features = customSort(temp); + this.sortedFeatures = new MatTableDataSource(this.features); + } // we should only be dealing with this stuff if the total hash changes // or if the charge changes, or if it's a polymer @@ -225,13 +259,13 @@ export class SubstanceFormStructureCardComponent extends SubstanceFormBase imple } openStructureExportDialog(): void { - + this.structureEditor.getSmiles().pipe(take(1)).subscribe(resp => { const dialogRef = this.dialog.open(StructureExportComponent, { height: 'auto', width: '650px', data: { molfile: this.mol, - smiles: this.smiles, + smiles: resp, type: this.substanceType } }); @@ -242,6 +276,7 @@ export class SubstanceFormStructureCardComponent extends SubstanceFormBase imple }, () => { this.overlayContainer.style.zIndex = null; }); + }); } openNameResolverDialog(): void { @@ -303,16 +338,20 @@ export class SubstanceFormStructureCardComponent extends SubstanceFormBase imple structure: response.structure.id } }; + if (this.configService.configData && this.configService.configData.gsrsHomeBaseUrl) { + console.log(this.configService.configData.gsrsHomeBaseUrl); + let url = this.configService.configData.gsrsHomeBaseUrl + '/structure-search?structure=' + response.structure.id; + window.open(url, '_blank'); + } else { - const url = this.router.serializeUrl( - this.router.createUrlTree(['/structure-search/'], { - queryParams: navigationExtras.queryParams}) - ); - - this.loadingService.setLoading(false); - window.open(url, '_blank'); - - + } + const urlTree = this.router.createUrlTree(['/structure-search/'], { + queryParams: navigationExtras.queryParams, + queryParamsHandling: 'merge', + preserveFragment: true + }); + console.log(urlTree); + window.open(urlTree.toString(), '_blank'); }, error => { this.loadingService.setLoading(false); }); diff --git a/src/app/core/substance-form/structure/substance-form-structure.module.ts b/src/app/core/substance-form/structure/substance-form-structure.module.ts index 589fb9ef0..97a8eca5e 100644 --- a/src/app/core/substance-form/structure/substance-form-structure.module.ts +++ b/src/app/core/substance-form/structure/substance-form-structure.module.ts @@ -13,6 +13,8 @@ import { DragDropPasteDirective } from '@gsrs-core/substance-form/structure/drag import {MatIconModule} from '@angular/material/icon'; import {MatMenuModule} from '@angular/material/menu'; import {MatButtonModule} from '@angular/material/button'; +import { MatTableModule } from '@angular/material/table'; +import { MatExpansionModule } from '@angular/material/expansion'; @NgModule({ imports: [ @@ -28,7 +30,9 @@ import {MatButtonModule} from '@angular/material/button'; NameResolverModule, MatMenuModule, MatIconModule, - MatButtonModule + MatButtonModule, + MatTableModule, + MatExpansionModule ], declarations: [ SubstanceFormStructureCardComponent,