aboutsummaryrefslogtreecommitdiffstats
path: root/openecomp-ui/src/sdc-app/onboarding/onboard
diff options
context:
space:
mode:
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/onboard')
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx134
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.stories.js36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogList.jsx51
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogModal.jsx62
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogTile.jsx31
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/DetailsCatalogView.jsx56
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/Onboard.js90
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/OnboardActionHelper.js45
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/OnboardConstants.js28
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/OnboardReducer.js31
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/OnboardView.jsx95
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogActionHelper.js85
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js50
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogReducer.js30
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogUtils.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogView.jsx98
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/Tooltip.jsx24
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VSPOverlay.jsx50
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogReducer.js38
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogView.jsx74
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorItem.jsx96
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceView.jsx57
22 files changed, 1282 insertions, 0 deletions
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 0000000000..c63fbff21b
--- /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 0000000000..c4e2724eaf
--- /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 0000000000..17248e3b02
--- /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 0000000000..1ef9c82822
--- /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 0000000000..c7720a9d0e
--- /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 0000000000..ef54848523
--- /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 0000000000..b13ccbbba2
--- /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 0000000000..6ebb40878f
--- /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 0000000000..41128bfb11
--- /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 0000000000..72145015db
--- /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 0000000000..b7a7fa5f68
--- /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 0000000000..73a447558d
--- /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 0000000000..071160c4fd
--- /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 0000000000..d7d9d0bd6c
--- /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 0000000000..ac623db920
--- /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 0000000000..b1f002d2fb
--- /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 0000000000..8d8d1162a0
--- /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 0000000000..1ba4834fa3
--- /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 0000000000..dd8b41bd22
--- /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 0000000000..c4e0599d85
--- /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 0000000000..cecccdd9ad
--- /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 0000000000..d86b674f13
--- /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;