diff --git a/src/app/components/analysis-panel/analysis-panel.component.html b/src/app/components/analysis-panel/analysis-panel.component.html index 32e3a0e6c7cc40c8991fe0c299a1f54a4f3d2dfd..95d06d2480d06b16d76a4414063966b514fde05f 100644 --- a/src/app/components/analysis-panel/analysis-panel.component.html +++ b/src/app/components/analysis-panel/analysis-panel.component.html @@ -138,101 +138,104 @@ </div> <footer *ngIf="myConfig.showFooter" class="card-footer toolbar network-footer-toolbar"> + + <div class="network-footer-toolbar-inner-container"> - <ng-container *ngIf="myConfig.showFooterButtonScreenshot"> - <button class="button is-primary is-rounded has-tooltip" - pTooltip="Take a screenshot of the current network." tooltipPosition="top" (click)="toImage()"> - <span class="icon"> - <i class="fas fa-camera" aria-hidden="true"></i> - </span> - <span [ngClass]="{'text-normal':smallStyle}"> - Screenshot - </span> - </button> - </ng-container> + <ng-container *ngIf="myConfig.showFooterButtonScreenshot"> + <button class="button is-primary is-rounded has-tooltip network-footer-toolbar-element" + pTooltip="Take a screenshot of the current network." tooltipPosition="top" (click)="toImage()"> + <span class="icon"> + <i class="fas fa-camera" aria-hidden="true"></i> + </span> + <span [ngClass]="{'text-normal':smallStyle}"> + Screenshot + </span> + </button> + </ng-container> - <div class="field"> - <p class="control footer-buttons"> - <a [href]="graphmlLink()" class="button is-success is-rounded has-tooltip" - pTooltip="Export this network as .graphml file." tooltipPosition="top"> - <span class="icon"> - <i class="fas fa-download" aria-hidden="true"></i> - </span> - <span [ngClass]="{'text-normal':smallStyle}"> - Export as .graphml - </span> - </a> - </p> - </div> + <div class="field network-footer-toolbar-element"> + <p class="control footer-buttons"> + <a [href]="graphmlLink()" class="button is-success is-rounded has-tooltip" + pTooltip="Export this network as .graphml file." tooltipPosition="top"> + <span class="icon"> + <i class="fas fa-download" aria-hidden="true"></i> + </span> + <span [ngClass]="{'text-normal':smallStyle}"> + Export as .graphml + </span> + </a> + </p> + </div> - <!-- <div class="field">--> - <!-- <p class="control footer-buttons">--> - <!-- <button class="button is-danger is-rounded has-tooltip" data-tooltip="Delete the current analysis."--> - <!-- (click)="analysis.removeTask(token); close()">--> - <!-- <span class="icon">--> - <!-- <i class="fas fa-trash" aria-hidden="true"></i>--> - <!-- </span>--> - <!-- <span>--> - <!-- Delete Analysis--> - <!-- </span>--> - <!-- </button>--> - <!-- </p>--> - <!-- </div>--> + <!-- <div class="field">--> + <!-- <p class="control footer-buttons">--> + <!-- <button class="button is-danger is-rounded has-tooltip" data-tooltip="Delete the current analysis."--> + <!-- (click)="analysis.removeTask(token); close()">--> + <!-- <span class="icon">--> + <!-- <i class="fas fa-trash" aria-hidden="true"></i>--> + <!-- </span>--> + <!-- <span>--> + <!-- Delete Analysis--> + <!-- </span>--> + <!-- </button>--> + <!-- </p>--> + <!-- </div>--> - <div class="footer-buttons dropdown is-up" [class.is-active]="expressionExpanded"> - <div class="dropdown-trigger"> - <button (click)="expressionExpanded=!expressionExpanded" - class="button is-rounded is-primary" [class.is-outlined]="!selectedTissue" - aria-haspopup="true" aria-controls="dropdown-menu" [ngClass]="{'button-small':smallStyle}" - pTooltip="Tissue expression data is provided by the GTEx project." tooltipPosition="top" - > - <div [ngClass]="{'text-small':smallStyle}"> - <span *ngIf="!selectedTissue">Tissue</span> - <span *ngIf="selectedTissue">{{selectedTissue.name}}</span> - <span class="icon is-small"> - <i class="fas" - [class.fa-angle-up]="expressionExpanded" - [class.fa-angle-left]="!expressionExpanded" aria-hidden="true"></i> - </span> - </div> - </button> - </div> - <div class="dropdown-menu" id="dropdown-menu" role="menu"> - <div class="dropdown-content tissue-dropdown" [ngClass]="{'button-small':smallStyle}"> - <div class="scroll-area" [ngClass]="{'text-small':smallStyle}"> - <a (click)="selectTissue(null)" - [class.is-active]="!selectedTissue" - class="dropdown-item"> - None - </a> - <a *ngFor="let tissue of analysis.getTissues()" - (click)="selectTissue(tissue)" - [class.is-active]="selectedTissue && tissue.netexId === selectedTissue.netexId" - class="dropdown-item"> - {{tissue.name}} - </a> + <div class="footer-buttons dropdown is-up network-footer-toolbar-element" [class.is-active]="expressionExpanded"> + <div class="dropdown-trigger"> + <button (click)="expressionExpanded=!expressionExpanded" + class="button is-rounded is-primary" [class.is-outlined]="!selectedTissue" + aria-haspopup="true" aria-controls="dropdown-menu" [ngClass]="{'button-small':smallStyle}" + pTooltip="Tissue expression data is provided by the GTEx project." tooltipPosition="top" + > + <div [ngClass]="{'text-small':smallStyle}"> + <span *ngIf="!selectedTissue">Tissue</span> + <span *ngIf="selectedTissue">{{selectedTissue.name}}</span> + <span class="icon is-small"> + <i class="fas" + [class.fa-angle-up]="expressionExpanded" + [class.fa-angle-left]="!expressionExpanded" aria-hidden="true"></i> + </span> + </div> + </button> + </div> + <div class="dropdown-menu" id="dropdown-menu" role="menu"> + <div class="dropdown-content tissue-dropdown" [ngClass]="{'button-small':smallStyle}"> + <div class="scroll-area" [ngClass]="{'text-small':smallStyle}"> + <a (click)="selectTissue(null)" + [class.is-active]="!selectedTissue" + class="dropdown-item"> + None + </a> + <a *ngFor="let tissue of analysis.getTissues()" + (click)="selectTissue(tissue)" + [class.is-active]="selectedTissue && tissue.netexId === selectedTissue.netexId" + class="dropdown-item"> + {{tissue.name}} + </a> + </div> </div> </div> </div> - </div> - <app-toggle class="footer-buttons" textOn="Seeds On" textOff="Off" - tooltipOn="Highlight seed nodes ON." - tooltipOff="Highlight seed nodes OFF." - [smallStyle]="smallStyle" - [value]="highlightSeeds" (valueChange)="updateHighlightSeeds($event)"></app-toggle> + <app-toggle class="footer-buttons network-footer-toolbar-element" textOn="Seeds On" textOff="Off" + tooltipOn="Highlight seed nodes ON." + tooltipOff="Highlight seed nodes OFF." + [smallStyle]="smallStyle" + [value]="highlightSeeds" (valueChange)="updateHighlightSeeds($event)"></app-toggle> - <app-toggle *ngIf="task.info.target === 'drug-target'" class="footer-buttons" textOn="Drugs On" textOff="Off" - tooltipOn="Display adjacent drugs ON." - tooltipOff="Display adjacent drugs OFF." - [smallStyle]="smallStyle" - [value]="adjacentDrugs" (valueChange)="updateAdjacentDrugs($event)"></app-toggle> + <app-toggle *ngIf="task.info.target === 'drug-target'" class="footer-buttons network-footer-toolbar-element" textOn="Drugs On" textOff="Off" + tooltipOn="Display adjacent drugs ON." + tooltipOff="Display adjacent drugs OFF." + [smallStyle]="smallStyle" + [value]="adjacentDrugs" (valueChange)="updateAdjacentDrugs($event)"></app-toggle> - <app-toggle class="footer-buttons" textOn="Animation On" textOff="Off" - tooltipOn="Enable the network animation." - tooltipOff="Disable the network animation and freeze nodes." - [smallStyle]="smallStyle" - [value]="physicsEnabled" (valueChange)="updatePhysicsEnabled($event)"></app-toggle> + <app-toggle class="footer-buttons network-footer-toolbar-element" textOn="Animation On" textOff="Off" + tooltipOn="Enable the network animation." + tooltipOff="Disable the network animation and freeze nodes." + [smallStyle]="smallStyle" + [value]="physicsEnabled" (valueChange)="updatePhysicsEnabled($event)"></app-toggle> + </div> </footer> </div> <div class="content tab-content scrollable table-tab" *ngIf="task && task.info.done" [class.is-visible]="tab === 'table'"> diff --git a/src/app/components/analysis-panel/analysis-panel.component.scss b/src/app/components/analysis-panel/analysis-panel.component.scss index e4cf77d38f15b3acec6412ca1ea4bf0fedccabf1..34923202bc25922ab092d504c1c9c8dd6c435940 100644 --- a/src/app/components/analysis-panel/analysis-panel.component.scss +++ b/src/app/components/analysis-panel/analysis-panel.component.scss @@ -73,3 +73,10 @@ overflow-y: auto; } +.network-footer-toolbar{ + .dropdown-menu{ + z-index: $analysis-network-toolbar-dropdown-z; + } +} + + diff --git a/src/app/components/analysis-panel/analysis-panel.component.ts b/src/app/components/analysis-panel/analysis-panel.component.ts index 1a7b525b74aa9c398d8bf86fe826e7e91d5ae871..9363902466fbcb707c58bec7e17a309540e8f333 100644 --- a/src/app/components/analysis-panel/analysis-panel.component.ts +++ b/src/app/components/analysis-panel/analysis-panel.component.ts @@ -115,6 +115,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { public tableProteinScoreTooltip = ''; public expressionMap: NodeAttributeMap; + public gradientMap: NodeAttributeMap; constructor(private http: HttpClient, public analysis: AnalysisService, public netex: NetexControllerService) { } @@ -267,12 +268,13 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { node.x = pos[item.id].x; node.y = pos[item.id].y; const isSeed = this.highlightSeeds ? this.seedMap[node.id] : false; + const gradient = (this.gradientMap !== {}) && (this.gradientMap[item.id]) ? this.gradientMap[item.id] : 1.0; const nodeStyled = NetworkSettings.getNodeStyle( node, this.myConfig, isSeed, selected, - 1.0 + gradient ) updatedNodes.push(nodeStyled); } @@ -294,6 +296,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { this.tableSelectedProteins = [...proteinSelection]; this.tableSelectedViralProteins = [...viralProteinSelection]; } else { + // else: selected is null const updatedNodes = []; this.nodeData.nodes.forEach((node) => { let drugType; @@ -302,12 +305,14 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { drugType = node.wrapper.data.status; drugInTrial = node.wrapper.data.inTrial; } + const isSeed = this.highlightSeeds ? this.seedMap[node.id] : false; + const gradient = (this.gradientMap !== {}) && (this.gradientMap[node.id]) ? this.gradientMap[node.id] : 1.0; const nodeStyled = NetworkSettings.getNodeStyle( node, this.myConfig, - false, + isSeed, selected, - 1.0 + gradient ) updatedNodes.push(nodeStyled); }); @@ -652,12 +657,13 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { const pos = this.network.getPositions([item.id]); node.x = pos[item.id].x; node.y = pos[item.id].y; + const isSeed = this.highlightSeeds ? this.seedMap[node.id] : false; Object.assign( node, NetworkSettings.getNodeStyle( node, this.myConfig, - false, + isSeed, this.analysis.inSelection(getWrapperFromNode(item)), 1.0 ) @@ -667,6 +673,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { this.nodeData.nodes.update(updatedNodes); // delete expression values this.expressionMap = undefined; + this.gradientMap = {}; } else { this.selectedTissue = tissue const minExp = 0.3; @@ -693,18 +700,19 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { continue; } const wrapper = getWrapperFromNode(node) - const gradient = expressionlvl !== null ? (Math.pow(expressionlvl / maxExpr, 1 / 3) * (1 - minExp) + minExp) : -1; + this.gradientMap[netexId] = expressionlvl !== null ? (Math.pow(expressionlvl / maxExpr, 1 / 3) * (1 - minExp) + minExp) : -1; const pos = this.network.getPositions([networkId]); node.x = pos[networkId].x; node.y = pos[networkId].y; + const isSeed = this.highlightSeeds ? this.seedMap[node.id] : false; Object.assign(node, NetworkSettings.getNodeStyle( node, this.myConfig, - false, // node.isSeed, + isSeed, this.analysis.inSelection(wrapper), - gradient)); - node.gradient = gradient; + this.gradientMap[netexId])); + node.gradient = this.gradientMap[netexId]; updatedNodes.push(node); } this.nodeData.nodes.update(updatedNodes); diff --git a/src/app/interfaces.ts b/src/app/interfaces.ts index 2e6a5760d437d7ee8a0800498ebbb1b65bcb2ac0..cab05e038dc8882bcd5d47fb10bb085379c7721c 100644 --- a/src/app/interfaces.ts +++ b/src/app/interfaces.ts @@ -35,7 +35,7 @@ export type legendContext = 'explorer' | 'adjacentDrugs' | 'drug' | 'drugTarget' 'drugTargetAndSeeds' | 'drugAndSeeds'; /// netexId to expressionlvl -export type NodeAttributeMap = { string: number }; +export type NodeAttributeMap = { string: number } | {}; export interface NodeInteraction { diff --git a/src/app/pages/explorer-page/explorer-page.component.html b/src/app/pages/explorer-page/explorer-page.component.html index 9cc38a205907ad93fa79fceeb019f7398b2efa86..2cf67c4595d470b67f76723c0252567bef7f773b 100644 --- a/src/app/pages/explorer-page/explorer-page.component.html +++ b/src/app/pages/explorer-page/explorer-page.component.html @@ -132,67 +132,69 @@ <footer *ngIf="myConfig.showFooter" class="card-footer toolbar network-footer-toolbar"> - <ng-container *ngIf="myConfig.showFooterButtonScreenshot"> - <button (click)="toImage()" class="button is-primary is-rounded has-tooltip network-footer-toolbar-element" - pTooltip="Take a screenshot of the current network." tooltipPosition="top"> - <span class="icon"> - <i class="fas fa-camera" aria-hidden="true"></i> - </span> - <span [ngClass]="{'text-normal':smallStyle}">Screenshot</span> - </button> - </ng-container> - - <ng-container *ngIf="myConfig.showFooterButtonExpression"> - <div class="footer-buttons dropdown is-up network-footer-toolbar-element" [class.is-active]="expressionExpanded"> - - <div class="dropdown-trigger"> - <button (click)="expressionExpanded=!expressionExpanded" - class="button is-rounded is-primary" [class.is-outlined]="!selectedTissue" - aria-haspopup="true" aria-controls="dropdown-menu" - pTooltip="Tissue expression data is provided by the GTEx project." tooltipPosition="top" - [ngClass]="{'button-small':smallStyle}"> - <span *ngIf="!selectedTissue" [ngClass]="{'text-small':smallStyle}">Tissue</span> - <span *ngIf="selectedTissue">{{selectedTissue.name}}</span> - <span *ngIf="expressionExpanded" class="icon is-small"> - <i class="fas fa-angle-up" aria-hidden="true"></i> - </span> - <span *ngIf="!expressionExpanded" class="icon is-small"> - <i class="fas fa-angle-left" aria-hidden="true"></i> - </span> - </button> - </div> - <div class="dropdown-menu" id="dropdown-menu" role="menu"> - <div class="dropdown-content tissue-dropdown"> - <div class="scroll-area"> - <a (click)="selectTissue(null)" - [class.is-active]="!selectedTissue" - class="dropdown-item"> - None - </a> - <a *ngFor="let tissue of analysis.getTissues()" - (click)="selectTissue(tissue)" - [class.is-active]="selectedTissue && tissue.netexId === selectedTissue.netexId" - class="dropdown-item"> - {{tissue.name}} - </a> + <div class="network-footer-toolbar-inner-container"> + + <ng-container *ngIf="myConfig.showFooterButtonScreenshot"> + <button (click)="toImage()" class="button is-primary is-rounded has-tooltip network-footer-toolbar-element" + pTooltip="Take a screenshot of the current network." tooltipPosition="top"> + <span class="icon"> + <i class="fas fa-camera" aria-hidden="true"></i> + </span> + <span [ngClass]="{'text-normal':smallStyle}">Screenshot</span> + </button> + </ng-container> + + <ng-container *ngIf="myConfig.showFooterButtonExpression"> + <div class="footer-buttons dropdown is-up network-footer-toolbar-element" [class.is-active]="expressionExpanded"> + + <div class="dropdown-trigger"> + <button (click)="expressionExpanded=!expressionExpanded" + class="button is-rounded is-primary" [class.is-outlined]="!selectedTissue" + aria-haspopup="true" aria-controls="dropdown-menu" + pTooltip="Tissue expression data is provided by the GTEx project." tooltipPosition="top" + [ngClass]="{'button-small':smallStyle}"> + <span *ngIf="!selectedTissue" [ngClass]="{'text-small':smallStyle}">Tissue</span> + <span *ngIf="selectedTissue">{{selectedTissue.name}}</span> + <span *ngIf="expressionExpanded" class="icon is-small"> + <i class="fas fa-angle-up" aria-hidden="true"></i> + </span> + <span *ngIf="!expressionExpanded" class="icon is-small"> + <i class="fas fa-angle-left" aria-hidden="true"></i> + </span> + </button> + </div> + <div class="dropdown-menu" id="dropdown-menu" role="menu"> + <div class="dropdown-content tissue-dropdown"> + <div class="scroll-area"> + <a (click)="selectTissue(null)" + [class.is-active]="!selectedTissue" + class="dropdown-item"> + None + </a> + <a *ngFor="let tissue of analysis.getTissues()" + (click)="selectTissue(tissue)" + [class.is-active]="selectedTissue && tissue.netexId === selectedTissue.netexId" + class="dropdown-item"> + {{tissue.name}} + </a> + </div> </div> </div> </div> - </div> - </ng-container> - - <app-toggle class="footer-buttons" textOn="Drugs" textOff="Off" - tooltipOn="Display adjacent drugs ON." - tooltipOff="Display adjacent drugs OFF." - [smallStyle]="smallStyle" - [value]="adjacentDrugs" (valueChange)="updateAdjacentDrugs($event)"></app-toggle> - - <app-toggle class="footer-buttons network-footer-toolbar-element" textOn="Animation On" textOff="Off" - tooltipOn="Enable the network animation." - tooltipOff="Disable the network animation and freeze nodes." - [smallStyle]="smallStyle" - [value]="physicsEnabled" (valueChange)="updatePhysicsEnabled($event)"></app-toggle> - + </ng-container> + + <app-toggle class="footer-buttons network-footer-toolbar-element" textOn="Drugs" textOff="Off" + tooltipOn="Display adjacent drugs ON." + tooltipOff="Display adjacent drugs OFF." + [smallStyle]="smallStyle" + [value]="adjacentDrugs" (valueChange)="updateAdjacentDrugs($event)"></app-toggle> + + <app-toggle class="footer-buttons network-footer-toolbar-element" textOn="Animation On" textOff="Off" + tooltipOn="Enable the network animation." + tooltipOff="Disable the network animation and freeze nodes." + [smallStyle]="smallStyle" + [value]="physicsEnabled" (valueChange)="updatePhysicsEnabled($event)"></app-toggle> + </div> </footer> </div> </div> diff --git a/src/styles.scss b/src/styles.scss index d6ff399d79bc4cd8e2d9b5026ee6afd80aa33bea..ef29e719e04c64858d252fa226fb60610cf235a8 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -15,17 +15,33 @@ .canvas-content { height: calc(100% - #{$network-footer-height}); + z-index: $explorer-network-z; } +// general network settings, some will be overwritten in analysis .network-footer-toolbar { position: absolute; - overflow-x: auto; - overflow-y: hidden; width: 100%; bottom: 0; height: $network-footer-height; + &-inner-container{ + width: 100%; + display: inline-flex; + overflow-x: auto; + overflow-y: hidden; + height: $network-footer-inner-container-height; + position: absolute; + bottom: 0; + } &-element { position: relative; + margin-top: calc(#{$network-footer-inner-container-height} - #{$network-footer-height} + #{$network-footer-space-button-to-border}); + } + .dropdown-menu{ + z-index: $explorer-network-toolbar-dropdown-z; + .scroll-area{ + height: calc(#{$network-footer-inner-container-height} - #{$network-footer-height}); + } } } @@ -185,7 +201,10 @@ div.covex.explorer { width: 100%; position: absolute; margin-top: 0; - z-index: 10; + z-index: $analysis-view-z; + .canvas-content { + z-index: $analysis-network-z; + } } div.field.has-addons.add-remove-toggle { diff --git a/src/variables.scss b/src/variables.scss index bf25cef9ccd28356a8b1ae3f21b4a5d78ca452d1..0af86f913ed1e48944cadf86adcee813e4c2f106 100644 --- a/src/variables.scss +++ b/src/variables.scss @@ -1,6 +1,15 @@ $row-data-selector-height: auto; $network-header-height: 3rem; $network-footer-height: 4rem; +$network-footer-inner-container-height: 25rem; +$network-footer-space-button-to-border: 0.5rem; + +$explorer-network-z: 10; +$explorer-network-toolbar-dropdown-z: 20; + +$analysis-view-z: 30; +$analysis-network-z: 40; +$analysis-network-toolbar-dropdown-z: 50; $analysis-tab-header-height: 2.5rem; $analysis-tab-header-padding: 1.5rem;