Enabled --prod mode for GUI2 - refactored modules

Change-Id: I224fe9564cb225b9ebaed0a43281de54ec6eb274
diff --git a/web/gui2/BUCK b/web/gui2/BUCK
index 4039147..94c492e 100644
--- a/web/gui2/BUCK
+++ b/web/gui2/BUCK
@@ -62,7 +62,8 @@
         + 'npm5 install -g @angular/cli@6.0.0 2>&1;'
         + 'npm5 install 2>&1;'
         + 'ng -v;'
-        + 'ng build --extract-css --preserve-symlinks --base-href /onos/ui2/dist/ --deploy-url /onos/ui2/dist/ --output-path="$OUT" 2>&1',
+# Build it in production mode - optimization is turned off because of Angular CLI 6.0.x bug https://github.com/angular/angular-cli/issues/7799
+        + 'ng build --extract-css --prod --optimization=false --preserve-symlinks --base-href /onos/ui2/dist/ --deploy-url /onos/ui2/dist/ --output-path="$OUT" 2>&1',
     out = 'dist',
     visibility = [ 'PUBLIC' ],
 )
diff --git a/web/gui2/README.md b/web/gui2/README.md
index 10b3459..80976ea 100644
--- a/web/gui2/README.md
+++ b/web/gui2/README.md
@@ -1,6 +1,8 @@
 # ONOS GUI 2.0.0
 
-This project is based on __[Angular 6](https://angular.io/docs)__, as an alternative to the 1.0.0 GUI which was based 
+This project is based on __[Angular 6](https://angular.io/docs)__ 
+and __[ES6](http://www.ecma-international.org/ecma-262/6.0/index.html)__ (aka __ES2015__), 
+as an alternative to the 1.0.0 GUI which was based 
 off __[AngularJS 1.3.5](https://angularjs.org/)__
 
 Building, testing and running lint are all handled by BUCK. See web/gui2/BUCK file.
@@ -13,10 +15,13 @@
 
 # Development
 There are 2 ways to go about development - 
-1. rebuild the code and rerun through BUCK OR (much like can be done with any ordinary ONOS app)
-2. use Angular 6 CLI (ng command) to rebuild on the fly (must faster for development) 
+1. rebuild the code and rerun through BUCK (much like can be done with any ordinary ONOS app) 
+ (this is not recommended though since in this mode the browser side code is built in '--prod' mode
+ and all debug symbols are stripped and debug statements are not logged and the code is uglified and minimized.
+ It is useful for testing "prod" mode works though) OR
+2. use Angular 6 CLI (__ng__ command) to rebuild on the fly (must faster for development) 
 
-For 1) if you change the code you can redeploy the application with (requies you to be in ~/onos directory):
+For 1) if you change the code you can redeploy the application without restarting ONOS with (requires you to be in ~/onos directory):
 ```
 onos-buck build //web/gui2:onos-web-gui2-oar --show-output|grep /app.oar | cut -d\  -f2 | xargs onos-app localhost reinstall!
 ```
@@ -24,7 +29,7 @@
 For 2) it's well worth becoming familiar with Angular CLI.
 The project is created with [Angular CLI](https://github.com/angular/angular-cli) v6 to simplify development of the browser side code.
 
-This allows you to develop the Angular 6 Type Script code independent of ONOS in a separate container. 
+This allows you to develop the Angular 6 TypeScript code independent of ONOS in a separate container. 
 Since WebSockets have been implemented (Jun 18) there is a requirement to run ONOS in the background.
 
 There is no need to install node, npm or ng again on your system, and indeed if they are already installed, it's best
@@ -52,9 +57,12 @@
 
 ## Development server
 
-Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
+Run `ng serve --aot` for a dev server (because we are using ES6, we [must use AOT](https://github.com/angular/angular-cli/wiki/build)). 
+Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
 
-Press Ctrl-Shift-I in Chrome and Firefox to bring up the developer tools and the browser console. 
+Press Ctrl-Shift-I in Chrome and Firefox to bring up the developer tools and the browser console.
+
+There are certain extra debugging can be turned on by adding the parameter 'debug' For example to turn extra logging for WebSockets add on __?debug=txrx__ 
 
 ## Code scaffolding
 
@@ -62,13 +70,13 @@
 
 ## Build
 The build is handled through the web/gui2/BUCK file. This downloads Node, NPM and Angular CLI
-It runs ```ng build``` and copies everything over in to WEB-INF/classes/dist (there
+It runs ```ng build --prod --extract-css``` and copies everything over in to WEB-INF/classes/dist (there
 is something weird in BUCK resources - if there is a file in the root dir of the
 outputted folder this is copied to the sources root directory, where as files
 are copied to WEB-INF/classes. To get around this I put all the outputted stuff in to 
 ```dist``` and it gets copied to /WEB-INF/classes/dist/ )
 
-To run it manually in Angular CLI run `ng build`
+To run it manually in Angular CLI run `ng build` (and add on --prod --extract-css --watch as necessary to alter its behaviour)
 
 ## Running unit tests
 This is automatically done when using "onos-buck test" - see the web/gui2/BUCK file for more details.
diff --git a/web/gui2/src/main/webapp/app/consolelogger.service.ts b/web/gui2/src/main/webapp/app/consolelogger.service.ts
index 84c9d03..a682fb3 100644
--- a/web/gui2/src/main/webapp/app/consolelogger.service.ts
+++ b/web/gui2/src/main/webapp/app/consolelogger.service.ts
@@ -19,19 +19,22 @@
 
 export let isDebugMode: boolean = !environment.production;
 
+const noop = (): any => undefined;
+
 /**
  * ONOS GUI -- LogService
  * Inspired by https://robferguson.org/blog/2017/09/09/a-simple-logging-service-for-angular-4/
  */
-@Injectable()
+@Injectable({
+  providedIn: 'root',
+})
 export class ConsoleLoggerService implements Logger {
-  private noop: () => void;
 
   get debug() {
     if (isDebugMode) {
       return console.debug.bind(console);
     } else {
-      return this.noop;
+      return noop;
     }
   }
 
@@ -39,7 +42,7 @@
     if (isDebugMode) {
       return console.info.bind(console);
     } else {
-      return this.noop;
+      return noop;
     }
   }
 
@@ -52,7 +55,7 @@
   }
 
   invokeConsoleMethod(type: string, args?: any): void {
-    const logFn: Function = (console)[type] || console.log || this.noop;
+    const logFn: Function = (console)[type] || console.log || noop;
     logFn.apply(console, [args]);
   }
 }
diff --git a/web/gui2/src/main/webapp/app/detectbrowser.directive.ts b/web/gui2/src/main/webapp/app/detectbrowser.directive.ts
index b8a3c77..a65dec7 100644
--- a/web/gui2/src/main/webapp/app/detectbrowser.directive.ts
+++ b/web/gui2/src/main/webapp/app/detectbrowser.directive.ts
@@ -30,7 +30,7 @@
     private fs: FnService,
     private log: LogService,
     private onos: OnosService,
-    @Inject(Window) private w: Window
+    @Inject('Window') private w: Window
   ) {
         const body: HTMLBodyElement = document.getElementsByTagName('body')[0];
 //        let body = d3.select('body');
diff --git a/web/gui2/src/main/webapp/app/fw/layer/layer.module.ts b/web/gui2/src/main/webapp/app/fw/layer/layer.module.ts
index 6292a8d..b4e39b2 100644
--- a/web/gui2/src/main/webapp/app/fw/layer/layer.module.ts
+++ b/web/gui2/src/main/webapp/app/fw/layer/layer.module.ts
@@ -15,7 +15,6 @@
  */
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
-import { UtilModule } from '../util/util.module';
 
 import { FlashComponent } from './flash/flash.component';
 import { DetailsPanelService } from './detailspanel.service';
@@ -35,8 +34,7 @@
     VeilComponent
   ],
   imports: [
-    CommonModule,
-    UtilModule
+    CommonModule
   ],
   declarations: [
     FlashComponent,
diff --git a/web/gui2/src/main/webapp/app/fw/mast/mast/mast.component.html b/web/gui2/src/main/webapp/app/fw/mast/mast/mast.component.html
index 94d8ce0..e7d0995 100644
--- a/web/gui2/src/main/webapp/app/fw/mast/mast/mast.component.html
+++ b/web/gui2/src/main/webapp/app/fw/mast/mast/mast.component.html
@@ -1,3 +1,18 @@
+<!--
+~ Copyright 2014-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="mast" align="left">
     <span class="nav-menu-button clickable" (click)="ns.toggleNav()">
         <img src="data/img/nav-menu-mojo.png"/>
diff --git a/web/gui2/src/main/webapp/app/fw/nav/nav.module.ts b/web/gui2/src/main/webapp/app/fw/nav/nav.module.ts
index 95a3c31..d25237f 100644
--- a/web/gui2/src/main/webapp/app/fw/nav/nav.module.ts
+++ b/web/gui2/src/main/webapp/app/fw/nav/nav.module.ts
@@ -17,6 +17,7 @@
 import { CommonModule } from '@angular/common';
 import { RouterModule, Routes } from '@angular/router';
 import { SvgModule } from '../svg/svg.module';
+import { OnosRoutingModule } from '../../onos-routing.module';
 
 import { NavComponent } from './nav/nav.component';
 import { NavService } from './nav.service';
@@ -30,6 +31,7 @@
 @NgModule({
   imports: [
     CommonModule,
+    OnosRoutingModule,
     RouterModule,
     SvgModule
   ],
diff --git a/web/gui2/src/main/webapp/app/fw/nav/nav/nav.component.html b/web/gui2/src/main/webapp/app/fw/nav/nav/nav.component.html
index a612214..f61a9ab 100644
--- a/web/gui2/src/main/webapp/app/fw/nav/nav/nav.component.html
+++ b/web/gui2/src/main/webapp/app/fw/nav/nav/nav.component.html
@@ -1,3 +1,18 @@
+<!--
+~ Copyright 2014-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.
+-->
 <nav id="nav" [@navState]="ns.showNav?'active':'inactive'">
     <div class="nav-hdr">Platform</div>
     <a (click)="ns.hideNav()" routerLink="/apps" routerLinkActive="active">
diff --git a/web/gui2/src/main/webapp/app/fw/remote/remote.module.ts b/web/gui2/src/main/webapp/app/fw/remote/remote.module.ts
deleted file mode 100644
index 179988d..0000000
--- a/web/gui2/src/main/webapp/app/fw/remote/remote.module.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2015-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 { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { SvgModule } from '../svg/svg.module';
-import { UtilModule } from '../util/util.module';
-
-import { UrlFnService } from './urlfn.service';
-import { WebSocketService } from './websocket.service';
-import { WSock } from './wsock.service';
-import { RestService } from './rest.service';
-
-/**
- * ONOS GUI -- Remote Communications Module
- */
-@NgModule({
-  imports: [
-    CommonModule,
-    SvgModule,
-    UtilModule
-  ],
-  providers: [
-    RestService,
-    UrlFnService,
-    WebSocketService,
-    WSock
-  ]
-})
-export class RemoteModule { }
diff --git a/web/gui2/src/main/webapp/app/fw/remote/rest.service.ts b/web/gui2/src/main/webapp/app/fw/remote/rest.service.ts
index 2d6bfa2..6fec638 100644
--- a/web/gui2/src/main/webapp/app/fw/remote/rest.service.ts
+++ b/web/gui2/src/main/webapp/app/fw/remote/rest.service.ts
@@ -21,7 +21,9 @@
 /**
  * ONOS GUI -- Remote Communications Module -- REST Service
  */
-@Injectable()
+@Injectable({
+  providedIn: 'root',
+})
 export class RestService {
 
   constructor(
diff --git a/web/gui2/src/main/webapp/app/fw/remote/urlfn.service.ts b/web/gui2/src/main/webapp/app/fw/remote/urlfn.service.ts
index 381a0c9..363663a 100644
--- a/web/gui2/src/main/webapp/app/fw/remote/urlfn.service.ts
+++ b/web/gui2/src/main/webapp/app/fw/remote/urlfn.service.ts
@@ -29,7 +29,7 @@
 export class UrlFnService {
     constructor(
         private log: LogService,
-        @Inject(Window) private w: Window
+        @Inject('Window') private w: Window
     ) {
         this.log.debug('UrlFnService constructed');
     }
diff --git a/web/gui2/src/main/webapp/app/fw/remote/websocket.service.ts b/web/gui2/src/main/webapp/app/fw/remote/websocket.service.ts
index 34a8ea9..18dd734 100644
--- a/web/gui2/src/main/webapp/app/fw/remote/websocket.service.ts
+++ b/web/gui2/src/main/webapp/app/fw/remote/websocket.service.ts
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Injectable } from '@angular/core';
+import { Injectable, Inject } from '@angular/core';
 import { FnService } from '../util/fn.service';
 import { GlyphService } from '../svg/glyph.service';
 import { LogService } from '../../log.service';
@@ -129,7 +129,7 @@
         private log: LogService,
         private ufs: UrlFnService,
         private wsock: WSock,
-        private window: Window
+        @Inject('Window') private window: Window
     ) {
         this.log.debug(window.location.hostname);
 
diff --git a/web/gui2/src/main/webapp/app/fw/svg/svg.module.ts b/web/gui2/src/main/webapp/app/fw/svg/svg.module.ts
index 3174263..bf2d1d9 100644
--- a/web/gui2/src/main/webapp/app/fw/svg/svg.module.ts
+++ b/web/gui2/src/main/webapp/app/fw/svg/svg.module.ts
@@ -15,7 +15,6 @@
  */
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
-import { UtilModule } from '../util/util.module';
 
 import { GeoDataService } from './geodata.service';
 import { GlyphService } from './glyph.service';
@@ -35,8 +34,7 @@
     IconComponent
   ],
   imports: [
-    CommonModule,
-    UtilModule
+    CommonModule
   ],
   declarations: [
     IconComponent
diff --git a/web/gui2/src/main/webapp/app/fw/util/ee.service.ts b/web/gui2/src/main/webapp/app/fw/util/ee.service.ts
index c16e4d1..8e1d87c 100644
--- a/web/gui2/src/main/webapp/app/fw/util/ee.service.ts
+++ b/web/gui2/src/main/webapp/app/fw/util/ee.service.ts
@@ -19,7 +19,9 @@
 /**
  * ONOS GUI -- Util -- EE functions
  */
-@Injectable()
+@Injectable({
+  providedIn: 'root',
+})
 export class EeService {
 
   constructor(
diff --git a/web/gui2/src/main/webapp/app/fw/util/fn.service.ts b/web/gui2/src/main/webapp/app/fw/util/fn.service.ts
index 7b9ea24..d0307e3 100644
--- a/web/gui2/src/main/webapp/app/fw/util/fn.service.ts
+++ b/web/gui2/src/main/webapp/app/fw/util/fn.service.ts
@@ -149,7 +149,9 @@
 /**
  * ONOS GUI -- Util -- General Purpose Functions
  */
-@Injectable()
+@Injectable({
+  providedIn: 'root',
+})
 export class FnService {
     // internal state
     private debugFlags = new Map<string, boolean>([
@@ -159,14 +161,14 @@
     constructor(
         private route: ActivatedRoute,
         private log: LogService,
-        @Inject(Window) private w: Window
+        @Inject('Window') private w: Window
     ) {
         this.route.queryParams.subscribe(params => {
             const debugparam: string = params['debug'];
             log.debug('Param:', debugparam);
             this.parseDebugFlags(debugparam);
         });
-        log.debug('FnService constructed');
+        this.log.debug('FnService constructed');
     }
 
     /**
diff --git a/web/gui2/src/main/webapp/app/fw/util/key.service.ts b/web/gui2/src/main/webapp/app/fw/util/key.service.ts
index b10b643..1eaa895 100644
--- a/web/gui2/src/main/webapp/app/fw/util/key.service.ts
+++ b/web/gui2/src/main/webapp/app/fw/util/key.service.ts
@@ -20,7 +20,9 @@
 /**
  * ONOS GUI -- Util -- Key Handler Service
  */
-@Injectable()
+@Injectable({
+  providedIn: 'root',
+})
 export class KeyService {
 
     constructor(
diff --git a/web/gui2/src/main/webapp/app/fw/util/prefs.service.ts b/web/gui2/src/main/webapp/app/fw/util/prefs.service.ts
index 3cef9b6..f696125 100644
--- a/web/gui2/src/main/webapp/app/fw/util/prefs.service.ts
+++ b/web/gui2/src/main/webapp/app/fw/util/prefs.service.ts
@@ -21,7 +21,9 @@
 /**
  * ONOS GUI -- Util -- User Preference Service
  */
-@Injectable()
+@Injectable({
+  providedIn: 'root',
+})
 export class PrefsService {
 
     constructor(
diff --git a/web/gui2/src/main/webapp/app/fw/util/random.service.ts b/web/gui2/src/main/webapp/app/fw/util/random.service.ts
index 5ec71b5..d808e48 100644
--- a/web/gui2/src/main/webapp/app/fw/util/random.service.ts
+++ b/web/gui2/src/main/webapp/app/fw/util/random.service.ts
@@ -20,7 +20,9 @@
 /**
  * ONOS GUI -- Random -- Encapsulated randomness
  */
-@Injectable()
+@Injectable({
+  providedIn: 'root',
+})
 export class RandomService {
 
     constructor(
diff --git a/web/gui2/src/main/webapp/app/fw/util/theme.service.ts b/web/gui2/src/main/webapp/app/fw/util/theme.service.ts
index e5c9564..fe85766 100644
--- a/web/gui2/src/main/webapp/app/fw/util/theme.service.ts
+++ b/web/gui2/src/main/webapp/app/fw/util/theme.service.ts
@@ -20,7 +20,9 @@
 /**
  * ONOS GUI -- Util -- Theme Service
  */
-@Injectable()
+@Injectable({
+  providedIn: 'root',
+})
 export class ThemeService {
     themes: string[] = ['light', 'dark'];
     thidx = 0;
diff --git a/web/gui2/src/main/webapp/app/fw/util/util.module.ts b/web/gui2/src/main/webapp/app/fw/util/util.module.ts
deleted file mode 100644
index 293d8e9..0000000
--- a/web/gui2/src/main/webapp/app/fw/util/util.module.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2014-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 { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-
-import { EeService } from './ee.service';
-import { FnService } from './fn.service';
-import { KeyService } from './key.service';
-import { LionService } from './lion.service';
-import { PrefsService } from './prefs.service';
-import { RandomService } from './random.service';
-import { ThemeService } from './theme.service';
-
-/**
- * ONOS GUI -- Utilities Module
- */
-@NgModule({
-  imports: [
-    CommonModule
-  ],
-  declarations: [],
-  providers: [
-    EeService,
-    FnService,
-    KeyService,
-    LionService,
-    PrefsService,
-    RandomService,
-    ThemeService
-  ]
-})
-export class UtilModule { }
diff --git a/web/gui2/src/main/webapp/app/fw/widget/widget.module.ts b/web/gui2/src/main/webapp/app/fw/widget/widget.module.ts
index 02393a9..50d013c 100644
--- a/web/gui2/src/main/webapp/app/fw/widget/widget.module.ts
+++ b/web/gui2/src/main/webapp/app/fw/widget/widget.module.ts
@@ -16,9 +16,7 @@
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { LayerModule } from '../layer/layer.module';
-import { RemoteModule } from '../remote/remote.module';
 import { SvgModule } from '../svg/svg.module';
-import { UtilModule } from '../util/util.module';
 
 import { ButtonService } from './button.service';
 import { ChartBuilderService } from './chartbuilder.service';
diff --git a/web/gui2/src/main/webapp/app/log.service.ts b/web/gui2/src/main/webapp/app/log.service.ts
index 3dc54a1..2835371 100644
--- a/web/gui2/src/main/webapp/app/log.service.ts
+++ b/web/gui2/src/main/webapp/app/log.service.ts
@@ -26,7 +26,9 @@
  * ONOS GUI -- LogService
  * Inspired by https://robferguson.org/blog/2017/09/09/a-simple-logging-service-for-angular-4/
  */
-@Injectable()
+@Injectable({
+  providedIn: 'root',
+})
 export class LogService extends Logger {
   debug: any;
   info: any;
diff --git a/web/gui2/src/main/webapp/app/onos-routing.module.ts b/web/gui2/src/main/webapp/app/onos-routing.module.ts
new file mode 100644
index 0000000..abc6ee0
--- /dev/null
+++ b/web/gui2/src/main/webapp/app/onos-routing.module.ts
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014-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 { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+const onosRoutes: Routes = [
+    {
+        path: 'apps',
+        loadChildren: 'app/view/apps/apps.module#AppsModule'
+    },
+    {
+        path: 'devices',
+        loadChildren: 'app/view/device/device.module#DeviceModule'
+    },
+    {
+        path: '',
+        redirectTo: '',
+        pathMatch: 'full'
+    }
+];
+
+/**
+ * ONOS GUI -- Main Routing Module - allows modules to be lazy loaded
+ *
+ * See https://angular.io/guide/lazy-loading-ngmodules
+ * for the theory of operation
+ */
+@NgModule({
+    imports: [
+        RouterModule.forRoot(onosRoutes)
+    ],
+    exports: [RouterModule],
+    providers: []
+})
+export class OnosRoutingModule { }
diff --git a/web/gui2/src/main/webapp/app/onos.component.html b/web/gui2/src/main/webapp/app/onos.component.html
index 18297ed..3ec1c69 100644
--- a/web/gui2/src/main/webapp/app/onos.component.html
+++ b/web/gui2/src/main/webapp/app/onos.component.html
@@ -1,3 +1,18 @@
+<!--
+~ Copyright 2014-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="view" onosDetectBrowser>
     <onos-mast></onos-mast>
     <onos-nav></onos-nav>
diff --git a/web/gui2/src/main/webapp/app/onos.component.ts b/web/gui2/src/main/webapp/app/onos.component.ts
index 1246314..c2680b7 100644
--- a/web/gui2/src/main/webapp/app/onos.component.ts
+++ b/web/gui2/src/main/webapp/app/onos.component.ts
@@ -83,7 +83,7 @@
         private ps: PanelService,
         private qhs: QuickHelpService,
         private ee: EeService,
-        private wss: WebSocketService,
+        public wss: WebSocketService,
         private ss: SpriteService,
         private log: LogService,
         private onos: OnosService
diff --git a/web/gui2/src/main/webapp/app/onos.module.ts b/web/gui2/src/main/webapp/app/onos.module.ts
index 8e4af34..78cf112 100644
--- a/web/gui2/src/main/webapp/app/onos.module.ts
+++ b/web/gui2/src/main/webapp/app/onos.module.ts
@@ -16,7 +16,6 @@
 import { BrowserModule } from '@angular/platform-browser';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import { NgModule } from '@angular/core';
-import { RouterModule, Routes } from '@angular/router';
 
 import { AppsModule } from './view/apps/apps.module';
 import { DeviceModule } from './view/device/device.module';
@@ -25,12 +24,9 @@
 import { MastModule } from './fw/mast/mast.module';
 import { NavModule } from './fw/nav/nav.module';
 import { SvgModule } from './fw/svg/svg.module';
-import { RemoteModule } from './fw/remote/remote.module';
-import { UtilModule } from './fw/util/util.module';
 import { WidgetModule } from './fw/widget/widget.module';
+import { OnosRoutingModule } from './onos-routing.module';
 
-import { AppsComponent } from './view/apps/apps.component';
-import { DeviceComponent } from './view/device/device.component';
 import { OnosComponent } from './onos.component';
 import { DetectBrowserDirective } from './detectbrowser.directive';
 
@@ -38,12 +34,6 @@
 import { LogService } from './log.service';
 import { OnosService } from './onos.service';
 
-const onosRoutes: Routes = [
-  { path: 'apps', component: AppsComponent },     // All except default should be driven by
-  { path: 'device', component: DeviceComponent }, // servlet like {INJECTED-VIEW-DATA-START}
-  { path: '**', component: DeviceComponent } // Change to Topo(2) when it's ready for normal behaviour
-];
-
 /**
  * ONOS GUI -- Main Application Module
  */
@@ -53,23 +43,19 @@
     DetectBrowserDirective
   ],
   imports: [
-    AppsModule,
-    DeviceModule,
     BrowserModule,
     BrowserAnimationsModule,
     LayerModule,
     MastModule,
     NavModule,
-    RouterModule.forRoot(onosRoutes, { enableTracing: false }),
     SvgModule,
-    RemoteModule,
-    UtilModule, // For OnosComponent
-    WidgetModule
+    WidgetModule,
+    OnosRoutingModule
   ],
   providers: [
     OnosService,
     { provide: LogService, useClass: ConsoleLoggerService },
-    { provide: Window, useValue: window }
+    { provide: 'Window', useValue: window }
   ],
   bootstrap: [
     OnosComponent,
diff --git a/web/gui2/src/main/webapp/app/onos.service.ts b/web/gui2/src/main/webapp/app/onos.service.ts
index 7b4d519..1100310 100644
--- a/web/gui2/src/main/webapp/app/onos.service.ts
+++ b/web/gui2/src/main/webapp/app/onos.service.ts
@@ -27,7 +27,9 @@
 /**
  * ONOS GUI -- OnosService - a placeholder for the global onos variable
  */
-@Injectable()
+@Injectable({
+  providedIn: 'root',
+})
 export class OnosService {
     // Global variable
     public browser: string;
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps-routing.module.ts b/web/gui2/src/main/webapp/app/view/apps/apps-routing.module.ts
new file mode 100644
index 0000000..2fed90d
--- /dev/null
+++ b/web/gui2/src/main/webapp/app/view/apps/apps-routing.module.ts
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2018-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 { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+import { AppsComponent } from './apps.component';
+
+
+const appsRoutes: Routes = [
+    {
+        path: '',
+        component: AppsComponent
+    }
+];
+
+/**
+ * ONOS GUI -- Apps Tabular View Feature Routing Module - allows it to be lazy loaded
+ *
+ * See https://angular.io/guide/lazy-loading-ngmodules
+ */
+@NgModule({
+    imports: [RouterModule.forChild(appsRoutes)],
+    exports: [RouterModule]
+})
+export class AppsRoutingModule { }
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps.component.html b/web/gui2/src/main/webapp/app/view/apps/apps.component.html
index 6397f63..c34694c 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps.component.html
+++ b/web/gui2/src/main/webapp/app/view/apps/apps.component.html
@@ -1,3 +1,18 @@
+<!--
+~ Copyright 2014-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="ov-app" filedrop on-file-drop="appDropped()">
     <div class="tabular-header">
         <h2>
@@ -77,7 +92,7 @@
                 </td>
             </tr>
             <!--&lt;!&ndash;TODO: Add back in  | filter:queryFilter&ndash;&gt;-->
-            <tr class="table-body" *ngFor="let app of tableData; trackBy $index"
+            <tr class="table-body" *ngFor="let app of tableData"
                 (click)="selectCallback($event, app)"
                 [ngClass]="{selected: app.id === selId, 'data-change': isChanged(app.id)}">
                 <td class="table-icon">
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps.component.ts b/web/gui2/src/main/webapp/app/view/apps/apps.component.ts
index b2bb38b..ed6d30a 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps.component.ts
+++ b/web/gui2/src/main/webapp/app/view/apps/apps.component.ts
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Component, OnInit, OnDestroy } from '@angular/core';
+import { Component, OnInit, OnDestroy, Inject } from '@angular/core';
 import { DialogService } from '../../fw/layer/dialog.service';
 import { FnService } from '../../fw/util/fn.service';
 import { IconService } from '../../fw/svg/icon.service';
@@ -97,6 +97,14 @@
     friendlyProps: string[];
     ctrlBtnState: CtrlBtnState;
     detailsPanel: any;
+    appFile: any;
+    activateImmediately = '';
+
+    uploadTip: string;
+    activateTip: string;
+    deactivateTip: string;
+    uninstallTip: string;
+    downloadTip: string;
 
     constructor(
         protected fs: FnService,
@@ -109,7 +117,7 @@
         private ps: PanelService,
         private ufs: UrlFnService,
         protected wss: WebSocketService,
-        private window: Window,
+        @Inject('Window') private window: Window,
     ) {
         super(fs, null, log, wss, 'app');
         this.responseCallback = this.appResponseCb;
@@ -130,6 +138,11 @@
         } else {
             this.doLion();
         }
+        this.uploadTip = this.lionFn('tt_ctl_upload');
+        this.activateTip = this.lionFn('tt_ctl_activate');
+        this.deactivateTip = this.lionFn('tt_ctl_deactivate');
+        this.uninstallTip = this.lionFn('tt_ctl_uninstall');
+        this.downloadTip = this.lionFn('tt_ctl_download');
     }
 
     ngOnInit() {
@@ -244,4 +257,10 @@
     dummyLion(key: string): string {
         return '%' + key + '%';
     }
+
+    appDropped() {
+        this.activateImmediately = activateOption;
+//        $scope.$emit('FileChanged'); // TODO: Implement this
+        this.appFile = null;
+    }
 }
diff --git a/web/gui2/src/main/webapp/app/view/apps/apps.module.ts b/web/gui2/src/main/webapp/app/view/apps/apps.module.ts
index 3e3d5c4..48092a9 100644
--- a/web/gui2/src/main/webapp/app/view/apps/apps.module.ts
+++ b/web/gui2/src/main/webapp/app/view/apps/apps.module.ts
@@ -15,6 +15,7 @@
  */
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
+import { AppsRoutingModule } from './apps-routing.module';
 import { AppsComponent } from './apps.component';
 import { TriggerFormDirective } from './triggerform.directive';
 import { SvgModule } from '../../fw/svg/svg.module';
@@ -27,11 +28,9 @@
  * the 'app' folder which is the root of the complete framework
  */
 @NgModule({
-    exports: [
-        AppsComponent
-    ],
     imports: [
         CommonModule,
+        AppsRoutingModule,
         SvgModule
     ],
     declarations: [
diff --git a/web/gui2/src/main/webapp/app/view/device/device-routing.module.ts b/web/gui2/src/main/webapp/app/view/device/device-routing.module.ts
new file mode 100644
index 0000000..3110eca
--- /dev/null
+++ b/web/gui2/src/main/webapp/app/view/device/device-routing.module.ts
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2018-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 { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+import { DeviceComponent } from './device.component';
+
+
+const deviceRoutes: Routes = [
+    {
+        path: '',
+        component: DeviceComponent
+    }
+];
+
+/**
+ * ONOS GUI -- Devices Tabular View Feature Routing Module - allows it to be lazy loaded
+ *
+ * See https://angular.io/guide/lazy-loading-ngmodules
+ */
+@NgModule({
+    imports: [RouterModule.forChild(deviceRoutes)],
+    exports: [RouterModule]
+})
+export class DeviceRoutingModule { }
diff --git a/web/gui2/src/main/webapp/app/view/device/device.component.html b/web/gui2/src/main/webapp/app/view/device/device.component.html
index e2d3fda..0e09d69 100644
--- a/web/gui2/src/main/webapp/app/view/device/device.component.html
+++ b/web/gui2/src/main/webapp/app/view/device/device.component.html
@@ -1,3 +1,18 @@
+<!--
+~ Copyright 2014-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="ov-device">
     <div class="tabular-header">
         <h2>Devices ({{ tableData.length }} total)</h2>
@@ -61,7 +76,7 @@
             </tr>
 
 
-            <tr class="table-body" *ngFor="let dev of tableData; trackBy $index"
+            <tr class="table-body" *ngFor="let dev of tableData"
                 (click)="selectCallback($event, dev)"
                 [ngClass]="{selected: dev.id === selId, 'data-change': isChanged(dev.id)}">
                 <td class="table-icon">
diff --git a/web/gui2/src/main/webapp/app/view/device/device.component.ts b/web/gui2/src/main/webapp/app/view/device/device.component.ts
index f4a6fbe..99564d0 100644
--- a/web/gui2/src/main/webapp/app/view/device/device.component.ts
+++ b/web/gui2/src/main/webapp/app/view/device/device.component.ts
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Component, OnInit, OnDestroy } from '@angular/core';
+import { Component, OnInit, OnDestroy, Inject } from '@angular/core';
 import { DetailsPanelService } from '../../fw/layer/detailspanel.service';
 import { FnService } from '../../fw/util/fn.service';
 import { IconService } from '../../fw/svg/icon.service';
@@ -77,7 +77,7 @@
         private ps: PanelService,
         private tds: TableDetailService,
         protected wss: WebSocketService,
-        private window: Window,
+        @Inject('Window') private window: Window,
     ) {
         super(fs, ls, log, wss, 'device');
         this.responseCallback = this.deviceResponseCb;
diff --git a/web/gui2/src/main/webapp/app/view/device/device.module.ts b/web/gui2/src/main/webapp/app/view/device/device.module.ts
index 99b15bd..7840292 100644
--- a/web/gui2/src/main/webapp/app/view/device/device.module.ts
+++ b/web/gui2/src/main/webapp/app/view/device/device.module.ts
@@ -15,7 +15,7 @@
  */
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
-import { RouterModule, Routes } from '@angular/router';
+import { DeviceRoutingModule } from './device-routing.module';
 import { DeviceComponent } from './device.component';
 import { DeviceDetailsPanelDirective } from './devicedetailspanel.directive';
 import { SvgModule } from '../../fw/svg/svg.module';
@@ -24,12 +24,9 @@
  * ONOS GUI -- Device View Module
  */
 @NgModule({
-  exports: [
-    DeviceComponent
-  ],
   imports: [
     CommonModule,
-    RouterModule,
+    DeviceRoutingModule,
     SvgModule
   ],
   declarations: [
diff --git a/web/gui2/src/main/webapp/app/view/device/devicedetailspanel.directive.ts b/web/gui2/src/main/webapp/app/view/device/devicedetailspanel.directive.ts
index 13e7e69..d81a67d 100644
--- a/web/gui2/src/main/webapp/app/view/device/devicedetailspanel.directive.ts
+++ b/web/gui2/src/main/webapp/app/view/device/devicedetailspanel.directive.ts
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Directive } from '@angular/core';
+import { Directive, Inject } from '@angular/core';
 import { KeyService } from '../../fw/util/key.service';
 import { LogService } from '../../log.service';
 
@@ -31,8 +31,7 @@
 
     constructor(
         private ks: KeyService,
-        private log: LogService,
-        private window: Window
+        private log: LogService
     ) {
         this.log.debug('DeviceDetailsPanelDirective constructed');
     }
diff --git a/web/gui2/src/main/webapp/tests/app/detectbrowser.directive.spec.ts b/web/gui2/src/main/webapp/tests/app/detectbrowser.directive.spec.ts
index 9183536..37f4a8e 100644
--- a/web/gui2/src/main/webapp/tests/app/detectbrowser.directive.spec.ts
+++ b/web/gui2/src/main/webapp/tests/app/detectbrowser.directive.spec.ts
@@ -62,7 +62,7 @@
                 { provide: LogService, useValue: log },
                 { provide: OnosService, useClass: MockOnosService },
                 { provide: Document, useValue: document },
-                { provide: Window, useFactory: (() => mockWindow ) }
+                { provide: 'Window', useFactory: (() => mockWindow ) }
             ]
         });
     });
diff --git a/web/gui2/src/main/webapp/tests/app/fw/remote/urlfn.service.spec.ts b/web/gui2/src/main/webapp/tests/app/fw/remote/urlfn.service.spec.ts
index 6b229bd..0aa14ea 100644
--- a/web/gui2/src/main/webapp/tests/app/fw/remote/urlfn.service.spec.ts
+++ b/web/gui2/src/main/webapp/tests/app/fw/remote/urlfn.service.spec.ts
@@ -58,7 +58,7 @@
         TestBed.configureTestingModule({
             providers: [UrlFnService,
                 { provide: LogService, useValue: log },
-                { provide: Window, useFactory: (() => windowMock ) },
+                { provide: 'Window', useFactory: (() => windowMock ) },
             ]
         });
 
diff --git a/web/gui2/src/main/webapp/tests/app/fw/remote/websocket.service.spec.ts b/web/gui2/src/main/webapp/tests/app/fw/remote/websocket.service.spec.ts
index 391b62c..e0c7675 100644
--- a/web/gui2/src/main/webapp/tests/app/fw/remote/websocket.service.spec.ts
+++ b/web/gui2/src/main/webapp/tests/app/fw/remote/websocket.service.spec.ts
@@ -76,7 +76,7 @@
                 { provide: LogService, useValue: logSpy },
                 { provide: GlyphService, useClass: MockGlyphService },
                 { provide: UrlFnService, useValue: new UrlFnService(logSpy, windowMock) },
-                { provide: Window, useFactory: (() => windowMock ) },
+                { provide: 'Window', useFactory: (() => windowMock ) },
                 { provide: WSock, useFactory: (() => {
                         return {
                             newWebSocket: (() => mockWebSocket)
diff --git a/web/gui2/src/main/webapp/tests/app/fw/util/fn.service.spec.ts b/web/gui2/src/main/webapp/tests/app/fw/util/fn.service.spec.ts
index bf75091..e3d3c87 100644
--- a/web/gui2/src/main/webapp/tests/app/fw/util/fn.service.spec.ts
+++ b/web/gui2/src/main/webapp/tests/app/fw/util/fn.service.spec.ts
@@ -62,7 +62,7 @@
             providers: [FnService,
                 { provide: LogService, useValue: logSpy },
                 { provide: ActivatedRoute, useValue: ar },
-                { provide: Window, useFactory: (() => mockWindow ) }
+                { provide: 'Window', useFactory: (() => mockWindow ) }
             ]
         });
 
diff --git a/web/gui2/src/main/webapp/tests/app/fw/util/lion.service.spec.ts b/web/gui2/src/main/webapp/tests/app/fw/util/lion.service.spec.ts
index 6535f07..0b661c6 100644
--- a/web/gui2/src/main/webapp/tests/app/fw/util/lion.service.spec.ts
+++ b/web/gui2/src/main/webapp/tests/app/fw/util/lion.service.spec.ts
@@ -72,7 +72,7 @@
                 { provide: UrlFnService, useClass: MockUrlFnService },
                 { provide: WSock, useClass: MockWSock },
                 { provide: WebSocketService, useClass: WebSocketService },
-                { provide: Window, useFactory: (() => windowMock ) },
+                { provide: 'Window', useFactory: (() => windowMock ) },
             ]
         });
     });
diff --git a/web/gui2/src/main/webapp/tests/app/view/apps/apps.component.spec.ts b/web/gui2/src/main/webapp/tests/app/view/apps/apps.component.spec.ts
index 6682e41..2d2f75f 100644
--- a/web/gui2/src/main/webapp/tests/app/view/apps/apps.component.spec.ts
+++ b/web/gui2/src/main/webapp/tests/app/view/apps/apps.component.spec.ts
@@ -124,7 +124,7 @@
                 { provide: ThemeService, useClass: MockThemeService },
                 { provide: UrlFnService, useClass: MockUrlFnService },
                 { provide: WebSocketService, useClass: MockWebSocketService },
-                { provide: Window, useValue: windowMock },
+                { provide: 'Window', useValue: windowMock },
             ]
         })
         .compileComponents();
diff --git a/web/gui2/src/main/webapp/tests/app/view/device/device.component.spec.ts b/web/gui2/src/main/webapp/tests/app/view/device/device.component.spec.ts
index 6d54ac4..40edf5d 100644
--- a/web/gui2/src/main/webapp/tests/app/view/device/device.component.spec.ts
+++ b/web/gui2/src/main/webapp/tests/app/view/device/device.component.spec.ts
@@ -124,7 +124,7 @@
                 { provide: TableDetailService, useClass: MockTableDetailService },
                 { provide: ThemeService, useClass: MockThemeService },
                 { provide: WebSocketService, useClass: MockWebSocketService },
-                { provide: Window, useValue: windowMock },
+                { provide: 'Window', useValue: windowMock },
              ]
         })
         .compileComponents();
diff --git a/web/gui2/src/main/webapp/tests/app/view/device/devicedetailspanel.directive.spec.ts b/web/gui2/src/main/webapp/tests/app/view/device/devicedetailspanel.directive.spec.ts
index 83a7f78..883d38a 100644
--- a/web/gui2/src/main/webapp/tests/app/view/device/devicedetailspanel.directive.spec.ts
+++ b/web/gui2/src/main/webapp/tests/app/view/device/devicedetailspanel.directive.spec.ts
@@ -27,7 +27,6 @@
  */
 describe('DeviceDetailsPanelDirective', () => {
     let log: LogService;
-    const windowMock = <any>{ location: <any> { hostname: 'localhost' } };
 
     beforeEach(() => {
         log = new ConsoleLoggerService();
@@ -35,8 +34,7 @@
         TestBed.configureTestingModule({
             providers: [ DeviceDetailsPanelDirective,
                 { provide: LogService, useValue: log },
-                { provide: KeyService, useClass: MockKeyService },
-                { provide: Window, useValue: windowMock },
+                { provide: KeyService, useClass: MockKeyService }
             ]
         });
     });