CORD-731 Added debug decorator

Change-Id: Idd9595f30f9d09f4072dbcd2b05535dafba3202b
diff --git a/src/app/core/header/header.ts b/src/app/core/header/header.ts
index 620aecd..1f01bf8 100644
--- a/src/app/core/header/header.ts
+++ b/src/app/core/header/header.ts
@@ -48,10 +48,6 @@
       // tapToDismiss: false
     });
 
-    // this.$rootScope.$on('xos.core.modelSetup', () => {
-    //   this.states = _.uniqBy(this.states, 'state');
-    // });
-
     this.search = (query: string) => {
       return this.SearchService.search(query);
     };
@@ -61,7 +57,6 @@
       if (e.key === 'f') {
         $('.navbar-form input').focus();
       }
-      // console.log(this.SearchService.getStates());
     });
 
     // redirect to selected page
diff --git a/src/app/core/login/login.ts b/src/app/core/login/login.ts
index a08c17d..673d9a8 100644
--- a/src/app/core/login/login.ts
+++ b/src/app/core/login/login.ts
@@ -4,11 +4,12 @@
 import {IXosStyleConfig} from '../../../index';
 
 class LoginCtrl {
-  static $inject = ['AuthService', '$state', 'ModelSetup', 'StyleConfig'];
+  static $inject = ['$log', 'AuthService', '$state', 'ModelSetup', 'StyleConfig'];
   public loginStyle: any;
   public img: string;
   /** @ngInject */
   constructor(
+    private $log: ng.ILogService,
     private authService: AuthService,
     private $state: angular.ui.IStateService,
     private ModelSetup: IXosModelSetupService,
@@ -39,7 +40,7 @@
         this.$state.go('xos.dashboard');
       })
       .catch(e => {
-        console.error(e);
+        this.$log.error(e);
       });
   }
 
diff --git a/src/app/core/services/helpers/model-setup.helpers.ts b/src/app/core/services/helpers/model-setup.helpers.ts
index b0a2be6..e79899d 100644
--- a/src/app/core/services/helpers/model-setup.helpers.ts
+++ b/src/app/core/services/helpers/model-setup.helpers.ts
@@ -53,8 +53,7 @@
             parent: 'xos.core'
           });
         });
-        console.log('xos.core.modelSetup');
-        this.$rootScope.$emit('xos.core.modelSetup', {done: true});
+
         d.resolve();
       })
       .catch(d.reject);
diff --git a/src/app/core/validation/validation.ts b/src/app/core/validation/validation.ts
index 7481b3b..5a27045 100644
--- a/src/app/core/validation/validation.ts
+++ b/src/app/core/validation/validation.ts
@@ -7,7 +7,6 @@
   public config: any;
 
   $onInit() {
-    console.log('validation');
     this.config = {
       type: 'danger'
     };
diff --git a/src/app/datasources/stores/model.store.spec.ts b/src/app/datasources/stores/model.store.spec.ts
index 97ce890..a73e5ff 100644
--- a/src/app/datasources/stores/model.store.spec.ts
+++ b/src/app/datasources/stores/model.store.spec.ts
@@ -105,7 +105,6 @@
             }
           },
           err => {
-            console.log(err);
             done(err);
           }
         );
diff --git a/src/app/datasources/stores/model.store.ts b/src/app/datasources/stores/model.store.ts
index 4c6c09d..a070436 100644
--- a/src/app/datasources/stores/model.store.ts
+++ b/src/app/datasources/stores/model.store.ts
@@ -11,9 +11,10 @@
 }
 
 export class ModelStore {
-  static $inject = ['WebSocket', 'StoreHelpers', 'ModelRest'];
+  static $inject = ['$log', 'WebSocket', 'StoreHelpers', 'ModelRest'];
   private _collections: any; // NOTE contains a map of {model: BehaviourSubject}
   constructor(
+    private $log: ng.ILogService,
     private webSocket: IWSEventService,
     private storeHelpers: IStoreHelpersService,
     private ModelRest: IXosResourceService,
@@ -71,8 +72,9 @@
       .then(
         res => {
           this._collections[model].next(res);
-        },
-        err => console.log(`Error retrieving ${model}`, err)
+        })
+      .catch(
+        err => this.$log.log(`Error retrieving ${model}`, err)
       );
   }
 }
