RIFT-15726 - optimize download size -> lodash usage in UI
- Isolate specific lodash utilities to be included
- covert usage of underscore library to lodash
- did not make changes to backend api

Change-Id: Ic2fb75c0f25e35dee179c3603ab8f714e51e32af
Signed-off-by: Bob Gallagher <bob.gallagher@riftio.com>
diff --git a/skyquake/framework/utils/rw.js b/skyquake/framework/utils/rw.js
index 1cca8f2..0c280c1 100644
--- a/skyquake/framework/utils/rw.js
+++ b/skyquake/framework/utils/rw.js
@@ -30,6 +30,11 @@
  *     ['c', 'd']
  */
 
+import _isNumber from 'lodash/isNumber';
+import _each from 'lodash/each';
+import _flatten from 'lodash/flatten';
+import _union from 'lodash/union';
+
 var rw = rw || {
   // Angular specific for now but can be modified in one location if need ever be
   BaseController: function() {
@@ -304,7 +309,7 @@
   },
 
   sum : function(total, i, key, value) {
-    if (_.isNumber(value)) {
+    if (_isNumber(value)) {
       total[key] = (i === 0 ? value : (total[key] + value));
     }
   },
@@ -312,7 +317,7 @@
   sum2 : function(key) {
     return function(prev, cur, i) {
       var value = cur[key];
-      if (_.isNumber(value)) {
+      if (_isNumber(value)) {
         if (typeof(prev) === 'undefined') {
           return value;
         } else {
@@ -326,7 +331,7 @@
   max : function(key) {
     return function(prev, cur, i) {
       var value = cur[key];
-      if (_.isNumber(value)) {
+      if (_isNumber(value)) {
         if (typeof(prev) === 'undefined') {
           return value;
         } else if (prev < value) {
@@ -370,7 +375,7 @@
       operation(total, i, key, value);
     };
     for (i = 0; i < rows.length; i++) {
-      _.each(rows[i], f);
+      _each(rows[i], f);
     }
   }
 };
@@ -702,10 +707,10 @@
 
 rw.vnf = {
   ports: function(service) {
-    return _.flatten(jsonPath.eval(service, '$.connector[*].interface[*].port'));
+    return _flatten(jsonPath.eval(service, '$.connector[*].interface[*].port'));
   },
   fabricPorts: function(service) {
-    return _.flatten(jsonPath.eval(service, '$.vm[*].fabric.port'));
+    return _flatten(jsonPath.eval(service, '$.vm[*].fabric.port'));
   }
 };
 
@@ -749,7 +754,7 @@
     }
     var i = 0;
     var self = this;
-    _.each(children, function(child) {
+    _each(children, function(child) {
       self.visit.call(self, child, parent, i, listType);
       i += 1;
     });
@@ -759,7 +764,7 @@
 rw.vcs = {
 
   allVms : function() {
-    return _.flatten([this.jpath('$.collection[*].vm'), this.jpath('$.collection[*].collection[*].vm')], true);
+    return _flatten([this.jpath('$.collection[*].vm'), this.jpath('$.collection[*].collection[*].vm')], true);
   },
 
   vms: function(n) {
@@ -826,7 +831,7 @@
   getChildren: function(n) {
     switch (rw.vcs.nodeType(n)) {
       case 'rwcolony':
-        return 'vm' in n ? _.union(n.collection, n.vm) : n.collection;
+        return 'vm' in n ? _union(n.collection, n.vm) : n.collection;
       case 'rwcluster':
         return n.vm;
       case 'RWVM':
@@ -838,7 +843,7 @@
   },
 
   jpath : function(jpath, n) {
-    return _.flatten(jsonPath.eval(n || this, jpath), true);
+    return _flatten(jsonPath.eval(n || this, jpath), true);
   }
 };
 
diff --git a/skyquake/framework/utils/utils.js b/skyquake/framework/utils/utils.js
index e8e9ad1..fc6b592 100644
--- a/skyquake/framework/utils/utils.js
+++ b/skyquake/framework/utils/utils.js
@@ -18,9 +18,9 @@
 //Login needs to be refactored. Too many cross dependencies
 var AuthActions = require('../widgets/login/loginAuthActions.js');
 var $ = require('jquery');
-var rw = require('utils/rw.js');
+import rw from './rw.js';
 var API_SERVER = rw.getSearchParams(window.location).api_server;
-let NODE_PORT = require('utils/rw.js').getSearchParams(window.location).api_port || ((window.location.protocol == 'https:') ? 8443 : 8000);
+let NODE_PORT = rw.getSearchParams(window.location).api_port || ((window.location.protocol == 'https:') ? 8443 : 8000);
 var SockJS = require('sockjs-client');
 
 var Utils = {};
diff --git a/skyquake/framework/widgets/listy/listy.js b/skyquake/framework/widgets/listy/listy.js
index ac0e58a..d032f97 100644
--- a/skyquake/framework/widgets/listy/listy.js
+++ b/skyquake/framework/widgets/listy/listy.js
@@ -16,7 +16,9 @@
  *
  */
 import React from 'react';
-import _ from 'lodash';
+import _isArrayLike from 'lodash/isArrayLike';
+import _isObjectLike from 'lodash/isObjectLike';
+import _isEmpty from 'lodash/isEmpty';
 
 /**
  *
@@ -40,10 +42,10 @@
 
  		var listNode = null;
  		var self = this;
- 		if (_.isArrayLike(data) && _.isObjectLike(data)) {
+ 		if (_isArrayLike(data) && _isObjectLike(data)) {
  			var children = [];
 			data.forEach(function(element, index, array) {
-				if ( _.isArrayLike(element) || _.isObjectLike(element)) {
+				if ( _isArrayLike(element) || _isObjectLike(element)) {
 					children.push(self.createList(element, iter+1));
 				} else {
 					children.push(React.createElement(itemTag, {
@@ -57,10 +59,10 @@
 				key: iter,
 				className: groupClass }, children);
  		}
- 		else if (_.isObjectLike(data)) {
+ 		else if (_isObjectLike(data)) {
  			var children = [];
  			for (var key in data) {
- 				if ( _.isArrayLike(data[key]) || _.isObjectLike(data[key])) {
+ 				if ( _isArrayLike(data[key]) || _isObjectLike(data[key])) {
  					children.push(
  						React.createElement(listHeaderTag, {
  							key: key + '_header',
@@ -103,7 +105,7 @@
 
  		return React.createElement("div", {
  			className: "listy" },
- 			_.isEmpty(data) ? 
+ 			_isEmpty(data) ? 
  			this.noDataMessage() : 
  			this.createList(data)
  		)
@@ -116,7 +118,7 @@
 
 	if (!obj)
 		return new Error('Validation failed. "%" is undefined', fullAttr);
-	if (!obj.hasOwnProperty("tag") || _.isEmpty(obj.tag))
+	if (!obj.hasOwnProperty("tag") || _isEmpty(obj.tag))
 		return new Error('Validation failed. "%s" missing attribute "tag"', fullAttr);
 	if (!obj.hasOwnProperty("className") || obj.className == undefined)
 		return new Error('Validation failed. "%s" missing attribute "className"', fullAttr);
diff --git a/skyquake/framework/widgets/login/login.jsx b/skyquake/framework/widgets/login/login.jsx
index 1506809..840a2bd 100644
--- a/skyquake/framework/widgets/login/login.jsx
+++ b/skyquake/framework/widgets/login/login.jsx
@@ -19,7 +19,8 @@
 import Utils from 'utils/utils.js';
 import Button from 'widgets/button/rw.button.js';
 import './login.scss'
-let rw = require('utils/rw.js');
+import rw from 'utils/rw.js';
+
 class LoginScreen extends React.Component{
   constructor(props) {
     super(props);
diff --git a/skyquake/framework/widgets/skyquake_container/eventCenter.jsx b/skyquake/framework/widgets/skyquake_container/eventCenter.jsx
index 75d2d52..7df4e3e 100644
--- a/skyquake/framework/widgets/skyquake_container/eventCenter.jsx
+++ b/skyquake/framework/widgets/skyquake_container/eventCenter.jsx
@@ -28,7 +28,9 @@
 import Utils from 'utils/utils.js';
 import Crouton from 'react-crouton';
 import TreeView from 'react-treeview';
-import _ from 'lodash';
+import _isEqual from 'lodash/isEqual';
+import _merge from 'lodash/merge';
+import _indexOf from 'lodash/indexOf';
 import '../../../node_modules/react-treeview/react-treeview.css';
 import './eventCenter.scss';
 
@@ -48,7 +50,7 @@
 		if (props.newNotificationEvent && props.newNotificationMsg) {
 			if (latestNotification) {
 				latestNotification = JSON.parse(latestNotification);
-				if (!_.isEqual(props.newNotificationMsg, latestNotification)) {
+				if (!_isEqual(props.newNotificationMsg, latestNotification)) {
 					stateObject.newNotificationEvent = props.newNotificationEvent;
 					stateObject.newNotificationMsg = props.newNotificationMsg;
 					sessionStorage.setItem('latestNotification', JSON.stringify(stateObject.newNotificationMsg));
@@ -67,7 +69,7 @@
 		}
 
 		if (notificationList) {
-			stateObject.notifications = _.merge(notificationList, props.notifications);
+			stateObject.notifications = _merge(notificationList, props.notifications);
 		} else {
 			stateObject.notifications = props.notifications;
 		}
@@ -112,7 +114,7 @@
 			notificationFields.eventTime = notification.eventTime;
 
 			Object.keys(notification).map((notificationKey) => {
-				if (_.indexOf(['source', 'eventTime'], notificationKey) == -1) {
+				if (_indexOf(['source', 'eventTime'], notificationKey) == -1) {
 					notificationFields.eventKey = notificationKey;
 					notificationFields.details = notification[notificationFields.eventKey];
 				}
diff --git a/skyquake/framework/widgets/skyquake_container/skyquakeContainer.jsx b/skyquake/framework/widgets/skyquake_container/skyquakeContainer.jsx
index bf036e2..d53d85f 100644
--- a/skyquake/framework/widgets/skyquake_container/skyquakeContainer.jsx
+++ b/skyquake/framework/widgets/skyquake_container/skyquakeContainer.jsx
@@ -24,7 +24,6 @@
 import SkyquakeContainerStore from './skyquakeContainerStore.js';
 // import Breadcrumbs from 'react-breadcrumbs';
 import Utils from 'utils/utils.js';
-import _ from 'lodash';
 import Crouton from 'react-crouton';
 import ScreenLoader from 'widgets/screen-loader/screenLoader.jsx';
 import './skyquakeApp.scss';
diff --git a/skyquake/framework/widgets/skyquake_container/skyquakeContainerSource.js b/skyquake/framework/widgets/skyquake_container/skyquakeContainerSource.js
index ae2147a..76dffea 100644
--- a/skyquake/framework/widgets/skyquake_container/skyquakeContainerSource.js
+++ b/skyquake/framework/widgets/skyquake_container/skyquakeContainerSource.js
@@ -18,13 +18,14 @@
 import Alt from './skyquakeAltInstance.js';
 import $ from 'jquery';
 import SkyquakeContainerActions from './skyquakeContainerActions'
+import rw from 'utils/rw.js';
+import Utils from 'utils/utils.js';
 
-let Utils = require('utils/utils.js');
-let API_SERVER = require('utils/rw.js').getSearchParams(window.location).api_server;
+let API_SERVER = rw.getSearchParams(window.location).api_server;
 let HOST = API_SERVER;
-let NODE_PORT = require('utils/rw.js').getSearchParams(window.location).api_port || ((window.location.protocol == 'https:') ? 8443 : 8000);
-let DEV_MODE = require('utils/rw.js').getSearchParams(window.location).dev_mode || false;
-let RW_REST_API_PORT = require('utils/rw.js').getSearchParams(window.location).rw_rest_api_port || 8008;
+let NODE_PORT = rw.getSearchParams(window.location).api_port || ((window.location.protocol == 'https:') ? 8443 : 8000);
+let DEV_MODE = rw.getSearchParams(window.location).dev_mode || false;
+let RW_REST_API_PORT = rw.getSearchParams(window.location).rw_rest_api_port || 8008;
 
 if (DEV_MODE) {
     HOST = window.location.protocol + '//' + window.location.hostname;
diff --git a/skyquake/framework/widgets/skyquake_container/skyquakeContainerStore.js b/skyquake/framework/widgets/skyquake_container/skyquakeContainerStore.js
index f69014e..56ebdda 100644
--- a/skyquake/framework/widgets/skyquake_container/skyquakeContainerStore.js
+++ b/skyquake/framework/widgets/skyquake_container/skyquakeContainerStore.js
@@ -20,9 +20,10 @@
 import Alt from './skyquakeAltInstance.js';
 import SkyquakeContainerSource from './skyquakeContainerSource.js';
 import SkyquakeContainerActions from './skyquakeContainerActions';
-import _ from 'lodash';
+import _indexOf from 'lodash/indexOf';
 //Temporary, until api server is on same port as webserver
-var rw = require('utils/rw.js');
+import rw from 'utils/rw.js';
+
 var API_SERVER = rw.getSearchParams(window.location).api_server;
 var UPLOAD_SERVER = rw.getSearchParams(window.location).upload_server;
 
@@ -100,7 +101,7 @@
                 } else {
                     // Temp to test before adding multi-sources
                     data.notification.source = streamSource;
-                    if (_.indexOf(self.notifications, data.notification) == -1) {
+                    if (_indexOf(self.notifications, data.notification) == -1) {
                         // newly appreared event.
                         // Add to the notifications list and setState
                         self.notifications.unshift(data.notification);
diff --git a/skyquake/framework/widgets/skyquake_container/skyquakeNav.jsx b/skyquake/framework/widgets/skyquake_container/skyquakeNav.jsx
index 73a2f02..8814a18 100644
--- a/skyquake/framework/widgets/skyquake_container/skyquakeNav.jsx
+++ b/skyquake/framework/widgets/skyquake_container/skyquakeNav.jsx
@@ -23,7 +23,8 @@
 import 'style/common.scss';
 
 //Temporary, until api server is on same port as webserver
-var rw = require('utils/rw.js');
+import rw from 'utils/rw.js';
+
 var API_SERVER = rw.getSearchParams(window.location).api_server;
 var UPLOAD_SERVER = rw.getSearchParams(window.location).upload_server;
 
diff --git a/skyquake/framework/widgets/topology/topologyTree.jsx b/skyquake/framework/widgets/topology/topologyTree.jsx
index 5e0d895..9c77c13 100644
--- a/skyquake/framework/widgets/topology/topologyTree.jsx
+++ b/skyquake/framework/widgets/topology/topologyTree.jsx
@@ -20,7 +20,7 @@
 import ReactDOM from 'react-dom';
 import d3 from 'd3';
 import DashboardCard from '../dashboard_card/dashboard_card.jsx';
-import _ from 'lodash';
+import _cloneDeep from 'lodash/cloneDeep';
 import $ from 'jquery';
 import './topologyTree.scss';
 
@@ -66,7 +66,7 @@
             //this.props.selectNode(props.data);
         }
         if(this.svg) {
-          this.update(_.cloneDeep(props.data));
+          this.update(_cloneDeep(props.data));
           // this.selectedID = props.data.id;
         }
     }