diff --git a/src/app/app.module.ts b/src/app/app.module.ts index df8f6d13316f1d8684d4d2ea708d3471ec74298a..9d4402b422a2d4aca7155ea545ee97252f8799f8 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -16,6 +16,7 @@ import {TaskListComponent} from './components/task-list/task-list.component'; import {ToggleComponent} from './components/toggle/toggle.component'; import {InfoTileComponent} from './components/info-tile/info-tile.component'; import {CustomProteinsComponent} from './dialogs/custom-proteins/custom-proteins.component'; +import { DownloadButtonComponent } from './components/download-button/download-button.component'; import {MatTooltipModule} from '@angular/material/tooltip'; @@ -50,6 +51,7 @@ import {TooltipModule} from 'primeng/tooltip'; NetworkLegendComponent, ProtTableComponent, DrugTableComponent, + DownloadButtonComponent, ], imports: [ BrowserModule, diff --git a/src/app/components/analysis-panel/analysis-panel.component.html b/src/app/components/analysis-panel/analysis-panel.component.html index 5a680644281c15311111b6d3482e4e7490348c57..f31d4510bb0829c643e0e0c683fb0c9a087186e6 100644 --- a/src/app/components/analysis-panel/analysis-panel.component.html +++ b/src/app/components/analysis-panel/analysis-panel.component.html @@ -136,7 +136,7 @@ <div class="tab-content" *ngIf="task && task.info.done" [class.is-visible]="tab === 'network'"> <div class="card-image canvas-content" #networkWithLegend> <div *ngIf="myConfig.showLegend"> - <app-network-legend [config]="myConfig" [context]="legendContext"></app-network-legend> + <app-network-legend [config]="myConfig" [context]="legendContext" [smallStyle]="smallStyle"></app-network-legend> </div> <div class="parent fullheight"> <div class="center image1 fullheight" #network> @@ -154,6 +154,7 @@ pTooltip="Take a screenshot of the current network." [tooltipStyleClass]="'drgstn drgstn-tooltip'" tooltipPosition="top" + [ngClass]="{ 'button-small': smallStyle }" (click)="toImage()"> <span class="icon"> <i class="fas fa-camera" aria-hidden="true"></i> @@ -165,20 +166,7 @@ </ng-container> <ng-container *ngIf="myConfig.showFooterButtonExportGraphml"> - <button - (click)="graphmlLink()" - class="button is-primary is-rounded has-tooltip network-footer-toolbar-element footer-buttons" - pTooltip="Export this network as .graphml file." - [tooltipStyleClass]="'drgstn drgstn-tooltip'" - tooltipPosition="top" - > - <span class="icon"> - <i class="fas fa-download" aria-hidden="true"></i> - </span> - <span [ngClass]="{ 'text-normal': smallStyle }" - >.graphml</span - > - </button> + <app-download-button [nodeData]=nodeData [smallStyle]="smallStyle" [buttonId]="'analysis-download'"></app-download-button> </ng-container> <!-- <div class="field">--> diff --git a/src/app/components/analysis-panel/analysis-panel.component.ts b/src/app/components/analysis-panel/analysis-panel.component.ts index c95513c66267a242b5b3fbba70901dce01431d55..ab8bbb4e14090f7600eb3cdc1f6c11c74ea9c22f 100644 --- a/src/app/components/analysis-panel/analysis-panel.component.ts +++ b/src/app/components/analysis-panel/analysis-panel.component.ts @@ -79,7 +79,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { public myConfig: IConfig = JSON.parse(JSON.stringify(defaultConfig)); public network: any; - private nodeData: { nodes: any, edges: any } = {nodes: null, edges: null}; + public nodeData: { nodes: any, edges: any } = {nodes: null, edges: null}; private drugNodes: any[] = []; private drugEdges: any[] = []; public showDrugs = false; @@ -476,13 +476,6 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { return `${environment.backend}task_result/?token=${this.token}&view=${view}&fmt=csv`; } - public graphmlLink() { - const data = {nodes: this.nodeData.nodes.get(), edges: this.nodeData.edges.get()} - this.netex.graphmlLink(data).subscribe(response => { - return downLoadFile(response, "application/xml"); - }) - } - public inferEdgeGroup(edge: object): EdgeType { if (edge['to'].startsWith('d')) { return 'protein-drug'; diff --git a/src/app/components/download-button/download-button.component.html b/src/app/components/download-button/download-button.component.html new file mode 100644 index 0000000000000000000000000000000000000000..e75f66ff8233e0183c1e4822f2fccb1786facc42 --- /dev/null +++ b/src/app/components/download-button/download-button.component.html @@ -0,0 +1,42 @@ +<div class="footer-buttons network-footer-toolbar-element"> + <div class="dropdown is-hoverable is-up"> + <div class="dropdown-trigger"> + <button + [id]="buttonId" + class="button is-primary is-rounded has-tooltip" + aria-haspopup="true" + attr.aria-controls="{{ 'controls-' + buttonId }}" + [ngClass]="{ 'button-small': smallStyle }" + > + <span class="icon"> + <i class="fas fa-download" aria-hidden="true"></i> + </span> + <span [ngClass]="{ 'text-normal': smallStyle }">Download</span> + </button> + </div> + <div class="dropdown-menu" id="{{ 'controls-' + buttonId }}" role="menu"> + <div class="dropdown-content"> + <a + (click)="downloadLink('graphml')" + class="dropdown-item" + [ngClass]="{ 'text-normal': smallStyle }" + >.graphml</a + > + <hr class="dropdown-divider" /> + <a + (click)="downloadLink('json')" + class="dropdown-item" + [ngClass]="{ 'text-normal': smallStyle }" + >.json</a + > + <hr class="dropdown-divider" /> + <a + (click)="downloadLink('csv')" + class="dropdown-item" + [ngClass]="{ 'text-normal': smallStyle }" + >.csv</a + > + </div> + </div> + </div> +</div> diff --git a/src/app/components/download-button/download-button.component.scss b/src/app/components/download-button/download-button.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..6f4b627a8c5fb90c7c46b7d7934fefac183c59dd --- /dev/null +++ b/src/app/components/download-button/download-button.component.scss @@ -0,0 +1,5 @@ +@import "src/stylesheets/variables"; + +.dropdown-menu{ + z-index: $analysis-network-toolbar-dropdown-z !important; +} \ No newline at end of file diff --git a/src/app/components/download-button/download-button.component.spec.ts b/src/app/components/download-button/download-button.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..635c59fb8253e9cb1a3576ae90c18819a2732cb1 --- /dev/null +++ b/src/app/components/download-button/download-button.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DownloadButtonComponent } from './download-button.component'; + +describe('DownloadButtonComponent', () => { + let component: DownloadButtonComponent; + let fixture: ComponentFixture<DownloadButtonComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DownloadButtonComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DownloadButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/download-button/download-button.component.ts b/src/app/components/download-button/download-button.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..596f7558a16e2220af9d2ba4bdbad3632e0b8c5d --- /dev/null +++ b/src/app/components/download-button/download-button.component.ts @@ -0,0 +1,28 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { NetexControllerService } from 'src/app/services/netex-controller/netex-controller.service'; +import { downLoadFile } from 'src/app/utils'; + +@Component({ + selector: 'app-download-button', + templateUrl: './download-button.component.html', + styleUrls: ['./download-button.component.scss'] +}) +export class DownloadButtonComponent implements OnInit { + + @Input() nodeData: { nodes: any, edges: any } = {nodes: null, edges: null}; + @Input() smallStyle: boolean; + @Input() buttonId: string; + + constructor(public netex: NetexControllerService) { } + + ngOnInit(): void { + } + + public downloadLink(fmt) { + const data = {nodes: this.nodeData.nodes.get(), edges: this.nodeData.edges.get(), fmt: fmt}; + this.netex.graphExport(data).subscribe(response => { + return downLoadFile(response, `application/${fmt}`, fmt); + }); + } + +} diff --git a/src/app/components/network-legend/network-legend.component.html b/src/app/components/network-legend/network-legend.component.html index d126229385c73d7c1a29da458c59d259bb63a4f8..bb1703f764071d8bb54182721da27916f4e415a1 100644 --- a/src/app/components/network-legend/network-legend.component.html +++ b/src/app/components/network-legend/network-legend.component.html @@ -11,7 +11,7 @@ <th> <img [src]="nodeGroup.value.image" class="legend-icon"/> </th> - <td class="group-name"> {{ nodeGroup.value.groupName }}</td> + <td class="group-name" [ngClass]="{ 'text-normal': smallStyle }"> {{ nodeGroup.value.groupName }}</td> </ng-container> <ng-container *ngIf="!nodeGroup.value.image" [ngSwitch]="nodeGroup.value.shape"> @@ -56,7 +56,7 @@ <span class="node {{ nodeGroup.value.shape }}" [style.background-color]=nodeGroup.value.color.background> </span> </th> - <td class="group-name"> {{ nodeGroup.value.groupName }}</td> + <td class="group-name" [ngClass]="{ 'text-normal': smallStyle }"> {{ nodeGroup.value.groupName }}</td> </ng-container> </ng-container> </tr> @@ -69,7 +69,7 @@ <hr *ngIf="!edgeGroup.value.dashes" class="edge" [style.background-color]=edgeGroup.value.color> <hr *ngIf="edgeGroup.value.dashes" class="edge dashes" [style.color]=edgeGroup.value.color> </th> - <td class="group-name"> {{ edgeGroup.value.groupName }}</td> + <td class="group-name" [ngClass]="{ 'text-normal': smallStyle }"> {{ edgeGroup.value.groupName }}</td> </ng-container> </tr> </ng-container> diff --git a/src/app/components/network-legend/network-legend.component.ts b/src/app/components/network-legend/network-legend.component.ts index 142c0e0728e834544c73dab5af343c2600e75ba3..a3a02b78bdf0fdc43016915921f065fd14b3d6da 100644 --- a/src/app/components/network-legend/network-legend.component.ts +++ b/src/app/components/network-legend/network-legend.component.ts @@ -11,6 +11,7 @@ export class NetworkLegendComponent implements OnInit { @Input() context: legendContext; @Input() config: IConfig; + @Input() smallStyle: boolean; private contextNodeGroupsToDelete = { 'explorer': ['foundNode', 'foundDrug', 'seedNode', 'default', 'defaultDisorder'], @@ -39,17 +40,11 @@ export class NetworkLegendComponent implements OnInit { // selected node is not supposed to appear in legend return false; } - if (this.contextNodeGroupsToDelete[this.context].includes(nodeGroupKey)) { - return false; - } - return true; + return !this.contextNodeGroupsToDelete[this.context].includes(nodeGroupKey); } public checkEdgeGroupContext(edgeGroupKey) { - if (this.contextEdgeGroupsToDelete[this.context].includes(edgeGroupKey)) { - return false; - } - return true; + return !this.contextEdgeGroupsToDelete[this.context].includes(edgeGroupKey); } constructor() { } diff --git a/src/app/components/task-list/task-list.component.html b/src/app/components/task-list/task-list.component.html index 7db23b0f12b278d3f02f5fb4f05762dddf8943eb..1c44521f3a3a28c113a1a28f9d3752da6b464730 100644 --- a/src/app/components/task-list/task-list.component.html +++ b/src/app/components/task-list/task-list.component.html @@ -1,74 +1,168 @@ <div class="content"> - <div class="list is-hoverable"> - <a *ngFor="let task of analysis.tasks" class="list-item box small-box" [class.is-active]="task.token === token"> + <div class="list is-hoverable" [ngClass]="{ 'text-normal': smallStyle }"> + <a + *ngFor="let task of analysis.tasks" + class="list-item box small-box" + [class.is-active]="task.token === token" + > <div *ngIf="!task.info.startedAt"> - <p> - <span class="is-capitalized"><i class="fa" [class.fa-capsules]="task.info.target === 'drug'" - [class.fa-crosshairs]="task.info.target === 'drug-target'"></i> {{algorithmNames[task.info.algorithm]}}</span> - <span class="icon is-pulled-right"><i class="fas fa-pause" aria-hidden="true"></i></span> - </p> - <p> - <small *ngIf="task.stats.queueLength > 0 && task.stats.queuePosition === 1"> - Queued: 1 other task to finish - </small> - <small *ngIf="task.stats.queueLength > 0 && task.stats.queuePosition > 1"> - Queued: {{task.stats.queuePosition}} other tasks to finish - </small> - <small *ngIf="task.stats.queueLength === 0 || task.stats.queuePosition === 0"> - Execution imminent... - </small> - <a (click)="analysis.removeTask(task.token)" class="text-danger"> - <span class="icon is-pulled-right"> - <i class="fa fa-trash"></i> - </span> - </a> - </p> + <div class="columns mb-0"> + <div class="column is-8"> + <span class="is-capitalized" + ><i + class="fa" + [class.fa-capsules]="task.info.target === 'drug'" + [class.fa-crosshairs]="task.info.target === 'drug-target'" + ></i> + {{ algorithmNames[task.info.algorithm] }}</span + > + </div> + <div class="column is-2"> + <span class="icon " + ><i class="fas fa-pause" aria-hidden="true"></i + ></span> + </div> + </div> + <div class="columns mb-0"> + <div class="column is-8 pt-0 pb-0"> + <small + *ngIf=" + task.stats.queueLength > 0 && task.stats.queuePosition === 1 + " + > + Queued: 1 other task to finish + </small> + <small + *ngIf="task.stats.queueLength > 0 && task.stats.queuePosition > 1" + > + Queued: {{ task.stats.queuePosition }} other tasks to finish + </small> + <small + *ngIf=" + task.stats.queueLength === 0 || task.stats.queuePosition === 0 + " + > + Execution imminent... + </small> + </div> + <div class="column is-2 pt-0 pb-0"> + <a (click)="analysis.removeTask(task.token)" class="text-danger"> + <span class="icon"> + <i class="fa fa-trash"></i> + </span> + </a> + </div> + </div> </div> <div *ngIf="!task.info.done && !task.info.failed && task.info.startedAt"> - <p> - <span class="is-capitalized"><i class="fa" [class.fa-capsules]="task.info.target === 'drug'" - [class.fa-crosshairs]="task.info.target === 'drug-target'"></i> {{algorithmNames[task.info.algorithm]}}</span> - <span class="icon is-pulled-right"><i class="fas fa-spinner fa-spin" aria-hidden="true"></i></span> - </p> - <p> - <small>Started {{task.info.startedAt | date :'short'}}</small> - <a (click)="analysis.removeTask(task.token)" class="is-pulled-right text-danger"> - <span class="icon is-pulled-right"> - <i class="fa fa-trash"></i> - </span> - </a> - </p> - <progress class="progress is-success" [value]="task.info.progress * 100" max="100"></progress> + <div class="columns mb-0"> + <div class="column is-8"> + <span class="is-capitalized" + ><i + class="fa" + [class.fa-capsules]="task.info.target === 'drug'" + [class.fa-crosshairs]="task.info.target === 'drug-target'" + ></i> + {{ algorithmNames[task.info.algorithm] }}</span + > + </div> + <div class="column is-2"> + <span class="icon" + ><i class="fas fa-spinner fa-spin" aria-hidden="true"></i + ></span> + </div> + </div> + <div class="columns mb-0"> + <div class="column is-8 pt-0 pb-0"> + <small>Started {{ task.info.startedAt | date: "short" }}</small> + </div> + <div class="column is-2 pt-0 pb-0"> + <a + (click)="analysis.removeTask(task.token)" + class=" text-danger" + > + <span class="icon"> + <i class="fa fa-trash"></i> + </span> + </a> + </div> + </div> + <progress + class="progress is-success" + [value]="task.info.progress * 100" + max="100" + ></progress> </div> - <div *ngIf="task.info.done" (click)="open(task.token)" pTooltip="Show analysis results" [tooltipStyleClass]="'drgstn drgstn-tooltip'" tooltipPosition="top"> - <p> - <span class="is-capitalized"><i class="fa" [class.fa-capsules]="task.info.target === 'drug'" - [class.fa-crosshairs]="task.info.target === 'drug-target'"></i> {{algorithmNames[task.info.algorithm]}}</span> - <span class="icon is-pulled-right"><i class="fas fa-check" aria-hidden="true"></i></span> - </p> - <p> - <small>Finished {{task.info.finishedAt | date :'short'}}</small> - <a (click)="analysis.removeTask(task.token)" class="is-pulled-right text-danger"> - <span class="icon is-pulled-right"> - <i class="fa fa-trash"></i> - </span> - </a> - </p> + <div + *ngIf="task.info.done" + (click)="open(task.token)" + pTooltip="Show analysis results" + [tooltipStyleClass]="'drgstn drgstn-tooltip'" + tooltipPosition="top" + > + <div class="columns mb-0"> + <div class="column is-8"> + <span class="is-capitalized" + ><i + class="fa" + [class.fa-capsules]="task.info.target === 'drug'" + [class.fa-crosshairs]="task.info.target === 'drug-target'" + ></i> + {{ algorithmNames[task.info.algorithm] }}</span + > + </div> + <div class="column is-2"> + <span class="icon" + ><i class="fas fa-check" aria-hidden="true"></i + ></span> + </div> + </div> + <div class="columns mb-0"> + <div class="column is-8 pt-0 pb-0"> + <small>Finished {{ task.info.finishedAt | date: "short" }}</small> + </div> + <div class="column is-2 pt-0 pb-0"> + <a (click)="analysis.removeTask(task.token)" class="text-danger"> + <span class="icon"> + <i class="fa fa-trash"></i> + </span> + </a> + </div> + </div> </div> <div *ngIf="task.info.failed"> - <p> - <span class="is-capitalized"><i class="fa" [class.fa-capsules]="task.info.target === 'drug'" - [class.fa-crosshairs]="task.info.target === 'drug-target'"></i> {{algorithmNames[task.info.algorithm]}}</span> - <span class="icon is-pulled-right"><i class="fas fa-exclamation-triangle" aria-hidden="true"></i></span> - </p> - <p class="text-danger"> - <small class="status-field">{{task.info.status}}</small> - <a (click)="analysis.removeTask(task.token)" class="is-pulled-right text-danger"> - <span class="icon is-pulled-right"> - <i class="fa fa-trash"></i> - </span> - </a> - </p> + <div class="columns mb-0"> + <div class="column is-8"> + <span class="is-capitalized" + ><i + class="fa" + [class.fa-capsules]="task.info.target === 'drug'" + [class.fa-crosshairs]="task.info.target === 'drug-target'" + ></i> + {{ algorithmNames[task.info.algorithm] }}</span + > + </div> + <div class="column is-2"> + <span class="icon " + ><i class="fas fa-exclamation-triangle" aria-hidden="true"></i + ></span> + </div> + </div> + <div class="columns mb-0"> + <div class="column is-8 pt-0 pb-0 text-danger"> + <small class="status-field">{{ task.info.status }}</small> + </div> + <div class="column is-2 pt-0 pb-0"> + <a + (click)="analysis.removeTask(task.token)" + class=" text-danger" + > + <span class="icon "> + <i class="fa fa-trash"></i> + </span> + </a> + </div> + </div> </div> </a> </div> diff --git a/src/app/components/task-list/task-list.component.scss b/src/app/components/task-list/task-list.component.scss index 81b579eb2752bd0a5f73efb6907beda18f6f7cd3..ec5bceefa372b1f007e9ec671231569e201a1783 100644 --- a/src/app/components/task-list/task-list.component.scss +++ b/src/app/components/task-list/task-list.component.scss @@ -7,6 +7,11 @@ margin-top: 5px; margin-bottom: 5px; } + + .icon { + display: block !important; + } + } .status-field { @@ -14,8 +19,8 @@ padding: 2px; font-size: 10px; max-width: 215px; - height: 20px; - overflow: hidden; + max-height: 30px; + overflow: scroll; border: 1px solid var(--drgstn-border); display: inline-block; } diff --git a/src/app/components/task-list/task-list.component.ts b/src/app/components/task-list/task-list.component.ts index b238299144cbc4b81774577df4f6dbfbd4271c09..7d65563c8d4c25513f29d6a432e48a9234121797 100644 --- a/src/app/components/task-list/task-list.component.ts +++ b/src/app/components/task-list/task-list.component.ts @@ -12,6 +12,7 @@ export class TaskListComponent implements OnInit { @Input() token: string; @Output() tokenChange: EventEmitter<string> = new EventEmitter(); + @Input() smallStyle: boolean; public algorithmNames = algorithmNames; diff --git a/src/app/config.ts b/src/app/config.ts index eeb8d4826efb35c9094c9b652b87573a911a5277..d581c050678d2fc6ab80d23af4902555e392ea50 100644 --- a/src/app/config.ts +++ b/src/app/config.ts @@ -35,7 +35,8 @@ export interface IConfig { legendUrl: string; legendClass: string; legendPos: 'left' | 'right'; - taskName: string; + taskTargetName: string, + taskDrugName: string, showLeftSidebar: boolean; showRightSidebar: boolean; showOverview: boolean; @@ -72,7 +73,8 @@ export const defaultConfig: IConfig = { legendUrl: '', // 'https://exbio.wzw.tum.de/covex/assets/leg1.png' show legend image if set, otherwise default legend legendClass: 'legend', legendPos: 'left', - taskName: 'Find Drug Candidates', + taskTargetName: 'Drug Target Search', + taskDrugName: 'Drug Search', showLegendNodes: true, showLegendEdges: true, showLeftSidebar: true, diff --git a/src/app/pages/explorer-page/explorer-page.component.html b/src/app/pages/explorer-page/explorer-page.component.html index 2bf03cafffd4eb6143f9e78b7f5040bcc712d63d..774e6032938e0eb70acc634fbf90ade1b29d6e28 100644 --- a/src/app/pages/explorer-page/explorer-page.component.html +++ b/src/app/pages/explorer-page/explorer-page.component.html @@ -1,7 +1,4 @@ -<div - id="appWindow" - (window:resize)="onResize($event)" -> +<div id="appWindow" (window:resize)="onResize($event)"> <div class="is-hidden-mobile fullheight" id="appContainer"> <app-launch-analysis [(show)]="showAnalysisDialog" @@ -73,7 +70,9 @@ <div> <p class="heading">Nodes</p> <p class="title"> - {{ currentViewNodes != null ? currentViewNodes.length : 0 }} + {{ + currentViewNodes != null ? currentViewNodes.length : 0 + }} </p> </div> </div> @@ -81,7 +80,9 @@ <div> <p class="heading">Interactions</p> <p class="title"> - {{ currentViewEdges != null ? currentViewEdges.length : 0 }} + {{ + currentViewEdges != null ? currentViewEdges.length : 0 + }} </p> </div> </div> @@ -158,6 +159,7 @@ <app-network-legend [config]="myConfig" [context]="legendContext" + [smallStyle]="smallStyle" ></app-network-legend> </div> <div class="center image1 fullheight" #network> @@ -173,58 +175,31 @@ > <div class="network-footer-toolbar-inner-container"> <ng-container *ngIf="myConfig.showFooterButtonScreenshot"> - <div - class=" - footer-buttons - network-footer-toolbar-element - " - > + <div class="footer-buttons network-footer-toolbar-element"> <button (click)="toImage()" - class=" - button - is-primary is-rounded - has-tooltip - " + class="button is-primary is-rounded has-tooltip" pTooltip="Take a screenshot of the current network." [ngClass]="{ 'button-small': smallStyle }" [tooltipStyleClass]="'drgstn drgstn-tooltip'" tooltipPosition="top" > - <span class="icon"> - <i class="fas fa-camera" aria-hidden="true"></i> - </span> + <span class="icon"> + <i class="fas fa-camera" aria-hidden="true"></i> + </span> <span [ngClass]="{ 'text-normal': smallStyle }" - >Screenshot</span + >Screenshot</span > </button> </div> </ng-container> <ng-container *ngIf="myConfig.showFooterButtonExportGraphml"> - <div - class=" - footer-buttons - network-footer-toolbar-element" - > - <button - (click)="graphmlLink()" - class="button - is-primary is-rounded - has-tooltip" - [ngClass]="{ 'button-small': smallStyle }" - pTooltip="Export this network as .graphml file." - [tooltipStyleClass]="'drgstn drgstn-tooltip'" - tooltipPosition="top" - > - <span class="icon"> - <i class="fas fa-download" aria-hidden="true"></i> - </span> - <span [ngClass]="{ 'text-normal': smallStyle }" - >.graphml</span - > - </button> - </div> + <app-download-button + [nodeData]="nodeData" + [smallStyle]="smallStyle" + [buttonId]="'explorer-download'" + ></app-download-button> </ng-container> <ng-container *ngIf="myConfig.showFooterButtonExpression"> @@ -252,10 +227,11 @@ <span *ngIf="!selectedTissue" [ngClass]="{ 'text-small': smallStyle }" - >Tissue</span> + >Tissue</span + > <span *ngIf="selectedTissue">{{ selectedTissue.name - }}</span> + }}</span> <span *ngIf="expressionExpanded" class="icon is-small"> <i class="fas fa-angle-up" aria-hidden="true"></i> </span> @@ -407,82 +383,147 @@ </a> </header> <div *ngIf="collapseAnalysisQuick"> - <div class="card-content quick-find" [ngClass]="{small:smallStyle}"> + <div + class="card-content quick-find" + [ngClass]="{ small: smallStyle }" + > <div class="field"> <div class="control"> - <div class="tile notification quick-start warning" [ngClass]="{small:smallStyle}"> + <div + class="tile notification quick-start warning" + [ngClass]="{ small: smallStyle }" + > <div class="align-vmiddle"> - <div [ngClass]="{'digit':!smallStyle, 'digit-small': smallStyle}"> + <div + [ngClass]="{ + digit: !smallStyle, + 'digit-small': smallStyle + }" + > <i class="fa fa-fast-forward"></i> </div> - <div style="display: flex; justify-content: center; width:100%"> + <div + style=" + display: flex; + justify-content: center; + width: 100%; + " + > <button (click)="analysis.startQuickAnalysis(true, null)" [disabled]="analysis.isLaunchingQuick()" - class="button is-white is-rounded has-tooltip quick-start-btn" + class=" + button + is-white is-rounded + has-tooltip + quick-start-btn + " pTooltip="Find drugs for all proteins." [tooltipStyleClass]="'drgstn drgstn-tooltip'" tooltipPosition="top" > - <span class="icon quick-icon"> - <span *ngIf="!analysis.isLaunchingQuick()"> - <i class="fa fa-capsules"></i> + <span class="icon quick-icon"> + <span *ngIf="!analysis.isLaunchingQuick()"> + <i class="fa fa-capsules"></i> + </span> + <span *ngIf="analysis.isLaunchingQuick()"> + <i class="fa fa-spin fa-spinner"></i> </span> - <span *ngIf="analysis.isLaunchingQuick()"> - <i class="fa fa-spin fa-spinner"></i> </span> - </span> <span [ngClass]="{ 'text-normal': smallStyle }"> - Quick Start - </span> + Quick Start + </span> </button> </div> </div> </div> <div class="divisor-rapid">— or —</div> - <div class="tile notification quick-start info" [ngClass]="{small:smallStyle}"> + <div + class="tile notification quick-start info" + [ngClass]="{ small: smallStyle }" + > <div class="align-vmiddle"> - <div [ngClass]="{'digit':!smallStyle, 'digit-small': smallStyle}" - *ngIf="analysis.getCount() == 0"> + <div + [ngClass]="{ + digit: !smallStyle, + 'digit-small': smallStyle + }" + *ngIf="analysis.getCount() == 0" + > 1 </div> - <div [ngClass]="{ 'digit': !smallStyle, 'digit-small': smallStyle }" - *ngIf="analysis.getCount() > 0"> + <div + [ngClass]="{ + digit: !smallStyle, + 'digit-small': smallStyle + }" + *ngIf="analysis.getCount() > 0" + > <i class="fa fa-check"></i> </div> - <div style="display: flex; justify-content: center; width:100%"> - <div [ngClass]="{ 'text-normal': smallStyle }" class="quick-start-btn" - >Select Proteins - </div + <div + style=" + display: flex; + justify-content: center; + width: 100%; + " + > + <div + [ngClass]="{ 'text-normal': smallStyle }" + class="quick-start-btn" > + Select Proteins + </div> </div> </div> </div> - <div class="tile notification quick-start info" [ngClass]="{small:smallStyle}"> + <div + class="tile notification quick-start info" + [ngClass]="{ small: smallStyle }" + > <div class="align-vmiddle"> - <div [ngClass]="{'digit':!smallStyle, 'digit-small': smallStyle}">2</div> - <div style="display: flex; justify-content: center; width:100%"> + <div + [ngClass]="{ + digit: !smallStyle, + 'digit-small': smallStyle + }" + > + 2 + </div> + <div + style=" + display: flex; + justify-content: center; + width: 100%; + " + > <button (click)="analysis.startQuickAnalysis(false, null)" [disabled]=" - analysis.getCount() === 0 || - analysis.isLaunchingQuick() - " - class="button is-white is-rounded quick-start-btn drugs-btn" + analysis.getCount() === 0 || + analysis.isLaunchingQuick() + " + class=" + button + is-white is-rounded + quick-start-btn + drugs-btn + " pTooltip="Find drugs for the selected proteins." [tooltipStyleClass]="'drgstn drgstn-tooltip'" tooltipPosition="top" - ><span class="icon quick-icon"> - <span *ngIf="!analysis.isLaunchingQuick()"> - <i class="fa fa-capsules"></i> + > + <span class="icon quick-icon"> + <span *ngIf="!analysis.isLaunchingQuick()"> + <i class="fa fa-capsules"></i> + </span> + <span *ngIf="analysis.isLaunchingQuick()"> + <i class="fa fa-spin fa-spinner"></i> </span> - <span *ngIf="analysis.isLaunchingQuick()"> - <i class="fa fa-spin fa-spinner"></i> </span> - </span> <span [ngClass]="{ 'text-normal': smallStyle }"> - Find Drugs - </span> + {{ myConfig.taskDrugName }} + </span> </button> </div> </div> @@ -543,7 +584,7 @@ <span class="icon"> <i class="fa fa-crosshairs"></i> </span> - <span> Find Drug Targets </span> + <span>{{ myConfig.taskDrugName }}</span> </button> </div> </div> @@ -570,7 +611,7 @@ <i class="fa fa-capsules"></i> </span> <span> - {{ myConfig.taskName }} + {{ myConfig.taskDrugName }} </span> </button> </div> @@ -652,7 +693,10 @@ class="card-content overflow task-list-container" *ngIf="analysis.tasks && analysis.tasks.length > 0" > - <app-task-list [(token)]="selectedAnalysisToken"></app-task-list> + <app-task-list + [(token)]="selectedAnalysisToken" + [smallStyle]="smallStyle" + ></app-task-list> </div> <footer class="card-footer"> <a @@ -710,45 +754,45 @@ *ngIf="analysis.getCount() > 0" > <thead> - <tr> - <td>Label</td> - <td>Group</td> - <td *ngIf="myConfig.identifier !== 'symbol'">Symbol</td> - <td *ngIf="myConfig.identifier !== 'uniprot'">Uniprot</td> - <td>Actions</td> - </tr> + <tr> + <td>Label</td> + <td>Group</td> + <td *ngIf="myConfig.identifier !== 'symbol'">Symbol</td> + <td *ngIf="myConfig.identifier !== 'uniprot'">Uniprot</td> + <td>Actions</td> + </tr> </thead> <tbody> - <tr *ngFor="let p of analysis.getSelection()"> - <td> - <p class="is-capitalized">{{ p.data.label }}</p> - </td> - <td> - <p> - {{ myConfig.nodeGroups[p.data.group]["groupName"] }} - </p> - </td> - <td *ngIf="myConfig.identifier !== 'symbol'"> - <p>{{ p.data.symbol }}</p> - </td> - <td *ngIf="myConfig.identifier !== 'uniprot'"> - <p>{{ p.data.uniprotAc }}</p> - </td> - <td> - <button - (click)="analysis.removeItems([p])" - class=" + <tr *ngFor="let p of analysis.getSelection()"> + <td> + <p class="is-capitalized">{{ p.data.label }}</p> + </td> + <td> + <p> + {{ myConfig.nodeGroups[p.data.group]["groupName"] }} + </p> + </td> + <td *ngIf="myConfig.identifier !== 'symbol'"> + <p>{{ p.data.symbol }}</p> + </td> + <td *ngIf="myConfig.identifier !== 'uniprot'"> + <p>{{ p.data.uniprotAc }}</p> + </td> + <td> + <button + (click)="analysis.removeItems([p])" + class=" button is-small is-danger is-outlined has-tooltip " - tooltipPosition="top" - pTooltip="Remove from selection." - > - <i class="fa fa-trash"></i> - </button> - </td> - </tr> + tooltipPosition="top" + pTooltip="Remove from selection." + > + <i class="fa fa-trash"></i> + </button> + </td> + </tr> </tbody> </table> <i *ngIf="analysis.getCount() === 0"> diff --git a/src/app/pages/explorer-page/explorer-page.component.ts b/src/app/pages/explorer-page/explorer-page.component.ts index d5ac088e11e7cebb00bf7ddfdf7778e04b598e6a..be407ec6ee5f5e785b5f5a49a54786293d31f8ae 100644 --- a/src/app/pages/explorer-page/explorer-page.component.ts +++ b/src/app/pages/explorer-page/explorer-page.component.ts @@ -369,13 +369,6 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { }); } - public graphmlLink() { - const data = {nodes: this.nodeData.nodes.get(), edges: this.nodeData.edges.get()}; - this.netex.graphmlLink(data).subscribe(response => { - return downLoadFile(response, "application/xml"); - }); - } - public async openSummary(item: Wrapper, zoom: boolean) { this.selectedWrapper = item; if (zoom) { diff --git a/src/app/services/netex-controller/netex-controller.service.ts b/src/app/services/netex-controller/netex-controller.service.ts index 0570859e78b7bb3ae60398e4cd7236b0e795a16d..32a1cd6455f8af7b82ea6f802ef469605df53cb2 100644 --- a/src/app/services/netex-controller/netex-controller.service.ts +++ b/src/app/services/netex-controller/netex-controller.service.ts @@ -122,9 +122,9 @@ export class NetexControllerService { return this.http.post<any>(`${environment.backend}adjacent_drugs/`, params); } - public graphmlLink(graph_data: { edges: EdgeType[], nodes: Node[] }) { + public graphExport(graph_data: { edges: EdgeType[], nodes: Node[] }) { /** - * Sends complete graph data to backend where it is written to graphml File. + * Sends complete graph data to backend where it is written to graphml or json File. * The file is returned as download for the user. */ return this.http.post(`${environment.backend}graph_export/`, graph_data, {responseType: 'text'}); diff --git a/src/app/utils.ts b/src/app/utils.ts index cd80e64ed93470672b601297798ce7e1678d773e..3036e23201ba5d90e495457be7d60750954eae37 100644 --- a/src/app/utils.ts +++ b/src/app/utils.ts @@ -124,11 +124,11 @@ export function removeDuplicateObjectsFromList(nodes: Node[], attribute: string) * @param data - Array Buffer data * @param type - type of the document. */ -export function downLoadFile(data: any, type: string) { +export function downLoadFile(data: any, type: string, fmt: string) { let blob = new Blob([data], { type: type}); var a = document.createElement("a"); a.href = URL.createObjectURL(blob); - a.download = 'test.graphml'; + a.download = `drugstone_network_${new Date().getTime()}.${fmt}`; a.click(); } diff --git a/src/stylesheets/bulma.scss b/src/stylesheets/bulma.scss index 4253f5b8da5b1cd5c8e717ee0bcc976e5422d837..1e4d756021a176af189c12e506aa7d618f2d4ab9 100644 --- a/src/stylesheets/bulma.scss +++ b/src/stylesheets/bulma.scss @@ -1,6 +1,10 @@ @import "toast"; #appWindow { @import "../../node_modules/bulma/bulma"; + + // bulma variables + $dropdown-content-radius: 20px; + height: var(--drgstn-height, 500px); margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; diff --git a/src/stylesheets/variables.scss b/src/stylesheets/variables.scss index 943a772546faff0ecc0a11c89f84a53c382f6bc9..03d7e80c7baa236d738382479774d3d708365401 100644 --- a/src/stylesheets/variables.scss +++ b/src/stylesheets/variables.scss @@ -51,3 +51,4 @@ $text-normal-font-size: 12px; $text-small-font-size: 11px; $button-small-padding: 3px 10px 3px 10px; +