From 7cf140d75b1ea6d3906371e7535fa21764de8764 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julian=20Sp=C3=A4th?= <julian.spaeth@wzw.tum.de>
Date: Tue, 7 Apr 2020 16:37:42 +0200
Subject: [PATCH] Show drug info

---
 src/app/analysis.service.ts                   | 18 ++---
 .../analysis-window.component.ts              | 79 +++++++++++++------
 src/app/interfaces.ts                         | 10 ++-
 .../explorer-page.component.html              | 54 +++++++++----
 .../explorer-page/explorer-page.component.ts  | 60 +++++++-------
 src/styles.scss                               |  4 +
 6 files changed, 141 insertions(+), 84 deletions(-)

diff --git a/src/app/analysis.service.ts b/src/app/analysis.service.ts
index d85b8c67..e33eaae6 100644
--- a/src/app/analysis.service.ts
+++ b/src/app/analysis.service.ts
@@ -106,18 +106,18 @@ export class AnalysisService {
   showToast(task: Task, status: 'DONE' | 'FAILED') {
     let toastMessage;
     let toastType;
-    const startDate = new Date(task.info.startedAt);
-    const finishedDate = new Date(task.info.finishedAt);
+    // const startDate = new Date(task.info.startedAt);
+    // const finishedDate = new Date(task.info.finishedAt);
     if (status === 'DONE') {
-      toastMessage = `Computation finished succesfully.
-              \n- Algorithm: ${task.info.algorithm}
-              \n- Started At: ${startDate.getHours()}:${startDate.getMinutes()}
-              \n- Finished At: ${finishedDate.getHours()}:${finishedDate.getMinutes()}`;
+      toastMessage = 'Computation finished succesfully.';
+              // \n- Algorithm: ${task.info.algorithm}
+              // \n- Started At: ${startDate.getHours()}:${startDate.getMinutes()}
+              // \n- Finished At: ${finishedDate.getHours()}:${finishedDate.getMinutes()}`;
       toastType = 'is-success';
     } else if (status === 'FAILED') {
-      toastMessage = `Computation failed.
-              \n- Algorithm: ${task.info.algorithm}
-              \n- Started At: ${startDate.getHours()}:${startDate.getMinutes()}`;
+      toastMessage = 'Computation failed.';
+              // \n- Algorithm: ${task.info.algorithm}
+              // \n- Started At: ${startDate.getHours()}:${startDate.getMinutes()}`;
       toastType = 'is-danger';
     }
 
diff --git a/src/app/components/analysis-window/analysis-window.component.ts b/src/app/components/analysis-window/analysis-window.component.ts
index ccc612ef..ac64064d 100644
--- a/src/app/components/analysis-window/analysis-window.component.ts
+++ b/src/app/components/analysis-window/analysis-window.component.ts
@@ -12,7 +12,7 @@ import {
 import {HttpClient} from '@angular/common/http';
 import {environment} from '../../../environments/environment';
 import {AnalysisService} from '../../analysis.service';
-import {Protein, Task, NodeType, ViralProtein} from '../../interfaces';
+import {Protein, Task, NodeType, ViralProtein, Drug} from '../../interfaces';
 
 declare var vis: any;
 
@@ -71,23 +71,27 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
         const options = {};
 
         this.network = new vis.Network(container, this.nodeData, options);
+        this.network.on('deselectNode', (properties) => {
+          this.showDetailsChange.emit([false, [null, null, null, null, null, null]]);
+        });
         this.network.on('selectNode', (properties) => {
           const selectedNodes = this.nodeData.nodes.get(properties.nodes);
           if (selectedNodes.length > 0) {
-            let selectedProteinItem;
-            let selectedProteinName;
-            let selectedProteinType;
-            let selectedProteinAc;
-            let selectedProteinDataset;
-            let selectedProteinVirus;
+            let selectedItem;
+            let selectedName;
+            let selectedType;
+            let selectedId;
+            let selectedVirusName;
+            let selectedStatus;
             if (selectedNodes[0].nodeType === 'host') {
               const protein: Protein = {name: '', proteinAc: selectedNodes[0].id};
-              selectedProteinName = null;
-              selectedProteinDataset = null;
-              selectedProteinVirus = null;
-              selectedProteinItem = {name: selectedNodes[0].id, type: 'Host Protein', data: protein};
-              selectedProteinAc = protein.proteinAc;
-              selectedProteinType = 'Host Protein';
+              selectedVirusName = null;
+              selectedStatus = null;
+              selectedItem = {name: selectedNodes[0].id, type: 'Host Protein', data: protein};
+              // TODO use gene name here
+              selectedName = protein.proteinAc;
+              selectedId = protein.proteinAc;
+              selectedType = 'Host Protein';
               if (properties.event.srcEvent.ctrlKey) {
                 if (this.analysis.inSelection(protein.proteinAc)) {
                   this.analysis.removeItem(protein.proteinAc);
@@ -97,27 +101,45 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
                 }
               }
             } else if (selectedNodes[0].nodeType === 'virus') {
-              const virus: ViralProtein = {viralProteinId: null, effectName: selectedNodes[0].id, virusName: null, datasetName: null};
-              selectedProteinAc = null;
-              selectedProteinDataset = null;
-              selectedProteinVirus = null;
-              selectedProteinItem = {name: virus.effectName, type: 'Viral Protein', data: virus};
-              selectedProteinName = virus.effectName;
-              selectedProteinType = 'Viral Protein';
+              const virus: ViralProtein = {
+                viralProteinId: null,
+                effectName: selectedNodes[0].id,
+                virusName: null,
+                datasetName: null
+              };
+              selectedId = null;
+              selectedStatus = null;
+              selectedItem = {name: virus.effectName, type: 'Viral Protein', data: virus};
+              selectedVirusName = virus.virusName;
+              selectedName = virus.effectName;
+              selectedType = 'Viral Protein';
               if (properties.event.srcEvent.ctrlKey) {
                 if (this.analysis.inSelection(virus.effectName)) {
                   this.analysis.removeItem(virus.effectName);
                 } else {
-                  this.analysis.addItem(selectedProteinItem);
+                  this.analysis.addItem(selectedItem);
                   this.analysis.getCount();
                 }
               }
+            } else if (selectedNodes[0].nodeType === 'drug') {
+              const drug: Drug = {
+                drugId: selectedNodes[0].details.drugId,
+                name: selectedNodes[0].details.name,
+                status: selectedNodes[0].details.status,
+              };
+              selectedId = drug.drugId;
+              selectedStatus = drug.status;
+              selectedName = drug.name;
+              selectedType = 'Drug';
+              selectedItem = {name: drug.name, type: 'Drug', data: drug};
+              selectedVirusName = null;
             }
-            this.showDetailsChange.emit([true, [selectedProteinItem, selectedProteinName, selectedProteinType, selectedProteinAc,
-              selectedProteinDataset, selectedProteinVirus]]);
+            this.showDetailsChange.emit([true, [selectedItem, selectedName, selectedType,
+              selectedId, selectedVirusName, selectedStatus]]);
           } else {
             this.showDetailsChange.emit([false, [null, null, null, null, null, null]]);
           }
+
         });
 
         this.analysis.subscribe((item, selected) => {
@@ -157,6 +179,8 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
   public inferNodeType(nodeId: string): 'host' | 'virus' | 'drug' {
     if (nodeId.indexOf('-') !== -1 || nodeId.indexOf('_') !== -1) {
       return 'virus';
+    } else if (nodeId.startsWith('DB')) {
+      return 'drug';
     }
     return 'host';
   }
@@ -174,9 +198,12 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
       const nodeTypes = attributes.nodeTypes || {};
       const isSeed = attributes.isSeed || {};
       const scores = attributes.scores || {};
+      const details = attributes.details || {};
+
+
 
       for (const node of network.nodes) {
-        nodes.push(this.mapNode(node, nodeTypes[node] || this.inferNodeType(node), isSeed[node], scores[node]));
+        nodes.push(this.mapNode(node, nodeTypes[node] || this.inferNodeType(node), isSeed[node], scores[node], details[node]));
       }
 
       for (const edge of network.edges) {
@@ -225,13 +252,13 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
     return {color, shape, size, font, shadow};
   }
 
-  private mapNode(nodeId: any, nodeType?: NodeType, isSeed?: boolean, score?: number): any {
+  private mapNode(nodeId: any, nodeType?: NodeType, isSeed?: boolean, score?: number, details?): any {
     const {shape, color, size, font, shadow} = this.getNodeLooks(nodeId, nodeType, isSeed);
     return {
       id: nodeId,
       label: nodeId,
       size, color, shape, font, shadow,
-      nodeType, isSeed,
+      nodeType, isSeed, details
     };
   }
 
diff --git a/src/app/interfaces.ts b/src/app/interfaces.ts
index 5ae4c54a..fb986b18 100644
--- a/src/app/interfaces.ts
+++ b/src/app/interfaces.ts
@@ -53,6 +53,12 @@ export interface Task {
 
 export interface QueryItem {
   name: string;
-  type: 'Host Protein' | 'Viral Protein';
-  data: Protein | ViralProtein;
+  type: 'Host Protein' | 'Viral Protein' | 'Drug';
+  data: Protein | ViralProtein | Drug;
+}
+
+export interface Drug {
+  drugId: string;
+  name: string;
+  status: 'approved' | 'investigational';
 }
diff --git a/src/app/pages/explorer-page/explorer-page.component.html b/src/app/pages/explorer-page/explorer-page.component.html
index 99f89360..8715dc56 100644
--- a/src/app/pages/explorer-page/explorer-page.component.html
+++ b/src/app/pages/explorer-page/explorer-page.component.html
@@ -148,8 +148,8 @@
                 <div class="network center image1" #network>
                   <button class="button is-loading center" alt="Snow">Loading</button>
                 </div>
-                <div class="image2" >
-                    <img src="assets/legend.png"  width="160px"/>
+                <div class="image2">
+                  <img src="assets/legend.png" width="160px"/>
                 </div>
               </div>
             </div>
@@ -194,8 +194,11 @@
       <header class="card-header">
         <p class="card-header-title">
           <span class="icon">
-        <i class="fas fa-info" aria-hidden="true"></i>
-      </span> {{ selectedProteinType }}
+        <i *ngIf="!showDetails" class="fas fa-info" aria-hidden="true"></i>
+        <i *ngIf="selectedType === 'Host Protein'" class="fas fa-dna" aria-hidden="true"></i>
+        <i *ngIf="selectedType === 'Viral Protein'" class="fas fa-virus" aria-hidden="true"></i>
+        <i *ngIf="selectedType === 'Drug'" class="fas fa-capsules" aria-hidden="true"></i>
+      </span> {{ selectedType }}
         </p>
         <a (click)="collabsDetails = !collabsDetails" data-action="collapse"
            class="card-header-icon is-hidden-fullscreen" aria-label="more options">
@@ -207,27 +210,44 @@
       <div *ngIf="collabsDetails">
         <div class="card-content">
           <div *ngIf="showDetails">
-            <p *ngIf="selectedProteinName"><b>Name:</b> {{ selectedProteinName }}</p>
-            <p *ngIf="selectedProteinDataset"><b>Virus:</b> {{ selectedProteinVirus }}</p>
-            <p *ngIf="selectedProteinAc"><b>Protein AC:</b>
-              <a href="https://www.uniprot.org/uniprot/{{ selectedProteinAc }}"
-                 target="_blank"> {{ selectedProteinAc }}</a>
+            <p *ngIf="selectedName && selectedType=='Drug'"><b><span>Name:</span></b> {{ selectedName }} <span
+              class="icon is-small">
+                  <i class="fas fa-capsules"></i>
+            </span></p>
+            <p *ngIf="selectedName && selectedType=='Host Protein'"><b><span>Gene Name:</span></b> {{ selectedName }}
+              <span class="icon is-small">
+                  <i class="fas fa-dna"></i>
+            </span></p>
+            <p *ngIf="selectedVirusName"><b><span>Virus:</span></b> {{ selectedVirusName }} <span class="icon is-small">
+                  <i class="fas fa-virus"></i>
+            </span></p>
+            <p *ngIf="selectedName && selectedType=='Viral Protein'"><b>Effect:</b> {{ selectedName }}</p>
+            <p *ngIf="selectedId && selectedType == 'Host Protein'"><b>Uniprot AC:</b>
+              <a href="https://www.uniprot.org/uniprot/{{ selectedId }}"
+                 target="_blank"> {{ selectedId }}</a>
+            </p>
+            <p *ngIf="selectedId && selectedType == 'Drug'"><b>DrugBank ID:</b>
+              <a href="https://www.drugbank.ca/drugs/{{ selectedId }}"
+                 target="_blank"> {{ selectedId }}</a>
+            </p>
+            <p *ngIf="selectedStatus === 'investigational' "><b>Status:</b> Investigational <span class="icon is-small"><i class="fas fa-search investigational"></i></span>
+            <p *ngIf="selectedStatus === 'approved' "><b>Status:</b> Approved <span class="icon is-small"><i class="fas fa-check"></i></span>
             </p>
             <div class="field has-addons add-remove-toggle">
-              <p class="control">
-                <button class="button is-rounded" [class.is-success]="!analysis.inSelection(selectedProteinName)"
-                        [disabled]="analysis.inSelection(selectedProteinName)"
-                        (click)="analysis.addItem(selectedProteinItem)">
+              <p *ngIf="selectedType !== 'Drug'" class="control">
+                <button class="button is-rounded" [class.is-success]="!analysis.inSelection(selectedName)"
+                        [disabled]="analysis.inSelection(selectedName)"
+                        (click)="analysis.addItem(selectedItem)">
                 <span class="icon is-small">
                   <i class="fas fa-plus"></i>
                 </span>
                   <span>Add to Analysis</span>
                 </button>
               </p>
-              <p class="control">
-                <button class="button is-rounded" [class.is-danger]="analysis.inSelection(selectedProteinName)"
-                        [disabled]="!analysis.inSelection(selectedProteinName)"
-                        (click)="analysis.removeItem(selectedProteinName)">
+              <p *ngIf="selectedType !== 'Drug'" class="control">
+                <button class="button is-rounded" [class.is-danger]="analysis.inSelection(selectedName)"
+                        [disabled]="!analysis.inSelection(selectedName)"
+                        (click)="analysis.removeItem(selectedName)">
                   <span>Remove</span>
                   <span class="icon is-small">
                   <i class="fas fa-trash"></i>
diff --git a/src/app/pages/explorer-page/explorer-page.component.ts b/src/app/pages/explorer-page/explorer-page.component.ts
index 9d2b19f4..7edd4fc7 100644
--- a/src/app/pages/explorer-page/explorer-page.component.ts
+++ b/src/app/pages/explorer-page/explorer-page.component.ts
@@ -23,12 +23,12 @@ declare var vis: any;
 export class ExplorerPageComponent implements OnInit, AfterViewInit {
 
   public showDetails = false;
-  public selectedProteinName = null;
-  public selectedProteinType = null;
-  public selectedProteinAc = null;
-  public selectedProteinItem = null;
-  public selectedProteinVirus = null;
-  public selectedProteinDataset = null;
+  public selectedName = null;
+  public selectedType = null;
+  public selectedId = null;
+  public selectedItem = null;
+  public selectedVirusName = null;
+  public selectedStatus = null;
   public collabsAnalysis = true;
   public collabsDetails = true;
   public collabsTask = true;
@@ -159,29 +159,29 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
   }
 
   public changeInfo(showList: any[]) {
-    this.selectedProteinItem = showList[0];
-    this.selectedProteinName = showList[1];
-    this.selectedProteinType = showList[2];
-    this.selectedProteinAc = showList[3];
-    this.selectedProteinDataset = showList[4];
-    this.selectedProteinVirus = showList[5];
+    this.selectedItem = showList[0];
+    this.selectedName = showList[1];
+    this.selectedType = showList[2];
+    this.selectedId = showList[3];
+    this.selectedVirusName = showList[4];
+    this.selectedStatus = showList[5];
   }
 
   public async openSummary(item: QueryItem, zoom: boolean) {
-    this.selectedProteinAc = null;
-    this.selectedProteinItem = item;
-    this.selectedProteinType = item.type;
-    this.selectedProteinName = item.name;
-    if (this.selectedProteinType === 'Host Protein') {
+    this.selectedId = null;
+    this.selectedItem = item;
+    this.selectedType = item.type;
+    this.selectedName = item.name;
+    if (this.selectedType === 'Host Protein') {
       const hostProtein = item.data as Protein;
-      this.selectedProteinAc = hostProtein.proteinAc;
+      this.selectedId = hostProtein.proteinAc;
       if (zoom) {
         this.zoomToNode(`p_${item.name}`);
       }
     } else if (item.type === 'Viral Protein') {
       const viralProtein = item.data as ViralProtein;
-      this.selectedProteinVirus = viralProtein.virusName;
-      this.selectedProteinDataset = viralProtein.datasetName;
+      this.selectedName = viralProtein.effectName;
+      this.selectedVirusName = viralProtein.virusName;
       if (zoom) {
         this.zoomToNode(`eff_${viralProtein.effectName}_${viralProtein.datasetName}_${viralProtein.virusName}`);
       }
@@ -190,12 +190,12 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
   }
 
   public async closeSummary() {
-    this.selectedProteinItem = null;
-    this.selectedProteinName = null;
-    this.selectedProteinType = null;
-    this.selectedProteinAc = null;
-    this.selectedProteinVirus = null;
-    this.selectedProteinDataset = null;
+    this.selectedItem = null;
+    this.selectedName = null;
+    this.selectedType = null;
+    this.selectedId = null;
+    this.selectedVirusName = null;
+    this.selectedStatus = null;
     this.showDetails = false;
   }
 
@@ -292,14 +292,14 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
       this.network.stabilize();
     }
 
-    if (this.selectedProteinItem) {
-      this.zoomToNode(`p_${this.selectedProteinItem.name}`);
+    if (this.selectedItem) {
+      this.zoomToNode(`p_${this.selectedItem.name}`);
     }
 
     this.queryItems = [];
     this.fillQueryItems(this.proteins, this.effects);
-    if (this.selectedProteinItem) {
-      this.network.selectNodes(['p_' + this.selectedProteinItem.name]);
+    if (this.selectedItem) {
+      this.network.selectNodes(['p_' + this.selectedItem.name]);
     }
   }
 
diff --git a/src/styles.scss b/src/styles.scss
index 642097fe..041cd42d 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -159,6 +159,10 @@ div.field.has-addons.add-remove-toggle {
   color: #48C774;
 }
 
+.fa-search.investigational {
+  color: #e2b600;
+}
+
 .fa-spinner {
   color: #e2b600;
 }
-- 
GitLab