From b20f52e231ecddc53b5bd4aef817474568431bf6 Mon Sep 17 00:00:00 2001
From: Michael Hartung <michi@Michaels-MacBook-Pro.local>
Date: Tue, 27 Jul 2021 17:30:40 +0200
Subject: [PATCH] fix shadow on nodes and edges; keep default node and edge
 group for fallback cases

---
 .../network-legend.component.html             | 14 ++--
 .../network-legend.component.ts               | 34 +++++++---
 src/app/config.ts                             |  1 -
 src/app/main-network.ts                       |  8 +--
 src/app/network-settings.ts                   |  4 +-
 .../explorer-page/explorer-page.component.ts  | 68 ++++++-------------
 src/index.html                                |  4 +-
 7 files changed, 60 insertions(+), 73 deletions(-)

diff --git a/src/app/components/network-legend/network-legend.component.html b/src/app/components/network-legend/network-legend.component.html
index 8fe27208..f9d7c24b 100644
--- a/src/app/components/network-legend/network-legend.component.html
+++ b/src/app/components/network-legend/network-legend.component.html
@@ -5,7 +5,7 @@
     <ng-container *ngIf="this.config.showLegendNodes">
       <tr *ngFor="let nodeGroup of this.config.nodeGroups | keyvalue" class="list-item">
 
-        <ng-container *ngIf="nodeGroup.key && checkContext(nodeGroup.key)">
+        <ng-container *ngIf="nodeGroup.key && checkNodeGroupContext(nodeGroup.key)">
           <ng-container *ngIf="nodeGroup.value.image">
             <!-- group icon given, use icon in legend -->
             <th>
@@ -65,11 +65,13 @@
 
     <ng-container *ngIf="this.config.showLegendEdges">
       <tr *ngFor="let edgeGroup of this.config.edgeGroups | keyvalue" class="list-item">
-        <th>
-          <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>&nbsp;{{ edgeGroup.value.groupName }}</td>
+        <ng-container *ngIf="edgeGroup.key && checkEdgeGroupContext(edgeGroup.key)">
+          <th>
+            <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>&nbsp;{{ edgeGroup.value.groupName }}</td>
+        </ng-container>
       </tr>
     </ng-container>
   </table>
