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;
         }
     }
diff --git a/skyquake/plugins/accounts/src/account/account.jsx b/skyquake/plugins/accounts/src/account/account.jsx
index 37063ca..e588e74 100644
--- a/skyquake/plugins/accounts/src/account/account.jsx
+++ b/skyquake/plugins/accounts/src/account/account.jsx
@@ -18,7 +18,7 @@
 
 import React from 'react';
 import Button from 'widgets/button/rw.button.js';
-import _ from 'lodash';
+import _cloneDeep from 'lodash/cloneDeep';
 import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
 import Crouton from 'react-crouton';
 import TextInput from 'widgets/form_controls/textInput.jsx';
@@ -94,7 +94,7 @@
             }
         }
 
-        let newAccount = _.cloneDeep(removeTrailingWhitespace(Account));
+        let newAccount = _cloneDeep(removeTrailingWhitespace(Account));
         delete newAccount.params;
         newAccount.nestedParams &&
             newAccount.nestedParams['container-name'] &&
diff --git a/skyquake/plugins/composer/src/src/components/CanvasPanel.js b/skyquake/plugins/composer/src/src/components/CanvasPanel.js
index 9eece49..160db5f 100644
--- a/skyquake/plugins/composer/src/src/components/CanvasPanel.js
+++ b/skyquake/plugins/composer/src/src/components/CanvasPanel.js
@@ -18,7 +18,7 @@
  */
 'use strict';
 
-import _ from 'lodash'
+import _includes from 'lodash/includes'
 import cc from 'change-case'
 import React from 'react'
 import PureRenderMixin from 'react-addons-pure-render-mixin'
@@ -115,7 +115,7 @@
 		);
 	},
 	onDragOver(event) {
-		const isDraggingFiles = _.includes(event.dataTransfer.types, 'Files');
+		const isDraggingFiles = _includes(event.dataTransfer.types, 'Files');
 		if (!isDraggingFiles) {
 			event.preventDefault();
 			event.dataTransfer.dropEffect = 'copy';
diff --git a/skyquake/plugins/composer/src/src/components/CatalogPanel.js b/skyquake/plugins/composer/src/src/components/CatalogPanel.js
index d7ebf0f..0314e19 100644
--- a/skyquake/plugins/composer/src/src/components/CatalogPanel.js
+++ b/skyquake/plugins/composer/src/src/components/CatalogPanel.js
@@ -18,7 +18,7 @@
  */
 'use strict';
 
-import _ from 'lodash'
+import _includes from 'lodash/includes'
 import React from 'react'
 import ReactDOM from 'react-dom'
 import messages from './messages'
@@ -167,7 +167,7 @@
 			uiTransientState.isDrop = false;
 			uiTransientState.isDragging = true;
 			uiTransientState.wasTrayOpen = this.state.isTrayOpen;
-			uiTransientState.isDraggingFiles = _.includes(e.dataTransfer.types, 'Files');
+			uiTransientState.isDraggingFiles = _includes(e.dataTransfer.types, 'Files');
 			const dragState = ComposerAppStore.getState().drag || {};
 			if (uiTransientState.isDraggingFiles || (dragState.type === 'catalog-item')) {
 				CatalogPanelTrayActions.open();
diff --git a/skyquake/plugins/composer/src/src/components/DetailsPanel.js b/skyquake/plugins/composer/src/src/components/DetailsPanel.js
index a20679f..2e12052 100644
--- a/skyquake/plugins/composer/src/src/components/DetailsPanel.js
+++ b/skyquake/plugins/composer/src/src/components/DetailsPanel.js
@@ -18,7 +18,7 @@
  */
 'use strict';
 
-import _ from 'lodash'
+import _cloneDeep from 'lodash/cloneDeep'
 import React from 'react';
 import PureRenderMixin from 'react-addons-pure-render-mixin'
 import messages from './messages'
@@ -57,7 +57,7 @@
 		const selectedContainer = selected[0];
 		if (selectedContainer) {
 			bodyComponent = <CatalogItemDetailsEditor container={selectedContainer} width={this.props.layout.right} />;
-			const edit = _.cloneDeep(selectedContainer.model);
+			const edit = _cloneDeep(selectedContainer.model);
 			json = serializers.serialize(edit) || edit;
 		}
 		const jsonViewerTitle = selectedContainer ? selectedContainer.model.name : 'nothing selected';
diff --git a/skyquake/plugins/composer/src/src/components/EditDescriptorModelProperties.js b/skyquake/plugins/composer/src/src/components/EditDescriptorModelProperties.js
index b3d8afb..2615c6e 100644
--- a/skyquake/plugins/composer/src/src/components/EditDescriptorModelProperties.js
+++ b/skyquake/plugins/composer/src/src/components/EditDescriptorModelProperties.js
@@ -22,7 +22,9 @@
  */
 'use strict';
 
-import _ from 'lodash'
+import _includes from 'lodash/includes'
+import _isArray from 'lodash/isArray'
+import _cloneDeep from 'lodash/cloneDeep'
 import utils from '../libraries/utils'
 import React from 'react'
 import ClassNames from 'classnames'
@@ -47,12 +49,12 @@
 import '../styles/EditDescriptorModelProperties.scss'
 
 function getDescriptorMetaBasicForType(type) {
-	const basicPropertiesFilter = d => _.includes(DESCRIPTOR_MODEL_FIELDS[type], d.name);
+	const basicPropertiesFilter = d => _includes(DESCRIPTOR_MODEL_FIELDS[type], d.name);
 	return DescriptorModelMetaFactory.getModelMetaForType(type, basicPropertiesFilter) || {properties: []};
 }
 
 function getDescriptorMetaAdvancedForType(type) {
-	const advPropertiesFilter = d => !_.includes(DESCRIPTOR_MODEL_FIELDS[type], d.name);
+	const advPropertiesFilter = d => !_includes(DESCRIPTOR_MODEL_FIELDS[type], d.name);
 	return DescriptorModelMetaFactory.getModelMetaForType(type, advPropertiesFilter) || {properties: []};
 }
 
@@ -206,7 +208,7 @@
 		}
 
 		if (isLeafRef) {
-			let fullFieldKey = _.isArray(fieldKey) ? fieldKey.join(':') : fieldKey;
+			let fullFieldKey = _isArray(fieldKey) ? fieldKey.join(':') : fieldKey;
 			let containerRef = container;
 			while (containerRef.parent) {
 				fullFieldKey = containerRef.parent.key + ':' + fullFieldKey;
@@ -226,7 +228,7 @@
 		}
 
 		if (isBoolean) {
-			let fullFieldKey = _.isArray(fieldKey) ? fieldKey.join(':') : fieldKey;
+			let fullFieldKey = _isArray(fieldKey) ? fieldKey.join(':') : fieldKey;
 			let containerRef = container;
 			while (containerRef.parent) {
 				fullFieldKey = containerRef.parent.key + ':' + fullFieldKey;
@@ -335,7 +337,7 @@
 					isTopCase = true;
 					choiceObject = utils.resolvePath(this.model, [selected].join('.'));
 				}
-				utils.assignPathValue(stateObject, [selected].join('.'), _.cloneDeep(choiceObject));
+				utils.assignPathValue(stateObject, [selected].join('.'), _cloneDeep(choiceObject));
 
 				if(selected) {
 					if(this.model.uiState.choice.hasOwnProperty(name)) {
@@ -422,7 +424,7 @@
 		//If selectedOptionValue is present, take first item in string which represents the case name.
 		const valueProperty = caseByNameMap[selectedOptionValue ? selectedOptionValue.split('.')[0] : undefined] || {properties: []};
 		const isLeaf = Property.isLeaf(valueProperty);
-		const hasProperties = _.isArray(valueProperty.properties) && valueProperty.properties.length;
+		const hasProperties = _isArray(valueProperty.properties) && valueProperty.properties.length;
 		const isMissingDescriptorMeta = !hasProperties && !Property.isLeaf(valueProperty);
 		//Some magic that prevents errors for arising
 		const valueResponse = valueProperty.properties && valueProperty.properties.length ? valueProperty.properties.map(valuePropertyFn) : (!isMissingDescriptorMeta) ? build(container, valueProperty, path.concat(valueProperty.name), utils.resolvePath(container.model, path.concat(valueProperty.name).join('.')) || container.model[valueProperty.name]) :
@@ -508,7 +510,7 @@
 			property.properties = uiState.properties;
 		}
 
-		const hasProperties = _.isArray(property.properties) && property.properties.length;
+		const hasProperties = _isArray(property.properties) && property.properties.length;
 		const isMissingDescriptorMeta = !hasProperties && !Property.isLeaf(property);
 
 		// ensure value is not undefined for non-leaf property types
@@ -517,7 +519,7 @@
 				value = isArray ? [] : {};
 			}
 		}
-		const valueAsArray = _.isArray(value) ? value : isLeafList && typeof value === 'undefined' ? [] : [value];
+		const valueAsArray = _isArray(value) ? value : isLeafList && typeof value === 'undefined' ? [] : [value];
 
 		const isMetaField = property.name === 'meta';
 		const isCVNFD = property.name === 'constituent-vnfd';
diff --git a/skyquake/plugins/composer/src/src/components/filemanager/FileManager.jsx b/skyquake/plugins/composer/src/src/components/filemanager/FileManager.jsx
index 3833ab4..d1e5c93 100644
--- a/skyquake/plugins/composer/src/src/components/filemanager/FileManager.jsx
+++ b/skyquake/plugins/composer/src/src/components/filemanager/FileManager.jsx
@@ -18,7 +18,8 @@
 
 
 //https://raw.githubusercontent.com/RIFTIO/RIFT.ware/master/rift-shell
-import _ from 'lodash'
+import _cloneDeep from 'lodash/cloneDeep'
+import _findIndex from 'lodash/findIndex'
 import React from 'react';
 import ReactDOM from 'react-dom';
 import TreeView from 'react-treeview';
@@ -83,11 +84,11 @@
             let splitUrl = url.split('/');
             let fileName = splitUrl[splitUrl.length - 1];
             folder.pop;
-            let fullPath = _.cloneDeep(folder);
+            let fullPath = _cloneDeep(folder);
             fullPath.push(fileName);
             fullPath = fullPath.join('/');
             folder = folder.join('/');
-            let fileIndex = _.findIndex(files[folder], function(f) {
+            let fileIndex = _findIndex(files[folder], function(f) {
                 return f.name == fullPath;
             })
             if (fileIndex == -1) {
diff --git a/skyquake/plugins/composer/src/src/components/filemanager/FileManagerSource.js b/skyquake/plugins/composer/src/src/components/filemanager/FileManagerSource.js
index fec49f1..42c190f 100644
--- a/skyquake/plugins/composer/src/src/components/filemanager/FileManagerSource.js
+++ b/skyquake/plugins/composer/src/src/components/filemanager/FileManagerSource.js
@@ -18,7 +18,6 @@
  */
 'use strict';
 
-import _ from 'lodash'
 import $ from 'jquery'
 import alt from '../../alt'
 import utils from '../../libraries/utils'
diff --git a/skyquake/plugins/composer/src/src/libraries/DeletionManager.js b/skyquake/plugins/composer/src/src/libraries/DeletionManager.js
index 026555c..d5734df 100644
--- a/skyquake/plugins/composer/src/src/libraries/DeletionManager.js
+++ b/skyquake/plugins/composer/src/src/libraries/DeletionManager.js
@@ -20,7 +20,6 @@
  * Created by onvelocity on 10/2/15.
  */
 
-import _ from 'lodash'
 import d3 from 'd3'
 import UID from './UniqueId'
 import SelectionManager from './SelectionManager'
diff --git a/skyquake/plugins/composer/src/src/libraries/SelectionManager.js b/skyquake/plugins/composer/src/src/libraries/SelectionManager.js
index 94ab813..3089b82 100644
--- a/skyquake/plugins/composer/src/src/libraries/SelectionManager.js
+++ b/skyquake/plugins/composer/src/src/libraries/SelectionManager.js
@@ -5,7 +5,6 @@
 
 'use strict';
 
-import _ from 'lodash'
 import d3 from 'd3'
 import UID from './UniqueId'
 import React from 'react'
diff --git a/skyquake/plugins/composer/src/src/libraries/graph/DescriptorGraph.js b/skyquake/plugins/composer/src/src/libraries/graph/DescriptorGraph.js
index b70c921..69ae493 100644
--- a/skyquake/plugins/composer/src/src/libraries/graph/DescriptorGraph.js
+++ b/skyquake/plugins/composer/src/src/libraries/graph/DescriptorGraph.js
@@ -21,7 +21,6 @@
  */
 'use strict';
 
-import _ from 'lodash'
 import d3 from 'd3'
 import math from './math'
 import ClassNames from 'classnames'
diff --git a/skyquake/plugins/composer/src/src/libraries/graph/HighlightRecordServicePaths.js b/skyquake/plugins/composer/src/src/libraries/graph/HighlightRecordServicePaths.js
index 9274c23..0094e01 100644
--- a/skyquake/plugins/composer/src/src/libraries/graph/HighlightRecordServicePaths.js
+++ b/skyquake/plugins/composer/src/src/libraries/graph/HighlightRecordServicePaths.js
@@ -4,7 +4,7 @@
 
 'use strict';
 
-import _ from 'lodash'
+import _isArray from 'lodash/isArray'
 import d3 from 'd3'
 
 /**
@@ -26,7 +26,7 @@
 		Array.from(document.querySelectorAll(`svg .forwarding-graph-paths`)).forEach(d => {
 			d3.select(d).classed('-is-highlighting', true);
 		});
-		const list = _.isArray(rsp) ? rsp : [rsp];
+		const list = _isArray(rsp) ? rsp : [rsp];
 		list.forEach(rsp => {
 			Array.from(document.querySelectorAll(`[data-id="${rsp.id}"]`)).forEach(d => {
 				d.parentNode.appendChild(d);
diff --git a/skyquake/plugins/composer/src/src/libraries/graph/layouts/RelationsAndNetworksLayout.js b/skyquake/plugins/composer/src/src/libraries/graph/layouts/RelationsAndNetworksLayout.js
index f53b4dc..571fcdf 100644
--- a/skyquake/plugins/composer/src/src/libraries/graph/layouts/RelationsAndNetworksLayout.js
+++ b/skyquake/plugins/composer/src/src/libraries/graph/layouts/RelationsAndNetworksLayout.js
@@ -2,7 +2,6 @@
  * Created by onvelocity on 2/10/16.
  */
 import alt from '../../../alt'
-import _ from 'lodash'
 import d3 from 'd3'
 import math from '../math'
 import ClassNames from 'classnames'
diff --git a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModel.js b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModel.js
index 1a2ba4f..eb70e2a 100644
--- a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModel.js
+++ b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModel.js
@@ -20,7 +20,7 @@
  * Created by onvelocity on 8/23/15.
  */
 
-import _ from 'lodash'
+import _isArray from 'lodash/isArray'
 import guid from '../guid'
 import Position from '../graph/Position'
 import IconFactory from './IconFactory'
@@ -279,7 +279,7 @@
 
 	updateModelList(modelFieldName, modelFieldValue, descriptorClass = DescriptorModel, newItemAddedSuccessCallback = () => {}) {
 		// value can be Array of (DescriptorModel | json model), DescriptorModel, or json model
-		if (_.isArray(modelFieldValue)) {
+		if (_isArray(modelFieldValue)) {
 			this.model[modelFieldName] = modelFieldValue.map(d => d instanceof descriptorClass ? d.model : d);
 			return true;
 		}
diff --git a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelFactory.js b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelFactory.js
index ac59872..6de5d21 100644
--- a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelFactory.js
+++ b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelFactory.js
@@ -21,7 +21,8 @@
 
 'use strict';
 
-import _ from 'lodash'
+import _isEmpty from 'lodash/isEmpty'
+import _cloneDeep from 'lodash/cloneDeep'
 import d3 from 'd3'
 import UID from './../UniqueId'
 import guid from '../guid'
@@ -157,7 +158,7 @@
 		}
 
 		return (containerList, obj) => {
-			if (_.isEmpty(obj)) {
+			if (_isEmpty(obj)) {
 				return containerList;
 			}
 			switch (obj.uiState.type) {
@@ -249,7 +250,7 @@
 		} else {
 			model = vnfdToWrap;
 		}
-		return new VirtualNetworkFunctionReadOnlyWrapper(_.cloneDeep(model), parent);
+		return new VirtualNetworkFunctionReadOnlyWrapper(_cloneDeep(model), parent);
 	}
 
 	static newClassifier(model, parent) {
diff --git a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelMetaFactory.js b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelMetaFactory.js
index d3ef200..164c850 100644
--- a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelMetaFactory.js
+++ b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelMetaFactory.js
@@ -6,7 +6,7 @@
 
 'use strict';
 
-import _ from 'lodash'
+import _cloneDeep from 'lodash/cloneDeep'
 import utils from './../utils'
 import DescriptorModelMetaProperty from './DescriptorModelMetaProperty'
 import CommonUtils from 'utils/utils';
@@ -72,7 +72,7 @@
 		// resolve paths like 'nsd' or 'vnfd.vdu' or 'nsd.constituent-vnfd'
 		const found = utils.resolvePath(modelMetaByPropertyNameMap, getPathForType(typeOrPath));
 		if (found) {
-			const uiState = _.cloneDeep(found[':meta']);
+			const uiState = _cloneDeep(found[':meta']);
 			uiState.properties = uiState.properties.filter(filterProperties);
 			return uiState;
 		}
diff --git a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelMetaProperty.js b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelMetaProperty.js
index 8fe51d9..4318c5b 100644
--- a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelMetaProperty.js
+++ b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelMetaProperty.js
@@ -23,7 +23,8 @@
 
 'use strict';
 
-import _ from 'lodash'
+import _includes from 'lodash/includes'
+import _isArray from 'lodash/isArray'
 import guid from './../guid'
 import changeCase from 'change-case'
 import InstanceCounter from './../InstanceCounter'
@@ -69,7 +70,7 @@
         return !/^(leaf|leaf_list)$/.test(property.type);
 	},
 	isSimpleList(property = {}) {
-		return _.includes(DescriptorModelFields.simpleList, property.name);
+		return _includes(DescriptorModelFields.simpleList, property.name);
 	},
 	isPrimativeDataType(property = {}) {
 		const Property = this;
@@ -155,7 +156,7 @@
 				if (uiState.name === 'name') {
 					return changeCase.param(parentMeta.name) + '-' + InstanceCounter.count(parentMeta[':qualified-type']);
 				}
-				if (_.isArray(parentMeta.key) && _.includes(parentMeta.key, uiState.name)) {
+				if (_isArray(parentMeta.key) && _includes(parentMeta.key, uiState.name)) {
 					if (/uuid/.test(uiState['data-type'])) {
 						return guid();
 					}
diff --git a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelSerializer.js b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelSerializer.js
index 8ce90cf..737078f 100644
--- a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelSerializer.js
+++ b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelSerializer.js
@@ -20,7 +20,11 @@
  * Created by onvelocity on 10/20/15.
  */
 
-import _ from 'lodash'
+import _isNumber from 'lodash/isNumber'
+import _cloneDeep from 'lodash/cloneDeep'
+import _isEmpty from 'lodash/isEmpty'
+import _omit from 'lodash/omit'
+import _pick from 'lodash/pick'
 import utils from './../utils'
 import DescriptorModelFields from './DescriptorModelFields'
 import DescriptorModelMetaFactory from './DescriptorModelMetaFactory'
@@ -54,7 +58,7 @@
 		// remove empty / blank value fields
 		function clean(m) {
 			Object.keys(m).forEach(k => {
-				const isEmptyObject = typeof m[k] === 'object' && _.isEmpty(m[k]);
+				const isEmptyObject = typeof m[k] === 'object' && _isEmpty(m[k]);
 				if (typeof m[k] === 'undefined' || isEmptyObject || m[k] === '') {
 					delete m[k];
 				}
@@ -62,8 +66,8 @@
 				if (k === 'uiState') {
 					if (isMetaAllowed) {
 						// remove any transient ui state properties
-						const uiState = _.pick(m.uiState, DescriptorModelFields.meta);
-						if (!_.isEmpty(uiState)) {
+						const uiState = _pick(m.uiState, DescriptorModelFields.meta);
+						if (!_isEmpty(uiState)) {
 							// uiState field must be a string
 							m['meta'] = JSON.stringify(uiState);
 						}
@@ -81,7 +85,7 @@
 	nsd: {
 		serialize(nsdModel) {
 			if(!nsdFields) nsdFields = DescriptorModelMetaFactory.getModelFieldNamesForType('nsd').concat('uiState');
-			const confd = _.pick(nsdModel, nsdFields);
+			const confd = _pick(nsdModel, nsdFields);
 
 			// vnfd is defined in the ETSI etsi_gs reference manual but RIFT does not use it
 			delete confd.vnfd;
@@ -95,13 +99,13 @@
 				};
 
 				if (d['vnf-configuration']) {
-					const vnfConfig = _.cloneDeep(d['vnf-configuration']);
+					const vnfConfig = _cloneDeep(d['vnf-configuration']);
 					const configType = vnfConfig['config-type'] || 'none';
 					// make sure we send the correct values based on config type
 					if (configType === 'none') {
 						constituentVNFD['vnf-configuration'] = {'config-type': 'none'};
 						const configPriority = utils.resolvePath(vnfConfig, 'input-params.config-priority');
-						const configPriorityValue = _.isNumber(configPriority) ? configPriority : d.uiState['member-vnf-index'];
+						const configPriorityValue = _isNumber(configPriority) ? configPriority : d.uiState['member-vnf-index'];
 						utils.assignPathValue(constituentVNFD['vnf-configuration'], 'input-params.config-priority', configPriorityValue);
 					} else {
 						// remove any unused configuration options
@@ -136,7 +140,7 @@
 	vld: {
 		serialize(vldModel) {
 			if(!vldFields) vldFields = DescriptorModelMetaFactory.getModelFieldNamesForType('nsd.vld');
-			const confd = _.pick(vldModel, vldFields);
+			const confd = _pick(vldModel, vldFields);
 			const property = 'vnfd-connection-point-ref';
 
 			// TODO: There is a bug in RIFT-REST that is not accepting empty
@@ -166,35 +170,35 @@
 	},
 	'vnfd-connection-point-ref': {
 		serialize(ref) {
-			return _.pick(ref, ['member-vnf-index-ref', 'vnfd-id-ref', 'vnfd-connection-point-ref']);
+			return _pick(ref, ['member-vnf-index-ref', 'vnfd-id-ref', 'vnfd-connection-point-ref']);
 		}
 	},
 	'internal-connection-point': {
 		serialize(ref) {
-			return _.pick(ref, ['id-ref']);
+			return _pick(ref, ['id-ref']);
 		}
 	},
 	'constituent-vnfd': {
 		serialize(cvnfdModel) {
 			if(!cvnfdFields) cvnfdFields = DescriptorModelMetaFactory.getModelFieldNamesForType('nsd.constituent-vnfd');
-			return _.pick(cvnfdModel, cvnfdFields);
+			return _pick(cvnfdModel, cvnfdFields);
 		}
 	},
 	vnfd: {
 		serialize(vnfdModel) {
 			if(!vnfdFields) vnfdFields = DescriptorModelMetaFactory.getModelFieldNamesForType('vnfd').concat('uiState');
-			const confd = _.pick(vnfdModel, vnfdFields);
+			const confd = _pick(vnfdModel, vnfdFields);
 			confd.vdu = confd.vdu.map(d => DescriptorModelSerializer.serialize(d));
 			return cleanEmptyTopKeys(confd);
 		}
 	},
 	vdu: {
 		serialize(vduModel) {
-			const copy = _.cloneDeep(vduModel);
+			const copy = _cloneDeep(vduModel);
 			for (let k in copy) {
 				checkForChoiceAndRemove(k, copy, vduModel)
 			}
-			const confd = _.omit(copy, ['uiState']);
+			const confd = _omit(copy, ['uiState']);
 			return cleanEmptyTopKeys(confd);
 		}
 	}
@@ -231,7 +235,7 @@
 
 function cleanEmptyTopKeys(m){
     Object.keys(m).forEach(k => {
-        const isEmptyObject = typeof m[k] === 'object' && _.isEmpty(m[k]);
+        const isEmptyObject = typeof m[k] === 'object' && _isEmpty(m[k]);
         if (typeof m[k] === 'undefined' || isEmptyObject || m[k] === '') {
             delete m[k];
         }
diff --git a/skyquake/plugins/composer/src/src/libraries/model/DescriptorTemplateFactory.js b/skyquake/plugins/composer/src/src/libraries/model/DescriptorTemplateFactory.js
index 28e7480..2946f18 100644
--- a/skyquake/plugins/composer/src/src/libraries/model/DescriptorTemplateFactory.js
+++ b/skyquake/plugins/composer/src/src/libraries/model/DescriptorTemplateFactory.js
@@ -23,7 +23,10 @@
 
 'use strict';
 
-import _ from 'lodash'
+import _isFunction from 'lodash/isFunction'
+import _isArray from 'lodash/isArray'
+import _isObject from 'lodash/isObject'
+import _cloneDeep from 'lodash/cloneDeep'
 import DescriptorTemplates from './DescriptorTemplates'
 import DescriptorModelMetaFactory from './DescriptorModelMetaFactory'
 
@@ -33,13 +36,13 @@
 	function init(m) {
 		keys(m).map(key => {
 			const value = m[key];
-			if (_.isFunction(value)) {
+			if (_isFunction(value)) {
 				m[key] = value(m, key, model);
 			}
-			if (_.isArray(value)) {
+			if (_isArray(value)) {
 				value.forEach(v => init(v));
 			}
-			if (_.isObject(value)) {
+			if (_isObject(value)) {
 				init(value);
 			}
 		});
@@ -52,7 +55,7 @@
 	createModelForType(type) {
 		const template = DescriptorTemplates[type];
 		if (template) {
-			const model = _.cloneDeep(template);
+			const model = _cloneDeep(template);
 			return resolveInitHandlers(model);
 		}
 	}
diff --git a/skyquake/plugins/composer/src/src/libraries/model/descriptors/ForwardingGraph.js b/skyquake/plugins/composer/src/src/libraries/model/descriptors/ForwardingGraph.js
index ef99af6..35b3077 100644
--- a/skyquake/plugins/composer/src/src/libraries/model/descriptors/ForwardingGraph.js
+++ b/skyquake/plugins/composer/src/src/libraries/model/descriptors/ForwardingGraph.js
@@ -21,7 +21,6 @@
 
 'use strict';
 
-import _ from 'lodash'
 import Classifier from './Classifier'
 import DescriptorModel from '../DescriptorModel'
 import RecordServicePath from './RecordServicePath'
diff --git a/skyquake/plugins/composer/src/src/libraries/model/descriptors/NetworkService.js b/skyquake/plugins/composer/src/src/libraries/model/descriptors/NetworkService.js
index 16fb159..17646aa 100644
--- a/skyquake/plugins/composer/src/src/libraries/model/descriptors/NetworkService.js
+++ b/skyquake/plugins/composer/src/src/libraries/model/descriptors/NetworkService.js
@@ -21,7 +21,6 @@
 
 'use strict';
 
-import _ from 'lodash'
 import ColorGroups from '../../ColorGroups'
 import DescriptorModel from '../DescriptorModel'
 import ForwardingGraph from './ForwardingGraph'
diff --git a/skyquake/plugins/composer/src/src/libraries/model/descriptors/RecordServicePath.js b/skyquake/plugins/composer/src/src/libraries/model/descriptors/RecordServicePath.js
index 8c43f10..7c2b631 100644
--- a/skyquake/plugins/composer/src/src/libraries/model/descriptors/RecordServicePath.js
+++ b/skyquake/plugins/composer/src/src/libraries/model/descriptors/RecordServicePath.js
@@ -21,7 +21,6 @@
 
 'use strict';
 
-import _ from 'lodash'
 import DescriptorModel from '../DescriptorModel'
 import RspConnectionPointRef from './RspConnectionPointRef'
 import DescriptorModelFactory from '../DescriptorModelFactory'
diff --git a/skyquake/plugins/composer/src/src/libraries/utils.js b/skyquake/plugins/composer/src/src/libraries/utils.js
index 75afab3..ef37a0b 100644
--- a/skyquake/plugins/composer/src/src/libraries/utils.js
+++ b/skyquake/plugins/composer/src/src/libraries/utils.js
@@ -18,7 +18,14 @@
 
 'use strict';
 
-import changeCase from 'change-case';
+import _cloneDeep from 'lodash/cloneDeep';
+import _isArray from 'lodash/isArray';
+import _map from 'lodash/map';
+import _flatten from 'lodash/flatten';
+import _find from 'lodash/find';
+import _toNumber from 'lodash/toNumber';
+import _isNumber from 'lodash/isNumber';
+import _clone from 'lodash/clone';
 
 export default {
 	addAuthorizationStub(xhr) {
@@ -133,22 +140,22 @@
 	},
 
 	getResults (topLevelObject, pathArray) {
-		let objectCopy = _.cloneDeep(topLevelObject);
+		let objectCopy = _cloneDeep(topLevelObject);
 		let i = pathArray.length;
 		let results = [];
 
 		while(pathArray[pathArray.length - i]) {
-			if (_.isArray(objectCopy[pathArray[pathArray.length - i]])) {
+			if (_isArray(objectCopy[pathArray[pathArray.length - i]])) {
 				if (i == 2) {
-					results = _.map(objectCopy[pathArray[pathArray.length - i]], pathArray[pathArray.length - 1]);
+					results = _map(objectCopy[pathArray[pathArray.length - i]], pathArray[pathArray.length - 1]);
 				} else {
 					objectCopy = objectCopy[pathArray[pathArray.length - i]];
 				}
-			} else if (_.isArray(objectCopy)) {
+			} else if (_isArray(objectCopy)) {
 				objectCopy.map((object) => {
-					if (_.isArray(object[pathArray[pathArray.length - i]])) {
+					if (_isArray(object[pathArray[pathArray.length - i]])) {
 						if (i == 2) {
-							results = results.concat(_.map(object[pathArray[pathArray.length - i]], pathArray[pathArray.length - 1]));
+							results = results.concat(_map(object[pathArray[pathArray.length - i]], pathArray[pathArray.length - 1]));
 						}
 					}
 				})
@@ -161,7 +168,7 @@
 
 	getAbsoluteResults (topLevelObject, pathArray) {
 		let i = pathArray.length;
-		let objectCopy = _.cloneDeep(topLevelObject);
+		let objectCopy = _cloneDeep(topLevelObject);
 		let results = [];
 
 		let fragment = pathArray[pathArray.length - i]
@@ -169,9 +176,9 @@
 		while (fragment) {
 			if (i == 1) {
 				// last fragment
-				if (_.isArray(objectCopy)) {
+				if (_isArray(objectCopy)) {
 					// results will be obtained from a map
-					results = _.map(objectCopy, fragment);
+					results = _map(objectCopy, fragment);
 				} else {
 					// object
 					if (fragment.match(/\[.*\]/g)) {
@@ -184,16 +191,16 @@
 					}
 				}
 			} else {
-				if (_.isArray(objectCopy)) {
+				if (_isArray(objectCopy)) {
 					// is array
-					objectCopy = _.map(objectCopy, fragment);
+					objectCopy = _map(objectCopy, fragment);
 
 					// If any of the deeper object is an array, flatten the entire list.
 					// This would usually be a bad leafref going out of its scope.
 					// Log it too
 					for (let i = 0; i < objectCopy.length; i++) {
-						if (_.isArray(objectCopy[i])) {
-							objectCopy = _.flatten(objectCopy);
+						if (_isArray(objectCopy[i])) {
+							objectCopy = _flatten(objectCopy);
 							console.log('This might be a bad leafref. Verify with backend team.')
 							break;
 						}
@@ -212,7 +219,7 @@
 						let key = fragment.split('[')[0];
 						let searchObject = {};
 						searchObject[predicateKey] = predicateValue;
-						let found = _.find(objectCopy[key], searchObject);
+						let found = _find(objectCopy[key], searchObject);
 						if (found) {
 							objectCopy = found;
 						} else {
@@ -222,10 +229,10 @@
 								predicateValue != NaN &&
 								predicateValue != Infinity &&
 								predicateValue != -Infinity) {
-								let numericalPredicateValue = _.toNumber(predicateValue);
-								if (_.isNumber(numericalPredicateValue)) {
+								let numericalPredicateValue = _toNumber(predicateValue);
+								if (_isNumber(numericalPredicateValue)) {
 									searchObject[predicateKey] = numericalPredicateValue;
-									found = _.find(objectCopy[key], searchObject);
+									found = _find(objectCopy[key], searchObject);
 								}
 							}
 							if (found) {
@@ -277,7 +284,7 @@
 	},
 
 	resolveLeafRefPath (catalogs, leafRefPath, fieldKey, path, container) {
-		let pathCopy = _.clone(path);
+		let pathCopy = _clone(path);
 		// Strip any prefixes
 		let leafRefPathCopy = leafRefPath.replace(/[\w\d]*:/g, '');
 		// Strip any spaces
@@ -310,7 +317,7 @@
 			if (fieldKeyArray.length == 1) {
 				for (let key in catalogs) {
 					for (let subKey in catalogs[key]) {
-						let found = _.find(catalogs[key][subKey], {id: fieldKeyArray[0]});
+						let found = _find(catalogs[key][subKey], {id: fieldKeyArray[0]});
 						if (found) {
 							results = this.getAbsoluteResults(found, pathArray.splice(-i, i));
 							return results;
@@ -320,10 +327,10 @@
 			} else if (fieldKeyArray.length == 2) {
 				for (let key in catalogs) {
 					for (let subKey in catalogs[key]) {
-						let found = _.find(catalogs[key][subKey], {id: fieldKeyArray[0]});
+						let found = _find(catalogs[key][subKey], {id: fieldKeyArray[0]});
 						if (found) {
 							for (let foundKey in found) {
-								// let topLevel = _.find(found[foundKey], {id: fieldKeyArray[1]});
+								// let topLevel = _find(found[foundKey], {id: fieldKeyArray[1]});
 								if (foundKey == fieldKeyArray[1]) {
 									results = this.getAbsoluteResults(found[foundKey], pathArray.splice(-i, i));
 									return results;
diff --git a/skyquake/plugins/composer/src/src/sources/CatalogDataSource.js b/skyquake/plugins/composer/src/src/sources/CatalogDataSource.js
index e742a9e..9c297ca 100644
--- a/skyquake/plugins/composer/src/src/sources/CatalogDataSource.js
+++ b/skyquake/plugins/composer/src/src/sources/CatalogDataSource.js
@@ -18,7 +18,6 @@
  */
 'use strict';
 
-import _ from 'lodash'
 import $ from 'jquery'
 import alt from '../alt'
 import utils from '../libraries/utils'
diff --git a/skyquake/plugins/composer/src/src/stores/CatalogDataStore.js b/skyquake/plugins/composer/src/src/stores/CatalogDataStore.js
index 1098f0e..afc5009 100644
--- a/skyquake/plugins/composer/src/src/stores/CatalogDataStore.js
+++ b/skyquake/plugins/composer/src/src/stores/CatalogDataStore.js
@@ -18,7 +18,9 @@
  */
 'use strict';
 
-import _ from 'lodash'
+import _pick from 'lodash/pick'
+import _isEqual from 'lodash/isEqual'
+import _cloneDeep from 'lodash/cloneDeep'
 import cc from 'change-case'
 import alt from '../alt'
 import UID from '../libraries/UniqueId'
@@ -44,9 +46,9 @@
 
 const areCatalogItemsMetaDataEqual = function (a, b) {
 	const metaProps = ['id', 'name', 'short-name', 'description', 'vendor', 'version'];
-	const aMetaData = _.pick(a, metaProps);
-	const bMetaData = _.pick(b, metaProps);
-	return _.isEqual(aMetaData, bMetaData);
+	const aMetaData = _pick(a, metaProps);
+	const bMetaData = _pick(b, metaProps);
+	return _isEqual(aMetaData, bMetaData);
 };
 
 function createItem (type) {
@@ -201,7 +203,7 @@
 							vnfd.uiState['instance-ref-count'] = instanceRefCount;
 						}
 						// create an instance of this vnfd to carry transient ui state properties
-						const instance = _.cloneDeep(vnfd);
+						const instance = _cloneDeep(vnfd);
 						instance.uiState['member-vnf-index'] = d['member-vnf-index'];
 						instance['vnf-configuration'] = d['vnf-configuration'];
 						instance['start-by-default'] = d['start-by-default'];
@@ -323,7 +325,7 @@
 								ComposerAppActions.showError.defer({
 									errorMessage: 'Cannot edit NSD/VNFD with references to instantiated Network Services'
 								});
-								return _.cloneDeep(d);
+								return _cloneDeep(d);
 							} else {
 								item.uiState.modified = modified;
 								requiresSave = true;
@@ -357,7 +359,7 @@
 							ComposerAppActions.showError.defer({
 								errorMessage: 'Cannot edit NSD/VNFD with references to instantiated Network Services'
 							});
-							return _.cloneDeep(d);
+							return _cloneDeep(d);
 						} else {
 							itemDescriptor.model.uiState.modified = true;
 							this.addSnapshot(itemDescriptor.model);
@@ -461,7 +463,7 @@
 	duplicateSelectedCatalogItem() {
 		const item = this.getFirstSelectedCatalogItem();
 		if (item) {
-			const newItem = _.cloneDeep(item);
+			const newItem = _cloneDeep(item);
 			newItem.name = newItem.name + ' Copy';
 			newItem.id = guid();
 			UID.assignUniqueId(newItem.uiState);
diff --git a/skyquake/plugins/composer/src/src/stores/CatalogPackageManagerStore.js b/skyquake/plugins/composer/src/src/stores/CatalogPackageManagerStore.js
index 3a82114..ac7ee1f 100644
--- a/skyquake/plugins/composer/src/src/stores/CatalogPackageManagerStore.js
+++ b/skyquake/plugins/composer/src/src/stores/CatalogPackageManagerStore.js
@@ -18,7 +18,8 @@
  */
 'use strict';
 
-import _ from 'lodash'
+import _delay from 'lodash/delay'
+import _pick from 'lodash/pick'
 import alt from '../alt'
 import guid from '../libraries/guid'
 import numeral from 'numeral'
@@ -65,7 +66,7 @@
 			delete catalogPackage.checkStatusTimeoutId;
 			statusCheckFunction(catalogPackage).catch(exception);
 		};
-		catalogPackage.checkStatusTimeoutId = _.delay(delayCallback, defaults.checkStatusDelayInSeconds * 1000);
+		catalogPackage.checkStatusTimeoutId = _delay(delayCallback, defaults.checkStatusDelayInSeconds * 1000);
 	}
 }
 
@@ -109,7 +110,7 @@
 
 	uploadCatalogPackage(file) {
 		file.id = file.id || guid();
-		const catalogPackage = _.pick(file, packagePropertyNames);
+		const catalogPackage = _pick(file, packagePropertyNames);
 		catalogPackage.icon = file.riftAction === 'onboard' ? imgOnboard : imgUpdate;
 		catalogPackage.type = 'upload';
 		this.addPackage(catalogPackage);
diff --git a/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js b/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js
index 97813ea..b23db5c 100644
--- a/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js
+++ b/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js
@@ -18,7 +18,14 @@
  */
 'use strict';
 
-import _ from 'lodash'
+import _isNumber from 'lodash/isNumber'
+import _cloneDeep from 'lodash/cloneDeep'
+import _isEmpty from 'lodash/isEmpty'
+import _mergeWith from 'lodash/mergeWith'
+import _uniqBy from 'lodash/uniqBy'
+import _isEqual from 'lodash/isEqual'
+import _findIndex from 'lodash/findIndex'
+import _remove from 'lodash/remove'
 import d3 from 'd3'
 import alt from '../alt'
 import UID from '../libraries/UniqueId'
@@ -56,7 +63,7 @@
 const getDefault = (name, defaultValue) => {
 	const val = window.localStorage.getItem('defaults-' + name);
 	if (val) {
-		if (_.isNumber(val)) {
+		if (_isNumber(val)) {
 			if (val < 0) {
 				return setDefault(name, 0);
 			}
@@ -218,7 +225,7 @@
 				d.cpNumber = ++cpNumber;
 				containers.filter(d => DescriptorModelFactory.isVnfdConnectionPointRef(d)).filter(ref => ref.key === d.key).forEach(ref => ref.cpNumber = d.cpNumber);
 			});
-			this.setState({containers: containers, item: _.cloneDeep(item)});
+			this.setState({containers: containers, item: _cloneDeep(item)});
 		}
 		SelectionManager.refreshOutline();
 	}
@@ -267,7 +274,7 @@
 
 	applyDefaultLayout() {
 		if (this.item && this.item.uiState && this.item.uiState.containerPositionMap) {
-			if (!_.isEmpty(this.item.uiState.containerPositionMap)) {
+			if (!_isEmpty(this.item.uiState.containerPositionMap)) {
 				this.item.uiState.containerPositionMap = {};
 				CatalogItemsActions.catalogItemMetaDataChanged.defer(this.item);
 			}
@@ -410,7 +417,7 @@
 
 			if (isFullScreen()) {
 				const layout = comp.layout;
-				const restoreLayout = _.cloneDeep(layout);
+				const restoreLayout = _cloneDeep(layout);
 				uiTransientState.restoreLayout = restoreLayout;
 				layout.left = 0;
 				layout.right = 0;
@@ -475,13 +482,12 @@
         if (self.fileMonitoringSocketID) {
         	let newState = {};
         	if(data.hasOwnProperty('contents')) {
-        		filesState = addInputState( _.cloneDeep(this.filesState),data);
-				// filesState = _.merge(self.filesState, addInputState({},data));
+        		filesState = addInputState( _cloneDeep(this.filesState),data);
 				let normalizedData = normalizeTree(data);
 				newState = {
 					files: {
-						data: _.mergeWith(normalizedData.data, self.files.data, function(obj, src) {
-							return _.uniqBy(obj? obj.concat(src) : src, 'name');
+						data: _mergeWith(normalizedData.data, self.files.data, function(obj, src) {
+							return _uniqBy(obj? obj.concat(src) : src, 'name');
 						}),
 						id: normalizedData.id
 					},
@@ -492,7 +498,7 @@
         			files: false
         		}
         	}
-        	if(!_.isEqual(newState.files, this.files) || ! _.isEqual(newState.fileState, this.fileState)) {
+        	if(!_isEqual(newState.files, this.files) || ! _isEqual(newState.fileState, this.fileState)) {
         		this.setState(newState);
         	}
 
@@ -540,7 +546,7 @@
 	updateFileLocationInput = (data) => {
 		let name = data.name;
 		let value = data.value;
-		var filesState = _.cloneDeep(this.filesState);
+		var filesState = _cloneDeep(this.filesState);
 		filesState[name] = value;
 		this.setState({
 			filesState: filesState
@@ -550,7 +556,7 @@
 		if(!data.refresh) {
 			let path = data.path;
 			let fileName = data.fileName;
-			let files = _.cloneDeep(this.files);
+			let files = _cloneDeep(this.files);
 			let loadingIndex = files.data[path].push({
 				status: 'DOWNLOADING',
 				name: path + '/' + fileName
@@ -568,7 +574,7 @@
 	openDownloadMonitoringSocketSuccess = (id) => {
 		let self = this;
 		let ws = window.multiplexer.channel(id);
-		let downloadJobs = _.cloneDeep(self.downloadJobs);
+		let downloadJobs = _cloneDeep(self.downloadJobs);
 		let newFiles = false;
 		ws.onmessage = (socket) => {
             if (self.files && self.files.length > 0) {
@@ -576,14 +582,14 @@
                 try {
                     jobs = JSON.parse(socket.data);
                 } catch(e) {}
-                newFiles = _.cloneDeep(self.files);
+                newFiles = _cloneDeep(self.files);
                 jobs.map(function(j) {
                     //check if not in completed state
                     let fullPath = j['package-path'];
                     let path = fullPath.split('/');
                     let fileName = path.pop();
                     path = path.join('/');
-                    let index = _.findIndex(self.files.data[path], function(o){
+                    let index = _findIndex(self.files.data[path], function(o){
                         return fullPath == o.name
                     });
                     if((index > -1) && newFiles.data[path][index]) {
@@ -661,11 +667,11 @@
 	}
 	deleteFileSuccess = (data) => {
 		let path = data.path.split('/')
-		let files = _.cloneDeep(this.files);
+		let files = _cloneDeep(this.files);
 		path.pop();
 		path = path.join('/');
 		let pathFiles = files.data[path]
-		_.remove(pathFiles, function(c) {
+		_remove(pathFiles, function(c) {
 			return c.name == data.path;
 		});
 
diff --git a/skyquake/plugins/composer/test/spec/libraries/DescriptorModelFactorySpec.js b/skyquake/plugins/composer/test/spec/libraries/DescriptorModelFactorySpec.js
index 66376b9..eff8962 100644
--- a/skyquake/plugins/composer/test/spec/libraries/DescriptorModelFactorySpec.js
+++ b/skyquake/plugins/composer/test/spec/libraries/DescriptorModelFactorySpec.js
@@ -21,7 +21,7 @@
 /*global describe, beforeEach, it, expect, xit, xdescribe */
 
 'use strict';
-import _ from 'lodash'
+import _cloneDeep from 'lodash/cloneDeep'
 import DescriptorModelSerializer from '../../../src/libraries/model/DescriptorModelSerializer'
 import DescriptorModelFactory from '../../../src/libraries/model/DescriptorModelFactory'
 import SampleCatalogs from 'json!../../../src/assets/ping-pong-catalog.json'
@@ -34,7 +34,7 @@
 	describe('buildCatalogItemFactory', () => {
 		let containers;
 		beforeEach(() => {
-			const nsdJson = _.cloneDeep(SampleCatalogs[0].descriptors[0]);
+			const nsdJson = _cloneDeep(SampleCatalogs[0].descriptors[0]);
 			// the CatalogItemsStore adds the type to the uiState field when the catalog is loaded
 			nsdJson.uiState = {type: 'nsd'};
 			// the user will open a catalog item by dbl clicking on it in the ui that is when we
@@ -49,7 +49,7 @@
 			expect(result).toEqual([]);
 		});
 		it('parses an NSD object', () => {
-			const nsdJson = _.cloneDeep(SampleCatalogs[0].descriptors[0]);
+			const nsdJson = _cloneDeep(SampleCatalogs[0].descriptors[0]);
 			nsdJson.uiState = {type: 'nsd'};
 			const factory = DescriptorModelFactory.buildCatalogItemFactory(SampleCatalogs);
 			const result = [nsdJson].reduce(factory, [])[0];
@@ -68,7 +68,7 @@
 		});
 		describe('DescriptorModelSerializer', () => {
 			it('outputs the same JSON that was parsed by the .buildCatalogItemFactory method', () => {
-				const inputJSON = _.cloneDeep(TestCatalogs[0].descriptors[0]);
+				const inputJSON = _cloneDeep(TestCatalogs[0].descriptors[0]);
 				inputJSON.uiState = {type: 'nsd'};
 				const factory = DescriptorModelFactory.buildCatalogItemFactory(TestCatalogs);
 				const parsedModel = [inputJSON].reduce(factory, []);
diff --git a/skyquake/plugins/composer/test/spec/libraries/DescriptorModelSpec.js b/skyquake/plugins/composer/test/spec/libraries/DescriptorModelSpec.js
index 5388780..b65e2e7 100644
--- a/skyquake/plugins/composer/test/spec/libraries/DescriptorModelSpec.js
+++ b/skyquake/plugins/composer/test/spec/libraries/DescriptorModelSpec.js
@@ -21,7 +21,6 @@
 /*global describe, beforeEach, it, expect, xit */
 
 'use strict';
-import _ from 'lodash'
 import DescriptorModel from 'libraries/model/DescriptorModel'
 
 class TestDescriptorModel extends DescriptorModel {
diff --git a/skyquake/plugins/config/src/dashboard/inputs.jsx b/skyquake/plugins/config/src/dashboard/inputs.jsx
index 457a08e..1636f4c 100644
--- a/skyquake/plugins/config/src/dashboard/inputs.jsx
+++ b/skyquake/plugins/config/src/dashboard/inputs.jsx
@@ -4,7 +4,7 @@
 
 import React from 'react';
 import Button from 'widgets/button/rw.button.js';
-import _ from 'lodash';
+import _cloneDeep from 'lodash/cloneDeep';
 import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
 import Crouton from 'react-crouton';
 import TextInput from 'widgets/form_controls/textInput.jsx';
@@ -79,7 +79,7 @@
             }
         }
 
-        let newAccount = _.cloneDeep(removeTrailingWhitespace(Account));
+        let newAccount = _cloneDeep(removeTrailingWhitespace(Account));
         delete newAccount.params;
         newAccount.nestedParams &&
             newAccount.nestedParams['container-name'] &&
diff --git a/skyquake/plugins/launchpad/src/instantiate/instantiateStore.js b/skyquake/plugins/launchpad/src/instantiate/instantiateStore.js
index 01c624d..3ec2a80 100644
--- a/skyquake/plugins/launchpad/src/instantiate/instantiateStore.js
+++ b/skyquake/plugins/launchpad/src/instantiate/instantiateStore.js
@@ -20,7 +20,8 @@
 import GUID from 'utils/guid.js';
 import AppHeaderActions from 'widgets/header/headerActions.js';
 import Alt from '../alt';
-import _ from 'lodash';
+import _cloneDeep from 'lodash/cloneDeep';
+import _find from 'lodash/find';
 
 
 class LaunchNetworkServiceStore {
@@ -640,7 +641,7 @@
             },
             updateSSHkeyRef: function(i, j, remove){
                 return function(e) {
-                    let usersList = _.cloneDeep(self.usersList)
+                    let usersList = _cloneDeep(self.usersList)
                     let keys = usersList[i]['ssh-authorized-key'];
                     if(!remove) {
                         let keyRef = JSON.parse(e.target.value).name;
@@ -672,7 +673,7 @@
 
         // Create a filtered NSD payload from the decorated one as RW.REST cannot handle extra parameters now
         let nsdPayload = {};
-        nsdPayload = _.cloneDeep(_.find(this.state.nsd[0].descriptors, {id: this.state.selectedNSDid}));
+        nsdPayload = _cloneDeep(_find(this.state.nsd[0].descriptors, {id: this.state.selectedNSDid}));
 
         if (nsdPayload != {}) {
             nsdPayload['meta'] && delete nsdPayload['meta'];
diff --git a/skyquake/plugins/launchpad/src/launchpad.jsx b/skyquake/plugins/launchpad/src/launchpad.jsx
index 1643926..759c7d6 100644
--- a/skyquake/plugins/launchpad/src/launchpad.jsx
+++ b/skyquake/plugins/launchpad/src/launchpad.jsx
@@ -25,7 +25,6 @@
 import NsListPanel from './nsListPanel/nsListPanel.jsx';
 import Crouton from 'react-crouton'
 import AppHeader from 'widgets/header/header.jsx';
-import Utils from 'utils/utils.js';
 import './launchpad.scss';
 let ReactCSSTransitionGroup = require('react-addons-css-transition-group');
 var LaunchpadFleetActions = require('./launchpadFleetActions.js');
diff --git a/skyquake/plugins/launchpad/src/launchpadFleetStore.js b/skyquake/plugins/launchpad/src/launchpadFleetStore.js
index a4b622b..69255a4 100644
--- a/skyquake/plugins/launchpad/src/launchpadFleetStore.js
+++ b/skyquake/plugins/launchpad/src/launchpadFleetStore.js
@@ -17,7 +17,9 @@
  *
  */
 import Alt from './alt';
-
+import _filter from 'lodash/filter';
+import _extend from 'lodash/extend';
+import _debounce from 'lodash/debounce';
 var FleetSource = require('./launchpadFleetSource.js');
 var FleetActions = require('./launchpadFleetActions.js');
 import CardActions from './launchpad_card/launchpadCardActions.js';
@@ -29,8 +31,6 @@
 
 
 var FleetStore;
-var _ = require('underscore');
-//  _.debounce(function(){});
 function FleetStoreConstructor() {
   var self = this;
   this.fleets = [];
@@ -134,7 +134,7 @@
       let deletingNSRs = [];
 
       if (self.nsrs) {
-        deletingNSRs = _.filter(self.nsrs, function(nsr) {
+        deletingNSRs = _filter(self.nsrs, function(nsr) {
           return nsr.deleting == true;
         });
       };
@@ -142,7 +142,7 @@
       deletingNSRs.forEach(function(deletingNSR) {
         data.nsrs.map(nsr => {
           if (nsr.id == deletingNSR.id) {
-            _.extend(nsr, deletingNSR);
+            _extend(nsr, deletingNSR);
           }
         });
       });
@@ -191,7 +191,7 @@
 FleetStoreConstructor.prototype.getNsrInstancesError = function(data) {
   console.log('ERROR', data)
 };
-FleetStoreConstructor.prototype.handleUpdateControlInput = _.debounce(function(data) {
+FleetStoreConstructor.prototype.handleUpdateControlInput = _debounce(function(data) {
   var opt = data[0];
   FleetStore.nsrControl(opt.operation, opt.url, data[1])
 }, 500).bind(null);
diff --git a/skyquake/plugins/launchpad/src/launchpad_card/nsrScalingGroups.jsx b/skyquake/plugins/launchpad/src/launchpad_card/nsrScalingGroups.jsx
index b6abf5c..be8d4eb 100644
--- a/skyquake/plugins/launchpad/src/launchpad_card/nsrScalingGroups.jsx
+++ b/skyquake/plugins/launchpad/src/launchpad_card/nsrScalingGroups.jsx
@@ -19,7 +19,6 @@
 import RecordViewStore from '../recordViewer/recordViewStore.js';
 import Button from 'widgets/button/rw.button.js';
 import Utils from 'utils/utils.js';
-import _ from 'underscore';
 import UpTime from 'widgets/uptime/uptime.jsx';
 import './nsrScalingGroups.scss';
 
diff --git a/skyquake/plugins/launchpad/src/recordViewer/recordCard.jsx b/skyquake/plugins/launchpad/src/recordViewer/recordCard.jsx
index 7051aeb..ea3eb2f 100644
--- a/skyquake/plugins/launchpad/src/recordViewer/recordCard.jsx
+++ b/skyquake/plugins/launchpad/src/recordViewer/recordCard.jsx
@@ -32,7 +32,7 @@
 import JobListCard from '../launchpad_card/jobListCard.jsx';
 import NSVirtualLinks from '../virtual_links/nsVirtualLinks.jsx';
 import LaunchpadFleetStore from '../launchpadFleetStore.js';
-
+import _forEach from 'lodash/forEach';
 import Prism from 'prismjs';
 import 'prismjs/themes/prism.css';
 
@@ -142,7 +142,7 @@
                 //     </pre>
                 function buildProperties(obj) {
                   let p = [];
-                    _.forEach(obj, function(v, k) {
+                    _forEach(obj, function(v, k) {
                     p.push(
                       <div style={{margin: '0.5rem 0.5rem'}} key={k + '-' + vi}>
                         <div style={{margin: '0 0.5rem',
diff --git a/skyquake/plugins/launchpad/src/recordViewer/recordViewStore.js b/skyquake/plugins/launchpad/src/recordViewer/recordViewStore.js
index 4a5b49c..72609e4 100644
--- a/skyquake/plugins/launchpad/src/recordViewer/recordViewStore.js
+++ b/skyquake/plugins/launchpad/src/recordViewer/recordViewStore.js
@@ -20,7 +20,9 @@
 // import source
 // import AppHeaderActions from 'widgets/header/headerActions.js';
 import Alt from '../alt';
-import _ from 'underscore';
+import _find from 'lodash/find';
+import _indexOf from 'lodash/indexOf';
+import _extend from 'lodash/extend';
 
 class RecordViewStore {
     constructor() {
@@ -429,7 +431,7 @@
 
                     sgInstance['vnfrs'] && sgInstance['vnfrs'].map((vnfr, vnfrIndex) => {
                         scaledVnfrs.push(vnfr);
-                        let vnfrObj = _.findWhere(nsrs.vnfrs, {id: vnfr});
+                        let vnfrObj = _find(nsrs.vnfrs, {id: vnfr});
                         scaledVnfNav.vnfr.push({
                             name: vnfrObj['short-name'],
                             id: vnfr,
@@ -444,7 +446,7 @@
 
             // Non-scaled VNFRs
             nsrs.vnfrs.map(function(vnfr, vnfrIndex) {
-                if (_.indexOf(scaledVnfrs, vnfr.id) == -1) {
+                if (_indexOf(scaledVnfrs, vnfr.id) == -1) {
                     nav.push({
                         name: vnfr["short-name"],
                         id: vnfr.id,
@@ -461,7 +463,7 @@
             };
         }
 
-        navigatorState = _.extend(navigatorState, {
+        navigatorState = _extend(navigatorState, {
             recordData: recordData,
             recordType: type,
             cardLoading: false,
diff --git a/skyquake/plugins/launchpad/src/ssh_keys/sshKeyStore.js b/skyquake/plugins/launchpad/src/ssh_keys/sshKeyStore.js
index 7ae421b..c62a1b4 100644
--- a/skyquake/plugins/launchpad/src/ssh_keys/sshKeyStore.js
+++ b/skyquake/plugins/launchpad/src/ssh_keys/sshKeyStore.js
@@ -20,7 +20,8 @@
 import GUID from 'utils/guid.js';
 import AppHeaderActions from 'widgets/header/headerActions.js';
 import Alt from '../alt';
-import _ from 'lodash';
+import _cloneDeep from 'lodash/cloneDeep';
+import _merge from 'lodash/merge';
 
 
 export default class SshKeyStore {
@@ -29,7 +30,7 @@
             keys: [],
             entities: {}
         };
-        this.dataCache = _.cloneDeep(this.data);
+        this.dataCache = _cloneDeep(this.data);
         this.newKey = {
           name: '',
           key: ''
@@ -67,7 +68,7 @@
     cancelEditSshKeyPair = (k) => {
         let self = this;
         return function(e) {
-            let data = _.cloneDeep(self.data);
+            let data = _cloneDeep(self.data);
             data.entities[k].key = self.dataCache.entities[k].key;
             data.entities[k].isEditable = false;
             self.setState({data:data});
@@ -106,7 +107,7 @@
             isEditable: false
         };
         this.setState({
-            dataCache: _.cloneDeep(keys),
+            dataCache: _cloneDeep(keys),
             data: keys,
             newKey: {
               name: '',
@@ -122,7 +123,7 @@
             isEditable: false
         };
         this.setState({
-            dataCache: _.cloneDeep(keys),
+            dataCache: _cloneDeep(keys),
             data: keys,
             newKey: {
               name: '',
@@ -135,7 +136,7 @@
         keys.keys.splice(keys.keys.indexOf(data.name), 1);
         delete keys.entities[data.name];
         this.setState({
-            dataCache: _.cloneDeep(keys),
+            dataCache: _cloneDeep(keys),
             data: keys
         })
     }
@@ -146,7 +147,7 @@
         let flattened = this.flattenKeys(data);
         this.setState({
             data: flattened,
-            dataCache: _.cloneDeep(flattened)
+            dataCache: _cloneDeep(flattened)
         })
     }
     updateSshKeyPair = (k, field) => {
@@ -166,7 +167,7 @@
         };
         data && data.map(function(d){
             fd.keys.push(d.name);
-            fd.entities[d.name] = _.merge({isEditable: false}, d)
+            fd.entities[d.name] = _merge({isEditable: false}, d)
         });
         return fd;
     }
diff --git a/skyquake/plugins/launchpad/src/topologyL2View/detailView.jsx b/skyquake/plugins/launchpad/src/topologyL2View/detailView.jsx
index 9436671..459f4af 100644
--- a/skyquake/plugins/launchpad/src/topologyL2View/detailView.jsx
+++ b/skyquake/plugins/launchpad/src/topologyL2View/detailView.jsx
@@ -20,7 +20,7 @@
 import DashboardCard from 'widgets/dashboard_card/dashboard_card.jsx';
 import Listy from 'widgets/listy/listy.js';
 
-import _ from 'underscore';
+import _isEmpty from 'lodash/isEmpty';
 
 export default class TopologyDetail extends React.Component {
     constructor(props) {
@@ -28,7 +28,7 @@
     }
 
     detailData(data) {
-        if (_.isEmpty(data)) {
+        if (_isEmpty(data)) {
             return {};
         } else {
             return {
diff --git a/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkCreate.jsx b/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkCreate.jsx
index dcd0f5b..bec414e 100644
--- a/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkCreate.jsx
+++ b/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkCreate.jsx
@@ -17,7 +17,6 @@
  */
 import React from 'react';
 import Utils from 'utils/utils.js';
-import _ from 'lodash';
 import './nsVirtualLinks.scss';
 import NSVirtualLinkCreateStore from './nsVirtualLinkCreateStore.js';
 import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
diff --git a/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkCreateStore.js b/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkCreateStore.js
index dbd7f58..ac050e4 100644
--- a/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkCreateStore.js
+++ b/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkCreateStore.js
@@ -18,7 +18,9 @@
 import NSVirtualLinkCreateActions from './nsVirtualLinkCreateActions.js';
 import NSVirtualLinkCreateSource from './nsVirtualLinkCreateSource.js';
 import Alt from '../alt';
-import _ from 'lodash';
+import _cloneDeep from 'lodash/cloneDeep';
+import _pickBy from 'lodash/pickBy';
+import _identity from 'lodash/identity';
 
 class NSVirtualLinkCreateStore {
 	constructor() {
@@ -141,7 +143,7 @@
 	}
 
 	updateFirstLevelKey = (key, e) => {
-		let vld = _.cloneDeep(this.vld);
+		let vld = _cloneDeep(this.vld);
 		let value = e.target.nodeName == "SELECT" ? JSON.parse(e.target.value) : e.target.value;
 		vld[key] = value;
 		this.setState({
@@ -150,7 +152,7 @@
 	}
 
 	updateSecondLevelKey = (firstLevelKey, secondLevelKey, e) => {
-		let vld = _.cloneDeep(this.vld);
+		let vld = _cloneDeep(this.vld);
 		if (!vld[firstLevelKey]) {
 			vld[firstLevelKey] = {};
 		}
@@ -176,7 +178,7 @@
 	}
 
 	updateVLDInitParamsValue = (currentVLDInitParamsType, e) => {
-		let vld = _.cloneDeep(this.vld);
+		let vld = _cloneDeep(this.vld);
 		this.vldInitParamsTypes.map((vldInitParamType) => {
 			if (currentVLDInitParamsType == vldInitParamType) {
 				let value = e.target.nodeName == "SELECT" ? JSON.parse(e.target.value) : e.target.value;
@@ -192,7 +194,7 @@
 	}
 
 	updateFirstLevelListKeyChange = (listName, index, keyName, e) => {
-		let vld = _.cloneDeep(this.vld);
+		let vld = _cloneDeep(this.vld);
 		
 
 		!vld[listName] && (vld[listName] = []);
@@ -207,7 +209,7 @@
 	addConnectionPointRef = () => {
 		let vld = {};
 		if (this.vld) {
-			vld = _.cloneDeep(this.vld);
+			vld = _cloneDeep(this.vld);
 			if (!vld['vnfd-connection-point-ref']) {
 				vld['vnfd-connection-point-ref'] = [];
 			}
@@ -224,7 +226,7 @@
 	}
 
 	removeConnectionPointRef = (vnfdConnectionPointRefIndex) => {
-		let vld = _.cloneDeep(this.vld);
+		let vld = _cloneDeep(this.vld);
 		vld['vnfd-connection-point-ref'].splice(vnfdConnectionPointRefIndex, 1);
 		this.setState({
 			vld: vld
@@ -258,7 +260,7 @@
 
 	cleanupPayload = (mode, vld) => {
 		// Do necessary cleanup here
-		let cleanVld = _.pickBy(vld, _.identity);
+		let cleanVld = _pickBy(vld, _identity);
 		return cleanVld;
 	}
 
diff --git a/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkDetails.jsx b/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkDetails.jsx
index 33404e0..c6a45e7 100644
--- a/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkDetails.jsx
+++ b/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinkDetails.jsx
@@ -18,7 +18,7 @@
 import React from 'react';
 import RecordViewStore from '../recordViewer/recordViewStore.js';
 import Utils from 'utils/utils.js';
-import _ from 'lodash';
+import _isArray from 'lodash/isArray';
 import './nsVirtualLinks.scss';
 import UpTime from 'widgets/uptime/uptime.jsx';
 import NSVirtualLinksStore from './nsVirtualLinksStore.js';
@@ -64,7 +64,7 @@
 				let value = this.resolvePath(this.props.virtualLink, field.key);
 				let textFields = [];
 
-				if (_.isArray(value)) {
+				if (_isArray(value)) {
 					value.map((v, idx) => {
 						let transformedValue = this.transformValue(field, v);
 						textFields.push(
diff --git a/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinks.jsx b/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinks.jsx
index 2f5b15b..37cf0b3 100644
--- a/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinks.jsx
+++ b/skyquake/plugins/launchpad/src/virtual_links/nsVirtualLinks.jsx
@@ -19,7 +19,7 @@
 import NSVirtualLinkCreateStore from './nsVirtualLinkCreateStore.js';
 import Button from 'widgets/button/rw.button.js';
 import Utils from 'utils/utils.js';
-import _ from 'lodash';
+import _find from 'lodash/find';
 import './nsVirtualLinks.scss';
 import UpTime from 'widgets/uptime/uptime.jsx';
 import NSVirtualLinkDetails from './nsVirtualLinkDetails.jsx';
@@ -114,7 +114,7 @@
 	handleSelectVirtualLinkClick = (virtualLinkId, event) => {
 		this.setState({
 			mode: 'viewing',
-			selectedVirtualLink: this.props.data && this.props.data['decorated-vlrs'] && _.find(this.props.data['decorated-vlrs'], {id: virtualLinkId}),
+			selectedVirtualLink: this.props.data && this.props.data['decorated-vlrs'] && _find(this.props.data['decorated-vlrs'], {id: virtualLinkId}),
 			editingVirtualLink: null
 		});
 	}
@@ -122,8 +122,8 @@
 		event.stopPropagation();
 		this.setState({
 			mode: 'editing',
-			editingVirtualLink: this.props.data && this.props.data['nsd'] && this.props.data['nsd']['vld'] && _.find(this.props.data['nsd']['vld'], {id: vldId}),
-			selectedVirtualLink: this.props.data && this.props.data['decorated-vlrs'] && _.find(this.props.data['decorated-vlrs'], {id: vlrId})
+			editingVirtualLink: this.props.data && this.props.data['nsd'] && this.props.data['nsd']['vld'] && _find(this.props.data['nsd']['vld'], {id: vldId}),
+			selectedVirtualLink: this.props.data && this.props.data['decorated-vlrs'] && _find(this.props.data['decorated-vlrs'], {id: vlrId})
 		});
 	}
 
diff --git a/skyquake/plugins/logging/src/loggingGeneral.jsx b/skyquake/plugins/logging/src/loggingGeneral.jsx
index 7b50c76..0aced4e 100644
--- a/skyquake/plugins/logging/src/loggingGeneral.jsx
+++ b/skyquake/plugins/logging/src/loggingGeneral.jsx
@@ -16,7 +16,9 @@
  *
  */
 import React from 'react';
-import _ from 'lodash';
+import _isEmpty from 'lodash/isEmpty';
+import _find from 'lodash/find';
+import _cloneDeep from 'lodash/cloneDeep';
 import './logging.scss';
 
 import Button from 'widgets/button/rw.button.js';
@@ -199,7 +201,7 @@
   getData() {
     LoggingStore.getLoggingConfig();
     this.setState({
-      isLoading: _.isEmpty(this.state.loggingConfig)
+      isLoading: _isEmpty(this.state.loggingConfig)
     });
   }
   componentWillUnmount = () => {
@@ -239,7 +241,7 @@
     this.context.router.push({pathname: ''});
   }
   // removeCategoryNulls(config) {
-  //   let cleanConfig = _.cloneDeep(config);
+  //   let cleanConfig = _cloneDeep(config);
   //   let cleanSeverities = [];
   //   config.defaultSeverities.map(function(d) {
   //     if (d.severity) {
@@ -250,7 +252,7 @@
   //   return cleanConfig;
   // }
   cleanupConfig(config) {
-    let cleanConfig = _.cloneDeep(config);
+    let cleanConfig = _cloneDeep(config);
     let cleanSeverities = [];
     cleanConfig.defaultSeverities && cleanConfig.defaultSeverities.map((defSev) => {
       if (defSev.severity) {
@@ -360,14 +362,14 @@
     // for RIFT-14856 so that default severities map to syslog sink
     
     // Find first syslog sink with (WTF - no type on sinks!) name syslog.
-    let syslogSink = this.state.loggingConfig.sinks && _.find(this.state.loggingConfig.sinks, {
+    let syslogSink = this.state.loggingConfig.sinks && _find(this.state.loggingConfig.sinks, {
       name: 'syslog'
     });
     let defaultSyslogSeverities = [];
 
     this.state.loggingConfig && this.state.loggingConfig.defaultSeverities && this.state.loggingConfig.defaultSeverities.map((defaultSeverity) => {
       // Mapping between default categories and names inside a sink
-      let syslogFilterCategory = (syslogSink.filter && syslogSink.filter.category && _.find(syslogSink.filter.category, {
+      let syslogFilterCategory = (syslogSink.filter && syslogSink.filter.category && _find(syslogSink.filter.category, {
         name: defaultSeverity.category
       })) || {
         name: defaultSeverity.category,
diff --git a/skyquake/plugins/logging/src/loggingStore.js b/skyquake/plugins/logging/src/loggingStore.js
index e95e657..3c306ae 100644
--- a/skyquake/plugins/logging/src/loggingStore.js
+++ b/skyquake/plugins/logging/src/loggingStore.js
@@ -15,7 +15,9 @@
  *   limitations under the License.
  *
  */
-import _ from 'lodash';
+import _cloneDeep from 'lodash/cloneDeep';
+import _findIndex from 'lodash/findIndex';
+import _remove from 'lodash/remove';
 import LoggingActions from './loggingActions.js';
 import LoggingSource from './loggingSource.js';
 
@@ -44,7 +46,7 @@
   getLoggingConfigSuccess = (data) => {
       console.log("LoggingStore.getLoggingConfigSuccess called. data=", data);
       // Do we need to do a deep clone?
-      const initialLoggingConfig = _.cloneDeep(data);
+      const initialLoggingConfig = _cloneDeep(data);
       console.log("initialLoggingConfig=", initialLoggingConfig);
       this.setState({
       loggingConfig: data,
@@ -59,7 +61,7 @@
 
   putLoggingConfigSuccess = (data) => {
     console.log("LoggingStore.putLoggingConfigSuccess called. data=", data);
-    const initialLoggingConfig = _.cloneDeep(this.loggingConfig);
+    const initialLoggingConfig = _cloneDeep(this.loggingConfig);
     this.setState({
       isLoading: false,
       initialLoggingConfig: initialLoggingConfig
@@ -73,7 +75,7 @@
   resetLoggingConfigData = (data) => {
     console.log('LoggingStore.resetLoggingConfigData called. data=', data);
     // Do we need to do a deep clone?
-    const loggingConfig = _.cloneDeep(this.initialLoggingConfig);
+    const loggingConfig = _cloneDeep(this.initialLoggingConfig);
     this.setState({
       loggingConfig: loggingConfig
     });
@@ -83,7 +85,7 @@
     console.log("LoggingStore.updateCategoryDefaultSeverity:", catsev);
     // find the category
 
-    let catIndex = _.findIndex(this.loggingConfig.defaultSeverities, function(o) {
+    let catIndex = _findIndex(this.loggingConfig.defaultSeverities, function(o) {
       return o.category == catsev.category;
     });
     console.log("catIndex=", catIndex);
@@ -104,7 +106,7 @@
     // find the category (name) in the syslog sink
 
     let self = this;
-    let loggingConfig = _.cloneDeep(this.loggingConfig);
+    let loggingConfig = _cloneDeep(this.loggingConfig);
     let syslogSinkIndex = -1;
     let nulledCategories = this.nulledCategories;
 
@@ -112,7 +114,7 @@
       if (sink.name == 'syslog') {
         if (sink.filter) {
           if (sink.filter.category) {
-            let catIndex = _.findIndex(sink.filter.category, {
+            let catIndex = _findIndex(sink.filter.category, {
               name: catsev.name
             });
             if (catIndex != -1) {
@@ -127,14 +129,14 @@
                 // missing elements is not allowed!
                 // When backend supports it, in loggingSource change the order of operations
                 // // Delete first followed by save/put.
-                _.remove(loggingConfig.sinks[sinkIndex].filter.category, {
+                _remove(loggingConfig.sinks[sinkIndex].filter.category, {
                   name: catsev.name
                 });
               } else {
                 sink.filter.category[catIndex] = catsev;
               }
             } else {
-              _.remove(nulledCategories, (v) => v == catsev.name);
+              _remove(nulledCategories, (v) => v == catsev.name);
               this.setState({
                 nulledCategories: nulledCategories
               });