[CORD-2424] Adding Instances and Networks to the graph

Change-Id: Ib30081f4995930d979447af59124896f1308f54d
diff --git a/src/app/core/services/helpers/config.helpers.spec.ts b/src/app/core/services/helpers/config.helpers.spec.ts
index f36c20a..db1c840 100644
--- a/src/app/core/services/helpers/config.helpers.spec.ts
+++ b/src/app/core/services/helpers/config.helpers.spec.ts
@@ -187,7 +187,7 @@
       });
 
       it('should return the state with params for usage in js', () => {
-        expect(service.stateWithParamsForJs('Test', {id: 1})).toEqual({ name: 'xos.core.tests', params: Object({ id: 1 }) });
+        expect(service.stateWithParamsForJs('Test', 1)).toEqual({ name: 'xos.core.tests', params: Object({ id: 1 }) });
       });
     });
   });
diff --git a/src/app/core/services/helpers/config.helpers.ts b/src/app/core/services/helpers/config.helpers.ts
index 91db9f2..4baf9c5 100644
--- a/src/app/core/services/helpers/config.helpers.ts
+++ b/src/app/core/services/helpers/config.helpers.ts
@@ -196,7 +196,7 @@
       };
 
       if (f.name === 'id' || f.name === 'name') {
-        col.link = item => this.stateWithParamsForJs(modelName, item);
+        col.link = item => this.stateWithParamsForJs(modelName, item.id);
       }
 
       // if the field identify a relation, create a link
@@ -206,7 +206,7 @@
           this.populateRelated(item, item[f.name], f);
           return item[f.name];
         };
-        col.link = item => this.relatedStateWithParams(f.relation.model, item[col.prop]);
+        col.link = item => this.stateWithParamsForJs(f.relation.model, item[col.prop]);
       }
 
       if (f.name === 'backend_status' || f.name === 'policy_status') {
@@ -257,9 +257,9 @@
     return `${state}({id: ${id}})`;
   }
 
-  public stateWithParamsForJs(name: string, model: any): any {
+  public stateWithParamsForJs(name: string, id: number): any {
     const state = this.stateFromCoreModel(name);
-    return {name: state, params: {id: model.id}};
+    return {name: state, params: {id: id}};
   }
 
   public modelFieldToInputCfg(fields: IXosModelDefsField[]): IXosFormInput[] {
diff --git a/src/app/core/services/keyboard-shortcut.spec.ts b/src/app/core/services/keyboard-shortcut.spec.ts
index fa9bf41..d113161 100644
--- a/src/app/core/services/keyboard-shortcut.spec.ts
+++ b/src/app/core/services/keyboard-shortcut.spec.ts
@@ -195,4 +195,65 @@
       expect(logSpy).toHaveBeenCalledWith('[XosKeyboardShortcut] A shortcut for key "a" has already been registered');
     });
   });
+
+  describe('the removeKeyBinding method', () => {
+
+    const globalBinding = {
+      key: 'g',
+      cb: 'callback',
+      modifiers: null
+    };
+
+    const viewBinding = {
+      key: 'v',
+      cb: 'callback',
+      modifiers: null
+    };
+
+    const missingBinding = {
+      key: 'b',
+      cb: 'callback',
+      modifiers: null
+    };
+
+    beforeEach(() => {
+      service['keyMapping'] = {
+        global: [
+          {
+            key: 'g',
+            cb: 'cb',
+            modifiers: null
+          }
+        ],
+        view: [
+          {
+            key: 'v',
+            cb: 'cb',
+            modifiers: null
+          }
+        ]
+      };
+    });
+
+    it(' should remove an existing global keybinding', () => {
+      service.removeKeyBinding(globalBinding);
+      expect(logSpy).not.toHaveBeenCalled();
+      expect(service['keyMapping']['global'].length).toBe(0);
+      expect(service['keyMapping']['view'].length).toBe(1);
+    });
+
+    it(' should remove an existing view keybinding', () => {
+      service.removeKeyBinding(viewBinding);
+      expect(logSpy).not.toHaveBeenCalled();
+      expect(service['keyMapping']['global'].length).toBe(1);
+      expect(service['keyMapping']['view'].length).toBe(0);
+    });
+
+    it('should not raise if removing a missing keybing', () => {
+      service.removeKeyBinding(missingBinding);
+      expect(service['keyMapping']['global'].length).toBe(1);
+      expect(service['keyMapping']['view'].length).toBe(1);
+      expect(logSpy).toHaveBeenCalledWith('[XosKeyboardShortcut] Trying to remove a shortcut for key "b" but it was not registered');
+    });
+  });
 });
diff --git a/src/app/core/services/keyboard-shortcut.ts b/src/app/core/services/keyboard-shortcut.ts
index 9b98b45..e2a3a38 100644
--- a/src/app/core/services/keyboard-shortcut.ts
+++ b/src/app/core/services/keyboard-shortcut.ts
@@ -23,6 +23,7 @@
 export interface IXosKeyboardShortcutService {
   keyMapping: IXosKeyboardShortcutMap;
   registerKeyBinding(binding: IXosKeyboardShortcutBinding, target?: string);
+  removeKeyBinding(binding: IXosKeyboardShortcutBinding);
   setup(): void;
 }
 
@@ -64,11 +65,17 @@
   public baseBindings: IXosKeyboardShortcutBinding[] = [
     {
       key: 'slash',
-      label: '/',
+      label: '/ or ?',
       description: 'Toggle Shortcut Panel',
       cb: this.toggleKeyBindingPanel,
     },
     {
+      // NOTE this is the ? code
+      key: 'slash',
+      modifiers: ['shift'],
+      cb: this.toggleKeyBindingPanel,
+    },
+    {
       key: 'esc',
       label: 'Esc',
       cb: (event) => {
@@ -102,6 +109,7 @@
     $('body').on('keydown', (e) => {
 
       const pressedKey = this.whatKey(e.which);
+      this.$log.debug(`[XosKeyboardShortcut] Pressed key: ${pressedKey}`);
       if (!pressedKey) {
         return;
       }
@@ -149,6 +157,18 @@
     this.keyMapping[target].push(binding);
   }
 
+  public removeKeyBinding(binding: IXosKeyboardShortcutBinding): void {
+    if (_.find(this.keyMapping.global, {key: binding.key, modifiers: binding.modifiers})) {
+      _.remove(this.keyMapping.global, {key: binding.key, modifiers: binding.modifiers});
+    }
+    else if (_.find(this.keyMapping.view, {key: binding.key, modifiers: binding.modifiers})) {
+      _.remove(this.keyMapping.view, {key: binding.key, modifiers: binding.modifiers});
+    }
+    else {
+      this.$log.warn(`[XosKeyboardShortcut] Trying to remove a shortcut for key "${binding.key}" but it was not registered`);
+    }
+  }
+
   private addActiveModifierKey(key: string) {
     if (this.activeModifiers.indexOf(key) === -1) {
       this.activeModifiers.push(key);