diff --git a/src/decorators.ts b/src/decorators.ts
new file mode 100644
index 0000000..3b2ab4e
--- /dev/null
+++ b/src/decorators.ts
@@ -0,0 +1,39 @@
+export default function XosLogDecorator($provide: ng.auto.IProvideService) {
+  $provide.decorator('$log', function($delegate: any) {
+    const isLogEnabled = () => {
+      return window.location.href.indexOf('debug=true') >= 0;
+    };
+    // Save the original $log.debug()
+    let logFn = $delegate.log;
+    let infoFn = $delegate.info;
+    let warnFn = $delegate.warn;
+    let errorFn = $delegate.error;
+    let debugFn = $delegate.debug;
+
+    // create the replacement function
+    const replacement = (fn) => {
+      return function(){
+        if (!isLogEnabled()) {
+          return;
+        }
+
+        let args    = [].slice.call(arguments);
+        let now     = new Date();
+
+        // Prepend timestamp
+        args[0] = `[${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}] ${args[0]}`;
+
+        // Call the original with the output prepended with formatted timestamp
+        fn.apply(null, args);
+      };
+    };
+
+    $delegate.info = replacement(infoFn);
+    $delegate.log = replacement(logFn);
+    $delegate.warn = replacement(warnFn);
+    $delegate.error = replacement(errorFn); // note this will prevent errors to be printed
+    $delegate.debug = replacement(debugFn);
+
+    return $delegate;
+  });
+}
diff --git a/src/index.ts b/src/index.ts
index 0be6245..0322608 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -25,6 +25,7 @@
 import {IXosAuthService} from './app/datasources/rest/auth.rest';
 import {IXosModelSetupService} from './app/core/services/helpers/model-setup.helpers';
 import {IXosNavigationRoute} from './app/core/services/navigation';
+import XosLogDecorator from './decorators';
 
 export interface IXosState extends angular.ui.IState {
   data: IXosCrudData;
@@ -53,13 +54,14 @@
     'ngResource',
     xosTemplate // template module
   ])
+  .config(XosLogDecorator)
   .config(routesConfig)
   .config(interceptorConfig)
   .factory('UserStatusInterceptor', userStatusInterceptor)
   .factory('CredentialsInterceptor', CredentialsInterceptor)
   .factory('NoHyperlinksInterceptor', NoHyperlinksInterceptor)
   .component('xos', main)
-  .run(function($rootScope: ng.IRootScopeService, $transitions: any, StyleConfig: IXosStyleConfig) {
+  .run(function($log: ng.ILogService, $rootScope: ng.IRootScopeService, $transitions: any, StyleConfig: IXosStyleConfig) {
     $rootScope['favicon'] = `./app/images/brand/${StyleConfig.favicon}`;
     $transitions.onSuccess({ to: '**' }, (transtion) => {
       if (transtion.$to().name === 'login') {
@@ -71,6 +73,7 @@
     });
   })
   .run((
+    $rootScope: ng.IRootScopeService,
     $transitions: any,
     $location: ng.ILocationService,
     $state: ng.ui.IStateService,
@@ -87,15 +90,29 @@
       }
     });
 
+    // preserve debug=true query string parameter
+    $transitions.onStart({ to: '**' }, (transtion) => {
+      // save location.search so we can add it back after transition is done
+      this.locationSearch = $location.search();
+    });
+
+    $transitions.onSuccess({ to: '**' }, (transtion) => {
+      // restore all query string parameters back to $location.search
+      if (angular.isDefined(this.locationSearch.debug) && this.locationSearch.debug) {
+        $location.search({debug: 'true'});
+      }
+    });
+
     // save the last visited state before reload
-    const lastRoute = window.location.hash.replace('#', '');
+    const lastRoute = $location.path();
+    const lastQueryString = $location.search();
 
     // if the user is authenticated
     if (AuthService.getUser()) {
       ModelSetup.setup()
         .then(() => {
           // after setting up dynamic routes, redirect to previous state
-          $location.path(lastRoute);
+          $location.path(lastRoute).search(lastQueryString);
         });
     }
 
diff --git a/tslint.json b/tslint.json
index 9f4f2c7..04d33e1 100644
--- a/tslint.json
+++ b/tslint.json
@@ -1,6 +1,5 @@
 {
   "rules": {
-    "no-console": [true],
     "ban": [true,
       ["_", "extend"],
       ["_", "isNull"],
@@ -31,7 +30,9 @@
       "info",
       "time",
       "timeEnd",
-      "trace"
+      "trace",
+      "log",
+      "error"
     ],
     "no-construct": true,
     "no-constructor-vars": false,