From 4495f64489621d3fdd621003c31782e88948395c Mon Sep 17 00:00:00 2001
From: Michael Hartung <michi@Michaels-MacBook-Pro.local>
Date: Tue, 27 Jul 2021 12:24:58 +0200
Subject: [PATCH] expression dropdown fix issue with overflow hidden

---
 .../analysis-panel.component.html             | 173 +++++++++---------
 .../analysis-panel.component.scss             |   7 +
 .../analysis-panel.component.ts               |  24 ++-
 src/app/interfaces.ts                         |   2 +-
 .../explorer-page.component.html              | 118 ++++++------
 src/styles.scss                               |  25 ++-
 src/variables.scss                            |   9 +
 7 files changed, 203 insertions(+), 155 deletions(-)

diff --git a/src/app/components/analysis-panel/analysis-panel.component.html b/src/app/components/analysis-panel/analysis-panel.component.html
index 32e3a0e6..95d06d24 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 e4cf77d3..34923202 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 1a7b525b..93639024 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 2e6a5760..cab05e03 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 9cc38a20..2cf67c45 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 d6ff399d..ef29e719 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 bf25cef9..0af86f91 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;
-- 
GitLab