GUI2 add in support for Preferences Service

Change-Id: Icdf2165d9f638aeff1b110a64777b93295935ed2
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/gui2-fw-lib.module.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/gui2-fw-lib.module.ts
index 6004bce..f213ca1 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/gui2-fw-lib.module.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/gui2-fw-lib.module.ts
@@ -23,6 +23,7 @@
 import { MastComponent } from './mast/mast/mast.component';
 import { TableFilterPipe } from './widget/tablefilter.pipe';
 import { TableResizeDirective } from './widget/tableresize.directive';
+import { QuickhelpComponent } from './layer/quickhelp/quickhelp.component';
 
 @NgModule({
   imports: [
@@ -35,6 +36,7 @@
     VeilComponent,
     FlashComponent,
     ConfirmComponent,
+    QuickhelpComponent,
     MastComponent,
     TableFilterPipe
   ],
@@ -45,6 +47,7 @@
     VeilComponent,
     FlashComponent,
     ConfirmComponent,
+    QuickhelpComponent,
     MastComponent,
     TableFilterPipe
   ]
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.css b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.css
new file mode 100644
index 0000000..26c1643
--- /dev/null
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.css
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ ONOS GUI -- Quickhelp Panel -- CSS file
+ */
+
+/*
+ ONOS GUI -- Quick Help Service (layout) -- CSS file
+ */
+
+#quickhelp {
+    top: 100px;
+    z-index: 5000;
+    position: relative;
+}
+
+#quickhelp div.help {
+    background: black;
+    opacity: 0.8;
+}
+
+#quickhelp div.help table {
+    vertical-align: top;
+}
+
+#quickhelp div.help p {
+    text-align: center;
+    color: white;
+    font-weight: bold;
+}
+
+#quickhelp td.key {
+    color: #add;
+    padding-left: 8px;
+    padding-right: 4px;
+}
+
+#quickhelp td.desc {
+    color: white;
+}
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.html b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.html
new file mode 100644
index 0000000..d387284
--- /dev/null
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.html
@@ -0,0 +1,160 @@
+<!--
+~ Copyright 2019-present Open Networking Foundation
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~     http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
+<div id="quickhelp" [@quickHelpState]="ks.quickHelpShown">
+    <div class="help" *ngIf="ks.quickHelpShown">
+        <p class="title">{{lionFn("qh_title")}}</p>
+        <!-- TODO: drive this through the keys service keyHandler -->
+        <table class="qhrow">
+            <tr>
+                <td class="key">&#92;</td>
+                <td class="desc">Afficher/cacher l'aide rapide</td>
+            </tr>
+            <tr>
+                <td class="key">/</td>
+                <td class="desc">Afficher/cacher l'aide rapide</td>
+            </tr>
+            <tr>
+                <td class="key">Esc</td>
+                <td class="desc">ignorer la boîte de dialogue ou annuler les
+                    sélections
+                </td>
+            </tr>
+            <tr>
+                <td class="key">T</td>
+                <td class="desc">basculer de thème</td>
+            </tr>
+        </table>
+        <hr class="qhrowsep">
+        <table class="qhrow">
+            <tr>
+                <td class="key">I</td>
+                <td class="desc">Basculer au panneau de instance
+                    ONOS
+                </td>
+                <td class="key">O</td>
+                <td class="desc">Baculer au panneau récapitulatif
+                    ONOS
+                </td>
+                <td class="key">D</td>
+                <td class="desc">Basculer le panneau de détails</td>
+            </tr>
+            <tr>
+                <td class="key">H</td>
+                <td class="desc">Basculer la visibilité de l'hôte
+                </td>
+                <td class="key">M</td>
+                <td class="desc">Basculer la visibilité hors-ligne
+                </td>
+                <td class="key">P</td>
+                <td class="desc">Basculer le port mis en évidence
+                </td>
+            </tr>
+            <tr>
+                <td class="key">Dash</td>
+                <td class="desc">Montrer les mauvais liens</td>
+                <td class="key">B</td>
+                <td class="desc">Basculer la carte géo de fond</td>
+                <td class="key">G</td>
+                <td class="desc">Sélectionner la carte géo de fond
+                </td>
+            </tr>
+            <tr>
+                <td class="key">S</td>
+                <td class="desc">Toggle sprite layer</td>
+                <td class="key" y="0">X</td>
+                <td class="desc" y="0" x="33.53125">réinitialiser la
+                    carte des noeuds
+                </td>
+                <td class="key">Z</td>
+                <td class="desc">Basculer la vue oblique
+                    (expérimental)
+                </td>
+            </tr>
+            <tr>
+                <td class="key">N</td>
+                <td class="desc">cycle couche de noeuds</td>
+                <td class="key">L</td>
+                <td class="desc">Parcourir étiquettes appareils</td>
+                <td class="key">Shift-l</td>
+                <td class="desc">Parcourir étiquettes hôte</td>
+            </tr>
+            <tr>
+                <td class="key">U</td>
+                <td class="desc">survoler avec la souris</td>
+                <td class="key">R</td>
+                <td class="desc">réinitialiser le zoom et le
+                    panoramique
+                </td>
+                <td class="key">E</td>
+                <td class="desc">Egaliser les rôles de maîtrises
+                </td>
+            </tr>
+            <tr>
+                <td class="key">Dot</td>
+                <td class="desc">Basculer a la barre d'outils</td>
+                <td class="key">0</td>
+                <td class="desc">Annuler la surveillance du trafic
+                </td>
+                <td class="key">A</td>
+                <td class="desc">Surveiller tout le trafic</td>
+            </tr>
+            <tr>
+                <td class="key">F</td>
+                <td class="desc">Afficher les flux de liaison de périphérique
+                </td>
+                <td class="key">V</td>
+                <td class="desc">Show all related intents</td>
+                <td class="key">L-arrow</td>
+                <td class="desc">Show previous related intent</td>
+            </tr>
+            <tr>
+                <td class="key">R-arrow</td>
+                <td class="desc">Show next related intent</td>
+                <td class="key">W</td>
+                <td class="desc">Monitor traffic of selected intent</td>
+            </tr>
+        </table>
+        <hr>
+        <div class="qhrow">
+            <table class="qh-r4-c0">
+                <tr>
+                    <td class="key">cliquer</td>
+                    <td class="desc">Sélectionner l'article et montrer les
+                        détails
+                    </td>
+                </tr>
+                <tr>
+                    <td class="key">Cliquer sur MAJ</td>
+                    <td class="desc">Basculer l'état de sélection</td>
+                </tr>
+                <tr>
+                    <td class="key">Glisser</td>
+                    <td class="desc">Repositionner (et épingler) le périphérique
+                        / l'hôte
+                    </td>
+                </tr>
+                <tr>
+                    <td class="key">cmd défiler</td>
+                    <td class="desc">Zoom avant/arrière</td>
+                </tr>
+                <tr>
+                    <td class="key" y="48">cmd-glisser</td>
+                    <td class="desc" y="48" x="74.84375">Pan
+                </tr>
+            </table>
+        </div>
+    </div>
+</div>
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.spec.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.spec.ts
new file mode 100644
index 0000000..da60a1b
--- /dev/null
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.spec.ts
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { QuickhelpComponent } from './quickhelp.component';
+import {LogService} from '../../log.service';
+import {ConsoleLoggerService} from '../../consolelogger.service';
+import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
+import {FnService} from '../../util/fn.service';
+import {LionService} from '../../util/lion.service';
+import {KeysService} from '../../util/keys.service';
+
+class MockFnService {}
+
+class MockKeysService {
+
+}
+
+/**
+ * ONOS GUI -- Layer -- Quickhelp Component - Unit Tests
+ */
+describe('QuickhelpComponent', () => {
+    let log: LogService;
+    let component: QuickhelpComponent;
+    let fixture: ComponentFixture<QuickhelpComponent>;
+    const bundleObj = {
+        'core.fw.QuickHelp': {
+            test: 'test1',
+            tt_help: 'Help!'
+        }
+    };
+    const mockLion = (key) =>  {
+        return bundleObj[key] || '%' + key + '%';
+    };
+
+    beforeEach(async(() => {
+        log = new ConsoleLoggerService();
+        TestBed.configureTestingModule({
+            imports: [ BrowserAnimationsModule ],
+            declarations: [ QuickhelpComponent ],
+            providers: [
+                { provide: LogService, useValue: log },
+                { provide: FnService, useClass: MockFnService },
+                { provide: LionService, useFactory: (() => {
+                        return {
+                            bundle: ((bundleId) => mockLion),
+                            ubercache: new Array(),
+                            loadCbs: new Map<string, () => void>([])
+                        };
+                    })
+                },
+                { provide: KeysService, useClass: MockKeysService }
+            ]
+        })
+        .compileComponents();
+    }));
+
+    beforeEach(() => {
+        fixture = TestBed.createComponent(QuickhelpComponent);
+        component = fixture.componentInstance;
+        fixture.detectChanges();
+    });
+
+    it('should create', () => {
+        expect(component).toBeTruthy();
+    });
+});
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.ts
new file mode 100644
index 0000000..6789e14
--- /dev/null
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/layer/quickhelp/quickhelp.component.ts
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {Component} from '@angular/core';
+import {animate, state, style, transition, trigger} from '@angular/animations';
+import {LogService} from '../../log.service';
+import {FnService} from '../../util/fn.service';
+import {KeysService} from '../../util/keys.service';
+import {LionService} from '../../util/lion.service';
+
+
+@Component({
+    selector: 'onos-quickhelp',
+    templateUrl: './quickhelp.component.html',
+    styleUrls: ['./quickhelp.component.css'],
+    animations: [
+        trigger('quickHelpState', [
+            state('true', style({
+                opacity: '1.0',
+            })),
+            state('false', style({
+                opacity: '0.0',
+            })),
+            transition('0 => 1', animate('500ms ease-in')),
+            transition('1 => 0', animate('500ms ease-out'))
+        ])
+    ]
+})
+export class QuickhelpComponent {
+    lionFn; // Function
+
+    constructor(
+        private log: LogService,
+        private fs: FnService,
+        public ks: KeysService,
+        private lion: LionService
+    ) {
+        if (this.lion.ubercache.length === 0) {
+            this.lionFn = this.dummyLion;
+            this.lion.loadCbs.set('quickhelp', () => this.doLion());
+        } else {
+            this.doLion();
+        }
+
+        this.log.debug('Quickhelp component constructed');
+    }
+
+    /**
+     * Read the LION bundle for Toolbar and set up the lionFn
+     */
+    doLion() {
+        this.lionFn = this.lion.bundle('core.fw.QuickHelp');
+    }
+
+    /**
+    * A dummy implementation of the lionFn until the response is received and the LION
+    * bundle is received from the WebSocket
+    */
+    dummyLion(key: string): string {
+        return '%' + key + '%';
+    }
+}
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/nav/nav.service.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/nav/nav.service.ts
index 337b104..98de228 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/nav/nav.service.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/nav/nav.service.ts
@@ -48,10 +48,8 @@
     }
 
     hideNav() {
-        this.showNav = !this.showNav;
-        if (!this.showNav) {
-            this.log.debug('Hiding Nav menu');
-        }
+        this.showNav = false;
+        this.log.debug('Hiding Nav menu');
     }
 
     toggleNav() {
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/urlfn.service.spec.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/urlfn.service.spec.ts
index 2c31610..37a0cbd 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/urlfn.service.spec.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/urlfn.service.spec.ts
@@ -71,7 +71,7 @@
         windowMock.location.port = p;
         windowMock.location.protocol = prot;
         windowMock.location.href = prot + '://' + h + ':' + p +
-            ctx + '/onos/ui/';
+            ctx + '/onos/ui2/';
     }
 
     it('should define UrlFnService', () => {
@@ -87,37 +87,37 @@
 
     it('should return the correct (http) RS url', () => {
         setLoc('http', 'foo', '123');
-        expect(ufs.rsUrl('path')).toEqual('http://foo:123/onos/ui/rs/path');
+        expect(ufs.rsUrl('path')).toEqual('http://foo:123/onos/ui2/rs/path');
     });
 
     it('should return the correct (https) RS url', () => {
         setLoc('https', 'foo', '123');
-        expect(ufs.rsUrl('path')).toEqual('https://foo:123/onos/ui/rs/path');
+        expect(ufs.rsUrl('path')).toEqual('https://foo:123/onos/ui2/rs/path');
     });
 
     it('should return the correct (ws) WS url', () => {
         setLoc('http', 'foo', '123');
-        expect(ufs.wsUrl('path')).toEqual('ws://foo:123/onos/ui/websock/path');
+        expect(ufs.wsUrl('path')).toEqual('ws://foo:123/onos/ui2/websock/path');
     });
 
     it('should return the correct (wss) WS url', () => {
         setLoc('https', 'foo', '123');
-        expect(ufs.wsUrl('path')).toEqual('wss://foo:123/onos/ui/websock/path');
+        expect(ufs.wsUrl('path')).toEqual('wss://foo:123/onos/ui2/websock/path');
     });
 
     it('should allow us to define an alternate WS port', () => {
         setLoc('http', 'foo', '123');
-        expect(ufs.wsUrl('xyyzy', '456')).toEqual('ws://foo:456/onos/ui/websock/xyyzy');
+        expect(ufs.wsUrl('xyyzy', '456')).toEqual('ws://foo:456/onos/ui2/websock/xyyzy');
     });
 
     it('should allow us to define an alternate host', () => {
         setLoc('http', 'foo', '123');
-        expect(ufs.wsUrl('core', '456', 'bar')).toEqual('ws://bar:456/onos/ui/websock/core');
+        expect(ufs.wsUrl('core', '456', 'bar')).toEqual('ws://bar:456/onos/ui2/websock/core');
     });
 
     it('should allow us to inject an app context', () => {
         setLoc('http', 'foo', '123', '/my/app');
-        expect(ufs.wsUrl('path')).toEqual('ws://foo:123/my/app/onos/ui/websock/path');
+        expect(ufs.wsUrl('path')).toEqual('ws://foo:123/my/app/onos/ui2/websock/path');
     });
 
 });
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/urlfn.service.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/urlfn.service.ts
index a7576c0..12ca11c 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/urlfn.service.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/urlfn.service.ts
@@ -16,7 +16,7 @@
 import { Injectable, Inject } from '@angular/core';
 import { LogService } from '../log.service';
 
