Skip to content
Snippets Groups Projects
Commit 818c4b14 authored by Julian Matschinske's avatar Julian Matschinske
Browse files

Merge branch 'show-drug-info' into 'master'

Show drug info

See merge request covid-19/frontend!52
parents 8629ab3c 7cf140d7
No related branches found
No related tags found
No related merge requests found
...@@ -106,18 +106,18 @@ export class AnalysisService { ...@@ -106,18 +106,18 @@ export class AnalysisService {
showToast(task: Task, status: 'DONE' | 'FAILED') { showToast(task: Task, status: 'DONE' | 'FAILED') {
let toastMessage; let toastMessage;
let toastType; let toastType;
const startDate = new Date(task.info.startedAt); // const startDate = new Date(task.info.startedAt);
const finishedDate = new Date(task.info.finishedAt); // const finishedDate = new Date(task.info.finishedAt);
if (status === 'DONE') { if (status === 'DONE') {
toastMessage = `Computation finished succesfully. toastMessage = 'Computation finished succesfully.';
\n- Algorithm: ${task.info.algorithm} // \n- Algorithm: ${task.info.algorithm}
\n- Started At: ${startDate.getHours()}:${startDate.getMinutes()} // \n- Started At: ${startDate.getHours()}:${startDate.getMinutes()}
\n- Finished At: ${finishedDate.getHours()}:${finishedDate.getMinutes()}`; // \n- Finished At: ${finishedDate.getHours()}:${finishedDate.getMinutes()}`;
toastType = 'is-success'; toastType = 'is-success';
} else if (status === 'FAILED') { } else if (status === 'FAILED') {
toastMessage = `Computation failed. toastMessage = 'Computation failed.';
\n- Algorithm: ${task.info.algorithm} // \n- Algorithm: ${task.info.algorithm}
\n- Started At: ${startDate.getHours()}:${startDate.getMinutes()}`; // \n- Started At: ${startDate.getHours()}:${startDate.getMinutes()}`;
toastType = 'is-danger'; toastType = 'is-danger';
} }
......
...@@ -12,7 +12,7 @@ import { ...@@ -12,7 +12,7 @@ import {
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
import {environment} from '../../../environments/environment'; import {environment} from '../../../environments/environment';
import {AnalysisService} from '../../analysis.service'; import {AnalysisService} from '../../analysis.service';
import {Protein, Task, NodeType, ViralProtein} from '../../interfaces'; import {Protein, Task, NodeType, ViralProtein, Drug} from '../../interfaces';
declare var vis: any; declare var vis: any;
...@@ -71,23 +71,27 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -71,23 +71,27 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
const options = {}; const options = {};
this.network = new vis.Network(container, this.nodeData, 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) => { this.network.on('selectNode', (properties) => {
const selectedNodes = this.nodeData.nodes.get(properties.nodes); const selectedNodes = this.nodeData.nodes.get(properties.nodes);
if (selectedNodes.length > 0) { if (selectedNodes.length > 0) {
let selectedProteinItem; let selectedItem;
let selectedProteinName; let selectedName;
let selectedProteinType; let selectedType;
let selectedProteinAc; let selectedId;
let selectedProteinDataset; let selectedVirusName;
let selectedProteinVirus; let selectedStatus;
if (selectedNodes[0].nodeType === 'host') { if (selectedNodes[0].nodeType === 'host') {
const protein: Protein = {name: '', proteinAc: selectedNodes[0].id}; const protein: Protein = {name: '', proteinAc: selectedNodes[0].id};
selectedProteinName = null; selectedVirusName = null;
selectedProteinDataset = null; selectedStatus = null;
selectedProteinVirus = null; selectedItem = {name: selectedNodes[0].id, type: 'Host Protein', data: protein};
selectedProteinItem = {name: selectedNodes[0].id, type: 'Host Protein', data: protein}; // TODO use gene name here
selectedProteinAc = protein.proteinAc; selectedName = protein.proteinAc;
selectedProteinType = 'Host Protein'; selectedId = protein.proteinAc;
selectedType = 'Host Protein';
if (properties.event.srcEvent.ctrlKey) { if (properties.event.srcEvent.ctrlKey) {
if (this.analysis.inSelection(protein.proteinAc)) { if (this.analysis.inSelection(protein.proteinAc)) {
this.analysis.removeItem(protein.proteinAc); this.analysis.removeItem(protein.proteinAc);
...@@ -97,27 +101,45 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -97,27 +101,45 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
} }
} }
} else if (selectedNodes[0].nodeType === 'virus') { } else if (selectedNodes[0].nodeType === 'virus') {
const virus: ViralProtein = {viralProteinId: null, effectName: selectedNodes[0].id, virusName: null, datasetName: null}; const virus: ViralProtein = {
selectedProteinAc = null; viralProteinId: null,
selectedProteinDataset = null; effectName: selectedNodes[0].id,
selectedProteinVirus = null; virusName: null,
selectedProteinItem = {name: virus.effectName, type: 'Viral Protein', data: virus}; datasetName: null
selectedProteinName = virus.effectName; };
selectedProteinType = 'Viral Protein'; 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 (properties.event.srcEvent.ctrlKey) {
if (this.analysis.inSelection(virus.effectName)) { if (this.analysis.inSelection(virus.effectName)) {
this.analysis.removeItem(virus.effectName); this.analysis.removeItem(virus.effectName);
} else { } else {
this.analysis.addItem(selectedProteinItem); this.analysis.addItem(selectedItem);
this.analysis.getCount(); this.analysis.getCount();
} }
} }
} } else if (selectedNodes[0].nodeType === 'drug') {
this.showDetailsChange.emit([true, [selectedProteinItem, selectedProteinName, selectedProteinType, selectedProteinAc, const drug: Drug = {
selectedProteinDataset, selectedProteinVirus]]); 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, [selectedItem, selectedName, selectedType,
selectedId, selectedVirusName, selectedStatus]]);
} else { } else {
this.showDetailsChange.emit([false, [null, null, null, null, null, null]]); this.showDetailsChange.emit([false, [null, null, null, null, null, null]]);
} }
}); });
this.analysis.subscribe((item, selected) => { this.analysis.subscribe((item, selected) => {
...@@ -157,6 +179,8 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -157,6 +179,8 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
public inferNodeType(nodeId: string): 'host' | 'virus' | 'drug' { public inferNodeType(nodeId: string): 'host' | 'virus' | 'drug' {
if (nodeId.indexOf('-') !== -1 || nodeId.indexOf('_') !== -1) { if (nodeId.indexOf('-') !== -1 || nodeId.indexOf('_') !== -1) {
return 'virus'; return 'virus';
} else if (nodeId.startsWith('DB')) {
return 'drug';
} }
return 'host'; return 'host';
} }
...@@ -174,9 +198,12 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -174,9 +198,12 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
const nodeTypes = attributes.nodeTypes || {}; const nodeTypes = attributes.nodeTypes || {};
const isSeed = attributes.isSeed || {}; const isSeed = attributes.isSeed || {};
const scores = attributes.scores || {}; const scores = attributes.scores || {};
const details = attributes.details || {};
for (const node of network.nodes) { 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) { for (const edge of network.edges) {
...@@ -225,13 +252,13 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -225,13 +252,13 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
return {color, shape, size, font, shadow}; 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); const {shape, color, size, font, shadow} = this.getNodeLooks(nodeId, nodeType, isSeed);
return { return {
id: nodeId, id: nodeId,
label: nodeId, label: nodeId,
size, color, shape, font, shadow, size, color, shape, font, shadow,
nodeType, isSeed, nodeType, isSeed, details
}; };
} }
......
...@@ -53,6 +53,12 @@ export interface Task { ...@@ -53,6 +53,12 @@ export interface Task {
export interface QueryItem { export interface QueryItem {
name: string; name: string;
type: 'Host Protein' | 'Viral Protein'; type: 'Host Protein' | 'Viral Protein' | 'Drug';
data: Protein | ViralProtein; data: Protein | ViralProtein | Drug;
}
export interface Drug {
drugId: string;
name: string;
status: 'approved' | 'investigational';
} }
...@@ -194,8 +194,11 @@ ...@@ -194,8 +194,11 @@
<header class="card-header"> <header class="card-header">
<p class="card-header-title"> <p class="card-header-title">
<span class="icon"> <span class="icon">
<i class="fas fa-info" aria-hidden="true"></i> <i *ngIf="!showDetails" class="fas fa-info" aria-hidden="true"></i>
</span> {{ selectedProteinType }} <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> </p>
<a (click)="collabsDetails = !collabsDetails" data-action="collapse" <a (click)="collabsDetails = !collabsDetails" data-action="collapse"
class="card-header-icon is-hidden-fullscreen" aria-label="more options"> class="card-header-icon is-hidden-fullscreen" aria-label="more options">
...@@ -207,27 +210,44 @@ ...@@ -207,27 +210,44 @@
<div *ngIf="collabsDetails"> <div *ngIf="collabsDetails">
<div class="card-content"> <div class="card-content">
<div *ngIf="showDetails"> <div *ngIf="showDetails">
<p *ngIf="selectedProteinName"><b>Name:</b> {{ selectedProteinName }}</p> <p *ngIf="selectedName && selectedType=='Drug'"><b><span>Name:</span></b> {{ selectedName }} <span
<p *ngIf="selectedProteinDataset"><b>Virus:</b> {{ selectedProteinVirus }}</p> class="icon is-small">
<p *ngIf="selectedProteinAc"><b>Protein AC:</b> <i class="fas fa-capsules"></i>
<a href="https://www.uniprot.org/uniprot/{{ selectedProteinAc }}" </span></p>
target="_blank"> {{ selectedProteinAc }}</a> <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> </p>
<div class="field has-addons add-remove-toggle"> <div class="field has-addons add-remove-toggle">
<p class="control"> <p *ngIf="selectedType !== 'Drug'" class="control">
<button class="button is-rounded" [class.is-success]="!analysis.inSelection(selectedProteinName)" <button class="button is-rounded" [class.is-success]="!analysis.inSelection(selectedName)"
[disabled]="analysis.inSelection(selectedProteinName)" [disabled]="analysis.inSelection(selectedName)"
(click)="analysis.addItem(selectedProteinItem)"> (click)="analysis.addItem(selectedItem)">
<span class="icon is-small"> <span class="icon is-small">
<i class="fas fa-plus"></i> <i class="fas fa-plus"></i>
</span> </span>
<span>Add to Analysis</span> <span>Add to Analysis</span>
</button> </button>
</p> </p>
<p class="control"> <p *ngIf="selectedType !== 'Drug'" class="control">
<button class="button is-rounded" [class.is-danger]="analysis.inSelection(selectedProteinName)" <button class="button is-rounded" [class.is-danger]="analysis.inSelection(selectedName)"
[disabled]="!analysis.inSelection(selectedProteinName)" [disabled]="!analysis.inSelection(selectedName)"
(click)="analysis.removeItem(selectedProteinName)"> (click)="analysis.removeItem(selectedName)">
<span>Remove</span> <span>Remove</span>
<span class="icon is-small"> <span class="icon is-small">
<i class="fas fa-trash"></i> <i class="fas fa-trash"></i>
......
...@@ -23,12 +23,12 @@ declare var vis: any; ...@@ -23,12 +23,12 @@ declare var vis: any;
export class ExplorerPageComponent implements OnInit, AfterViewInit { export class ExplorerPageComponent implements OnInit, AfterViewInit {
public showDetails = false; public showDetails = false;
public selectedProteinName = null; public selectedName = null;
public selectedProteinType = null; public selectedType = null;
public selectedProteinAc = null; public selectedId = null;
public selectedProteinItem = null; public selectedItem = null;
public selectedProteinVirus = null; public selectedVirusName = null;
public selectedProteinDataset = null; public selectedStatus = null;
public collabsAnalysis = true; public collabsAnalysis = true;
public collabsDetails = true; public collabsDetails = true;
public collabsTask = true; public collabsTask = true;
...@@ -159,29 +159,29 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -159,29 +159,29 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
} }
public changeInfo(showList: any[]) { public changeInfo(showList: any[]) {
this.selectedProteinItem = showList[0]; this.selectedItem = showList[0];
this.selectedProteinName = showList[1]; this.selectedName = showList[1];
this.selectedProteinType = showList[2]; this.selectedType = showList[2];
this.selectedProteinAc = showList[3]; this.selectedId = showList[3];
this.selectedProteinDataset = showList[4]; this.selectedVirusName = showList[4];
this.selectedProteinVirus = showList[5]; this.selectedStatus = showList[5];
} }
public async openSummary(item: QueryItem, zoom: boolean) { public async openSummary(item: QueryItem, zoom: boolean) {
this.selectedProteinAc = null; this.selectedId = null;
this.selectedProteinItem = item; this.selectedItem = item;
this.selectedProteinType = item.type; this.selectedType = item.type;
this.selectedProteinName = item.name; this.selectedName = item.name;
if (this.selectedProteinType === 'Host Protein') { if (this.selectedType === 'Host Protein') {
const hostProtein = item.data as Protein; const hostProtein = item.data as Protein;
this.selectedProteinAc = hostProtein.proteinAc; this.selectedId = hostProtein.proteinAc;
if (zoom) { if (zoom) {
this.zoomToNode(`p_${item.name}`); this.zoomToNode(`p_${item.name}`);
} }
} else if (item.type === 'Viral Protein') { } else if (item.type === 'Viral Protein') {
const viralProtein = item.data as ViralProtein; const viralProtein = item.data as ViralProtein;
this.selectedProteinVirus = viralProtein.virusName; this.selectedName = viralProtein.effectName;
this.selectedProteinDataset = viralProtein.datasetName; this.selectedVirusName = viralProtein.virusName;
if (zoom) { if (zoom) {
this.zoomToNode(`eff_${viralProtein.effectName}_${viralProtein.datasetName}_${viralProtein.virusName}`); this.zoomToNode(`eff_${viralProtein.effectName}_${viralProtein.datasetName}_${viralProtein.virusName}`);
} }
...@@ -190,12 +190,12 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -190,12 +190,12 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
} }
public async closeSummary() { public async closeSummary() {
this.selectedProteinItem = null; this.selectedItem = null;
this.selectedProteinName = null; this.selectedName = null;
this.selectedProteinType = null; this.selectedType = null;
this.selectedProteinAc = null; this.selectedId = null;
this.selectedProteinVirus = null; this.selectedVirusName = null;
this.selectedProteinDataset = null; this.selectedStatus = null;
this.showDetails = false; this.showDetails = false;
} }
...@@ -292,14 +292,14 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -292,14 +292,14 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
this.network.stabilize(); this.network.stabilize();
} }
if (this.selectedProteinItem) { if (this.selectedItem) {
this.zoomToNode(`p_${this.selectedProteinItem.name}`); this.zoomToNode(`p_${this.selectedItem.name}`);
} }
this.queryItems = []; this.queryItems = [];
this.fillQueryItems(this.proteins, this.effects); this.fillQueryItems(this.proteins, this.effects);
if (this.selectedProteinItem) { if (this.selectedItem) {
this.network.selectNodes(['p_' + this.selectedProteinItem.name]); this.network.selectNodes(['p_' + this.selectedItem.name]);
} }
} }
......
...@@ -159,6 +159,10 @@ div.field.has-addons.add-remove-toggle { ...@@ -159,6 +159,10 @@ div.field.has-addons.add-remove-toggle {
color: #48C774; color: #48C774;
} }
.fa-search.investigational {
color: #e2b600;
}
.fa-spinner { .fa-spinner {
color: #e2b600; color: #e2b600;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment