Add new code new version

Change-Id: Ic02a76313503b526f17c3df29eb387a29fe6a42a
Signed-off-by: Michael Lando <ml636r@att.com>
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js
new file mode 100644
index 0000000..a851e77
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes} from './LicenseModelConstants.js';
+
+export default (state = [], action) => {
+	switch (action.type) {
+		case actionTypes.FINALIZED_LICENSE_MODELS_LIST_LOADED:
+			return [...action.response.results];
+		default:
+			return state;
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js
new file mode 100644
index 0000000..ad91a0d
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js
@@ -0,0 +1,147 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {connect} from 'react-redux';
+
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {statusEnum as versionStatusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import TabulatedEditor from 'src/nfvo-components/editor/TabulatedEditor.jsx';
+
+import {enums} from 'sdc-app/onboarding/OnboardingConstants.js';
+import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
+
+import {navigationItems} from './LicenseModelConstants.js';
+import LicenseModelActionHelper from './LicenseModelActionHelper.js';
+import LicenseAgreementActionHelper from './licenseAgreement/LicenseAgreementActionHelper.js';
+import FeatureGroupsActionHelper from './featureGroups/FeatureGroupsActionHelper.js';
+import EntitlementPoolsActionHelper from './entitlementPools/EntitlementPoolsActionHelper.js';
+import LicenseKeyGroupsActionHelper from './licenseKeyGroups/LicenseKeyGroupsActionHelper.js';
+
+
+const buildNavigationBarProps = (licenseModel, screen) => {
+	const {id, vendorName, version} = licenseModel;
+	const meta = {version};
+
+	const groups = [{
+		id,
+		name: vendorName,
+		items: [
+			{
+				id: navigationItems.LICENSE_AGREEMENTS,
+				name: i18n('License Agreements'),
+				meta
+			},
+			{
+				id: navigationItems.FEATURE_GROUPS,
+				name: i18n('Feature Groups'),
+				meta
+			},
+			{
+				id: navigationItems.ENTITLEMENT_POOLS,
+				name: i18n('Entitlement Pools'),
+				meta
+			},
+			{
+				id: navigationItems.LICENSE_KEY_GROUPS,
+				name: i18n('License Key Groups'),
+				meta
+			}
+		]
+	}];
+
+	const activeItemId = ({
+		[enums.SCREEN.LICENSE_AGREEMENTS]: navigationItems.LICENSE_AGREEMENTS,
+		[enums.SCREEN.FEATURE_GROUPS]: navigationItems.FEATURE_GROUPS,
+		[enums.SCREEN.ENTITLEMENT_POOLS]: navigationItems.ENTITLEMENT_POOLS,
+		[enums.SCREEN.LICENSE_KEY_GROUPS]: navigationItems.LICENSE_KEY_GROUPS
+	})[screen];
+
+	return {
+		activeItemId, groups
+	};
+};
+
+
+const buildVersionControllerProps = (licenseModel) => {
+	let {version, viewableVersions, status: currentStatus, lockingUser} = licenseModel;
+	let {status, isCheckedOut} = (currentStatus === versionStatusEnum.CHECK_OUT_STATUS) ?
+		VersionControllerUtils.getCheckOutStatusKindByUserID(currentStatus, lockingUser) :
+		{status: currentStatus, isCheckedOut: false};
+
+	return {
+		version,
+		viewableVersions,
+		status,
+		isCheckedOut
+	};
+};
+
+
+const mapStateToProps = ({licenseModel: {licenseModelEditor}}, {currentScreen: {screen}}) => {
+	return {
+		versionControllerProps: buildVersionControllerProps(licenseModelEditor.data),
+		navigationBarProps: buildNavigationBarProps(licenseModelEditor.data, screen)
+	};
+};
+
+
+const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {licenseModelId}}}) => {
+	return {
+		onVersionControllerAction: action =>
+			LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action}).then(() => {
+				switch(screen) {
+					case enums.SCREEN.LICENSE_AGREEMENTS:
+						LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId});
+						break;
+					case enums.SCREEN.FEATURE_GROUPS:
+						FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId});
+						break;
+					case enums.SCREEN.ENTITLEMENT_POOLS:
+						EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId});
+						break;
+					case enums.SCREEN.LICENSE_KEY_GROUPS:
+						LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId});
+						break;
+				}
+			}),
+		onVersionSwitching: version => LicenseAgreementActionHelper.switchVersion(dispatch, {licenseModelId, version}),
+		onClose: () => OnboardingActionHelper.navigateToOnboardingCatalog(dispatch),
+
+		onNavigate: ({id, meta: {version}}) => {
+			switch(id) {
+				case navigationItems.LICENSE_AGREEMENTS:
+					OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId, version});
+					break;
+				case navigationItems.FEATURE_GROUPS:
+					OnboardingActionHelper.navigateToFeatureGroups(dispatch, {licenseModelId, version});
+					break;
+				case navigationItems.ENTITLEMENT_POOLS:
+					OnboardingActionHelper.navigateToEntitlementPools(dispatch, {licenseModelId, version});
+					break;
+				case navigationItems.LICENSE_KEY_GROUPS:
+					OnboardingActionHelper.navigateToLicenseKeyGroups(dispatch, {licenseModelId, version});
+					break;
+			}
+		}
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(TabulatedEditor);
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js
new file mode 100644
index 0000000..a379a2c
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js
@@ -0,0 +1,101 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import {actionTypes} from './LicenseModelConstants.js';
+import {actionsEnum as vcActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import NotificationConstants from 'nfvo-components/notifications/NotificationConstants.js';
+
+function baseUrl() {
+	const restPrefix = Configuration.get('restPrefix');
+	return `${restPrefix}/v1.0/vendor-license-models/`;
+}
+
+function fetchLicenseModels() {
+	return RestAPIUtil.fetch(baseUrl());
+}
+
+function fetchFinalizedLicenseModels() {
+	return RestAPIUtil.fetch(`${baseUrl()}?versionFilter=Final`);
+}
+
+function fetchLicenseModelById(licenseModelId, version) {
+	let versionQuery = version ? `?version=${version}` : '';
+	return RestAPIUtil.fetch(`${baseUrl()}${licenseModelId}${versionQuery}`);
+}
+
+function putLicenseModelAction(id, action) {
+	return RestAPIUtil.save(`${baseUrl()}${id}/actions`, {action: action});
+}
+
+const LicenseModelActionHelper = {
+
+	fetchLicenseModels(dispatch) {
+		return fetchLicenseModels().then(response => {
+			dispatch({
+				type: actionTypes.LICENSE_MODELS_LIST_LOADED,
+				response
+			});
+		});
+	},
+
+	fetchFinalizedLicenseModels(dispatch) {
+		return fetchFinalizedLicenseModels().then(response => dispatch({
+			type: actionTypes.FINALIZED_LICENSE_MODELS_LIST_LOADED,
+			response
+		}));
+
+	},
+
+	fetchLicenseModelById(dispatch, {licenseModelId, version}) {
+		return fetchLicenseModelById(licenseModelId, version).then(response => {
+			if(version) {
+				response.version = version;
+			}
+			dispatch({
+				type: actionTypes.LICENSE_MODEL_LOADED,
+				response
+			});
+		});
+	},
+
+	addLicenseModel(dispatch, {licenseModel}){
+		dispatch({
+			type: actionTypes.ADD_LICENSE_MODEL,
+			licenseModel
+		});
+	},
+
+	performVCAction(dispatch, {licenseModelId, action}) {
+		return putLicenseModelAction(licenseModelId, action).then(() => {
+			if(action === vcActionsEnum.SUBMIT){
+				dispatch({
+					type: NotificationConstants.NOTIFY_SUCCESS,
+					data: {title: i18n('Submit Succeeded'), msg: i18n('This license model successfully submitted'), timeout: 2000}
+				});
+			}
+			return LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId});
+		});
+	}
+};
+
+export default LicenseModelActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js
new file mode 100644
index 0000000..13fa9f5
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+	LICENSE_MODEL_LOADED: null,
+	LICENSE_MODELS_LIST_LOADED: null,
+	FINALIZED_LICENSE_MODELS_LIST_LOADED: null,
+	ADD_LICENSE_MODEL: null,
+	EDIT_LICENSE_MODEL: null
+});
+
+export const navigationItems = keyMirror({
+	LICENSE_AGREEMENTS: 'License Agreements',
+	FEATURE_GROUPS: 'Feature Groups',
+	ENTITLEMENT_POOLS: 'Entitlement Pools',
+	LICENSE_KEY_GROUPS: 'License Key Groups'
+});
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js
new file mode 100644
index 0000000..e92e32a
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes} from './LicenseModelConstants.js';
+
+export default (state = {}, action) => {
+	switch (action.type) {
+		case actionTypes.LICENSE_MODEL_LOADED:
+			return {
+				...state,
+				data: action.response
+			};
+		default:
+			return state;
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js
new file mode 100644
index 0000000..8874c4c
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes} from './LicenseModelConstants.js';
+
+export default (state = [], action) => {
+	switch (action.type) {
+		case actionTypes.LICENSE_MODELS_LIST_LOADED:
+			return [...action.response.results];
+		case actionTypes.ADD_LICENSE_MODEL:
+			return [...state, action.licenseModel];
+		default:
+			return state;
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js
new file mode 100644
index 0000000..5982b9f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {combineReducers} from 'redux';
+
+import licenseModelCreationReducer from './creation/LicenseModelCreationReducer.js';
+import licenseModelEditorReducer from './LicenseModelEditorReducer.js';
+
+import licenseAgreementListReducer from './licenseAgreement/LicenseAgreementListReducer.js';
+import licenseAgreementEditorReducer from './licenseAgreement/LicenseAgreementEditorReducer.js';
+import {actionTypes as licenseAgreementActionTypes} from './licenseAgreement/LicenseAgreementConstants.js';
+
+import featureGroupsEditorReducer from './featureGroups/FeatureGroupsEditorReducer.js';
+import featureGroupsListReducer from './featureGroups/FeatureGroupsListReducer.js';
+import {actionTypes as featureGroupsActionConstants} from './featureGroups/FeatureGroupsConstants';
+
+import entitlementPoolsListReducer from './entitlementPools/EntitlementPoolsListReducer.js';
+import entitlementPoolsEditorReducer from './entitlementPools/EntitlementPoolsEditorReducer.js';
+import {actionTypes as entitlementPoolsConstants} from './entitlementPools/EntitlementPoolsConstants';
+
+import licenseKeyGroupsEditorReducer from './licenseKeyGroups/LicenseKeyGroupsEditorReducer.js';
+import licenseKeyGroupsListReducer from './licenseKeyGroups/LicenseKeyGroupsListReducer.js';
+import {actionTypes as licenseKeyGroupsConstants} from './licenseKeyGroups/LicenseKeyGroupsConstants.js';
+
+export default combineReducers({
+	licenseModelCreation: licenseModelCreationReducer,
+	licenseModelEditor: licenseModelEditorReducer,
+
+	licenseAgreement: combineReducers({
+		licenseAgreementEditor: licenseAgreementEditorReducer,
+		licenseAgreementList: licenseAgreementListReducer,
+		licenseAgreementToDelete: (state = false, action) => action.type === licenseAgreementActionTypes.LICENSE_AGREEMENT_DELETE_CONFIRM ? action.licenseAgreementToDelete : state
+	}),
+	featureGroup: combineReducers({
+		featureGroupEditor: featureGroupsEditorReducer,
+		featureGroupsList: featureGroupsListReducer,
+		featureGroupToDelete: (state = false, action) => action.type === featureGroupsActionConstants.FEATURE_GROUPS_DELETE_CONFIRM ? action.featureGroupToDelete : state
+	}),
+	entitlementPool: combineReducers({
+		entitlementPoolEditor: entitlementPoolsEditorReducer,
+		entitlementPoolsList: entitlementPoolsListReducer,
+		entitlementPoolToDelete: (state = false, action) => action.type === entitlementPoolsConstants.ENTITLEMENT_POOLS_DELETE_CONFIRM ? action.entitlementPoolToDelete : state
+	}),
+	licenseKeyGroup: combineReducers({
+		licenseKeyGroupsEditor: licenseKeyGroupsEditorReducer,
+		licenseKeyGroupsList: licenseKeyGroupsListReducer,
+		licenseKeyGroupToDelete: (state = false, action) => action.type === licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM ? action.licenseKeyGroupToDelete : state
+	}),
+});
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js
new file mode 100644
index 0000000..63d0f27
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {connect} from 'react-redux';
+import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
+import LicenseModelCreationActionHelper from './LicenseModelCreationActionHelper.js';
+import LicenseModelCreationView from './LicenseModelCreationView.jsx';
+
+const mapStateToProps = ({licenseModel: {licenseModelCreation}}) => licenseModelCreation;
+
+const mapActionsToProps = (dispatch) => {
+	return {
+		onDataChanged: deltaData => LicenseModelCreationActionHelper.dataChanged(dispatch, {deltaData}),
+		onCancel: () => LicenseModelCreationActionHelper.close(dispatch),
+		onSubmit: (licenseModel) => {
+			LicenseModelCreationActionHelper.close(dispatch);
+			LicenseModelCreationActionHelper.createLicenseModel(dispatch, {licenseModel}).then(licenseModelId => {
+				OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId});
+			});
+		}
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(LicenseModelCreationView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js
new file mode 100644
index 0000000..c2a0409
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
+import {actionTypes} from './LicenseModelCreationConstants.js';
+
+function baseUrl() {
+	const restPrefix = Configuration.get('restPrefix');
+	return `${restPrefix}/v1.0/vendor-license-models/`;
+}
+
+function createLicenseModel(licenseModel) {
+	return RestAPIUtil.create(baseUrl(), {
+		vendorName: licenseModel.vendorName,
+		description: licenseModel.description,
+		iconRef: 'icon'
+	});
+}
+
+
+export default {
+
+	open(dispatch) {
+		dispatch({
+			type: actionTypes.OPEN
+		});
+	},
+
+	close(dispatch){
+		dispatch({
+			type: actionTypes.CLOSE
+		});
+	},
+
+	dataChanged(dispatch, {deltaData}){
+		dispatch({
+			type: actionTypes.DATA_CHANGED,
+			deltaData
+		});
+	},
+
+	createLicenseModel(dispatch, {licenseModel}){
+		return createLicenseModel(licenseModel).then(response => {
+			LicenseModelActionHelper.addLicenseModel(dispatch, {
+				licenseModel: {
+					...licenseModel,
+					id: response.value
+				}
+			});
+			return response.value;
+		});
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js
new file mode 100644
index 0000000..603d177
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+	OPEN: null,
+	CLOSE: null,
+	DATA_CHANGED: null
+});
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js
new file mode 100644
index 0000000..a54d1b3
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes} from './LicenseModelCreationConstants.js';
+
+export default (state = {}, action) => {
+	switch (action.type) {
+		case actionTypes.OPEN:
+			return {
+				...state,
+				data: {}
+			};
+		case actionTypes.CLOSE:
+			return {};
+		case actionTypes.DATA_CHANGED:
+			return {
+				...state,
+				data: {
+					...state.data,
+					...action.deltaData
+				}
+			};
+		default:
+			return state;
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx
new file mode 100644
index 0000000..4dccc9e
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx
@@ -0,0 +1,60 @@
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
+import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
+
+const LicenseModelPropType = React.PropTypes.shape({
+	id: React.PropTypes.string,
+	vendorName: React.PropTypes.string,
+	description: React.PropTypes.string
+});
+
+class LicenseModelCreationView extends React.Component {
+
+	static propTypes = {
+		data: LicenseModelPropType,
+		onDataChanged: React.PropTypes.func.isRequired,
+		onSubmit: React.PropTypes.func.isRequired,
+		onCancel: React.PropTypes.func.isRequired
+	};
+
+	render() {
+		let {data = {}, onDataChanged} = this.props;
+		let {vendorName, description} = data;
+		return (
+			<div>
+				<ValidationForm
+					ref='validationForm'
+					hasButtons={true}
+					onSubmit={ () => this.submit() }
+					onReset={ () => this.props.onCancel() }
+					labledButtons={true}>
+					<ValidationInput
+						value={vendorName}
+						label={i18n('Vendor Name')}
+						ref='vendor-name'
+						onChange={vendorName => onDataChanged({vendorName})}
+						validations={{maxLength: 25, required: true}}
+						type='text'
+						className='field-section'/>
+					<ValidationInput
+						value={description}
+						label={i18n('Description')}
+						ref='description'
+						onChange={description => onDataChanged({description})}
+						validations={{maxLength: 1000, required: true}}
+						type='textarea'
+						className='field-section'/>
+				</ValidationForm>
+			</div>
+		);
+	}
+
+
+	submit() {
+		const {data:licenseModel} = this.props;
+		this.props.onSubmit(licenseModel);
+	}
+}
+
+export default LicenseModelCreationView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js
new file mode 100644
index 0000000..631597a
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js
@@ -0,0 +1,149 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import {actionTypes as entitlementPoolsActionTypes } from './EntitlementPoolsConstants.js';
+import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
+
+function baseUrl(licenseModelId) {
+	const restPrefix = Configuration.get('restPrefix');
+	return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/entitlement-pools`;
+}
+
+function fetchEntitlementPoolsList(licenseModelId, version) {
+	let versionQuery = version ? `?version=${version}` : '';
+	return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`);
+}
+
+function postEntitlementPool(licenseModelId, entitlementPool) {
+	return RestAPIUtil.create(baseUrl(licenseModelId), {
+		name: entitlementPool.name,
+		description: entitlementPool.description,
+		thresholdValue: entitlementPool.thresholdValue,
+		thresholdUnits: entitlementPool.thresholdUnits,
+		entitlementMetric: entitlementPool.entitlementMetric,
+		increments: entitlementPool.increments,
+		aggregationFunction: entitlementPool.aggregationFunction,
+		operationalScope: entitlementPool.operationalScope,
+		time: entitlementPool.time,
+		manufacturerReferenceNumber: entitlementPool.manufacturerReferenceNumber
+	});
+}
+
+
+function putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool) {
+	return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${entitlementPool.id}`, {
+		name: entitlementPool.name,
+		description: entitlementPool.description,
+		thresholdValue: entitlementPool.thresholdValue,
+		thresholdUnits: entitlementPool.thresholdUnits,
+		entitlementMetric: entitlementPool.entitlementMetric,
+		increments: entitlementPool.increments,
+		aggregationFunction: entitlementPool.aggregationFunction,
+		operationalScope: entitlementPool.operationalScope,
+		time: entitlementPool.time,
+		manufacturerReferenceNumber: entitlementPool.manufacturerReferenceNumber
+	});
+}
+
+function deleteEntitlementPool(licenseModelId, entitlementPoolId) {
+	return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${entitlementPoolId}`);
+}
+
+
+export default {
+	fetchEntitlementPoolsList(dispatch, {licenseModelId, version}) {
+		return fetchEntitlementPoolsList(licenseModelId, version).then(response => dispatch({
+			type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_LIST_LOADED,
+			response
+		}));
+	},
+
+	openEntitlementPoolsEditor(dispatch, {entitlementPool} = {}) {
+		dispatch({
+			type: entitlementPoolsActionTypes.entitlementPoolsEditor.OPEN,
+			entitlementPool
+		});
+	},
+
+	deleteEntitlementPool(dispatch, {licenseModelId, entitlementPoolId}) {
+		return deleteEntitlementPool(licenseModelId, entitlementPoolId).then(() => {
+			dispatch({
+				type: entitlementPoolsActionTypes.DELETE_ENTITLEMENT_POOL,
+				entitlementPoolId
+			});
+		});
+	},
+
+	entitlementPoolsEditorDataChanged(dispatch, {deltaData}) {
+		dispatch({
+			type: entitlementPoolsActionTypes.entitlementPoolsEditor.DATA_CHANGED,
+			deltaData
+		});
+	},
+
+	closeEntitlementPoolsEditor(dispatch) {
+		dispatch({
+			type: entitlementPoolsActionTypes.entitlementPoolsEditor.CLOSE
+		});
+	},
+
+	saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool}) {
+		if (previousEntitlementPool) {
+			return putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool).then(() => {
+				dispatch({
+					type: entitlementPoolsActionTypes.EDIT_ENTITLEMENT_POOL,
+					entitlementPool
+				});
+			});
+		}
+		else {
+			return postEntitlementPool(licenseModelId, entitlementPool).then(response => {
+				dispatch({
+					type: entitlementPoolsActionTypes.ADD_ENTITLEMENT_POOL,
+					entitlementPool: {
+						...entitlementPool,
+						id: response.value
+					}
+				});
+			});
+		}
+	},
+
+	hideDeleteConfirm(dispatch) {
+		dispatch({
+			type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_DELETE_CONFIRM,
+			entitlementPoolToDelete: false
+		});
+	},
+	openDeleteEntitlementPoolConfirm(dispatch, {entitlementPool}) {
+		dispatch({
+			type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_DELETE_CONFIRM,
+			entitlementPoolToDelete: entitlementPool
+		});
+	},
+
+	switchVersion(dispatch, {licenseModelId, version}) {
+		LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
+			this.fetchEntitlementPoolsList(dispatch, {licenseModelId, version});
+		});
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx
new file mode 100644
index 0000000..04f038f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx
@@ -0,0 +1,51 @@
+import React from 'react';
+import {connect} from 'react-redux';
+import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
+import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+function renderMsg(entitlementPoolToDelete) {
+	let poolName = entitlementPoolToDelete ? entitlementPoolToDelete.name : '';
+	let msg = i18n('Are you sure you want to delete "{poolName}"?', {poolName});
+	let subMsg = entitlementPoolToDelete
+	&& entitlementPoolToDelete.referencingFeatureGroups
+	&& entitlementPoolToDelete.referencingFeatureGroups.length > 0 ?
+		i18n('This entitlement pool is associated with one or more feature groups') :
+		'';
+	return (
+		<div>
+			<p>{msg}</p>
+			<p>{subMsg}</p>
+		</div>
+	);
+};
+
+const mapStateToProps = ({licenseModel: {entitlementPool}}, {licenseModelId}) => {
+	let {entitlementPoolToDelete} = entitlementPool;
+	const show = entitlementPoolToDelete !== false;
+	return {
+		show,
+		title: 'Warning!',
+		type: 'warning',
+		msg: renderMsg(entitlementPoolToDelete),
+		confirmationDetails: {entitlementPoolToDelete, licenseModelId}
+	};
+};
+
+const mapActionsToProps = (dispatch) => {
+	return {
+		onConfirmed: ({entitlementPoolToDelete, licenseModelId}) => {
+			EntitlementPoolsActionHelper.deleteEntitlementPool(dispatch, {
+				licenseModelId,
+				entitlementPoolId: entitlementPoolToDelete.id
+			});
+			EntitlementPoolsActionHelper.hideDeleteConfirm(dispatch);
+		},
+		onDeclined: () => {
+			EntitlementPoolsActionHelper.hideDeleteConfirm(dispatch);
+		}
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js
new file mode 100644
index 0000000..8a85507
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+export const actionTypes = keyMirror({
+
+	ENTITLEMENT_POOLS_LIST_LOADED: null,
+	ADD_ENTITLEMENT_POOL: null,
+	EDIT_ENTITLEMENT_POOL: null,
+	DELETE_ENTITLEMENT_POOL: null,
+	ENTITLEMENT_POOLS_DELETE_CONFIRM: null,
+
+	entitlementPoolsEditor: {
+		OPEN: null,
+		CLOSE: null,
+		DATA_CHANGED: null,
+	}
+
+});
+
+export const enums = keyMirror({
+	SELECTED_FEATURE_GROUP_TAB: {
+		GENERAL: 1,
+		ENTITLEMENT_POOLS: 2,
+		LICENCE_KEY_GROUPS: 3
+	},
+	SELECTED_ENTITLEMENT_POOLS_BUTTONTAB: {
+		ASSOCIATED_ENTITLEMENT_POOLS: 1,
+		AVAILABLE_ENTITLEMENT_POOLS: 2
+	}
+});
+
+export const defaultState = {
+	ENTITLEMENT_POOLS_EDITOR_DATA: {
+		entitlementMetric: {choice: '', other: ''},
+		aggregationFunction: {choice: '', other: ''},
+		operationalScope: {choices: [], other: ''},
+		time: {choice: '', other: ''}
+	}
+};
+
+export const thresholdUnitType = {
+	ABSOLUTE: 'Absolute',
+	PERCENTAGE: 'Percentage'
+};
+
+export const optionsInputValues = {
+	OPERATIONAL_SCOPE: [
+		{enum: '', title: i18n('please select…')},
+		{enum: 'Network_Wide', title: 'Network Wide'},
+		{enum: 'Availability_Zone', title: 'Availability Zone'},
+		{enum: 'Data_Center', title: 'Data Center'},
+		{enum: 'Tenant', title: 'Tenant'},
+		{enum: 'VM', title: 'VM'},
+		{enum: 'CPU', title: 'CPU'},
+		{enum: 'Core', title: 'Core'}
+	],
+	TIME: [
+		{enum: '', title: i18n('please select…')},
+		{enum: 'Hour', title: 'Hour'},
+		{enum: 'Day', title: 'Day'},
+		{enum: 'Month', title: 'Month'}
+	],
+	AGGREGATE_FUNCTION: [
+		{enum: '', title: i18n('please select…')},
+		{enum: 'Peak', title: 'Peak'},
+		{enum: 'Average', title: 'Average'}
+	],
+	ENTITLEMENT_METRIC: [
+		{enum: '', title: i18n('please select…')},
+		{enum: 'Software_Instances_Count', title: 'Software Instances'},
+		{enum: 'Core', title: 'Core'},
+		{enum: 'CPU', title: 'CPU'},
+		{enum: 'Trunks', title: 'Trunks'},
+		{enum: 'User', title: 'User'},
+		{enum: 'Subscribers', title: 'Subscribers'},
+		{enum: 'Tenants', title: 'Tenants'},
+		{enum: 'Tokens', title: 'Tokens'},
+		{enum: 'Seats', title: 'Seats'},
+		{enum: 'Units_TB', title: 'Units-TB'},
+		{enum: 'Units_GB', title: 'Units-GB'},
+		{enum: 'Units_MB', title: 'Units-MB'}
+	],
+	THRESHOLD_UNITS: [
+		{enum: '', title: i18n('please select…')},
+		{enum: thresholdUnitType.ABSOLUTE, title: 'Absolute'},
+		{enum: thresholdUnitType.PERCENTAGE, title: '%'}
+	]
+};
+
+
+
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js
new file mode 100644
index 0000000..d5bd07e
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {connect} from 'react-redux';
+import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
+import EntitlementPoolsEditorView from './EntitlementPoolsEditorView.jsx';
+
+const mapStateToProps = ({licenseModel: {entitlementPool}}) => {
+
+
+	let {data} = entitlementPool.entitlementPoolEditor;
+	
+	let previousData;
+	const entitlementPoolId = data ? data.id : null;
+	if(entitlementPoolId) {
+		previousData = entitlementPool.entitlementPoolsList.find(entitlementPool => entitlementPool.id === entitlementPoolId);
+	}
+
+	return {
+		data,
+		previousData
+	};
+};
+
+const mapActionsToProps = (dispatch, {licenseModelId}) => {
+	return {
+		onDataChanged: deltaData => EntitlementPoolsActionHelper.entitlementPoolsEditorDataChanged(dispatch, {deltaData}),
+		onCancel: () => EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch),
+		onSubmit: ({previousEntitlementPool, entitlementPool}) => {
+			EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch);
+			EntitlementPoolsActionHelper.saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool});
+		}
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(EntitlementPoolsEditorView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js
new file mode 100644
index 0000000..86e97ec
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes, defaultState} from './EntitlementPoolsConstants.js';
+
+export default (state = {}, action) => {
+	switch (action.type) {
+		case actionTypes.entitlementPoolsEditor.OPEN:
+			return {
+				...state,
+				data: action.entitlementPool ? {...action.entitlementPool} : defaultState.ENTITLEMENT_POOLS_EDITOR_DATA
+			};
+		case actionTypes.entitlementPoolsEditor.DATA_CHANGED:
+			return {
+				...state,
+				data: {
+					...state.data,
+					...action.deltaData
+				}
+			};
+		case actionTypes.entitlementPoolsEditor.CLOSE:
+			return {};
+		default:
+			return state;
+	}
+
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx
new file mode 100644
index 0000000..77c5a12
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx
@@ -0,0 +1,167 @@
+import React from 'react';
+
+
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
+import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
+import {optionsInputValues as  EntitlementPoolsOptionsInputValues, thresholdUnitType}  from  './EntitlementPoolsConstants.js';
+import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+
+
+const EntitlementPoolPropType = React.PropTypes.shape({
+	id: React.PropTypes.string,
+	name: React.PropTypes.string,
+	description: React.PropTypes.string,
+	manufacturerReferenceNumber: React.PropTypes.string,
+	operationalScope: React.PropTypes.shape({
+		choices: React.PropTypes.array,
+		other: React.PropTypes.string
+	}),
+	aggregationFunction: React.PropTypes.shape({
+		choice: React.PropTypes.string,
+		other: React.PropTypes.string
+	}),
+	increments: React.PropTypes.string,
+	time: React.PropTypes.shape({
+		choice: React.PropTypes.string,
+		other: React.PropTypes.string
+	}),
+	entitlementMetric: React.PropTypes.shape({
+		choice: React.PropTypes.string,
+		other: React.PropTypes.string
+	})
+});
+
+class EntitlementPoolsEditorView extends React.Component {
+
+	static propTypes = {
+		data: EntitlementPoolPropType,
+		previousData: EntitlementPoolPropType,
+		isReadOnlyMode: React.PropTypes.bool,
+		onDataChanged: React.PropTypes.func.isRequired,
+		onSubmit: React.PropTypes.func.isRequired,
+		onCancel: React.PropTypes.func.isRequired
+	};
+
+	static defaultProps = {
+		data: {}
+	};
+
+	render() {
+		let {data = {}, onDataChanged, isReadOnlyMode} = this.props;
+		let {
+			name, description, manufacturerReferenceNumber, operationalScope, aggregationFunction, thresholdUnits, thresholdValue,
+			increments, time, entitlementMetric} = data;
+		let thresholdValueValidation = thresholdUnits === thresholdUnitType.PERCENTAGE ? {numeric: true, required: true, maxValue: 100} : {numeric: true, required: true};
+		let timeValidation = time && time.choice === optionInputOther.OTHER ? {numeric: true, required: true} : {required: true};
+
+		return (
+			<ValidationForm
+				ref='validationForm'
+				hasButtons={true}
+				onSubmit={ () => this.submit() }
+				onReset={ () => this.props.onCancel() }
+				labledButtons={true}
+				isReadOnlyMode={isReadOnlyMode}
+				className='entitlement-pools-form'>
+				<div className='entitlement-pools-form-row'>
+					<ValidationInput
+						onChange={name => onDataChanged({name})}
+						label={i18n('Name')}
+						value={name}
+						validations={{maxLength: 120, required: true}}
+						type='text'/>
+
+					<ValidationInput
+						isMultiSelect={true}
+						onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}})}
+						onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER], other: operationalScope}})}
+						multiSelectedEnum={operationalScope && operationalScope.choices}
+						label={i18n('Operational Scope')}
+						otherValue={operationalScope && operationalScope.other}
+						validations={{required: true}}
+						values={EntitlementPoolsOptionsInputValues.OPERATIONAL_SCOPE}/>
+
+				</div>
+				<div className='entitlement-pools-form-row'>
+					<ValidationInput
+						onChange={description => onDataChanged({description})}
+						label={i18n('Description')}
+						value={description}
+						validations={{maxLength: 1000, required: true}}
+						type='textarea'/>
+					<div className='entitlement-pools-form-row-group'>
+						<div className='entitlement-pools-form-row'>
+							<ValidationInput
+								onEnumChange={thresholdUnits => onDataChanged({thresholdUnits})}
+								selectedEnum={thresholdUnits}
+								label={i18n('Threshold Value')}
+								type='select'
+								values={EntitlementPoolsOptionsInputValues.THRESHOLD_UNITS}
+								validations={{required: true}}/>
+							<ValidationInput
+								className='entitlement-pools-form-row-threshold-value'
+								onChange={thresholdValue => onDataChanged({thresholdValue})}
+								value={thresholdValue}
+								validations={thresholdValueValidation}
+								type='text'/>
+						</div>
+
+						<ValidationInput
+							onEnumChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: entitlementMetric, other: ''}})}
+							onOtherChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: optionInputOther.OTHER, other: entitlementMetric}})}
+							selectedEnum={entitlementMetric && entitlementMetric.choice}
+							otherValue={entitlementMetric && entitlementMetric.other}
+							label={i18n('Entitlement Metric')}
+							validations={{required: true}}
+							values={EntitlementPoolsOptionsInputValues.ENTITLEMENT_METRIC}/>
+						<ValidationInput
+							onEnumChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: aggregationFunction, other: ''}})}
+							onOtherChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: optionInputOther.OTHER, other: aggregationFunction}})}
+							selectedEnum={aggregationFunction && aggregationFunction.choice}
+							otherValue={aggregationFunction && aggregationFunction.other}
+							validations={{required: true}}
+							label={i18n('Aggregate Function')}
+							values={EntitlementPoolsOptionsInputValues.AGGREGATE_FUNCTION}/>
+
+					</div>
+				</div>
+				<div className='entitlement-pools-form-row'>
+
+					<ValidationInput
+						onChange={manufacturerReferenceNumber => onDataChanged({manufacturerReferenceNumber})}
+						label={i18n('Manufacturer Reference Number')}
+						value={manufacturerReferenceNumber}
+						validations={{maxLength: 100, required: true}}
+						type='text'/>
+
+					<ValidationInput
+						onEnumChange={time => onDataChanged({time:{choice: time, other: ''}})}
+						onOtherChange={time => onDataChanged({time:{choice: optionInputOther.OTHER, other: time}})}
+						selectedEnum={time && time.choice}
+						otherValue={time && time.other}
+						validations={timeValidation}
+						label={i18n('Time')}
+						values={EntitlementPoolsOptionsInputValues.TIME}/>
+				</div>
+				<div className='entitlement-pools-form-row'>
+					<ValidationInput
+						onChange={increments => onDataChanged({increments})}
+						label={i18n('Increments')}
+						value={increments}
+						validations={{maxLength: 120}}
+						type='text'/>
+
+				</div>
+			</ValidationForm>
+		);
+	}
+
+	submit() {
+		const {data: entitlementPool, previousData: previousEntitlementPool} = this.props;
+		this.props.onSubmit({entitlementPool, previousEntitlementPool});
+	}
+}
+
+export default EntitlementPoolsEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js
new file mode 100644
index 0000000..4b21a2f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {connect} from 'react-redux';
+import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
+import EntitlementPoolsListEditorView from './EntitlementPoolsListEditorView.jsx';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+
+const mapStateToProps = ({licenseModel: {entitlementPool, licenseModelEditor}}) => {
+	let {entitlementPoolsList} = entitlementPool;
+	let {data} = entitlementPool.entitlementPoolEditor;
+
+	let {vendorName} = licenseModelEditor.data;
+	let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data);
+
+	return {
+		vendorName,
+		entitlementPoolsList,
+		isReadOnlyMode,
+		isDisplayModal: Boolean(data),
+		isModalInEditMode: Boolean(data && data.id),
+	};
+};
+
+const mapActionsToProps = (dispatch, {licenseModelId}) => {
+	return {
+		onAddEntitlementPoolClick: () => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch),
+		onEditEntitlementPoolClick: entitlementPool => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch, {entitlementPool}),
+		onDeleteEntitlementPool: entitlementPool => EntitlementPoolsActionHelper.openDeleteEntitlementPoolConfirm(dispatch, {
+			licenseModelId,
+			entitlementPool
+		})
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(EntitlementPoolsListEditorView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx
new file mode 100644
index 0000000..52df102
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx
@@ -0,0 +1,132 @@
+import React from 'react';
+
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Modal from 'nfvo-components/modal/Modal.jsx';
+import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
+import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+
+import EntitlementPoolsEditor from './EntitlementPoolsEditor.js';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+import {optionsInputValues} from './EntitlementPoolsConstants';
+import EntitlementPoolsConfirmationModal from './EntitlementPoolsConfirmationModal.jsx';
+
+
+class EntitlementPoolsListEditorView extends React.Component {
+	static propTypes = {
+		vendorName: React.PropTypes.string,
+		licenseModelId: React.PropTypes.string.isRequired,
+		entitlementPoolsList: React.PropTypes.array,
+		isReadOnlyMode: React.PropTypes.bool.isRequired,
+		isDisplayModal: React.PropTypes.bool,
+		isModalInEditMode: React.PropTypes.bool,
+		onAddEntitlementPoolClick: React.PropTypes.func,
+		onEditEntitlementPoolClick: React.PropTypes.func,
+		onDeleteEntitlementPool: React.PropTypes.func,
+	};
+
+	static defaultProps = {
+		entitlementPoolsList: []
+	};
+
+	state = {
+		localFilter: ''
+	};
+
+	render() {
+		let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props;
+		let {onAddEntitlementPoolClick} = this.props;
+		const {localFilter} = this.state;
+
+		return (
+			<div className='entitlement-pools-list-editor'>
+				<ListEditorView
+					title={i18n('Entitlement Pools for {vendorName} License Model', {vendorName})}
+					plusButtonTitle={i18n('Add Entitlement Pool')}
+					onAdd={onAddEntitlementPoolClick}
+					filterValue={localFilter}
+					onFilter={filter => this.setState({localFilter: filter})}
+					isReadOnlyMode={isReadOnlyMode}>
+					{this.filterList().map(entitlementPool => this.renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode))}
+				</ListEditorView>
+				<Modal show={isDisplayModal} bsSize='large' animation={true} className='entitlement-pools-modal'>
+					<Modal.Header>
+						<Modal.Title>{`${isModalInEditMode ? i18n('Edit Entitlement Pool') : i18n('Create New Entitlement Pool')}`}</Modal.Title>
+					</Modal.Header>
+					<Modal.Body>
+						{
+							isDisplayModal && (
+								<EntitlementPoolsEditor  licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>
+							)
+						}
+					</Modal.Body>
+				</Modal>
+
+				<EntitlementPoolsConfirmationModal licenseModelId={licenseModelId}/>
+			</div>
+		);
+	}
+
+	filterList() {
+		let {entitlementPoolsList} = this.props;
+		let {localFilter} = this.state;
+		if(localFilter.trim()) {
+			const filter = new RegExp(escape(localFilter), 'i');
+			return entitlementPoolsList.filter(({name = '', description = ''}) => {
+				return escape(name).match(filter) || escape(description).match(filter);
+			});
+		}
+		else {
+			return entitlementPoolsList;
+		}
+	}
+
+	renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode) {
+		let {id, name, description, thresholdValue, thresholdUnits, entitlementMetric, aggregationFunction,
+			manufacturerReferenceNumber, time} = entitlementPool;
+		let {onEditEntitlementPoolClick, onDeleteEntitlementPool} = this.props;
+		return (
+			<ListEditorItemView
+				key={id}
+				onSelect={() => onEditEntitlementPoolClick(entitlementPool)}
+				onDelete={() => onDeleteEntitlementPool(entitlementPool)}
+				className='list-editor-item-view'
+				isReadOnlyMode={isReadOnlyMode}>
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Name')}</div>
+					<div className='text name'>{name}</div>
+				</div>
+
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Entitlement')}</div>
+					<div className='entitlement-parameters'>{`${this.extractValue(aggregationFunction)} ${this.extractValue(entitlementMetric)} per  ${this.extractValue(time)}`}</div>
+					<div className='entitlement-pools-count'>{`${thresholdValue ? thresholdValue : ''} ${this.extractUnits(thresholdUnits)}`}</div>
+				</div>
+
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Manufacturer Reference Number')}</div>
+					<div className='text contract-number'>{manufacturerReferenceNumber}</div>
+				</div>
+
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Description')}</div>
+					<div className='text description'>{description}</div>
+				</div>
+			</ListEditorItemView>
+		);
+	}
+
+
+
+	extractUnits(units) {
+		if (units === undefined) {return '';} //TODO fix it later
+		return units === 'Absolute' ? '' : '%';
+	}
+
+	extractValue(item) {
+		if (item === undefined) {return '';} //TODO fix it later
+
+		return  item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
+	}
+}
+
+export default EntitlementPoolsListEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js
new file mode 100644
index 0000000..63e351f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes} from './EntitlementPoolsConstants';
+export default (state = [], action) => {
+	switch (action.type) {
+		case actionTypes.ENTITLEMENT_POOLS_LIST_LOADED:
+			return [...action.response.results];
+		case actionTypes.ADD_ENTITLEMENT_POOL:
+			return [...state, action.entitlementPool];
+		case actionTypes.EDIT_ENTITLEMENT_POOL:
+			const indexForEdit = state.findIndex(entitlementPool => entitlementPool.id === action.entitlementPool.id);
+			return [...state.slice(0, indexForEdit), action.entitlementPool, ...state.slice(indexForEdit + 1)];
+		case actionTypes.DELETE_ENTITLEMENT_POOL:
+			return state.filter(entitlementPool => entitlementPool.id !== action.entitlementPoolId);
+		default:
+			return state;
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js
new file mode 100644
index 0000000..c2b269b
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {connect} from 'react-redux';
+
+import FeatureGroupsActionHelper from './FeatureGroupsActionHelper.js';
+import FeatureGroupEditorView from './FeatureGroupEditorView.jsx';
+
+const mapStateToProps = ({licenseModel: {featureGroup, entitlementPool, licenseKeyGroup}}) => {
+
+	const {featureGroupEditor} = featureGroup;
+
+	let {data, selectedTab, selectedEntitlementPoolsButtonTab, selectedLicenseKeyGroupsButtonTab} = featureGroupEditor;
+
+	let previousData;
+	const featureGroupId = data ? data.id : null;
+	if (featureGroupId) {
+		previousData = featureGroup.featureGroupsList.find(featureGroup => featureGroup.id === featureGroupId);
+	}
+	let {entitlementPoolsList = []} = entitlementPool;
+	let {licenseKeyGroupsList = []} = licenseKeyGroup;
+
+	return {
+		data,
+		previousData,
+		selectedTab,
+		selectedEntitlementPoolsButtonTab,
+		selectedLicenseKeyGroupsButtonTab,
+		entitlementPoolsList,
+		licenseKeyGroupsList
+	};
+};
+
+
+const mapActionsToProps = (dispatch, {licenseModelId}) => {
+	return {
+		onTabSelect: tab => FeatureGroupsActionHelper.selectEntitlementPoolsEditorTab(dispatch, {tab}),
+		onEntitlementPoolsButtonTabSelect: buttonTab => FeatureGroupsActionHelper.selectFeatureGroupsEditorEntitlementPoolsButtonTab(dispatch, {buttonTab}),
+		onLicenseKeyGroupsButtonTabSelect: buttonTab => FeatureGroupsActionHelper.selectFeatureGroupsEditorLicenseKeyGroupsButtonTab(dispatch, {buttonTab}),
+		onDataChanged: deltaData => FeatureGroupsActionHelper.featureGroupsEditorDataChanged(dispatch, {deltaData}),
+		onSubmit: (previousFeatureGroup, featureGroup) => {
+			FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch);
+			FeatureGroupsActionHelper.saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup});
+		}
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(FeatureGroupEditorView);
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx
new file mode 100644
index 0000000..6fecd16
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx
@@ -0,0 +1,339 @@
+import React from 'react';
+import ValidationTabs from 'nfvo-components/input/validation/ValidationTabs.jsx';
+import ValidationTab from 'nfvo-components/input/validation/ValidationTab.jsx';
+import ButtonGroup from 'react-bootstrap/lib/ButtonGroup.js';
+import Button from 'react-bootstrap/lib/Button.js';
+
+import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
+import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx';
+import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
+import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
+import ListEditorViewItem from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+import {state as FeatureGroupStateConstants} from './FeatureGroupsConstants.js';
+
+const FeatureGroupsPropType = React.PropTypes.shape({
+	id: React.PropTypes.string,
+	name: React.PropTypes.string,
+	description: React.PropTypes.string,
+	partNumber: React.PropTypes.string,
+	entitlementPoolsIds: React.PropTypes.array(React.PropTypes.string),
+	licenseKeyGroupsIds: React.PropTypes.array(React.PropTypes.string)
+});
+
+class FeatureGroupEditorView extends React.Component {
+
+
+	static propTypes = {
+		data: FeatureGroupsPropType,
+		previousData: FeatureGroupsPropType,
+		isReadOnlyMode: React.PropTypes.bool,
+
+		onSubmit: React.PropTypes.func,
+		onCancel: React.PropTypes.func,
+
+		selectedTab: React.PropTypes.number,
+		onTabSelect: React.PropTypes.func,
+
+		selectedEntitlementPoolsButtonTab: React.PropTypes.number,
+		selectedLicenseKeyGroupsButtonTab: React.PropTypes.number,
+		onEntitlementPoolsButtonTabSelect: React.PropTypes.func,
+		onLicenseKeyGroupsButtonTabSelect: React.PropTypes.func,
+
+		entitlementPoolsList: DualListboxView.propTypes.availableList,
+		licenseKeyGroupsList: DualListboxView.propTypes.availableList
+	};
+
+
+	static defaultProps = {
+		data: {},
+		selectedTab: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL,
+		selectedEntitlementPoolsButtonTab: FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.ASSOCIATED_ENTITLEMENT_POOLS,
+		selectedLicenseKeyGroupsButtonTab: FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.ASSOCIATED_LICENSE_KEY_GROUPS
+	};
+
+	state = {
+		localEntitlementPoolsListFilter: '',
+		localLicenseKeyGroupsListFilter: ''
+	};
+
+
+	render() {
+		let {selectedTab, onTabSelect, isReadOnlyMode} = this.props;
+		return (
+			<ValidationForm
+				ref='validationForm'
+				hasButtons={true}
+				onSubmit={ () => this.submit() }
+				onReset={ () => this.props.onCancel() }
+				labledButtons={true}
+				isReadOnlyMode={isReadOnlyMode}
+				name='feature-group-validation-form'
+				className='feature-group-form'>
+				<ValidationTabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect}>
+					{this.renderGeneralTab()}
+					{this.renderEntitlementPoolsTab()}
+					{this.renderLicenseKeyGroupsTab()}
+				</ValidationTabs>
+
+			</ValidationForm>
+		);
+	}
+
+	submit() {
+		const {data: featureGroup, previousData: previousFeatureGroup} = this.props;
+		this.props.onSubmit(previousFeatureGroup, featureGroup);
+	}
+
+	renderGeneralTab() {
+		let {data = {}, onDataChanged} = this.props;
+		let {name, description, partNumber} = data;
+		return (
+			<ValidationTab eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL} title={i18n('General')}>
+				<div>
+					<ValidationInput
+						groupClassName='field-section'
+						onChange={name => onDataChanged({name})}
+						ref='name'
+						label={i18n('Name')}
+						value={name}
+						name='feature-group-name'
+						validations={{maxLength: 120, required: true}}
+						type='text'/>
+					<ValidationInput
+						groupClassName='field-section'
+						className='description-field'
+						onChange={description => onDataChanged({description})}
+						ref='description'
+						label={i18n('Description')}
+						value={description}
+						name='feature-group-description'
+						validations={{maxLength: 1000, required: true}}
+						type='textarea'/>
+					<ValidationInput
+						groupClassName='field-section'
+						onChange={partNumber => onDataChanged({partNumber})}
+						label={i18n('Part Number')}
+						value={partNumber}
+						validations={{required: true}}
+						type='text'/>
+				</div>
+			</ValidationTab>
+		);
+	}
+
+	renderEntitlementPoolsTab() {
+		let {selectedEntitlementPoolsButtonTab, onEntitlementPoolsButtonTabSelect, entitlementPoolsList} = this.props;
+		if (entitlementPoolsList.length > 0) {
+			return (
+				<ValidationTab
+					eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS}
+					title={i18n('Entitlement Pools')}>
+					<ButtonGroup>
+						{
+							this.renderButtonsTab(
+								FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.ASSOCIATED_ENTITLEMENT_POOLS,
+								selectedEntitlementPoolsButtonTab,
+								i18n('Associated Entitlement Pools'),
+								onEntitlementPoolsButtonTabSelect
+							)
+						}
+						{
+							this.renderButtonsTab(
+								FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.AVAILABLE_ENTITLEMENT_POOLS,
+								selectedEntitlementPoolsButtonTab,
+								i18n('Available Entitlement Pools'),
+								onEntitlementPoolsButtonTabSelect
+							)
+						}
+					</ButtonGroup>
+					{this.renderEntitlementPoolsButtonTabContent(selectedEntitlementPoolsButtonTab)}
+				</ValidationTab>
+			);
+		} else {
+			return (
+				<ValidationTab
+					eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS}
+					title={i18n('Entitlement Pools')}>
+					<p>{i18n('There is no available entitlement pools.')}</p>
+				</ValidationTab>
+			);
+		}
+	}
+
+	renderLicenseKeyGroupsTab() {
+		let {selectedLicenseKeyGroupsButtonTab, onLicenseKeyGroupsButtonTabSelect, licenseKeyGroupsList} = this.props;
+		if (licenseKeyGroupsList.length > 0) {
+			return (
+				<ValidationTab
+					eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS}
+					title={i18n('License Key Groups')}>
+					<ButtonGroup>
+						{
+							this.renderButtonsTab(
+								FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.ASSOCIATED_LICENSE_KEY_GROUPS,
+								selectedLicenseKeyGroupsButtonTab,
+								i18n('Associated License Key Groups'),
+								onLicenseKeyGroupsButtonTabSelect
+							)
+						}
+						{
+							this.renderButtonsTab(
+								FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.AVAILABLE_LICENSE_KEY_GROUPS,
+								selectedLicenseKeyGroupsButtonTab,
+								i18n('Available License Key Groups'),
+								onLicenseKeyGroupsButtonTabSelect
+							)
+						}
+					</ButtonGroup>
+					{this.renderLicenseKeyGroupsTabContent(selectedLicenseKeyGroupsButtonTab)}
+				</ValidationTab>
+			);
+		} else {
+			return (
+				<ValidationTab
+					eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS}
+					title={i18n('License Key Groups')}>
+					<p>{i18n('There is no available license key groups')}</p>
+				</ValidationTab>);
+		}
+	}
+
+	renderButtonsTab(buttonTab, selectedButtonTab, title, onClick) {
+		const isSelected = buttonTab === selectedButtonTab;
+		return (
+			<Button
+				className='button-tab'
+				active={isSelected}
+				onClick={() => !isSelected && onClick(buttonTab)}>
+				{ title }
+			</Button>
+		);
+	}
+
+	renderEntitlementPoolsButtonTabContent(selectedFeatureGroupsButtonTab) {
+		const {entitlementPoolsList = [], data: {entitlementPoolsIds = []}} = this.props;
+		let dualBoxTitle = {
+			left: i18n('Available Entitlement Pools'),
+			right: i18n('Selected Entitlement Pools')
+		};
+
+		if (entitlementPoolsList.length) {
+			const {localEntitlementPoolsListFilter} = this.state;
+			let selectedEntitlementPools = entitlementPoolsIds.map(entitlementPoolId => entitlementPoolsList.find(entitlementPool => entitlementPool.id === entitlementPoolId));
+
+			switch (selectedFeatureGroupsButtonTab) {
+				case FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.ASSOCIATED_ENTITLEMENT_POOLS:
+					if (selectedEntitlementPools.length) {
+						return (
+							<ListEditorView
+								className='thinner-list'
+								filterValue={localEntitlementPoolsListFilter}
+								onFilter={localEntitlementPoolsListFilter => this.setState({localEntitlementPoolsListFilter})}>
+								{this.filterAssociatedItems(selectedEntitlementPools, localEntitlementPoolsListFilter)
+									.map(entitlementPool => this.renderAssociatedListItem(entitlementPool
+										, FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS))}
+							</ListEditorView>
+						);
+					}
+					else {
+						return (
+							<div>
+								<br/>{i18n('There are currently no entitlement pools associated with this feature group. Click "Available Entitlement Pools" to associate.')}
+							</div>
+						);
+					}
+				case FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.AVAILABLE_ENTITLEMENT_POOLS:
+					return (
+						<DualListboxView
+							filterTitle={dualBoxTitle}
+							selectedValuesList={entitlementPoolsIds}
+							availableList={entitlementPoolsList}
+							onChange={ selectedValuesList => this.props.onDataChanged( { entitlementPoolsIds: selectedValuesList } )}/>
+					);
+			}
+		}
+	}
+
+	renderLicenseKeyGroupsTabContent(selectedFeatureGroupsButtonTab) {
+		const {licenseKeyGroupsList = [], data: {licenseKeyGroupsIds = []}} = this.props;
+		let dualBoxFilterTitle = {
+			left: i18n('Available License Key Groups'),
+			right: i18n('Selected License Key Groups')
+		};
+
+		if (licenseKeyGroupsList.length) {
+			const {localLicenseKeyGroupsListFilter} = this.state;
+			let selectedLicenseKeyGroups = licenseKeyGroupsIds.map(licenseKeyGroupId => licenseKeyGroupsList.find(licenseKeyGroup => licenseKeyGroup.id === licenseKeyGroupId));
+
+			switch (selectedFeatureGroupsButtonTab) {
+				case FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.ASSOCIATED_LICENSE_KEY_GROUPS:
+					if (selectedLicenseKeyGroups.length) {
+						return (
+							<ListEditorView
+								className='thinner-list'
+								filterValue={localLicenseKeyGroupsListFilter}
+								onFilter={localLicenseKeyGroupsListFilter => this.setState({localLicenseKeyGroupsListFilter})}>
+								{this.filterAssociatedItems(selectedLicenseKeyGroups, localLicenseKeyGroupsListFilter)
+									.map(licenseKeyGroup => this.renderAssociatedListItem(licenseKeyGroup
+										, FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS))}
+							</ListEditorView>
+						);
+					} else {
+						return (
+							<div className='no-items-msg'>
+								{i18n('There are currently no license key groups associated with this feature group. Click "Available License Key Groups" to associate.')}
+							</div>
+						);
+					}
+				case FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.AVAILABLE_LICENSE_KEY_GROUPS:
+					return (
+						<DualListboxView
+							filterTitle={dualBoxFilterTitle}
+							selectedValuesList={this.props.data.licenseKeyGroupsIds}
+							availableList={this.props.licenseKeyGroupsList}
+							onChange={ selectedValuesList => this.props.onDataChanged( { licenseKeyGroupsIds: selectedValuesList } )}/>
+					);
+			}
+		}
+	}
+
+
+	renderAssociatedListItem(listItem, itemType) {
+		let {isReadOnlyMode} = this.props;
+		return (
+			<ListEditorViewItem
+				key={listItem.id}
+				onDelete={() => this.deleteAssociatedItem(listItem.id, itemType)}
+				isReadOnlyMode={isReadOnlyMode}>
+				<div className='name'>{listItem.name}</div>
+				<div className='description'>{listItem.description}</div>
+			</ListEditorViewItem>
+		);
+	}
+
+	filterAssociatedItems(list, localList) {
+		if (localList) {
+			const filter = new RegExp(escape(localList), 'i');
+			return list.filter(({name = '', description = ''}) => name.match(filter) || description.match(filter));
+		}
+		else {
+			return list;
+		}
+	}
+
+	deleteAssociatedItem(id, type) {
+		const {data: {licenseKeyGroupsIds = [], entitlementPoolsIds = []}} = this.props;
+		if (type === FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS) {
+			this.props.onDataChanged({licenseKeyGroupsIds: licenseKeyGroupsIds.filter(listId => listId !== id)});
+		} else {
+			this.props.onDataChanged({entitlementPoolsIds: entitlementPoolsIds.filter(listId => listId !== id)});
+		}
+
+	}
+}
+
+
+export default FeatureGroupEditorView;
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js
new file mode 100644
index 0000000..9ea5a31
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {connect} from 'react-redux';
+import FeatureGroupsActionHelper  from './FeatureGroupsActionHelper.js';
+import FeatureGroupListEditorView from './FeatureGroupListEditorView.jsx';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+
+const mapStateToProps = ({licenseModel: {featureGroup, licenseModelEditor}}) => {
+	const {featureGroupEditor: {data}, featureGroupsList} = featureGroup;
+	let {vendorName} = licenseModelEditor.data;
+	let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data);
+
+	return {
+		vendorName,
+		featureGroupsModal: {
+			show: Boolean(data),
+			editMode: Boolean(data && data.id)
+		},
+		featureGroupsList,
+		isReadOnlyMode
+	};
+};
+
+
+const mapActionsToProps = (dispatch, {licenseModelId}) => {
+	return {
+		onDeleteFeatureGroupClick: (featureGroup) => FeatureGroupsActionHelper.openDeleteFeatureGroupConfirm(dispatch, {licenseModelId, featureGroup}),
+		onCancelFeatureGroupsEditor: () => FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch),
+
+		onAddFeatureGroupClick: () => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {licenseModelId}),
+		onEditFeatureGroupClick: featureGroup => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {
+			featureGroup,
+			licenseModelId
+		})
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(FeatureGroupListEditorView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx
new file mode 100644
index 0000000..d998f92
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx
@@ -0,0 +1,136 @@
+import React from 'react';
+
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Modal from 'nfvo-components/modal/Modal.jsx';
+import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
+import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+
+import FeatureGroupEditor from './FeatureGroupEditor.js';
+import FeatureGroupsConfirmationModal from './FeatureGroupsConfirmationModal.jsx';
+
+class FeatureGroupListEditorView extends React.Component {
+	static propTypes = {
+		vendorName: React.PropTypes.string,
+		licenseModelId: React.PropTypes.string.isRequired,
+		featureGroupsModal: React.PropTypes.shape({
+			show: React.PropTypes.bool,
+			editMode: React.PropTypes.bool
+		}),
+		isReadOnlyMode: React.PropTypes.bool.isRequired,
+		onAddFeatureGroupClick: React.PropTypes.func,
+		onEditFeatureGroupClick: React.PropTypes.func,
+		onDeleteFeatureGroupClick: React.PropTypes.func,
+		onCancelFeatureGroupsEditor: React.PropTypes.func,
+		featureGroupsList: React.PropTypes.array
+	};
+
+	static defaultProps = {
+		featureGroupsList: [],
+		featureGroupsModal: {
+			show: false,
+			editMode: false
+		}
+	};
+
+	state = {
+		localFilter: ''
+	};
+
+	render() {
+		let {vendorName, licenseModelId, featureGroupsModal, isReadOnlyMode, onAddFeatureGroupClick} = this.props;
+		const {localFilter} = this.state;
+
+		return (
+			<div className='feature-groups-list-editor'>
+				<ListEditorView
+					title={i18n('Feature Groups for {vendorName} License Model', {vendorName})}
+					plusButtonTitle={i18n('Add Feature Group')}
+					filterValue={localFilter}
+					onFilter={filter => this.setState({localFilter: filter})}
+					onAdd={() => onAddFeatureGroupClick()}
+					isReadOnlyMode={isReadOnlyMode}>
+					{this.filterList().map(listItem => this.renderFeatureGroupListItem(listItem, isReadOnlyMode))}
+				</ListEditorView>
+				<Modal show={featureGroupsModal.show} bsSize='large' animation={true} className='feature-group-modal'>
+					<Modal.Header>
+						<Modal.Title>{`${featureGroupsModal.editMode ? i18n('Edit Feature Group') : i18n('Create New Feature Group')}`}</Modal.Title>
+					</Modal.Header>
+					<Modal.Body>
+						<FeatureGroupEditor
+							onCancel={() => this.closeFeatureGroupsEditor()}
+							licenseModelId={licenseModelId}
+							isReadOnlyMode={isReadOnlyMode}/>
+					</Modal.Body>
+				</Modal>
+
+				<FeatureGroupsConfirmationModal licenseModelId={licenseModelId}/>
+
+			</div>
+		);
+	}
+
+
+	renderFeatureGroupListItem(listItem, isReadOnlyMode) {
+		let {name, description, entitlementPoolsIds = [], licenseKeyGroupsIds = []} = listItem;
+		return (
+			<ListEditorItemView
+				key={listItem.id}
+				onDelete={() => this.deleteFeatureGroupItem(listItem)}
+				onSelect={() => this.editFeatureGroupItem(listItem)}
+				className='list-editor-item-view'
+				isReadOnlyMode={isReadOnlyMode}>
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Name')}</div>
+					<div className='text name'>{name}</div>
+				</div>
+
+				<div className='list-editor-item-view-field'>
+					<div className='feature-groups-count-field'>
+						<div className='title'>{i18n('Entitlement')}</div>
+						<div className='title'>{i18n('Pools')}</div>
+						<div className='feature-groups-count-ep'>{entitlementPoolsIds.length || 0}</div>
+					</div>
+					<div className='feature-groups-count-field'>
+						<div className='title'>{i18n('License key')}</div>
+						<div className='title'>{i18n('Groups')}</div>
+						<div className='feature-groups-count-lk'>{licenseKeyGroupsIds.length || 0}</div>
+					</div>
+				</div>
+
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Description')}</div>
+					<div className='text description'>{description}</div>
+				</div>
+
+			</ListEditorItemView>
+		);
+	}
+
+	filterList() {
+		let {featureGroupsList} = this.props;
+		let {localFilter} = this.state;
+		if (localFilter.trim()) {
+			const filter = new RegExp(escape(localFilter), 'i');
+			return featureGroupsList.filter(({name = '', description = ''}) => {
+				return escape(name).match(filter) || escape(description).match(filter);
+			});
+		}
+		else {
+			return featureGroupsList;
+		}
+	}
+
+	closeFeatureGroupsEditor() {
+		this.props.onCancelFeatureGroupsEditor();
+	}
+
+	editFeatureGroupItem(featureGroup) {
+		this.props.onEditFeatureGroupClick(featureGroup);
+	}
+
+	deleteFeatureGroupItem(featureGroup) {
+		this.props.onDeleteFeatureGroupClick(featureGroup);
+	}
+}
+
+export default FeatureGroupListEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js
new file mode 100644
index 0000000..3776c01
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js
@@ -0,0 +1,165 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import {actionTypes as featureGroupsActionConstants} from './FeatureGroupsConstants.js';
+import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
+import EntitlementPoolsActionHelper from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js';
+import LicenseKeyGroupsActionHelper from 'sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js';
+
+function baseUrl(licenseModelId) {
+	const restPrefix = Configuration.get('restPrefix');
+	return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/feature-groups`;
+}
+
+function fetchFeatureGroupsList(licenseModelId, version) {
+	let versionQuery = version ? `?version=${version}` : '';
+	return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`);
+}
+
+function deleteFeatureGroup(licenseModelId, featureGroupId) {
+	return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${featureGroupId}`);
+}
+
+function addFeatureGroup(licenseModelId, featureGroup) {
+	return RestAPIUtil.create(baseUrl(licenseModelId), {
+		name: featureGroup.name,
+		description: featureGroup.description,
+		partNumber: featureGroup.partNumber,
+		addedLicenseKeyGroupsIds: featureGroup.licenseKeyGroupsIds,
+		addedEntitlementPoolsIds: featureGroup.entitlementPoolsIds
+	});
+}
+
+function updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup) {
+
+	const {licenseKeyGroupsIds = []} = featureGroup;
+	const {licenseKeyGroupsIds: prevLicenseKeyGroupsIds = []} = previousFeatureGroup;
+	const {entitlementPoolsIds = []} = featureGroup;
+	const {entitlementPoolsIds: prevEntitlementPoolsIds = []} = previousFeatureGroup;
+	return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${featureGroup.id}`, {
+		name: featureGroup.name,
+		description: featureGroup.description,
+		partNumber: featureGroup.partNumber,
+		addedLicenseKeyGroupsIds: licenseKeyGroupsIds.filter(licenseKeyGroupId => prevLicenseKeyGroupsIds.indexOf(licenseKeyGroupId) === -1),
+		removedLicenseKeyGroupsIds: prevLicenseKeyGroupsIds.filter(prevLicenseKeyGroupId => licenseKeyGroupsIds.indexOf(prevLicenseKeyGroupId) === -1),
+		addedEntitlementPoolsIds: entitlementPoolsIds.filter(entitlementPoolId => prevEntitlementPoolsIds.indexOf(entitlementPoolId) === -1),
+		removedEntitlementPoolsIds: prevEntitlementPoolsIds.filter(prevEntitlementPoolId => entitlementPoolsIds.indexOf(prevEntitlementPoolId) === -1)
+
+	});
+}
+
+export default {
+	fetchFeatureGroupsList(dispatch, {licenseModelId, version}) {
+		return fetchFeatureGroupsList(licenseModelId, version).then(response => dispatch({
+			type: featureGroupsActionConstants.FEATURE_GROUPS_LIST_LOADED,
+			response
+		}));
+	},
+
+	deleteFeatureGroup(dispatch, {licenseModelId, featureGroupId}) {
+		return deleteFeatureGroup(licenseModelId, featureGroupId).then(() => dispatch({
+			type: featureGroupsActionConstants.DELETE_FEATURE_GROUPS,
+			featureGroupId
+		}));
+	},
+
+	saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup}) {
+		if (previousFeatureGroup) {
+			return updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup).then(() => dispatch({
+				type: featureGroupsActionConstants.EDIT_FEATURE_GROUPS,
+				featureGroup
+			}));
+		}
+		else {
+			return addFeatureGroup(licenseModelId, featureGroup).then(response => dispatch({
+				type: featureGroupsActionConstants.ADD_FEATURE_GROUPS,
+				featureGroup: {
+					...featureGroup,
+					id: response.value
+				}
+			}));
+		}
+	},
+
+	selectEntitlementPoolsEditorTab(dispatch, {tab}) {
+		dispatch({
+			type: featureGroupsActionConstants.featureGroupsEditor.SELECT_TAB,
+			tab
+		});
+	},
+
+	selectFeatureGroupsEditorEntitlementPoolsButtonTab(dispatch, {buttonTab}) {
+		dispatch({
+			type: featureGroupsActionConstants.featureGroupsEditor.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB,
+			buttonTab
+		});
+	},
+
+	selectFeatureGroupsEditorLicenseKeyGroupsButtonTab(dispatch, {buttonTab}) {
+		dispatch({
+			type: featureGroupsActionConstants.featureGroupsEditor.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB,
+			buttonTab
+		});
+	},
+
+	openFeatureGroupsEditor(dispatch, {featureGroup, licenseModelId}) {
+		EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId});
+		LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId});
+		dispatch({
+			type: featureGroupsActionConstants.featureGroupsEditor.OPEN,
+			featureGroup
+		});
+	},
+
+	closeFeatureGroupsEditor(dispatch) {
+		dispatch({
+			type: featureGroupsActionConstants.featureGroupsEditor.CLOSE
+		});
+	},
+
+	featureGroupsEditorDataChanged(dispatch, {deltaData}) {
+		dispatch({
+			type: featureGroupsActionConstants.featureGroupsEditor.DATA_CHANGED,
+			deltaData
+		});
+	},
+
+	hideDeleteConfirm(dispatch) {
+		dispatch({
+			type: featureGroupsActionConstants.FEATURE_GROUPS_DELETE_CONFIRM,
+			featureGroupToDelete: false
+		});
+	},
+
+	openDeleteFeatureGroupConfirm(dispatch, {featureGroup}) {
+		dispatch({
+			type: featureGroupsActionConstants.FEATURE_GROUPS_DELETE_CONFIRM,
+			featureGroupToDelete: featureGroup
+		});
+	},
+
+	switchVersion(dispatch, {licenseModelId, version}) {
+		LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
+			this.fetchFeatureGroupsList(dispatch, {licenseModelId, version});
+		});
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConfirmationModal.jsx
new file mode 100644
index 0000000..142ec3c
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConfirmationModal.jsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import {connect} from 'react-redux';
+import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
+import FeatureGroupsActionHelper from './FeatureGroupsActionHelper.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+function renderMsg(featureGroupToDelete) {
+	let name = featureGroupToDelete ? featureGroupToDelete.name : '';
+	let msg = i18n('Are you sure you want to delete "{name}"?', {name});
+	let subMsg = featureGroupToDelete
+	&& featureGroupToDelete.referencingLicenseAgreements
+	&& featureGroupToDelete.referencingLicenseAgreements.length > 0 ?
+		i18n('This feature group is associated with one ore more license agreements') :
+		'';
+	return (
+		<div>
+			<p>{msg}</p>
+			<p>{subMsg}</p>
+		</div>
+	);
+};
+
+const mapStateToProps = ({licenseModel: {featureGroup}}, {licenseModelId}) => {
+	let {featureGroupToDelete} = featureGroup;
+	const show = featureGroupToDelete !== false;
+	return {
+		show,
+		title: 'Warning!',
+		type: 'warning',
+		msg: renderMsg(featureGroupToDelete),
+		confirmationDetails: {featureGroupToDelete, licenseModelId}
+	};
+};
+
+const mapActionsToProps = (dispatch) => {
+	return {
+		onConfirmed: ({featureGroupToDelete, licenseModelId}) => {
+			FeatureGroupsActionHelper.deleteFeatureGroup(dispatch, {featureGroupId: featureGroupToDelete.id, licenseModelId});
+			FeatureGroupsActionHelper.hideDeleteConfirm(dispatch);
+		},
+		onDeclined: () => {
+			FeatureGroupsActionHelper.hideDeleteConfirm(dispatch);
+		}
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js
new file mode 100644
index 0000000..e02c545
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+	FEATURE_GROUPS_LIST_LOADED: null,
+	ADD_FEATURE_GROUPS: null,
+	EDIT_FEATURE_GROUPS: null,
+	DELETE_FEATURE_GROUPS: null,
+	FEATURE_GROUPS_DELETE_CONFIRM: null,
+
+
+	ENTITLEMENT_POOLS_LIST_LOADED: null,
+
+	featureGroupsEditor: {
+		OPEN: null,
+		CLOSE: null,
+		DATA_CHANGED: null,
+		SELECT_TAB: null,
+		SELECTED_ENTITLEMENT_POOLS_BUTTONTAB: null,
+		SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB: null
+	}
+});
+
+export const state = keyMirror({
+	SELECTED_FEATURE_GROUP_TAB: {
+		GENERAL: 1,
+		ENTITLEMENT_POOLS: 2,
+		LICENCE_KEY_GROUPS: 3
+	},
+	SELECTED_ENTITLEMENT_POOLS_BUTTONTAB: {
+		ASSOCIATED_ENTITLEMENT_POOLS: 1,
+		AVAILABLE_ENTITLEMENT_POOLS: 2
+	},
+	SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB: {
+		ASSOCIATED_LICENSE_KEY_GROUPS: 1,
+		AVAILABLE_LICENSE_KEY_GROUPS: 2
+	},
+});
+
+
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js
new file mode 100644
index 0000000..576a535
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes} from './FeatureGroupsConstants.js';
+
+
+
+export default (state = {}, action) => {
+	switch (action.type) {
+		case actionTypes.featureGroupsEditor.OPEN:
+			return {
+				...state,
+				data: action.featureGroup || {}
+			};
+		case actionTypes.featureGroupsEditor.DATA_CHANGED:
+			return {
+				...state,
+				data: {
+					...state.data,
+					...action.deltaData
+				}
+			};
+		case actionTypes.featureGroupsEditor.CLOSE:
+			return {};
+		case actionTypes.featureGroupsEditor.SELECT_TAB:
+			return {
+				...state,
+				selectedTab: action.tab
+			};
+
+		case actionTypes.featureGroupsEditor.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB:
+			return {
+				...state,
+				selectedEntitlementPoolsButtonTab: action.buttonTab
+			};
+		case actionTypes.featureGroupsEditor.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB:
+			return {
+				...state,
+				selectedLicenseKeyGroupsButtonTab: action.buttonTab
+			};
+		default:
+			return state;
+	}
+
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js
new file mode 100644
index 0000000..5cf3248
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes} from './FeatureGroupsConstants.js';
+export default (state = [], action) => {
+	switch (action.type) {
+		case actionTypes.FEATURE_GROUPS_LIST_LOADED:
+			return [...action.response.results];
+		case actionTypes.ADD_FEATURE_GROUPS:
+			return [...state, action.featureGroup];
+		case actionTypes.EDIT_FEATURE_GROUPS:
+			const indexForEdit = state.findIndex(featureGroup => featureGroup.id === action.featureGroup.id);
+			return [...state.slice(0, indexForEdit), action.featureGroup, ...state.slice(indexForEdit + 1)];
+		case actionTypes.DELETE_FEATURE_GROUPS:
+			return state.filter(featureGroup => featureGroup.id !== action.featureGroupId);
+		default:
+			return state;
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js
new file mode 100644
index 0000000..9616b60
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js
@@ -0,0 +1,160 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import {actionTypes as licenseAgreementActionTypes} from './LicenseAgreementConstants.js';
+import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
+import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
+
+function baseUrl(licenseModelId) {
+	const restPrefix = Configuration.get('restPrefix');
+	return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/license-agreements`;
+}
+
+function fetchLicenseAgreementList(licenseModelId, version) {
+	let versionQuery = version ? `?version=${version}` : '';
+	return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`);
+}
+
+function postLicenseAgreement(licenseModelId, licenseAgreement) {
+	return RestAPIUtil.create(baseUrl(licenseModelId), {
+		name: licenseAgreement.name,
+		description: licenseAgreement.description,
+		licenseTerm: licenseAgreement.licenseTerm,
+		requirementsAndConstrains: licenseAgreement.requirementsAndConstrains,
+		addedFeatureGroupsIds: licenseAgreement.featureGroupsIds
+	});
+}
+
+function putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement) {
+	const {featureGroupsIds = []} = licenseAgreement;
+	const {featureGroupsIds: prevFeatureGroupsIds = []} = previousLicenseAgreement;
+	return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${licenseAgreement.id}`, {
+		name: licenseAgreement.name,
+		description: licenseAgreement.description,
+		licenseTerm: licenseAgreement.licenseTerm,
+		requirementsAndConstrains: licenseAgreement.requirementsAndConstrains,
+		addedFeatureGroupsIds: featureGroupsIds.filter(featureGroupId => prevFeatureGroupsIds.indexOf(featureGroupId) === -1),
+		removedFeatureGroupsIds: prevFeatureGroupsIds.filter(prevFeatureGroupsId => featureGroupsIds.indexOf(prevFeatureGroupsId) === -1)
+	});
+}
+
+function deleteLicenseAgreement(licenseModelId, licenseAgreementId) {
+	return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${licenseAgreementId}`);
+}
+
+export default {
+
+	fetchLicenseAgreementList(dispatch, {licenseModelId, version}) {
+		return fetchLicenseAgreementList(licenseModelId, version).then(response => dispatch({
+			type: licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED,
+			response
+		}));
+	},
+
+	openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement}) {
+		FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId});
+		dispatch({
+			type: licenseAgreementActionTypes.licenseAgreementEditor.OPEN,
+			licenseAgreement
+		});
+	},
+
+	licenseAgreementEditorDataChanged(dispatch, {deltaData}) {
+		dispatch({
+			type: licenseAgreementActionTypes.licenseAgreementEditor.DATA_CHANGED,
+			deltaData
+		});
+	},
+
+	closeLicenseAgreementEditor(dispatch) {
+		dispatch({
+			type: licenseAgreementActionTypes.licenseAgreementEditor.CLOSE
+		});
+	},
+
+
+	saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement}) {
+		if (previousLicenseAgreement) {
+			return putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement).then(() => {
+				dispatch({
+					type: licenseAgreementActionTypes.EDIT_LICENSE_AGREEMENT,
+					licenseAgreement
+				});
+			});
+		}
+		else {
+			return postLicenseAgreement(licenseModelId, licenseAgreement).then(response => {
+				dispatch({
+					type: licenseAgreementActionTypes.ADD_LICENSE_AGREEMENT,
+					licenseAgreement: {
+						...licenseAgreement,
+						id: response.value
+					}
+				});
+			});
+		}
+	},
+
+	deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId}) {
+		return deleteLicenseAgreement(licenseModelId, licenseAgreementId).then(() => {
+			dispatch({
+				type: licenseAgreementActionTypes.DELETE_LICENSE_AGREEMENT,
+				licenseAgreementId
+			});
+		});
+	},
+
+	selectLicenseAgreementEditorTab(dispatch, {tab}) {
+		dispatch({
+			type: licenseAgreementActionTypes.licenseAgreementEditor.SELECT_TAB,
+			tab
+		});
+	},
+
+	selectLicenseAgreementEditorFeatureGroupsButtonTab(dispatch, {buttonTab}) {
+		dispatch({
+			type: licenseAgreementActionTypes.licenseAgreementEditor.SELECT_FEATURE_GROUPS_BUTTONTAB,
+			buttonTab
+		});
+	},
+
+	hideDeleteConfirm(dispatch) {
+		dispatch({
+			type: licenseAgreementActionTypes.LICENSE_AGREEMENT_DELETE_CONFIRM,
+			licenseAgreementToDelete: false
+		});
+	},
+
+	openDeleteLicenseAgreementConfirm(dispatch, {licenseAgreement} ) {
+		dispatch({
+			type: licenseAgreementActionTypes.LICENSE_AGREEMENT_DELETE_CONFIRM,
+			licenseAgreementToDelete: licenseAgreement
+		});
+	},
+
+	switchVersion(dispatch, {licenseModelId, version}) {
+		LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
+			this.fetchLicenseAgreementList(dispatch, {licenseModelId, version});
+		});
+	}
+};
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx
new file mode 100644
index 0000000..42f2407
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import {connect} from 'react-redux';
+import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
+import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+function renderMsg(licenseAgreementToDelete) {
+	let name = licenseAgreementToDelete ? licenseAgreementToDelete.name : '';
+	let msg = i18n('Are you sure you want to delete "{name}"?', {name});
+	return(
+		<div>
+			<p>{msg}</p>
+		</div>
+	);
+};
+
+const mapStateToProps = ({licenseModel: {licenseAgreement}}, {licenseModelId}) => {
+	let {licenseAgreementToDelete} = licenseAgreement;
+	const show = licenseAgreementToDelete !== false;
+	return {
+		show,
+		title: 'Warning!',
+		type: 'warning',
+		msg: renderMsg(licenseAgreementToDelete),
+		confirmationDetails: {licenseAgreementToDelete, licenseModelId}
+	};
+};
+
+const mapActionsToProps = (dispatch) => {
+	return {
+		onConfirmed: ({licenseAgreementToDelete, licenseModelId}) => {
+
+			LicenseAgreementActionHelper.deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId: licenseAgreementToDelete.id});
+			LicenseAgreementActionHelper.hideDeleteConfirm(dispatch);
+		},
+		onDeclined: () => {
+			LicenseAgreementActionHelper.hideDeleteConfirm(dispatch);
+		}
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js
new file mode 100644
index 0000000..af5c454
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+export const actionTypes = keyMirror({
+	LICENSE_AGREEMENT_LIST_LOADED: null,
+	ADD_LICENSE_AGREEMENT: null,
+	EDIT_LICENSE_AGREEMENT: null,
+	DELETE_LICENSE_AGREEMENT: null,
+	LICENSE_AGREEMENT_DELETE_CONFIRM: null,
+
+	licenseAgreementEditor: {
+		OPEN: null,
+		CLOSE: null,
+		DATA_CHANGED: null,
+		SELECT_TAB: null,
+		SELECT_FEATURE_GROUPS_BUTTONTAB: null,
+	}
+
+});
+
+export const enums = keyMirror({
+	SELECTED_LICENSE_AGREEMENT_TAB: {
+		GENERAL: 1,
+		FEATURE_GROUPS: 2
+	},
+
+	SELECTED_FEATURE_GROUPS_BUTTONTAB: {
+		ASSOCIATED_FEATURE_GROUPS: 1,
+		AVAILABLE_FEATURE_GROUPS: 2
+	}
+});
+
+export const defaultState = {
+	LICENSE_AGREEMENT_EDITOR_DATA: {
+		licenseTerm: {choice: '', other: ''}
+	}
+};
+
+export const optionsInputValues = {
+	LICENSE_MODEL_TYPE: [
+		{enum: '', title: i18n('please select…')},
+		{enum: 'Fixed_Term', title: 'Fixed Term'},
+		{enum: 'Perpetual', title: 'Perpetual'},
+		{enum: 'Unlimited', title: 'Unlimited'}
+	]
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js
new file mode 100644
index 0000000..6a3e4db
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {connect} from 'react-redux';
+import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js';
+import LicenseAgreementEditorView from './LicenseAgreementEditorView.jsx';
+
+export const mapStateToProps = ({licenseModel: {licenseAgreement, featureGroup}}) => {
+
+
+	let {data, selectedTab, selectedFeatureGroupsButtonTab} = licenseAgreement.licenseAgreementEditor;
+
+	let previousData;
+	const licenseAgreementId = data ? data.id : null;
+	if(licenseAgreementId) {
+		previousData = licenseAgreement.licenseAgreementList.find(licenseAgreement => licenseAgreement.id === licenseAgreementId);
+	}
+
+	const {featureGroupsList = []} = featureGroup;
+
+	return {
+		data,
+		previousData,
+		selectedTab,
+		selectedFeatureGroupsButtonTab,
+		featureGroupsList
+	};
+};
+
+export const mapActionsToProps = (dispatch, {licenseModelId}) => {
+	return {
+		onDataChanged: deltaData => LicenseAgreementActionHelper.licenseAgreementEditorDataChanged(dispatch, {deltaData}),
+		onTabSelect: tab => LicenseAgreementActionHelper.selectLicenseAgreementEditorTab(dispatch, {tab}),
+		onFeatureGroupsButtonTabSelect: buttonTab => LicenseAgreementActionHelper.selectLicenseAgreementEditorFeatureGroupsButtonTab(dispatch, {buttonTab}),
+		onCancel: () => LicenseAgreementActionHelper.closeLicenseAgreementEditor(dispatch),
+		onSubmit: ({previousLicenseAgreement, licenseAgreement}) => {
+			LicenseAgreementActionHelper.closeLicenseAgreementEditor(dispatch);
+			LicenseAgreementActionHelper.saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement});
+		}
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(LicenseAgreementEditorView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
new file mode 100644
index 0000000..74e2f6e
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes, defaultState} from './LicenseAgreementConstants.js';
+
+export default (state = {}, action) => {
+	switch (action.type) {
+		case actionTypes.licenseAgreementEditor.OPEN:
+			return {
+				...state,
+				data: action.licenseAgreement ? { ...action.licenseAgreement } : defaultState.LICENSE_AGREEMENT_EDITOR_DATA
+			};
+		case actionTypes.licenseAgreementEditor.DATA_CHANGED:
+			return {
+				...state,
+				data: {
+					...state.data,
+					...action.deltaData
+				}
+			};
+		case actionTypes.licenseAgreementEditor.CLOSE:
+			return {};
+		case actionTypes.licenseAgreementEditor.SELECT_TAB:
+			return {
+				...state,
+				selectedTab: action.tab
+			};
+		case actionTypes.licenseAgreementEditor.SELECT_FEATURE_GROUPS_BUTTONTAB:
+			return {
+				...state,
+				selectedFeatureGroupsButtonTab: action.buttonTab
+			};
+		default:
+			return state;
+	}
+
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
new file mode 100644
index 0000000..b21f943
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
@@ -0,0 +1,247 @@
+import React from 'react';
+import ButtonGroup from 'react-bootstrap/lib/ButtonGroup.js';
+import Button from 'react-bootstrap/lib/Button.js';
+import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
+import ValidationTabs from 'nfvo-components/input/validation/ValidationTabs.jsx';
+import ValidationTab from 'nfvo-components/input/validation/ValidationTab.jsx';
+import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
+import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx';
+import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
+import ListEditorViewItem from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+import {enums as LicenseAgreementEnums, optionsInputValues as LicenseAgreementOptionsInputValues} from './LicenseAgreementConstants.js';
+
+
+const LicenseAgreementPropType = React.PropTypes.shape({
+	id: React.PropTypes.string,
+	name: React.PropTypes.string,
+	description: React.PropTypes.string,
+	requirementsAndConstrains: React.PropTypes.string,
+	licenseTerm: React.PropTypes.object,
+	featureGroupsIds: React.PropTypes.arrayOf(React.PropTypes.string)
+});
+
+class LicenseAgreementEditorView extends React.Component {
+
+	static propTypes = {
+		data: LicenseAgreementPropType,
+		previousData: LicenseAgreementPropType,
+		isReadOnlyMode: React.PropTypes.bool,
+		onDataChanged: React.PropTypes.func.isRequired,
+		onSubmit: React.PropTypes.func.isRequired,
+		onCancel: React.PropTypes.func.isRequired,
+
+		selectedTab: React.PropTypes.number,
+		onTabSelect: React.PropTypes.func,
+
+		selectedFeatureGroupsButtonTab: React.PropTypes.number,
+		onFeatureGroupsButtonTabSelect: React.PropTypes.func,
+		featureGroupsList: DualListboxView.propTypes.availableList
+	};
+
+	static defaultProps = {
+		selectedTab: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL,
+		selectedFeatureGroupsButtonTab: LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS,
+		data: {}
+	};
+
+	state = {
+		localFeatureGroupsListFilter: ''
+	};
+
+	render() {
+		let {selectedTab, onTabSelect, isReadOnlyMode} = this.props;
+		return (
+			<ValidationForm
+				ref='validationForm'
+				hasButtons={true}
+				onSubmit={ () => this.submit() }
+				onReset={ () => this.props.onCancel() }
+				labledButtons={true}
+				isReadOnlyMode={isReadOnlyMode}
+				className='license-agreement-form'>
+				<ValidationTabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect}>
+					{this.renderGeneralTab()}
+					{this.renderFeatureGroupsTab()}
+				</ValidationTabs>
+			</ValidationForm>
+		);
+	}
+
+	submit() {
+		const {data: licenseAgreement, previousData: previousLicenseAgreement} = this.props;
+		this.props.onSubmit({licenseAgreement, previousLicenseAgreement});
+	}
+
+	renderGeneralTab() {
+		let {data = {}, onDataChanged} = this.props;
+		let {name, description, requirementsAndConstrains, licenseTerm} = data;
+		return (
+			<ValidationTab
+				eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL}
+				title={i18n('General')}>
+				<div className='license-agreement-form-row'>
+					<div className='license-agreement-form-col'>
+						<ValidationInput
+							onChange={name => onDataChanged({name})}
+							label={i18n('Name')}
+							value={name}
+							name='license-agreement-name'
+							validations={{maxLength: 25, required: true}}
+							type='text'/>
+						<ValidationInput
+							onChange={requirementsAndConstrains => onDataChanged({requirementsAndConstrains})}
+							label={i18n('Requirements and Constraints')}
+							value={requirementsAndConstrains}
+							name='license-agreement-requirements-and-constraints'
+							validations={{maxLength: 1000}}
+							type='textarea'/>
+					</div>
+					<ValidationInput
+						onChange={description => onDataChanged({description})}
+						label={i18n('Description')}
+						value={description}
+						name='license-agreement-description'
+						validations={{maxLength: 1000, required: true}}
+						type='textarea'/>
+				</div>
+				<div className='license-agreement-form-row'>
+					<ValidationInput
+						onEnumChange={licenseTerm => onDataChanged({licenseTerm:{choice: licenseTerm, other: ''}})}
+						selectedEnum={licenseTerm && licenseTerm.choice}
+						validations={{required: true}}
+						type='select'
+						label={i18n('License Term')}
+						values={LicenseAgreementOptionsInputValues.LICENSE_MODEL_TYPE}/>
+				</div>
+			</ValidationTab>
+		);
+	}
+
+	renderFeatureGroupsTab() {
+		let {onFeatureGroupsButtonTabSelect, selectedFeatureGroupsButtonTab, featureGroupsList} = this.props;
+		if (featureGroupsList.length > 0) {
+			return (
+				<ValidationTab
+					eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS}
+					title={i18n('Feature Groups')}>
+					<ButtonGroup>
+						{
+							this.renderFeatureGroupsButtonTab(
+								LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.ASSOCIATED_FEATURE_GROUPS,
+								selectedFeatureGroupsButtonTab,
+								i18n('Associated Feature Groups'),
+								onFeatureGroupsButtonTabSelect
+							)
+						}
+						{
+							this.renderFeatureGroupsButtonTab(
+								LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS,
+								selectedFeatureGroupsButtonTab,
+								i18n('Available Feature Groups'),
+								onFeatureGroupsButtonTabSelect
+							)
+						}
+					</ButtonGroup>
+					{this.renderFeatureGroupsButtonTabContent(selectedFeatureGroupsButtonTab)}
+				</ValidationTab>
+			);
+		} else {
+			return (
+				<ValidationTab
+					eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS}
+					title={i18n('Feature Groups')}>
+					<p>{i18n('There is no available feature groups')}</p>
+				</ValidationTab>
+			);
+		}
+	}
+
+	renderFeatureGroupsButtonTabContent(selectedFeatureGroupsButtonTab) {
+		const {featureGroupsList = [], data: {featureGroupsIds = []}} = this.props;
+		const {localFeatureGroupsListFilter} = this.state;
+		let selectedFeatureGroups = featureGroupsIds.map(featureGroupId => featureGroupsList.find(featureGroup => featureGroup.id === featureGroupId));
+
+		const dualBoxFilterTitle = {
+			left: i18n('Available Feature Groups'),
+			right: i18n('Selected Feature Groups')
+		};
+
+		switch (selectedFeatureGroupsButtonTab) {
+			case LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.ASSOCIATED_FEATURE_GROUPS:
+				if (!selectedFeatureGroups.length) {
+					return (
+						<div className='no-items-msg'>
+							{i18n('There are currently no feature groups associated with this license agreement. Click "Available Feature Groups" to associate.')}
+						</div>
+					);
+				}
+				if (featureGroupsList.length) {
+					return (
+						<ListEditorView
+							className='thinner-list'
+							filterValue={localFeatureGroupsListFilter}
+							onFilter={localFeatureGroupsListFilter => this.setState({localFeatureGroupsListFilter})}>
+							{this.filterAssociatedFeatureGroupsList(selectedFeatureGroups).map(featureGroup => this.renderAssociatedFeatureGroupListItem(featureGroup))}
+						</ListEditorView>
+					);
+				}
+				return;
+			case LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS:
+				return (
+					<DualListboxView
+						filterTitle={dualBoxFilterTitle}
+						selectedValuesList={this.props.data.featureGroupsIds}
+						availableList={this.props.featureGroupsList}
+						onChange={ selectedValuesList => this.props.onDataChanged( { featureGroupsIds: selectedValuesList } )}/>
+				);
+		}
+	}
+
+	renderFeatureGroupsButtonTab(buttonTab, selectedButtonTab, title, onClick) {
+		const isSelected = buttonTab === selectedButtonTab;
+		return (
+			<Button
+				className='button-tab'
+				active={isSelected}
+				onClick={() => !isSelected && onClick(buttonTab)}>
+				{ title }
+			</Button>
+		);
+	}
+
+	renderAssociatedFeatureGroupListItem({id, name, entitlementPoolsIds = [], licenseKeyGroupsIds = []}) {
+		const {onDataChanged, data: {featureGroupsIds}, isReadOnlyMode} = this.props;
+		return (
+			<ListEditorViewItem
+				key={id}
+				onDelete={() => onDataChanged({featureGroupsIds: featureGroupsIds.filter(featureGroupId => featureGroupId !== id)})}
+				isReadOnlyMode={isReadOnlyMode}>
+				<div className='name'>{name}</div>
+				<div className='inner-objects-count'>{
+					i18n(
+						'Entitlement Pools({entitlementPoolsCounter}), License Key Groups({licenseKeyGroupsCount})',
+						{
+							entitlementPoolsCounter: entitlementPoolsIds.length,
+							licenseKeyGroupsCount: licenseKeyGroupsIds.length
+						}
+					)
+				}</div>
+			</ListEditorViewItem>
+		);
+	}
+
+	filterAssociatedFeatureGroupsList(featureGroupsList) {
+		let {localFeatureGroupsListFilter} = this.state;
+		if (localFeatureGroupsListFilter) {
+			const filter = new RegExp(escape(localFeatureGroupsListFilter), 'i');
+			return featureGroupsList.filter(({name}) => name.match(filter));
+		}
+		else {
+			return featureGroupsList;
+		}
+	}
+}
+
+export default LicenseAgreementEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js
new file mode 100644
index 0000000..ca18bfa
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {connect} from 'react-redux';
+import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
+import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js';
+import LicenseAgreementListEditorView from './LicenseAgreementListEditorView.jsx';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
+
+const mapStateToProps = ({licenseModel: {licenseAgreement, licenseModelEditor}}) => {
+	let {licenseAgreementList} = licenseAgreement;
+	let {data} = licenseAgreement.licenseAgreementEditor;
+	let {vendorName} = licenseModelEditor.data;
+
+	let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data);
+
+	return {
+		vendorName,
+		licenseAgreementList,
+		isReadOnlyMode,
+		isDisplayModal: Boolean(data),
+		isModalInEditMode: Boolean(data && data.id)
+	};
+};
+
+const mapActionsToProps = (dispatch, {licenseModelId}) => {
+	return {
+		onAddLicenseAgreementClick: () => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId}),
+		onEditLicenseAgreementClick: licenseAgreement => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement}),
+		onDeleteLicenseAgreement: licenseAgreement => LicenseAgreementActionHelper.openDeleteLicenseAgreementConfirm(dispatch, {licenseAgreement}),
+		onCallVCAction: action => {
+			LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action}).then(() => {
+				LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId});
+			});
+		},
+		switchLicenseModelVersion: version => LicenseAgreementActionHelper.switchVersion(dispatch, {licenseModelId, version}),
+		onClose: () => OnboardingActionHelper.navigateToOnboardingCatalog(dispatch)
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(LicenseAgreementListEditorView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx
new file mode 100644
index 0000000..4d7e704
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx
@@ -0,0 +1,126 @@
+import React from 'react';
+
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Modal from 'nfvo-components/modal/Modal.jsx';
+
+import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
+import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+import LicenseAgreementEditor from './LicenseAgreementEditor.js';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+import {optionsInputValues} from './LicenseAgreementConstants';
+import LicenseAgreementConfirmationModal from './LicenseAgreementConfirmationModal.jsx';
+
+
+class LicenseAgreementListEditorView extends React.Component {
+	static propTypes = {
+		vendorName: React.PropTypes.string,
+		licenseModelId: React.PropTypes.string.isRequired,
+		licenseAgreementList: React.PropTypes.array,
+		isReadOnlyMode: React.PropTypes.bool.isRequired,
+		isDisplayModal: React.PropTypes.bool,
+		isModalInEditMode: React.PropTypes.bool,
+		onAddLicenseAgreementClick: React.PropTypes.func,
+		onEditLicenseAgreementClick: React.PropTypes.func,
+		onDeleteLicenseAgreement: React.PropTypes.func,
+		onCallVCAction: React.PropTypes.func
+	};
+
+	static defaultProps = {
+		licenseAgreementList: []
+	};
+
+	state = {
+		localFilter: ''
+	};
+
+	render() {
+		const {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props;
+		const {onAddLicenseAgreementClick} = this.props;
+		const {localFilter} = this.state;
+
+		return (
+			<div className='license-agreement-list-editor'>
+					<ListEditorView
+						title={i18n('License Agreements for {vendorName} License Model', {vendorName})}
+						plusButtonTitle={i18n('Add License Agreement')}
+						onAdd={onAddLicenseAgreementClick}
+						filterValue={localFilter}
+						onFilter={filter => this.setState({localFilter: filter})}
+						isReadOnlyMode={isReadOnlyMode}>
+						{this.filterList().map(licenseAgreement => this.renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode))}
+					</ListEditorView>
+				<Modal show={isDisplayModal} bsSize='large' animation={true} className='license-agreement-modal'>
+					<Modal.Header>
+						<Modal.Title>{`${isModalInEditMode ? i18n('Edit License Agreement') : i18n('Create New License Agreement')}`}</Modal.Title>
+					</Modal.Header>
+					<Modal.Body>
+						{
+							isDisplayModal && (
+								<LicenseAgreementEditor licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode} />
+							)
+						}
+					</Modal.Body>
+				</Modal>
+				<LicenseAgreementConfirmationModal licenseModelId={licenseModelId}/>
+
+			</div>
+		);
+	}
+
+	filterList() {
+		let {licenseAgreementList} = this.props;
+		let {localFilter} = this.state;
+		if (localFilter.trim()) {
+			const filter = new RegExp(escape(localFilter), 'i');
+			return licenseAgreementList.filter(({name = '', description = '', licenseTerm = ''}) => {
+				return escape(name).match(filter) || escape(description).match(filter) || escape(this.extractValue(licenseTerm)).match(filter);
+			});
+		}
+		else {
+			return licenseAgreementList;
+		}
+	}
+
+	renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode) {
+		let {id, name, description, licenseTerm, featureGroupsIds = []} = licenseAgreement;
+		let {onEditLicenseAgreementClick, onDeleteLicenseAgreement} = this.props;
+		return (
+			<ListEditorItemView
+				key={id}
+				onSelect={() => onEditLicenseAgreementClick(licenseAgreement)}
+				onDelete={() => onDeleteLicenseAgreement(licenseAgreement)}
+				className='list-editor-item-view'
+				isReadOnlyMode={isReadOnlyMode}>
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Name')}</div>
+					<div className='text name'>{name}</div>
+				</div>
+				<div className='list-editor-item-view-field'>
+					<div className='list-editor-item-view-field-tight'>
+						<div className='title'>{i18n('Type')}</div>
+						<div className='text type'>{this.extractValue(licenseTerm)}</div>
+					</div>
+					<div className='list-editor-item-view-field-tight'>
+						<div className='title'>{i18n('Feature')}</div>
+						<div className='title'>{i18n('Groups')}</div>
+						<div className='feature-groups-count'>{featureGroupsIds.length}</div>
+					</div>
+				</div>
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Description')}</div>
+					<div className='text description'>{description}</div>
+				</div>
+			</ListEditorItemView>
+		);
+	}
+
+	extractValue(item) {
+		if (item === undefined) {
+			return '';
+		} //TODO fix it later
+
+		return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
+	}
+}
+
+export default LicenseAgreementListEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js
new file mode 100644
index 0000000..5b5fa00
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes as licenseAgreementActionTypes} from './LicenseAgreementConstants';
+
+export default (state = [], action) => {
+	switch (action.type) {
+		case licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED:
+			return [...action.response.results];
+		case licenseAgreementActionTypes.ADD_LICENSE_AGREEMENT:
+			return [...state, action.licenseAgreement];
+		case licenseAgreementActionTypes.EDIT_LICENSE_AGREEMENT:
+			const indexForEdit = state.findIndex(licenseAgreement => licenseAgreement.id === action.licenseAgreement.id);
+			return [...state.slice(0, indexForEdit), action.licenseAgreement, ...state.slice(indexForEdit + 1)];
+		case licenseAgreementActionTypes.DELETE_LICENSE_AGREEMENT:
+			return state.filter(licenseAgreement => licenseAgreement.id !== action.licenseAgreementId);
+		default:
+			return state;
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js
new file mode 100644
index 0000000..50ac2c8
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js
@@ -0,0 +1,139 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import {actionTypes as licenseKeyGroupsConstants} from './LicenseKeyGroupsConstants.js';
+import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
+
+function baseUrl(licenseModelId) {
+	const restPrefix = Configuration.get('restPrefix');
+	return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/license-key-groups`;
+}
+
+function fetchLicenseKeyGroupsList(licenseModelId, version) {
+	let versionQuery = version ? `?version=${version}` : '';
+	return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`);
+}
+
+function deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId) {
+	return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${licenseKeyGroupId}`);
+}
+
+function postLicenseKeyGroup(licenseModelId, licenseKeyGroup) {
+	return RestAPIUtil.create(baseUrl(licenseModelId), {
+		name: licenseKeyGroup.name,
+		description: licenseKeyGroup.description,
+		operationalScope: licenseKeyGroup.operationalScope,
+		type: licenseKeyGroup.type
+	});
+}
+
+function putLicenseKeyGroup(licenseModelId, licenseKeyGroup) {
+	return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${licenseKeyGroup.id}`, {
+		name: licenseKeyGroup.name,
+		description: licenseKeyGroup.description,
+		operationalScope: licenseKeyGroup.operationalScope,
+		type: licenseKeyGroup.type
+	});
+}
+
+
+export default {
+	fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version}) {
+		return fetchLicenseKeyGroupsList(licenseModelId, version).then(response => dispatch({
+			type: licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_LIST_LOADED,
+			response
+		}));
+	},
+
+	openLicenseKeyGroupsEditor(dispatch, {licenseKeyGroup} = {}) {
+		dispatch({
+			type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.OPEN,
+			licenseKeyGroup
+		});
+	},
+
+	closeLicenseKeyGroupEditor(dispatch){
+		dispatch({
+			type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.CLOSE
+		});
+	},
+
+	saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup}) {
+		if (previousLicenseKeyGroup) {
+			return putLicenseKeyGroup(licenseModelId, licenseKeyGroup).then(() => {
+				dispatch({
+					type: licenseKeyGroupsConstants.EDIT_LICENSE_KEY_GROUP,
+					licenseKeyGroup
+				});
+			});
+		}
+		else {
+			return postLicenseKeyGroup(licenseModelId, licenseKeyGroup).then(response => {
+				dispatch({
+					type: licenseKeyGroupsConstants.ADD_LICENSE_KEY_GROUP,
+					licenseKeyGroup: {
+						...licenseKeyGroup,
+						id: response.value
+					}
+				});
+			});
+		}
+
+
+	},
+
+	deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId}){
+		return deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId).then(()=> {
+			dispatch({
+				type: licenseKeyGroupsConstants.DELETE_LICENSE_KEY_GROUP,
+				licenseKeyGroupId
+			});
+		});
+	},
+
+	licenseKeyGroupEditorDataChanged(dispatch, {deltaData}) {
+		dispatch({
+			type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.DATA_CHANGED,
+			deltaData
+		});
+	},
+
+	hideDeleteConfirm(dispatch) {
+		dispatch({
+			type: licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM,
+			licenseKeyGroupToDelete: false
+		});
+	},
+
+	openDeleteLicenseAgreementConfirm(dispatch, {licenseKeyGroup}) {
+		dispatch({
+			type: licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM,
+			licenseKeyGroupToDelete: licenseKeyGroup
+		});
+	},
+
+	switchVersion(dispatch, {licenseModelId, version}) {
+		LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
+			this.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version});
+		});
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConfirmationModal.jsx
new file mode 100644
index 0000000..2413db5
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConfirmationModal.jsx
@@ -0,0 +1,49 @@
+import React from 'react';
+import {connect} from 'react-redux';
+import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
+import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+function renderMsg(licenseKeyGroupToDelete) {
+	let name = licenseKeyGroupToDelete ? licenseKeyGroupToDelete.name : '';
+	let msg = i18n('Are you sure you want to delete "{name}"?', {name});
+	let subMsg =  licenseKeyGroupToDelete
+					&& licenseKeyGroupToDelete.referencingFeatureGroups
+					&& licenseKeyGroupToDelete.referencingFeatureGroups.length > 0 ?
+					i18n('This license key group is associated with one or more feature groups') :
+					'';
+	return(
+		<div>
+			<p>{msg}</p>
+			<p>{subMsg}</p>
+		</div>
+	);
+};
+
+const mapStateToProps = ({licenseModel: {licenseKeyGroup}}, {licenseModelId}) => {
+	let {licenseKeyGroupToDelete} = licenseKeyGroup;
+	const show = licenseKeyGroupToDelete !== false;
+	return {
+		show,
+		title: 'Warning!',
+		type: 'warning',
+		msg: renderMsg(licenseKeyGroupToDelete),
+		confirmationDetails: {licenseKeyGroupToDelete, licenseModelId}
+	};
+};
+
+const mapActionsToProps = (dispatch) => {
+	return {
+		onConfirmed: ({licenseKeyGroupToDelete, licenseModelId}) => {
+
+			LicenseKeyGroupsActionHelper.deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId:licenseKeyGroupToDelete.id});
+			LicenseKeyGroupsActionHelper.hideDeleteConfirm(dispatch);
+		},
+		onDeclined: () => {
+			LicenseKeyGroupsActionHelper.hideDeleteConfirm(dispatch);
+		}
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js
new file mode 100644
index 0000000..d32bc52
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+export const actionTypes = keyMirror({
+
+	LICENSE_KEY_GROUPS_LIST_LOADED: null,
+	DELETE_LICENSE_KEY_GROUP: null,
+	EDIT_LICENSE_KEY_GROUP: null,
+	ADD_LICENSE_KEY_GROUP: null,
+	LICENSE_KEY_GROUPS_DELETE_CONFIRM: null,
+	licenseKeyGroupsEditor: {
+		OPEN: null,
+		CLOSE: null,
+		DATA_CHANGED: null,
+	}
+});
+
+export const defaultState = {
+	licenseKeyGroupsEditor: {
+		type: '',
+		operationalScope: {choices: [], other: ''}
+	}
+};
+
+export const optionsInputValues = {
+	OPERATIONAL_SCOPE: [
+		{enum: '', title: i18n('please select…')},
+		{enum: 'Network_Wide', title: 'Network Wide'},
+		{enum: 'Availability_Zone', title: 'Availability Zone'},
+		{enum: 'Data_Center', title: 'Data Center'},
+		{enum: 'Tenant', title: 'Tenant'},
+		{enum: 'VM', title: 'VM'},
+		{enum: 'CPU', title: 'CPU'},
+		{enum: 'Core', title: 'Core'}
+	],
+	TYPE: [
+		{enum: '', title: i18n('please select…')},
+		{enum: 'Universal', title: 'Universal'},
+		{enum: 'Unique', title: 'Unique'},
+		{enum: 'One_Time', title: 'One Time'}
+	]
+};
+
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js
new file mode 100644
index 0000000..3940ec5
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {connect} from 'react-redux';
+import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
+import LicenseKeyGroupsEditorView from './LicenseKeyGroupsEditorView.jsx';
+
+const mapStateToProps = ({licenseModel: {licenseKeyGroup}}) => {
+
+
+	let {data} = licenseKeyGroup.licenseKeyGroupsEditor;
+
+	let previousData;
+	const licenseKeyGroupId = data ? data.id : null;
+	if(licenseKeyGroupId) {
+		previousData = licenseKeyGroup.licenseKeyGroupsList.find(licenseKeyGroup => licenseKeyGroup.id === licenseKeyGroupId);
+	}
+
+	return {
+		data,
+		previousData
+	};
+};
+
+const mapActionsToProps = (dispatch, {licenseModelId}) => {
+	return {
+		onDataChanged: deltaData => LicenseKeyGroupsActionHelper.licenseKeyGroupEditorDataChanged(dispatch, {deltaData}),
+		onCancel: () => LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch),
+		onSubmit: ({previousLicenseKeyGroup, licenseKeyGroup}) => {
+			LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch);
+			LicenseKeyGroupsActionHelper.saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup});
+		}
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(LicenseKeyGroupsEditorView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js
new file mode 100644
index 0000000..a744982
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes, defaultState} from './LicenseKeyGroupsConstants.js';
+
+export default (state = {}, action) => {
+	switch (action.type) {
+		case actionTypes.licenseKeyGroupsEditor.OPEN:
+			return {
+				...state,
+				data: action.licenseKeyGroup ? {...action.licenseKeyGroup} : defaultState.licenseKeyGroupsEditor
+			};
+		case actionTypes.licenseKeyGroupsEditor.CLOSE:
+			return {};
+		case actionTypes.licenseKeyGroupsEditor.DATA_CHANGED:
+			return {
+				...state,
+				data: {
+					...state.data,
+					...action.deltaData
+				}
+			};
+		default:
+			return state;
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx
new file mode 100644
index 0000000..102e713
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx
@@ -0,0 +1,92 @@
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
+import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
+import {optionsInputValues as licenseKeyGroupOptionsInputValues} from './LicenseKeyGroupsConstants.js';
+import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+
+const LicenseKeyGroupPropType = React.PropTypes.shape({
+	id: React.PropTypes.string,
+	name: React.PropTypes.string,
+	description: React.PropTypes.string,
+	operationalScope: React.PropTypes.shape({
+		choices: React.PropTypes.array,
+		other: React.PropTypes.string
+	}),
+	type: React.PropTypes.string
+});
+
+class LicenseKeyGroupsEditorView extends React.Component {
+	static propTypes = {
+		data: LicenseKeyGroupPropType,
+		previousData: LicenseKeyGroupPropType,
+		isReadOnlyMode: React.PropTypes.bool,
+		onDataChanged: React.PropTypes.func.isRequired,
+		onSubmit: React.PropTypes.func.isRequired,
+		onCancel: React.PropTypes.func.isRequired
+	};
+
+	static defaultProps = {
+		data: {}
+	};
+
+	render() {
+		let {data = {}, onDataChanged, isReadOnlyMode} = this.props;
+		let {name, description, operationalScope, type} = data;
+		return (
+			<ValidationForm
+				ref='validationForm'
+				hasButtons={true}
+				onSubmit={ () => this.submit() }
+				onReset={ () => this.props.onCancel() }
+				labledButtons={true}
+				isReadOnlyMode={isReadOnlyMode}
+				className='license-key-groups-form'>
+				<div className='license-key-groups-form-row'>
+					<ValidationInput
+						onChange={name => onDataChanged({name})}
+						ref='name'
+						label={i18n('Name')}
+						value={name}
+						validations={{maxLength: 120, required: true}}
+						type='text'/>
+					<ValidationInput
+						isMultiSelect={true}
+						isRequired={true}
+						onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}})}
+						onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER], other: operationalScope}})}
+						label={i18n('Operational Scope')}
+						validations={{required: true}}
+						multiSelectedEnum={operationalScope && operationalScope.choices}
+						otherValue={operationalScope && operationalScope.other}
+						values={licenseKeyGroupOptionsInputValues.OPERATIONAL_SCOPE}/>
+				</div>
+				<div className='license-key-groups-form-row'>
+					<ValidationInput
+						onChange={description => onDataChanged({description})}
+						ref='description'
+						label={i18n('Description')}
+						value={description}
+						validations={{maxLength: 1000, required: true}}
+						type='textarea'/>
+						<ValidationInput
+							isRequired={true}
+							onEnumChange={type => onDataChanged({type})}
+							selectedEnum={type}
+							label={i18n('Type')}
+							type='select'
+							validations={{required: true}}
+							values={licenseKeyGroupOptionsInputValues.TYPE}/>
+					</div>
+			</ValidationForm>
+		);
+	}
+
+	submit() {
+		const {data: licenseKeyGroup, previousData: previousLicenseKeyGroup} = this.props;
+		this.props.onSubmit({licenseKeyGroup, previousLicenseKeyGroup});
+	}
+}
+
+export default LicenseKeyGroupsEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js
new file mode 100644
index 0000000..e1b610f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js
@@ -0,0 +1,50 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {connect} from 'react-redux';
+import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
+import LicenseKeyGroupsListEditorView from './LicenseKeyGroupsListEditorView.jsx';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+
+const mapStateToProps = ({licenseModel: {licenseKeyGroup, licenseModelEditor}}) => {
+	let {licenseKeyGroupsList} = licenseKeyGroup;
+	let {data} = licenseKeyGroup.licenseKeyGroupsEditor;
+	let {vendorName} = licenseModelEditor.data;
+	let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data);
+
+	return {
+		vendorName,
+		licenseKeyGroupsList,
+		isReadOnlyMode,
+		isDisplayModal: Boolean(data),
+		isModalInEditMode: Boolean(data && data.id)
+	};
+};
+
+const mapActionsToProps = (dispatch) => {
+	return {
+		onAddLicenseKeyGroupClick: () => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch),
+		onEditLicenseKeyGroupClick: licenseKeyGroup => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch, {licenseKeyGroup}),
+		onDeleteLicenseKeyGroupClick: licenseKeyGroup => LicenseKeyGroupsActionHelper.openDeleteLicenseAgreementConfirm(dispatch, {licenseKeyGroup})
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(LicenseKeyGroupsListEditorView);
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx
new file mode 100644
index 0000000..1ed1d20
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx
@@ -0,0 +1,138 @@
+import React from 'react';
+
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Modal from 'nfvo-components/modal/Modal.jsx';
+import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
+import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+
+import LicenseKeyGroupsEditor from './LicenseKeyGroupsEditor.js';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+import {optionsInputValues} from './LicenseKeyGroupsConstants';
+import LicenseKeyGroupsConfirmationModal from './LicenseKeyGroupsConfirmationModal.jsx';
+
+
+class LicenseKeyGroupsListEditorView extends React.Component {
+	static propTypes = {
+		vendorName: React.PropTypes.string,
+		licenseModelId: React.PropTypes.string.isRequired,
+		licenseKeyGroupsList: React.PropTypes.array,
+		isReadOnlyMode: React.PropTypes.bool.isRequired,
+		isDisplayModal: React.PropTypes.bool,
+		isModalInEditMode: React.PropTypes.bool,
+		onAddLicenseKeyGroupClick: React.PropTypes.func,
+		onEditLicenseKeyGroupClick: React.PropTypes.func,
+		onDeleteLicenseKeyGroupClick: React.PropTypes.func
+	};
+
+	static defaultProps = {
+		licenseKeyGroupsList: []
+	};
+
+	state = {
+		localFilter: ''
+	};
+
+	render() {
+		let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props;
+		let {onAddLicenseKeyGroupClick} = this.props;
+		const {localFilter} = this.state;
+
+		return (
+			<div className='license-key-groups-list-editor'>
+				<ListEditorView
+					title={i18n('License Key Groups for {vendorName} License Model', {vendorName})}
+					plusButtonTitle={i18n('Add License Key Group')}
+					onAdd={onAddLicenseKeyGroupClick}
+					filterValue={localFilter}
+					onFilter={filter => this.setState({localFilter: filter})}
+					isReadOnlyMode={isReadOnlyMode}>
+					{this.filterList().map(licenseKeyGroup => (this.renderLicenseKeyGroupListItem(licenseKeyGroup, isReadOnlyMode)))}
+				</ListEditorView>
+				<Modal show={isDisplayModal} bsSize='large' animation={true} className='license-key-groups-modal'>
+					<Modal.Header>
+						<Modal.Title>{`${isModalInEditMode ? i18n('Edit License Key Group') : i18n('Create New License Key Group')}`}</Modal.Title>
+					</Modal.Header>
+					<Modal.Body>
+						{
+							isDisplayModal && (
+								<LicenseKeyGroupsEditor licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>
+							)
+						}
+					</Modal.Body>
+				</Modal>
+				<LicenseKeyGroupsConfirmationModal licenseModelId={licenseModelId}/>
+
+			</div>
+		);
+	}
+
+	filterList() {
+		let {licenseKeyGroupsList} = this.props;
+		let {localFilter} = this.state;
+		if (localFilter.trim()) {
+			const filter = new RegExp(escape(localFilter), 'i');
+			return licenseKeyGroupsList.filter(({name = '', description = '', operationalScope = '', type = ''}) => {
+				return escape(name).match(filter) || escape(description).match(filter) || escape(this.extractValue(operationalScope)).match(filter) || escape(type).match(filter);
+			});
+		}
+		else {
+			return licenseKeyGroupsList;
+		}
+	}
+
+	renderLicenseKeyGroupListItem(licenseKeyGroup, isReadOnlyMode) {
+		let {id, name, description, operationalScope, type} = licenseKeyGroup;
+		let {onEditLicenseKeyGroupClick, onDeleteLicenseKeyGroupClick} = this.props;
+		return (
+			<ListEditorItemView
+				key={id}
+				onSelect={() => onEditLicenseKeyGroupClick(licenseKeyGroup)}
+				onDelete={() => onDeleteLicenseKeyGroupClick(licenseKeyGroup)}
+				className='list-editor-item-view'
+				isReadOnlyMode={isReadOnlyMode}>
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Name')}</div>
+					<div className='text name'>{name}</div>
+				</div>
+
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Operational Scope')}</div>
+					<div className='text operational-scope'>{operationalScope && this.getOperationalScopes(operationalScope)}</div>
+
+					<div className='title'>{i18n('Type')}</div>
+					<div className='text type'>{InputOptions.getTitleByName(optionsInputValues, type)}</div>
+				</div>
+				<div className='list-editor-item-view-field'>
+					<div className='title'>{i18n('Description')}</div>
+					<div className='text description'>{description}</div>
+				</div>
+			</ListEditorItemView>
+		);
+	}
+
+	getOperationalScopes(operationalScope) {
+		if(operationalScope.choices.toString() === i18n(optionInputOther.OTHER) && operationalScope.other !== '') {
+			return operationalScope.other;
+		}
+		else {
+			let allOpScopes = '';
+			for (let opScope of operationalScope.choices) {
+				allOpScopes += allOpScopes === '' ? InputOptions.getTitleByName(optionsInputValues, opScope) : `, ${InputOptions.getTitleByName(optionsInputValues, opScope)}`;
+			}
+			return allOpScopes;
+		}
+	}
+
+	extractValue(item) {
+		if (item === undefined) {
+			return '';
+		} //TODO fix it later
+
+		return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
+	}
+}
+
+export default LicenseKeyGroupsListEditorView;
+
+
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js
new file mode 100644
index 0000000..54ce4e3
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {actionTypes} from './LicenseKeyGroupsConstants.js';
+export default (state = [], action) => {
+	switch (action.type) {
+		case actionTypes.LICENSE_KEY_GROUPS_LIST_LOADED:
+			return [...action.response.results];
+		case actionTypes.DELETE_LICENSE_KEY_GROUP:
+			return state.filter(licenseKeyGroup => licenseKeyGroup.id !== action.licenseKeyGroupId);
+		case actionTypes.ADD_LICENSE_KEY_GROUP:
+			return [...state, action.licenseKeyGroup];
+		case actionTypes.EDIT_LICENSE_KEY_GROUP:
+			const indexForEdit = state.findIndex(licenseKeyGroup => licenseKeyGroup.id === action.licenseKeyGroup.id);
+			return [...state.slice(0, indexForEdit), action.licenseKeyGroup, ...state.slice(indexForEdit + 1)];
+		default:
+			return state;
+	}
+};
+