diff options
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/softwareProduct')
6 files changed, 394 insertions, 18 deletions
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js index 4a2d7a2ece..25bd32e468 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js @@ -45,8 +45,11 @@ import { CommitModalType } from 'nfvo-components/panel/versionController/compone import { actionTypes as commonActionTypes } from 'sdc-app/common/reducers/PlainDataReducerConstants.js'; import versionPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js'; import { itemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js'; -import { catalogItemStatuses } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js'; import getValue from 'nfvo-utils/getValue.js'; +import { + itemStatus, + versionStatus +} from 'sdc-app/common/helpers/ItemsHelperConstants.js'; function getLicensingData(licensingData = {}) { const { licenseAgreement, featureGroups } = licensingData; @@ -112,19 +115,17 @@ function putSoftwareProductAction(id, action, version) { function fetchSoftwareProductList() { return RestAPIUtil.fetch( - `${baseUrl()}?versionFilter=${catalogItemStatuses.DRAFT}` + `${baseUrl()}?versionFilter=${versionStatus.DRAFT}` ); } function fetchArchivedSoftwareProductList() { - return RestAPIUtil.fetch( - `${baseUrl()}?Status=${catalogItemStatuses.ARCHIVED}` - ); + return RestAPIUtil.fetch(`${baseUrl()}?Status=${itemStatus.ARCHIVED}`); } function fetchFinalizedSoftwareProductList() { return RestAPIUtil.fetch( - `${baseUrl()}?versionFilter=${catalogItemStatuses.CERTIFIED}` + `${baseUrl()}?versionFilter=${versionStatus.CERTIFIED}` ); } @@ -664,9 +665,8 @@ const SoftwareProductActionHelper = { version }).then(({ inMerge, isDirty, updatedVersion }) => { if ( - (updatedVersion.status === catalogItemStatuses.CERTIFIED || - updatedVersion.archivedStatus === - catalogItemStatuses.ARCHIVED) && + (updatedVersion.status === versionStatus.CERTIFIED || + updatedVersion.archivedStatus === itemStatus.ARCHIVED) && (action === VersionControllerActionsEnum.COMMIT || action === VersionControllerActionsEnum.SYNC) ) { @@ -675,8 +675,7 @@ const SoftwareProductActionHelper = { itemId: softwareProductId }); const msg = - updatedVersion.archivedStatus === - catalogItemStatuses.ARCHIVED + updatedVersion.archivedStatus === itemStatus.ARCHIVED ? i18n('Item was Archived') : i18n('Item version already Certified'); dispatch({ diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js index 41584d94e2..9a7d257d7d 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js @@ -14,9 +14,11 @@ * permissions and limitations under the License. */ import { connect } from 'react-redux'; - +import featureToggle from 'sdc-app/features/featureToggle.js'; +import { featureToggleNames } from 'sdc-app/features/FeaturesConstants.js'; import SoftwareProductCreationActionHelper from './SoftwareProductCreationActionHelper.js'; import SoftwareProductCreationView from './SoftwareProductCreationView.jsx'; +import SoftwareProductCreationViewWithFilter from './SoftwareProductCreationViewWithFilter.jsx'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; import SoftwareProductActionHelper from '../SoftwareProductActionHelper.js'; import VersionsPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js'; @@ -24,6 +26,16 @@ import { itemTypes as versionItemTypes } from 'sdc-app/onboarding/versionsPage/V import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js'; import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js'; import PermissionsActionHelper from 'sdc-app/onboarding/permissions/PermissionsActionHelper.js'; +import UniqueTypesHelper from 'sdc-app/common/helpers/UniqueTypesHelper.js'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import { itemType } from 'sdc-app/common/helpers/ItemsHelperConstants.js'; + +const ToggledSoftwareProductCreationView = featureToggle( + featureToggleNames.FILTER +)({ + OnComp: SoftwareProductCreationViewWithFilter, + OffComp: SoftwareProductCreationView +}); export const mapStateToProps = ({ finalizedLicenseModelList, @@ -33,7 +45,7 @@ export const mapStateToProps = ({ finalizedSoftwareProductList, softwareProduct: { softwareProductCreation, softwareProductCategories } }) => { - let { genericFieldInfo } = softwareProductCreation; + let { genericFieldInfo, vendorList = [] } = softwareProductCreation; let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); let VSPNames = {}; @@ -52,6 +64,7 @@ export const mapStateToProps = ({ disableVendor: softwareProductCreation.disableVendor, softwareProductCategories, finalizedLicenseModelList, + vendorList, isFormValid, formReady: softwareProductCreation.formReady, genericFieldInfo, @@ -99,10 +112,22 @@ export const mapActionsToProps = dispatch => { }); }, onValidateForm: formName => - ValidationHelper.validateForm(dispatch, formName) + ValidationHelper.validateForm(dispatch, formName), + isNameUnique: (value, name, formName) => + UniqueTypesHelper.isNameUnique(dispatch, { + value, + name, + formName, + errorText: `${i18n( + 'Software product by the name' + )} ${value} ${i18n('already exists')}. ${i18n( + 'Software product name must be unique' + )}`, + itemType: itemType.VSP + }) }; }; export default connect(mapStateToProps, mapActionsToProps, null, { withRef: true -})(SoftwareProductCreationView); +})(ToggledSoftwareProductCreationView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js index 1b1fd71fef..259b50ba4f 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js @@ -24,7 +24,11 @@ import { import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; import { actionTypes } from './SoftwareProductCreationConstants.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; - +import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js'; +import { + itemStatus, + versionStatus +} from 'sdc-app/common/helpers/ItemsHelperConstants.js'; function baseUrl() { const restPrefix = Configuration.get('restPrefix'); return `${restPrefix}/v1.0/vendor-software-products/`; @@ -45,7 +49,7 @@ const SoftwareProductCreationActionHelper = { type: actionTypes.OPEN, selectedVendorId: vendorId }); - + this.loadVendorList(dispatch); dispatch({ type: modalActionTypes.GLOBAL_MODAL_SHOW, data: { @@ -78,6 +82,19 @@ const SoftwareProductCreationActionHelper = { }); return result; }); + }, + async loadVendorList(dispatch) { + const { results } = await ItemsHelper.fetchItems({ + itemStatus: itemStatus.ACTIVE, + versionStatus: versionStatus.CERTIFIED, + itemType: { + vlm: true + } + }); + dispatch({ + type: actionTypes.VENDOR_LIST_LOADED, + vendorList: results + }); } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js index ad1034602a..128b3edfd9 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js @@ -18,7 +18,8 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ OPEN: null, RESET_DATA: null, - SOFTWARE_PRODUCT_CREATED: null + SOFTWARE_PRODUCT_CREATED: null, + VENDOR_LIST_LOADED: null }); export const SP_CREATION_FORM_NAME = 'SPCREATIONFORM'; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js index 5f70f18f75..b019248ba0 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js @@ -74,6 +74,11 @@ export default (state = {}, action) => { }, showModal: true }; + case actionTypes.VENDOR_LIST_LOADED: + return { + ...state, + vendorList: action.vendorList + }; case actionTypes.RESET_DATA: return {}; default: diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationViewWithFilter.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationViewWithFilter.jsx new file mode 100644 index 0000000000..810337dbed --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationViewWithFilter.jsx @@ -0,0 +1,329 @@ +/*! + * Copyright © 2016-2018 European Support Limited + * + * 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 PropTypes from 'prop-types'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import Validator from 'nfvo-utils/Validator.js'; +import Input from 'nfvo-components/input/validation/Input.jsx'; +import Form from 'nfvo-components/input/validation/Form.jsx'; +import GridSection from 'nfvo-components/grid/GridSection.jsx'; +import GridItem from 'nfvo-components/grid/GridItem.jsx'; + +import { SP_CREATION_FORM_NAME } from './SoftwareProductCreationConstants.js'; +import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js'; + +import SoftwareProductCategoriesHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js'; +import { onboardingMethod as onboardingMethodConst } from '../SoftwareProductConstants.js'; + +const SoftwareProductPropType = PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + description: PropTypes.string, + category: PropTypes.string, + subCategory: PropTypes.string, + vendorId: PropTypes.string +}); + +class SoftwareProductCreationView extends React.Component { + static propTypes = { + data: SoftwareProductPropType, + finalizedLicenseModelList: PropTypes.array, + softwareProductCategories: PropTypes.array, + VSPNames: PropTypes.object, + usersList: PropTypes.array, + onDataChanged: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, + onCancel: PropTypes.func.isRequired + }; + + render() { + let { + softwareProductCategories, + data = {}, + onDataChanged, + onCancel, + genericFieldInfo, + disableVendor + } = this.props; + let { + name, + description, + vendorId, + subCategory, + onboardingMethod + } = data; + + const vendorList = this.getVendorList(); + return ( + <div className="software-product-creation-page"> + {genericFieldInfo && ( + <Form + ref={validationForm => + (this.validationForm = validationForm) + } + hasButtons={true} + onSubmit={() => this.submit()} + onReset={() => onCancel()} + labledButtons={true} + isValid={this.props.isFormValid} + submitButtonText={i18n('Create')} + formReady={this.props.formReady} + onValidateForm={() => this.validate()}> + <GridSection hasLastColSet> + <GridItem colSpan="2"> + <Input + value={name} + label={i18n('Name')} + isRequired={true} + onChange={name => + onDataChanged( + { name }, + SP_CREATION_FORM_NAME + ) + } + onBlur={this.validateIsNameUnique} + isValid={genericFieldInfo.name.isValid} + errorText={genericFieldInfo.name.errorText} + type="text" + className="field-section" + data-test-id="new-vsp-name" + /> + <Input + label={i18n('Vendor')} + type="select" + value={vendorId} + overlayPos="bottom" + isRequired={true} + disabled={disableVendor} + onChange={e => this.onSelectVendor(e)} + isValid={genericFieldInfo.vendorId.isValid} + errorText={ + genericFieldInfo.vendorId.errorText + } + className="input-options-select" + groupClassName="bootstrap-input-options" + data-test-id="new-vsp-vendor"> + {vendorList.map(vendor => ( + <option + key={vendor.title} + value={vendor.enum}> + {vendor.title} + </option> + ))} + </Input> + <Input + label={i18n('Category')} + type="select" + value={subCategory} + isRequired={true} + onChange={e => this.onSelectSubCategory(e)} + isValid={ + genericFieldInfo.subCategory.isValid + } + errorText={ + genericFieldInfo.subCategory.errorText + } + className="input-options-select" + groupClassName="bootstrap-input-options" + data-test-id="new-vsp-category"> + <option key="" value=""> + {i18n('please select…')} + </option> + {softwareProductCategories.map( + category => + category.subcategories && ( + <optgroup + key={category.name} + label={category.name}> + {category.subcategories.map( + sub => ( + <option + key={ + sub.uniqueId + } + value={ + sub.uniqueId + }>{`${ + sub.name + } (${ + category.name + })`}</option> + ) + )} + </optgroup> + ) + )} + </Input> + </GridItem> + <GridItem colSpan="2" stretch lastColInRow> + <Input + value={description} + label={i18n('Description')} + isRequired={true} + overlayPos="bottom" + onChange={description => + onDataChanged( + { description }, + SP_CREATION_FORM_NAME + ) + } + isValid={ + genericFieldInfo.description.isValid + } + errorText={ + genericFieldInfo.description.errorText + } + type="textarea" + className="field-section" + data-test-id="new-vsp-description" + /> + </GridItem> + </GridSection> + <OnboardingProcedure + genericFieldInfo={genericFieldInfo} + onboardingMethod={onboardingMethod} + onDataChanged={onDataChanged} + /> + </Form> + )} + </div> + ); + } + + getVendorList() { + let { vendorList } = this.props; + + return [{ enum: '', title: i18n('please select...') }].concat( + sortByStringProperty(vendorList, 'name').map(vendor => { + return { + enum: vendor.id, + title: vendor.name + }; + }) + ); + } + + onSelectVendor(e) { + const selectedIndex = e.target.selectedIndex; + const vendorId = e.target.options[selectedIndex].value; + this.props.onDataChanged({ vendorId }, SP_CREATION_FORM_NAME); + } + + onSelectSubCategory(e) { + const selectedIndex = e.target.selectedIndex; + const subCategory = e.target.options[selectedIndex].value; + let { softwareProductCategories, onDataChanged } = this.props; + let category = SoftwareProductCategoriesHelper.getCurrentCategoryOfSubCategory( + subCategory, + softwareProductCategories + ); + onDataChanged({ category, subCategory }, SP_CREATION_FORM_NAME); + } + + submit() { + let { + data: softwareProduct, + finalizedLicenseModelList, + usersList + } = this.props; + softwareProduct.vendorName = finalizedLicenseModelList.find( + vendor => vendor.id === softwareProduct.vendorId + ).name; + this.props.onSubmit(softwareProduct, usersList); + } + + validateName(value) { + const { data: { id }, VSPNames } = this.props; + const isExists = Validator.isItemNameAlreadyExistsInList({ + itemId: id, + itemName: value, + list: VSPNames + }); + + return !isExists + ? { isValid: true, errorText: '' } + : { + isValid: false, + errorText: i18n( + "Software product by the name '" + + value + + "' already exists. Software product name must be unique" + ) + }; + } + + validateIsNameUnique = e => { + const value = e.target.value; + this.props.isNameUnique(value, 'name', SP_CREATION_FORM_NAME); + }; + + validate() { + this.props.onValidateForm(SP_CREATION_FORM_NAME); + } +} + +const OnboardingProcedure = ({ + onboardingMethod, + onDataChanged, + genericFieldInfo +}) => { + return ( + <GridSection title={i18n('Onboarding procedure')}> + <GridItem colSpan={4}> + <Input + label={i18n('Network Package')} + overlayPos="top" + isValid={genericFieldInfo.onboardingMethod.isValid} + checked={ + onboardingMethod === + onboardingMethodConst.NETWORK_PACKAGE + } + errorText={genericFieldInfo.onboardingMethod.errorText} + onChange={() => + onDataChanged( + { + onboardingMethod: + onboardingMethodConst.NETWORK_PACKAGE + }, + SP_CREATION_FORM_NAME + ) + } + type="radio" + data-test-id="new-vsp-creation-procedure-heat" + /> + </GridItem> + <GridItem colSpan={4}> + <Input + label={i18n('Manual')} + overlayPos="bottom" + checked={onboardingMethod === onboardingMethodConst.MANUAL} + isValid={genericFieldInfo.onboardingMethod.isValid} + errorText={genericFieldInfo.onboardingMethod.errorText} + onChange={() => + onDataChanged( + { onboardingMethod: onboardingMethodConst.MANUAL }, + SP_CREATION_FORM_NAME + ) + } + type="radio" + data-test-id="new-vsp-creation-procedure-manual" + /> + </GridItem> + </GridSection> + ); +}; + +export default SoftwareProductCreationView; |