-const UICONTEXT = '/onos/ui/';
+const UICONTEXT = '/onos/ui2/';
 const RSSUFFIX = UICONTEXT + 'rs/';
 const WSSUFFIX = UICONTEXT + 'websock/';
 
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/websocket.service.spec.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/websocket.service.spec.ts
index 7695e13..6c6ade8 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/websocket.service.spec.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/websocket.service.spec.ts
@@ -64,8 +64,8 @@
                 port: '80',
                 protocol: 'http',
                 search: { debug: 'true'},
-                href: 'ws://foo:123/onos/ui/websock/path',
-                absUrl: 'ws://foo:123/onos/ui/websock/path'
+                href: 'ws://foo:123/onos/ui2/websock/path',
+                absUrl: 'ws://foo:123/onos/ui2/websock/path'
             }
         };
         fs = new FnService(ar, logSpy, windowMock);
@@ -108,13 +108,13 @@
 
     it('should use the appropriate URL, createWebsocket', () => {
         const url = wss.createWebSocket();
-        expect(url).toEqual('ws://foo:80/onos/ui/websock/core');
+        expect(url).toEqual('ws://foo:80/onos/ui2/websock/core');
     });
 
     it('should use the appropriate URL with modified port, createWebsocket',
         () => {
             const url = wss.createWebSocket(<WsOptions>{ wsport: 1243 });
-            expect(url).toEqual('ws://foo:1243/onos/ui/websock/core');
+            expect(url).toEqual('ws://foo:1243/onos/ui2/websock/core');
     });
 
     it('should verify websocket event handlers, createWebsocket', () => {
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/websocket.service.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/websocket.service.ts
index c4d5227..2a254b4 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/websocket.service.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/remote/websocket.service.ts
@@ -91,6 +91,7 @@
      */
     private bootstrap(data: Bootstrap) {
         this.loggedInUser = data.user;
+        this.log.info('Websocket connection bootstraped', data);
 
         this.clusterNodes = data.clusterNodes;
         this.clusterNodes.forEach((d, i) => {
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/keys.service.spec.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/keys.service.spec.ts
index 5f4b349..47299e7 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/keys.service.spec.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/keys.service.spec.ts
@@ -89,7 +89,6 @@
         });
         ks = TestBed.get(KeysService);
         ks.installOn(d3Elem);
-        ks.bindQhs(qhs);
         logServiceSpy = TestBed.get(LogService);
     });
 
@@ -103,7 +102,7 @@
 
     it('should define api functions', () => {
         expect(fs.areFunctions(ks, [
-            'bindQhs', 'installOn', 'keyBindings', 'unbindKeys', 'dialogKeys',
+            'installOn', 'keyBindings', 'unbindKeys', 'dialogKeys',
             'addSeq', 'remSeq', 'gestureNotes', 'enableKeys', 'enableGlobalKeys',
             'checkNotGlobal', 'getKeyBindings',
             'matchSeq', 'whatKey', 'textFieldInput', 'keyIn', 'qhlion', 'qhlionShowHide',
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/keys.service.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/keys.service.ts
index decb87b..035037e 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/keys.service.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/keys.service.ts
@@ -59,7 +59,7 @@
         enter: 1,
         esc: 1,
     };
-    qhs: any; // Quick Help Service ??
+    quickHelpShown: boolean = false;
 
     constructor(
         protected log: LogService,
@@ -70,10 +70,6 @@
         this.log.debug('KeyService constructed');
     }
 
-    bindQhs(_qhs_) {
-        this.qhs = _qhs_;
-    }
-
     installOn(elem) {
         this.log.debug('Installing keys handler');
         elem.on('keydown', () => { this.keyIn(); });
@@ -314,14 +310,14 @@
         if (!this.globalEnabled) {
             return false;
         }
-        this.qhs.showQuickHelp(this.keyHandler);
+        this.quickHelpShown = !this.quickHelpShown;
         return true;
     }
 
     // returns true if we 'consumed' the ESC keypress, false otherwise
     protected escapeKey(view, key, code, ev) {
+        this.quickHelpShown = false;
         return this.ns.hideNav();
-        // TODO - also hide this.qhs.hideQuickHelp();
     }
 
     protected toggleTheme(view, key, code, ev) {
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/prefs.service.spec.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/prefs.service.spec.ts
index d925ecf..13892af 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/prefs.service.spec.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/prefs.service.spec.ts
@@ -35,6 +35,19 @@
  */
 describe('PrefsService', () => {
     let log: LogService;
+    let windowMock: Window;
+
+    windowMock = <any>{
+        location: <any> {
+            hostname: 'foo',
+            host: 'foo',
+            port: '80',
+            protocol: 'http',
+            search: { debug: 'true'},
+            href: 'ws://foo:123/onos/ui/websock/path',
+            absUrl: 'ws://foo:123/onos/ui/websock/path'
+        }
+    };
 
     beforeEach(() => {
         log = new ConsoleLoggerService();
@@ -43,6 +56,7 @@
             providers: [PrefsService,
                 { provide: LogService, useValue: log },
                 { provide: FnService, useClass: MockFnService },
+                { provide: 'Window', useFactory: (() => windowMock ) },
                 { provide: WebSocketService, useClass: MockWebSocketService },
             ]
         });
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/prefs.service.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/prefs.service.ts
index 8145921..b68b4dd 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/prefs.service.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/util/prefs.service.ts
@@ -13,11 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Injectable } from '@angular/core';
+import {Inject, Injectable} from '@angular/core';
 import { FnService } from './fn.service';
 import { LogService } from '../log.service';
 import { WebSocketService } from '../remote/websocket.service';
 
+const UPDATE_PREFS: string = 'updatePrefs';
+const UPDATE_PREFS_REQ: string = 'updatePrefReq';
 /**
  * ONOS GUI -- Util -- User Preference Service
  */
@@ -25,32 +27,36 @@
     providedIn: 'root',
 })
 export class PrefsService {
-    protected Prefs;
     protected handlers: string[] = [];
-    cache: any;
-    listeners: any;
+    cache: Object;
+    listeners: ((data) => void)[] = [];
     constructor(
         protected fs: FnService,
         protected log: LogService,
-        protected wss: WebSocketService
+        protected wss: WebSocketService,
+        @Inject('Window') private window: any
     ) {
-        this.cache = {};
         this.wss.bindHandlers(new Map<string, (data) => void>([
-            [this.Prefs, (data) => this.updatePrefs(data)]
+            [UPDATE_PREFS, (data) => this.updatePrefs(data)]
         ]));
-        this.handlers.push(this.Prefs);
+        this.handlers.push(UPDATE_PREFS);
+
+        // When index.html is fetched it is served up by MainIndexResource.java
+        // which fetches userPrefs in to the global scope.
+        // After that updates are done through WebSocket
+        this.cache = Object.assign({}, this.window['userPrefs']);
 
         this.log.debug('PrefsService constructed');
     }
 
-    setPrefs(name: string, obj: any) {
+    setPrefs(name: string, obj: Object) {
         // keep a cached copy of the object and send an update to server
         this.cache[name] = obj;
-        this.wss.sendEvent('updatePrefReq', { key: name, value: obj });
+        this.wss.sendEvent(UPDATE_PREFS_REQ, { key: name, value: obj });
     }
     updatePrefs(data: any) {
         this.cache = data;
-        this.listeners.forEach(function (lsnr) { lsnr(); });
+        this.listeners.forEach((lsnr) => lsnr(data) );
     }
 
     asNumbers(obj: any, keys?: any, not?: any) {
@@ -101,17 +107,22 @@
     //  defined keys should overwrite the corresponding values, but any
     //  existing keys that are NOT explicitly defined here should be left
     //  alone (not deleted).
-    mergePrefs(name: string, obj: any) {
+    mergePrefs(name: string, obj: any): void {
         const merged = this.cache[name] || {};
         this.setPrefs(name, Object.assign(merged, obj));
     }
 
-    addListener(listener: any) {
+    /**
+     * Add a listener function
+     * This will get called back when an 'updatePrefs' message is received on WSS
+     * @param listener a function that can accept one param - data
+     */
+    addListener(listener: (data) => void): void {
         this.listeners.push(listener);
     }
 
-    removeListener(listener: any) {
-        this.listeners = this.listeners.filter(function (obj) { return obj === listener; });
+    removeListener(listener: (data) => void) {
+        this.listeners = this.listeners.filter((obj) => obj !== listener);
     }
 
 }
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/public_api.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/public_api.ts
index 5f162d5..3c6d141 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/public_api.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/public_api.ts
@@ -49,6 +49,7 @@
 export * from './lib/layer/veil/veil.component';
 export * from './lib/layer/flash/flash.component';
 export * from './lib/layer/confirm/confirm.component';
+export * from './lib/layer/quickhelp/quickhelp.component';
 export * from './lib/svg/icon/icon.component';
 
 export * from './lib/widget/tableresize.directive';