[SDC-29] Amdocs OnBoard 1707 initial commit.

Change-Id: Ie4d12a3f574008b792899b368a0902a8b46b5370
Signed-off-by: AviZi <avi.ziv@amdocs.com>
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx
new file mode 100644
index 0000000..c63fbff
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx
@@ -0,0 +1,134 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import {catalogItemTypeClasses, migrationStatusMapper} from './onboardingCatalog/OnboardingCatalogConstants.js';
+import CatalogTile from './CatalogTile.jsx';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import {statusEnum, statusBarTextMap} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
+import tooltip from './onboardingCatalog/Tooltip.jsx';
+
+
+
+const CatalogTileIcon = ({catalogItemTypeClass}) => (
+		<div className={'catalog-tile-icon ' + catalogItemTypeClass}>
+			<div className='icon'><SVGIcon
+				name={catalogItemTypeClass === catalogItemTypeClasses.LICENSE_MODEL ? 'vlm' : 'vsp' }/>
+			</div>
+		</div>
+);
+
+const ItemTypeTitle = ({catalogItemTypeClass}) => {
+	const itemTypeTitle = catalogItemTypeClass === catalogItemTypeClasses.LICENSE_MODEL ? i18n('VLM') : i18n('VSP');
+	return(		
+		<div className={`catalog-tile-type ${catalogItemTypeClass}`}>{itemTypeTitle}</div>
+	);
+};
+
+const CatalogTileVendorName = ({vendorName, catalogItemTypeClass}) => { 
+	const name = catalogItemTypeClass === catalogItemTypeClasses.SOFTWARE_PRODUCT ? vendorName : '';	
+	return(
+		<div>
+			<OverlayTrigger placement='top' overlay={tooltip(name)}>
+				<div className='catalog-tile-vendor-name'>{name}</div>
+			</OverlayTrigger>
+		</div>
+	);
+};
+
+const CatalogTileItemName = ({name}) => (
+	<div>
+		<OverlayTrigger placement='top'  overlay={tooltip(name && name.toUpperCase())}>
+			<div className='catalog-tile-item-name'>{name}</div>
+		</OverlayTrigger>	
+	</div>
+);
+
+const VersionInfo = ({version}) => (
+	<div className='catalog-tile-version-info'>
+		<div className='catalog-tile-item-version' data-test-id='catalog-item-version'>
+			V {version}
+		</div>
+	</div>	
+);
+
+const EntityDetails = ({catalogItemData, catalogItemTypeClass}) => {
+	const {vendorName, name, version} = catalogItemData;
+	return (
+		<div className='catalog-tile-entity-details'>
+			<CatalogTileVendorName catalogItemTypeClass={catalogItemTypeClass} vendorName={vendorName}/>
+			<CatalogTileItemName name={name}/>
+			<VersionInfo version={version.label} />
+		</div>			
+	);
+};
+
+
+const  ItemStatusInfo = ({catalogItemTypeClass, lockingUser, itemStatus}) => {	
+	const status = statusBarTextMap[itemStatus];
+	const lockedBy = lockingUser ? ` by ${lockingUser}` : '';
+	const toolTipMsg = `${status}${lockedBy}`;
+
+	return (
+		<div className={'catalog-tile-content ' + catalogItemTypeClass}>						
+			<div className='catalog-tile-locking-user-name'>{i18n(status)}</div>
+			<OverlayTrigger placement='top'  overlay={tooltip(toolTipMsg)}>							
+				<div className='catalog-tile-check-in-status'><SVGIcon
+					name={itemStatus === statusEnum.CHECK_OUT_STATUS ? 'unlocked' : 'locked'}
+					data-test-id={itemStatus === statusEnum.CHECK_IN_STATUS ? 'catalog-item-checked-in' : 'catalog-item-checked-out'}/>
+				</div>
+			</OverlayTrigger>													
+		</div>
+		
+	);
+};
+
+const  CatalogItemDetails = ({catalogItemData, catalogItemTypeClass, onSelect, onMigrate}) =>  {
+	
+	let {status: itemStatus} = VersionControllerUtils.getCheckOutStatusKindByUserID(catalogItemData.status, catalogItemData.lockingUser);
+	
+	return (
+		<CatalogTile catalogItemTypeClass={catalogItemTypeClass} onSelect={() => {
+			if (catalogItemData.isOldVersion && catalogItemData.isOldVersion === migrationStatusMapper.OLD_VERSION) {
+				onMigrate({
+					softwareProduct: catalogItemData
+				});
+			} else {
+				onSelect();
+			}
+		}} data-test-id={catalogItemTypeClass}>
+			<div className='catalog-tile-top item-details'>			
+				<ItemTypeTitle catalogItemTypeClass={catalogItemTypeClass}/>				
+				<CatalogTileIcon catalogItemTypeClass={catalogItemTypeClass}/>										
+				<EntityDetails catalogItemTypeClass={catalogItemTypeClass} catalogItemData={catalogItemData} />
+				<ItemStatusInfo itemStatus={itemStatus} catalogItemTypeClass={catalogItemTypeClass} lockingUser={catalogItemData.lockingUser} />								
+			</div>
+		</CatalogTile>
+	);
+	
+};
+
+CatalogItemDetails.PropTypes = {
+	catalogItemData: React.PropTypes.obj,
+	catalogItemTypeClass: React.PropTypes.string,
+	onSelect: React.PropTypes.func,
+	onMigrate: React.PropTypes.func
+};
+
+export default CatalogItemDetails;
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.stories.js b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.stories.js
new file mode 100644
index 0000000..c4e2724
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.stories.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import {storiesOf, action} from '@kadira/storybook';
+import {select, withKnobs} from '@kadira/storybook-addon-knobs';
+import CatalogItemDetails from './CatalogItemDetails.jsx';
+import {FinalizedLicenseModelFactory} from 'test-utils/factories/licenseModel/LicenseModelFactories.js';
+import {statusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+
+
+
+const stories = storiesOf('CatalogTiles', module);
+stories.addDecorator(withKnobs);
+
+const types = [
+    'license-model-type',
+    'software-product-type'
+];
+
+function selectType() {
+    return select('Item type' , types, types[0]);
+}
+
+let vlm = FinalizedLicenseModelFactory.build({name: 'Test-VLM'});
+let unclockedVlm = {...vlm,  status: statusEnum.CHECK_OUT_STATUS};
+
+
+stories
+    .add('preview', () => (
+        <div className='catalog-view'>
+            <div className='catalog-list'>
+                <div className='catalog-items'>
+                    <CatalogItemDetails catalogItemData={vlm} catalogItemTypeClass={selectType()} onSelect={action('onSelect')} onMigrate={action('onMigrate')}/>                   
+                    <CatalogItemDetails catalogItemData={unclockedVlm} catalogItemTypeClass={selectType()} onSelect={action('onSelect')} onMigrate={action('onMigrate')}/>                   
+                </div>    
+            </div>   
+        </div>                           
+    ));     
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogList.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogList.jsx
new file mode 100644
index 0000000..17248e3
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogList.jsx
@@ -0,0 +1,51 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+
+const SoftwareProductListHeader = ({selectedVendor, onBack}) => (
+	<div className='vendor-page-header'>
+		<SVGIcon name='back' onClick={onBack}/>
+		<div className='tab-separator' />
+		<div className='vendor-name'>{selectedVendor.vendorName}</div>
+	</div>
+);
+
+const CatalogList = ({children, onAddVLM, onAddVSP, vendorPageOptions}) => (
+	<div className='catalog-list'>
+		{vendorPageOptions && <SoftwareProductListHeader onBack={vendorPageOptions.onBack} selectedVendor={vendorPageOptions.selectedVendor}/>}
+		<div className='catalog-items'>
+			<div className='create-catalog-item-wrapper'>
+				{onAddVLM && <CreateItemTile onClick={onAddVLM} dataTestId={'catalog-add-new-lm'} className='vlm-type' title={i18n('CREATE NEW VLM')}/>}
+				{onAddVSP &&
+				<CreateItemTile onClick={onAddVSP} dataTestId={'catalog-add-new-vsp'} className='vsp-type' title={i18n('CREATE NEW VSP')}/>}
+			</div>
+			{children}
+		</div>
+	</div>
+);
+
+const CreateItemTile = ({onClick, dataTestId, title, className = ''}) => {
+	return (
+			<div className={'create-catalog-item tile ' + className} onClick={() => onClick()} data-test-id={dataTestId}>
+				<div className='create-item-plus-icon'><SVGIcon name='plus' /></div>
+				<div className='create-item-text'>{title}</div>
+			</div>
+	);
+};
+
+export default CatalogList;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogModal.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogModal.jsx
new file mode 100644
index 0000000..1ef9c82
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogModal.jsx
@@ -0,0 +1,62 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import {modalMapper, catalogItemTypes, catalogItemTypeClasses } from './onboardingCatalog/OnboardingCatalogConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Modal from 'nfvo-components/modal/Modal.jsx';
+import LicenseModelCreation from '../licenseModel/creation/LicenseModelCreation.js';
+import SoftwareProductCreation from '../softwareProduct/creation/SoftwareProductCreation.js';
+
+class CatalogModal extends React.Component{
+
+	getModalDetails(){
+		const {modalToShow} = this.props;
+		switch (modalToShow) {
+			case catalogItemTypes.LICENSE_MODEL:
+				return {
+					title: i18n('New License Model'),
+					element: <LicenseModelCreation/>
+				};
+			case catalogItemTypes.SOFTWARE_PRODUCT:
+				return {
+					title: i18n('New Software Product'),
+					element: <SoftwareProductCreation/>
+				};
+		}
+	}
+
+	render(){
+		const {modalToShow} = this.props;
+		const modalDetails = this.getModalDetails(modalToShow);
+
+		return (
+			<Modal
+				show={Boolean(modalDetails)}
+				className={`${catalogItemTypeClasses[modalMapper[modalToShow]]}-modal`}>
+				<Modal.Header>
+					<Modal.Title>{modalDetails && modalDetails.title}</Modal.Title>
+				</Modal.Header>
+				<Modal.Body>
+					{
+						modalDetails && modalDetails.element
+					}
+				</Modal.Body>
+			</Modal>
+		);
+	}
+}
+
+export default CatalogModal;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogTile.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogTile.jsx
new file mode 100644
index 0000000..c7720a9
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogTile.jsx
@@ -0,0 +1,31 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+
+const CatalogTile = ({catalogItemTypeClass, onSelect, children}) => {
+	return(
+		<div className={`catalog-tile tile ${catalogItemTypeClass}`} onClick={(e) => {e.stopPropagation(); e.preventDefault(); onSelect();}} data-test-id={catalogItemTypeClass}>
+		 	{children}
+		</div>
+	);
+};
+
+CatalogTile.PropTypes = {
+	catalogItemTypeClass: React.PropTypes.string,
+	onSelect: React.PropTypes.func
+};
+
+export default CatalogTile;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/DetailsCatalogView.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/DetailsCatalogView.jsx
new file mode 100644
index 0000000..ef54848
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/DetailsCatalogView.jsx
@@ -0,0 +1,56 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import {catalogItemTypes, modalMapper, catalogItemTypeClasses} from './onboardingCatalog/OnboardingCatalogConstants.js';
+import {filterCatalogItemsByType} from './onboardingCatalog/OnboardingCatalogUtils.js';
+import CatalogList from './CatalogList.jsx';
+import CatalogItemDetails from './CatalogItemDetails.jsx';
+
+class DetailsCatalogView extends React.Component{
+
+	static propTypes = {
+		VLMList: React.PropTypes.array,
+		VSPList: React.PropTypes.array,
+		onSelectVLM: React.PropTypes.func.isRequired,
+		onSelectVSP: React.PropTypes.func.isRequired,
+		onAddVLM: React.PropTypes.func.isRequired,
+		onAddVSP: React.PropTypes.func.isRequired,
+		filter: React.PropTypes.string.isRequired
+	};
+
+	renderCatalogItems(items, type, filter, onSelect, onMigrate, tileType){
+		return filterCatalogItemsByType(items, type, filter).map(item =>
+		<CatalogItemDetails
+			key={item.id}
+			catalogItemData={type === catalogItemTypes.LICENSE_MODEL ? {...item, name: item.vendorName} : item}
+			catalogItemTypeClass={catalogItemTypeClasses[modalMapper[type]]}
+			onMigrate={onMigrate}
+			onSelect={() => onSelect(item)}
+			tileType={tileType} />
+		);
+	}
+
+	render() {
+		let {VLMList, VSPList, onAddVSP, onAddVLM, onSelectVLM, onSelectVSP, filter = '', onMigrate, tileType} = this.props;
+		return (
+			<CatalogList onAddVLM={onAddVLM} onAddVSP={onAddVSP}>
+				{this.renderCatalogItems(VLMList, catalogItemTypes.LICENSE_MODEL, filter, onSelectVLM, onMigrate, tileType)}
+				{this.renderCatalogItems(VSPList, catalogItemTypes.SOFTWARE_PRODUCT, filter, onSelectVSP, onMigrate, tileType)}
+			</CatalogList>
+		);
+	}
+}
+export default DetailsCatalogView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/Onboard.js b/openecomp-ui/src/sdc-app/onboarding/onboard/Onboard.js
new file mode 100644
index 0000000..b13ccbb
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/Onboard.js
@@ -0,0 +1,90 @@
+/*!
+ * 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.
+ */
+
+import {connect} from 'react-redux';
+import OnboardView from './OnboardView.jsx';
+import OnboardingActionHelper from '../OnboardingActionHelper.js';
+import OnboardingCatalogActionHelper from './onboardingCatalog/OnboardingCatalogActionHelper.js';
+import OnboardActionHelper from './OnboardActionHelper.js';
+import LicenseModelCreationActionHelper from '../licenseModel/creation/LicenseModelCreationActionHelper.js';
+import SoftwareProductCreationActionHelper from '../softwareProduct/creation/SoftwareProductCreationActionHelper.js';
+import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
+
+export const mapStateToProps = ({
+	onboard: {onboardingCatalog, activeTab, searchValue}, licenseModelList, finalizedLicenseModelList, softwareProductList, finalizedSoftwareProductList
+}) => {
+
+	const reduceLicenseModelList = (accum, vlm)=> {
+		let currentSoftwareProductList = sortByStringProperty(
+			finalizedSoftwareProductList
+				.filter(vsp => vsp.vendorId === vlm.id),
+			'name'
+		);
+		accum.push({...vlm, softwareProductList: currentSoftwareProductList});
+		return accum;
+	};
+
+	finalizedLicenseModelList = sortByStringProperty(
+		licenseModelList
+			.filter(vlm => finalizedLicenseModelList.map(finalVlm => finalVlm.id).includes(vlm.id))
+			.reduce(reduceLicenseModelList, []),
+		'vendorName'
+	);
+
+	finalizedSoftwareProductList = sortByStringProperty(
+		softwareProductList
+			.filter(vsp => finalizedSoftwareProductList.map(finalVsp => finalVsp.id).includes(vsp.id)),
+		'name'
+	);
+
+
+	let {activeTab: catalogActiveTab, vendorCatalog: {vspOverlay, selectedVendor}} = onboardingCatalog;
+
+	return {
+		finalizedLicenseModelList,
+		finalizedSoftwareProductList,
+		licenseModelList,
+		softwareProductList,
+		activeTab,
+		catalogActiveTab,
+		searchValue,
+		vspOverlay,
+		selectedVendor
+	};
+};
+
+const mapActionsToProps = (dispatch) => {
+	return {
+		onSelectLicenseModel({id: licenseModelId, version}) {
+			OnboardingActionHelper.navigateToLicenseModelOverview(dispatch, {licenseModelId, version});
+		},
+		onSelectSoftwareProduct(softwareProduct) {
+			let {id: softwareProductId, vendorId: licenseModelId, licensingVersion, version} = softwareProduct;
+			OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version, licenseModelId, licensingVersion});
+		},
+		onAddSoftwareProductClick: (vendorId) => SoftwareProductCreationActionHelper.open(dispatch, vendorId),
+		onAddLicenseModelClick: () => LicenseModelCreationActionHelper.open(dispatch),
+		onVspOverlayChange: (vendor) => OnboardingCatalogActionHelper.changeVspOverlay(dispatch, vendor),
+		closeVspOverlay: () => OnboardingCatalogActionHelper.closeVspOverlay(dispatch),
+		onCatalogTabClick: (tab) => OnboardingCatalogActionHelper.changeActiveTab(dispatch, tab),
+		onTabClick: (tab) => OnboardActionHelper.changeActiveTab(dispatch, tab),
+		onSearch: (searchValue) => OnboardActionHelper.changeSearchValue(dispatch, searchValue),
+		onVendorSelect: (vendor) => OnboardingCatalogActionHelper.onVendorSelect(dispatch, {vendor}),
+		onMigrate: ({softwareProduct}) => OnboardingCatalogActionHelper.onMigrate(dispatch, softwareProduct)
+	};
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(OnboardView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardActionHelper.js
new file mode 100644
index 0000000..6ebb408
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardActionHelper.js
@@ -0,0 +1,45 @@
+/*!
+ * 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.
+ */
+import {actionTypes} from './OnboardConstants.js';
+
+const OnboardActionHelper = {
+	resetOnboardStore(dispatch) {
+		dispatch({
+			type: actionTypes.RESET_ONBOARD_STORE
+		});
+	},
+	changeActiveTab(dispatch, activeTab) {
+		this.clearSearchValue(dispatch);
+		dispatch({
+			type: actionTypes.CHANGE_ACTIVE_ONBOARD_TAB,
+			activeTab
+		});
+	},
+	changeSearchValue(dispatch, searchValue) {
+		dispatch({
+			type: actionTypes.CHANGE_SEARCH_VALUE,
+			searchValue
+		});
+	},
+	clearSearchValue(dispatch) {
+		dispatch({
+			type: actionTypes.CHANGE_SEARCH_VALUE,
+			searchValue: ''
+		});
+	}
+};
+
+export default OnboardActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardConstants.js b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardConstants.js
new file mode 100644
index 0000000..41128bf
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardConstants.js
@@ -0,0 +1,28 @@
+/*!
+ * 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.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const tabsMapping = {
+	'WORKSPACE': 1,
+	'CATALOG': 2
+};
+
+export const actionTypes = keyMirror({
+	CHANGE_ACTIVE_ONBOARD_TAB: null,
+	CHANGE_SEARCH_VALUE: null,
+	RESET_ONBOARD_STORE: null,
+	VSP_MIGRATION: null
+});
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardReducer.js b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardReducer.js
new file mode 100644
index 0000000..7214501
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardReducer.js
@@ -0,0 +1,31 @@
+/*!
+ * 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.
+ */
+import {actionTypes, tabsMapping} from './OnboardConstants.js';
+import {combineReducers} from 'redux';
+import onboardingCatalogReducer from './onboardingCatalog/OnboardingCatalogReducer.js';
+
+const onboardReducer = combineReducers({
+	onboardingCatalog: onboardingCatalogReducer,
+	activeTab: (state = tabsMapping.WORKSPACE, action) => action.type === actionTypes.CHANGE_ACTIVE_ONBOARD_TAB ? action.activeTab : state,
+	searchValue: (state = '', action) => action.type === actionTypes.CHANGE_SEARCH_VALUE ? action.searchValue : state
+});
+
+export default (state, action) => {
+	if (action.type === actionTypes.RESET_ONBOARD_STORE) {
+		state = undefined;
+	}
+	return onboardReducer(state, action);
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardView.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardView.jsx
new file mode 100644
index 0000000..b7a7fa5
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardView.jsx
@@ -0,0 +1,95 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import OnboardingCatalogView from './onboardingCatalog/OnboardingCatalogView.jsx';
+import WorkspaceView from './workspace/WorkspaceView.jsx';
+import {tabsMapping} from './OnboardConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import classnames from 'classnames';
+import ExpandableInput from 'nfvo-components/input/ExpandableInput.jsx';
+import objectValues from 'lodash/values.js';
+import {catalogItemTypes} from './onboardingCatalog/OnboardingCatalogConstants.js';
+
+const OnboardHeaderTabs = ({onTabClick, activeTab}) => (
+	<div className='onboard-header-tabs'>
+		<div
+			className={classnames('onboard-header-tab', {'active': activeTab === tabsMapping.WORKSPACE })}
+			onClick={() => onTabClick(tabsMapping.WORKSPACE)}
+			data-test-id='onboard-workspace-tab'>
+			{i18n('WORKSPACE')}
+		</div>
+		<div
+			className={classnames('onboard-header-tab', {'active': activeTab === tabsMapping.CATALOG })}
+			onClick={() => onTabClick(tabsMapping.CATALOG)}
+			data-test-id='onboard-onboard-tab'>
+			{i18n('ONBOARD CATALOG')}
+		</div>
+	</div>
+);
+
+const OnboardHeader = ({onSearch, activeTab, onTabClick, searchValue}) => (
+	<div className='onboard-header'>
+		<OnboardHeaderTabs activeTab={activeTab} onTabClick={onTabClick} />
+		<ExpandableInput
+			onChange={onSearch}
+			iconType='search'
+			value={searchValue}/>
+	</div>
+);
+
+class OnboardView extends React.Component {
+	static propTypes = {
+		licenseModelList: React.PropTypes.array,
+		softwareProductList: React.PropTypes.array,
+		finalizedLicenseModelList: React.PropTypes.array,
+		finalizedSoftwareProductList: React.PropTypes.array,
+		modalToShow: React.PropTypes.oneOf(objectValues(catalogItemTypes)),
+		onSelectLicenseModel: React.PropTypes.func.isRequired,
+		onSelectSoftwareProduct: React.PropTypes.func.isRequired,
+		onAddLicenseModelClick: React.PropTypes.func.isRequired,
+		onAddSoftwareProductClick: React.PropTypes.func.isRequired,
+		closeVspOverlay: React.PropTypes.func.isRequired,
+		onVspOverlayChange: React.PropTypes.func.isRequired,
+		onTabClick: React.PropTypes.func.isRequired,
+		onCatalogTabClick: React.PropTypes.func.isRequired,
+		onSearch: React.PropTypes.func.isRequired,
+		activeTab: React.PropTypes.number.isRequired,
+		catalogActiveTab: React.PropTypes.number.isRequired,
+		searchValue: React.PropTypes.string.isRequired,
+		onMigrate: React.PropTypes.func.isRequired,
+	};
+	renderViewByTab(activeTab){
+		switch (activeTab){
+			case tabsMapping.WORKSPACE:
+				return <WorkspaceView {...this.props} />;
+			case tabsMapping.CATALOG:
+			default:
+				return <OnboardingCatalogView {...this.props} />;
+		}
+	}
+
+	render() {
+		let {closeVspOverlay, activeTab, onTabClick, onSearch, searchValue} = this.props;
+		return (
+			<div className='catalog-view' onClick={closeVspOverlay}>
+				<OnboardHeader activeTab={activeTab} onTabClick={onTabClick} searchValue={searchValue} onSearch={value => onSearch(value)}/>
+				{this.renderViewByTab(activeTab)}
+			</div>
+		);
+	}
+}
+
+export default OnboardView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogActionHelper.js
new file mode 100644
index 0000000..73a4475
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogActionHelper.js
@@ -0,0 +1,85 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {actionTypes} from './OnboardingCatalogConstants.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import {statusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import OnboardActionHelper from '../OnboardActionHelper.js';
+import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
+
+
+function getMessageForMigration(name) {
+	return (
+		<div>
+			<div>{i18n('{name} needs to be updated. Click ‘Checkout & Update’, to proceed.',{name})}</div>
+			<div>{i18n('Please don’t forget to submit afterwards')}</div>
+		</div>
+	);
+}
+
+const OnboardingCatalogActionHelper = {
+	changeVspOverlay(dispatch, vendor) {
+		dispatch({
+			type: actionTypes.CHANGE_VSP_OVERLAY,
+			vendorId: vendor ? vendor.id : null
+		});
+	},
+	closeVspOverlay(dispatch) {
+		dispatch({
+			type: actionTypes.CLOSE_VSP_OVERLAY
+		});
+	},
+	changeActiveTab(dispatch, activeTab) {
+		OnboardActionHelper.clearSearchValue(dispatch);
+		dispatch({
+			type: actionTypes.CHANGE_ACTIVE_CATALOG_TAB,
+			activeTab
+		});
+	},
+	onVendorSelect(dispatch, {vendor}) {
+		OnboardActionHelper.clearSearchValue(dispatch);
+		dispatch({
+			type: actionTypes.ONBOARDING_CATALOG_OPEN_VENDOR_PAGE,
+			selectedVendor: vendor
+		});
+	},	
+	onMigrate(dispatch, softwareProduct) {
+		const {status, name, lockingUser} = softwareProduct;
+		if (status === statusEnum.CHECK_OUT_STATUS && !VersionControllerUtils.isCheckedOutByCurrentUser(softwareProduct)) {
+			dispatch({
+				type: modalActionTypes.GLOBAL_MODAL_WARNING,				
+				data: {
+					title: 'WARNING',
+					msg: i18n('{name} is locked by user {lockingUser} for self-healing',{name, lockingUser})
+				}
+			});
+		} else { 
+			dispatch({
+				type: modalActionTypes.GLOBAL_MODAL_WARNING,
+				data:{
+					title: 'WARNING',
+					msg: getMessageForMigration(softwareProduct.name.toUpperCase()),													
+					confirmationButtonText: i18n('Checkout & Update'),
+					onConfirmed: ()=>SoftwareProductActionHelper.migrateSoftwareProduct(dispatch, {softwareProduct})
+				}
+			});
+		}	
+	}
+};
+
+export default OnboardingCatalogActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js
new file mode 100644
index 0000000..071160c
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js
@@ -0,0 +1,50 @@
+/*!
+ * 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.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const catalogItemTypes = Object.freeze({
+	LICENSE_MODEL: 'license-model',
+	SOFTWARE_PRODUCT: 'software-product'
+});
+
+export const catalogItemTypeClasses = {
+	LICENSE_MODEL: 'license-model-type',
+	SOFTWARE_PRODUCT: 'software-product-type',
+	VENDOR: 'vendor-type'
+
+};
+
+export const modalMapper = {
+	'license-model': 'LICENSE_MODEL',
+	'software-product': 'SOFTWARE_PRODUCT'
+};
+
+export const tabsMapping = {
+	'BY_VENDOR': 1,
+	'ALL': 2
+};
+
+export const migrationStatusMapper = {
+	OLD_VERSION: 'True',
+};
+
+export const actionTypes = keyMirror({
+	ONBOARDING_CATALOG_OPEN_VENDOR_PAGE: null,
+	CHANGE_ACTIVE_CATALOG_TAB: null,
+	CHANGE_SEARCH_VALUE: null,
+	CHANGE_VSP_OVERLAY: null,
+	CLOSE_VSP_OVERLAY: null
+});
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogReducer.js b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogReducer.js
new file mode 100644
index 0000000..d7d9d0b
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogReducer.js
@@ -0,0 +1,30 @@
+/*!
+ * 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.
+ */
+import {actionTypes, tabsMapping} from './OnboardingCatalogConstants.js';
+import {combineReducers} from 'redux';
+import vendorCatalogReducer from './VendorCatalogReducer.js';
+
+const onboardingCatalogReducer = combineReducers({
+	vendorCatalog: vendorCatalogReducer,
+	activeTab: (state = tabsMapping.ALL, action) => action.type === actionTypes.CHANGE_ACTIVE_CATALOG_TAB ? action.activeTab : state
+});
+
+export default (state, action) => {
+	if (action.type === actionTypes.RESET_ONBOARDING_CATALOG_STORE) {
+		state = undefined;
+	}
+	return onboardingCatalogReducer(state, action);
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogUtils.js b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogUtils.js
new file mode 100644
index 0000000..ac623db
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogUtils.js
@@ -0,0 +1,21 @@
+/*!
+ * 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.
+ */
+import {catalogItemTypes} from './OnboardingCatalogConstants.js';
+
+export const filterCatalogItemsByType = (items, type, filter) => {
+	const fieldName = type === catalogItemTypes.LICENSE_MODEL ? 'vendorName' : 'name';
+	return items.filter(item => item[fieldName].toLowerCase().indexOf(filter.toLowerCase()) > -1);
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogView.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogView.jsx
new file mode 100644
index 0000000..b1f002d
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogView.jsx
@@ -0,0 +1,98 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import classnames from 'classnames';
+import DetailsCatalogView from 'sdc-app/onboarding/onboard/DetailsCatalogView.jsx';
+import VendorCatalogView from './VendorCatalogView.jsx';
+import { tabsMapping} from './OnboardingCatalogConstants.js';
+
+const CatalogHeaderTabs = ({onTabPress, activeTab}) => (
+	<div className='catalog-header-tabs'>
+		<div
+			className={classnames('catalog-header-tab', {'active': activeTab === tabsMapping.ALL })}
+			onClick={() => onTabPress(tabsMapping.ALL)}
+			data-test-id='catalog-all-tab'>
+			{i18n('ALL')}
+		</div>
+		<div className='tab-separator'/>
+		<div
+			className={classnames('catalog-header-tab', {'active': activeTab === tabsMapping.BY_VENDOR })}
+			onClick={() => onTabPress(tabsMapping.BY_VENDOR)}
+			data-test-id='catalog-by-vendor-tab'>
+			{i18n('BY VENDOR')}
+		</div>
+	</div>
+);
+
+const CatalogHeader = ({activeTab, onTabPress}) => (
+	<div className='catalog-header'>
+		<CatalogHeaderTabs activeTab={activeTab} onTabPress={onTabPress} />
+	</div>
+);
+
+class OnboardingCatalogView extends React.Component {
+	renderViewByTab(activeTab){
+		const {finalizedLicenseModelList: licenseModelList, vspOverlay, finalizedSoftwareProductList: softwareProductList, onSelectLicenseModel, onSelectSoftwareProduct,
+				onAddLicenseModelClick, onAddSoftwareProductClick, onVspOverlayChange, onVendorSelect, selectedVendor, searchValue, onMigrate} = this.props;
+		switch (activeTab){
+			case tabsMapping.ALL:
+				return (
+					<DetailsCatalogView
+						VLMList={licenseModelList}
+						VSPList={softwareProductList}
+						onAddVLM={onAddLicenseModelClick}
+						onAddVSP={onAddSoftwareProductClick}
+						onSelectVLM={onSelectLicenseModel}
+						onSelectVSP={onSelectSoftwareProduct}
+						filter={searchValue}
+						onMigrate={onMigrate}/>
+				);
+			case tabsMapping.BY_VENDOR:
+			default:
+				return (
+					<VendorCatalogView
+						licenseModelList={licenseModelList}
+						onAddVSP={onAddSoftwareProductClick}
+						onAddVLM={onAddLicenseModelClick}
+						onSelectVSP={onSelectSoftwareProduct}
+						onSelectVLM={onSelectLicenseModel}
+						vspOverlay={vspOverlay}
+						onVendorSelect={onVendorSelect}
+						selectedVendor={selectedVendor}
+						onVspOverlayChange={onVspOverlayChange}
+						onMigrate={onMigrate}
+						filter={searchValue}/>
+				);
+		}
+	}
+
+	render() {
+		const {selectedVendor, catalogActiveTab: activeTab, onCatalogTabClick, onSearch, searchValue} = this.props;
+		return (
+			<div className='catalog-wrapper'>
+				{!selectedVendor && <CatalogHeader
+					onSearch={event => onSearch(event.target.value)}
+					activeTab={activeTab}
+					onTabPress={tab => onCatalogTabClick(tab)}
+					searchValue={searchValue}/>}
+				{this.renderViewByTab(activeTab)}
+			</div>
+		);
+	}
+}
+
+export default OnboardingCatalogView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/Tooltip.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/Tooltip.jsx
new file mode 100644
index 0000000..8d8d116
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/Tooltip.jsx
@@ -0,0 +1,24 @@
+/*!
+ * 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.
+ */
+
+import React from 'react';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+
+export default function tooltip (msg)  {
+	return (
+  		<Tooltip className='tile-tooltip' id='tile-tooltip'>{msg}</Tooltip>
+	);
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VSPOverlay.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VSPOverlay.jsx
new file mode 100644
index 0000000..1ba4834
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VSPOverlay.jsx
@@ -0,0 +1,50 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {migrationStatusMapper} from './OnboardingCatalogConstants.js';
+
+const VSPOverlay = ({VSPList, onSelectVSP, onSeeMore, onMigrate}) => (
+	<div className='vsp-overlay-wrapper' onClick={(e) => {
+		e.stopPropagation();
+		e.preventDefault();
+	}}>
+		<div className='vsp-overlay-arrow'></div>
+		<div className='vsp-overlay'>
+			<div className='vsp-overlay-title'>{i18n('Recently Edited')}</div>
+			<div className='vsp-overlay-list'>
+				{VSPList.slice(0, 5).map(vsp => <div key={vsp.id} className='vsp-overlay-detail' onClick={() => {
+					if (vsp.isOldVersion && vsp.isOldVersion === migrationStatusMapper.OLD_VERSION) {
+						onMigrate({
+							softwareProduct: vsp
+						});
+					} else {
+						onSelectVSP(vsp);
+					}
+				}
+				}>{i18n(vsp.name)}</div>)}
+			</div>
+			{VSPList.length > 5 && <div className='vsp-overlay-see-more' onClick={onSeeMore}>{i18n('See More')}</div>}
+		</div>
+	</div>
+);
+
+VSPOverlay.PropTypes = {
+	VSPList: React.PropTypes.array,
+	onSelectVSP: React.PropTypes.func
+};
+
+export default VSPOverlay;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogReducer.js b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogReducer.js
new file mode 100644
index 0000000..dd8b41b
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogReducer.js
@@ -0,0 +1,38 @@
+/*!
+ * 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.
+ */
+import {actionTypes} from './OnboardingCatalogConstants.js';
+
+export default (state = {}, action) => {
+	switch(action.type) {
+		case actionTypes.ONBOARDING_CATALOG_OPEN_VENDOR_PAGE:
+			return {
+				...state,
+				selectedVendor: action.selectedVendor
+			};
+		case actionTypes.CHANGE_VSP_OVERLAY:
+			return {
+				...state,
+				vspOverlay: action.vendorId
+			};
+		case actionTypes.CLOSE_VSP_OVERLAY:
+			return {
+				...state,
+				vspOverlay: null
+			};
+		default:
+			return state;
+	}
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogView.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogView.jsx
new file mode 100644
index 0000000..c4e0599
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogView.jsx
@@ -0,0 +1,74 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import VendorItem from './VendorItem.jsx';
+import CatalogList from '../CatalogList.jsx';
+import CatalogItemDetails from '../CatalogItemDetails.jsx';
+import {catalogItemTypes, catalogItemTypeClasses} from './OnboardingCatalogConstants.js';
+import {filterCatalogItemsByType} from './OnboardingCatalogUtils.js';
+
+const VendorList = ({onAddVLM, onAddVSP, onSelectVSP, licenseModelList = [], vspOverlay: currentOverlay, onVspOverlayChange, onVendorSelect, filter, onMigrate}) => {
+	return(
+		<CatalogList onAddVLM={onAddVLM} onAddVSP={onAddVSP}>
+			{
+				filterCatalogItemsByType(licenseModelList, catalogItemTypes.LICENSE_MODEL, filter).map(vlm =>
+					<VendorItem
+						key={vlm.id}
+						onAddVSP={onAddVSP}
+						onSelectVSP={onSelectVSP}
+						shouldShowOverlay={currentOverlay === vlm.id}
+						onVSPIconClick={(hasVSP) => onVspOverlayChange(vlm.id === currentOverlay || !hasVSP ? null : vlm)}
+						onVendorSelect={onVendorSelect}
+						onMigrate={onMigrate}
+						vendor={vlm}/>)
+			}
+		</CatalogList>
+	);
+};
+
+const SoftwareProductListByVendor = ({onAddVSP, selectedVendor, onVendorSelect, onSelectVSP, onSelectVLM, filter, onMigrate}) => {
+	return(
+		<div>
+			<CatalogList onAddVSP={()=>{onAddVSP(selectedVendor.id);}} vendorPageOptions={{selectedVendor, onBack: () => onVendorSelect(false)}}>
+				<CatalogItemDetails
+					key={selectedVendor.id}
+					onSelect={() => onSelectVLM(selectedVendor)}
+					catalogItemTypeClass={catalogItemTypeClasses.LICENSE_MODEL}
+					onMigrate={onMigrate}
+					catalogItemData={{...selectedVendor, name: selectedVendor.vendorName}}/>
+				{
+					filterCatalogItemsByType(selectedVendor.softwareProductList, catalogItemTypes.SOFTWARE_PRODUCT, filter).map(vsp =>
+						<CatalogItemDetails
+							key={vsp.id}
+							catalogItemTypeClass={catalogItemTypeClasses.SOFTWARE_PRODUCT}
+							onMigrate={onMigrate}
+							onSelect={() => onSelectVSP(vsp)}
+							catalogItemData={vsp}/>
+					)
+				}
+			</CatalogList>
+		</div>
+	);
+};
+
+class VendorCatalogView extends React.Component {
+	render() {
+		let {selectedVendor} = this.props;
+		return( selectedVendor ? <SoftwareProductListByVendor {...this.props}/> : <VendorList {...this.props}/>);
+	}
+}
+
+export default VendorCatalogView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorItem.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorItem.jsx
new file mode 100644
index 0000000..cecccdd
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorItem.jsx
@@ -0,0 +1,96 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import {catalogItemTypeClasses} from './OnboardingCatalogConstants.js';
+import CatalogTile from '../CatalogTile.jsx';
+import classnames from 'classnames';
+import VSPOverlay from './VSPOverlay.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
+import tooltip from './Tooltip.jsx';
+
+
+class VendorItem extends React.Component {
+
+	static PropTypes = {
+		softwareProductList: React.PropTypes.array,
+		vendor: React.PropTypes.object,
+		onSelectVSP: React.PropTypes.func,
+		shouldShowOverlay: React.PropTypes.boolm,
+		onVendorSelect: React.PropTypes.func,
+		onAddVSP: React.PropTypes.func,
+		onVSPIconClick: React.PropTypes.func,
+
+	};
+
+	render() {
+		let {vendor, onSelectVSP, shouldShowOverlay, onVendorSelect, onMigrate} = this.props;
+		let {softwareProductList = [], vendorName} = vendor;
+		return (
+			<CatalogTile
+				catalogItemTypeClass={catalogItemTypeClasses.VENDOR}
+				onSelect={() =>  onVendorSelect(vendor)}>
+				<div className='catalog-tile-top'>
+					<div className='catalog-tile-icon vendor-type'>
+						<div className='icon'><SVGIcon name='vendor'/></div>
+					</div>
+					<OverlayTrigger placement='top' overlay={tooltip(vendorName)}>
+						<div className='catalog-tile-item-name'>{vendorName}</div>
+					</OverlayTrigger>	
+					<div
+						className={classnames('catalog-tile-vsp-count', {active: shouldShowOverlay}, {clickable: softwareProductList.length})}
+						onClick={(event) => this.handleVspCountClick(event)}
+						data-test-id='catalog-vsp-count'>
+						{i18n(`${softwareProductList.length} VSPs`)}
+					</div>
+					<div className='catalog-tile-content' onClick={(event) => this.onCreateVspClick(event)} data-test-id='catalog-create-new-vsp-from-vendor'>
+						<div className='create-new-vsp-button'>
+							<SVGIcon name='plus'/>&nbsp;&nbsp;&nbsp;{i18n('Create new VSP')}
+						</div>
+					</div>
+				</div>
+				
+				{shouldShowOverlay && softwareProductList.length > 0
+				&& <VSPOverlay onMigrate={onMigrate} VSPList={softwareProductList} onSelectVSP={onSelectVSP} onSeeMore={() => onVendorSelect(vendor)}/>}
+			</CatalogTile>
+		);
+	}
+
+	onClick(vlm) {
+		this.setState({
+			licenseModelToShow: vlm
+		});
+	}
+
+	onCreateVspClick(event) {
+		let {onAddVSP, vendor: {id}} = this.props;
+		event.stopPropagation();
+		event.preventDefault();
+		onAddVSP(id);
+	}
+
+	handleVspCountClick(e){
+		let {onVSPIconClick, vendor: {softwareProductList}} = this.props;
+		e.stopPropagation();
+		e.preventDefault();
+		const hasVSP = Boolean(softwareProductList.length);
+		onVSPIconClick(hasVSP);
+	}
+
+}
+
+export default VendorItem;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceView.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceView.jsx
new file mode 100644
index 0000000..d86b674
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceView.jsx
@@ -0,0 +1,57 @@
+/*!
+ * 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.
+ */
+import React from 'react';
+import DetailsCatalogView from '../DetailsCatalogView.jsx';
+import {statusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {tabsMapping} from 'sdc-app/onboarding/onboard/OnboardConstants.js';
+
+const WorkspaceView = (props) => {
+	let {
+		licenseModelList, softwareProductList, onAddLicenseModelClick,
+		onAddSoftwareProductClick, onSelectLicenseModel, onSelectSoftwareProduct, searchValue, onMigrate
+	} = props;
+
+	let {getCheckOutStatusKindByUserID} = VersionControllerUtils;
+	let unfinalizedLicenseModelList = licenseModelList.filter(vlm => {
+		let {status} = getCheckOutStatusKindByUserID(vlm.status, vlm.lockingUser);
+		return status !== statusEnum.SUBMIT_STATUS && status !== statusEnum.LOCK_STATUS;
+	});
+	let unfinalizedSoftwareProductList = softwareProductList.filter(vsp =>{
+		let {status} = getCheckOutStatusKindByUserID(vsp.status, vsp.lockingUser);
+		return status !== statusEnum.SUBMIT_STATUS && status !== statusEnum.LOCK_STATUS;
+	});
+
+	return (
+		<div className='catalog-wrapper workspace-view'>
+			<div className='catalog-header workspace-header'>
+				{i18n('WORKSPACE')}
+			</div>
+			<DetailsCatalogView
+				VLMList={unfinalizedLicenseModelList}
+				VSPList={unfinalizedSoftwareProductList}
+				onAddVLM={onAddLicenseModelClick}
+				onAddVSP={onAddSoftwareProductClick}
+				onSelectVLM={onSelectLicenseModel}
+				onSelectVSP={onSelectSoftwareProduct}
+				onMigrate={onMigrate}
+				filter={searchValue}
+				tileType={tabsMapping.WORKSPACE} />
+		</div>);
+};
+
+export default WorkspaceView;