diff --git a/src/app/components/network-legend/network-legend.component.ts b/src/app/components/network-legend/network-legend.component.ts
index 1b9bd1b2..431fbe69 100644
--- a/src/app/components/network-legend/network-legend.component.ts
+++ b/src/app/components/network-legend/network-legend.component.ts
@@ -12,21 +12,37 @@ export class NetworkLegendComponent implements OnInit {
   @Input() context: legendContext;
   @Input() config: IConfig;
 
-  private contextGroupsToDelete = {
-    'explorer': ['foundNode', 'foundDrug', 'seedNode'],
-    'adjacentDrugs': ['foundNode', 'seedNode'],
-    'drugTarget': ['foundDrug', 'seedNode'],
-    'drug': ['seedNode'],
-    'drugTargetAndSeeds': ['foundDrug'],
-    'drugAndSeeds': []
+  private contextNodeGroupsToDelete = {
+    'explorer': ['foundNode', 'foundDrug', 'seedNode', 'default'],
+    'adjacentDrugs': ['foundNode', 'seedNode', 'default'],
+    'drugTarget': ['foundDrug', 'seedNode', 'default'],
+    'drug': ['seedNode', 'default'],
+    'drugTargetAndSeeds': ['foundDrug', 'default'],
+    'drugAndSeeds': ['default']
   }
 
-  public checkContext(nodeGroupKey) {
+  private contextEdgeGroupsToDelete = {
+    'explorer': ['default'],
+    'adjacentDrugs': ['default'],
+    'drugTarget': ['default'],
+    'drug': ['default'],
+    'drugTargetAndSeeds': ['default'],
+    'drugAndSeeds': ['default']
+  }
+
+  public checkNodeGroupContext(nodeGroupKey) {
     if (nodeGroupKey === 'selectedNode') {
       // selected node is not supposed to appear in legend
       return false;
     }
-    if (this.contextGroupsToDelete[this.context].includes(nodeGroupKey)) {
+    if (this.contextNodeGroupsToDelete[this.context].includes(nodeGroupKey)) {
+      return false;
+    }
+    return true;
+  }
+
+  public checkEdgeGroupContext(edgeGroupKey) {
+    if (this.contextEdgeGroupsToDelete[this.context].includes(edgeGroupKey)) {
       return false;
     }
     return true;
diff --git a/src/app/config.ts b/src/app/config.ts
index ab2ff279..62a8ab8c 100644
--- a/src/app/config.ts
+++ b/src/app/config.ts
@@ -105,7 +105,6 @@ export const defaultConfig: IConfig = {
           border: '#FF0000',
           background: '#FF0000'
         },
-      shadow: true,
       },
       shape: 'triangle',
       type: 'default type',
diff --git a/src/app/main-network.ts b/src/app/main-network.ts
index 3dbe25be..1abe89b4 100644
--- a/src/app/main-network.ts
+++ b/src/app/main-network.ts
@@ -75,7 +75,7 @@ export class ProteinNetwork {
   let node;
   if (customNode.group === undefined) {
     // fallback to default node
-    node = JSON.parse(JSON.stringify(defaultConfig.nodeGroups.default));
+    node = JSON.parse(JSON.stringify(config.nodeGroups.default));
     node.group = 'default';
   } else {
     if (config.nodeGroups[customNode.group] === undefined) {
@@ -103,10 +103,10 @@ export function mapCustomEdge(customEdge: NodeInteraction, config: IConfig): any
   let edge;
   if (customEdge.group === undefined) {
     // fallback to default node
-    edge = JSON.parse(JSON.stringify(defaultConfig.edgeGroups.default));
+    edge = JSON.parse(JSON.stringify(config.edgeGroups.default));
   } else {
     if (config.edgeGroups[customEdge.group] === undefined) {
-      throw `Edge "from ${customEdge.from}" - "to ${customEdge.to}" has undefined edge group ${customEdge.group}.`
+      console.error(`Edge "from ${customEdge.from}" - "to ${customEdge.to}" has undefined edge group ${customEdge.group}.`);
     }
     // copy
     edge = JSON.parse(JSON.stringify(config.edgeGroups[customEdge.group]));
@@ -114,6 +114,6 @@ export function mapCustomEdge(customEdge: NodeInteraction, config: IConfig): any
   edge = {
     ...edge,
     ...customEdge
-  }
+  };
   return edge;
 }
diff --git a/src/app/network-settings.ts b/src/app/network-settings.ts
index 649d1d94..7a649fae 100644
--- a/src/app/network-settings.ts
+++ b/src/app/network-settings.ts
@@ -127,10 +127,10 @@ export class NetworkSettings {
     isSelected: boolean,
     gradient: number = 1): Node {
       // delete possible old styles
-      Object.keys(defaultConfig.nodeGroups.default).forEach(e => delete node[e]);
+      Object.keys(config.nodeGroups.default).forEach(e => delete node[e]);
       // set group styles
       if (node.group === 'default') {
-        node = merge(node, defaultConfig.nodeGroups.default);
+        node = merge(node, config.nodeGroups.default);
       } else {
         node = merge(node, config.nodeGroups[node.group]);
       }
diff --git a/src/app/pages/explorer-page/explorer-page.component.ts b/src/app/pages/explorer-page/explorer-page.component.ts
index 1d415f1a..ac2bb1d0 100644
--- a/src/app/pages/explorer-page/explorer-page.component.ts
+++ b/src/app/pages/explorer-page/explorer-page.component.ts
@@ -57,24 +57,23 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
     if (typeof config === 'undefined') {
       return;
     }
+
+    // addd settings to config
+    const configObj = JSON.parse(config);
+    this.myConfig = merge(this.myConfig, configObj)
+
+    // update Drugst.One according to the settings
     // check if config updates affect network
     let updateNetworkFlag = false;
-    const configObj = JSON.parse(config);
     for (const key of Object.keys(configObj)) {
       if (key === 'nodeGroups') {
         this.setConfigNodeGroup(key, configObj[key]);
         updateNetworkFlag = true;
-        // dont set the key here, will be set in function
-        continue;
       } else if (key === 'edgeGroups') {
         this.setConfigEdgeGroup(key, configObj[key]);
         updateNetworkFlag = true;
-        // dont set the key here, will be set in function
-        continue;
       } else if (key === 'interactions') {
         this.getInteractions(configObj[key]);
-        // dont set the key here, will be set in function
-        continue;
       } else if (key === 'showLeftSidebar') {
         if (configObj[key]) {
           // shrink main column
@@ -92,7 +91,6 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
           document.getElementById('main-column').classList.add('rightgone');
         }
       }
-      this.myConfig[key] = configObj[key];
     }
     // trigger updates on config e.g. in legend
     this.myConfig = {...this.myConfig};
@@ -477,25 +475,21 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
    * @param values
    */
   public setConfigNodeGroup(key: string, nodeGroups: { [key: string]: NodeGroup }) {
-    if (nodeGroups === undefined || !Object.keys(nodeGroups).length) {
-      // if node groups are not set or empty, use default node group(s)
-      this.myConfig[key] = defaultConfig.nodeGroups;
-    }
+    // make sure that return-groups (seeds, drugs, found nodes) are set
+    const defaultNodeGroups = JSON.parse(JSON.stringify(defaultConfig.nodeGroups));
+    // user merge function to do deep merge
+    nodeGroups = merge(defaultNodeGroups, nodeGroups);
 
     // make sure all keys are set
     Object.entries(nodeGroups).forEach(([key, group]) => {
-      if (key in defaultConfig.nodeGroups) {
-        // skip the groups that overwrite default groups in case user only wants to overwrite partially
-        return
+      if (!group.color && key !== 'selectedNode') {
+        console.error(`Group ${key} has no attribute 'color'.`);
       }
-      if (!group.color) {
-        throw `Group ${defaultConfig.nodeGroups.groupName} has no attribute 'color'.`;
+      if (!group.shape && key !== 'selectedNode') {
+        console.error(`Group ${key} has no attribute 'shape'.`);
       }
-      if (!group.shape) {
-        throw `Group ${defaultConfig.nodeGroups.groupName} has no attribute 'shape'.`;
-      }
-      if (!group.groupName) {
-        throw `Group ${defaultConfig.nodeGroups.groupName} has no attribute 'groupName'.`;
+      if (!group.groupName && key !== 'selectedNode') {
+        console.error(`Group ${key} has no attribute 'groupName'.`);
       }
       // set default values in case they are not set by user
       // these values are not mandatory but are neede to override default vis js styles after e.g. deselecting
@@ -526,28 +520,8 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
       }
       // implement nodeShadow option, it needs to be set for all nodes or none
       group.shadow = this.myConfig.nodeShadow;
-
-      // color needs to be hexacode to calculate gradient, group.color might not be set for seed and selected group
-      // if (!group.color.startsWith('#')) {
-      //   // color is either rgba, rgb or string like "red"
-      //   if (group.color.startsWith('rgba')) {
-      //     group.color = rgbaToHex(group.color).slice(0, 7)
-      //   } else if (group.color.startsWith('rgb')) {
-      //     group.color = rgbToHex(group.color)
-      //   } else (
-      //     group.color = standardize_color(group.color)
-      //   )
-      // }
     });
 
-    // make sure that return-groups (seeds, drugs, found nodes) are set
-    const defaultNodeGroups = JSON.parse(JSON.stringify(defaultConfig.nodeGroups));
-    // if user has set nodeGroups, do not use group "default"
-    delete defaultNodeGroups.default;
-    // if user has not set the return-groups, take the defaults
-    // user merge function to do deep merge
-    nodeGroups = merge(defaultNodeGroups, nodeGroups);
-    // overwrite default node groups
     this.myConfig[key] = nodeGroups;
   }
 
@@ -558,12 +532,9 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
    * @param values
    */
   public setConfigEdgeGroup(key: string, edgeGroups: { [key: string]: EdgeGroup }) {
-    if (edgeGroups === undefined || !Object.keys(edgeGroups).length) {
-      // if edge groups are not set or empty, use default edge group(s)
-      this.myConfig[key] = defaultConfig.edgeGroups;
-      // stop if edgeGroups do not contain any information
-      return;
-    }
+    // make sure that default-groups are set
+    const defaultNodeGroups = JSON.parse(JSON.stringify(defaultConfig.edgeGroups));
+    edgeGroups = merge(defaultNodeGroups, edgeGroups);
 
     // // do not allow '_' in node Group names since it causes problems with backend
     // edgeGroups = removeUnderscoreFromKeys(edgeGroups)
@@ -578,7 +549,6 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
       // implement edgeShadow option, it needs to be set for all nodes or none
       value.shadow = this.myConfig.edgeShadow;
     });
-    // override default node groups
     this.myConfig[key] = edgeGroups;
   }
 
diff --git a/src/index.html b/src/index.html
index 90593de9..60f927f0 100644
--- a/src/index.html
+++ b/src/index.html
@@ -38,8 +38,8 @@
                       "nodeGroups": {"selectedNode": {"font": {"size": "18"} }, "0.5": {"shadow":"true","font": "18px verdana blue", "type": "0.5er Instanz", "color": "green", "groupName": "0.5", "shape": "star"}, "patientgroup": {"type": "Patient", "detailShowLabel": "true", "color": "#632345", "groupName": "patient group", "shape": "dot", "size": "50"}, "pugGroup": {"type": "woof woof", "color": "grey", "groupName": "Pug Group", "shape": "triangle", "image": "https://static.raymondcamden.com/images/2016/11/pug.png"}},
                       "edgeGroups": {"xxx": {"color": "black", "groupName": "xxx Group", "dashes": [1, 2]}, "notdashes": {"color": "black", "groupName": "not dashes Group"}},
                       "identifier": "symbol",
-                      "nodeShadow": "true",
-                      "edgeShadow": "true"
+                      "nodeShadow": true,
+                      "edgeShadow": true
                     }'
                     network='{
                       "nodes": [{"id": "TP53", "group": "0.5"}, {"id": "MYC", "group": "pugGroup"}, {"id": "Patient No. 5", "group": "patientgroup"}, {"label": "PTEN", "id": "PTEN", "group": 0.5, "value":"5"}],
-- 
GitLab