diff options
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/onboard')
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'/> {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; |